diff options
Diffstat (limited to 'drivers/net/usb')
-rw-r--r-- | drivers/net/usb/catc.c | 2 | ||||
-rw-r--r-- | drivers/net/usb/mcs7830.c | 4 | ||||
-rw-r--r-- | drivers/net/usb/pegasus.c | 41 | ||||
-rw-r--r-- | drivers/net/usb/smsc95xx.c | 79 | ||||
-rw-r--r-- | drivers/net/usb/usbnet.c | 5 |
5 files changed, 98 insertions, 33 deletions
diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c index 466a89e2444..d7621239059 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/mcs7830.c b/drivers/net/usb/mcs7830.c index b5143509e8b..bbcc76ae3c9 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 7914867110e..075e8e94225 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 51e2f5d7d14..4638a7bb471 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 02d25c74399..aa314907888 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); |