| .. | .. |
|---|
| 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); |
|---|