.. | .. |
---|
85 | 85 | int rx; |
---|
86 | 86 | int final_tx; |
---|
87 | 87 | int final_rx; |
---|
| 88 | + int max_delay; |
---|
88 | 89 | }; |
---|
89 | 90 | |
---|
90 | 91 | #define DMA_CONTROL_OSP BIT(4) |
---|
.. | .. |
---|
545 | 546 | static void dwmac_rk_rx_clean(struct stmmac_priv *priv, |
---|
546 | 547 | struct dwmac_rk_lb_priv *lb_priv) |
---|
547 | 548 | { |
---|
548 | | - struct sk_buff *skb; |
---|
549 | | - |
---|
550 | | - skb = lb_priv->rx_skbuff; |
---|
551 | | - |
---|
552 | | - if (likely(lb_priv->rx_skbuff)) { |
---|
| 549 | + if (likely(lb_priv->rx_skbuff_dma)) { |
---|
553 | 550 | dma_unmap_single(priv->device, |
---|
554 | 551 | lb_priv->rx_skbuff_dma, |
---|
555 | 552 | lb_priv->dma_buf_sz, DMA_FROM_DEVICE); |
---|
556 | | - dev_kfree_skb(skb); |
---|
| 553 | + lb_priv->rx_skbuff_dma = 0; |
---|
| 554 | + } |
---|
| 555 | + |
---|
| 556 | + if (likely(lb_priv->rx_skbuff)) { |
---|
| 557 | + dev_consume_skb_any(lb_priv->rx_skbuff); |
---|
557 | 558 | lb_priv->rx_skbuff = NULL; |
---|
558 | 559 | } |
---|
559 | 560 | } |
---|
.. | .. |
---|
582 | 583 | } |
---|
583 | 584 | |
---|
584 | 585 | frame_len -= ETH_FCS_LEN; |
---|
| 586 | + prefetch(skb->data - NET_IP_ALIGN); |
---|
585 | 587 | skb_put(skb, frame_len); |
---|
| 588 | + dma_unmap_single(priv->device, |
---|
| 589 | + lb_priv->rx_skbuff_dma, |
---|
| 590 | + lb_priv->dma_buf_sz, |
---|
| 591 | + DMA_FROM_DEVICE); |
---|
586 | 592 | |
---|
587 | 593 | return dwmac_rk_loopback_validate(priv, lb_priv, skb); |
---|
588 | 594 | } |
---|
.. | .. |
---|
616 | 622 | static void dwmac_rk_tx_clean(struct stmmac_priv *priv, |
---|
617 | 623 | struct dwmac_rk_lb_priv *lb_priv) |
---|
618 | 624 | { |
---|
619 | | - struct sk_buff *skb; |
---|
| 625 | + struct sk_buff *skb = lb_priv->tx_skbuff; |
---|
620 | 626 | struct dma_desc *p; |
---|
621 | 627 | |
---|
622 | | - skb = lb_priv->tx_skbuff; |
---|
623 | 628 | p = lb_priv->dma_tx; |
---|
624 | 629 | |
---|
625 | 630 | if (likely(lb_priv->tx_skbuff_dma)) { |
---|
.. | .. |
---|
631 | 636 | } |
---|
632 | 637 | |
---|
633 | 638 | if (likely(skb)) { |
---|
634 | | - dev_kfree_skb(skb); |
---|
| 639 | + dev_consume_skb_any(skb); |
---|
635 | 640 | lb_priv->tx_skbuff = NULL; |
---|
636 | 641 | } |
---|
637 | 642 | |
---|
.. | .. |
---|
655 | 660 | lb_priv->tx_skbuff = skb; |
---|
656 | 661 | |
---|
657 | 662 | des = dma_map_single(priv->device, skb->data, |
---|
658 | | - nopaged_len, DMA_TO_DEVICE); |
---|
| 663 | + nopaged_len, DMA_TO_DEVICE); |
---|
659 | 664 | if (dma_mapping_error(priv->device, des)) |
---|
660 | 665 | goto dma_map_err; |
---|
| 666 | + lb_priv->tx_skbuff_dma = des; |
---|
661 | 667 | |
---|
662 | 668 | stmmac_set_desc_addr(priv, desc, des); |
---|
663 | 669 | lb_priv->tx_skbuff_dma_len = nopaged_len; |
---|
.. | .. |
---|
771 | 777 | return __dwmac_rk_loopback_run(priv, lb_priv); |
---|
772 | 778 | } |
---|
773 | 779 | |
---|
774 | | -static inline bool dwmac_rk_delayline_is_valid(int tx, int rx) |
---|
| 780 | +static inline bool dwmac_rk_delayline_is_txvalid(struct dwmac_rk_lb_priv *lb_priv, |
---|
| 781 | + int tx) |
---|
775 | 782 | { |
---|
776 | | - if ((tx > 0 && tx < MAX_DELAYLINE) && (rx > 0 && rx < MAX_DELAYLINE)) |
---|
| 783 | + if (tx > 0 && tx < lb_priv->max_delay) |
---|
| 784 | + return true; |
---|
| 785 | + else |
---|
| 786 | + return false; |
---|
| 787 | +} |
---|
| 788 | + |
---|
| 789 | +static inline bool dwmac_rk_delayline_is_valid(struct dwmac_rk_lb_priv *lb_priv, |
---|
| 790 | + int tx, int rx) |
---|
| 791 | +{ |
---|
| 792 | + if ((tx > 0 && tx < lb_priv->max_delay) && |
---|
| 793 | + (rx > 0 && rx < lb_priv->max_delay)) |
---|
777 | 794 | return true; |
---|
778 | 795 | else |
---|
779 | 796 | return false; |
---|
.. | .. |
---|
784 | 801 | { |
---|
785 | 802 | int tx_left, tx_right, rx_up, rx_down; |
---|
786 | 803 | int i, j, tx_index, rx_index; |
---|
787 | | - int tx_mid, rx_mid; |
---|
| 804 | + int tx_mid = 0, rx_mid = 0; |
---|
788 | 805 | |
---|
789 | 806 | /* initiation */ |
---|
790 | 807 | tx_index = SCAN_STEP; |
---|
.. | .. |
---|
792 | 809 | |
---|
793 | 810 | re_scan: |
---|
794 | 811 | /* start from rx based on the experience */ |
---|
795 | | - for (i = rx_index; i <= (MAX_DELAYLINE - SCAN_STEP); i += SCAN_STEP) { |
---|
| 812 | + for (i = rx_index; i <= (lb_priv->max_delay - SCAN_STEP); i += SCAN_STEP) { |
---|
796 | 813 | tx_left = 0; |
---|
797 | 814 | tx_right = 0; |
---|
798 | 815 | tx_mid = 0; |
---|
799 | 816 | |
---|
800 | | - for (j = tx_index; j <= (MAX_DELAYLINE - SCAN_STEP); |
---|
| 817 | + for (j = tx_index; j <= (lb_priv->max_delay - SCAN_STEP); |
---|
801 | 818 | j += SCAN_STEP) { |
---|
802 | 819 | if (!dwmac_rk_loopback_with_identify(priv, |
---|
803 | 820 | lb_priv, j, i)) { |
---|
.. | .. |
---|
815 | 832 | } |
---|
816 | 833 | |
---|
817 | 834 | /* Worst case: reach the end */ |
---|
818 | | - if (i >= (MAX_DELAYLINE - SCAN_STEP)) |
---|
| 835 | + if (i >= (lb_priv->max_delay - SCAN_STEP)) |
---|
819 | 836 | goto end; |
---|
820 | 837 | |
---|
821 | 838 | rx_up = 0; |
---|
822 | 839 | rx_down = 0; |
---|
823 | 840 | |
---|
824 | 841 | /* look for rx_mid base on the tx_mid */ |
---|
825 | | - for (i = SCAN_STEP; i <= (MAX_DELAYLINE - SCAN_STEP); |
---|
| 842 | + for (i = SCAN_STEP; i <= (lb_priv->max_delay - SCAN_STEP); |
---|
826 | 843 | i += SCAN_STEP) { |
---|
827 | 844 | if (!dwmac_rk_loopback_with_identify(priv, lb_priv, |
---|
828 | 845 | tx_mid, i)) { |
---|
.. | .. |
---|
841 | 858 | goto re_scan; |
---|
842 | 859 | } |
---|
843 | 860 | |
---|
844 | | - if (dwmac_rk_delayline_is_valid(tx_mid, rx_mid)) { |
---|
| 861 | + if (dwmac_rk_delayline_is_valid(lb_priv, tx_mid, rx_mid)) { |
---|
845 | 862 | lb_priv->final_tx = tx_mid; |
---|
846 | 863 | lb_priv->final_rx = rx_mid; |
---|
847 | 864 | |
---|
848 | | - pr_info("Find suitable tx_delay = 0x%02x, rx_delay = 0x%02x\n", |
---|
| 865 | + pr_info("Find available tx_delay = 0x%02x, rx_delay = 0x%02x\n", |
---|
849 | 866 | lb_priv->final_tx, lb_priv->final_rx); |
---|
850 | 867 | |
---|
851 | 868 | return 0; |
---|
852 | 869 | } |
---|
853 | 870 | end: |
---|
854 | | - pr_err("Can't find suitable delayline\n"); |
---|
| 871 | + pr_err("Can't find available delayline\n"); |
---|
855 | 872 | return -ENXIO; |
---|
856 | 873 | } |
---|
857 | 874 | |
---|
858 | 875 | static int dwmac_rk_delayline_scan(struct stmmac_priv *priv, |
---|
859 | 876 | struct dwmac_rk_lb_priv *lb_priv) |
---|
860 | 877 | { |
---|
| 878 | + int phy_iface = dwmac_rk_get_phy_interface(priv); |
---|
861 | 879 | int tx, rx, tx_sum, rx_sum, count; |
---|
862 | 880 | int tx_mid, rx_mid; |
---|
863 | 881 | int ret = -ENXIO; |
---|
.. | .. |
---|
866 | 884 | rx_sum = 0; |
---|
867 | 885 | count = 0; |
---|
868 | 886 | |
---|
869 | | - for (rx = 0x0; rx <= MAX_DELAYLINE; rx++) { |
---|
870 | | - printk(KERN_CONT "RX(0x%02x):", rx); |
---|
871 | | - for (tx = 0x0; tx <= MAX_DELAYLINE; tx++) { |
---|
| 887 | + for (rx = 0x0; rx <= lb_priv->max_delay; rx++) { |
---|
| 888 | + if (phy_iface == PHY_INTERFACE_MODE_RGMII_RXID) |
---|
| 889 | + rx = -1; |
---|
| 890 | + printk(KERN_CONT "RX(%03d):", rx); |
---|
| 891 | + for (tx = 0x0; tx <= lb_priv->max_delay; tx++) { |
---|
872 | 892 | if (!dwmac_rk_loopback_with_identify(priv, |
---|
873 | 893 | lb_priv, tx, rx)) { |
---|
874 | 894 | tx_sum += tx; |
---|
.. | .. |
---|
880 | 900 | } |
---|
881 | 901 | } |
---|
882 | 902 | printk(KERN_CONT "\n"); |
---|
| 903 | + |
---|
| 904 | + if (phy_iface == PHY_INTERFACE_MODE_RGMII_RXID) |
---|
| 905 | + break; |
---|
883 | 906 | } |
---|
884 | 907 | |
---|
885 | 908 | if (tx_sum && rx_sum && count) { |
---|
886 | 909 | tx_mid = tx_sum / count; |
---|
887 | 910 | rx_mid = rx_sum / count; |
---|
888 | 911 | |
---|
889 | | - if (dwmac_rk_delayline_is_valid(tx_mid, rx_mid)) { |
---|
890 | | - lb_priv->final_tx = tx_mid; |
---|
891 | | - lb_priv->final_rx = rx_mid; |
---|
892 | | - ret = 0; |
---|
| 912 | + if (phy_iface == PHY_INTERFACE_MODE_RGMII_RXID) { |
---|
| 913 | + if (dwmac_rk_delayline_is_txvalid(lb_priv, tx_mid)) { |
---|
| 914 | + lb_priv->final_tx = tx_mid; |
---|
| 915 | + lb_priv->final_rx = -1; |
---|
| 916 | + ret = 0; |
---|
| 917 | + } |
---|
| 918 | + } else { |
---|
| 919 | + if (dwmac_rk_delayline_is_valid(lb_priv, tx_mid, rx_mid)) { |
---|
| 920 | + lb_priv->final_tx = tx_mid; |
---|
| 921 | + lb_priv->final_rx = rx_mid; |
---|
| 922 | + ret = 0; |
---|
| 923 | + } |
---|
893 | 924 | } |
---|
894 | 925 | } |
---|
895 | 926 | |
---|
896 | | - if (ret) |
---|
| 927 | + if (ret) { |
---|
897 | 928 | pr_err("\nCan't find suitable delayline\n"); |
---|
898 | | - else |
---|
899 | | - pr_info("\nFind suitable tx_delay = 0x%02x, rx_delay = 0x%02x\n", |
---|
900 | | - lb_priv->final_tx, lb_priv->final_rx); |
---|
| 929 | + } else { |
---|
| 930 | + if (phy_iface == PHY_INTERFACE_MODE_RGMII_RXID) |
---|
| 931 | + pr_info("Find available tx_delay = 0x%02x, rx_delay = disable\n", |
---|
| 932 | + lb_priv->final_tx); |
---|
| 933 | + else |
---|
| 934 | + pr_info("\nFind suitable tx_delay = 0x%02x, rx_delay = 0x%02x\n", |
---|
| 935 | + lb_priv->final_tx, lb_priv->final_rx); |
---|
| 936 | + } |
---|
901 | 937 | |
---|
902 | 938 | return ret; |
---|
903 | 939 | } |
---|
.. | .. |
---|
1173 | 1209 | dwmac_rk_free_dma_desc_resources(priv, lb_priv); |
---|
1174 | 1210 | } |
---|
1175 | 1211 | |
---|
| 1212 | +static int dwmac_rk_get_max_delayline(struct stmmac_priv *priv) |
---|
| 1213 | +{ |
---|
| 1214 | + return MAX_DELAYLINE; |
---|
| 1215 | +} |
---|
| 1216 | + |
---|
1176 | 1217 | static int dwmac_rk_loopback_run(struct stmmac_priv *priv, |
---|
1177 | 1218 | struct dwmac_rk_lb_priv *lb_priv) |
---|
1178 | 1219 | { |
---|
.. | .. |
---|
1183 | 1224 | |
---|
1184 | 1225 | if (!ndev || !priv->mii) |
---|
1185 | 1226 | return -EINVAL; |
---|
| 1227 | + |
---|
| 1228 | + lb_priv->max_delay = dwmac_rk_get_max_delayline(priv); |
---|
1186 | 1229 | |
---|
1187 | 1230 | rtnl_lock(); |
---|
1188 | 1231 | /* check the netdevice up or not */ |
---|
.. | .. |
---|
1224 | 1267 | if (lb_priv->scan) { |
---|
1225 | 1268 | /* scan only support for rgmii mode */ |
---|
1226 | 1269 | if (phy_iface != PHY_INTERFACE_MODE_RGMII && |
---|
1227 | | - phy_iface != PHY_INTERFACE_MODE_RGMII_ID) { |
---|
| 1270 | + phy_iface != PHY_INTERFACE_MODE_RGMII_ID && |
---|
| 1271 | + phy_iface != PHY_INTERFACE_MODE_RGMII_RXID && |
---|
| 1272 | + phy_iface != PHY_INTERFACE_MODE_RGMII_TXID) { |
---|
1228 | 1273 | ret = -EINVAL; |
---|
1229 | 1274 | goto out; |
---|
1230 | 1275 | } |
---|
.. | .. |
---|
1286 | 1331 | *data = 0; |
---|
1287 | 1332 | data++; |
---|
1288 | 1333 | |
---|
1289 | | - if (kstrtoint(tmp, 0, &tx) || tx > MAX_DELAYLINE) |
---|
| 1334 | + if (kstrtoint(tmp, 0, &tx) || tx > dwmac_rk_get_max_delayline(priv)) |
---|
1290 | 1335 | goto out; |
---|
1291 | 1336 | |
---|
1292 | | - if (kstrtoint(data, 0, &rx) || rx > MAX_DELAYLINE) |
---|
| 1337 | + if (kstrtoint(data, 0, &rx) || rx > dwmac_rk_get_max_delayline(priv)) |
---|
1293 | 1338 | goto out; |
---|
1294 | 1339 | |
---|
1295 | 1340 | dwmac_rk_set_rgmii_delayline(priv, tx, rx); |
---|