summaryrefslogtreecommitdiff
path: root/drivers/net/usb
diff options
context:
space:
mode:
authorStephen Rothwell <sfr@canb.auug.org.au>2008-12-01 14:22:55 +1100
committerStephen Rothwell <sfr@canb.auug.org.au>2008-12-01 14:26:56 +1100
commitc1ea68f0237fc3e8ea5a6c084af9bda6b9a3722c (patch)
tree18f1c1a9ec816260ae4576496fa0b40559fb7dfd /drivers/net/usb
parent9a6cf71fa371180543df9f196e93986e37582c81 (diff)
parent25f13048bce61f33f6a102e0bf377fd3922ed364 (diff)
Merge commit 'net/master'
Conflicts: drivers/net/ixgbe/ixgbe_main.c drivers/net/smc91x.c
Diffstat (limited to 'drivers/net/usb')
-rw-r--r--drivers/net/usb/catc.c2
-rw-r--r--drivers/net/usb/hso.c31
-rw-r--r--drivers/net/usb/mcs7830.c4
-rw-r--r--drivers/net/usb/pegasus.c41
-rw-r--r--drivers/net/usb/smsc95xx.c79
-rw-r--r--drivers/net/usb/usbnet.c5
6 files changed, 118 insertions, 44 deletions
diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c
index 466a89e24444..d7621239059a 100644
--- a/drivers/net/usb/catc.c
+++ b/drivers/net/usb/catc.c
@@ -271,8 +271,6 @@ static void catc_rx_done(struct urb *urb)
} while (pkt_start - (u8 *) urb->transfer_buffer < urb->actual_length);
- catc->netdev->last_rx = jiffies;
-
if (catc->is_f5u011) {
if (atomic_read(&catc->recq_sz)) {
int status;
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
index 8e90891f0e42..c5c1aeae94fe 100644
--- a/drivers/net/usb/hso.c
+++ b/drivers/net/usb/hso.c
@@ -417,6 +417,11 @@ static const struct usb_device_id hso_ids[] = {
{USB_DEVICE(0x0af0, 0x7401)}, /* GI 0401 */
{USB_DEVICE(0x0af0, 0x7501)}, /* GTM 382 */
{USB_DEVICE(0x0af0, 0x7601)}, /* GE40x */
+ {USB_DEVICE(0x0af0, 0x7701)},
+ {USB_DEVICE(0x0af0, 0x7801)},
+ {USB_DEVICE(0x0af0, 0x7901)},
+ {USB_DEVICE(0x0af0, 0x7361)},
+ {icon321_port_device(0x0af0, 0xd051)},
{}
};
MODULE_DEVICE_TABLE(usb, hso_ids);
@@ -2750,18 +2755,21 @@ static int hso_resume(struct usb_interface *iface)
if (network_table[i] &&
(network_table[i]->interface == iface)) {
hso_net = dev2net(network_table[i]);
- /* First transmit any lingering data, then restart the
- * device. */
- if (hso_net->skb_tx_buf) {
- dev_dbg(&iface->dev,
- "Transmitting lingering data\n");
- hso_net_start_xmit(hso_net->skb_tx_buf,
- hso_net->net);
- hso_net->skb_tx_buf = NULL;
+ if (hso_net->flags & IFF_UP) {
+ /* First transmit any lingering data,
+ then restart the device. */
+ if (hso_net->skb_tx_buf) {
+ dev_dbg(&iface->dev,
+ "Transmitting"
+ " lingering data\n");
+ hso_net_start_xmit(hso_net->skb_tx_buf,
+ hso_net->net);
+ hso_net->skb_tx_buf = NULL;
+ }
+ result = hso_start_net_device(network_table[i]);
+ if (result)
+ goto out;
}
- result = hso_start_net_device(network_table[i]);
- if (result)
- goto out;
}
}
@@ -2894,6 +2902,7 @@ static struct usb_driver hso_driver = {
.id_table = hso_ids,
.suspend = hso_suspend,
.resume = hso_resume,
+ .reset_resume = hso_resume,
.supports_autosuspend = 1,
};
diff --git a/drivers/net/usb/mcs7830.c b/drivers/net/usb/mcs7830.c
index b5143509e8be..bbcc76ae3c9c 100644
--- a/drivers/net/usb/mcs7830.c
+++ b/drivers/net/usb/mcs7830.c
@@ -344,14 +344,14 @@ out:
static int mcs7830_mdio_read(struct net_device *netdev, int phy_id,
int location)
{
- struct usbnet *dev = netdev->priv;
+ struct usbnet *dev = netdev_priv(netdev);
return mcs7830_read_phy(dev, location);
}
static void mcs7830_mdio_write(struct net_device *netdev, int phy_id,
int location, int val)
{
- struct usbnet *dev = netdev->priv;
+ struct usbnet *dev = netdev_priv(netdev);
mcs7830_write_phy(dev, location, val);
}
diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c
index 32cc6617cc71..7a45700651f4 100644
--- a/drivers/net/usb/pegasus.c
+++ b/drivers/net/usb/pegasus.c
@@ -1213,7 +1213,7 @@ static void pegasus_set_multicast(struct net_device *net)
pegasus->eth_regs[EthCtrl0] |= RX_MULTICAST;
pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS;
if (netif_msg_link(pegasus))
- pr_info("%s: set allmulti\n", net->name);
+ pr_debug("%s: set allmulti\n", net->name);
} else {
pegasus->eth_regs[EthCtrl0] &= ~RX_MULTICAST;
pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS;
@@ -1273,6 +1273,7 @@ static inline void setup_pegasus_II(pegasus_t * pegasus)
}
+static int pegasus_count;
static struct workqueue_struct *pegasus_workqueue = NULL;
#define CARRIER_CHECK_DELAY (2 * HZ)
@@ -1301,6 +1302,18 @@ static int pegasus_blacklisted(struct usb_device *udev)
return 0;
}
+/* we rely on probe() and remove() being serialized so we
+ * don't need extra locking on pegasus_count.
+ */
+static void pegasus_dec_workqueue(void)
+{
+ pegasus_count--;
+ if (pegasus_count == 0) {
+ destroy_workqueue(pegasus_workqueue);
+ pegasus_workqueue = NULL;
+ }
+}
+
static int pegasus_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
@@ -1309,14 +1322,18 @@ static int pegasus_probe(struct usb_interface *intf,
pegasus_t *pegasus;
int dev_index = id - pegasus_ids;
int res = -ENOMEM;
- DECLARE_MAC_BUF(mac);
- usb_get_dev(dev);
+ if (pegasus_blacklisted(dev))
+ return -ENODEV;
- if (pegasus_blacklisted(dev)) {
- res = -ENODEV;
- goto out;
+ if (pegasus_count == 0) {
+ pegasus_workqueue = create_singlethread_workqueue("pegasus");
+ if (!pegasus_workqueue)
+ return -ENOMEM;
}
+ pegasus_count++;
+
+ usb_get_dev(dev);
net = alloc_etherdev(sizeof(struct pegasus));
if (!net) {
@@ -1386,10 +1403,10 @@ static int pegasus_probe(struct usb_interface *intf,
queue_delayed_work(pegasus_workqueue, &pegasus->carrier_check,
CARRIER_CHECK_DELAY);
- dev_info(&intf->dev, "%s, %s, %s\n",
+ dev_info(&intf->dev, "%s, %s, %pM\n",
net->name,
usb_dev_id[dev_index].name,
- print_mac(mac, net->dev_addr));
+ net->dev_addr);
return 0;
out3:
@@ -1401,6 +1418,7 @@ out1:
free_netdev(net);
out:
usb_put_dev(dev);
+ pegasus_dec_workqueue();
return res;
}
@@ -1426,6 +1444,7 @@ static void pegasus_disconnect(struct usb_interface *intf)
pegasus->rx_skb = NULL;
}
free_netdev(pegasus->net);
+ pegasus_dec_workqueue();
}
static int pegasus_suspend (struct usb_interface *intf, pm_message_t message)
@@ -1469,7 +1488,7 @@ static struct usb_driver pegasus_driver = {
.resume = pegasus_resume,
};
-static void parse_id(char *id)
+static void __init parse_id(char *id)
{
unsigned int vendor_id=0, device_id=0, flags=0, i=0;
char *token, *name=NULL;
@@ -1505,15 +1524,11 @@ static int __init pegasus_init(void)
pr_info("%s: %s, " DRIVER_DESC "\n", driver_name, DRIVER_VERSION);
if (devid)
parse_id(devid);
- pegasus_workqueue = create_singlethread_workqueue("pegasus");
- if (!pegasus_workqueue)
- return -ENOMEM;
return usb_register(&pegasus_driver);
}
static void __exit pegasus_exit(void)
{
- destroy_workqueue(pegasus_workqueue);
usb_deregister(&pegasus_driver);
}
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index 51e2f5d7d14e..4638a7bb471e 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -31,7 +31,7 @@
#include "smsc95xx.h"
#define SMSC_CHIPNAME "smsc95xx"
-#define SMSC_DRIVER_VERSION "1.0.3"
+#define SMSC_DRIVER_VERSION "1.0.4"
#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)
@@ -40,15 +40,18 @@
#define MAX_SINGLE_PACKET_SIZE (2048)
#define LAN95XX_EEPROM_MAGIC (0x9500)
#define EEPROM_MAC_OFFSET (0x01)
+#define DEFAULT_TX_CSUM_ENABLE (true)
#define DEFAULT_RX_CSUM_ENABLE (true)
#define SMSC95XX_INTERNAL_PHY_ID (1)
#define SMSC95XX_TX_OVERHEAD (8)
+#define SMSC95XX_TX_OVERHEAD_CSUM (12)
#define FLOW_CTRL_TX (1)
#define FLOW_CTRL_RX (2)
struct smsc95xx_priv {
u32 mac_cr;
spinlock_t mac_cr_lock;
+ bool use_tx_csum;
bool use_rx_csum;
};
@@ -556,9 +559,10 @@ static void smsc95xx_status(struct usbnet *dev, struct urb *urb)
devwarn(dev, "unexpected interrupt, intdata=0x%08X", intdata);
}
-/* Enable or disable Rx checksum offload engine */
-static int smsc95xx_set_rx_csum(struct usbnet *dev, bool enable)
+/* Enable or disable Tx & Rx checksum offload engines */
+static int smsc95xx_set_csums(struct usbnet *dev)
{
+ struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
u32 read_buf;
int ret = smsc95xx_read_reg(dev, COE_CR, &read_buf);
if (ret < 0) {
@@ -566,7 +570,12 @@ static int smsc95xx_set_rx_csum(struct usbnet *dev, bool enable)
return ret;
}
- if (enable)
+ if (pdata->use_tx_csum)
+ read_buf |= Tx_COE_EN_;
+ else
+ read_buf &= ~Tx_COE_EN_;
+
+ if (pdata->use_rx_csum)
read_buf |= Rx_COE_EN_;
else
read_buf &= ~Rx_COE_EN_;
@@ -626,7 +635,26 @@ static int smsc95xx_ethtool_set_rx_csum(struct net_device *netdev, u32 val)
pdata->use_rx_csum = !!val;
- return smsc95xx_set_rx_csum(dev, pdata->use_rx_csum);
+ return smsc95xx_set_csums(dev);
+}
+
+static u32 smsc95xx_ethtool_get_tx_csum(struct net_device *netdev)
+{
+ struct usbnet *dev = netdev_priv(netdev);
+ struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+
+ return pdata->use_tx_csum;
+}
+
+static int smsc95xx_ethtool_set_tx_csum(struct net_device *netdev, u32 val)
+{
+ struct usbnet *dev = netdev_priv(netdev);
+ struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+
+ pdata->use_tx_csum = !!val;
+
+ ethtool_op_set_tx_hw_csum(netdev, pdata->use_tx_csum);
+ return smsc95xx_set_csums(dev);
}
static struct ethtool_ops smsc95xx_ethtool_ops = {
@@ -640,6 +668,8 @@ static struct ethtool_ops smsc95xx_ethtool_ops = {
.get_eeprom_len = smsc95xx_ethtool_get_eeprom_len,
.get_eeprom = smsc95xx_ethtool_get_eeprom,
.set_eeprom = smsc95xx_ethtool_set_eeprom,
+ .get_tx_csum = smsc95xx_ethtool_get_tx_csum,
+ .set_tx_csum = smsc95xx_ethtool_set_tx_csum,
.get_rx_csum = smsc95xx_ethtool_get_rx_csum,
.set_rx_csum = smsc95xx_ethtool_set_rx_csum,
};
@@ -757,9 +787,9 @@ static int smsc95xx_phy_initialize(struct usbnet *dev)
static int smsc95xx_reset(struct usbnet *dev)
{
struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+ struct net_device *netdev = dev->net;
u32 read_buf, write_buf, burst_cap;
int ret = 0, timeout;
- DECLARE_MAC_BUF(mac);
if (netif_msg_ifup(dev))
devdbg(dev, "entering smsc95xx_reset");
@@ -818,8 +848,7 @@ static int smsc95xx_reset(struct usbnet *dev)
return ret;
if (netif_msg_ifup(dev))
- devdbg(dev, "MAC Address: %s",
- print_mac(mac, dev->net->dev_addr));
+ devdbg(dev, "MAC Address: %pM", dev->net->dev_addr);
ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
if (ret < 0) {
@@ -970,10 +999,11 @@ static int smsc95xx_reset(struct usbnet *dev)
return ret;
}
- /* Enable or disable Rx checksum offload engine */
- ret = smsc95xx_set_rx_csum(dev, pdata->use_rx_csum);
+ /* Enable or disable checksum offload engines */
+ ethtool_op_set_tx_hw_csum(netdev, pdata->use_tx_csum);
+ ret = smsc95xx_set_csums(dev);
if (ret < 0) {
- devwarn(dev, "Failed to set Rx csum offload: %d", ret);
+ devwarn(dev, "Failed to set csum offload: %d", ret);
return ret;
}
@@ -1029,6 +1059,7 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
spin_lock_init(&pdata->mac_cr_lock);
+ pdata->use_tx_csum = DEFAULT_TX_CSUM_ENABLE;
pdata->use_rx_csum = DEFAULT_RX_CSUM_ENABLE;
/* Init all registers */
@@ -1148,22 +1179,44 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
return 1;
}
+static u32 smsc95xx_calc_csum_preamble(struct sk_buff *skb)
+{
+ int len = skb->data - skb->head;
+ u16 high_16 = (u16)(skb->csum_offset + skb->csum_start - len);
+ u16 low_16 = (u16)(skb->csum_start - len);
+ return (high_16 << 16) | low_16;
+}
+
static struct sk_buff *smsc95xx_tx_fixup(struct usbnet *dev,
struct sk_buff *skb, gfp_t flags)
{
+ struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+ bool csum = pdata->use_tx_csum && (skb->ip_summed == CHECKSUM_PARTIAL);
+ int overhead = csum ? SMSC95XX_TX_OVERHEAD_CSUM : SMSC95XX_TX_OVERHEAD;
u32 tx_cmd_a, tx_cmd_b;
- if (skb_headroom(skb) < SMSC95XX_TX_OVERHEAD) {
+ /* We do not advertise SG, so skbs should be already linearized */
+ BUG_ON(skb_shinfo(skb)->nr_frags);
+
+ if (skb_headroom(skb) < overhead) {
struct sk_buff *skb2 = skb_copy_expand(skb,
- SMSC95XX_TX_OVERHEAD, 0, flags);
+ overhead, 0, flags);
dev_kfree_skb_any(skb);
skb = skb2;
if (!skb)
return NULL;
}
+ if (csum) {
+ u32 csum_preamble = smsc95xx_calc_csum_preamble(skb);
+ skb_push(skb, 4);
+ memcpy(skb->data, &csum_preamble, 4);
+ }
+
skb_push(skb, 4);
tx_cmd_b = (u32)(skb->len - 4);
+ if (csum)
+ tx_cmd_b |= TX_CMD_B_CSUM_ENABLE;
cpu_to_le32s(&tx_cmd_b);
memcpy(skb->data, &tx_cmd_b, 4);
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 02d25c743994..aa3149078888 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -1125,7 +1125,6 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
struct usb_device *xdev;
int status;
const char *name;
- DECLARE_MAC_BUF(mac);
name = udev->dev.driver->name;
info = (struct driver_info *) prod->driver_info;
@@ -1236,11 +1235,11 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
if (status)
goto out3;
if (netif_msg_probe (dev))
- devinfo (dev, "register '%s' at usb-%s-%s, %s, %s",
+ devinfo (dev, "register '%s' at usb-%s-%s, %s, %pM",
udev->dev.driver->name,
xdev->bus->bus_name, xdev->devpath,
dev->driver_info->description,
- print_mac(mac, net->dev_addr));
+ net->dev_addr);
// ok, it's ready to go.
usb_set_intfdata (udev, dev);