Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 199196
b: refs/heads/master
c: 23ecc4b
h: refs/heads/master
v: v3
  • Loading branch information
Brian Hill authored and David S. Miller committed May 27, 2010
1 parent d28da87 commit fe32388
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 25 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: 755fae0ac41672523a3ac00d41fe9bac226b0578
refs/heads/master: 23ecc4bde21f0ccb38f4b53cadde7fc5d67d68e3
5 changes: 5 additions & 0 deletions trunk/drivers/net/ll_temac.h
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,10 @@ This option defaults to enabled (set) */

#define MULTICAST_CAM_TABLE_NUM 4

/* TEMAC Synthesis features */
#define TEMAC_FEATURE_RX_CSUM (1 << 0)
#define TEMAC_FEATURE_TX_CSUM (1 << 1)

/* TX/RX CURDESC_PTR points to first descriptor */
/* TX/RX TAILDESC_PTR points to last descriptor in linked list */

Expand Down Expand Up @@ -353,6 +357,7 @@ struct temac_local {
struct mutex indirect_mutex;
u32 options; /* Current options word */
int last_link;
unsigned int temac_features;

/* Buffer descriptors */
struct cdmac_bd *tx_bd_v;
Expand Down
82 changes: 58 additions & 24 deletions trunk/drivers/net/ll_temac_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ static int temac_dma_bd_init(struct net_device *ndev)
CHNL_CTRL_IRQ_COAL_EN);
/* 0x10220483 */
/* 0x00100483 */
lp->dma_out(lp, RX_CHNL_CTRL, 0xff010000 |
lp->dma_out(lp, RX_CHNL_CTRL, 0xff070000 |
CHNL_CTRL_IRQ_EN |
CHNL_CTRL_IRQ_DLY_EN |
CHNL_CTRL_IRQ_COAL_EN |
Expand Down Expand Up @@ -574,6 +574,10 @@ static void temac_start_xmit_done(struct net_device *ndev)
if (cur_p->app4)
dev_kfree_skb_irq((struct sk_buff *)cur_p->app4);
cur_p->app0 = 0;
cur_p->app1 = 0;
cur_p->app2 = 0;
cur_p->app3 = 0;
cur_p->app4 = 0;

ndev->stats.tx_packets++;
ndev->stats.tx_bytes += cur_p->len;
Expand All @@ -589,6 +593,29 @@ static void temac_start_xmit_done(struct net_device *ndev)
netif_wake_queue(ndev);
}

static inline int temac_check_tx_bd_space(struct temac_local *lp, int num_frag)
{
struct cdmac_bd *cur_p;
int tail;

tail = lp->tx_bd_tail;
cur_p = &lp->tx_bd_v[tail];

do {
if (cur_p->app0)
return NETDEV_TX_BUSY;

tail++;
if (tail >= TX_BD_NUM)
tail = 0;

cur_p = &lp->tx_bd_v[tail];
num_frag--;
} while (num_frag >= 0);

return 0;
}

static int temac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
{
struct temac_local *lp = netdev_priv(ndev);
Expand All @@ -603,7 +630,7 @@ static int temac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
start_p = lp->tx_bd_p + sizeof(*lp->tx_bd_v) * lp->tx_bd_tail;
cur_p = &lp->tx_bd_v[lp->tx_bd_tail];

if (cur_p->app0 & STS_CTRL_APP0_CMPLT) {
if (temac_check_tx_bd_space(lp, num_frag)) {
if (!netif_queue_stopped(ndev)) {
netif_stop_queue(ndev);
return NETDEV_TX_BUSY;
Expand All @@ -613,29 +640,14 @@ static int temac_start_xmit(struct sk_buff *skb, struct net_device *ndev)

cur_p->app0 = 0;
if (skb->ip_summed == CHECKSUM_PARTIAL) {
const struct iphdr *ip = ip_hdr(skb);
int length = 0, start = 0, insert = 0;

switch (ip->protocol) {
case IPPROTO_TCP:
start = sizeof(struct iphdr) + ETH_HLEN;
insert = sizeof(struct iphdr) + ETH_HLEN + 16;
length = ip->tot_len - sizeof(struct iphdr);
break;
case IPPROTO_UDP:
start = sizeof(struct iphdr) + ETH_HLEN;
insert = sizeof(struct iphdr) + ETH_HLEN + 6;
length = ip->tot_len - sizeof(struct iphdr);
break;
default:
break;
}
cur_p->app1 = ((start << 16) | insert);
cur_p->app2 = csum_tcpudp_magic(ip->saddr, ip->daddr,
length, ip->protocol, 0);
skb->data[insert] = 0;
skb->data[insert + 1] = 0;
unsigned int csum_start_off = skb_transport_offset(skb);
unsigned int csum_index_off = csum_start_off + skb->csum_offset;

cur_p->app0 |= 1; /* TX Checksum Enabled */
cur_p->app1 = (csum_start_off << 16) | csum_index_off;
cur_p->app2 = 0; /* initial checksum seed */
}

cur_p->app0 |= STS_CTRL_APP0_SOP;
cur_p->len = skb_headlen(skb);
cur_p->phys = dma_map_single(ndev->dev.parent, skb->data, skb->len,
Expand Down Expand Up @@ -699,6 +711,15 @@ static void ll_temac_recv(struct net_device *ndev)
skb->protocol = eth_type_trans(skb, ndev);
skb->ip_summed = CHECKSUM_NONE;

/* if we're doing rx csum offload, set it up */
if (((lp->temac_features & TEMAC_FEATURE_RX_CSUM) != 0) &&
(skb->protocol == __constant_htons(ETH_P_IP)) &&
(skb->len > 64)) {

skb->csum = cur_p->app3 & 0xFFFF;
skb->ip_summed = CHECKSUM_COMPLETE;
}

netif_rx(skb);

ndev->stats.rx_packets++;
Expand Down Expand Up @@ -883,6 +904,7 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
struct temac_local *lp;
struct net_device *ndev;
const void *addr;
__be32 *p;
int size, rc = 0;

/* Init network device structure */
Expand Down Expand Up @@ -926,6 +948,18 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
goto nodev;
}

/* Setup checksum offload, but default to off if not specified */
lp->temac_features = 0;
p = (__be32 *)of_get_property(op->dev.of_node, "xlnx,txcsum", NULL);
if (p && be32_to_cpu(*p)) {
lp->temac_features |= TEMAC_FEATURE_TX_CSUM;
/* Can checksum TCP/UDP over IPv4. */
ndev->features |= NETIF_F_IP_CSUM;
}
p = (__be32 *)of_get_property(op->dev.of_node, "xlnx,rxcsum", NULL);
if (p && be32_to_cpu(*p))
lp->temac_features |= TEMAC_FEATURE_RX_CSUM;

/* Find the DMA node, map the DMA registers, and decode the DMA IRQs */
np = of_parse_phandle(op->node, "llink-connected", 0);
if (!np) {
Expand Down

0 comments on commit fe32388

Please sign in to comment.