diff options
Diffstat (limited to 'drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c')
-rw-r--r-- | drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c | 95 |
1 files changed, 65 insertions, 30 deletions
diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c index 9e2bcb807923..a17628769a1f 100644 --- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c +++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c | |||
@@ -278,14 +278,20 @@ static int fs_enet_tx_napi(struct napi_struct *napi, int budget) | |||
278 | fep->stats.collisions++; | 278 | fep->stats.collisions++; |
279 | 279 | ||
280 | /* unmap */ | 280 | /* unmap */ |
281 | dma_unmap_single(fep->dev, CBDR_BUFADDR(bdp), | 281 | if (fep->mapped_as_page[dirtyidx]) |
282 | skb->len, DMA_TO_DEVICE); | 282 | dma_unmap_page(fep->dev, CBDR_BUFADDR(bdp), |
283 | CBDR_DATLEN(bdp), DMA_TO_DEVICE); | ||
284 | else | ||
285 | dma_unmap_single(fep->dev, CBDR_BUFADDR(bdp), | ||
286 | CBDR_DATLEN(bdp), DMA_TO_DEVICE); | ||
283 | 287 | ||
284 | /* | 288 | /* |
285 | * Free the sk buffer associated with this last transmit. | 289 | * Free the sk buffer associated with this last transmit. |
286 | */ | 290 | */ |
287 | dev_kfree_skb(skb); | 291 | if (skb) { |
288 | fep->tx_skbuff[dirtyidx] = NULL; | 292 | dev_kfree_skb(skb); |
293 | fep->tx_skbuff[dirtyidx] = NULL; | ||
294 | } | ||
289 | 295 | ||
290 | /* | 296 | /* |
291 | * Update pointer to next buffer descriptor to be transmitted. | 297 | * Update pointer to next buffer descriptor to be transmitted. |
@@ -299,7 +305,7 @@ static int fs_enet_tx_napi(struct napi_struct *napi, int budget) | |||
299 | * Since we have freed up a buffer, the ring is no longer | 305 | * Since we have freed up a buffer, the ring is no longer |
300 | * full. | 306 | * full. |
301 | */ | 307 | */ |
302 | if (!fep->tx_free++) | 308 | if (++fep->tx_free >= MAX_SKB_FRAGS) |
303 | do_wake = 1; | 309 | do_wake = 1; |
304 | has_tx_work = 1; | 310 | has_tx_work = 1; |
305 | } | 311 | } |
@@ -509,6 +515,9 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
509 | cbd_t __iomem *bdp; | 515 | cbd_t __iomem *bdp; |
510 | int curidx; | 516 | int curidx; |
511 | u16 sc; | 517 | u16 sc; |
518 | int nr_frags = skb_shinfo(skb)->nr_frags; | ||
519 | skb_frag_t *frag; | ||
520 | int len; | ||
512 | 521 | ||
513 | #ifdef CONFIG_FS_ENET_MPC5121_FEC | 522 | #ifdef CONFIG_FS_ENET_MPC5121_FEC |
514 | if (((unsigned long)skb->data) & 0x3) { | 523 | if (((unsigned long)skb->data) & 0x3) { |
@@ -530,7 +539,7 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
530 | */ | 539 | */ |
531 | bdp = fep->cur_tx; | 540 | bdp = fep->cur_tx; |
532 | 541 | ||
533 | if (!fep->tx_free || (CBDR_SC(bdp) & BD_ENET_TX_READY)) { | 542 | if (fep->tx_free <= nr_frags || (CBDR_SC(bdp) & BD_ENET_TX_READY)) { |
534 | netif_stop_queue(dev); | 543 | netif_stop_queue(dev); |
535 | spin_unlock(&fep->tx_lock); | 544 | spin_unlock(&fep->tx_lock); |
536 | 545 | ||
@@ -543,35 +552,42 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
543 | } | 552 | } |
544 | 553 | ||
545 | curidx = bdp - fep->tx_bd_base; | 554 | curidx = bdp - fep->tx_bd_base; |
546 | /* | ||
547 | * Clear all of the status flags. | ||
548 | */ | ||
549 | CBDC_SC(bdp, BD_ENET_TX_STATS); | ||
550 | |||
551 | /* | ||
552 | * Save skb pointer. | ||
553 | */ | ||
554 | fep->tx_skbuff[curidx] = skb; | ||
555 | |||
556 | fep->stats.tx_bytes += skb->len; | ||
557 | 555 | ||
556 | len = skb->len; | ||
557 | fep->stats.tx_bytes += len; | ||
558 | if (nr_frags) | ||
559 | len -= skb->data_len; | ||
560 | fep->tx_free -= nr_frags + 1; | ||
558 | /* | 561 | /* |
559 | * Push the data cache so the CPM does not get stale memory data. | 562 | * Push the data cache so the CPM does not get stale memory data. |
560 | */ | 563 | */ |
561 | CBDW_BUFADDR(bdp, dma_map_single(fep->dev, | 564 | CBDW_BUFADDR(bdp, dma_map_single(fep->dev, |
562 | skb->data, skb->len, DMA_TO_DEVICE)); | 565 | skb->data, len, DMA_TO_DEVICE)); |
563 | CBDW_DATLEN(bdp, skb->len); | 566 | CBDW_DATLEN(bdp, len); |
567 | |||
568 | fep->mapped_as_page[curidx] = 0; | ||
569 | frag = skb_shinfo(skb)->frags; | ||
570 | while (nr_frags) { | ||
571 | CBDC_SC(bdp, | ||
572 | BD_ENET_TX_STATS | BD_ENET_TX_LAST | BD_ENET_TX_TC); | ||
573 | CBDS_SC(bdp, BD_ENET_TX_READY); | ||
574 | |||
575 | if ((CBDR_SC(bdp) & BD_ENET_TX_WRAP) == 0) | ||
576 | bdp++, curidx++; | ||
577 | else | ||
578 | bdp = fep->tx_bd_base, curidx = 0; | ||
564 | 579 | ||
565 | /* | 580 | len = skb_frag_size(frag); |
566 | * If this was the last BD in the ring, start at the beginning again. | 581 | CBDW_BUFADDR(bdp, skb_frag_dma_map(fep->dev, frag, 0, len, |
567 | */ | 582 | DMA_TO_DEVICE)); |
568 | if ((CBDR_SC(bdp) & BD_ENET_TX_WRAP) == 0) | 583 | CBDW_DATLEN(bdp, len); |
569 | fep->cur_tx++; | ||
570 | else | ||
571 | fep->cur_tx = fep->tx_bd_base; | ||
572 | 584 | ||
573 | if (!--fep->tx_free) | 585 | fep->tx_skbuff[curidx] = NULL; |
574 | netif_stop_queue(dev); | 586 | fep->mapped_as_page[curidx] = 1; |
587 | |||
588 | frag++; | ||
589 | nr_frags--; | ||
590 | } | ||
575 | 591 | ||
576 | /* Trigger transmission start */ | 592 | /* Trigger transmission start */ |
577 | sc = BD_ENET_TX_READY | BD_ENET_TX_INTR | | 593 | sc = BD_ENET_TX_READY | BD_ENET_TX_INTR | |
@@ -582,8 +598,22 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
582 | * yay for hw reuse :) */ | 598 | * yay for hw reuse :) */ |
583 | if (skb->len <= 60) | 599 | if (skb->len <= 60) |
584 | sc |= BD_ENET_TX_PAD; | 600 | sc |= BD_ENET_TX_PAD; |
601 | CBDC_SC(bdp, BD_ENET_TX_STATS); | ||
585 | CBDS_SC(bdp, sc); | 602 | CBDS_SC(bdp, sc); |
586 | 603 | ||
604 | /* Save skb pointer. */ | ||
605 | fep->tx_skbuff[curidx] = skb; | ||
606 | |||
607 | /* If this was the last BD in the ring, start at the beginning again. */ | ||
608 | if ((CBDR_SC(bdp) & BD_ENET_TX_WRAP) == 0) | ||
609 | bdp++; | ||
610 | else | ||
611 | bdp = fep->tx_bd_base; | ||
612 | fep->cur_tx = bdp; | ||
613 | |||
614 | if (fep->tx_free < MAX_SKB_FRAGS) | ||
615 | netif_stop_queue(dev); | ||
616 | |||
587 | skb_tx_timestamp(skb); | 617 | skb_tx_timestamp(skb); |
588 | 618 | ||
589 | (*fep->ops->tx_kickstart)(dev); | 619 | (*fep->ops->tx_kickstart)(dev); |
@@ -917,7 +947,7 @@ static int fs_enet_probe(struct platform_device *ofdev) | |||
917 | } | 947 | } |
918 | 948 | ||
919 | fpi->rx_ring = 32; | 949 | fpi->rx_ring = 32; |
920 | fpi->tx_ring = 32; | 950 | fpi->tx_ring = 64; |
921 | fpi->rx_copybreak = 240; | 951 | fpi->rx_copybreak = 240; |
922 | fpi->napi_weight = 17; | 952 | fpi->napi_weight = 17; |
923 | fpi->phy_node = of_parse_phandle(ofdev->dev.of_node, "phy-handle", 0); | 953 | fpi->phy_node = of_parse_phandle(ofdev->dev.of_node, "phy-handle", 0); |
@@ -955,7 +985,8 @@ static int fs_enet_probe(struct platform_device *ofdev) | |||
955 | 985 | ||
956 | privsize = sizeof(*fep) + | 986 | privsize = sizeof(*fep) + |
957 | sizeof(struct sk_buff **) * | 987 | sizeof(struct sk_buff **) * |
958 | (fpi->rx_ring + fpi->tx_ring); | 988 | (fpi->rx_ring + fpi->tx_ring) + |
989 | sizeof(char) * fpi->tx_ring; | ||
959 | 990 | ||
960 | ndev = alloc_etherdev(privsize); | 991 | ndev = alloc_etherdev(privsize); |
961 | if (!ndev) { | 992 | if (!ndev) { |
@@ -978,6 +1009,8 @@ static int fs_enet_probe(struct platform_device *ofdev) | |||
978 | 1009 | ||
979 | fep->rx_skbuff = (struct sk_buff **)&fep[1]; | 1010 | fep->rx_skbuff = (struct sk_buff **)&fep[1]; |
980 | fep->tx_skbuff = fep->rx_skbuff + fpi->rx_ring; | 1011 | fep->tx_skbuff = fep->rx_skbuff + fpi->rx_ring; |
1012 | fep->mapped_as_page = (char *)(fep->rx_skbuff + fpi->rx_ring + | ||
1013 | fpi->tx_ring); | ||
981 | 1014 | ||
982 | spin_lock_init(&fep->lock); | 1015 | spin_lock_init(&fep->lock); |
983 | spin_lock_init(&fep->tx_lock); | 1016 | spin_lock_init(&fep->tx_lock); |
@@ -1007,6 +1040,8 @@ static int fs_enet_probe(struct platform_device *ofdev) | |||
1007 | 1040 | ||
1008 | netif_carrier_off(ndev); | 1041 | netif_carrier_off(ndev); |
1009 | 1042 | ||
1043 | ndev->features |= NETIF_F_SG; | ||
1044 | |||
1010 | ret = register_netdev(ndev); | 1045 | ret = register_netdev(ndev); |
1011 | if (ret) | 1046 | if (ret) |
1012 | goto out_free_bd; | 1047 | goto out_free_bd; |