/***************************************************************************
*
* Copyright (C) 2007-2010 SMSC
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*****************************************************************************/
#include <linux/module.h>
#include <linux/kmod.h>
#include <linux/init.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/mii.h>
#include <linux/usb.h>
#include <linux/crc32.h>
#include <linux/usb/usbnet.h>
#include "smsc75xx.h"
#define SMSC_CHIPNAME "smsc75xx"
#define SMSC_DRIVER_VERSION "1.0.0"
#define HS_USB_PKT_SIZE (512)
#define FS_USB_PKT_SIZE (64)
#define DEFAULT_HS_BURST_CAP_SIZE (16 * 1024 + 5 * HS_USB_PKT_SIZE)
#define DEFAULT_FS_BURST_CAP_SIZE (6 * 1024 + 33 * FS_USB_PKT_SIZE)
#define DEFAULT_BULK_IN_DELAY (0x00002000)
#define MAX_SINGLE_PACKET_SIZE (9000)
#define LAN75XX_EEPROM_MAGIC (0x7500)
#define EEPROM_MAC_OFFSET (0x01)
#define DEFAULT_TX_CSUM_ENABLE (true)
#define DEFAULT_RX_CSUM_ENABLE (true)
#define DEFAULT_TSO_ENABLE (true)
#define SMSC75XX_INTERNAL_PHY_ID (1)
#define SMSC75XX_TX_OVERHEAD (8)
#define MAX_RX_FIFO_SIZE (20 * 1024)
#define MAX_TX_FIFO_SIZE (12 * 1024)
#define USB_VENDOR_ID_SMSC (0x0424)
#define USB_PRODUCT_ID_LAN7500 (0x7500)
#define USB_PRODUCT_ID_LAN7505 (0x7505)
#define check_warn(ret, fmt, args...) \
({ if (ret < 0) netdev_warn(dev->net, fmt, ##args); })
#define check_warn_return(ret, fmt, args...) \
({ if (ret < 0) { netdev_warn(dev->net, fmt, ##args); return ret; } })
#define check_warn_goto_done(ret, fmt, args...) \
({ if (ret < 0) { netdev_warn(dev->net, fmt, ##args); goto done; } })
struct smsc75xx_priv {
struct usbnet *dev;
u32 rfe_ctl;
u32 multicast_hash_table[DP_SEL_VHF_HASH_LEN];
bool use_rx_csum;
struct mutex dataport_mutex;
spinlock_t rfe_ctl_lock;
struct work_struct set_multicast;
};
struct usb_context {
struct usb_ctrlrequest req;
struct usbnet *dev;
};
static int turbo_mode = true;
module_param(turbo_mode, bool, 0644);
MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction");
static int __must_check smsc75xx_read_reg(struct usbnet *dev, u32 index,
u32 *data)
{
u32 *buf = kmalloc(4, GFP_KERNEL);
int ret;
BUG_ON(!dev);
if (!buf)
return -ENOMEM;
ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
USB_VENDOR_REQUEST_READ_REGISTER,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
00, index, buf, 4, USB_CTRL_GET_TIMEOUT);
if (unlikely(ret < 0))
netdev_warn(dev->net,
"Failed to read register index 0x%08x", index);
le32_to_cpus(buf);
*data = *buf;
kfree(buf);
return ret;
}
static int __must_check smsc75xx_write_reg(struct usbnet *dev, u32 index,
u32 data)
{
u32 *buf = kmalloc(4,