blob: e98ff8c77ec5a4cf42e03470966eae50f3509757 [file] [log] [blame]
Steve Glendinning2f7ca802008-10-02 05:27:57 +00001 /***************************************************************************
2 *
3 * Copyright (C) 2007-2008 SMSC
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 *
19 *****************************************************************************/
20
21#include <linux/module.h>
22#include <linux/kmod.h>
23#include <linux/init.h>
24#include <linux/netdevice.h>
25#include <linux/etherdevice.h>
26#include <linux/ethtool.h>
27#include <linux/mii.h>
28#include <linux/usb.h>
Steve Glendinningbbd9f9e2012-10-26 03:43:56 +000029#include <linux/bitrev.h>
30#include <linux/crc16.h>
Steve Glendinning2f7ca802008-10-02 05:27:57 +000031#include <linux/crc32.h>
32#include <linux/usb/usbnet.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090033#include <linux/slab.h>
Steve Glendinning2f7ca802008-10-02 05:27:57 +000034#include "smsc95xx.h"
35
36#define SMSC_CHIPNAME "smsc95xx"
Steve Glendinningf7b29272008-11-20 04:19:21 -080037#define SMSC_DRIVER_VERSION "1.0.4"
Steve Glendinning2f7ca802008-10-02 05:27:57 +000038#define HS_USB_PKT_SIZE (512)
39#define FS_USB_PKT_SIZE (64)
40#define DEFAULT_HS_BURST_CAP_SIZE (16 * 1024 + 5 * HS_USB_PKT_SIZE)
41#define DEFAULT_FS_BURST_CAP_SIZE (6 * 1024 + 33 * FS_USB_PKT_SIZE)
42#define DEFAULT_BULK_IN_DELAY (0x00002000)
43#define MAX_SINGLE_PACKET_SIZE (2048)
44#define LAN95XX_EEPROM_MAGIC (0x9500)
45#define EEPROM_MAC_OFFSET (0x01)
Steve Glendinningf7b29272008-11-20 04:19:21 -080046#define DEFAULT_TX_CSUM_ENABLE (true)
Steve Glendinning2f7ca802008-10-02 05:27:57 +000047#define DEFAULT_RX_CSUM_ENABLE (true)
48#define SMSC95XX_INTERNAL_PHY_ID (1)
49#define SMSC95XX_TX_OVERHEAD (8)
Steve Glendinningf7b29272008-11-20 04:19:21 -080050#define SMSC95XX_TX_OVERHEAD_CSUM (12)
Steve Glendinninge5e3af82012-11-22 08:05:24 +000051#define SUPPORTED_WAKE (WAKE_PHY | WAKE_UCAST | WAKE_BCAST | \
Steve Glendinningbbd9f9e2012-10-26 03:43:56 +000052 WAKE_MCAST | WAKE_ARP | WAKE_MAGIC)
Steve Glendinning2f7ca802008-10-02 05:27:57 +000053
Steve Glendinning9ebca502012-11-22 08:05:23 +000054#define FEATURE_8_WAKEUP_FILTERS (0x01)
55#define FEATURE_PHY_NLP_CROSSOVER (0x02)
56#define FEATURE_AUTOSUSPEND (0x04)
57
Steve Glendinning769ea6d2012-09-28 00:07:09 +000058#define check_warn(ret, fmt, args...) \
59 ({ if (ret < 0) netdev_warn(dev->net, fmt, ##args); })
60
61#define check_warn_return(ret, fmt, args...) \
62 ({ if (ret < 0) { netdev_warn(dev->net, fmt, ##args); return ret; } })
63
64#define check_warn_goto_done(ret, fmt, args...) \
65 ({ if (ret < 0) { netdev_warn(dev->net, fmt, ##args); goto done; } })
66
Steve Glendinning2f7ca802008-10-02 05:27:57 +000067struct smsc95xx_priv {
68 u32 mac_cr;
Marc Zyngier3c0f3c62011-03-18 03:53:58 +000069 u32 hash_hi;
70 u32 hash_lo;
Steve Glendinninge0e474a2012-09-28 00:07:12 +000071 u32 wolopts;
Steve Glendinning2f7ca802008-10-02 05:27:57 +000072 spinlock_t mac_cr_lock;
Steve Glendinning9ebca502012-11-22 08:05:23 +000073 u8 features;
Steve Glendinning2f7ca802008-10-02 05:27:57 +000074};
75
Rusty Russelleb939922011-12-19 14:08:01 +000076static bool turbo_mode = true;
Steve Glendinning2f7ca802008-10-02 05:27:57 +000077module_param(turbo_mode, bool, 0644);
78MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction");
79
Ming Leiec321152012-11-06 04:53:07 +000080static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index,
81 u32 *data, int in_pm)
Steve Glendinning2f7ca802008-10-02 05:27:57 +000082{
Ming Lei72108fd2012-10-24 19:47:04 +000083 u32 buf;
Steve Glendinning2f7ca802008-10-02 05:27:57 +000084 int ret;
Ming Leiec321152012-11-06 04:53:07 +000085 int (*fn)(struct usbnet *, u8, u8, u16, u16, void *, u16);
Steve Glendinning2f7ca802008-10-02 05:27:57 +000086
87 BUG_ON(!dev);
88
Ming Leiec321152012-11-06 04:53:07 +000089 if (!in_pm)
90 fn = usbnet_read_cmd;
91 else
92 fn = usbnet_read_cmd_nopm;
93
94 ret = fn(dev, USB_VENDOR_REQUEST_READ_REGISTER, USB_DIR_IN
95 | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
96 0, index, &buf, 4);
Steve Glendinning2f7ca802008-10-02 05:27:57 +000097 if (unlikely(ret < 0))
Ming Leiec321152012-11-06 04:53:07 +000098 netdev_warn(dev->net,
99 "Failed to read reg index 0x%08x: %d", index, ret);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000100
Ming Lei72108fd2012-10-24 19:47:04 +0000101 le32_to_cpus(&buf);
102 *data = buf;
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000103
104 return ret;
105}
106
Ming Leiec321152012-11-06 04:53:07 +0000107static int __must_check __smsc95xx_write_reg(struct usbnet *dev, u32 index,
108 u32 data, int in_pm)
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000109{
Ming Lei72108fd2012-10-24 19:47:04 +0000110 u32 buf;
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000111 int ret;
Ming Leiec321152012-11-06 04:53:07 +0000112 int (*fn)(struct usbnet *, u8, u8, u16, u16, const void *, u16);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000113
114 BUG_ON(!dev);
115
Ming Leiec321152012-11-06 04:53:07 +0000116 if (!in_pm)
117 fn = usbnet_write_cmd;
118 else
119 fn = usbnet_write_cmd_nopm;
120
Ming Lei72108fd2012-10-24 19:47:04 +0000121 buf = data;
122 cpu_to_le32s(&buf);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000123
Ming Leiec321152012-11-06 04:53:07 +0000124 ret = fn(dev, USB_VENDOR_REQUEST_WRITE_REGISTER, USB_DIR_OUT
125 | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
126 0, index, &buf, 4);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000127 if (unlikely(ret < 0))
Ming Leiec321152012-11-06 04:53:07 +0000128 netdev_warn(dev->net,
129 "Failed to write reg index 0x%08x: %d", index, ret);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000130
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000131 return ret;
132}
133
Ming Leiec321152012-11-06 04:53:07 +0000134static int __must_check smsc95xx_read_reg_nopm(struct usbnet *dev, u32 index,
135 u32 *data)
136{
137 return __smsc95xx_read_reg(dev, index, data, 1);
138}
139
140static int __must_check smsc95xx_write_reg_nopm(struct usbnet *dev, u32 index,
141 u32 data)
142{
143 return __smsc95xx_write_reg(dev, index, data, 1);
144}
145
146static int __must_check smsc95xx_read_reg(struct usbnet *dev, u32 index,
147 u32 *data)
148{
149 return __smsc95xx_read_reg(dev, index, data, 0);
150}
151
152static int __must_check smsc95xx_write_reg(struct usbnet *dev, u32 index,
153 u32 data)
154{
155 return __smsc95xx_write_reg(dev, index, data, 0);
156}
Steve Glendinninge0e474a2012-09-28 00:07:12 +0000157static int smsc95xx_set_feature(struct usbnet *dev, u32 feature)
158{
159 if (WARN_ON_ONCE(!dev))
160 return -EINVAL;
161
Ming Leiec321152012-11-06 04:53:07 +0000162 return usbnet_write_cmd_nopm(dev, USB_REQ_SET_FEATURE,
163 USB_RECIP_DEVICE, feature, 0,
164 NULL, 0);
Steve Glendinninge0e474a2012-09-28 00:07:12 +0000165}
166
167static int smsc95xx_clear_feature(struct usbnet *dev, u32 feature)
168{
169 if (WARN_ON_ONCE(!dev))
170 return -EINVAL;
171
Ming Leiec321152012-11-06 04:53:07 +0000172 return usbnet_write_cmd_nopm(dev, USB_REQ_CLEAR_FEATURE,
173 USB_RECIP_DEVICE, feature,
174 0, NULL, 0);
Steve Glendinninge0e474a2012-09-28 00:07:12 +0000175}
176
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000177/* Loop until the read is completed with timeout
178 * called with phy_mutex held */
Steve Glendinninge5e3af82012-11-22 08:05:24 +0000179static int __must_check __smsc95xx_phy_wait_not_busy(struct usbnet *dev,
180 int in_pm)
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000181{
182 unsigned long start_time = jiffies;
183 u32 val;
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000184 int ret;
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000185
186 do {
Steve Glendinninge5e3af82012-11-22 08:05:24 +0000187 ret = __smsc95xx_read_reg(dev, MII_ADDR, &val, in_pm);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000188 check_warn_return(ret, "Error reading MII_ACCESS");
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000189 if (!(val & MII_BUSY_))
190 return 0;
191 } while (!time_after(jiffies, start_time + HZ));
192
193 return -EIO;
194}
195
Steve Glendinninge5e3af82012-11-22 08:05:24 +0000196static int __smsc95xx_mdio_read(struct net_device *netdev, int phy_id, int idx,
197 int in_pm)
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000198{
199 struct usbnet *dev = netdev_priv(netdev);
200 u32 val, addr;
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000201 int ret;
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000202
203 mutex_lock(&dev->phy_mutex);
204
205 /* confirm MII not busy */
Steve Glendinninge5e3af82012-11-22 08:05:24 +0000206 ret = __smsc95xx_phy_wait_not_busy(dev, in_pm);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000207 check_warn_goto_done(ret, "MII is busy in smsc95xx_mdio_read");
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000208
209 /* set the address, index & direction (read from PHY) */
210 phy_id &= dev->mii.phy_id_mask;
211 idx &= dev->mii.reg_num_mask;
Steve Glendinning80928802012-11-06 00:08:53 +0000212 addr = (phy_id << 11) | (idx << 6) | MII_READ_ | MII_BUSY_;
Steve Glendinninge5e3af82012-11-22 08:05:24 +0000213 ret = __smsc95xx_write_reg(dev, MII_ADDR, addr, in_pm);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000214 check_warn_goto_done(ret, "Error writing MII_ADDR");
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000215
Steve Glendinninge5e3af82012-11-22 08:05:24 +0000216 ret = __smsc95xx_phy_wait_not_busy(dev, in_pm);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000217 check_warn_goto_done(ret, "Timed out reading MII reg %02X", idx);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000218
Steve Glendinninge5e3af82012-11-22 08:05:24 +0000219 ret = __smsc95xx_read_reg(dev, MII_DATA, &val, in_pm);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000220 check_warn_goto_done(ret, "Error reading MII_DATA");
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000221
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000222 ret = (u16)(val & 0xFFFF);
223
224done:
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000225 mutex_unlock(&dev->phy_mutex);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000226 return ret;
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000227}
228
Steve Glendinninge5e3af82012-11-22 08:05:24 +0000229static void __smsc95xx_mdio_write(struct net_device *netdev, int phy_id,
230 int idx, int regval, int in_pm)
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000231{
232 struct usbnet *dev = netdev_priv(netdev);
233 u32 val, addr;
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000234 int ret;
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000235
236 mutex_lock(&dev->phy_mutex);
237
238 /* confirm MII not busy */
Steve Glendinninge5e3af82012-11-22 08:05:24 +0000239 ret = __smsc95xx_phy_wait_not_busy(dev, in_pm);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000240 check_warn_goto_done(ret, "MII is busy in smsc95xx_mdio_write");
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000241
242 val = regval;
Steve Glendinninge5e3af82012-11-22 08:05:24 +0000243 ret = __smsc95xx_write_reg(dev, MII_DATA, val, in_pm);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000244 check_warn_goto_done(ret, "Error writing MII_DATA");
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000245
246 /* set the address, index & direction (write to PHY) */
247 phy_id &= dev->mii.phy_id_mask;
248 idx &= dev->mii.reg_num_mask;
Steve Glendinning80928802012-11-06 00:08:53 +0000249 addr = (phy_id << 11) | (idx << 6) | MII_WRITE_ | MII_BUSY_;
Steve Glendinninge5e3af82012-11-22 08:05:24 +0000250 ret = __smsc95xx_write_reg(dev, MII_ADDR, addr, in_pm);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000251 check_warn_goto_done(ret, "Error writing MII_ADDR");
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000252
Steve Glendinninge5e3af82012-11-22 08:05:24 +0000253 ret = __smsc95xx_phy_wait_not_busy(dev, in_pm);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000254 check_warn_goto_done(ret, "Timed out writing MII reg %02X", idx);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000255
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000256done:
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000257 mutex_unlock(&dev->phy_mutex);
258}
259
Steve Glendinninge5e3af82012-11-22 08:05:24 +0000260static int smsc95xx_mdio_read_nopm(struct net_device *netdev, int phy_id,
261 int idx)
262{
263 return __smsc95xx_mdio_read(netdev, phy_id, idx, 1);
264}
265
266static void smsc95xx_mdio_write_nopm(struct net_device *netdev, int phy_id,
267 int idx, int regval)
268{
269 __smsc95xx_mdio_write(netdev, phy_id, idx, regval, 1);
270}
271
272static int smsc95xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
273{
274 return __smsc95xx_mdio_read(netdev, phy_id, idx, 0);
275}
276
277static void smsc95xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
278 int regval)
279{
280 __smsc95xx_mdio_write(netdev, phy_id, idx, regval, 0);
281}
282
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000283static int __must_check smsc95xx_wait_eeprom(struct usbnet *dev)
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000284{
285 unsigned long start_time = jiffies;
286 u32 val;
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000287 int ret;
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000288
289 do {
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000290 ret = smsc95xx_read_reg(dev, E2P_CMD, &val);
291 check_warn_return(ret, "Error reading E2P_CMD");
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000292 if (!(val & E2P_CMD_BUSY_) || (val & E2P_CMD_TIMEOUT_))
293 break;
294 udelay(40);
295 } while (!time_after(jiffies, start_time + HZ));
296
297 if (val & (E2P_CMD_TIMEOUT_ | E2P_CMD_BUSY_)) {
Joe Perches60b86752010-02-17 10:30:23 +0000298 netdev_warn(dev->net, "EEPROM read operation timeout\n");
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000299 return -EIO;
300 }
301
302 return 0;
303}
304
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000305static int __must_check smsc95xx_eeprom_confirm_not_busy(struct usbnet *dev)
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000306{
307 unsigned long start_time = jiffies;
308 u32 val;
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000309 int ret;
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000310
311 do {
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000312 ret = smsc95xx_read_reg(dev, E2P_CMD, &val);
313 check_warn_return(ret, "Error reading E2P_CMD");
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000314
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000315 if (!(val & E2P_CMD_BUSY_))
316 return 0;
317
318 udelay(40);
319 } while (!time_after(jiffies, start_time + HZ));
320
Joe Perches60b86752010-02-17 10:30:23 +0000321 netdev_warn(dev->net, "EEPROM is busy\n");
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000322 return -EIO;
323}
324
325static int smsc95xx_read_eeprom(struct usbnet *dev, u32 offset, u32 length,
326 u8 *data)
327{
328 u32 val;
329 int i, ret;
330
331 BUG_ON(!dev);
332 BUG_ON(!data);
333
334 ret = smsc95xx_eeprom_confirm_not_busy(dev);
335 if (ret)
336 return ret;
337
338 for (i = 0; i < length; i++) {
339 val = E2P_CMD_BUSY_ | E2P_CMD_READ_ | (offset & E2P_CMD_ADDR_);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000340 ret = smsc95xx_write_reg(dev, E2P_CMD, val);
341 check_warn_return(ret, "Error writing E2P_CMD");
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000342
343 ret = smsc95xx_wait_eeprom(dev);
344 if (ret < 0)
345 return ret;
346
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000347 ret = smsc95xx_read_reg(dev, E2P_DATA, &val);
348 check_warn_return(ret, "Error reading E2P_DATA");
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000349
350 data[i] = val & 0xFF;
351 offset++;
352 }
353
354 return 0;
355}
356
357static int smsc95xx_write_eeprom(struct usbnet *dev, u32 offset, u32 length,
358 u8 *data)
359{
360 u32 val;
361 int i, ret;
362
363 BUG_ON(!dev);
364 BUG_ON(!data);
365
366 ret = smsc95xx_eeprom_confirm_not_busy(dev);
367 if (ret)
368 return ret;
369
370 /* Issue write/erase enable command */
371 val = E2P_CMD_BUSY_ | E2P_CMD_EWEN_;
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000372 ret = smsc95xx_write_reg(dev, E2P_CMD, val);
373 check_warn_return(ret, "Error writing E2P_DATA");
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000374
375 ret = smsc95xx_wait_eeprom(dev);
376 if (ret < 0)
377 return ret;
378
379 for (i = 0; i < length; i++) {
380
381 /* Fill data register */
382 val = data[i];
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000383 ret = smsc95xx_write_reg(dev, E2P_DATA, val);
384 check_warn_return(ret, "Error writing E2P_DATA");
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000385
386 /* Send "write" command */
387 val = E2P_CMD_BUSY_ | E2P_CMD_WRITE_ | (offset & E2P_CMD_ADDR_);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000388 ret = smsc95xx_write_reg(dev, E2P_CMD, val);
389 check_warn_return(ret, "Error writing E2P_CMD");
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000390
391 ret = smsc95xx_wait_eeprom(dev);
392 if (ret < 0)
393 return ret;
394
395 offset++;
396 }
397
398 return 0;
399}
400
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000401static int __must_check smsc95xx_write_reg_async(struct usbnet *dev, u16 index,
402 u32 *data)
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000403{
Steve Glendinning1d74a6b2008-10-09 14:34:47 -0700404 const u16 size = 4;
Ming Lei72108fd2012-10-24 19:47:04 +0000405 int ret;
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000406
Ming Lei72108fd2012-10-24 19:47:04 +0000407 ret = usbnet_write_cmd_async(dev, USB_VENDOR_REQUEST_WRITE_REGISTER,
408 USB_DIR_OUT | USB_TYPE_VENDOR |
409 USB_RECIP_DEVICE,
410 0, index, data, size);
411 if (ret < 0)
412 netdev_warn(dev->net, "Error write async cmd, sts=%d\n",
413 ret);
414 return ret;
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000415}
416
417/* returns hash bit number for given MAC address
418 * example:
419 * 01 00 5E 00 00 01 -> returns bit number 31 */
420static unsigned int smsc95xx_hash(char addr[ETH_ALEN])
421{
422 return (ether_crc(ETH_ALEN, addr) >> 26) & 0x3f;
423}
424
425static void smsc95xx_set_multicast(struct net_device *netdev)
426{
427 struct usbnet *dev = netdev_priv(netdev);
428 struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000429 unsigned long flags;
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000430 int ret;
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000431
Marc Zyngier3c0f3c62011-03-18 03:53:58 +0000432 pdata->hash_hi = 0;
433 pdata->hash_lo = 0;
434
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000435 spin_lock_irqsave(&pdata->mac_cr_lock, flags);
436
437 if (dev->net->flags & IFF_PROMISC) {
Joe Perchesa475f602010-02-17 10:30:24 +0000438 netif_dbg(dev, drv, dev->net, "promiscuous mode enabled\n");
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000439 pdata->mac_cr |= MAC_CR_PRMS_;
440 pdata->mac_cr &= ~(MAC_CR_MCPAS_ | MAC_CR_HPFILT_);
441 } else if (dev->net->flags & IFF_ALLMULTI) {
Joe Perchesa475f602010-02-17 10:30:24 +0000442 netif_dbg(dev, drv, dev->net, "receive all multicast enabled\n");
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000443 pdata->mac_cr |= MAC_CR_MCPAS_;
444 pdata->mac_cr &= ~(MAC_CR_PRMS_ | MAC_CR_HPFILT_);
Jiri Pirko4cd24ea2010-02-08 04:30:35 +0000445 } else if (!netdev_mc_empty(dev->net)) {
Jiri Pirko22bedad32010-04-01 21:22:57 +0000446 struct netdev_hw_addr *ha;
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000447
448 pdata->mac_cr |= MAC_CR_HPFILT_;
449 pdata->mac_cr &= ~(MAC_CR_PRMS_ | MAC_CR_MCPAS_);
450
Jiri Pirko22bedad32010-04-01 21:22:57 +0000451 netdev_for_each_mc_addr(ha, netdev) {
452 u32 bitnum = smsc95xx_hash(ha->addr);
Jiri Pirkoa92635d2010-02-18 04:02:26 +0000453 u32 mask = 0x01 << (bitnum & 0x1F);
454 if (bitnum & 0x20)
Marc Zyngier3c0f3c62011-03-18 03:53:58 +0000455 pdata->hash_hi |= mask;
Jiri Pirkoa92635d2010-02-18 04:02:26 +0000456 else
Marc Zyngier3c0f3c62011-03-18 03:53:58 +0000457 pdata->hash_lo |= mask;
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000458 }
459
Joe Perchesa475f602010-02-17 10:30:24 +0000460 netif_dbg(dev, drv, dev->net, "HASHH=0x%08X, HASHL=0x%08X\n",
Marc Zyngier3c0f3c62011-03-18 03:53:58 +0000461 pdata->hash_hi, pdata->hash_lo);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000462 } else {
Joe Perchesa475f602010-02-17 10:30:24 +0000463 netif_dbg(dev, drv, dev->net, "receive own packets only\n");
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000464 pdata->mac_cr &=
465 ~(MAC_CR_PRMS_ | MAC_CR_MCPAS_ | MAC_CR_HPFILT_);
466 }
467
468 spin_unlock_irqrestore(&pdata->mac_cr_lock, flags);
469
470 /* Initiate async writes, as we can't wait for completion here */
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000471 ret = smsc95xx_write_reg_async(dev, HASHH, &pdata->hash_hi);
472 check_warn(ret, "failed to initiate async write to HASHH");
473
474 ret = smsc95xx_write_reg_async(dev, HASHL, &pdata->hash_lo);
475 check_warn(ret, "failed to initiate async write to HASHL");
476
477 ret = smsc95xx_write_reg_async(dev, MAC_CR, &pdata->mac_cr);
478 check_warn(ret, "failed to initiate async write to MAC_CR");
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000479}
480
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000481static int smsc95xx_phy_update_flowcontrol(struct usbnet *dev, u8 duplex,
482 u16 lcladv, u16 rmtadv)
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000483{
484 u32 flow, afc_cfg = 0;
485
486 int ret = smsc95xx_read_reg(dev, AFC_CFG, &afc_cfg);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000487 check_warn_return(ret, "Error reading AFC_CFG");
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000488
489 if (duplex == DUPLEX_FULL) {
Steve Glendinningbc02ff92008-12-16 02:00:48 -0800490 u8 cap = mii_resolve_flowctrl_fdx(lcladv, rmtadv);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000491
492 if (cap & FLOW_CTRL_RX)
493 flow = 0xFFFF0002;
494 else
495 flow = 0;
496
497 if (cap & FLOW_CTRL_TX)
498 afc_cfg |= 0xF;
499 else
500 afc_cfg &= ~0xF;
501
Joe Perchesa475f602010-02-17 10:30:24 +0000502 netif_dbg(dev, link, dev->net, "rx pause %s, tx pause %s\n",
Joe Perches60b86752010-02-17 10:30:23 +0000503 cap & FLOW_CTRL_RX ? "enabled" : "disabled",
504 cap & FLOW_CTRL_TX ? "enabled" : "disabled");
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000505 } else {
Joe Perchesa475f602010-02-17 10:30:24 +0000506 netif_dbg(dev, link, dev->net, "half duplex\n");
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000507 flow = 0;
508 afc_cfg |= 0xF;
509 }
510
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000511 ret = smsc95xx_write_reg(dev, FLOW, flow);
512 check_warn_return(ret, "Error writing FLOW");
513
514 ret = smsc95xx_write_reg(dev, AFC_CFG, afc_cfg);
515 check_warn_return(ret, "Error writing AFC_CFG");
516
517 return 0;
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000518}
519
520static int smsc95xx_link_reset(struct usbnet *dev)
521{
522 struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
523 struct mii_if_info *mii = &dev->mii;
David Decotigny8ae6daca2011-04-27 18:32:38 +0000524 struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET };
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000525 unsigned long flags;
526 u16 lcladv, rmtadv;
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000527 int ret;
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000528
529 /* clear interrupt status */
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000530 ret = smsc95xx_mdio_read(dev->net, mii->phy_id, PHY_INT_SRC);
531 check_warn_return(ret, "Error reading PHY_INT_SRC");
532
533 ret = smsc95xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL_);
534 check_warn_return(ret, "Error writing INT_STS");
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000535
536 mii_check_media(mii, 1, 1);
537 mii_ethtool_gset(&dev->mii, &ecmd);
538 lcladv = smsc95xx_mdio_read(dev->net, mii->phy_id, MII_ADVERTISE);
539 rmtadv = smsc95xx_mdio_read(dev->net, mii->phy_id, MII_LPA);
540
David Decotigny8ae6daca2011-04-27 18:32:38 +0000541 netif_dbg(dev, link, dev->net,
542 "speed: %u duplex: %d lcladv: %04x rmtadv: %04x\n",
543 ethtool_cmd_speed(&ecmd), ecmd.duplex, lcladv, rmtadv);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000544
545 spin_lock_irqsave(&pdata->mac_cr_lock, flags);
546 if (ecmd.duplex != DUPLEX_FULL) {
547 pdata->mac_cr &= ~MAC_CR_FDPX_;
548 pdata->mac_cr |= MAC_CR_RCVOWN_;
549 } else {
550 pdata->mac_cr &= ~MAC_CR_RCVOWN_;
551 pdata->mac_cr |= MAC_CR_FDPX_;
552 }
553 spin_unlock_irqrestore(&pdata->mac_cr_lock, flags);
554
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000555 ret = smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr);
556 check_warn_return(ret, "Error writing MAC_CR");
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000557
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000558 ret = smsc95xx_phy_update_flowcontrol(dev, ecmd.duplex, lcladv, rmtadv);
559 check_warn_return(ret, "Error updating PHY flow control");
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000560
561 return 0;
562}
563
564static void smsc95xx_status(struct usbnet *dev, struct urb *urb)
565{
566 u32 intdata;
567
568 if (urb->actual_length != 4) {
Joe Perches60b86752010-02-17 10:30:23 +0000569 netdev_warn(dev->net, "unexpected urb length %d\n",
570 urb->actual_length);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000571 return;
572 }
573
574 memcpy(&intdata, urb->transfer_buffer, 4);
Steve Glendinning1d74a6b2008-10-09 14:34:47 -0700575 le32_to_cpus(&intdata);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000576
Joe Perchesa475f602010-02-17 10:30:24 +0000577 netif_dbg(dev, link, dev->net, "intdata: 0x%08X\n", intdata);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000578
579 if (intdata & INT_ENP_PHY_INT_)
580 usbnet_defer_kevent(dev, EVENT_LINK_RESET);
581 else
Joe Perches60b86752010-02-17 10:30:23 +0000582 netdev_warn(dev->net, "unexpected interrupt, intdata=0x%08X\n",
583 intdata);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000584}
585
Steve Glendinningf7b29272008-11-20 04:19:21 -0800586/* Enable or disable Tx & Rx checksum offload engines */
Michał Mirosławc8f44af2011-11-15 15:29:55 +0000587static int smsc95xx_set_features(struct net_device *netdev,
588 netdev_features_t features)
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000589{
Michał Mirosław78e47fe2011-04-01 20:56:23 -0700590 struct usbnet *dev = netdev_priv(netdev);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000591 u32 read_buf;
Michał Mirosław78e47fe2011-04-01 20:56:23 -0700592 int ret;
593
594 ret = smsc95xx_read_reg(dev, COE_CR, &read_buf);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000595 check_warn_return(ret, "Failed to read COE_CR: %d\n", ret);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000596
Michał Mirosław78e47fe2011-04-01 20:56:23 -0700597 if (features & NETIF_F_HW_CSUM)
Steve Glendinningf7b29272008-11-20 04:19:21 -0800598 read_buf |= Tx_COE_EN_;
599 else
600 read_buf &= ~Tx_COE_EN_;
601
Michał Mirosław78e47fe2011-04-01 20:56:23 -0700602 if (features & NETIF_F_RXCSUM)
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000603 read_buf |= Rx_COE_EN_;
604 else
605 read_buf &= ~Rx_COE_EN_;
606
607 ret = smsc95xx_write_reg(dev, COE_CR, read_buf);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000608 check_warn_return(ret, "Failed to write COE_CR: %d\n", ret);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000609
Joe Perchesa475f602010-02-17 10:30:24 +0000610 netif_dbg(dev, hw, dev->net, "COE_CR = 0x%08x\n", read_buf);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000611 return 0;
612}
613
614static int smsc95xx_ethtool_get_eeprom_len(struct net_device *net)
615{
616 return MAX_EEPROM_SIZE;
617}
618
619static int smsc95xx_ethtool_get_eeprom(struct net_device *netdev,
620 struct ethtool_eeprom *ee, u8 *data)
621{
622 struct usbnet *dev = netdev_priv(netdev);
623
624 ee->magic = LAN95XX_EEPROM_MAGIC;
625
626 return smsc95xx_read_eeprom(dev, ee->offset, ee->len, data);
627}
628
629static int smsc95xx_ethtool_set_eeprom(struct net_device *netdev,
630 struct ethtool_eeprom *ee, u8 *data)
631{
632 struct usbnet *dev = netdev_priv(netdev);
633
634 if (ee->magic != LAN95XX_EEPROM_MAGIC) {
Joe Perches60b86752010-02-17 10:30:23 +0000635 netdev_warn(dev->net, "EEPROM: magic value mismatch, magic = 0x%x\n",
636 ee->magic);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000637 return -EINVAL;
638 }
639
640 return smsc95xx_write_eeprom(dev, ee->offset, ee->len, data);
641}
642
Emeric Vigier9fa32e92012-07-09 17:44:45 -0400643static int smsc95xx_ethtool_getregslen(struct net_device *netdev)
644{
645 /* all smsc95xx registers */
646 return COE_CR - ID_REV + 1;
647}
648
649static void
650smsc95xx_ethtool_getregs(struct net_device *netdev, struct ethtool_regs *regs,
651 void *buf)
652{
653 struct usbnet *dev = netdev_priv(netdev);
Dan Carpenterd3484462012-07-10 20:32:51 +0000654 unsigned int i, j;
655 int retval;
Emeric Vigier9fa32e92012-07-09 17:44:45 -0400656 u32 *data = buf;
657
658 retval = smsc95xx_read_reg(dev, ID_REV, &regs->version);
659 if (retval < 0) {
660 netdev_warn(netdev, "REGS: cannot read ID_REV\n");
661 return;
662 }
663
664 for (i = ID_REV, j = 0; i <= COE_CR; i += (sizeof(u32)), j++) {
665 retval = smsc95xx_read_reg(dev, i, &data[j]);
666 if (retval < 0) {
667 netdev_warn(netdev, "REGS: cannot read reg[%x]\n", i);
668 return;
669 }
670 }
671}
672
Steve Glendinninge0e474a2012-09-28 00:07:12 +0000673static void smsc95xx_ethtool_get_wol(struct net_device *net,
674 struct ethtool_wolinfo *wolinfo)
675{
676 struct usbnet *dev = netdev_priv(net);
677 struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
678
679 wolinfo->supported = SUPPORTED_WAKE;
680 wolinfo->wolopts = pdata->wolopts;
681}
682
683static int smsc95xx_ethtool_set_wol(struct net_device *net,
684 struct ethtool_wolinfo *wolinfo)
685{
686 struct usbnet *dev = netdev_priv(net);
687 struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
688
689 pdata->wolopts = wolinfo->wolopts & SUPPORTED_WAKE;
690 return 0;
691}
692
Stephen Hemminger0fc0b732009-09-02 01:03:33 -0700693static const struct ethtool_ops smsc95xx_ethtool_ops = {
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000694 .get_link = usbnet_get_link,
695 .nway_reset = usbnet_nway_reset,
696 .get_drvinfo = usbnet_get_drvinfo,
697 .get_msglevel = usbnet_get_msglevel,
698 .set_msglevel = usbnet_set_msglevel,
699 .get_settings = usbnet_get_settings,
700 .set_settings = usbnet_set_settings,
701 .get_eeprom_len = smsc95xx_ethtool_get_eeprom_len,
702 .get_eeprom = smsc95xx_ethtool_get_eeprom,
703 .set_eeprom = smsc95xx_ethtool_set_eeprom,
Emeric Vigier9fa32e92012-07-09 17:44:45 -0400704 .get_regs_len = smsc95xx_ethtool_getregslen,
705 .get_regs = smsc95xx_ethtool_getregs,
Steve Glendinninge0e474a2012-09-28 00:07:12 +0000706 .get_wol = smsc95xx_ethtool_get_wol,
707 .set_wol = smsc95xx_ethtool_set_wol,
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000708};
709
710static int smsc95xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
711{
712 struct usbnet *dev = netdev_priv(netdev);
713
714 if (!netif_running(netdev))
715 return -EINVAL;
716
717 return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
718}
719
720static void smsc95xx_init_mac_address(struct usbnet *dev)
721{
722 /* try reading mac address from EEPROM */
723 if (smsc95xx_read_eeprom(dev, EEPROM_MAC_OFFSET, ETH_ALEN,
724 dev->net->dev_addr) == 0) {
725 if (is_valid_ether_addr(dev->net->dev_addr)) {
726 /* eeprom values are valid so use them */
Joe Perchesa475f602010-02-17 10:30:24 +0000727 netif_dbg(dev, ifup, dev->net, "MAC address read from EEPROM\n");
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000728 return;
729 }
730 }
731
732 /* no eeprom, or eeprom values are invalid. generate random MAC */
Danny Kukawkaf2cedb62012-02-15 06:45:39 +0000733 eth_hw_addr_random(dev->net);
Joe Perchesc7e12ea2012-07-12 19:33:07 +0000734 netif_dbg(dev, ifup, dev->net, "MAC address set to eth_random_addr\n");
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000735}
736
737static int smsc95xx_set_mac_address(struct usbnet *dev)
738{
739 u32 addr_lo = dev->net->dev_addr[0] | dev->net->dev_addr[1] << 8 |
740 dev->net->dev_addr[2] << 16 | dev->net->dev_addr[3] << 24;
741 u32 addr_hi = dev->net->dev_addr[4] | dev->net->dev_addr[5] << 8;
742 int ret;
743
744 ret = smsc95xx_write_reg(dev, ADDRL, addr_lo);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000745 check_warn_return(ret, "Failed to write ADDRL: %d\n", ret);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000746
747 ret = smsc95xx_write_reg(dev, ADDRH, addr_hi);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000748 check_warn_return(ret, "Failed to write ADDRH: %d\n", ret);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000749
750 return 0;
751}
752
753/* starts the TX path */
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000754static int smsc95xx_start_tx_path(struct usbnet *dev)
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000755{
756 struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
757 unsigned long flags;
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000758 int ret;
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000759
760 /* Enable Tx at MAC */
761 spin_lock_irqsave(&pdata->mac_cr_lock, flags);
762 pdata->mac_cr |= MAC_CR_TXEN_;
763 spin_unlock_irqrestore(&pdata->mac_cr_lock, flags);
764
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000765 ret = smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr);
766 check_warn_return(ret, "Failed to write MAC_CR: %d\n", ret);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000767
768 /* Enable Tx at SCSRs */
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000769 ret = smsc95xx_write_reg(dev, TX_CFG, TX_CFG_ON_);
770 check_warn_return(ret, "Failed to write TX_CFG: %d\n", ret);
771
772 return 0;
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000773}
774
775/* Starts the Receive path */
Ming Leiec321152012-11-06 04:53:07 +0000776static int smsc95xx_start_rx_path(struct usbnet *dev, int in_pm)
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000777{
778 struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
779 unsigned long flags;
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000780 int ret;
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000781
782 spin_lock_irqsave(&pdata->mac_cr_lock, flags);
783 pdata->mac_cr |= MAC_CR_RXEN_;
784 spin_unlock_irqrestore(&pdata->mac_cr_lock, flags);
785
Ming Leiec321152012-11-06 04:53:07 +0000786 ret = __smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr, in_pm);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000787 check_warn_return(ret, "Failed to write MAC_CR: %d\n", ret);
788
789 return 0;
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000790}
791
792static int smsc95xx_phy_initialize(struct usbnet *dev)
793{
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000794 int bmcr, ret, timeout = 0;
Steve Glendinningdb443c42010-03-16 09:03:06 +0000795
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000796 /* Initialize MII structure */
797 dev->mii.dev = dev->net;
798 dev->mii.mdio_read = smsc95xx_mdio_read;
799 dev->mii.mdio_write = smsc95xx_mdio_write;
800 dev->mii.phy_id_mask = 0x1f;
801 dev->mii.reg_num_mask = 0x1f;
802 dev->mii.phy_id = SMSC95XX_INTERNAL_PHY_ID;
803
Steve Glendinningdb443c42010-03-16 09:03:06 +0000804 /* reset phy and wait for reset to complete */
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000805 smsc95xx_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
Steve Glendinningdb443c42010-03-16 09:03:06 +0000806
807 do {
808 msleep(10);
809 bmcr = smsc95xx_mdio_read(dev->net, dev->mii.phy_id, MII_BMCR);
810 timeout++;
Rabin Vincentd9460922011-04-30 08:29:27 +0000811 } while ((bmcr & BMCR_RESET) && (timeout < 100));
Steve Glendinningdb443c42010-03-16 09:03:06 +0000812
813 if (timeout >= 100) {
814 netdev_warn(dev->net, "timeout on PHY Reset");
815 return -EIO;
816 }
817
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000818 smsc95xx_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
819 ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP |
820 ADVERTISE_PAUSE_ASYM);
821
822 /* read to clear */
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000823 ret = smsc95xx_mdio_read(dev->net, dev->mii.phy_id, PHY_INT_SRC);
824 check_warn_return(ret, "Failed to read PHY_INT_SRC during init");
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000825
826 smsc95xx_mdio_write(dev->net, dev->mii.phy_id, PHY_INT_MASK,
827 PHY_INT_MASK_DEFAULT_);
828 mii_nway_restart(&dev->mii);
829
Joe Perchesa475f602010-02-17 10:30:24 +0000830 netif_dbg(dev, ifup, dev->net, "phy initialised successfully\n");
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000831 return 0;
832}
833
834static int smsc95xx_reset(struct usbnet *dev)
835{
836 struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
837 u32 read_buf, write_buf, burst_cap;
838 int ret = 0, timeout;
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000839
Joe Perchesa475f602010-02-17 10:30:24 +0000840 netif_dbg(dev, ifup, dev->net, "entering smsc95xx_reset\n");
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000841
Steve Glendinning44367612012-09-28 00:07:08 +0000842 ret = smsc95xx_write_reg(dev, HW_CFG, HW_CFG_LRST_);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000843 check_warn_return(ret, "Failed to write HW_CFG_LRST_ bit in HW_CFG\n");
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000844
845 timeout = 0;
846 do {
Steve Glendinningcf2acec2012-09-28 00:07:07 +0000847 msleep(10);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000848 ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000849 check_warn_return(ret, "Failed to read HW_CFG: %d\n", ret);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000850 timeout++;
851 } while ((read_buf & HW_CFG_LRST_) && (timeout < 100));
852
853 if (timeout >= 100) {
Joe Perches60b86752010-02-17 10:30:23 +0000854 netdev_warn(dev->net, "timeout waiting for completion of Lite Reset\n");
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000855 return ret;
856 }
857
Steve Glendinning44367612012-09-28 00:07:08 +0000858 ret = smsc95xx_write_reg(dev, PM_CTRL, PM_CTL_PHY_RST_);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000859 check_warn_return(ret, "Failed to write PM_CTRL: %d\n", ret);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000860
861 timeout = 0;
862 do {
Steve Glendinningcf2acec2012-09-28 00:07:07 +0000863 msleep(10);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000864 ret = smsc95xx_read_reg(dev, PM_CTRL, &read_buf);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000865 check_warn_return(ret, "Failed to read PM_CTRL: %d\n", ret);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000866 timeout++;
867 } while ((read_buf & PM_CTL_PHY_RST_) && (timeout < 100));
868
869 if (timeout >= 100) {
Joe Perches60b86752010-02-17 10:30:23 +0000870 netdev_warn(dev->net, "timeout waiting for PHY Reset\n");
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000871 return ret;
872 }
873
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000874 ret = smsc95xx_set_mac_address(dev);
875 if (ret < 0)
876 return ret;
877
Joe Perchesa475f602010-02-17 10:30:24 +0000878 netif_dbg(dev, ifup, dev->net,
879 "MAC Address: %pM\n", dev->net->dev_addr);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000880
881 ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000882 check_warn_return(ret, "Failed to read HW_CFG: %d\n", ret);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000883
Joe Perchesa475f602010-02-17 10:30:24 +0000884 netif_dbg(dev, ifup, dev->net,
885 "Read Value from HW_CFG : 0x%08x\n", read_buf);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000886
887 read_buf |= HW_CFG_BIR_;
888
889 ret = smsc95xx_write_reg(dev, HW_CFG, read_buf);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000890 check_warn_return(ret, "Failed to write HW_CFG_BIR_ bit in HW_CFG\n");
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000891
892 ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000893 check_warn_return(ret, "Failed to read HW_CFG: %d\n", ret);
Joe Perchesa475f602010-02-17 10:30:24 +0000894 netif_dbg(dev, ifup, dev->net,
895 "Read Value from HW_CFG after writing HW_CFG_BIR_: 0x%08x\n",
896 read_buf);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000897
898 if (!turbo_mode) {
899 burst_cap = 0;
900 dev->rx_urb_size = MAX_SINGLE_PACKET_SIZE;
901 } else if (dev->udev->speed == USB_SPEED_HIGH) {
902 burst_cap = DEFAULT_HS_BURST_CAP_SIZE / HS_USB_PKT_SIZE;
903 dev->rx_urb_size = DEFAULT_HS_BURST_CAP_SIZE;
904 } else {
905 burst_cap = DEFAULT_FS_BURST_CAP_SIZE / FS_USB_PKT_SIZE;
906 dev->rx_urb_size = DEFAULT_FS_BURST_CAP_SIZE;
907 }
908
Joe Perchesa475f602010-02-17 10:30:24 +0000909 netif_dbg(dev, ifup, dev->net,
910 "rx_urb_size=%ld\n", (ulong)dev->rx_urb_size);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000911
912 ret = smsc95xx_write_reg(dev, BURST_CAP, burst_cap);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000913 check_warn_return(ret, "Failed to write BURST_CAP: %d\n", ret);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000914
915 ret = smsc95xx_read_reg(dev, BURST_CAP, &read_buf);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000916 check_warn_return(ret, "Failed to read BURST_CAP: %d\n", ret);
917
Joe Perchesa475f602010-02-17 10:30:24 +0000918 netif_dbg(dev, ifup, dev->net,
919 "Read Value from BURST_CAP after writing: 0x%08x\n",
920 read_buf);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000921
Steve Glendinning44367612012-09-28 00:07:08 +0000922 ret = smsc95xx_write_reg(dev, BULK_IN_DLY, DEFAULT_BULK_IN_DELAY);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000923 check_warn_return(ret, "Failed to write BULK_IN_DLY: %d\n", ret);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000924
925 ret = smsc95xx_read_reg(dev, BULK_IN_DLY, &read_buf);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000926 check_warn_return(ret, "Failed to read BULK_IN_DLY: %d\n", ret);
927
Joe Perchesa475f602010-02-17 10:30:24 +0000928 netif_dbg(dev, ifup, dev->net,
929 "Read Value from BULK_IN_DLY after writing: 0x%08x\n",
930 read_buf);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000931
932 ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000933 check_warn_return(ret, "Failed to read HW_CFG: %d\n", ret);
934
Joe Perchesa475f602010-02-17 10:30:24 +0000935 netif_dbg(dev, ifup, dev->net,
936 "Read Value from HW_CFG: 0x%08x\n", read_buf);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000937
938 if (turbo_mode)
939 read_buf |= (HW_CFG_MEF_ | HW_CFG_BCE_);
940
941 read_buf &= ~HW_CFG_RXDOFF_;
942
943 /* set Rx data offset=2, Make IP header aligns on word boundary. */
944 read_buf |= NET_IP_ALIGN << 9;
945
946 ret = smsc95xx_write_reg(dev, HW_CFG, read_buf);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000947 check_warn_return(ret, "Failed to write HW_CFG: %d\n", ret);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000948
949 ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000950 check_warn_return(ret, "Failed to read HW_CFG: %d\n", ret);
951
Joe Perchesa475f602010-02-17 10:30:24 +0000952 netif_dbg(dev, ifup, dev->net,
953 "Read Value from HW_CFG after writing: 0x%08x\n", read_buf);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000954
Steve Glendinning44367612012-09-28 00:07:08 +0000955 ret = smsc95xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL_);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000956 check_warn_return(ret, "Failed to write INT_STS: %d\n", ret);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000957
958 ret = smsc95xx_read_reg(dev, ID_REV, &read_buf);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000959 check_warn_return(ret, "Failed to read ID_REV: %d\n", ret);
Joe Perchesa475f602010-02-17 10:30:24 +0000960 netif_dbg(dev, ifup, dev->net, "ID_REV = 0x%08x\n", read_buf);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000961
Steve Glendinningf2935012009-05-01 05:46:51 +0000962 /* Configure GPIO pins as LED outputs */
963 write_buf = LED_GPIO_CFG_SPD_LED | LED_GPIO_CFG_LNK_LED |
964 LED_GPIO_CFG_FDX_LED;
965 ret = smsc95xx_write_reg(dev, LED_GPIO_CFG, write_buf);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000966 check_warn_return(ret, "Failed to write LED_GPIO_CFG: %d\n", ret);
Steve Glendinningf2935012009-05-01 05:46:51 +0000967
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000968 /* Init Tx */
Steve Glendinning44367612012-09-28 00:07:08 +0000969 ret = smsc95xx_write_reg(dev, FLOW, 0);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000970 check_warn_return(ret, "Failed to write FLOW: %d\n", ret);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000971
Steve Glendinning44367612012-09-28 00:07:08 +0000972 ret = smsc95xx_write_reg(dev, AFC_CFG, AFC_CFG_DEFAULT);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000973 check_warn_return(ret, "Failed to write AFC_CFG: %d\n", ret);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000974
975 /* Don't need mac_cr_lock during initialisation */
976 ret = smsc95xx_read_reg(dev, MAC_CR, &pdata->mac_cr);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000977 check_warn_return(ret, "Failed to read MAC_CR: %d\n", ret);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000978
979 /* Init Rx */
980 /* Set Vlan */
Steve Glendinning44367612012-09-28 00:07:08 +0000981 ret = smsc95xx_write_reg(dev, VLAN1, (u32)ETH_P_8021Q);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000982 check_warn_return(ret, "Failed to write VLAN1: %d\n", ret);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000983
Steve Glendinningf7b29272008-11-20 04:19:21 -0800984 /* Enable or disable checksum offload engines */
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000985 ret = smsc95xx_set_features(dev->net, dev->net->features);
986 check_warn_return(ret, "Failed to set checksum offload features");
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000987
988 smsc95xx_set_multicast(dev->net);
989
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000990 ret = smsc95xx_phy_initialize(dev);
991 check_warn_return(ret, "Failed to init PHY");
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000992
993 ret = smsc95xx_read_reg(dev, INT_EP_CTL, &read_buf);
Steve Glendinning769ea6d2012-09-28 00:07:09 +0000994 check_warn_return(ret, "Failed to read INT_EP_CTL: %d\n", ret);
Steve Glendinning2f7ca802008-10-02 05:27:57 +0000995
996 /* enable PHY interrupts */
997 read_buf |= INT_EP_CTL_PHY_INT_;
998
999 ret = smsc95xx_write_reg(dev, INT_EP_CTL, read_buf);
Steve Glendinning769ea6d2012-09-28 00:07:09 +00001000 check_warn_return(ret, "Failed to write INT_EP_CTL: %d\n", ret);
Steve Glendinning2f7ca802008-10-02 05:27:57 +00001001
Steve Glendinning769ea6d2012-09-28 00:07:09 +00001002 ret = smsc95xx_start_tx_path(dev);
1003 check_warn_return(ret, "Failed to start TX path");
1004
Ming Leiec321152012-11-06 04:53:07 +00001005 ret = smsc95xx_start_rx_path(dev, 0);
Steve Glendinning769ea6d2012-09-28 00:07:09 +00001006 check_warn_return(ret, "Failed to start RX path");
Steve Glendinning2f7ca802008-10-02 05:27:57 +00001007
Joe Perchesa475f602010-02-17 10:30:24 +00001008 netif_dbg(dev, ifup, dev->net, "smsc95xx_reset, return 0\n");
Steve Glendinning2f7ca802008-10-02 05:27:57 +00001009 return 0;
1010}
1011
Stephen Hemminger63e77b32009-03-20 19:35:58 +00001012static const struct net_device_ops smsc95xx_netdev_ops = {
1013 .ndo_open = usbnet_open,
1014 .ndo_stop = usbnet_stop,
1015 .ndo_start_xmit = usbnet_start_xmit,
1016 .ndo_tx_timeout = usbnet_tx_timeout,
1017 .ndo_change_mtu = usbnet_change_mtu,
1018 .ndo_set_mac_address = eth_mac_addr,
1019 .ndo_validate_addr = eth_validate_addr,
1020 .ndo_do_ioctl = smsc95xx_ioctl,
Jiri Pirkoafc4b132011-08-16 06:29:01 +00001021 .ndo_set_rx_mode = smsc95xx_set_multicast,
Michał Mirosław78e47fe2011-04-01 20:56:23 -07001022 .ndo_set_features = smsc95xx_set_features,
Stephen Hemminger63e77b32009-03-20 19:35:58 +00001023};
1024
Steve Glendinning2f7ca802008-10-02 05:27:57 +00001025static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
1026{
1027 struct smsc95xx_priv *pdata = NULL;
Steve Glendinningbbd9f9e2012-10-26 03:43:56 +00001028 u32 val;
Steve Glendinning2f7ca802008-10-02 05:27:57 +00001029 int ret;
1030
1031 printk(KERN_INFO SMSC_CHIPNAME " v" SMSC_DRIVER_VERSION "\n");
1032
1033 ret = usbnet_get_endpoints(dev, intf);
Steve Glendinning769ea6d2012-09-28 00:07:09 +00001034 check_warn_return(ret, "usbnet_get_endpoints failed: %d\n", ret);
Steve Glendinning2f7ca802008-10-02 05:27:57 +00001035
1036 dev->data[0] = (unsigned long)kzalloc(sizeof(struct smsc95xx_priv),
1037 GFP_KERNEL);
1038
1039 pdata = (struct smsc95xx_priv *)(dev->data[0]);
1040 if (!pdata) {
Joe Perches60b86752010-02-17 10:30:23 +00001041 netdev_warn(dev->net, "Unable to allocate struct smsc95xx_priv\n");
Steve Glendinning2f7ca802008-10-02 05:27:57 +00001042 return -ENOMEM;
1043 }
1044
1045 spin_lock_init(&pdata->mac_cr_lock);
1046
Michał Mirosław78e47fe2011-04-01 20:56:23 -07001047 if (DEFAULT_TX_CSUM_ENABLE)
1048 dev->net->features |= NETIF_F_HW_CSUM;
1049 if (DEFAULT_RX_CSUM_ENABLE)
1050 dev->net->features |= NETIF_F_RXCSUM;
1051
1052 dev->net->hw_features = NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
Steve Glendinning2f7ca802008-10-02 05:27:57 +00001053
Bernard Blackhamf4e8ab72010-10-18 13:16:39 +00001054 smsc95xx_init_mac_address(dev);
1055
Steve Glendinning2f7ca802008-10-02 05:27:57 +00001056 /* Init all registers */
1057 ret = smsc95xx_reset(dev);
1058
Steve Glendinningbbd9f9e2012-10-26 03:43:56 +00001059 /* detect device revision as different features may be available */
1060 ret = smsc95xx_read_reg(dev, ID_REV, &val);
1061 check_warn_return(ret, "Failed to read ID_REV: %d\n", ret);
1062 val >>= 16;
Steve Glendinning9ebca502012-11-22 08:05:23 +00001063
1064 if ((val == ID_REV_CHIP_ID_9500A_) || (val == ID_REV_CHIP_ID_9530_) ||
1065 (val == ID_REV_CHIP_ID_89530_) || (val == ID_REV_CHIP_ID_9730_))
1066 pdata->features = (FEATURE_8_WAKEUP_FILTERS |
1067 FEATURE_PHY_NLP_CROSSOVER |
1068 FEATURE_AUTOSUSPEND);
1069 else if (val == ID_REV_CHIP_ID_9512_)
1070 pdata->features = FEATURE_8_WAKEUP_FILTERS;
Steve Glendinningbbd9f9e2012-10-26 03:43:56 +00001071
Stephen Hemminger63e77b32009-03-20 19:35:58 +00001072 dev->net->netdev_ops = &smsc95xx_netdev_ops;
Steve Glendinning2f7ca802008-10-02 05:27:57 +00001073 dev->net->ethtool_ops = &smsc95xx_ethtool_ops;
Steve Glendinning2f7ca802008-10-02 05:27:57 +00001074 dev->net->flags |= IFF_MULTICAST;
Michał Mirosław78e47fe2011-04-01 20:56:23 -07001075 dev->net->hard_header_len += SMSC95XX_TX_OVERHEAD_CSUM;
Stephane Fillod9bbf5662012-04-20 09:39:23 +00001076 dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
Steve Glendinning2f7ca802008-10-02 05:27:57 +00001077 return 0;
1078}
1079
1080static void smsc95xx_unbind(struct usbnet *dev, struct usb_interface *intf)
1081{
1082 struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
1083 if (pdata) {
Joe Perchesa475f602010-02-17 10:30:24 +00001084 netif_dbg(dev, ifdown, dev->net, "free pdata\n");
Steve Glendinning2f7ca802008-10-02 05:27:57 +00001085 kfree(pdata);
1086 pdata = NULL;
1087 dev->data[0] = 0;
1088 }
1089}
1090
Steve Glendinningbbd9f9e2012-10-26 03:43:56 +00001091static u16 smsc_crc(const u8 *buffer, size_t len, int filter)
1092{
1093 return bitrev16(crc16(0xFFFF, buffer, len)) << ((filter % 2) * 16);
1094}
1095
Steve Glendinninge5e3af82012-11-22 08:05:24 +00001096static int smsc95xx_enable_phy_wakeup_interrupts(struct usbnet *dev, u16 mask)
1097{
1098 struct mii_if_info *mii = &dev->mii;
1099 int ret;
1100
1101 netdev_dbg(dev->net, "enabling PHY wakeup interrupts");
1102
1103 /* read to clear */
1104 ret = smsc95xx_mdio_read_nopm(dev->net, mii->phy_id, PHY_INT_SRC);
1105 check_warn_return(ret, "Error reading PHY_INT_SRC");
1106
1107 /* enable interrupt source */
1108 ret = smsc95xx_mdio_read_nopm(dev->net, mii->phy_id, PHY_INT_MASK);
1109 check_warn_return(ret, "Error reading PHY_INT_MASK");
1110
1111 ret |= mask;
1112
1113 smsc95xx_mdio_write_nopm(dev->net, mii->phy_id, PHY_INT_MASK, ret);
1114
1115 return 0;
1116}
1117
1118static int smsc95xx_link_ok_nopm(struct usbnet *dev)
1119{
1120 struct mii_if_info *mii = &dev->mii;
1121 int ret;
1122
1123 /* first, a dummy read, needed to latch some MII phys */
1124 ret = smsc95xx_mdio_read_nopm(dev->net, mii->phy_id, MII_BMSR);
1125 check_warn_return(ret, "Error reading MII_BMSR");
1126
1127 ret = smsc95xx_mdio_read_nopm(dev->net, mii->phy_id, MII_BMSR);
1128 check_warn_return(ret, "Error reading MII_BMSR");
1129
1130 return !!(ret & BMSR_LSTATUS);
1131}
1132
Steve Glendinningb5a04472012-09-28 00:07:11 +00001133static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message)
1134{
1135 struct usbnet *dev = usb_get_intfdata(intf);
Steve Glendinninge0e474a2012-09-28 00:07:12 +00001136 struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
Steve Glendinninge5e3af82012-11-22 08:05:24 +00001137 u32 val, link_up;
Steve Glendinningb5a04472012-09-28 00:07:11 +00001138 int ret;
Steve Glendinningb5a04472012-09-28 00:07:11 +00001139
Steve Glendinningb5a04472012-09-28 00:07:11 +00001140 ret = usbnet_suspend(intf, message);
1141 check_warn_return(ret, "usbnet_suspend error");
1142
Steve Glendinninge5e3af82012-11-22 08:05:24 +00001143 /* determine if link is up using only _nopm functions */
1144 link_up = smsc95xx_link_ok_nopm(dev);
1145
1146 /* if no wol options set, or if link is down and we're not waking on
1147 * PHY activity, enter lowest power SUSPEND2 mode
1148 */
1149 if (!(pdata->wolopts & SUPPORTED_WAKE) ||
1150 !(link_up || (pdata->wolopts & WAKE_PHY))) {
Steve Glendinninge0e474a2012-09-28 00:07:12 +00001151 netdev_info(dev->net, "entering SUSPEND2 mode");
1152
1153 /* disable energy detect (link up) & wake up events */
Ming Leiec321152012-11-06 04:53:07 +00001154 ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val);
Steve Glendinninge0e474a2012-09-28 00:07:12 +00001155 check_warn_return(ret, "Error reading WUCSR");
1156
1157 val &= ~(WUCSR_MPEN_ | WUCSR_WAKE_EN_);
1158
Ming Leiec321152012-11-06 04:53:07 +00001159 ret = smsc95xx_write_reg_nopm(dev, WUCSR, val);
Steve Glendinninge0e474a2012-09-28 00:07:12 +00001160 check_warn_return(ret, "Error writing WUCSR");
1161
Ming Leiec321152012-11-06 04:53:07 +00001162 ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
Steve Glendinninge0e474a2012-09-28 00:07:12 +00001163 check_warn_return(ret, "Error reading PM_CTRL");
1164
1165 val &= ~(PM_CTL_ED_EN_ | PM_CTL_WOL_EN_);
1166
Ming Leiec321152012-11-06 04:53:07 +00001167 ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
Steve Glendinninge0e474a2012-09-28 00:07:12 +00001168 check_warn_return(ret, "Error writing PM_CTRL");
1169
1170 /* enter suspend2 mode */
Ming Leiec321152012-11-06 04:53:07 +00001171 ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
Steve Glendinninge0e474a2012-09-28 00:07:12 +00001172 check_warn_return(ret, "Error reading PM_CTRL");
1173
1174 val &= ~(PM_CTL_SUS_MODE_ | PM_CTL_WUPS_ | PM_CTL_PHY_RST_);
1175 val |= PM_CTL_SUS_MODE_2;
1176
Ming Leiec321152012-11-06 04:53:07 +00001177 ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
Steve Glendinninge0e474a2012-09-28 00:07:12 +00001178 check_warn_return(ret, "Error writing PM_CTRL");
1179
1180 return 0;
1181 }
1182
Steve Glendinninge5e3af82012-11-22 08:05:24 +00001183 if (pdata->wolopts & WAKE_PHY) {
1184 ret = smsc95xx_enable_phy_wakeup_interrupts(dev,
1185 (PHY_INT_MASK_ANEG_COMP_ | PHY_INT_MASK_LINK_DOWN_));
1186 check_warn_return(ret, "error enabling PHY wakeup ints");
1187
1188 /* if link is down then configure EDPD and enter SUSPEND1,
1189 * otherwise enter SUSPEND0 below
1190 */
1191 if (!link_up) {
1192 struct mii_if_info *mii = &dev->mii;
1193 netdev_info(dev->net, "entering SUSPEND1 mode");
1194
1195 /* reconfigure link pulse detection timing for
1196 * compatibility with non-standard link partners
1197 */
1198 if (pdata->features & FEATURE_PHY_NLP_CROSSOVER)
1199 smsc95xx_mdio_write_nopm(dev->net, mii->phy_id,
1200 PHY_EDPD_CONFIG,
1201 PHY_EDPD_CONFIG_DEFAULT);
1202
1203 /* enable energy detect power-down mode */
1204 ret = smsc95xx_mdio_read_nopm(dev->net, mii->phy_id,
1205 PHY_MODE_CTRL_STS);
1206 check_warn_return(ret, "Error reading PHY_MODE_CTRL_STS");
1207
1208 ret |= MODE_CTRL_STS_EDPWRDOWN_;
1209
1210 smsc95xx_mdio_write_nopm(dev->net, mii->phy_id,
1211 PHY_MODE_CTRL_STS, ret);
1212
1213 /* enter SUSPEND1 mode */
1214 ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
1215 check_warn_return(ret, "Error reading PM_CTRL");
1216
1217 val &= ~(PM_CTL_SUS_MODE_ | PM_CTL_WUPS_ | PM_CTL_PHY_RST_);
1218 val |= PM_CTL_SUS_MODE_1;
1219
1220 ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
1221 check_warn_return(ret, "Error writing PM_CTRL");
1222
1223 /* clear wol status, enable energy detection */
1224 val &= ~PM_CTL_WUPS_;
1225 val |= (PM_CTL_WUPS_ED_ | PM_CTL_ED_EN_);
1226
1227 ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
1228 check_warn_return(ret, "Error writing PM_CTRL");
1229
1230 smsc95xx_set_feature(dev, USB_DEVICE_REMOTE_WAKEUP);
1231
1232 return 0;
1233 }
1234 }
1235
Steve Glendinningbbd9f9e2012-10-26 03:43:56 +00001236 if (pdata->wolopts & (WAKE_BCAST | WAKE_MCAST | WAKE_ARP | WAKE_UCAST)) {
1237 u32 *filter_mask = kzalloc(32, GFP_KERNEL);
Ming Lei06a221b2012-11-06 04:53:06 +00001238 u32 command[2];
1239 u32 offset[2];
1240 u32 crc[4];
Steve Glendinning9ebca502012-11-22 08:05:23 +00001241 int wuff_filter_count =
1242 (pdata->features & FEATURE_8_WAKEUP_FILTERS) ?
1243 LAN9500A_WUFF_NUM : LAN9500_WUFF_NUM;
Steve Glendinningbbd9f9e2012-10-26 03:43:56 +00001244 int i, filter = 0;
1245
Ming Lei06a221b2012-11-06 04:53:06 +00001246 memset(command, 0, sizeof(command));
1247 memset(offset, 0, sizeof(offset));
1248 memset(crc, 0, sizeof(crc));
1249
Steve Glendinningbbd9f9e2012-10-26 03:43:56 +00001250 if (pdata->wolopts & WAKE_BCAST) {
1251 const u8 bcast[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
1252 netdev_info(dev->net, "enabling broadcast detection");
1253 filter_mask[filter * 4] = 0x003F;
1254 filter_mask[filter * 4 + 1] = 0x00;
1255 filter_mask[filter * 4 + 2] = 0x00;
1256 filter_mask[filter * 4 + 3] = 0x00;
1257 command[filter/4] |= 0x05UL << ((filter % 4) * 8);
1258 offset[filter/4] |= 0x00 << ((filter % 4) * 8);
1259 crc[filter/2] |= smsc_crc(bcast, 6, filter);
1260 filter++;
1261 }
1262
1263 if (pdata->wolopts & WAKE_MCAST) {
1264 const u8 mcast[] = {0x01, 0x00, 0x5E};
1265 netdev_info(dev->net, "enabling multicast detection");
1266 filter_mask[filter * 4] = 0x0007;
1267 filter_mask[filter * 4 + 1] = 0x00;
1268 filter_mask[filter * 4 + 2] = 0x00;
1269 filter_mask[filter * 4 + 3] = 0x00;
1270 command[filter/4] |= 0x09UL << ((filter % 4) * 8);
1271 offset[filter/4] |= 0x00 << ((filter % 4) * 8);
1272 crc[filter/2] |= smsc_crc(mcast, 3, filter);
1273 filter++;
1274 }
1275
1276 if (pdata->wolopts & WAKE_ARP) {
1277 const u8 arp[] = {0x08, 0x06};
1278 netdev_info(dev->net, "enabling ARP detection");
1279 filter_mask[filter * 4] = 0x0003;
1280 filter_mask[filter * 4 + 1] = 0x00;
1281 filter_mask[filter * 4 + 2] = 0x00;
1282 filter_mask[filter * 4 + 3] = 0x00;
1283 command[filter/4] |= 0x05UL << ((filter % 4) * 8);
1284 offset[filter/4] |= 0x0C << ((filter % 4) * 8);
1285 crc[filter/2] |= smsc_crc(arp, 2, filter);
1286 filter++;
1287 }
1288
1289 if (pdata->wolopts & WAKE_UCAST) {
1290 netdev_info(dev->net, "enabling unicast detection");
1291 filter_mask[filter * 4] = 0x003F;
1292 filter_mask[filter * 4 + 1] = 0x00;
1293 filter_mask[filter * 4 + 2] = 0x00;
1294 filter_mask[filter * 4 + 3] = 0x00;
1295 command[filter/4] |= 0x01UL << ((filter % 4) * 8);
1296 offset[filter/4] |= 0x00 << ((filter % 4) * 8);
1297 crc[filter/2] |= smsc_crc(dev->net->dev_addr, ETH_ALEN, filter);
1298 filter++;
1299 }
1300
Steve Glendinning9ebca502012-11-22 08:05:23 +00001301 for (i = 0; i < (wuff_filter_count * 4); i++) {
Ming Leiec321152012-11-06 04:53:07 +00001302 ret = smsc95xx_write_reg_nopm(dev, WUFF, filter_mask[i]);
Ming Lei06a221b2012-11-06 04:53:06 +00001303 if (ret < 0)
1304 kfree(filter_mask);
Steve Glendinningbbd9f9e2012-10-26 03:43:56 +00001305 check_warn_return(ret, "Error writing WUFF");
1306 }
Ming Lei06a221b2012-11-06 04:53:06 +00001307 kfree(filter_mask);
Steve Glendinningbbd9f9e2012-10-26 03:43:56 +00001308
Steve Glendinning9ebca502012-11-22 08:05:23 +00001309 for (i = 0; i < (wuff_filter_count / 4); i++) {
Ming Leiec321152012-11-06 04:53:07 +00001310 ret = smsc95xx_write_reg_nopm(dev, WUFF, command[i]);
Steve Glendinningbbd9f9e2012-10-26 03:43:56 +00001311 check_warn_return(ret, "Error writing WUFF");
1312 }
1313
Steve Glendinning9ebca502012-11-22 08:05:23 +00001314 for (i = 0; i < (wuff_filter_count / 4); i++) {
Ming Leiec321152012-11-06 04:53:07 +00001315 ret = smsc95xx_write_reg_nopm(dev, WUFF, offset[i]);
Steve Glendinningbbd9f9e2012-10-26 03:43:56 +00001316 check_warn_return(ret, "Error writing WUFF");
1317 }
1318
Steve Glendinning9ebca502012-11-22 08:05:23 +00001319 for (i = 0; i < (wuff_filter_count / 2); i++) {
Ming Leiec321152012-11-06 04:53:07 +00001320 ret = smsc95xx_write_reg_nopm(dev, WUFF, crc[i]);
Steve Glendinningbbd9f9e2012-10-26 03:43:56 +00001321 check_warn_return(ret, "Error writing WUFF");
1322 }
1323
1324 /* clear any pending pattern match packet status */
Ming Leiec321152012-11-06 04:53:07 +00001325 ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val);
Steve Glendinningbbd9f9e2012-10-26 03:43:56 +00001326 check_warn_return(ret, "Error reading WUCSR");
1327
1328 val |= WUCSR_WUFR_;
1329
Ming Leiec321152012-11-06 04:53:07 +00001330 ret = smsc95xx_write_reg_nopm(dev, WUCSR, val);
Steve Glendinningbbd9f9e2012-10-26 03:43:56 +00001331 check_warn_return(ret, "Error writing WUCSR");
1332 }
1333
Steve Glendinninge0e474a2012-09-28 00:07:12 +00001334 if (pdata->wolopts & WAKE_MAGIC) {
1335 /* clear any pending magic packet status */
Ming Leiec321152012-11-06 04:53:07 +00001336 ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val);
Steve Glendinninge0e474a2012-09-28 00:07:12 +00001337 check_warn_return(ret, "Error reading WUCSR");
1338
1339 val |= WUCSR_MPR_;
1340
Ming Leiec321152012-11-06 04:53:07 +00001341 ret = smsc95xx_write_reg_nopm(dev, WUCSR, val);
Steve Glendinninge0e474a2012-09-28 00:07:12 +00001342 check_warn_return(ret, "Error writing WUCSR");
1343 }
1344
Steve Glendinningbbd9f9e2012-10-26 03:43:56 +00001345 /* enable/disable wakeup sources */
Ming Leiec321152012-11-06 04:53:07 +00001346 ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val);
Steve Glendinninge0e474a2012-09-28 00:07:12 +00001347 check_warn_return(ret, "Error reading WUCSR");
1348
Steve Glendinningbbd9f9e2012-10-26 03:43:56 +00001349 if (pdata->wolopts & (WAKE_BCAST | WAKE_MCAST | WAKE_ARP | WAKE_UCAST)) {
1350 netdev_info(dev->net, "enabling pattern match wakeup");
1351 val |= WUCSR_WAKE_EN_;
1352 } else {
1353 netdev_info(dev->net, "disabling pattern match wakeup");
1354 val &= ~WUCSR_WAKE_EN_;
1355 }
1356
Steve Glendinninge0e474a2012-09-28 00:07:12 +00001357 if (pdata->wolopts & WAKE_MAGIC) {
1358 netdev_info(dev->net, "enabling magic packet wakeup");
1359 val |= WUCSR_MPEN_;
1360 } else {
1361 netdev_info(dev->net, "disabling magic packet wakeup");
1362 val &= ~WUCSR_MPEN_;
1363 }
1364
Ming Leiec321152012-11-06 04:53:07 +00001365 ret = smsc95xx_write_reg_nopm(dev, WUCSR, val);
Steve Glendinninge0e474a2012-09-28 00:07:12 +00001366 check_warn_return(ret, "Error writing WUCSR");
1367
1368 /* enable wol wakeup source */
Ming Leiec321152012-11-06 04:53:07 +00001369 ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
Steve Glendinninge0e474a2012-09-28 00:07:12 +00001370 check_warn_return(ret, "Error reading PM_CTRL");
1371
1372 val |= PM_CTL_WOL_EN_;
1373
Steve Glendinninge5e3af82012-11-22 08:05:24 +00001374 /* phy energy detect wakeup source */
1375 if (pdata->wolopts & WAKE_PHY)
1376 val |= PM_CTL_ED_EN_;
1377
Ming Leiec321152012-11-06 04:53:07 +00001378 ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
Steve Glendinninge0e474a2012-09-28 00:07:12 +00001379 check_warn_return(ret, "Error writing PM_CTRL");
1380
Steve Glendinningbbd9f9e2012-10-26 03:43:56 +00001381 /* enable receiver to enable frame reception */
Ming Leiec321152012-11-06 04:53:07 +00001382 smsc95xx_start_rx_path(dev, 1);
Steve Glendinninge0e474a2012-09-28 00:07:12 +00001383
1384 /* some wol options are enabled, so enter SUSPEND0 */
1385 netdev_info(dev->net, "entering SUSPEND0 mode");
Steve Glendinningb5a04472012-09-28 00:07:11 +00001386
Ming Leiec321152012-11-06 04:53:07 +00001387 ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
Steve Glendinningb5a04472012-09-28 00:07:11 +00001388 check_warn_return(ret, "Error reading PM_CTRL");
1389
Steve Glendinninge0e474a2012-09-28 00:07:12 +00001390 val &= (~(PM_CTL_SUS_MODE_ | PM_CTL_WUPS_ | PM_CTL_PHY_RST_));
1391 val |= PM_CTL_SUS_MODE_0;
Steve Glendinningb5a04472012-09-28 00:07:11 +00001392
Ming Leiec321152012-11-06 04:53:07 +00001393 ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
Steve Glendinningb5a04472012-09-28 00:07:11 +00001394 check_warn_return(ret, "Error writing PM_CTRL");
1395
Steve Glendinninge0e474a2012-09-28 00:07:12 +00001396 /* clear wol status */
1397 val &= ~PM_CTL_WUPS_;
1398 val |= PM_CTL_WUPS_WOL_;
Steve Glendinninge5e3af82012-11-22 08:05:24 +00001399
1400 /* enable energy detection */
1401 if (pdata->wolopts & WAKE_PHY)
1402 val |= PM_CTL_WUPS_ED_;
1403
Ming Leiec321152012-11-06 04:53:07 +00001404 ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
Steve Glendinninge0e474a2012-09-28 00:07:12 +00001405 check_warn_return(ret, "Error writing PM_CTRL");
1406
1407 /* read back PM_CTRL */
Ming Leiec321152012-11-06 04:53:07 +00001408 ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
Steve Glendinninge0e474a2012-09-28 00:07:12 +00001409 check_warn_return(ret, "Error reading PM_CTRL");
1410
1411 smsc95xx_set_feature(dev, USB_DEVICE_REMOTE_WAKEUP);
1412
1413 return 0;
1414}
1415
1416static int smsc95xx_resume(struct usb_interface *intf)
1417{
1418 struct usbnet *dev = usb_get_intfdata(intf);
1419 struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
1420 int ret;
1421 u32 val;
1422
1423 BUG_ON(!dev);
1424
Steve Glendinningbbd9f9e2012-10-26 03:43:56 +00001425 if (pdata->wolopts) {
Steve Glendinninge0e474a2012-09-28 00:07:12 +00001426 smsc95xx_clear_feature(dev, USB_DEVICE_REMOTE_WAKEUP);
1427
Steve Glendinningbbd9f9e2012-10-26 03:43:56 +00001428 /* clear wake-up sources */
Ming Leiec321152012-11-06 04:53:07 +00001429 ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val);
Steve Glendinninge0e474a2012-09-28 00:07:12 +00001430 check_warn_return(ret, "Error reading WUCSR");
1431
Steve Glendinningbbd9f9e2012-10-26 03:43:56 +00001432 val &= ~(WUCSR_WAKE_EN_ | WUCSR_MPEN_);
Steve Glendinninge0e474a2012-09-28 00:07:12 +00001433
Ming Leiec321152012-11-06 04:53:07 +00001434 ret = smsc95xx_write_reg_nopm(dev, WUCSR, val);
Steve Glendinninge0e474a2012-09-28 00:07:12 +00001435 check_warn_return(ret, "Error writing WUCSR");
1436
1437 /* clear wake-up status */
Ming Leiec321152012-11-06 04:53:07 +00001438 ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
Steve Glendinninge0e474a2012-09-28 00:07:12 +00001439 check_warn_return(ret, "Error reading PM_CTRL");
1440
1441 val &= ~PM_CTL_WOL_EN_;
1442 val |= PM_CTL_WUPS_;
1443
Ming Leiec321152012-11-06 04:53:07 +00001444 ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
Steve Glendinninge0e474a2012-09-28 00:07:12 +00001445 check_warn_return(ret, "Error writing PM_CTRL");
1446 }
1447
Steve Glendinningaf3d7c12012-11-22 08:05:22 +00001448 ret = usbnet_resume(intf);
Steve Glendinninge0e474a2012-09-28 00:07:12 +00001449 check_warn_return(ret, "usbnet_resume error");
1450
Steve Glendinningb5a04472012-09-28 00:07:11 +00001451 return 0;
1452}
1453
Steve Glendinning2f7ca802008-10-02 05:27:57 +00001454static void smsc95xx_rx_csum_offload(struct sk_buff *skb)
1455{
1456 skb->csum = *(u16 *)(skb_tail_pointer(skb) - 2);
1457 skb->ip_summed = CHECKSUM_COMPLETE;
1458 skb_trim(skb, skb->len - 2);
1459}
1460
1461static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
1462{
Steve Glendinning2f7ca802008-10-02 05:27:57 +00001463 while (skb->len > 0) {
1464 u32 header, align_count;
1465 struct sk_buff *ax_skb;
1466 unsigned char *packet;
1467 u16 size;
1468
1469 memcpy(&header, skb->data, sizeof(header));
1470 le32_to_cpus(&header);
1471 skb_pull(skb, 4 + NET_IP_ALIGN);
1472 packet = skb->data;
1473
1474 /* get the packet length */
1475 size = (u16)((header & RX_STS_FL_) >> 16);
1476 align_count = (4 - ((size + NET_IP_ALIGN) % 4)) % 4;
1477
1478 if (unlikely(header & RX_STS_ES_)) {
Joe Perchesa475f602010-02-17 10:30:24 +00001479 netif_dbg(dev, rx_err, dev->net,
1480 "Error header=0x%08x\n", header);
Herbert Xu80667ac2009-06-29 16:53:00 +00001481 dev->net->stats.rx_errors++;
1482 dev->net->stats.rx_dropped++;
Steve Glendinning2f7ca802008-10-02 05:27:57 +00001483
1484 if (header & RX_STS_CRC_) {
Herbert Xu80667ac2009-06-29 16:53:00 +00001485 dev->net->stats.rx_crc_errors++;
Steve Glendinning2f7ca802008-10-02 05:27:57 +00001486 } else {
1487 if (header & (RX_STS_TL_ | RX_STS_RF_))
Herbert Xu80667ac2009-06-29 16:53:00 +00001488 dev->net->stats.rx_frame_errors++;
Steve Glendinning2f7ca802008-10-02 05:27:57 +00001489
1490 if ((header & RX_STS_LE_) &&
1491 (!(header & RX_STS_FT_)))
Herbert Xu80667ac2009-06-29 16:53:00 +00001492 dev->net->stats.rx_length_errors++;
Steve Glendinning2f7ca802008-10-02 05:27:57 +00001493 }
1494 } else {
1495 /* ETH_FRAME_LEN + 4(CRC) + 2(COE) + 4(Vlan) */
1496 if (unlikely(size > (ETH_FRAME_LEN + 12))) {
Joe Perchesa475f602010-02-17 10:30:24 +00001497 netif_dbg(dev, rx_err, dev->net,
1498 "size err header=0x%08x\n", header);
Steve Glendinning2f7ca802008-10-02 05:27:57 +00001499 return 0;
1500 }
1501
1502 /* last frame in this batch */
1503 if (skb->len == size) {
Michał Mirosław78e47fe2011-04-01 20:56:23 -07001504 if (dev->net->features & NETIF_F_RXCSUM)
Steve Glendinning2f7ca802008-10-02 05:27:57 +00001505 smsc95xx_rx_csum_offload(skb);
Peter Korsgaarddf18acc2009-05-13 10:10:41 +00001506 skb_trim(skb, skb->len - 4); /* remove fcs */
Steve Glendinning2f7ca802008-10-02 05:27:57 +00001507 skb->truesize = size + sizeof(struct sk_buff);
1508
1509 return 1;
1510 }
1511
1512 ax_skb = skb_clone(skb, GFP_ATOMIC);
1513 if (unlikely(!ax_skb)) {
Joe Perches60b86752010-02-17 10:30:23 +00001514 netdev_warn(dev->net, "Error allocating skb\n");
Steve Glendinning2f7ca802008-10-02 05:27:57 +00001515 return 0;
1516 }
1517
1518 ax_skb->len = size;
1519 ax_skb->data = packet;
1520 skb_set_tail_pointer(ax_skb, size);
1521
Michał Mirosław78e47fe2011-04-01 20:56:23 -07001522 if (dev->net->features & NETIF_F_RXCSUM)
Steve Glendinning2f7ca802008-10-02 05:27:57 +00001523 smsc95xx_rx_csum_offload(ax_skb);
Peter Korsgaarddf18acc2009-05-13 10:10:41 +00001524 skb_trim(ax_skb, ax_skb->len - 4); /* remove fcs */
Steve Glendinning2f7ca802008-10-02 05:27:57 +00001525 ax_skb->truesize = size + sizeof(struct sk_buff);
1526
1527 usbnet_skb_return(dev, ax_skb);
1528 }
1529
1530 skb_pull(skb, size);
1531
1532 /* padding bytes before the next frame starts */
1533 if (skb->len)
1534 skb_pull(skb, align_count);
1535 }
1536
1537 if (unlikely(skb->len < 0)) {
Joe Perches60b86752010-02-17 10:30:23 +00001538 netdev_warn(dev->net, "invalid rx length<0 %d\n", skb->len);
Steve Glendinning2f7ca802008-10-02 05:27:57 +00001539 return 0;
1540 }
1541
1542 return 1;
1543}
1544
Steve Glendinningf7b29272008-11-20 04:19:21 -08001545static u32 smsc95xx_calc_csum_preamble(struct sk_buff *skb)
1546{
Michał Mirosław55508d62010-12-14 15:24:08 +00001547 u16 low_16 = (u16)skb_checksum_start_offset(skb);
1548 u16 high_16 = low_16 + skb->csum_offset;
Steve Glendinningf7b29272008-11-20 04:19:21 -08001549 return (high_16 << 16) | low_16;
1550}
1551
Steve Glendinning2f7ca802008-10-02 05:27:57 +00001552static struct sk_buff *smsc95xx_tx_fixup(struct usbnet *dev,
1553 struct sk_buff *skb, gfp_t flags)
1554{
Michał Mirosław78e47fe2011-04-01 20:56:23 -07001555 bool csum = skb->ip_summed == CHECKSUM_PARTIAL;
Steve Glendinningf7b29272008-11-20 04:19:21 -08001556 int overhead = csum ? SMSC95XX_TX_OVERHEAD_CSUM : SMSC95XX_TX_OVERHEAD;
Steve Glendinning2f7ca802008-10-02 05:27:57 +00001557 u32 tx_cmd_a, tx_cmd_b;
1558
Steve Glendinningf7b29272008-11-20 04:19:21 -08001559 /* We do not advertise SG, so skbs should be already linearized */
1560 BUG_ON(skb_shinfo(skb)->nr_frags);
1561
1562 if (skb_headroom(skb) < overhead) {
Steve Glendinning2f7ca802008-10-02 05:27:57 +00001563 struct sk_buff *skb2 = skb_copy_expand(skb,
Steve Glendinningf7b29272008-11-20 04:19:21 -08001564 overhead, 0, flags);
Steve Glendinning2f7ca802008-10-02 05:27:57 +00001565 dev_kfree_skb_any(skb);
1566 skb = skb2;
1567 if (!skb)
1568 return NULL;
1569 }
1570
Steve Glendinningf7b29272008-11-20 04:19:21 -08001571 if (csum) {
Steve Glendinning11bc3082010-03-18 22:18:41 -07001572 if (skb->len <= 45) {
1573 /* workaround - hardware tx checksum does not work
1574 * properly with extremely small packets */
Michał Mirosław55508d62010-12-14 15:24:08 +00001575 long csstart = skb_checksum_start_offset(skb);
Steve Glendinning11bc3082010-03-18 22:18:41 -07001576 __wsum calc = csum_partial(skb->data + csstart,
1577 skb->len - csstart, 0);
1578 *((__sum16 *)(skb->data + csstart
1579 + skb->csum_offset)) = csum_fold(calc);
1580
1581 csum = false;
1582 } else {
1583 u32 csum_preamble = smsc95xx_calc_csum_preamble(skb);
1584 skb_push(skb, 4);
Steve Glendinning00acda62012-11-02 00:44:20 +00001585 cpu_to_le32s(&csum_preamble);
Steve Glendinning11bc3082010-03-18 22:18:41 -07001586 memcpy(skb->data, &csum_preamble, 4);
1587 }
Steve Glendinningf7b29272008-11-20 04:19:21 -08001588 }
1589
Steve Glendinning2f7ca802008-10-02 05:27:57 +00001590 skb_push(skb, 4);
1591 tx_cmd_b = (u32)(skb->len - 4);
Steve Glendinningf7b29272008-11-20 04:19:21 -08001592 if (csum)
1593 tx_cmd_b |= TX_CMD_B_CSUM_ENABLE;
Steve Glendinning2f7ca802008-10-02 05:27:57 +00001594 cpu_to_le32s(&tx_cmd_b);
1595 memcpy(skb->data, &tx_cmd_b, 4);
1596
1597 skb_push(skb, 4);
1598 tx_cmd_a = (u32)(skb->len - 8) | TX_CMD_A_FIRST_SEG_ |
1599 TX_CMD_A_LAST_SEG_;
1600 cpu_to_le32s(&tx_cmd_a);
1601 memcpy(skb->data, &tx_cmd_a, 4);
1602
1603 return skb;
1604}
1605
1606static const struct driver_info smsc95xx_info = {
1607 .description = "smsc95xx USB 2.0 Ethernet",
1608 .bind = smsc95xx_bind,
1609 .unbind = smsc95xx_unbind,
1610 .link_reset = smsc95xx_link_reset,
1611 .reset = smsc95xx_reset,
1612 .rx_fixup = smsc95xx_rx_fixup,
1613 .tx_fixup = smsc95xx_tx_fixup,
1614 .status = smsc95xx_status,
Paolo Pisati07d69d42012-04-23 04:05:20 +00001615 .flags = FLAG_ETHER | FLAG_SEND_ZLP | FLAG_LINK_INTR,
Steve Glendinning2f7ca802008-10-02 05:27:57 +00001616};
1617
1618static const struct usb_device_id products[] = {
1619 {
1620 /* SMSC9500 USB Ethernet Device */
1621 USB_DEVICE(0x0424, 0x9500),
1622 .driver_info = (unsigned long) &smsc95xx_info,
1623 },
Steve Glendinning726474b2009-05-01 06:07:22 +00001624 {
Steve Glendinning6f41d122009-09-22 05:13:02 +00001625 /* SMSC9505 USB Ethernet Device */
1626 USB_DEVICE(0x0424, 0x9505),
1627 .driver_info = (unsigned long) &smsc95xx_info,
1628 },
1629 {
1630 /* SMSC9500A USB Ethernet Device */
1631 USB_DEVICE(0x0424, 0x9E00),
1632 .driver_info = (unsigned long) &smsc95xx_info,
1633 },
1634 {
1635 /* SMSC9505A USB Ethernet Device */
1636 USB_DEVICE(0x0424, 0x9E01),
1637 .driver_info = (unsigned long) &smsc95xx_info,
1638 },
1639 {
Steve Glendinning726474b2009-05-01 06:07:22 +00001640 /* SMSC9512/9514 USB Hub & Ethernet Device */
1641 USB_DEVICE(0x0424, 0xec00),
1642 .driver_info = (unsigned long) &smsc95xx_info,
1643 },
Steve Glendinning6f41d122009-09-22 05:13:02 +00001644 {
1645 /* SMSC9500 USB Ethernet Device (SAL10) */
1646 USB_DEVICE(0x0424, 0x9900),
1647 .driver_info = (unsigned long) &smsc95xx_info,
1648 },
1649 {
1650 /* SMSC9505 USB Ethernet Device (SAL10) */
1651 USB_DEVICE(0x0424, 0x9901),
1652 .driver_info = (unsigned long) &smsc95xx_info,
1653 },
1654 {
1655 /* SMSC9500A USB Ethernet Device (SAL10) */
1656 USB_DEVICE(0x0424, 0x9902),
1657 .driver_info = (unsigned long) &smsc95xx_info,
1658 },
1659 {
1660 /* SMSC9505A USB Ethernet Device (SAL10) */
1661 USB_DEVICE(0x0424, 0x9903),
1662 .driver_info = (unsigned long) &smsc95xx_info,
1663 },
1664 {
1665 /* SMSC9512/9514 USB Hub & Ethernet Device (SAL10) */
1666 USB_DEVICE(0x0424, 0x9904),
1667 .driver_info = (unsigned long) &smsc95xx_info,
1668 },
1669 {
1670 /* SMSC9500A USB Ethernet Device (HAL) */
1671 USB_DEVICE(0x0424, 0x9905),
1672 .driver_info = (unsigned long) &smsc95xx_info,
1673 },
1674 {
1675 /* SMSC9505A USB Ethernet Device (HAL) */
1676 USB_DEVICE(0x0424, 0x9906),
1677 .driver_info = (unsigned long) &smsc95xx_info,
1678 },
1679 {
1680 /* SMSC9500 USB Ethernet Device (Alternate ID) */
1681 USB_DEVICE(0x0424, 0x9907),
1682 .driver_info = (unsigned long) &smsc95xx_info,
1683 },
1684 {
1685 /* SMSC9500A USB Ethernet Device (Alternate ID) */
1686 USB_DEVICE(0x0424, 0x9908),
1687 .driver_info = (unsigned long) &smsc95xx_info,
1688 },
1689 {
1690 /* SMSC9512/9514 USB Hub & Ethernet Device (Alternate ID) */
1691 USB_DEVICE(0x0424, 0x9909),
1692 .driver_info = (unsigned long) &smsc95xx_info,
1693 },
Steve Glendinning88edaa42011-04-10 18:59:27 -07001694 {
1695 /* SMSC LAN9530 USB Ethernet Device */
1696 USB_DEVICE(0x0424, 0x9530),
1697 .driver_info = (unsigned long) &smsc95xx_info,
1698 },
1699 {
1700 /* SMSC LAN9730 USB Ethernet Device */
1701 USB_DEVICE(0x0424, 0x9730),
1702 .driver_info = (unsigned long) &smsc95xx_info,
1703 },
1704 {
1705 /* SMSC LAN89530 USB Ethernet Device */
1706 USB_DEVICE(0x0424, 0x9E08),
1707 .driver_info = (unsigned long) &smsc95xx_info,
1708 },
Steve Glendinning2f7ca802008-10-02 05:27:57 +00001709 { }, /* END */
1710};
1711MODULE_DEVICE_TABLE(usb, products);
1712
1713static struct usb_driver smsc95xx_driver = {
1714 .name = "smsc95xx",
1715 .id_table = products,
1716 .probe = usbnet_probe,
Steve Glendinningb5a04472012-09-28 00:07:11 +00001717 .suspend = smsc95xx_suspend,
Steve Glendinninge0e474a2012-09-28 00:07:12 +00001718 .resume = smsc95xx_resume,
1719 .reset_resume = smsc95xx_resume,
Steve Glendinning2f7ca802008-10-02 05:27:57 +00001720 .disconnect = usbnet_disconnect,
Sarah Sharpe1f12eb2012-04-23 10:08:51 -07001721 .disable_hub_initiated_lpm = 1,
Steve Glendinning2f7ca802008-10-02 05:27:57 +00001722};
1723
Greg Kroah-Hartmand632eb12011-11-18 09:44:20 -08001724module_usb_driver(smsc95xx_driver);
Steve Glendinning2f7ca802008-10-02 05:27:57 +00001725
1726MODULE_AUTHOR("Nancy Lin");
Steve Glendinning90b24cf2012-04-16 12:13:29 +01001727MODULE_AUTHOR("Steve Glendinning <steve.glendinning@shawell.net>");
Steve Glendinning2f7ca802008-10-02 05:27:57 +00001728MODULE_DESCRIPTION("SMSC95XX USB 2.0 Ethernet Devices");
1729MODULE_LICENSE("GPL");