|
@@ -780,6 +780,49 @@ static u32 stmmac_get_synopsys_id(struct stmmac_priv *priv)
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
|
+
|
|
|
+/* New GMAC chips support a new register to indicate the
|
|
|
+ * presence of the optional feature/functions.
|
|
|
+ */
|
|
|
+static int stmmac_get_hw_features(struct stmmac_priv *priv)
|
|
|
+{
|
|
|
+ u32 hw_cap = priv->hw->dma->get_hw_feature(priv->ioaddr);
|
|
|
+
|
|
|
+ if (likely(hw_cap)) {
|
|
|
+ priv->dma_cap.mbps_10_100 = (hw_cap & 0x1);
|
|
|
+ priv->dma_cap.mbps_1000 = (hw_cap & 0x2) >> 1;
|
|
|
+ priv->dma_cap.half_duplex = (hw_cap & 0x4) >> 2;
|
|
|
+ priv->dma_cap.hash_filter = (hw_cap & 0x10) >> 4;
|
|
|
+ priv->dma_cap.multi_addr = (hw_cap & 0x20) >> 5;
|
|
|
+ priv->dma_cap.pcs = (hw_cap & 0x40) >> 6;
|
|
|
+ priv->dma_cap.sma_mdio = (hw_cap & 0x100) >> 8;
|
|
|
+ priv->dma_cap.pmt_remote_wake_up = (hw_cap & 0x200) >> 9;
|
|
|
+ priv->dma_cap.pmt_magic_frame = (hw_cap & 0x400) >> 10;
|
|
|
+ priv->dma_cap.rmon = (hw_cap & 0x800) >> 11; /* MMC */
|
|
|
+ /* IEEE 1588-2002*/
|
|
|
+ priv->dma_cap.time_stamp = (hw_cap & 0x1000) >> 12;
|
|
|
+ /* IEEE 1588-2008*/
|
|
|
+ priv->dma_cap.atime_stamp = (hw_cap & 0x2000) >> 13;
|
|
|
+ /* 802.3az - Energy-Efficient Ethernet (EEE) */
|
|
|
+ priv->dma_cap.eee = (hw_cap & 0x4000) >> 14;
|
|
|
+ priv->dma_cap.av = (hw_cap & 0x8000) >> 15;
|
|
|
+ /* TX and RX csum */
|
|
|
+ priv->dma_cap.tx_coe = (hw_cap & 0x10000) >> 16;
|
|
|
+ priv->dma_cap.rx_coe_type1 = (hw_cap & 0x20000) >> 17;
|
|
|
+ priv->dma_cap.rx_coe_type2 = (hw_cap & 0x40000) >> 18;
|
|
|
+ priv->dma_cap.rxfifo_over_2048 = (hw_cap & 0x80000) >> 19;
|
|
|
+ /* TX and RX number of channels */
|
|
|
+ priv->dma_cap.number_rx_channel = (hw_cap & 0x300000) >> 20;
|
|
|
+ priv->dma_cap.number_tx_channel = (hw_cap & 0xc00000) >> 22;
|
|
|
+ /* Alternate (enhanced) DESC mode*/
|
|
|
+ priv->dma_cap.enh_desc = (hw_cap & 0x1000000) >> 24;
|
|
|
+
|
|
|
+ } else
|
|
|
+ pr_debug("\tNo HW DMA feature register supported");
|
|
|
+
|
|
|
+ return hw_cap;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* stmmac_open - open entry point of the driver
|
|
|
* @dev : pointer to the device structure.
|
|
@@ -854,6 +897,8 @@ static int stmmac_open(struct net_device *dev)
|
|
|
|
|
|
stmmac_get_synopsys_id(priv);
|
|
|
|
|
|
+ stmmac_get_hw_features(priv);
|
|
|
+
|
|
|
if (priv->rx_coe)
|
|
|
pr_info("stmmac: Rx Checksum Offload Engine supported\n");
|
|
|
if (priv->plat->tx_coe)
|
|
@@ -1450,6 +1495,7 @@ static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
|
|
|
#ifdef CONFIG_STMMAC_DEBUG_FS
|
|
|
static struct dentry *stmmac_fs_dir;
|
|
|
static struct dentry *stmmac_rings_status;
|
|
|
+static struct dentry *stmmac_dma_cap;
|
|
|
|
|
|
static int stmmac_sysfs_ring_read(struct seq_file *seq, void *v)
|
|
|
{
|
|
@@ -1503,6 +1549,78 @@ static const struct file_operations stmmac_rings_status_fops = {
|
|
|
.release = seq_release,
|
|
|
};
|
|
|
|
|
|
+static int stmmac_sysfs_dma_cap_read(struct seq_file *seq, void *v)
|
|
|
+{
|
|
|
+ struct net_device *dev = seq->private;
|
|
|
+ struct stmmac_priv *priv = netdev_priv(dev);
|
|
|
+
|
|
|
+ if (!stmmac_get_hw_features(priv)) {
|
|
|
+ seq_printf(seq, "DMA HW features not supported\n");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ seq_printf(seq, "==============================\n");
|
|
|
+ seq_printf(seq, "\tDMA HW features\n");
|
|
|
+ seq_printf(seq, "==============================\n");
|
|
|
+
|
|
|
+ seq_printf(seq, "\t10/100 Mbps %s\n",
|
|
|
+ (priv->dma_cap.mbps_10_100) ? "Y" : "N");
|
|
|
+ seq_printf(seq, "\t1000 Mbps %s\n",
|
|
|
+ (priv->dma_cap.mbps_1000) ? "Y" : "N");
|
|
|
+ seq_printf(seq, "\tHalf duple %s\n",
|
|
|
+ (priv->dma_cap.half_duplex) ? "Y" : "N");
|
|
|
+ seq_printf(seq, "\tHash Filter: %s\n",
|
|
|
+ (priv->dma_cap.hash_filter) ? "Y" : "N");
|
|
|
+ seq_printf(seq, "\tMultiple MAC address registers: %s\n",
|
|
|
+ (priv->dma_cap.multi_addr) ? "Y" : "N");
|
|
|
+ seq_printf(seq, "\tPCS (TBI/SGMII/RTBI PHY interfatces): %s\n",
|
|
|
+ (priv->dma_cap.pcs) ? "Y" : "N");
|
|
|
+ seq_printf(seq, "\tSMA (MDIO) Interface: %s\n",
|
|
|
+ (priv->dma_cap.sma_mdio) ? "Y" : "N");
|
|
|
+ seq_printf(seq, "\tPMT Remote wake up: %s\n",
|
|
|
+ (priv->dma_cap.pmt_remote_wake_up) ? "Y" : "N");
|
|
|
+ seq_printf(seq, "\tPMT Magic Frame: %s\n",
|
|
|
+ (priv->dma_cap.pmt_magic_frame) ? "Y" : "N");
|
|
|
+ seq_printf(seq, "\tRMON module: %s\n",
|
|
|
+ (priv->dma_cap.rmon) ? "Y" : "N");
|
|
|
+ seq_printf(seq, "\tIEEE 1588-2002 Time Stamp: %s\n",
|
|
|
+ (priv->dma_cap.time_stamp) ? "Y" : "N");
|
|
|
+ seq_printf(seq, "\tIEEE 1588-2008 Advanced Time Stamp:%s\n",
|
|
|
+ (priv->dma_cap.atime_stamp) ? "Y" : "N");
|
|
|
+ seq_printf(seq, "\t802.3az - Energy-Efficient Ethernet (EEE) %s\n",
|
|
|
+ (priv->dma_cap.eee) ? "Y" : "N");
|
|
|
+ seq_printf(seq, "\tAV features: %s\n", (priv->dma_cap.av) ? "Y" : "N");
|
|
|
+ seq_printf(seq, "\tChecksum Offload in TX: %s\n",
|
|
|
+ (priv->dma_cap.tx_coe) ? "Y" : "N");
|
|
|
+ seq_printf(seq, "\tIP Checksum Offload (type1) in RX: %s\n",
|
|
|
+ (priv->dma_cap.rx_coe_type1) ? "Y" : "N");
|
|
|
+ seq_printf(seq, "\tIP Checksum Offload (type2) in RX: %s\n",
|
|
|
+ (priv->dma_cap.rx_coe_type2) ? "Y" : "N");
|
|
|
+ seq_printf(seq, "\tRXFIFO > 2048bytes: %s\n",
|
|
|
+ (priv->dma_cap.rxfifo_over_2048) ? "Y" : "N");
|
|
|
+ seq_printf(seq, "\tNumber of Additional RX channel: %d\n",
|
|
|
+ priv->dma_cap.number_rx_channel);
|
|
|
+ seq_printf(seq, "\tNumber of Additional TX channel: %d\n",
|
|
|
+ priv->dma_cap.number_tx_channel);
|
|
|
+ seq_printf(seq, "\tEnhanced descriptors: %s\n",
|
|
|
+ (priv->dma_cap.enh_desc) ? "Y" : "N");
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int stmmac_sysfs_dma_cap_open(struct inode *inode, struct file *file)
|
|
|
+{
|
|
|
+ return single_open(file, stmmac_sysfs_dma_cap_read, inode->i_private);
|
|
|
+}
|
|
|
+
|
|
|
+static const struct file_operations stmmac_dma_cap_fops = {
|
|
|
+ .owner = THIS_MODULE,
|
|
|
+ .open = stmmac_sysfs_dma_cap_open,
|
|
|
+ .read = seq_read,
|
|
|
+ .llseek = seq_lseek,
|
|
|
+ .release = seq_release,
|
|
|
+};
|
|
|
+
|
|
|
static int stmmac_init_fs(struct net_device *dev)
|
|
|
{
|
|
|
/* Create debugfs entries */
|
|
@@ -1527,12 +1645,25 @@ static int stmmac_init_fs(struct net_device *dev)
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
|
|
|
+ /* Entry to report the DMA HW features */
|
|
|
+ stmmac_dma_cap = debugfs_create_file("dma_cap", S_IRUGO, stmmac_fs_dir,
|
|
|
+ dev, &stmmac_dma_cap_fops);
|
|
|
+
|
|
|
+ if (!stmmac_dma_cap || IS_ERR(stmmac_dma_cap)) {
|
|
|
+ pr_info("ERROR creating stmmac MMC debugfs file\n");
|
|
|
+ debugfs_remove(stmmac_rings_status);
|
|
|
+ debugfs_remove(stmmac_fs_dir);
|
|
|
+
|
|
|
+ return -ENOMEM;
|
|
|
+ }
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
static void stmmac_exit_fs(void)
|
|
|
{
|
|
|
debugfs_remove(stmmac_rings_status);
|
|
|
+ debugfs_remove(stmmac_dma_cap);
|
|
|
debugfs_remove(stmmac_fs_dir);
|
|
|
}
|
|
|
#endif /* CONFIG_STMMAC_DEBUG_FS */
|