@@ -245,7 +245,7 @@ static int temac_dma_bd_init(struct net_device *ndev)
245
245
CHNL_CTRL_IRQ_COAL_EN );
246
246
/* 0x10220483 */
247
247
/* 0x00100483 */
248
- lp -> dma_out (lp , RX_CHNL_CTRL , 0xff010000 |
248
+ lp -> dma_out (lp , RX_CHNL_CTRL , 0xff070000 |
249
249
CHNL_CTRL_IRQ_EN |
250
250
CHNL_CTRL_IRQ_DLY_EN |
251
251
CHNL_CTRL_IRQ_COAL_EN |
@@ -574,6 +574,10 @@ static void temac_start_xmit_done(struct net_device *ndev)
574
574
if (cur_p -> app4 )
575
575
dev_kfree_skb_irq ((struct sk_buff * )cur_p -> app4 );
576
576
cur_p -> app0 = 0 ;
577
+ cur_p -> app1 = 0 ;
578
+ cur_p -> app2 = 0 ;
579
+ cur_p -> app3 = 0 ;
580
+ cur_p -> app4 = 0 ;
577
581
578
582
ndev -> stats .tx_packets ++ ;
579
583
ndev -> stats .tx_bytes += cur_p -> len ;
@@ -589,6 +593,29 @@ static void temac_start_xmit_done(struct net_device *ndev)
589
593
netif_wake_queue (ndev );
590
594
}
591
595
596
+ static inline int temac_check_tx_bd_space (struct temac_local * lp , int num_frag )
597
+ {
598
+ struct cdmac_bd * cur_p ;
599
+ int tail ;
600
+
601
+ tail = lp -> tx_bd_tail ;
602
+ cur_p = & lp -> tx_bd_v [tail ];
603
+
604
+ do {
605
+ if (cur_p -> app0 )
606
+ return NETDEV_TX_BUSY ;
607
+
608
+ tail ++ ;
609
+ if (tail >= TX_BD_NUM )
610
+ tail = 0 ;
611
+
612
+ cur_p = & lp -> tx_bd_v [tail ];
613
+ num_frag -- ;
614
+ } while (num_frag >= 0 );
615
+
616
+ return 0 ;
617
+ }
618
+
592
619
static int temac_start_xmit (struct sk_buff * skb , struct net_device * ndev )
593
620
{
594
621
struct temac_local * lp = netdev_priv (ndev );
@@ -603,7 +630,7 @@ static int temac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
603
630
start_p = lp -> tx_bd_p + sizeof (* lp -> tx_bd_v ) * lp -> tx_bd_tail ;
604
631
cur_p = & lp -> tx_bd_v [lp -> tx_bd_tail ];
605
632
606
- if (cur_p -> app0 & STS_CTRL_APP0_CMPLT ) {
633
+ if (temac_check_tx_bd_space ( lp , num_frag ) ) {
607
634
if (!netif_queue_stopped (ndev )) {
608
635
netif_stop_queue (ndev );
609
636
return NETDEV_TX_BUSY ;
@@ -613,29 +640,14 @@ static int temac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
613
640
614
641
cur_p -> app0 = 0 ;
615
642
if (skb -> ip_summed == CHECKSUM_PARTIAL ) {
616
- const struct iphdr * ip = ip_hdr (skb );
617
- int length = 0 , start = 0 , insert = 0 ;
618
-
619
- switch (ip -> protocol ) {
620
- case IPPROTO_TCP :
621
- start = sizeof (struct iphdr ) + ETH_HLEN ;
622
- insert = sizeof (struct iphdr ) + ETH_HLEN + 16 ;
623
- length = ip -> tot_len - sizeof (struct iphdr );
624
- break ;
625
- case IPPROTO_UDP :
626
- start = sizeof (struct iphdr ) + ETH_HLEN ;
627
- insert = sizeof (struct iphdr ) + ETH_HLEN + 6 ;
628
- length = ip -> tot_len - sizeof (struct iphdr );
629
- break ;
630
- default :
631
- break ;
632
- }
633
- cur_p -> app1 = ((start << 16 ) | insert );
634
- cur_p -> app2 = csum_tcpudp_magic (ip -> saddr , ip -> daddr ,
635
- length , ip -> protocol , 0 );
636
- skb -> data [insert ] = 0 ;
637
- skb -> data [insert + 1 ] = 0 ;
643
+ unsigned int csum_start_off = skb_transport_offset (skb );
644
+ unsigned int csum_index_off = csum_start_off + skb -> csum_offset ;
645
+
646
+ cur_p -> app0 |= 1 ; /* TX Checksum Enabled */
647
+ cur_p -> app1 = (csum_start_off << 16 ) | csum_index_off ;
648
+ cur_p -> app2 = 0 ; /* initial checksum seed */
638
649
}
650
+
639
651
cur_p -> app0 |= STS_CTRL_APP0_SOP ;
640
652
cur_p -> len = skb_headlen (skb );
641
653
cur_p -> phys = dma_map_single (ndev -> dev .parent , skb -> data , skb -> len ,
@@ -699,6 +711,15 @@ static void ll_temac_recv(struct net_device *ndev)
699
711
skb -> protocol = eth_type_trans (skb , ndev );
700
712
skb -> ip_summed = CHECKSUM_NONE ;
701
713
714
+ /* if we're doing rx csum offload, set it up */
715
+ if (((lp -> temac_features & TEMAC_FEATURE_RX_CSUM ) != 0 ) &&
716
+ (skb -> protocol == __constant_htons (ETH_P_IP )) &&
717
+ (skb -> len > 64 )) {
718
+
719
+ skb -> csum = cur_p -> app3 & 0xFFFF ;
720
+ skb -> ip_summed = CHECKSUM_COMPLETE ;
721
+ }
722
+
702
723
netif_rx (skb );
703
724
704
725
ndev -> stats .rx_packets ++ ;
@@ -883,6 +904,7 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
883
904
struct temac_local * lp ;
884
905
struct net_device * ndev ;
885
906
const void * addr ;
907
+ __be32 * p ;
886
908
int size , rc = 0 ;
887
909
888
910
/* Init network device structure */
@@ -926,6 +948,18 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
926
948
goto nodev ;
927
949
}
928
950
951
+ /* Setup checksum offload, but default to off if not specified */
952
+ lp -> temac_features = 0 ;
953
+ p = (__be32 * )of_get_property (op -> dev .of_node , "xlnx,txcsum" , NULL );
954
+ if (p && be32_to_cpu (* p )) {
955
+ lp -> temac_features |= TEMAC_FEATURE_TX_CSUM ;
956
+ /* Can checksum TCP/UDP over IPv4. */
957
+ ndev -> features |= NETIF_F_IP_CSUM ;
958
+ }
959
+ p = (__be32 * )of_get_property (op -> dev .of_node , "xlnx,rxcsum" , NULL );
960
+ if (p && be32_to_cpu (* p ))
961
+ lp -> temac_features |= TEMAC_FEATURE_RX_CSUM ;
962
+
929
963
/* Find the DMA node, map the DMA registers, and decode the DMA IRQs */
930
964
np = of_parse_phandle (op -> node , "llink-connected" , 0 );
931
965
if (!np ) {
0 commit comments