diff options
author | Giuseppe CAVALLARO <peppe.cavallaro@st.com> | 2010-01-06 18:07:18 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-01-07 20:06:09 -0500 |
commit | aec7ff278145280c2c78377aeb98feed02c8b636 (patch) | |
tree | fa03f8eac900b08e278b64ad76d825400907af9c /drivers/net/stmmac/stmmac_main.c | |
parent | db98a0b001df79ffcdd4f231c3516411786a1113 (diff) |
stmmac: move the dma out from the main
This patch moves the dma related functions (interrupt, start, stop etc.)
out from the main driver code. This will help to support new DMA
engines.
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/stmmac/stmmac_main.c')
-rw-r--r-- | drivers/net/stmmac/stmmac_main.c | 268 |
1 files changed, 37 insertions, 231 deletions
diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c index 86e910300969..e6c5a3cf4af2 100644 --- a/drivers/net/stmmac/stmmac_main.c +++ b/drivers/net/stmmac/stmmac_main.c | |||
@@ -572,50 +572,6 @@ static void free_dma_desc_resources(struct stmmac_priv *priv) | |||
572 | } | 572 | } |
573 | 573 | ||
574 | /** | 574 | /** |
575 | * stmmac_dma_start_tx | ||
576 | * @ioaddr: device I/O address | ||
577 | * Description: this function starts the DMA tx process. | ||
578 | */ | ||
579 | static void stmmac_dma_start_tx(unsigned long ioaddr) | ||
580 | { | ||
581 | u32 value = readl(ioaddr + DMA_CONTROL); | ||
582 | value |= DMA_CONTROL_ST; | ||
583 | writel(value, ioaddr + DMA_CONTROL); | ||
584 | return; | ||
585 | } | ||
586 | |||
587 | static void stmmac_dma_stop_tx(unsigned long ioaddr) | ||
588 | { | ||
589 | u32 value = readl(ioaddr + DMA_CONTROL); | ||
590 | value &= ~DMA_CONTROL_ST; | ||
591 | writel(value, ioaddr + DMA_CONTROL); | ||
592 | return; | ||
593 | } | ||
594 | |||
595 | /** | ||
596 | * stmmac_dma_start_rx | ||
597 | * @ioaddr: device I/O address | ||
598 | * Description: this function starts the DMA rx process. | ||
599 | */ | ||
600 | static void stmmac_dma_start_rx(unsigned long ioaddr) | ||
601 | { | ||
602 | u32 value = readl(ioaddr + DMA_CONTROL); | ||
603 | value |= DMA_CONTROL_SR; | ||
604 | writel(value, ioaddr + DMA_CONTROL); | ||
605 | |||
606 | return; | ||
607 | } | ||
608 | |||
609 | static void stmmac_dma_stop_rx(unsigned long ioaddr) | ||
610 | { | ||
611 | u32 value = readl(ioaddr + DMA_CONTROL); | ||
612 | value &= ~DMA_CONTROL_SR; | ||
613 | writel(value, ioaddr + DMA_CONTROL); | ||
614 | |||
615 | return; | ||
616 | } | ||
617 | |||
618 | /** | ||
619 | * stmmac_dma_operation_mode - HW DMA operation mode | 575 | * stmmac_dma_operation_mode - HW DMA operation mode |
620 | * @priv : pointer to the private device structure. | 576 | * @priv : pointer to the private device structure. |
621 | * Description: it sets the DMA operation mode: tx/rx DMA thresholds | 577 | * Description: it sets the DMA operation mode: tx/rx DMA thresholds |
@@ -646,88 +602,6 @@ static void stmmac_dma_operation_mode(struct stmmac_priv *priv) | |||
646 | return; | 602 | return; |
647 | } | 603 | } |
648 | 604 | ||
649 | #ifdef STMMAC_DEBUG | ||
650 | /** | ||
651 | * show_tx_process_state | ||
652 | * @status: tx descriptor status field | ||
653 | * Description: it shows the Transmit Process State for CSR5[22:20] | ||
654 | */ | ||
655 | static void show_tx_process_state(unsigned int status) | ||
656 | { | ||
657 | unsigned int state; | ||
658 | state = (status & DMA_STATUS_TS_MASK) >> DMA_STATUS_TS_SHIFT; | ||
659 | |||
660 | switch (state) { | ||
661 | case 0: | ||
662 | pr_info("- TX (Stopped): Reset or Stop command\n"); | ||
663 | break; | ||
664 | case 1: | ||
665 | pr_info("- TX (Running):Fetching the Tx desc\n"); | ||
666 | break; | ||
667 | case 2: | ||
668 | pr_info("- TX (Running): Waiting for end of tx\n"); | ||
669 | break; | ||
670 | case 3: | ||
671 | pr_info("- TX (Running): Reading the data " | ||
672 | "and queuing the data into the Tx buf\n"); | ||
673 | break; | ||
674 | case 6: | ||
675 | pr_info("- TX (Suspended): Tx Buff Underflow " | ||
676 | "or an unavailable Transmit descriptor\n"); | ||
677 | break; | ||
678 | case 7: | ||
679 | pr_info("- TX (Running): Closing Tx descriptor\n"); | ||
680 | break; | ||
681 | default: | ||
682 | break; | ||
683 | } | ||
684 | return; | ||
685 | } | ||
686 | |||
687 | /** | ||
688 | * show_rx_process_state | ||
689 | * @status: rx descriptor status field | ||
690 | * Description: it shows the Receive Process State for CSR5[19:17] | ||
691 | */ | ||
692 | static void show_rx_process_state(unsigned int status) | ||
693 | { | ||
694 | unsigned int state; | ||
695 | state = (status & DMA_STATUS_RS_MASK) >> DMA_STATUS_RS_SHIFT; | ||
696 | |||
697 | switch (state) { | ||
698 | case 0: | ||
699 | pr_info("- RX (Stopped): Reset or Stop command\n"); | ||
700 | break; | ||
701 | case 1: | ||
702 | pr_info("- RX (Running): Fetching the Rx desc\n"); | ||
703 | break; | ||
704 | case 2: | ||
705 | pr_info("- RX (Running):Checking for end of pkt\n"); | ||
706 | break; | ||
707 | case 3: | ||
708 | pr_info("- RX (Running): Waiting for Rx pkt\n"); | ||
709 | break; | ||
710 | case 4: | ||
711 | pr_info("- RX (Suspended): Unavailable Rx buf\n"); | ||
712 | break; | ||
713 | case 5: | ||
714 | pr_info("- RX (Running): Closing Rx descriptor\n"); | ||
715 | break; | ||
716 | case 6: | ||
717 | pr_info("- RX(Running): Flushing the current frame" | ||
718 | " from the Rx buf\n"); | ||
719 | break; | ||
720 | case 7: | ||
721 | pr_info("- RX (Running): Queuing the Rx frame" | ||
722 | " from the Rx buf into memory\n"); | ||
723 | break; | ||
724 | default: | ||
725 | break; | ||
726 | } | ||
727 | return; | ||
728 | } | ||
729 | #endif | ||
730 | |||
731 | /** | 605 | /** |
732 | * stmmac_tx: | 606 | * stmmac_tx: |
733 | * @priv: private driver structure | 607 | * @priv: private driver structure |
@@ -811,7 +685,7 @@ static inline void stmmac_enable_irq(struct stmmac_priv *priv) | |||
811 | priv->tm->timer_start(tmrate); | 685 | priv->tm->timer_start(tmrate); |
812 | else | 686 | else |
813 | #endif | 687 | #endif |
814 | writel(DMA_INTR_DEFAULT_MASK, priv->dev->base_addr + DMA_INTR_ENA); | 688 | priv->hw->dma->enable_dma_irq(priv->dev->base_addr); |
815 | } | 689 | } |
816 | 690 | ||
817 | static inline void stmmac_disable_irq(struct stmmac_priv *priv) | 691 | static inline void stmmac_disable_irq(struct stmmac_priv *priv) |
@@ -821,7 +695,7 @@ static inline void stmmac_disable_irq(struct stmmac_priv *priv) | |||
821 | priv->tm->timer_stop(); | 695 | priv->tm->timer_stop(); |
822 | else | 696 | else |
823 | #endif | 697 | #endif |
824 | writel(0, priv->dev->base_addr + DMA_INTR_ENA); | 698 | priv->hw->dma->disable_dma_irq(priv->dev->base_addr); |
825 | } | 699 | } |
826 | 700 | ||
827 | static int stmmac_has_work(struct stmmac_priv *priv) | 701 | static int stmmac_has_work(struct stmmac_priv *priv) |
@@ -880,12 +754,12 @@ static void stmmac_tx_err(struct stmmac_priv *priv) | |||
880 | { | 754 | { |
881 | netif_stop_queue(priv->dev); | 755 | netif_stop_queue(priv->dev); |
882 | 756 | ||
883 | stmmac_dma_stop_tx(priv->dev->base_addr); | 757 | priv->hw->dma->stop_tx(priv->dev->base_addr); |
884 | dma_free_tx_skbufs(priv); | 758 | dma_free_tx_skbufs(priv); |
885 | priv->hw->desc->init_tx_desc(priv->dma_tx, priv->dma_tx_size); | 759 | priv->hw->desc->init_tx_desc(priv->dma_tx, priv->dma_tx_size); |
886 | priv->dirty_tx = 0; | 760 | priv->dirty_tx = 0; |
887 | priv->cur_tx = 0; | 761 | priv->cur_tx = 0; |
888 | stmmac_dma_start_tx(priv->dev->base_addr); | 762 | priv->hw->dma->start_tx(priv->dev->base_addr); |
889 | 763 | ||
890 | priv->dev->stats.tx_errors++; | 764 | priv->dev->stats.tx_errors++; |
891 | netif_wake_queue(priv->dev); | 765 | netif_wake_queue(priv->dev); |
@@ -893,95 +767,27 @@ static void stmmac_tx_err(struct stmmac_priv *priv) | |||
893 | return; | 767 | return; |
894 | } | 768 | } |
895 | 769 | ||
896 | /** | ||
897 | * stmmac_dma_interrupt - Interrupt handler for the driver | ||
898 | * @dev: net device structure | ||
899 | * Description: Interrupt handler for the driver (DMA). | ||
900 | */ | ||
901 | static void stmmac_dma_interrupt(struct net_device *dev) | ||
902 | { | ||
903 | unsigned long ioaddr = dev->base_addr; | ||
904 | struct stmmac_priv *priv = netdev_priv(dev); | ||
905 | /* read the status register (CSR5) */ | ||
906 | u32 intr_status = readl(ioaddr + DMA_STATUS); | ||
907 | |||
908 | DBG(intr, INFO, "%s: [CSR5: 0x%08x]\n", __func__, intr_status); | ||
909 | 770 | ||
910 | #ifdef STMMAC_DEBUG | 771 | static void stmmac_dma_interrupt(struct stmmac_priv *priv) |
911 | /* It displays the DMA transmit process state (CSR5 register) */ | 772 | { |
912 | if (netif_msg_tx_done(priv)) | 773 | unsigned long ioaddr = priv->dev->base_addr; |
913 | show_tx_process_state(intr_status); | 774 | int status; |
914 | if (netif_msg_rx_status(priv)) | 775 | |
915 | show_rx_process_state(intr_status); | 776 | status = priv->hw->dma->dma_interrupt(priv->dev->base_addr, |
916 | #endif | 777 | &priv->xstats); |
917 | /* ABNORMAL interrupts */ | 778 | if (likely(status == handle_tx_rx)) |
918 | if (unlikely(intr_status & DMA_STATUS_AIS)) { | 779 | _stmmac_schedule(priv); |
919 | DBG(intr, INFO, "CSR5[15] DMA ABNORMAL IRQ: "); | 780 | |
920 | if (unlikely(intr_status & DMA_STATUS_UNF)) { | 781 | else if (unlikely(status == tx_hard_error_bump_tc)) { |
921 | DBG(intr, INFO, "transmit underflow\n"); | 782 | /* Try to bump up the dma threshold on this failure */ |
922 | if (unlikely(tc != SF_DMA_MODE) && (tc <= 256)) { | 783 | if (unlikely(tc != SF_DMA_MODE) && (tc <= 256)) { |
923 | /* Try to bump up the threshold */ | 784 | tc += 64; |
924 | tc += 64; | 785 | priv->hw->dma->dma_mode(ioaddr, tc, SF_DMA_MODE); |
925 | priv->hw->dma->dma_mode(ioaddr, tc, | 786 | priv->xstats.threshold = tc; |
926 | SF_DMA_MODE); | ||
927 | priv->xstats.threshold = tc; | ||
928 | } | ||
929 | stmmac_tx_err(priv); | ||
930 | priv->xstats.tx_undeflow_irq++; | ||
931 | } | ||
932 | if (unlikely(intr_status & DMA_STATUS_TJT)) { | ||
933 | DBG(intr, INFO, "transmit jabber\n"); | ||
934 | priv->xstats.tx_jabber_irq++; | ||
935 | } | ||
936 | if (unlikely(intr_status & DMA_STATUS_OVF)) { | ||
937 | DBG(intr, INFO, "recv overflow\n"); | ||
938 | priv->xstats.rx_overflow_irq++; | ||
939 | } | ||
940 | if (unlikely(intr_status & DMA_STATUS_RU)) { | ||
941 | DBG(intr, INFO, "receive buffer unavailable\n"); | ||
942 | priv->xstats.rx_buf_unav_irq++; | ||
943 | } | ||
944 | if (unlikely(intr_status & DMA_STATUS_RPS)) { | ||
945 | DBG(intr, INFO, "receive process stopped\n"); | ||
946 | priv->xstats.rx_process_stopped_irq++; | ||
947 | } | ||
948 | if (unlikely(intr_status & DMA_STATUS_RWT)) { | ||
949 | DBG(intr, INFO, "receive watchdog\n"); | ||
950 | priv->xstats.rx_watchdog_irq++; | ||
951 | } | ||
952 | if (unlikely(intr_status & DMA_STATUS_ETI)) { | ||
953 | DBG(intr, INFO, "transmit early interrupt\n"); | ||
954 | priv->xstats.tx_early_irq++; | ||
955 | } | ||
956 | if (unlikely(intr_status & DMA_STATUS_TPS)) { | ||
957 | DBG(intr, INFO, "transmit process stopped\n"); | ||
958 | priv->xstats.tx_process_stopped_irq++; | ||
959 | stmmac_tx_err(priv); | ||
960 | } | ||
961 | if (unlikely(intr_status & DMA_STATUS_FBI)) { | ||
962 | DBG(intr, INFO, "fatal bus error\n"); | ||
963 | priv->xstats.fatal_bus_error_irq++; | ||
964 | stmmac_tx_err(priv); | ||
965 | } | 787 | } |
966 | } | 788 | stmmac_tx_err(priv); |
967 | 789 | } else if (unlikely(status == tx_hard_error)) | |
968 | /* TX/RX NORMAL interrupts */ | 790 | stmmac_tx_err(priv); |
969 | if (intr_status & DMA_STATUS_NIS) { | ||
970 | priv->xstats.normal_irq_n++; | ||
971 | if (likely((intr_status & DMA_STATUS_RI) || | ||
972 | (intr_status & (DMA_STATUS_TI)))) | ||
973 | _stmmac_schedule(priv); | ||
974 | } | ||
975 | |||
976 | /* Optional hardware blocks, interrupts should be disabled */ | ||
977 | if (unlikely(intr_status & | ||
978 | (DMA_STATUS_GPI | DMA_STATUS_GMI | DMA_STATUS_GLI))) | ||
979 | pr_info("%s: unexpected status %08x\n", __func__, intr_status); | ||
980 | |||
981 | /* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */ | ||
982 | writel((intr_status & 0x1ffff), ioaddr + DMA_STATUS); | ||
983 | |||
984 | DBG(intr, INFO, "\n\n"); | ||
985 | 791 | ||
986 | return; | 792 | return; |
987 | } | 793 | } |
@@ -1089,8 +895,8 @@ static int stmmac_open(struct net_device *dev) | |||
1089 | 895 | ||
1090 | /* Start the ball rolling... */ | 896 | /* Start the ball rolling... */ |
1091 | DBG(probe, DEBUG, "%s: DMA RX/TX processes started...\n", dev->name); | 897 | DBG(probe, DEBUG, "%s: DMA RX/TX processes started...\n", dev->name); |
1092 | stmmac_dma_start_tx(ioaddr); | 898 | priv->hw->dma->start_tx(ioaddr); |
1093 | stmmac_dma_start_rx(ioaddr); | 899 | priv->hw->dma->start_rx(ioaddr); |
1094 | 900 | ||
1095 | #ifdef CONFIG_STMMAC_TIMER | 901 | #ifdef CONFIG_STMMAC_TIMER |
1096 | priv->tm->timer_start(tmrate); | 902 | priv->tm->timer_start(tmrate); |
@@ -1142,8 +948,8 @@ static int stmmac_release(struct net_device *dev) | |||
1142 | free_irq(dev->irq, dev); | 948 | free_irq(dev->irq, dev); |
1143 | 949 | ||
1144 | /* Stop TX/RX DMA and clear the descriptors */ | 950 | /* Stop TX/RX DMA and clear the descriptors */ |
1145 | stmmac_dma_stop_tx(dev->base_addr); | 951 | priv->hw->dma->stop_tx(dev->base_addr); |
1146 | stmmac_dma_stop_rx(dev->base_addr); | 952 | priv->hw->dma->stop_rx(dev->base_addr); |
1147 | 953 | ||
1148 | /* Release and free the Rx/Tx resources */ | 954 | /* Release and free the Rx/Tx resources */ |
1149 | free_dma_desc_resources(priv); | 955 | free_dma_desc_resources(priv); |
@@ -1227,7 +1033,6 @@ static unsigned int stmmac_handle_jumbo_frames(struct sk_buff *skb, | |||
1227 | priv->hw->desc->prepare_tx_desc(desc, 0, buf2_size, | 1033 | priv->hw->desc->prepare_tx_desc(desc, 0, buf2_size, |
1228 | csum_insertion); | 1034 | csum_insertion); |
1229 | priv->hw->desc->set_tx_owner(desc); | 1035 | priv->hw->desc->set_tx_owner(desc); |
1230 | |||
1231 | priv->tx_skbuff[entry] = NULL; | 1036 | priv->tx_skbuff[entry] = NULL; |
1232 | } else { | 1037 | } else { |
1233 | desc->des2 = dma_map_single(priv->device, skb->data, | 1038 | desc->des2 = dma_map_single(priv->device, skb->data, |
@@ -1353,8 +1158,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1353 | 1158 | ||
1354 | dev->stats.tx_bytes += skb->len; | 1159 | dev->stats.tx_bytes += skb->len; |
1355 | 1160 | ||
1356 | /* CSR1 enables the transmit DMA to check for new descriptor */ | 1161 | priv->hw->dma->enable_dma_transmission(dev->base_addr); |
1357 | writel(1, dev->base_addr + DMA_XMT_POLL_DEMAND); | ||
1358 | 1162 | ||
1359 | return NETDEV_TX_OK; | 1163 | return NETDEV_TX_OK; |
1360 | } | 1164 | } |
@@ -1624,7 +1428,8 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id) | |||
1624 | /* To handle GMAC own interrupts */ | 1428 | /* To handle GMAC own interrupts */ |
1625 | priv->hw->mac->host_irq_status(ioaddr); | 1429 | priv->hw->mac->host_irq_status(ioaddr); |
1626 | } | 1430 | } |
1627 | stmmac_dma_interrupt(dev); | 1431 | |
1432 | stmmac_dma_interrupt(priv); | ||
1628 | 1433 | ||
1629 | return IRQ_HANDLED; | 1434 | return IRQ_HANDLED; |
1630 | } | 1435 | } |
@@ -1988,12 +1793,13 @@ out: | |||
1988 | static int stmmac_dvr_remove(struct platform_device *pdev) | 1793 | static int stmmac_dvr_remove(struct platform_device *pdev) |
1989 | { | 1794 | { |
1990 | struct net_device *ndev = platform_get_drvdata(pdev); | 1795 | struct net_device *ndev = platform_get_drvdata(pdev); |
1796 | struct stmmac_priv *priv = netdev_priv(ndev); | ||
1991 | struct resource *res; | 1797 | struct resource *res; |
1992 | 1798 | ||
1993 | pr_info("%s:\n\tremoving driver", __func__); | 1799 | pr_info("%s:\n\tremoving driver", __func__); |
1994 | 1800 | ||
1995 | stmmac_dma_stop_rx(ndev->base_addr); | 1801 | priv->hw->dma->stop_rx(ndev->base_addr); |
1996 | stmmac_dma_stop_tx(ndev->base_addr); | 1802 | priv->hw->dma->stop_tx(ndev->base_addr); |
1997 | 1803 | ||
1998 | stmmac_mac_disable_rx(ndev->base_addr); | 1804 | stmmac_mac_disable_rx(ndev->base_addr); |
1999 | stmmac_mac_disable_tx(ndev->base_addr); | 1805 | stmmac_mac_disable_tx(ndev->base_addr); |
@@ -2040,8 +1846,8 @@ static int stmmac_suspend(struct platform_device *pdev, pm_message_t state) | |||
2040 | napi_disable(&priv->napi); | 1846 | napi_disable(&priv->napi); |
2041 | 1847 | ||
2042 | /* Stop TX/RX DMA */ | 1848 | /* Stop TX/RX DMA */ |
2043 | stmmac_dma_stop_tx(dev->base_addr); | 1849 | priv->hw->dma->stop_tx(dev->base_addr); |
2044 | stmmac_dma_stop_rx(dev->base_addr); | 1850 | priv->hw->dma->stop_rx(dev->base_addr); |
2045 | /* Clear the Rx/Tx descriptors */ | 1851 | /* Clear the Rx/Tx descriptors */ |
2046 | priv->hw->desc->init_rx_desc(priv->dma_rx, priv->dma_rx_size, | 1852 | priv->hw->desc->init_rx_desc(priv->dma_rx, priv->dma_rx_size, |
2047 | dis_ic); | 1853 | dis_ic); |
@@ -2101,8 +1907,8 @@ static int stmmac_resume(struct platform_device *pdev) | |||
2101 | /* Enable the MAC and DMA */ | 1907 | /* Enable the MAC and DMA */ |
2102 | stmmac_mac_enable_rx(ioaddr); | 1908 | stmmac_mac_enable_rx(ioaddr); |
2103 | stmmac_mac_enable_tx(ioaddr); | 1909 | stmmac_mac_enable_tx(ioaddr); |
2104 | stmmac_dma_start_tx(ioaddr); | 1910 | priv->hw->dma->start_tx(ioaddr); |
2105 | stmmac_dma_start_rx(ioaddr); | 1911 | priv->hw->dma->start_rx(ioaddr); |
2106 | 1912 | ||
2107 | #ifdef CONFIG_STMMAC_TIMER | 1913 | #ifdef CONFIG_STMMAC_TIMER |
2108 | priv->tm->timer_start(tmrate); | 1914 | priv->tm->timer_start(tmrate); |