Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 121948
b: refs/heads/master
c: f7b2927
h: refs/heads/master
v: v3
  • Loading branch information
Steve Glendinning authored and David S. Miller committed Nov 20, 2008
1 parent 67961be commit ca8dc62
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 11 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 8761169cf15fdc9336abfddbb9c8dda59d974190
refs/heads/master: f7b29271c35ed38f990ca3419696ca148349c2d3
75 changes: 65 additions & 10 deletions trunk/drivers/net/usb/smsc95xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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;
};

Expand Down Expand Up @@ -556,17 +559,23 @@ 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) {
devwarn(dev, "Failed to read COE_CR: %d", ret);
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_;
Expand Down Expand Up @@ -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 = {
Expand All @@ -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,
};
Expand Down Expand Up @@ -757,6 +787,7 @@ 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;

Expand Down Expand Up @@ -968,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;
}

Expand Down Expand Up @@ -1027,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 */
Expand Down Expand Up @@ -1146,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);

Expand Down

0 comments on commit ca8dc62

Please sign in to comment.