1*2f7ca802SSteve Glendinning /*************************************************************************** 2*2f7ca802SSteve Glendinning * 3*2f7ca802SSteve Glendinning * Copyright (C) 2007-2008 SMSC 4*2f7ca802SSteve Glendinning * 5*2f7ca802SSteve Glendinning * This program is free software; you can redistribute it and/or 6*2f7ca802SSteve Glendinning * modify it under the terms of the GNU General Public License 7*2f7ca802SSteve Glendinning * as published by the Free Software Foundation; either version 2 8*2f7ca802SSteve Glendinning * of the License, or (at your option) any later version. 9*2f7ca802SSteve Glendinning * 10*2f7ca802SSteve Glendinning * This program is distributed in the hope that it will be useful, 11*2f7ca802SSteve Glendinning * but WITHOUT ANY WARRANTY; without even the implied warranty of 12*2f7ca802SSteve Glendinning * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13*2f7ca802SSteve Glendinning * GNU General Public License for more details. 14*2f7ca802SSteve Glendinning * 15*2f7ca802SSteve Glendinning * You should have received a copy of the GNU General Public License 16*2f7ca802SSteve Glendinning * along with this program; if not, write to the Free Software 17*2f7ca802SSteve Glendinning * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18*2f7ca802SSteve Glendinning * 19*2f7ca802SSteve Glendinning *****************************************************************************/ 20*2f7ca802SSteve Glendinning 21*2f7ca802SSteve Glendinning #include <linux/module.h> 22*2f7ca802SSteve Glendinning #include <linux/kmod.h> 23*2f7ca802SSteve Glendinning #include <linux/init.h> 24*2f7ca802SSteve Glendinning #include <linux/netdevice.h> 25*2f7ca802SSteve Glendinning #include <linux/etherdevice.h> 26*2f7ca802SSteve Glendinning #include <linux/ethtool.h> 27*2f7ca802SSteve Glendinning #include <linux/mii.h> 28*2f7ca802SSteve Glendinning #include <linux/usb.h> 29*2f7ca802SSteve Glendinning #include <linux/crc32.h> 30*2f7ca802SSteve Glendinning #include <linux/usb/usbnet.h> 31*2f7ca802SSteve Glendinning #include "smsc95xx.h" 32*2f7ca802SSteve Glendinning 33*2f7ca802SSteve Glendinning #define SMSC_CHIPNAME "smsc95xx" 34*2f7ca802SSteve Glendinning #define SMSC_DRIVER_VERSION "1.0.3" 35*2f7ca802SSteve Glendinning #define HS_USB_PKT_SIZE (512) 36*2f7ca802SSteve Glendinning #define FS_USB_PKT_SIZE (64) 37*2f7ca802SSteve Glendinning #define DEFAULT_HS_BURST_CAP_SIZE (16 * 1024 + 5 * HS_USB_PKT_SIZE) 38*2f7ca802SSteve Glendinning #define DEFAULT_FS_BURST_CAP_SIZE (6 * 1024 + 33 * FS_USB_PKT_SIZE) 39*2f7ca802SSteve Glendinning #define DEFAULT_BULK_IN_DELAY (0x00002000) 40*2f7ca802SSteve Glendinning #define MAX_SINGLE_PACKET_SIZE (2048) 41*2f7ca802SSteve Glendinning #define LAN95XX_EEPROM_MAGIC (0x9500) 42*2f7ca802SSteve Glendinning #define EEPROM_MAC_OFFSET (0x01) 43*2f7ca802SSteve Glendinning #define DEFAULT_RX_CSUM_ENABLE (true) 44*2f7ca802SSteve Glendinning #define SMSC95XX_INTERNAL_PHY_ID (1) 45*2f7ca802SSteve Glendinning #define SMSC95XX_TX_OVERHEAD (8) 46*2f7ca802SSteve Glendinning #define FLOW_CTRL_TX (1) 47*2f7ca802SSteve Glendinning #define FLOW_CTRL_RX (2) 48*2f7ca802SSteve Glendinning 49*2f7ca802SSteve Glendinning struct smsc95xx_priv { 50*2f7ca802SSteve Glendinning u32 mac_cr; 51*2f7ca802SSteve Glendinning spinlock_t mac_cr_lock; 52*2f7ca802SSteve Glendinning bool use_rx_csum; 53*2f7ca802SSteve Glendinning }; 54*2f7ca802SSteve Glendinning 55*2f7ca802SSteve Glendinning struct usb_context { 56*2f7ca802SSteve Glendinning struct usb_ctrlrequest req; 57*2f7ca802SSteve Glendinning struct completion notify; 58*2f7ca802SSteve Glendinning struct usbnet *dev; 59*2f7ca802SSteve Glendinning }; 60*2f7ca802SSteve Glendinning 61*2f7ca802SSteve Glendinning int turbo_mode = true; 62*2f7ca802SSteve Glendinning module_param(turbo_mode, bool, 0644); 63*2f7ca802SSteve Glendinning MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction"); 64*2f7ca802SSteve Glendinning 65*2f7ca802SSteve Glendinning static int smsc95xx_read_reg(struct usbnet *dev, u32 index, u32 *data) 66*2f7ca802SSteve Glendinning { 67*2f7ca802SSteve Glendinning u32 *buf = kmalloc(4, GFP_KERNEL); 68*2f7ca802SSteve Glendinning int ret; 69*2f7ca802SSteve Glendinning 70*2f7ca802SSteve Glendinning BUG_ON(!dev); 71*2f7ca802SSteve Glendinning 72*2f7ca802SSteve Glendinning if (!buf) 73*2f7ca802SSteve Glendinning return -ENOMEM; 74*2f7ca802SSteve Glendinning 75*2f7ca802SSteve Glendinning ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), 76*2f7ca802SSteve Glendinning USB_VENDOR_REQUEST_READ_REGISTER, 77*2f7ca802SSteve Glendinning USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 78*2f7ca802SSteve Glendinning 00, index, buf, 4, USB_CTRL_GET_TIMEOUT); 79*2f7ca802SSteve Glendinning 80*2f7ca802SSteve Glendinning if (unlikely(ret < 0)) 81*2f7ca802SSteve Glendinning devwarn(dev, "Failed to read register index 0x%08x", index); 82*2f7ca802SSteve Glendinning 83*2f7ca802SSteve Glendinning le32_to_cpus(buf); 84*2f7ca802SSteve Glendinning *data = *buf; 85*2f7ca802SSteve Glendinning kfree(buf); 86*2f7ca802SSteve Glendinning 87*2f7ca802SSteve Glendinning return ret; 88*2f7ca802SSteve Glendinning } 89*2f7ca802SSteve Glendinning 90*2f7ca802SSteve Glendinning static int smsc95xx_write_reg(struct usbnet *dev, u32 index, u32 data) 91*2f7ca802SSteve Glendinning { 92*2f7ca802SSteve Glendinning u32 *buf = kmalloc(4, GFP_KERNEL); 93*2f7ca802SSteve Glendinning int ret; 94*2f7ca802SSteve Glendinning 95*2f7ca802SSteve Glendinning BUG_ON(!dev); 96*2f7ca802SSteve Glendinning 97*2f7ca802SSteve Glendinning if (!buf) 98*2f7ca802SSteve Glendinning return -ENOMEM; 99*2f7ca802SSteve Glendinning 100*2f7ca802SSteve Glendinning *buf = data; 101*2f7ca802SSteve Glendinning cpu_to_le32s(buf); 102*2f7ca802SSteve Glendinning 103*2f7ca802SSteve Glendinning ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), 104*2f7ca802SSteve Glendinning USB_VENDOR_REQUEST_WRITE_REGISTER, 105*2f7ca802SSteve Glendinning USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 106*2f7ca802SSteve Glendinning 00, index, buf, 4, USB_CTRL_SET_TIMEOUT); 107*2f7ca802SSteve Glendinning 108*2f7ca802SSteve Glendinning if (unlikely(ret < 0)) 109*2f7ca802SSteve Glendinning devwarn(dev, "Failed to write register index 0x%08x", index); 110*2f7ca802SSteve Glendinning 111*2f7ca802SSteve Glendinning kfree(buf); 112*2f7ca802SSteve Glendinning 113*2f7ca802SSteve Glendinning return ret; 114*2f7ca802SSteve Glendinning } 115*2f7ca802SSteve Glendinning 116*2f7ca802SSteve Glendinning /* Loop until the read is completed with timeout 117*2f7ca802SSteve Glendinning * called with phy_mutex held */ 118*2f7ca802SSteve Glendinning static int smsc95xx_phy_wait_not_busy(struct usbnet *dev) 119*2f7ca802SSteve Glendinning { 120*2f7ca802SSteve Glendinning unsigned long start_time = jiffies; 121*2f7ca802SSteve Glendinning u32 val; 122*2f7ca802SSteve Glendinning 123*2f7ca802SSteve Glendinning do { 124*2f7ca802SSteve Glendinning smsc95xx_read_reg(dev, MII_ADDR, &val); 125*2f7ca802SSteve Glendinning if (!(val & MII_BUSY_)) 126*2f7ca802SSteve Glendinning return 0; 127*2f7ca802SSteve Glendinning } while (!time_after(jiffies, start_time + HZ)); 128*2f7ca802SSteve Glendinning 129*2f7ca802SSteve Glendinning return -EIO; 130*2f7ca802SSteve Glendinning } 131*2f7ca802SSteve Glendinning 132*2f7ca802SSteve Glendinning static int smsc95xx_mdio_read(struct net_device *netdev, int phy_id, int idx) 133*2f7ca802SSteve Glendinning { 134*2f7ca802SSteve Glendinning struct usbnet *dev = netdev_priv(netdev); 135*2f7ca802SSteve Glendinning u32 val, addr; 136*2f7ca802SSteve Glendinning 137*2f7ca802SSteve Glendinning mutex_lock(&dev->phy_mutex); 138*2f7ca802SSteve Glendinning 139*2f7ca802SSteve Glendinning /* confirm MII not busy */ 140*2f7ca802SSteve Glendinning if (smsc95xx_phy_wait_not_busy(dev)) { 141*2f7ca802SSteve Glendinning devwarn(dev, "MII is busy in smsc95xx_mdio_read"); 142*2f7ca802SSteve Glendinning mutex_unlock(&dev->phy_mutex); 143*2f7ca802SSteve Glendinning return -EIO; 144*2f7ca802SSteve Glendinning } 145*2f7ca802SSteve Glendinning 146*2f7ca802SSteve Glendinning /* set the address, index & direction (read from PHY) */ 147*2f7ca802SSteve Glendinning phy_id &= dev->mii.phy_id_mask; 148*2f7ca802SSteve Glendinning idx &= dev->mii.reg_num_mask; 149*2f7ca802SSteve Glendinning addr = (phy_id << 11) | (idx << 6) | MII_READ_; 150*2f7ca802SSteve Glendinning smsc95xx_write_reg(dev, MII_ADDR, addr); 151*2f7ca802SSteve Glendinning 152*2f7ca802SSteve Glendinning if (smsc95xx_phy_wait_not_busy(dev)) { 153*2f7ca802SSteve Glendinning devwarn(dev, "Timed out reading MII reg %02X", idx); 154*2f7ca802SSteve Glendinning mutex_unlock(&dev->phy_mutex); 155*2f7ca802SSteve Glendinning return -EIO; 156*2f7ca802SSteve Glendinning } 157*2f7ca802SSteve Glendinning 158*2f7ca802SSteve Glendinning smsc95xx_read_reg(dev, MII_DATA, &val); 159*2f7ca802SSteve Glendinning 160*2f7ca802SSteve Glendinning mutex_unlock(&dev->phy_mutex); 161*2f7ca802SSteve Glendinning 162*2f7ca802SSteve Glendinning return (u16)(val & 0xFFFF); 163*2f7ca802SSteve Glendinning } 164*2f7ca802SSteve Glendinning 165*2f7ca802SSteve Glendinning static void smsc95xx_mdio_write(struct net_device *netdev, int phy_id, int idx, 166*2f7ca802SSteve Glendinning int regval) 167*2f7ca802SSteve Glendinning { 168*2f7ca802SSteve Glendinning struct usbnet *dev = netdev_priv(netdev); 169*2f7ca802SSteve Glendinning u32 val, addr; 170*2f7ca802SSteve Glendinning 171*2f7ca802SSteve Glendinning mutex_lock(&dev->phy_mutex); 172*2f7ca802SSteve Glendinning 173*2f7ca802SSteve Glendinning /* confirm MII not busy */ 174*2f7ca802SSteve Glendinning if (smsc95xx_phy_wait_not_busy(dev)) { 175*2f7ca802SSteve Glendinning devwarn(dev, "MII is busy in smsc95xx_mdio_write"); 176*2f7ca802SSteve Glendinning mutex_unlock(&dev->phy_mutex); 177*2f7ca802SSteve Glendinning return; 178*2f7ca802SSteve Glendinning } 179*2f7ca802SSteve Glendinning 180*2f7ca802SSteve Glendinning val = regval; 181*2f7ca802SSteve Glendinning smsc95xx_write_reg(dev, MII_DATA, val); 182*2f7ca802SSteve Glendinning 183*2f7ca802SSteve Glendinning /* set the address, index & direction (write to PHY) */ 184*2f7ca802SSteve Glendinning phy_id &= dev->mii.phy_id_mask; 185*2f7ca802SSteve Glendinning idx &= dev->mii.reg_num_mask; 186*2f7ca802SSteve Glendinning addr = (phy_id << 11) | (idx << 6) | MII_WRITE_; 187*2f7ca802SSteve Glendinning smsc95xx_write_reg(dev, MII_ADDR, addr); 188*2f7ca802SSteve Glendinning 189*2f7ca802SSteve Glendinning if (smsc95xx_phy_wait_not_busy(dev)) 190*2f7ca802SSteve Glendinning devwarn(dev, "Timed out writing MII reg %02X", idx); 191*2f7ca802SSteve Glendinning 192*2f7ca802SSteve Glendinning mutex_unlock(&dev->phy_mutex); 193*2f7ca802SSteve Glendinning } 194*2f7ca802SSteve Glendinning 195*2f7ca802SSteve Glendinning static int smsc95xx_wait_eeprom(struct usbnet *dev) 196*2f7ca802SSteve Glendinning { 197*2f7ca802SSteve Glendinning unsigned long start_time = jiffies; 198*2f7ca802SSteve Glendinning u32 val; 199*2f7ca802SSteve Glendinning 200*2f7ca802SSteve Glendinning do { 201*2f7ca802SSteve Glendinning smsc95xx_read_reg(dev, E2P_CMD, &val); 202*2f7ca802SSteve Glendinning if (!(val & E2P_CMD_BUSY_) || (val & E2P_CMD_TIMEOUT_)) 203*2f7ca802SSteve Glendinning break; 204*2f7ca802SSteve Glendinning udelay(40); 205*2f7ca802SSteve Glendinning } while (!time_after(jiffies, start_time + HZ)); 206*2f7ca802SSteve Glendinning 207*2f7ca802SSteve Glendinning if (val & (E2P_CMD_TIMEOUT_ | E2P_CMD_BUSY_)) { 208*2f7ca802SSteve Glendinning devwarn(dev, "EEPROM read operation timeout"); 209*2f7ca802SSteve Glendinning return -EIO; 210*2f7ca802SSteve Glendinning } 211*2f7ca802SSteve Glendinning 212*2f7ca802SSteve Glendinning return 0; 213*2f7ca802SSteve Glendinning } 214*2f7ca802SSteve Glendinning 215*2f7ca802SSteve Glendinning static int smsc95xx_eeprom_confirm_not_busy(struct usbnet *dev) 216*2f7ca802SSteve Glendinning { 217*2f7ca802SSteve Glendinning unsigned long start_time = jiffies; 218*2f7ca802SSteve Glendinning u32 val; 219*2f7ca802SSteve Glendinning 220*2f7ca802SSteve Glendinning do { 221*2f7ca802SSteve Glendinning smsc95xx_read_reg(dev, E2P_CMD, &val); 222*2f7ca802SSteve Glendinning 223*2f7ca802SSteve Glendinning if (!(val & E2P_CMD_LOADED_)) { 224*2f7ca802SSteve Glendinning devwarn(dev, "No EEPROM present"); 225*2f7ca802SSteve Glendinning return -EIO; 226*2f7ca802SSteve Glendinning } 227*2f7ca802SSteve Glendinning 228*2f7ca802SSteve Glendinning if (!(val & E2P_CMD_BUSY_)) 229*2f7ca802SSteve Glendinning return 0; 230*2f7ca802SSteve Glendinning 231*2f7ca802SSteve Glendinning udelay(40); 232*2f7ca802SSteve Glendinning } while (!time_after(jiffies, start_time + HZ)); 233*2f7ca802SSteve Glendinning 234*2f7ca802SSteve Glendinning devwarn(dev, "EEPROM is busy"); 235*2f7ca802SSteve Glendinning return -EIO; 236*2f7ca802SSteve Glendinning } 237*2f7ca802SSteve Glendinning 238*2f7ca802SSteve Glendinning static int smsc95xx_read_eeprom(struct usbnet *dev, u32 offset, u32 length, 239*2f7ca802SSteve Glendinning u8 *data) 240*2f7ca802SSteve Glendinning { 241*2f7ca802SSteve Glendinning u32 val; 242*2f7ca802SSteve Glendinning int i, ret; 243*2f7ca802SSteve Glendinning 244*2f7ca802SSteve Glendinning BUG_ON(!dev); 245*2f7ca802SSteve Glendinning BUG_ON(!data); 246*2f7ca802SSteve Glendinning 247*2f7ca802SSteve Glendinning ret = smsc95xx_eeprom_confirm_not_busy(dev); 248*2f7ca802SSteve Glendinning if (ret) 249*2f7ca802SSteve Glendinning return ret; 250*2f7ca802SSteve Glendinning 251*2f7ca802SSteve Glendinning for (i = 0; i < length; i++) { 252*2f7ca802SSteve Glendinning val = E2P_CMD_BUSY_ | E2P_CMD_READ_ | (offset & E2P_CMD_ADDR_); 253*2f7ca802SSteve Glendinning smsc95xx_write_reg(dev, E2P_CMD, val); 254*2f7ca802SSteve Glendinning 255*2f7ca802SSteve Glendinning ret = smsc95xx_wait_eeprom(dev); 256*2f7ca802SSteve Glendinning if (ret < 0) 257*2f7ca802SSteve Glendinning return ret; 258*2f7ca802SSteve Glendinning 259*2f7ca802SSteve Glendinning smsc95xx_read_reg(dev, E2P_DATA, &val); 260*2f7ca802SSteve Glendinning 261*2f7ca802SSteve Glendinning data[i] = val & 0xFF; 262*2f7ca802SSteve Glendinning offset++; 263*2f7ca802SSteve Glendinning } 264*2f7ca802SSteve Glendinning 265*2f7ca802SSteve Glendinning return 0; 266*2f7ca802SSteve Glendinning } 267*2f7ca802SSteve Glendinning 268*2f7ca802SSteve Glendinning static int smsc95xx_write_eeprom(struct usbnet *dev, u32 offset, u32 length, 269*2f7ca802SSteve Glendinning u8 *data) 270*2f7ca802SSteve Glendinning { 271*2f7ca802SSteve Glendinning u32 val; 272*2f7ca802SSteve Glendinning int i, ret; 273*2f7ca802SSteve Glendinning 274*2f7ca802SSteve Glendinning BUG_ON(!dev); 275*2f7ca802SSteve Glendinning BUG_ON(!data); 276*2f7ca802SSteve Glendinning 277*2f7ca802SSteve Glendinning ret = smsc95xx_eeprom_confirm_not_busy(dev); 278*2f7ca802SSteve Glendinning if (ret) 279*2f7ca802SSteve Glendinning return ret; 280*2f7ca802SSteve Glendinning 281*2f7ca802SSteve Glendinning /* Issue write/erase enable command */ 282*2f7ca802SSteve Glendinning val = E2P_CMD_BUSY_ | E2P_CMD_EWEN_; 283*2f7ca802SSteve Glendinning smsc95xx_write_reg(dev, E2P_CMD, val); 284*2f7ca802SSteve Glendinning 285*2f7ca802SSteve Glendinning ret = smsc95xx_wait_eeprom(dev); 286*2f7ca802SSteve Glendinning if (ret < 0) 287*2f7ca802SSteve Glendinning return ret; 288*2f7ca802SSteve Glendinning 289*2f7ca802SSteve Glendinning for (i = 0; i < length; i++) { 290*2f7ca802SSteve Glendinning 291*2f7ca802SSteve Glendinning /* Fill data register */ 292*2f7ca802SSteve Glendinning val = data[i]; 293*2f7ca802SSteve Glendinning smsc95xx_write_reg(dev, E2P_DATA, val); 294*2f7ca802SSteve Glendinning 295*2f7ca802SSteve Glendinning /* Send "write" command */ 296*2f7ca802SSteve Glendinning val = E2P_CMD_BUSY_ | E2P_CMD_WRITE_ | (offset & E2P_CMD_ADDR_); 297*2f7ca802SSteve Glendinning smsc95xx_write_reg(dev, E2P_CMD, val); 298*2f7ca802SSteve Glendinning 299*2f7ca802SSteve Glendinning ret = smsc95xx_wait_eeprom(dev); 300*2f7ca802SSteve Glendinning if (ret < 0) 301*2f7ca802SSteve Glendinning return ret; 302*2f7ca802SSteve Glendinning 303*2f7ca802SSteve Glendinning offset++; 304*2f7ca802SSteve Glendinning } 305*2f7ca802SSteve Glendinning 306*2f7ca802SSteve Glendinning return 0; 307*2f7ca802SSteve Glendinning } 308*2f7ca802SSteve Glendinning 309*2f7ca802SSteve Glendinning static void smsc95xx_async_cmd_callback(struct urb *urb, struct pt_regs *regs) 310*2f7ca802SSteve Glendinning { 311*2f7ca802SSteve Glendinning struct usb_context *usb_context = urb->context; 312*2f7ca802SSteve Glendinning struct usbnet *dev = usb_context->dev; 313*2f7ca802SSteve Glendinning 314*2f7ca802SSteve Glendinning if (urb->status < 0) 315*2f7ca802SSteve Glendinning devwarn(dev, "async callback failed with %d", urb->status); 316*2f7ca802SSteve Glendinning 317*2f7ca802SSteve Glendinning complete(&usb_context->notify); 318*2f7ca802SSteve Glendinning 319*2f7ca802SSteve Glendinning kfree(usb_context); 320*2f7ca802SSteve Glendinning usb_free_urb(urb); 321*2f7ca802SSteve Glendinning } 322*2f7ca802SSteve Glendinning 323*2f7ca802SSteve Glendinning static int smsc95xx_write_reg_async(struct usbnet *dev, u32 index, u32 *data) 324*2f7ca802SSteve Glendinning { 325*2f7ca802SSteve Glendinning struct usb_context *usb_context; 326*2f7ca802SSteve Glendinning int status; 327*2f7ca802SSteve Glendinning struct urb *urb; 328*2f7ca802SSteve Glendinning const u32 size = 4; 329*2f7ca802SSteve Glendinning 330*2f7ca802SSteve Glendinning urb = usb_alloc_urb(0, GFP_ATOMIC); 331*2f7ca802SSteve Glendinning if (!urb) { 332*2f7ca802SSteve Glendinning devwarn(dev, "Error allocating URB"); 333*2f7ca802SSteve Glendinning return -ENOMEM; 334*2f7ca802SSteve Glendinning } 335*2f7ca802SSteve Glendinning 336*2f7ca802SSteve Glendinning usb_context = kmalloc(sizeof(struct usb_context), GFP_ATOMIC); 337*2f7ca802SSteve Glendinning if (usb_context == NULL) { 338*2f7ca802SSteve Glendinning devwarn(dev, "Error allocating control msg"); 339*2f7ca802SSteve Glendinning usb_free_urb(urb); 340*2f7ca802SSteve Glendinning return -ENOMEM; 341*2f7ca802SSteve Glendinning } 342*2f7ca802SSteve Glendinning 343*2f7ca802SSteve Glendinning usb_context->req.bRequestType = 344*2f7ca802SSteve Glendinning USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE; 345*2f7ca802SSteve Glendinning usb_context->req.bRequest = USB_VENDOR_REQUEST_WRITE_REGISTER; 346*2f7ca802SSteve Glendinning usb_context->req.wValue = 00; 347*2f7ca802SSteve Glendinning usb_context->req.wIndex = cpu_to_le32(index); 348*2f7ca802SSteve Glendinning usb_context->req.wLength = cpu_to_le32(size); 349*2f7ca802SSteve Glendinning init_completion(&usb_context->notify); 350*2f7ca802SSteve Glendinning 351*2f7ca802SSteve Glendinning usb_fill_control_urb(urb, dev->udev, usb_sndctrlpipe(dev->udev, 0), 352*2f7ca802SSteve Glendinning (void *)&usb_context->req, data, size, 353*2f7ca802SSteve Glendinning (usb_complete_t)smsc95xx_async_cmd_callback, 354*2f7ca802SSteve Glendinning (void *)usb_context); 355*2f7ca802SSteve Glendinning 356*2f7ca802SSteve Glendinning status = usb_submit_urb(urb, GFP_ATOMIC); 357*2f7ca802SSteve Glendinning if (status < 0) { 358*2f7ca802SSteve Glendinning devwarn(dev, "Error submitting control msg, sts=%d", status); 359*2f7ca802SSteve Glendinning kfree(usb_context); 360*2f7ca802SSteve Glendinning usb_free_urb(urb); 361*2f7ca802SSteve Glendinning } 362*2f7ca802SSteve Glendinning 363*2f7ca802SSteve Glendinning return status; 364*2f7ca802SSteve Glendinning } 365*2f7ca802SSteve Glendinning 366*2f7ca802SSteve Glendinning /* returns hash bit number for given MAC address 367*2f7ca802SSteve Glendinning * example: 368*2f7ca802SSteve Glendinning * 01 00 5E 00 00 01 -> returns bit number 31 */ 369*2f7ca802SSteve Glendinning static unsigned int smsc95xx_hash(char addr[ETH_ALEN]) 370*2f7ca802SSteve Glendinning { 371*2f7ca802SSteve Glendinning return (ether_crc(ETH_ALEN, addr) >> 26) & 0x3f; 372*2f7ca802SSteve Glendinning } 373*2f7ca802SSteve Glendinning 374*2f7ca802SSteve Glendinning static void smsc95xx_set_multicast(struct net_device *netdev) 375*2f7ca802SSteve Glendinning { 376*2f7ca802SSteve Glendinning struct usbnet *dev = netdev_priv(netdev); 377*2f7ca802SSteve Glendinning struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); 378*2f7ca802SSteve Glendinning u32 hash_hi = 0; 379*2f7ca802SSteve Glendinning u32 hash_lo = 0; 380*2f7ca802SSteve Glendinning unsigned long flags; 381*2f7ca802SSteve Glendinning 382*2f7ca802SSteve Glendinning spin_lock_irqsave(&pdata->mac_cr_lock, flags); 383*2f7ca802SSteve Glendinning 384*2f7ca802SSteve Glendinning if (dev->net->flags & IFF_PROMISC) { 385*2f7ca802SSteve Glendinning if (netif_msg_drv(dev)) 386*2f7ca802SSteve Glendinning devdbg(dev, "promiscuous mode enabled"); 387*2f7ca802SSteve Glendinning pdata->mac_cr |= MAC_CR_PRMS_; 388*2f7ca802SSteve Glendinning pdata->mac_cr &= ~(MAC_CR_MCPAS_ | MAC_CR_HPFILT_); 389*2f7ca802SSteve Glendinning } else if (dev->net->flags & IFF_ALLMULTI) { 390*2f7ca802SSteve Glendinning if (netif_msg_drv(dev)) 391*2f7ca802SSteve Glendinning devdbg(dev, "receive all multicast enabled"); 392*2f7ca802SSteve Glendinning pdata->mac_cr |= MAC_CR_MCPAS_; 393*2f7ca802SSteve Glendinning pdata->mac_cr &= ~(MAC_CR_PRMS_ | MAC_CR_HPFILT_); 394*2f7ca802SSteve Glendinning } else if (dev->net->mc_count > 0) { 395*2f7ca802SSteve Glendinning struct dev_mc_list *mc_list = dev->net->mc_list; 396*2f7ca802SSteve Glendinning int count = 0; 397*2f7ca802SSteve Glendinning 398*2f7ca802SSteve Glendinning pdata->mac_cr |= MAC_CR_HPFILT_; 399*2f7ca802SSteve Glendinning pdata->mac_cr &= ~(MAC_CR_PRMS_ | MAC_CR_MCPAS_); 400*2f7ca802SSteve Glendinning 401*2f7ca802SSteve Glendinning while (mc_list) { 402*2f7ca802SSteve Glendinning count++; 403*2f7ca802SSteve Glendinning if (mc_list->dmi_addrlen == ETH_ALEN) { 404*2f7ca802SSteve Glendinning u32 bitnum = smsc95xx_hash(mc_list->dmi_addr); 405*2f7ca802SSteve Glendinning u32 mask = 0x01 << (bitnum & 0x1F); 406*2f7ca802SSteve Glendinning if (bitnum & 0x20) 407*2f7ca802SSteve Glendinning hash_hi |= mask; 408*2f7ca802SSteve Glendinning else 409*2f7ca802SSteve Glendinning hash_lo |= mask; 410*2f7ca802SSteve Glendinning } else { 411*2f7ca802SSteve Glendinning devwarn(dev, "dmi_addrlen != 6"); 412*2f7ca802SSteve Glendinning } 413*2f7ca802SSteve Glendinning mc_list = mc_list->next; 414*2f7ca802SSteve Glendinning } 415*2f7ca802SSteve Glendinning 416*2f7ca802SSteve Glendinning if (count != ((u32)dev->net->mc_count)) 417*2f7ca802SSteve Glendinning devwarn(dev, "mc_count != dev->mc_count"); 418*2f7ca802SSteve Glendinning 419*2f7ca802SSteve Glendinning if (netif_msg_drv(dev)) 420*2f7ca802SSteve Glendinning devdbg(dev, "HASHH=0x%08X, HASHL=0x%08X", hash_hi, 421*2f7ca802SSteve Glendinning hash_lo); 422*2f7ca802SSteve Glendinning } else { 423*2f7ca802SSteve Glendinning if (netif_msg_drv(dev)) 424*2f7ca802SSteve Glendinning devdbg(dev, "receive own packets only"); 425*2f7ca802SSteve Glendinning pdata->mac_cr &= 426*2f7ca802SSteve Glendinning ~(MAC_CR_PRMS_ | MAC_CR_MCPAS_ | MAC_CR_HPFILT_); 427*2f7ca802SSteve Glendinning } 428*2f7ca802SSteve Glendinning 429*2f7ca802SSteve Glendinning spin_unlock_irqrestore(&pdata->mac_cr_lock, flags); 430*2f7ca802SSteve Glendinning 431*2f7ca802SSteve Glendinning /* Initiate async writes, as we can't wait for completion here */ 432*2f7ca802SSteve Glendinning smsc95xx_write_reg_async(dev, HASHH, &hash_hi); 433*2f7ca802SSteve Glendinning smsc95xx_write_reg_async(dev, HASHL, &hash_lo); 434*2f7ca802SSteve Glendinning smsc95xx_write_reg_async(dev, MAC_CR, &pdata->mac_cr); 435*2f7ca802SSteve Glendinning } 436*2f7ca802SSteve Glendinning 437*2f7ca802SSteve Glendinning static u8 smsc95xx_resolve_flowctrl_fulldplx(u16 lcladv, u16 rmtadv) 438*2f7ca802SSteve Glendinning { 439*2f7ca802SSteve Glendinning u8 cap = 0; 440*2f7ca802SSteve Glendinning 441*2f7ca802SSteve Glendinning if (lcladv & ADVERTISE_PAUSE_CAP) { 442*2f7ca802SSteve Glendinning if (lcladv & ADVERTISE_PAUSE_ASYM) { 443*2f7ca802SSteve Glendinning if (rmtadv & LPA_PAUSE_CAP) 444*2f7ca802SSteve Glendinning cap = FLOW_CTRL_TX | FLOW_CTRL_RX; 445*2f7ca802SSteve Glendinning else if (rmtadv & LPA_PAUSE_ASYM) 446*2f7ca802SSteve Glendinning cap = FLOW_CTRL_RX; 447*2f7ca802SSteve Glendinning } else { 448*2f7ca802SSteve Glendinning if (rmtadv & LPA_PAUSE_CAP) 449*2f7ca802SSteve Glendinning cap = FLOW_CTRL_TX | FLOW_CTRL_RX; 450*2f7ca802SSteve Glendinning } 451*2f7ca802SSteve Glendinning } else if (lcladv & ADVERTISE_PAUSE_ASYM) { 452*2f7ca802SSteve Glendinning if ((rmtadv & LPA_PAUSE_CAP) && (rmtadv & LPA_PAUSE_ASYM)) 453*2f7ca802SSteve Glendinning cap = FLOW_CTRL_TX; 454*2f7ca802SSteve Glendinning } 455*2f7ca802SSteve Glendinning 456*2f7ca802SSteve Glendinning return cap; 457*2f7ca802SSteve Glendinning } 458*2f7ca802SSteve Glendinning 459*2f7ca802SSteve Glendinning static void smsc95xx_phy_update_flowcontrol(struct usbnet *dev, u8 duplex, 460*2f7ca802SSteve Glendinning u16 lcladv, u16 rmtadv) 461*2f7ca802SSteve Glendinning { 462*2f7ca802SSteve Glendinning u32 flow, afc_cfg = 0; 463*2f7ca802SSteve Glendinning 464*2f7ca802SSteve Glendinning int ret = smsc95xx_read_reg(dev, AFC_CFG, &afc_cfg); 465*2f7ca802SSteve Glendinning if (ret < 0) { 466*2f7ca802SSteve Glendinning devwarn(dev, "error reading AFC_CFG"); 467*2f7ca802SSteve Glendinning return; 468*2f7ca802SSteve Glendinning } 469*2f7ca802SSteve Glendinning 470*2f7ca802SSteve Glendinning if (duplex == DUPLEX_FULL) { 471*2f7ca802SSteve Glendinning u8 cap = smsc95xx_resolve_flowctrl_fulldplx(lcladv, rmtadv); 472*2f7ca802SSteve Glendinning 473*2f7ca802SSteve Glendinning if (cap & FLOW_CTRL_RX) 474*2f7ca802SSteve Glendinning flow = 0xFFFF0002; 475*2f7ca802SSteve Glendinning else 476*2f7ca802SSteve Glendinning flow = 0; 477*2f7ca802SSteve Glendinning 478*2f7ca802SSteve Glendinning if (cap & FLOW_CTRL_TX) 479*2f7ca802SSteve Glendinning afc_cfg |= 0xF; 480*2f7ca802SSteve Glendinning else 481*2f7ca802SSteve Glendinning afc_cfg &= ~0xF; 482*2f7ca802SSteve Glendinning 483*2f7ca802SSteve Glendinning if (netif_msg_link(dev)) 484*2f7ca802SSteve Glendinning devdbg(dev, "rx pause %s, tx pause %s", 485*2f7ca802SSteve Glendinning (cap & FLOW_CTRL_RX ? "enabled" : "disabled"), 486*2f7ca802SSteve Glendinning (cap & FLOW_CTRL_TX ? "enabled" : "disabled")); 487*2f7ca802SSteve Glendinning } else { 488*2f7ca802SSteve Glendinning if (netif_msg_link(dev)) 489*2f7ca802SSteve Glendinning devdbg(dev, "half duplex"); 490*2f7ca802SSteve Glendinning flow = 0; 491*2f7ca802SSteve Glendinning afc_cfg |= 0xF; 492*2f7ca802SSteve Glendinning } 493*2f7ca802SSteve Glendinning 494*2f7ca802SSteve Glendinning smsc95xx_write_reg(dev, FLOW, flow); 495*2f7ca802SSteve Glendinning smsc95xx_write_reg(dev, AFC_CFG, afc_cfg); 496*2f7ca802SSteve Glendinning } 497*2f7ca802SSteve Glendinning 498*2f7ca802SSteve Glendinning static int smsc95xx_link_reset(struct usbnet *dev) 499*2f7ca802SSteve Glendinning { 500*2f7ca802SSteve Glendinning struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); 501*2f7ca802SSteve Glendinning struct mii_if_info *mii = &dev->mii; 502*2f7ca802SSteve Glendinning struct ethtool_cmd ecmd; 503*2f7ca802SSteve Glendinning unsigned long flags; 504*2f7ca802SSteve Glendinning u16 lcladv, rmtadv; 505*2f7ca802SSteve Glendinning u32 intdata; 506*2f7ca802SSteve Glendinning 507*2f7ca802SSteve Glendinning /* clear interrupt status */ 508*2f7ca802SSteve Glendinning smsc95xx_mdio_read(dev->net, mii->phy_id, PHY_INT_SRC); 509*2f7ca802SSteve Glendinning intdata = 0xFFFFFFFF; 510*2f7ca802SSteve Glendinning smsc95xx_write_reg(dev, INT_STS, intdata); 511*2f7ca802SSteve Glendinning 512*2f7ca802SSteve Glendinning mii_check_media(mii, 1, 1); 513*2f7ca802SSteve Glendinning mii_ethtool_gset(&dev->mii, &ecmd); 514*2f7ca802SSteve Glendinning lcladv = smsc95xx_mdio_read(dev->net, mii->phy_id, MII_ADVERTISE); 515*2f7ca802SSteve Glendinning rmtadv = smsc95xx_mdio_read(dev->net, mii->phy_id, MII_LPA); 516*2f7ca802SSteve Glendinning 517*2f7ca802SSteve Glendinning if (netif_msg_link(dev)) 518*2f7ca802SSteve Glendinning devdbg(dev, "speed: %d duplex: %d lcladv: %04x rmtadv: %04x", 519*2f7ca802SSteve Glendinning ecmd.speed, ecmd.duplex, lcladv, rmtadv); 520*2f7ca802SSteve Glendinning 521*2f7ca802SSteve Glendinning spin_lock_irqsave(&pdata->mac_cr_lock, flags); 522*2f7ca802SSteve Glendinning if (ecmd.duplex != DUPLEX_FULL) { 523*2f7ca802SSteve Glendinning pdata->mac_cr &= ~MAC_CR_FDPX_; 524*2f7ca802SSteve Glendinning pdata->mac_cr |= MAC_CR_RCVOWN_; 525*2f7ca802SSteve Glendinning } else { 526*2f7ca802SSteve Glendinning pdata->mac_cr &= ~MAC_CR_RCVOWN_; 527*2f7ca802SSteve Glendinning pdata->mac_cr |= MAC_CR_FDPX_; 528*2f7ca802SSteve Glendinning } 529*2f7ca802SSteve Glendinning spin_unlock_irqrestore(&pdata->mac_cr_lock, flags); 530*2f7ca802SSteve Glendinning 531*2f7ca802SSteve Glendinning smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr); 532*2f7ca802SSteve Glendinning 533*2f7ca802SSteve Glendinning smsc95xx_phy_update_flowcontrol(dev, ecmd.duplex, lcladv, rmtadv); 534*2f7ca802SSteve Glendinning 535*2f7ca802SSteve Glendinning return 0; 536*2f7ca802SSteve Glendinning } 537*2f7ca802SSteve Glendinning 538*2f7ca802SSteve Glendinning static void smsc95xx_status(struct usbnet *dev, struct urb *urb) 539*2f7ca802SSteve Glendinning { 540*2f7ca802SSteve Glendinning u32 intdata; 541*2f7ca802SSteve Glendinning 542*2f7ca802SSteve Glendinning if (urb->actual_length != 4) { 543*2f7ca802SSteve Glendinning devwarn(dev, "unexpected urb length %d", urb->actual_length); 544*2f7ca802SSteve Glendinning return; 545*2f7ca802SSteve Glendinning } 546*2f7ca802SSteve Glendinning 547*2f7ca802SSteve Glendinning memcpy(&intdata, urb->transfer_buffer, 4); 548*2f7ca802SSteve Glendinning le32_to_cpus(intdata); 549*2f7ca802SSteve Glendinning 550*2f7ca802SSteve Glendinning if (netif_msg_link(dev)) 551*2f7ca802SSteve Glendinning devdbg(dev, "intdata: 0x%08X", intdata); 552*2f7ca802SSteve Glendinning 553*2f7ca802SSteve Glendinning if (intdata & INT_ENP_PHY_INT_) 554*2f7ca802SSteve Glendinning usbnet_defer_kevent(dev, EVENT_LINK_RESET); 555*2f7ca802SSteve Glendinning else 556*2f7ca802SSteve Glendinning devwarn(dev, "unexpected interrupt, intdata=0x%08X", intdata); 557*2f7ca802SSteve Glendinning } 558*2f7ca802SSteve Glendinning 559*2f7ca802SSteve Glendinning /* Enable or disable Rx checksum offload engine */ 560*2f7ca802SSteve Glendinning static int smsc95xx_set_rx_csum(struct usbnet *dev, bool enable) 561*2f7ca802SSteve Glendinning { 562*2f7ca802SSteve Glendinning u32 read_buf; 563*2f7ca802SSteve Glendinning int ret = smsc95xx_read_reg(dev, COE_CR, &read_buf); 564*2f7ca802SSteve Glendinning if (ret < 0) { 565*2f7ca802SSteve Glendinning devwarn(dev, "Failed to read COE_CR: %d", ret); 566*2f7ca802SSteve Glendinning return ret; 567*2f7ca802SSteve Glendinning } 568*2f7ca802SSteve Glendinning 569*2f7ca802SSteve Glendinning if (enable) 570*2f7ca802SSteve Glendinning read_buf |= Rx_COE_EN_; 571*2f7ca802SSteve Glendinning else 572*2f7ca802SSteve Glendinning read_buf &= ~Rx_COE_EN_; 573*2f7ca802SSteve Glendinning 574*2f7ca802SSteve Glendinning ret = smsc95xx_write_reg(dev, COE_CR, read_buf); 575*2f7ca802SSteve Glendinning if (ret < 0) { 576*2f7ca802SSteve Glendinning devwarn(dev, "Failed to write COE_CR: %d", ret); 577*2f7ca802SSteve Glendinning return ret; 578*2f7ca802SSteve Glendinning } 579*2f7ca802SSteve Glendinning 580*2f7ca802SSteve Glendinning if (netif_msg_hw(dev)) 581*2f7ca802SSteve Glendinning devdbg(dev, "COE_CR = 0x%08x", read_buf); 582*2f7ca802SSteve Glendinning return 0; 583*2f7ca802SSteve Glendinning } 584*2f7ca802SSteve Glendinning 585*2f7ca802SSteve Glendinning static int smsc95xx_ethtool_get_eeprom_len(struct net_device *net) 586*2f7ca802SSteve Glendinning { 587*2f7ca802SSteve Glendinning return MAX_EEPROM_SIZE; 588*2f7ca802SSteve Glendinning } 589*2f7ca802SSteve Glendinning 590*2f7ca802SSteve Glendinning static int smsc95xx_ethtool_get_eeprom(struct net_device *netdev, 591*2f7ca802SSteve Glendinning struct ethtool_eeprom *ee, u8 *data) 592*2f7ca802SSteve Glendinning { 593*2f7ca802SSteve Glendinning struct usbnet *dev = netdev_priv(netdev); 594*2f7ca802SSteve Glendinning 595*2f7ca802SSteve Glendinning ee->magic = LAN95XX_EEPROM_MAGIC; 596*2f7ca802SSteve Glendinning 597*2f7ca802SSteve Glendinning return smsc95xx_read_eeprom(dev, ee->offset, ee->len, data); 598*2f7ca802SSteve Glendinning } 599*2f7ca802SSteve Glendinning 600*2f7ca802SSteve Glendinning static int smsc95xx_ethtool_set_eeprom(struct net_device *netdev, 601*2f7ca802SSteve Glendinning struct ethtool_eeprom *ee, u8 *data) 602*2f7ca802SSteve Glendinning { 603*2f7ca802SSteve Glendinning struct usbnet *dev = netdev_priv(netdev); 604*2f7ca802SSteve Glendinning 605*2f7ca802SSteve Glendinning if (ee->magic != LAN95XX_EEPROM_MAGIC) { 606*2f7ca802SSteve Glendinning devwarn(dev, "EEPROM: magic value mismatch, magic = 0x%x", 607*2f7ca802SSteve Glendinning ee->magic); 608*2f7ca802SSteve Glendinning return -EINVAL; 609*2f7ca802SSteve Glendinning } 610*2f7ca802SSteve Glendinning 611*2f7ca802SSteve Glendinning return smsc95xx_write_eeprom(dev, ee->offset, ee->len, data); 612*2f7ca802SSteve Glendinning } 613*2f7ca802SSteve Glendinning 614*2f7ca802SSteve Glendinning static u32 smsc95xx_ethtool_get_rx_csum(struct net_device *netdev) 615*2f7ca802SSteve Glendinning { 616*2f7ca802SSteve Glendinning struct usbnet *dev = netdev_priv(netdev); 617*2f7ca802SSteve Glendinning struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); 618*2f7ca802SSteve Glendinning 619*2f7ca802SSteve Glendinning return pdata->use_rx_csum; 620*2f7ca802SSteve Glendinning } 621*2f7ca802SSteve Glendinning 622*2f7ca802SSteve Glendinning static int smsc95xx_ethtool_set_rx_csum(struct net_device *netdev, u32 val) 623*2f7ca802SSteve Glendinning { 624*2f7ca802SSteve Glendinning struct usbnet *dev = netdev_priv(netdev); 625*2f7ca802SSteve Glendinning struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); 626*2f7ca802SSteve Glendinning 627*2f7ca802SSteve Glendinning pdata->use_rx_csum = !!val; 628*2f7ca802SSteve Glendinning 629*2f7ca802SSteve Glendinning return smsc95xx_set_rx_csum(dev, pdata->use_rx_csum); 630*2f7ca802SSteve Glendinning } 631*2f7ca802SSteve Glendinning 632*2f7ca802SSteve Glendinning static struct ethtool_ops smsc95xx_ethtool_ops = { 633*2f7ca802SSteve Glendinning .get_link = usbnet_get_link, 634*2f7ca802SSteve Glendinning .nway_reset = usbnet_nway_reset, 635*2f7ca802SSteve Glendinning .get_drvinfo = usbnet_get_drvinfo, 636*2f7ca802SSteve Glendinning .get_msglevel = usbnet_get_msglevel, 637*2f7ca802SSteve Glendinning .set_msglevel = usbnet_set_msglevel, 638*2f7ca802SSteve Glendinning .get_settings = usbnet_get_settings, 639*2f7ca802SSteve Glendinning .set_settings = usbnet_set_settings, 640*2f7ca802SSteve Glendinning .get_eeprom_len = smsc95xx_ethtool_get_eeprom_len, 641*2f7ca802SSteve Glendinning .get_eeprom = smsc95xx_ethtool_get_eeprom, 642*2f7ca802SSteve Glendinning .set_eeprom = smsc95xx_ethtool_set_eeprom, 643*2f7ca802SSteve Glendinning .get_rx_csum = smsc95xx_ethtool_get_rx_csum, 644*2f7ca802SSteve Glendinning .set_rx_csum = smsc95xx_ethtool_set_rx_csum, 645*2f7ca802SSteve Glendinning }; 646*2f7ca802SSteve Glendinning 647*2f7ca802SSteve Glendinning static int smsc95xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) 648*2f7ca802SSteve Glendinning { 649*2f7ca802SSteve Glendinning struct usbnet *dev = netdev_priv(netdev); 650*2f7ca802SSteve Glendinning 651*2f7ca802SSteve Glendinning if (!netif_running(netdev)) 652*2f7ca802SSteve Glendinning return -EINVAL; 653*2f7ca802SSteve Glendinning 654*2f7ca802SSteve Glendinning return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); 655*2f7ca802SSteve Glendinning } 656*2f7ca802SSteve Glendinning 657*2f7ca802SSteve Glendinning static void smsc95xx_init_mac_address(struct usbnet *dev) 658*2f7ca802SSteve Glendinning { 659*2f7ca802SSteve Glendinning /* try reading mac address from EEPROM */ 660*2f7ca802SSteve Glendinning if (smsc95xx_read_eeprom(dev, EEPROM_MAC_OFFSET, ETH_ALEN, 661*2f7ca802SSteve Glendinning dev->net->dev_addr) == 0) { 662*2f7ca802SSteve Glendinning if (is_valid_ether_addr(dev->net->dev_addr)) { 663*2f7ca802SSteve Glendinning /* eeprom values are valid so use them */ 664*2f7ca802SSteve Glendinning if (netif_msg_ifup(dev)) 665*2f7ca802SSteve Glendinning devdbg(dev, "MAC address read from EEPROM"); 666*2f7ca802SSteve Glendinning return; 667*2f7ca802SSteve Glendinning } 668*2f7ca802SSteve Glendinning } 669*2f7ca802SSteve Glendinning 670*2f7ca802SSteve Glendinning /* no eeprom, or eeprom values are invalid. generate random MAC */ 671*2f7ca802SSteve Glendinning random_ether_addr(dev->net->dev_addr); 672*2f7ca802SSteve Glendinning if (netif_msg_ifup(dev)) 673*2f7ca802SSteve Glendinning devdbg(dev, "MAC address set to random_ether_addr"); 674*2f7ca802SSteve Glendinning } 675*2f7ca802SSteve Glendinning 676*2f7ca802SSteve Glendinning static int smsc95xx_set_mac_address(struct usbnet *dev) 677*2f7ca802SSteve Glendinning { 678*2f7ca802SSteve Glendinning u32 addr_lo = dev->net->dev_addr[0] | dev->net->dev_addr[1] << 8 | 679*2f7ca802SSteve Glendinning dev->net->dev_addr[2] << 16 | dev->net->dev_addr[3] << 24; 680*2f7ca802SSteve Glendinning u32 addr_hi = dev->net->dev_addr[4] | dev->net->dev_addr[5] << 8; 681*2f7ca802SSteve Glendinning int ret; 682*2f7ca802SSteve Glendinning 683*2f7ca802SSteve Glendinning ret = smsc95xx_write_reg(dev, ADDRL, addr_lo); 684*2f7ca802SSteve Glendinning if (ret < 0) { 685*2f7ca802SSteve Glendinning devwarn(dev, "Failed to write ADDRL: %d", ret); 686*2f7ca802SSteve Glendinning return ret; 687*2f7ca802SSteve Glendinning } 688*2f7ca802SSteve Glendinning 689*2f7ca802SSteve Glendinning ret = smsc95xx_write_reg(dev, ADDRH, addr_hi); 690*2f7ca802SSteve Glendinning if (ret < 0) { 691*2f7ca802SSteve Glendinning devwarn(dev, "Failed to write ADDRH: %d", ret); 692*2f7ca802SSteve Glendinning return ret; 693*2f7ca802SSteve Glendinning } 694*2f7ca802SSteve Glendinning 695*2f7ca802SSteve Glendinning return 0; 696*2f7ca802SSteve Glendinning } 697*2f7ca802SSteve Glendinning 698*2f7ca802SSteve Glendinning /* starts the TX path */ 699*2f7ca802SSteve Glendinning static void smsc95xx_start_tx_path(struct usbnet *dev) 700*2f7ca802SSteve Glendinning { 701*2f7ca802SSteve Glendinning struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); 702*2f7ca802SSteve Glendinning unsigned long flags; 703*2f7ca802SSteve Glendinning u32 reg_val; 704*2f7ca802SSteve Glendinning 705*2f7ca802SSteve Glendinning /* Enable Tx at MAC */ 706*2f7ca802SSteve Glendinning spin_lock_irqsave(&pdata->mac_cr_lock, flags); 707*2f7ca802SSteve Glendinning pdata->mac_cr |= MAC_CR_TXEN_; 708*2f7ca802SSteve Glendinning spin_unlock_irqrestore(&pdata->mac_cr_lock, flags); 709*2f7ca802SSteve Glendinning 710*2f7ca802SSteve Glendinning smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr); 711*2f7ca802SSteve Glendinning 712*2f7ca802SSteve Glendinning /* Enable Tx at SCSRs */ 713*2f7ca802SSteve Glendinning reg_val = TX_CFG_ON_; 714*2f7ca802SSteve Glendinning smsc95xx_write_reg(dev, TX_CFG, reg_val); 715*2f7ca802SSteve Glendinning } 716*2f7ca802SSteve Glendinning 717*2f7ca802SSteve Glendinning /* Starts the Receive path */ 718*2f7ca802SSteve Glendinning static void smsc95xx_start_rx_path(struct usbnet *dev) 719*2f7ca802SSteve Glendinning { 720*2f7ca802SSteve Glendinning struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); 721*2f7ca802SSteve Glendinning unsigned long flags; 722*2f7ca802SSteve Glendinning 723*2f7ca802SSteve Glendinning spin_lock_irqsave(&pdata->mac_cr_lock, flags); 724*2f7ca802SSteve Glendinning pdata->mac_cr |= MAC_CR_RXEN_; 725*2f7ca802SSteve Glendinning spin_unlock_irqrestore(&pdata->mac_cr_lock, flags); 726*2f7ca802SSteve Glendinning 727*2f7ca802SSteve Glendinning smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr); 728*2f7ca802SSteve Glendinning } 729*2f7ca802SSteve Glendinning 730*2f7ca802SSteve Glendinning static int smsc95xx_phy_initialize(struct usbnet *dev) 731*2f7ca802SSteve Glendinning { 732*2f7ca802SSteve Glendinning /* Initialize MII structure */ 733*2f7ca802SSteve Glendinning dev->mii.dev = dev->net; 734*2f7ca802SSteve Glendinning dev->mii.mdio_read = smsc95xx_mdio_read; 735*2f7ca802SSteve Glendinning dev->mii.mdio_write = smsc95xx_mdio_write; 736*2f7ca802SSteve Glendinning dev->mii.phy_id_mask = 0x1f; 737*2f7ca802SSteve Glendinning dev->mii.reg_num_mask = 0x1f; 738*2f7ca802SSteve Glendinning dev->mii.phy_id = SMSC95XX_INTERNAL_PHY_ID; 739*2f7ca802SSteve Glendinning 740*2f7ca802SSteve Glendinning smsc95xx_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET); 741*2f7ca802SSteve Glendinning smsc95xx_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE, 742*2f7ca802SSteve Glendinning ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP | 743*2f7ca802SSteve Glendinning ADVERTISE_PAUSE_ASYM); 744*2f7ca802SSteve Glendinning 745*2f7ca802SSteve Glendinning /* read to clear */ 746*2f7ca802SSteve Glendinning smsc95xx_mdio_read(dev->net, dev->mii.phy_id, PHY_INT_SRC); 747*2f7ca802SSteve Glendinning 748*2f7ca802SSteve Glendinning smsc95xx_mdio_write(dev->net, dev->mii.phy_id, PHY_INT_MASK, 749*2f7ca802SSteve Glendinning PHY_INT_MASK_DEFAULT_); 750*2f7ca802SSteve Glendinning mii_nway_restart(&dev->mii); 751*2f7ca802SSteve Glendinning 752*2f7ca802SSteve Glendinning if (netif_msg_ifup(dev)) 753*2f7ca802SSteve Glendinning devdbg(dev, "phy initialised succesfully"); 754*2f7ca802SSteve Glendinning return 0; 755*2f7ca802SSteve Glendinning } 756*2f7ca802SSteve Glendinning 757*2f7ca802SSteve Glendinning static int smsc95xx_reset(struct usbnet *dev) 758*2f7ca802SSteve Glendinning { 759*2f7ca802SSteve Glendinning struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); 760*2f7ca802SSteve Glendinning u32 read_buf, write_buf, burst_cap; 761*2f7ca802SSteve Glendinning int ret = 0, timeout; 762*2f7ca802SSteve Glendinning DECLARE_MAC_BUF(mac); 763*2f7ca802SSteve Glendinning 764*2f7ca802SSteve Glendinning if (netif_msg_ifup(dev)) 765*2f7ca802SSteve Glendinning devdbg(dev, "entering smsc95xx_reset"); 766*2f7ca802SSteve Glendinning 767*2f7ca802SSteve Glendinning write_buf = HW_CFG_LRST_; 768*2f7ca802SSteve Glendinning ret = smsc95xx_write_reg(dev, HW_CFG, write_buf); 769*2f7ca802SSteve Glendinning if (ret < 0) { 770*2f7ca802SSteve Glendinning devwarn(dev, "Failed to write HW_CFG_LRST_ bit in HW_CFG " 771*2f7ca802SSteve Glendinning "register, ret = %d", ret); 772*2f7ca802SSteve Glendinning return ret; 773*2f7ca802SSteve Glendinning } 774*2f7ca802SSteve Glendinning 775*2f7ca802SSteve Glendinning timeout = 0; 776*2f7ca802SSteve Glendinning do { 777*2f7ca802SSteve Glendinning ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf); 778*2f7ca802SSteve Glendinning if (ret < 0) { 779*2f7ca802SSteve Glendinning devwarn(dev, "Failed to read HW_CFG: %d", ret); 780*2f7ca802SSteve Glendinning return ret; 781*2f7ca802SSteve Glendinning } 782*2f7ca802SSteve Glendinning msleep(10); 783*2f7ca802SSteve Glendinning timeout++; 784*2f7ca802SSteve Glendinning } while ((read_buf & HW_CFG_LRST_) && (timeout < 100)); 785*2f7ca802SSteve Glendinning 786*2f7ca802SSteve Glendinning if (timeout >= 100) { 787*2f7ca802SSteve Glendinning devwarn(dev, "timeout waiting for completion of Lite Reset"); 788*2f7ca802SSteve Glendinning return ret; 789*2f7ca802SSteve Glendinning } 790*2f7ca802SSteve Glendinning 791*2f7ca802SSteve Glendinning write_buf = PM_CTL_PHY_RST_; 792*2f7ca802SSteve Glendinning ret = smsc95xx_write_reg(dev, PM_CTRL, write_buf); 793*2f7ca802SSteve Glendinning if (ret < 0) { 794*2f7ca802SSteve Glendinning devwarn(dev, "Failed to write PM_CTRL: %d", ret); 795*2f7ca802SSteve Glendinning return ret; 796*2f7ca802SSteve Glendinning } 797*2f7ca802SSteve Glendinning 798*2f7ca802SSteve Glendinning timeout = 0; 799*2f7ca802SSteve Glendinning do { 800*2f7ca802SSteve Glendinning ret = smsc95xx_read_reg(dev, PM_CTRL, &read_buf); 801*2f7ca802SSteve Glendinning if (ret < 0) { 802*2f7ca802SSteve Glendinning devwarn(dev, "Failed to read PM_CTRL: %d", ret); 803*2f7ca802SSteve Glendinning return ret; 804*2f7ca802SSteve Glendinning } 805*2f7ca802SSteve Glendinning msleep(10); 806*2f7ca802SSteve Glendinning timeout++; 807*2f7ca802SSteve Glendinning } while ((read_buf & PM_CTL_PHY_RST_) && (timeout < 100)); 808*2f7ca802SSteve Glendinning 809*2f7ca802SSteve Glendinning if (timeout >= 100) { 810*2f7ca802SSteve Glendinning devwarn(dev, "timeout waiting for PHY Reset"); 811*2f7ca802SSteve Glendinning return ret; 812*2f7ca802SSteve Glendinning } 813*2f7ca802SSteve Glendinning 814*2f7ca802SSteve Glendinning smsc95xx_init_mac_address(dev); 815*2f7ca802SSteve Glendinning 816*2f7ca802SSteve Glendinning ret = smsc95xx_set_mac_address(dev); 817*2f7ca802SSteve Glendinning if (ret < 0) 818*2f7ca802SSteve Glendinning return ret; 819*2f7ca802SSteve Glendinning 820*2f7ca802SSteve Glendinning if (netif_msg_ifup(dev)) 821*2f7ca802SSteve Glendinning devdbg(dev, "MAC Address: %s", 822*2f7ca802SSteve Glendinning print_mac(mac, dev->net->dev_addr)); 823*2f7ca802SSteve Glendinning 824*2f7ca802SSteve Glendinning ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf); 825*2f7ca802SSteve Glendinning if (ret < 0) { 826*2f7ca802SSteve Glendinning devwarn(dev, "Failed to read HW_CFG: %d", ret); 827*2f7ca802SSteve Glendinning return ret; 828*2f7ca802SSteve Glendinning } 829*2f7ca802SSteve Glendinning 830*2f7ca802SSteve Glendinning if (netif_msg_ifup(dev)) 831*2f7ca802SSteve Glendinning devdbg(dev, "Read Value from HW_CFG : 0x%08x", read_buf); 832*2f7ca802SSteve Glendinning 833*2f7ca802SSteve Glendinning read_buf |= HW_CFG_BIR_; 834*2f7ca802SSteve Glendinning 835*2f7ca802SSteve Glendinning ret = smsc95xx_write_reg(dev, HW_CFG, read_buf); 836*2f7ca802SSteve Glendinning if (ret < 0) { 837*2f7ca802SSteve Glendinning devwarn(dev, "Failed to write HW_CFG_BIR_ bit in HW_CFG " 838*2f7ca802SSteve Glendinning "register, ret = %d", ret); 839*2f7ca802SSteve Glendinning return ret; 840*2f7ca802SSteve Glendinning } 841*2f7ca802SSteve Glendinning 842*2f7ca802SSteve Glendinning ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf); 843*2f7ca802SSteve Glendinning if (ret < 0) { 844*2f7ca802SSteve Glendinning devwarn(dev, "Failed to read HW_CFG: %d", ret); 845*2f7ca802SSteve Glendinning return ret; 846*2f7ca802SSteve Glendinning } 847*2f7ca802SSteve Glendinning if (netif_msg_ifup(dev)) 848*2f7ca802SSteve Glendinning devdbg(dev, "Read Value from HW_CFG after writing " 849*2f7ca802SSteve Glendinning "HW_CFG_BIR_: 0x%08x", read_buf); 850*2f7ca802SSteve Glendinning 851*2f7ca802SSteve Glendinning if (!turbo_mode) { 852*2f7ca802SSteve Glendinning burst_cap = 0; 853*2f7ca802SSteve Glendinning dev->rx_urb_size = MAX_SINGLE_PACKET_SIZE; 854*2f7ca802SSteve Glendinning } else if (dev->udev->speed == USB_SPEED_HIGH) { 855*2f7ca802SSteve Glendinning burst_cap = DEFAULT_HS_BURST_CAP_SIZE / HS_USB_PKT_SIZE; 856*2f7ca802SSteve Glendinning dev->rx_urb_size = DEFAULT_HS_BURST_CAP_SIZE; 857*2f7ca802SSteve Glendinning } else { 858*2f7ca802SSteve Glendinning burst_cap = DEFAULT_FS_BURST_CAP_SIZE / FS_USB_PKT_SIZE; 859*2f7ca802SSteve Glendinning dev->rx_urb_size = DEFAULT_FS_BURST_CAP_SIZE; 860*2f7ca802SSteve Glendinning } 861*2f7ca802SSteve Glendinning 862*2f7ca802SSteve Glendinning if (netif_msg_ifup(dev)) 863*2f7ca802SSteve Glendinning devdbg(dev, "rx_urb_size=%ld", (ulong)dev->rx_urb_size); 864*2f7ca802SSteve Glendinning 865*2f7ca802SSteve Glendinning ret = smsc95xx_write_reg(dev, BURST_CAP, burst_cap); 866*2f7ca802SSteve Glendinning if (ret < 0) { 867*2f7ca802SSteve Glendinning devwarn(dev, "Failed to write BURST_CAP: %d", ret); 868*2f7ca802SSteve Glendinning return ret; 869*2f7ca802SSteve Glendinning } 870*2f7ca802SSteve Glendinning 871*2f7ca802SSteve Glendinning ret = smsc95xx_read_reg(dev, BURST_CAP, &read_buf); 872*2f7ca802SSteve Glendinning if (ret < 0) { 873*2f7ca802SSteve Glendinning devwarn(dev, "Failed to read BURST_CAP: %d", ret); 874*2f7ca802SSteve Glendinning return ret; 875*2f7ca802SSteve Glendinning } 876*2f7ca802SSteve Glendinning if (netif_msg_ifup(dev)) 877*2f7ca802SSteve Glendinning devdbg(dev, "Read Value from BURST_CAP after writing: 0x%08x", 878*2f7ca802SSteve Glendinning read_buf); 879*2f7ca802SSteve Glendinning 880*2f7ca802SSteve Glendinning read_buf = DEFAULT_BULK_IN_DELAY; 881*2f7ca802SSteve Glendinning ret = smsc95xx_write_reg(dev, BULK_IN_DLY, read_buf); 882*2f7ca802SSteve Glendinning if (ret < 0) { 883*2f7ca802SSteve Glendinning devwarn(dev, "ret = %d", ret); 884*2f7ca802SSteve Glendinning return ret; 885*2f7ca802SSteve Glendinning } 886*2f7ca802SSteve Glendinning 887*2f7ca802SSteve Glendinning ret = smsc95xx_read_reg(dev, BULK_IN_DLY, &read_buf); 888*2f7ca802SSteve Glendinning if (ret < 0) { 889*2f7ca802SSteve Glendinning devwarn(dev, "Failed to read BULK_IN_DLY: %d", ret); 890*2f7ca802SSteve Glendinning return ret; 891*2f7ca802SSteve Glendinning } 892*2f7ca802SSteve Glendinning if (netif_msg_ifup(dev)) 893*2f7ca802SSteve Glendinning devdbg(dev, "Read Value from BULK_IN_DLY after writing: " 894*2f7ca802SSteve Glendinning "0x%08x", read_buf); 895*2f7ca802SSteve Glendinning 896*2f7ca802SSteve Glendinning ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf); 897*2f7ca802SSteve Glendinning if (ret < 0) { 898*2f7ca802SSteve Glendinning devwarn(dev, "Failed to read HW_CFG: %d", ret); 899*2f7ca802SSteve Glendinning return ret; 900*2f7ca802SSteve Glendinning } 901*2f7ca802SSteve Glendinning if (netif_msg_ifup(dev)) 902*2f7ca802SSteve Glendinning devdbg(dev, "Read Value from HW_CFG: 0x%08x", read_buf); 903*2f7ca802SSteve Glendinning 904*2f7ca802SSteve Glendinning if (turbo_mode) 905*2f7ca802SSteve Glendinning read_buf |= (HW_CFG_MEF_ | HW_CFG_BCE_); 906*2f7ca802SSteve Glendinning 907*2f7ca802SSteve Glendinning read_buf &= ~HW_CFG_RXDOFF_; 908*2f7ca802SSteve Glendinning 909*2f7ca802SSteve Glendinning /* set Rx data offset=2, Make IP header aligns on word boundary. */ 910*2f7ca802SSteve Glendinning read_buf |= NET_IP_ALIGN << 9; 911*2f7ca802SSteve Glendinning 912*2f7ca802SSteve Glendinning ret = smsc95xx_write_reg(dev, HW_CFG, read_buf); 913*2f7ca802SSteve Glendinning if (ret < 0) { 914*2f7ca802SSteve Glendinning devwarn(dev, "Failed to write HW_CFG register, ret=%d", ret); 915*2f7ca802SSteve Glendinning return ret; 916*2f7ca802SSteve Glendinning } 917*2f7ca802SSteve Glendinning 918*2f7ca802SSteve Glendinning ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf); 919*2f7ca802SSteve Glendinning if (ret < 0) { 920*2f7ca802SSteve Glendinning devwarn(dev, "Failed to read HW_CFG: %d", ret); 921*2f7ca802SSteve Glendinning return ret; 922*2f7ca802SSteve Glendinning } 923*2f7ca802SSteve Glendinning if (netif_msg_ifup(dev)) 924*2f7ca802SSteve Glendinning devdbg(dev, "Read Value from HW_CFG after writing: 0x%08x", 925*2f7ca802SSteve Glendinning read_buf); 926*2f7ca802SSteve Glendinning 927*2f7ca802SSteve Glendinning write_buf = 0xFFFFFFFF; 928*2f7ca802SSteve Glendinning ret = smsc95xx_write_reg(dev, INT_STS, write_buf); 929*2f7ca802SSteve Glendinning if (ret < 0) { 930*2f7ca802SSteve Glendinning devwarn(dev, "Failed to write INT_STS register, ret=%d", ret); 931*2f7ca802SSteve Glendinning return ret; 932*2f7ca802SSteve Glendinning } 933*2f7ca802SSteve Glendinning 934*2f7ca802SSteve Glendinning ret = smsc95xx_read_reg(dev, ID_REV, &read_buf); 935*2f7ca802SSteve Glendinning if (ret < 0) { 936*2f7ca802SSteve Glendinning devwarn(dev, "Failed to read ID_REV: %d", ret); 937*2f7ca802SSteve Glendinning return ret; 938*2f7ca802SSteve Glendinning } 939*2f7ca802SSteve Glendinning if (netif_msg_ifup(dev)) 940*2f7ca802SSteve Glendinning devdbg(dev, "ID_REV = 0x%08x", read_buf); 941*2f7ca802SSteve Glendinning 942*2f7ca802SSteve Glendinning /* Init Tx */ 943*2f7ca802SSteve Glendinning write_buf = 0; 944*2f7ca802SSteve Glendinning ret = smsc95xx_write_reg(dev, FLOW, write_buf); 945*2f7ca802SSteve Glendinning if (ret < 0) { 946*2f7ca802SSteve Glendinning devwarn(dev, "Failed to write FLOW: %d", ret); 947*2f7ca802SSteve Glendinning return ret; 948*2f7ca802SSteve Glendinning } 949*2f7ca802SSteve Glendinning 950*2f7ca802SSteve Glendinning read_buf = AFC_CFG_DEFAULT; 951*2f7ca802SSteve Glendinning ret = smsc95xx_write_reg(dev, AFC_CFG, read_buf); 952*2f7ca802SSteve Glendinning if (ret < 0) { 953*2f7ca802SSteve Glendinning devwarn(dev, "Failed to write AFC_CFG: %d", ret); 954*2f7ca802SSteve Glendinning return ret; 955*2f7ca802SSteve Glendinning } 956*2f7ca802SSteve Glendinning 957*2f7ca802SSteve Glendinning /* Don't need mac_cr_lock during initialisation */ 958*2f7ca802SSteve Glendinning ret = smsc95xx_read_reg(dev, MAC_CR, &pdata->mac_cr); 959*2f7ca802SSteve Glendinning if (ret < 0) { 960*2f7ca802SSteve Glendinning devwarn(dev, "Failed to read MAC_CR: %d", ret); 961*2f7ca802SSteve Glendinning return ret; 962*2f7ca802SSteve Glendinning } 963*2f7ca802SSteve Glendinning 964*2f7ca802SSteve Glendinning /* Init Rx */ 965*2f7ca802SSteve Glendinning /* Set Vlan */ 966*2f7ca802SSteve Glendinning write_buf = (u32)ETH_P_8021Q; 967*2f7ca802SSteve Glendinning ret = smsc95xx_write_reg(dev, VLAN1, write_buf); 968*2f7ca802SSteve Glendinning if (ret < 0) { 969*2f7ca802SSteve Glendinning devwarn(dev, "Failed to write VAN1: %d", ret); 970*2f7ca802SSteve Glendinning return ret; 971*2f7ca802SSteve Glendinning } 972*2f7ca802SSteve Glendinning 973*2f7ca802SSteve Glendinning /* Enable or disable Rx checksum offload engine */ 974*2f7ca802SSteve Glendinning ret = smsc95xx_set_rx_csum(dev, pdata->use_rx_csum); 975*2f7ca802SSteve Glendinning if (ret < 0) { 976*2f7ca802SSteve Glendinning devwarn(dev, "Failed to set Rx csum offload: %d", ret); 977*2f7ca802SSteve Glendinning return ret; 978*2f7ca802SSteve Glendinning } 979*2f7ca802SSteve Glendinning 980*2f7ca802SSteve Glendinning smsc95xx_set_multicast(dev->net); 981*2f7ca802SSteve Glendinning 982*2f7ca802SSteve Glendinning if (smsc95xx_phy_initialize(dev) < 0) 983*2f7ca802SSteve Glendinning return -EIO; 984*2f7ca802SSteve Glendinning 985*2f7ca802SSteve Glendinning ret = smsc95xx_read_reg(dev, INT_EP_CTL, &read_buf); 986*2f7ca802SSteve Glendinning if (ret < 0) { 987*2f7ca802SSteve Glendinning devwarn(dev, "Failed to read INT_EP_CTL: %d", ret); 988*2f7ca802SSteve Glendinning return ret; 989*2f7ca802SSteve Glendinning } 990*2f7ca802SSteve Glendinning 991*2f7ca802SSteve Glendinning /* enable PHY interrupts */ 992*2f7ca802SSteve Glendinning read_buf |= INT_EP_CTL_PHY_INT_; 993*2f7ca802SSteve Glendinning 994*2f7ca802SSteve Glendinning ret = smsc95xx_write_reg(dev, INT_EP_CTL, read_buf); 995*2f7ca802SSteve Glendinning if (ret < 0) { 996*2f7ca802SSteve Glendinning devwarn(dev, "Failed to write INT_EP_CTL: %d", ret); 997*2f7ca802SSteve Glendinning return ret; 998*2f7ca802SSteve Glendinning } 999*2f7ca802SSteve Glendinning 1000*2f7ca802SSteve Glendinning smsc95xx_start_tx_path(dev); 1001*2f7ca802SSteve Glendinning smsc95xx_start_rx_path(dev); 1002*2f7ca802SSteve Glendinning 1003*2f7ca802SSteve Glendinning if (netif_msg_ifup(dev)) 1004*2f7ca802SSteve Glendinning devdbg(dev, "smsc95xx_reset, return 0"); 1005*2f7ca802SSteve Glendinning return 0; 1006*2f7ca802SSteve Glendinning } 1007*2f7ca802SSteve Glendinning 1008*2f7ca802SSteve Glendinning static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf) 1009*2f7ca802SSteve Glendinning { 1010*2f7ca802SSteve Glendinning struct smsc95xx_priv *pdata = NULL; 1011*2f7ca802SSteve Glendinning int ret; 1012*2f7ca802SSteve Glendinning 1013*2f7ca802SSteve Glendinning printk(KERN_INFO SMSC_CHIPNAME " v" SMSC_DRIVER_VERSION "\n"); 1014*2f7ca802SSteve Glendinning 1015*2f7ca802SSteve Glendinning ret = usbnet_get_endpoints(dev, intf); 1016*2f7ca802SSteve Glendinning if (ret < 0) { 1017*2f7ca802SSteve Glendinning devwarn(dev, "usbnet_get_endpoints failed: %d", ret); 1018*2f7ca802SSteve Glendinning return ret; 1019*2f7ca802SSteve Glendinning } 1020*2f7ca802SSteve Glendinning 1021*2f7ca802SSteve Glendinning dev->data[0] = (unsigned long)kzalloc(sizeof(struct smsc95xx_priv), 1022*2f7ca802SSteve Glendinning GFP_KERNEL); 1023*2f7ca802SSteve Glendinning 1024*2f7ca802SSteve Glendinning pdata = (struct smsc95xx_priv *)(dev->data[0]); 1025*2f7ca802SSteve Glendinning if (!pdata) { 1026*2f7ca802SSteve Glendinning devwarn(dev, "Unable to allocate struct smsc95xx_priv"); 1027*2f7ca802SSteve Glendinning return -ENOMEM; 1028*2f7ca802SSteve Glendinning } 1029*2f7ca802SSteve Glendinning 1030*2f7ca802SSteve Glendinning spin_lock_init(&pdata->mac_cr_lock); 1031*2f7ca802SSteve Glendinning 1032*2f7ca802SSteve Glendinning pdata->use_rx_csum = DEFAULT_RX_CSUM_ENABLE; 1033*2f7ca802SSteve Glendinning 1034*2f7ca802SSteve Glendinning /* Init all registers */ 1035*2f7ca802SSteve Glendinning ret = smsc95xx_reset(dev); 1036*2f7ca802SSteve Glendinning 1037*2f7ca802SSteve Glendinning dev->net->do_ioctl = smsc95xx_ioctl; 1038*2f7ca802SSteve Glendinning dev->net->ethtool_ops = &smsc95xx_ethtool_ops; 1039*2f7ca802SSteve Glendinning dev->net->set_multicast_list = smsc95xx_set_multicast; 1040*2f7ca802SSteve Glendinning dev->net->flags |= IFF_MULTICAST; 1041*2f7ca802SSteve Glendinning dev->net->hard_header_len += SMSC95XX_TX_OVERHEAD; 1042*2f7ca802SSteve Glendinning return 0; 1043*2f7ca802SSteve Glendinning } 1044*2f7ca802SSteve Glendinning 1045*2f7ca802SSteve Glendinning static void smsc95xx_unbind(struct usbnet *dev, struct usb_interface *intf) 1046*2f7ca802SSteve Glendinning { 1047*2f7ca802SSteve Glendinning struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); 1048*2f7ca802SSteve Glendinning if (pdata) { 1049*2f7ca802SSteve Glendinning if (netif_msg_ifdown(dev)) 1050*2f7ca802SSteve Glendinning devdbg(dev, "free pdata"); 1051*2f7ca802SSteve Glendinning kfree(pdata); 1052*2f7ca802SSteve Glendinning pdata = NULL; 1053*2f7ca802SSteve Glendinning dev->data[0] = 0; 1054*2f7ca802SSteve Glendinning } 1055*2f7ca802SSteve Glendinning } 1056*2f7ca802SSteve Glendinning 1057*2f7ca802SSteve Glendinning static void smsc95xx_rx_csum_offload(struct sk_buff *skb) 1058*2f7ca802SSteve Glendinning { 1059*2f7ca802SSteve Glendinning skb->csum = *(u16 *)(skb_tail_pointer(skb) - 2); 1060*2f7ca802SSteve Glendinning skb->ip_summed = CHECKSUM_COMPLETE; 1061*2f7ca802SSteve Glendinning skb_trim(skb, skb->len - 2); 1062*2f7ca802SSteve Glendinning } 1063*2f7ca802SSteve Glendinning 1064*2f7ca802SSteve Glendinning static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) 1065*2f7ca802SSteve Glendinning { 1066*2f7ca802SSteve Glendinning struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); 1067*2f7ca802SSteve Glendinning 1068*2f7ca802SSteve Glendinning while (skb->len > 0) { 1069*2f7ca802SSteve Glendinning u32 header, align_count; 1070*2f7ca802SSteve Glendinning struct sk_buff *ax_skb; 1071*2f7ca802SSteve Glendinning unsigned char *packet; 1072*2f7ca802SSteve Glendinning u16 size; 1073*2f7ca802SSteve Glendinning 1074*2f7ca802SSteve Glendinning memcpy(&header, skb->data, sizeof(header)); 1075*2f7ca802SSteve Glendinning le32_to_cpus(&header); 1076*2f7ca802SSteve Glendinning skb_pull(skb, 4 + NET_IP_ALIGN); 1077*2f7ca802SSteve Glendinning packet = skb->data; 1078*2f7ca802SSteve Glendinning 1079*2f7ca802SSteve Glendinning /* get the packet length */ 1080*2f7ca802SSteve Glendinning size = (u16)((header & RX_STS_FL_) >> 16); 1081*2f7ca802SSteve Glendinning align_count = (4 - ((size + NET_IP_ALIGN) % 4)) % 4; 1082*2f7ca802SSteve Glendinning 1083*2f7ca802SSteve Glendinning if (unlikely(header & RX_STS_ES_)) { 1084*2f7ca802SSteve Glendinning if (netif_msg_rx_err(dev)) 1085*2f7ca802SSteve Glendinning devdbg(dev, "Error header=0x%08x", header); 1086*2f7ca802SSteve Glendinning dev->stats.rx_errors++; 1087*2f7ca802SSteve Glendinning dev->stats.rx_dropped++; 1088*2f7ca802SSteve Glendinning 1089*2f7ca802SSteve Glendinning if (header & RX_STS_CRC_) { 1090*2f7ca802SSteve Glendinning dev->stats.rx_crc_errors++; 1091*2f7ca802SSteve Glendinning } else { 1092*2f7ca802SSteve Glendinning if (header & (RX_STS_TL_ | RX_STS_RF_)) 1093*2f7ca802SSteve Glendinning dev->stats.rx_frame_errors++; 1094*2f7ca802SSteve Glendinning 1095*2f7ca802SSteve Glendinning if ((header & RX_STS_LE_) && 1096*2f7ca802SSteve Glendinning (!(header & RX_STS_FT_))) 1097*2f7ca802SSteve Glendinning dev->stats.rx_length_errors++; 1098*2f7ca802SSteve Glendinning } 1099*2f7ca802SSteve Glendinning } else { 1100*2f7ca802SSteve Glendinning /* ETH_FRAME_LEN + 4(CRC) + 2(COE) + 4(Vlan) */ 1101*2f7ca802SSteve Glendinning if (unlikely(size > (ETH_FRAME_LEN + 12))) { 1102*2f7ca802SSteve Glendinning if (netif_msg_rx_err(dev)) 1103*2f7ca802SSteve Glendinning devdbg(dev, "size err header=0x%08x", 1104*2f7ca802SSteve Glendinning header); 1105*2f7ca802SSteve Glendinning return 0; 1106*2f7ca802SSteve Glendinning } 1107*2f7ca802SSteve Glendinning 1108*2f7ca802SSteve Glendinning /* last frame in this batch */ 1109*2f7ca802SSteve Glendinning if (skb->len == size) { 1110*2f7ca802SSteve Glendinning if (pdata->use_rx_csum) 1111*2f7ca802SSteve Glendinning smsc95xx_rx_csum_offload(skb); 1112*2f7ca802SSteve Glendinning 1113*2f7ca802SSteve Glendinning skb->truesize = size + sizeof(struct sk_buff); 1114*2f7ca802SSteve Glendinning 1115*2f7ca802SSteve Glendinning return 1; 1116*2f7ca802SSteve Glendinning } 1117*2f7ca802SSteve Glendinning 1118*2f7ca802SSteve Glendinning ax_skb = skb_clone(skb, GFP_ATOMIC); 1119*2f7ca802SSteve Glendinning if (unlikely(!ax_skb)) { 1120*2f7ca802SSteve Glendinning devwarn(dev, "Error allocating skb"); 1121*2f7ca802SSteve Glendinning return 0; 1122*2f7ca802SSteve Glendinning } 1123*2f7ca802SSteve Glendinning 1124*2f7ca802SSteve Glendinning ax_skb->len = size; 1125*2f7ca802SSteve Glendinning ax_skb->data = packet; 1126*2f7ca802SSteve Glendinning skb_set_tail_pointer(ax_skb, size); 1127*2f7ca802SSteve Glendinning 1128*2f7ca802SSteve Glendinning if (pdata->use_rx_csum) 1129*2f7ca802SSteve Glendinning smsc95xx_rx_csum_offload(ax_skb); 1130*2f7ca802SSteve Glendinning 1131*2f7ca802SSteve Glendinning ax_skb->truesize = size + sizeof(struct sk_buff); 1132*2f7ca802SSteve Glendinning 1133*2f7ca802SSteve Glendinning usbnet_skb_return(dev, ax_skb); 1134*2f7ca802SSteve Glendinning } 1135*2f7ca802SSteve Glendinning 1136*2f7ca802SSteve Glendinning skb_pull(skb, size); 1137*2f7ca802SSteve Glendinning 1138*2f7ca802SSteve Glendinning /* padding bytes before the next frame starts */ 1139*2f7ca802SSteve Glendinning if (skb->len) 1140*2f7ca802SSteve Glendinning skb_pull(skb, align_count); 1141*2f7ca802SSteve Glendinning } 1142*2f7ca802SSteve Glendinning 1143*2f7ca802SSteve Glendinning if (unlikely(skb->len < 0)) { 1144*2f7ca802SSteve Glendinning devwarn(dev, "invalid rx length<0 %d", skb->len); 1145*2f7ca802SSteve Glendinning return 0; 1146*2f7ca802SSteve Glendinning } 1147*2f7ca802SSteve Glendinning 1148*2f7ca802SSteve Glendinning return 1; 1149*2f7ca802SSteve Glendinning } 1150*2f7ca802SSteve Glendinning 1151*2f7ca802SSteve Glendinning static struct sk_buff *smsc95xx_tx_fixup(struct usbnet *dev, 1152*2f7ca802SSteve Glendinning struct sk_buff *skb, gfp_t flags) 1153*2f7ca802SSteve Glendinning { 1154*2f7ca802SSteve Glendinning u32 tx_cmd_a, tx_cmd_b; 1155*2f7ca802SSteve Glendinning 1156*2f7ca802SSteve Glendinning if (skb_headroom(skb) < SMSC95XX_TX_OVERHEAD) { 1157*2f7ca802SSteve Glendinning struct sk_buff *skb2 = skb_copy_expand(skb, 1158*2f7ca802SSteve Glendinning SMSC95XX_TX_OVERHEAD, 0, flags); 1159*2f7ca802SSteve Glendinning dev_kfree_skb_any(skb); 1160*2f7ca802SSteve Glendinning skb = skb2; 1161*2f7ca802SSteve Glendinning if (!skb) 1162*2f7ca802SSteve Glendinning return NULL; 1163*2f7ca802SSteve Glendinning } 1164*2f7ca802SSteve Glendinning 1165*2f7ca802SSteve Glendinning skb_push(skb, 4); 1166*2f7ca802SSteve Glendinning tx_cmd_b = (u32)(skb->len - 4); 1167*2f7ca802SSteve Glendinning cpu_to_le32s(&tx_cmd_b); 1168*2f7ca802SSteve Glendinning memcpy(skb->data, &tx_cmd_b, 4); 1169*2f7ca802SSteve Glendinning 1170*2f7ca802SSteve Glendinning skb_push(skb, 4); 1171*2f7ca802SSteve Glendinning tx_cmd_a = (u32)(skb->len - 8) | TX_CMD_A_FIRST_SEG_ | 1172*2f7ca802SSteve Glendinning TX_CMD_A_LAST_SEG_; 1173*2f7ca802SSteve Glendinning cpu_to_le32s(&tx_cmd_a); 1174*2f7ca802SSteve Glendinning memcpy(skb->data, &tx_cmd_a, 4); 1175*2f7ca802SSteve Glendinning 1176*2f7ca802SSteve Glendinning return skb; 1177*2f7ca802SSteve Glendinning } 1178*2f7ca802SSteve Glendinning 1179*2f7ca802SSteve Glendinning static const struct driver_info smsc95xx_info = { 1180*2f7ca802SSteve Glendinning .description = "smsc95xx USB 2.0 Ethernet", 1181*2f7ca802SSteve Glendinning .bind = smsc95xx_bind, 1182*2f7ca802SSteve Glendinning .unbind = smsc95xx_unbind, 1183*2f7ca802SSteve Glendinning .link_reset = smsc95xx_link_reset, 1184*2f7ca802SSteve Glendinning .reset = smsc95xx_reset, 1185*2f7ca802SSteve Glendinning .rx_fixup = smsc95xx_rx_fixup, 1186*2f7ca802SSteve Glendinning .tx_fixup = smsc95xx_tx_fixup, 1187*2f7ca802SSteve Glendinning .status = smsc95xx_status, 1188*2f7ca802SSteve Glendinning .flags = FLAG_ETHER, 1189*2f7ca802SSteve Glendinning }; 1190*2f7ca802SSteve Glendinning 1191*2f7ca802SSteve Glendinning static const struct usb_device_id products[] = { 1192*2f7ca802SSteve Glendinning { 1193*2f7ca802SSteve Glendinning /* SMSC9500 USB Ethernet Device */ 1194*2f7ca802SSteve Glendinning USB_DEVICE(0x0424, 0x9500), 1195*2f7ca802SSteve Glendinning .driver_info = (unsigned long) &smsc95xx_info, 1196*2f7ca802SSteve Glendinning }, 1197*2f7ca802SSteve Glendinning { }, /* END */ 1198*2f7ca802SSteve Glendinning }; 1199*2f7ca802SSteve Glendinning MODULE_DEVICE_TABLE(usb, products); 1200*2f7ca802SSteve Glendinning 1201*2f7ca802SSteve Glendinning static struct usb_driver smsc95xx_driver = { 1202*2f7ca802SSteve Glendinning .name = "smsc95xx", 1203*2f7ca802SSteve Glendinning .id_table = products, 1204*2f7ca802SSteve Glendinning .probe = usbnet_probe, 1205*2f7ca802SSteve Glendinning .suspend = usbnet_suspend, 1206*2f7ca802SSteve Glendinning .resume = usbnet_resume, 1207*2f7ca802SSteve Glendinning .disconnect = usbnet_disconnect, 1208*2f7ca802SSteve Glendinning }; 1209*2f7ca802SSteve Glendinning 1210*2f7ca802SSteve Glendinning static int __init smsc95xx_init(void) 1211*2f7ca802SSteve Glendinning { 1212*2f7ca802SSteve Glendinning return usb_register(&smsc95xx_driver); 1213*2f7ca802SSteve Glendinning } 1214*2f7ca802SSteve Glendinning module_init(smsc95xx_init); 1215*2f7ca802SSteve Glendinning 1216*2f7ca802SSteve Glendinning static void __exit smsc95xx_exit(void) 1217*2f7ca802SSteve Glendinning { 1218*2f7ca802SSteve Glendinning usb_deregister(&smsc95xx_driver); 1219*2f7ca802SSteve Glendinning } 1220*2f7ca802SSteve Glendinning module_exit(smsc95xx_exit); 1221*2f7ca802SSteve Glendinning 1222*2f7ca802SSteve Glendinning MODULE_AUTHOR("Nancy Lin"); 1223*2f7ca802SSteve Glendinning MODULE_AUTHOR("Steve Glendinning <steve.glendinning@smsc.com>"); 1224*2f7ca802SSteve Glendinning MODULE_DESCRIPTION("SMSC95XX USB 2.0 Ethernet Devices"); 1225*2f7ca802SSteve Glendinning MODULE_LICENSE("GPL"); 1226