Skip to content

Commit

Permalink
stmmac: add HW DMA feature register (v3)
Browse files Browse the repository at this point in the history
New GMAC chips have an extra register to indicate
the presence of the optional features/functions of
the DMA core.

This patch adds this support and all the HW cap
are exported via debugfs.

Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Giuseppe CAVALLARO authored and David S. Miller committed Sep 15, 2011
1 parent f0b9d78 commit e743482
Show file tree
Hide file tree
Showing 6 changed files with 174 additions and 1 deletion.
3 changes: 2 additions & 1 deletion drivers/net/ethernet/stmicro/stmmac/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ config STMMAC_DEBUG_FS
default n
depends on STMMAC_ETH && DEBUG_FS
-- help
The stmmac entry in /sys reports DMA TX/RX rings.
The stmmac entry in /sys reports DMA TX/RX rings
or (if supported) the HW cap register.

config STMMAC_DA
bool "STMMAC DMA arbitration scheme"
Expand Down
33 changes: 33 additions & 0 deletions drivers/net/ethernet/stmicro/stmmac/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,37 @@ enum tx_dma_irq_status {
handle_tx_rx = 3,
};

/* DMA HW capabilities */
struct dma_features {
unsigned int mbps_10_100;
unsigned int mbps_1000;
unsigned int half_duplex;
unsigned int hash_filter;
unsigned int multi_addr;
unsigned int pcs;
unsigned int sma_mdio;
unsigned int pmt_remote_wake_up;
unsigned int pmt_magic_frame;
unsigned int rmon;
/* IEEE 1588-2002*/
unsigned int time_stamp;
/* IEEE 1588-2008*/
unsigned int atime_stamp;
/* 802.3az - Energy-Efficient Ethernet (EEE) */
unsigned int eee;
unsigned int av;
/* TX and RX csum */
unsigned int tx_coe;
unsigned int rx_coe_type1;
unsigned int rx_coe_type2;
unsigned int rxfifo_over_2048;
/* TX and RX number of channels */
unsigned int number_rx_channel;
unsigned int number_tx_channel;
/* Alternate (enhanced) DESC mode*/
unsigned int enh_desc;
};

/* GMAC TX FIFO is 8K, Rx FIFO is 16K */
#define BUF_SIZE_16KiB 16384
#define BUF_SIZE_8KiB 8192
Expand Down Expand Up @@ -188,6 +219,8 @@ struct stmmac_dma_ops {
void (*stop_rx) (void __iomem *ioaddr);
int (*dma_interrupt) (void __iomem *ioaddr,
struct stmmac_extra_stats *x);
/* If supported then get the optional core features */
unsigned int (*get_hw_feature) (void __iomem *ioaddr);
};

struct stmmac_ops {
Expand Down
6 changes: 6 additions & 0 deletions drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@ static void dwmac1000_dump_dma_regs(void __iomem *ioaddr)
}
}

static unsigned int dwmac1000_get_hw_feature(void __iomem *ioaddr)
{
return readl(ioaddr + DMA_HW_FEATURE);
}

const struct stmmac_dma_ops dwmac1000_dma_ops = {
.init = dwmac1000_dma_init,
.dump_regs = dwmac1000_dump_dma_regs,
Expand All @@ -144,4 +149,5 @@ const struct stmmac_dma_ops dwmac1000_dma_ops = {
.start_rx = dwmac_dma_start_rx,
.stop_rx = dwmac_dma_stop_rx,
.dma_interrupt = dwmac_dma_interrupt,
.get_hw_feature = dwmac1000_get_hw_feature,
};
1 change: 1 addition & 0 deletions drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#define DMA_MISSED_FRAME_CTR 0x00001020 /* Missed Frame Counter */
#define DMA_CUR_TX_BUF_ADDR 0x00001050 /* Current Host Tx Buffer */
#define DMA_CUR_RX_BUF_ADDR 0x00001054 /* Current Host Rx Buffer */
#define DMA_HW_FEATURE 0x00001058 /* HW Feature Register */

/* DMA Control register defines */
#define DMA_CONTROL_ST 0x00002000 /* Start/Stop Transmission */
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/stmicro/stmmac/stmmac.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ struct stmmac_priv {
#endif
struct plat_stmmacenet_data *plat;
struct stmmac_counters mmc;
struct dma_features dma_cap;
};

extern int stmmac_mdio_unregister(struct net_device *ndev);
Expand Down
131 changes: 131 additions & 0 deletions drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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 */
Expand All @@ -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 */
Expand Down

0 comments on commit e743482

Please sign in to comment.