diff options
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/Kconfig | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/common.h | 33 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c | 6 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 131 |
6 files changed, 174 insertions, 1 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig index ae7f56312f0..2e35be7ccfa 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig | |||
@@ -16,7 +16,8 @@ config STMMAC_DEBUG_FS | |||
16 | default n | 16 | default n |
17 | depends on STMMAC_ETH && DEBUG_FS | 17 | depends on STMMAC_ETH && DEBUG_FS |
18 | -- help | 18 | -- help |
19 | The stmmac entry in /sys reports DMA TX/RX rings. | 19 | The stmmac entry in /sys reports DMA TX/RX rings |
20 | or (if supported) the HW cap register. | ||
20 | 21 | ||
21 | config STMMAC_DA | 22 | config STMMAC_DA |
22 | bool "STMMAC DMA arbitration scheme" | 23 | bool "STMMAC DMA arbitration scheme" |
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index 65b1e56a97c..22c61b2ebfa 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h | |||
@@ -116,6 +116,37 @@ enum tx_dma_irq_status { | |||
116 | handle_tx_rx = 3, | 116 | handle_tx_rx = 3, |
117 | }; | 117 | }; |
118 | 118 | ||
119 | /* DMA HW capabilities */ | ||
120 | struct dma_features { | ||
121 | unsigned int mbps_10_100; | ||
122 | unsigned int mbps_1000; | ||
123 | unsigned int half_duplex; | ||
124 | unsigned int hash_filter; | ||
125 | unsigned int multi_addr; | ||
126 | unsigned int pcs; | ||
127 | unsigned int sma_mdio; | ||
128 | unsigned int pmt_remote_wake_up; | ||
129 | unsigned int pmt_magic_frame; | ||
130 | unsigned int rmon; | ||
131 | /* IEEE 1588-2002*/ | ||
132 | unsigned int time_stamp; | ||
133 | /* IEEE 1588-2008*/ | ||
134 | unsigned int atime_stamp; | ||
135 | /* 802.3az - Energy-Efficient Ethernet (EEE) */ | ||
136 | unsigned int eee; | ||
137 | unsigned int av; | ||
138 | /* TX and RX csum */ | ||
139 | unsigned int tx_coe; | ||
140 | unsigned int rx_coe_type1; | ||
141 | unsigned int rx_coe_type2; | ||
142 | unsigned int rxfifo_over_2048; | ||
143 | /* TX and RX number of channels */ | ||
144 | unsigned int number_rx_channel; | ||
145 | unsigned int number_tx_channel; | ||
146 | /* Alternate (enhanced) DESC mode*/ | ||
147 | unsigned int enh_desc; | ||
148 | }; | ||
149 | |||
119 | /* GMAC TX FIFO is 8K, Rx FIFO is 16K */ | 150 | /* GMAC TX FIFO is 8K, Rx FIFO is 16K */ |
120 | #define BUF_SIZE_16KiB 16384 | 151 | #define BUF_SIZE_16KiB 16384 |
121 | #define BUF_SIZE_8KiB 8192 | 152 | #define BUF_SIZE_8KiB 8192 |
@@ -188,6 +219,8 @@ struct stmmac_dma_ops { | |||
188 | void (*stop_rx) (void __iomem *ioaddr); | 219 | void (*stop_rx) (void __iomem *ioaddr); |
189 | int (*dma_interrupt) (void __iomem *ioaddr, | 220 | int (*dma_interrupt) (void __iomem *ioaddr, |
190 | struct stmmac_extra_stats *x); | 221 | struct stmmac_extra_stats *x); |
222 | /* If supported then get the optional core features */ | ||
223 | unsigned int (*get_hw_feature) (void __iomem *ioaddr); | ||
191 | }; | 224 | }; |
192 | 225 | ||
193 | struct stmmac_ops { | 226 | struct stmmac_ops { |
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c index a89384c0751..da66ac511c4 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c | |||
@@ -132,6 +132,11 @@ static void dwmac1000_dump_dma_regs(void __iomem *ioaddr) | |||
132 | } | 132 | } |
133 | } | 133 | } |
134 | 134 | ||
135 | static unsigned int dwmac1000_get_hw_feature(void __iomem *ioaddr) | ||
136 | { | ||
137 | return readl(ioaddr + DMA_HW_FEATURE); | ||
138 | } | ||
139 | |||
135 | const struct stmmac_dma_ops dwmac1000_dma_ops = { | 140 | const struct stmmac_dma_ops dwmac1000_dma_ops = { |
136 | .init = dwmac1000_dma_init, | 141 | .init = dwmac1000_dma_init, |
137 | .dump_regs = dwmac1000_dump_dma_regs, | 142 | .dump_regs = dwmac1000_dump_dma_regs, |
@@ -144,4 +149,5 @@ const struct stmmac_dma_ops dwmac1000_dma_ops = { | |||
144 | .start_rx = dwmac_dma_start_rx, | 149 | .start_rx = dwmac_dma_start_rx, |
145 | .stop_rx = dwmac_dma_stop_rx, | 150 | .stop_rx = dwmac_dma_stop_rx, |
146 | .dma_interrupt = dwmac_dma_interrupt, | 151 | .dma_interrupt = dwmac_dma_interrupt, |
152 | .get_hw_feature = dwmac1000_get_hw_feature, | ||
147 | }; | 153 | }; |
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h index da3f5ccf83d..437edacd602 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h | |||
@@ -34,6 +34,7 @@ | |||
34 | #define DMA_MISSED_FRAME_CTR 0x00001020 /* Missed Frame Counter */ | 34 | #define DMA_MISSED_FRAME_CTR 0x00001020 /* Missed Frame Counter */ |
35 | #define DMA_CUR_TX_BUF_ADDR 0x00001050 /* Current Host Tx Buffer */ | 35 | #define DMA_CUR_TX_BUF_ADDR 0x00001050 /* Current Host Tx Buffer */ |
36 | #define DMA_CUR_RX_BUF_ADDR 0x00001054 /* Current Host Rx Buffer */ | 36 | #define DMA_CUR_RX_BUF_ADDR 0x00001054 /* Current Host Rx Buffer */ |
37 | #define DMA_HW_FEATURE 0x00001058 /* HW Feature Register */ | ||
37 | 38 | ||
38 | /* DMA Control register defines */ | 39 | /* DMA Control register defines */ |
39 | #define DMA_CONTROL_ST 0x00002000 /* Start/Stop Transmission */ | 40 | #define DMA_CONTROL_ST 0x00002000 /* Start/Stop Transmission */ |
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index ef037965493..c3a2da71d1e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h | |||
@@ -78,6 +78,7 @@ struct stmmac_priv { | |||
78 | #endif | 78 | #endif |
79 | struct plat_stmmacenet_data *plat; | 79 | struct plat_stmmacenet_data *plat; |
80 | struct stmmac_counters mmc; | 80 | struct stmmac_counters mmc; |
81 | struct dma_features dma_cap; | ||
81 | }; | 82 | }; |
82 | 83 | ||
83 | extern int stmmac_mdio_unregister(struct net_device *ndev); | 84 | extern int stmmac_mdio_unregister(struct net_device *ndev); |
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index eb210ca2497..d0fbc5477d1 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | |||
@@ -780,6 +780,49 @@ static u32 stmmac_get_synopsys_id(struct stmmac_priv *priv) | |||
780 | } | 780 | } |
781 | return 0; | 781 | return 0; |
782 | } | 782 | } |
783 | |||
784 | /* New GMAC chips support a new register to indicate the | ||
785 | * presence of the optional feature/functions. | ||
786 | */ | ||
787 | static int stmmac_get_hw_features(struct stmmac_priv *priv) | ||
788 | { | ||
789 | u32 hw_cap = priv->hw->dma->get_hw_feature(priv->ioaddr); | ||
790 | |||
791 | if (likely(hw_cap)) { | ||
792 | priv->dma_cap.mbps_10_100 = (hw_cap & 0x1); | ||
793 | priv->dma_cap.mbps_1000 = (hw_cap & 0x2) >> 1; | ||
794 | priv->dma_cap.half_duplex = (hw_cap & 0x4) >> 2; | ||
795 | priv->dma_cap.hash_filter = (hw_cap & 0x10) >> 4; | ||
796 | priv->dma_cap.multi_addr = (hw_cap & 0x20) >> 5; | ||
797 | priv->dma_cap.pcs = (hw_cap & 0x40) >> 6; | ||
798 | priv->dma_cap.sma_mdio = (hw_cap & 0x100) >> 8; | ||
799 | priv->dma_cap.pmt_remote_wake_up = (hw_cap & 0x200) >> 9; | ||
800 | priv->dma_cap.pmt_magic_frame = (hw_cap & 0x400) >> 10; | ||
801 | priv->dma_cap.rmon = (hw_cap & 0x800) >> 11; /* MMC */ | ||
802 | /* IEEE 1588-2002*/ | ||
803 | priv->dma_cap.time_stamp = (hw_cap & 0x1000) >> 12; | ||
804 | /* IEEE 1588-2008*/ | ||
805 | priv->dma_cap.atime_stamp = (hw_cap & 0x2000) >> 13; | ||
806 | /* 802.3az - Energy-Efficient Ethernet (EEE) */ | ||
807 | priv->dma_cap.eee = (hw_cap & 0x4000) >> 14; | ||
808 | priv->dma_cap.av = (hw_cap & 0x8000) >> 15; | ||
809 | /* TX and RX csum */ | ||
810 | priv->dma_cap.tx_coe = (hw_cap & 0x10000) >> 16; | ||
811 | priv->dma_cap.rx_coe_type1 = (hw_cap & 0x20000) >> 17; | ||
812 | priv->dma_cap.rx_coe_type2 = (hw_cap & 0x40000) >> 18; | ||
813 | priv->dma_cap.rxfifo_over_2048 = (hw_cap & 0x80000) >> 19; | ||
814 | /* TX and RX number of channels */ | ||
815 | priv->dma_cap.number_rx_channel = (hw_cap & 0x300000) >> 20; | ||
816 | priv->dma_cap.number_tx_channel = (hw_cap & 0xc00000) >> 22; | ||
817 | /* Alternate (enhanced) DESC mode*/ | ||
818 | priv->dma_cap.enh_desc = (hw_cap & 0x1000000) >> 24; | ||
819 | |||
820 | } else | ||
821 | pr_debug("\tNo HW DMA feature register supported"); | ||
822 | |||
823 | return hw_cap; | ||
824 | } | ||
825 | |||
783 | /** | 826 | /** |
784 | * stmmac_open - open entry point of the driver | 827 | * stmmac_open - open entry point of the driver |
785 | * @dev : pointer to the device structure. | 828 | * @dev : pointer to the device structure. |
@@ -854,6 +897,8 @@ static int stmmac_open(struct net_device *dev) | |||
854 | 897 | ||
855 | stmmac_get_synopsys_id(priv); | 898 | stmmac_get_synopsys_id(priv); |
856 | 899 | ||
900 | stmmac_get_hw_features(priv); | ||
901 | |||
857 | if (priv->rx_coe) | 902 | if (priv->rx_coe) |
858 | pr_info("stmmac: Rx Checksum Offload Engine supported\n"); | 903 | pr_info("stmmac: Rx Checksum Offload Engine supported\n"); |
859 | if (priv->plat->tx_coe) | 904 | if (priv->plat->tx_coe) |
@@ -1450,6 +1495,7 @@ static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | |||
1450 | #ifdef CONFIG_STMMAC_DEBUG_FS | 1495 | #ifdef CONFIG_STMMAC_DEBUG_FS |
1451 | static struct dentry *stmmac_fs_dir; | 1496 | static struct dentry *stmmac_fs_dir; |
1452 | static struct dentry *stmmac_rings_status; | 1497 | static struct dentry *stmmac_rings_status; |
1498 | static struct dentry *stmmac_dma_cap; | ||
1453 | 1499 | ||
1454 | static int stmmac_sysfs_ring_read(struct seq_file *seq, void *v) | 1500 | static int stmmac_sysfs_ring_read(struct seq_file *seq, void *v) |
1455 | { | 1501 | { |
@@ -1503,6 +1549,78 @@ static const struct file_operations stmmac_rings_status_fops = { | |||
1503 | .release = seq_release, | 1549 | .release = seq_release, |
1504 | }; | 1550 | }; |
1505 | 1551 | ||
1552 | static int stmmac_sysfs_dma_cap_read(struct seq_file *seq, void *v) | ||
1553 | { | ||
1554 | struct net_device *dev = seq->private; | ||
1555 | struct stmmac_priv *priv = netdev_priv(dev); | ||
1556 | |||
1557 | if (!stmmac_get_hw_features(priv)) { | ||
1558 | seq_printf(seq, "DMA HW features not supported\n"); | ||
1559 | return 0; | ||
1560 | } | ||
1561 | |||
1562 | seq_printf(seq, "==============================\n"); | ||
1563 | seq_printf(seq, "\tDMA HW features\n"); | ||
1564 | seq_printf(seq, "==============================\n"); | ||
1565 | |||
1566 | seq_printf(seq, "\t10/100 Mbps %s\n", | ||
1567 | (priv->dma_cap.mbps_10_100) ? "Y" : "N"); | ||
1568 | seq_printf(seq, "\t1000 Mbps %s\n", | ||
1569 | (priv->dma_cap.mbps_1000) ? "Y" : "N"); | ||
1570 | seq_printf(seq, "\tHalf duple %s\n", | ||
1571 | (priv->dma_cap.half_duplex) ? "Y" : "N"); | ||
1572 | seq_printf(seq, "\tHash Filter: %s\n", | ||
1573 | (priv->dma_cap.hash_filter) ? "Y" : "N"); | ||
1574 | seq_printf(seq, "\tMultiple MAC address registers: %s\n", | ||
1575 | (priv->dma_cap.multi_addr) ? "Y" : "N"); | ||
1576 | seq_printf(seq, "\tPCS (TBI/SGMII/RTBI PHY interfatces): %s\n", | ||
1577 | (priv->dma_cap.pcs) ? "Y" : "N"); | ||
1578 | seq_printf(seq, "\tSMA (MDIO) Interface: %s\n", | ||
1579 | (priv->dma_cap.sma_mdio) ? "Y" : "N"); | ||
1580 | seq_printf(seq, "\tPMT Remote wake up: %s\n", | ||
1581 | (priv->dma_cap.pmt_remote_wake_up) ? "Y" : "N"); | ||
1582 | seq_printf(seq, "\tPMT Magic Frame: %s\n", | ||
1583 | (priv->dma_cap.pmt_magic_frame) ? "Y" : "N"); | ||
1584 | seq_printf(seq, "\tRMON module: %s\n", | ||
1585 | (priv->dma_cap.rmon) ? "Y" : "N"); | ||
1586 | seq_printf(seq, "\tIEEE 1588-2002 Time Stamp: %s\n", | ||
1587 | (priv->dma_cap.time_stamp) ? "Y" : "N"); | ||
1588 | seq_printf(seq, "\tIEEE 1588-2008 Advanced Time Stamp:%s\n", | ||
1589 | (priv->dma_cap.atime_stamp) ? "Y" : "N"); | ||
1590 | seq_printf(seq, "\t802.3az - Energy-Efficient Ethernet (EEE) %s\n", | ||
1591 | (priv->dma_cap.eee) ? "Y" : "N"); | ||
1592 | seq_printf(seq, "\tAV features: %s\n", (priv->dma_cap.av) ? "Y" : "N"); | ||
1593 | seq_printf(seq, "\tChecksum Offload in TX: %s\n", | ||
1594 | (priv->dma_cap.tx_coe) ? "Y" : "N"); | ||
1595 | seq_printf(seq, "\tIP Checksum Offload (type1) in RX: %s\n", | ||
1596 | (priv->dma_cap.rx_coe_type1) ? "Y" : "N"); | ||
1597 | seq_printf(seq, "\tIP Checksum Offload (type2) in RX: %s\n", | ||
1598 | (priv->dma_cap.rx_coe_type2) ? "Y" : "N"); | ||
1599 | seq_printf(seq, "\tRXFIFO > 2048bytes: %s\n", | ||
1600 | (priv->dma_cap.rxfifo_over_2048) ? "Y" : "N"); | ||
1601 | seq_printf(seq, "\tNumber of Additional RX channel: %d\n", | ||
1602 | priv->dma_cap.number_rx_channel); | ||
1603 | seq_printf(seq, "\tNumber of Additional TX channel: %d\n", | ||
1604 | priv->dma_cap.number_tx_channel); | ||
1605 | seq_printf(seq, "\tEnhanced descriptors: %s\n", | ||
1606 | (priv->dma_cap.enh_desc) ? "Y" : "N"); | ||
1607 | |||
1608 | return 0; | ||
1609 | } | ||
1610 | |||
1611 | static int stmmac_sysfs_dma_cap_open(struct inode *inode, struct file *file) | ||
1612 | { | ||
1613 | return single_open(file, stmmac_sysfs_dma_cap_read, inode->i_private); | ||
1614 | } | ||
1615 | |||
1616 | static const struct file_operations stmmac_dma_cap_fops = { | ||
1617 | .owner = THIS_MODULE, | ||
1618 | .open = stmmac_sysfs_dma_cap_open, | ||
1619 | .read = seq_read, | ||
1620 | .llseek = seq_lseek, | ||
1621 | .release = seq_release, | ||
1622 | }; | ||
1623 | |||
1506 | static int stmmac_init_fs(struct net_device *dev) | 1624 | static int stmmac_init_fs(struct net_device *dev) |
1507 | { | 1625 | { |
1508 | /* Create debugfs entries */ | 1626 | /* Create debugfs entries */ |
@@ -1527,12 +1645,25 @@ static int stmmac_init_fs(struct net_device *dev) | |||
1527 | return -ENOMEM; | 1645 | return -ENOMEM; |
1528 | } | 1646 | } |
1529 | 1647 | ||
1648 | /* Entry to report the DMA HW features */ | ||
1649 | stmmac_dma_cap = debugfs_create_file("dma_cap", S_IRUGO, stmmac_fs_dir, | ||
1650 | dev, &stmmac_dma_cap_fops); | ||
1651 | |||
1652 | if (!stmmac_dma_cap || IS_ERR(stmmac_dma_cap)) { | ||
1653 | pr_info("ERROR creating stmmac MMC debugfs file\n"); | ||
1654 | debugfs_remove(stmmac_rings_status); | ||
1655 | debugfs_remove(stmmac_fs_dir); | ||
1656 | |||
1657 | return -ENOMEM; | ||
1658 | } | ||
1659 | |||
1530 | return 0; | 1660 | return 0; |
1531 | } | 1661 | } |
1532 | 1662 | ||
1533 | static void stmmac_exit_fs(void) | 1663 | static void stmmac_exit_fs(void) |
1534 | { | 1664 | { |
1535 | debugfs_remove(stmmac_rings_status); | 1665 | debugfs_remove(stmmac_rings_status); |
1666 | debugfs_remove(stmmac_dma_cap); | ||
1536 | debugfs_remove(stmmac_fs_dir); | 1667 | debugfs_remove(stmmac_fs_dir); |
1537 | } | 1668 | } |
1538 | #endif /* CONFIG_STMMAC_DEBUG_FS */ | 1669 | #endif /* CONFIG_STMMAC_DEBUG_FS */ |