Skip to content

Commit

Permalink
stmmac: parameters auto-tuning through HW cap reg
Browse files Browse the repository at this point in the history
New GMAC devices (newer than the databook 3.50a) have the
HW capability register that provides which features are actually
supported by the hardware.

On old devices many information have to be passed through the
platform, for example: enhanced descriptor structure,
TX COE etc. These are mandatory to properly configure the driver.
This remains still valid because the driver has to support old
Synopsys devices but now it's also able to override them using the
values from the HW capability register if supported.

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 Nov 17, 2011
1 parent c5b9b4e commit 19e30c1
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 29 deletions.
2 changes: 1 addition & 1 deletion drivers/net/ethernet/stmicro/stmmac/stmmac.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,14 @@ struct stmmac_priv {
spinlock_t lock;
spinlock_t tx_lock;
int wolopts;
int wolenabled;
int wol_irq;
#ifdef CONFIG_STMMAC_TIMER
struct stmmac_timer *tm;
#endif
struct plat_stmmacenet_data *plat;
struct stmmac_counters mmc;
struct dma_features dma_cap;
int hw_cap_support;
};

extern int stmmac_mdio_unregister(struct net_device *ndev);
Expand Down
6 changes: 6 additions & 0 deletions drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,12 @@ static int stmmac_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
struct stmmac_priv *priv = netdev_priv(dev);
u32 support = WAKE_MAGIC | WAKE_UCAST;

/* By default almost all GMAC devices support the WoL via
* magic frame but we can disable it if the HW capability
* register shows no support for pmt_magic_frame. */
if ((priv->hw_cap_support) && (!priv->dma_cap.pmt_magic_frame))
wol->wolopts &= ~WAKE_MAGIC;

if (!device_can_wakeup(priv->device))
return -EINVAL;

Expand Down
93 changes: 65 additions & 28 deletions drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -805,8 +805,29 @@ 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.
/**
* stmmac_selec_desc_mode
* @dev : device pointer
* Description: select the Enhanced/Alternate or Normal descriptors */
static void stmmac_selec_desc_mode(struct stmmac_priv *priv)
{
if (priv->plat->enh_desc) {
pr_info(" Enhanced/Alternate descriptors\n");
priv->hw->desc = &enh_desc_ops;
} else {
pr_info(" Normal descriptors\n");
priv->hw->desc = &ndesc_ops;
}
}

/**
* stmmac_get_hw_features
* @priv : private device pointer
* Description:
* new GMAC chip generations have a new register to indicate the
* presence of the optional feature/functions.
* This can be also used to override the value passed through the
* platform and necessary for old MAC10/100 and GMAC chips.
*/
static int stmmac_get_hw_features(struct stmmac_priv *priv)
{
Expand All @@ -827,7 +848,7 @@ static int stmmac_get_hw_features(struct stmmac_priv *priv)
(hw_cap & DMA_HW_FEAT_RWKSEL) >> 9;
priv->dma_cap.pmt_magic_frame =
(hw_cap & DMA_HW_FEAT_MGKSEL) >> 10;
/*MMC*/
/* MMC */
priv->dma_cap.rmon = (hw_cap & DMA_HW_FEAT_MMCSEL) >> 11;
/* IEEE 1588-2002*/
priv->dma_cap.time_stamp =
Expand Down Expand Up @@ -855,8 +876,7 @@ static int stmmac_get_hw_features(struct stmmac_priv *priv)
priv->dma_cap.enh_desc =
(hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24;

} else
pr_debug("\tNo HW DMA feature register supported");
}

return hw_cap;
}
Expand Down Expand Up @@ -911,6 +931,44 @@ static int stmmac_open(struct net_device *dev)
goto open_error;
}

stmmac_get_synopsys_id(priv);

priv->hw_cap_support = stmmac_get_hw_features(priv);

if (priv->hw_cap_support) {
pr_info(" Support DMA HW capability register");

/* We can override some gmac/dma configuration fields: e.g.
* enh_desc, tx_coe (e.g. that are passed through the
* platform) with the values from the HW capability
* register (if supported).
*/
priv->plat->enh_desc = priv->dma_cap.enh_desc;
priv->plat->tx_coe = priv->dma_cap.tx_coe;
priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up;

/* By default disable wol on magic frame if not supported */
if (!priv->dma_cap.pmt_magic_frame)
priv->wolopts &= ~WAKE_MAGIC;

} else
pr_info(" No HW DMA feature register supported");

/* Select the enhnaced/normal descriptor structures */
stmmac_selec_desc_mode(priv);

/* PMT module is not integrated in all the MAC devices. */
if (priv->plat->pmt) {
pr_info(" Remote wake-up capable\n");
device_set_wakeup_capable(priv->device, 1);
}

priv->rx_coe = priv->hw->mac->rx_coe(priv->ioaddr);
if (priv->rx_coe)
pr_info(" Checksum Offload Engine supported\n");
if (priv->plat->tx_coe)
pr_info(" Checksum insertion supported\n");

/* Create and initialize the TX/RX descriptors chains. */
priv->dma_tx_size = STMMAC_ALIGN(dma_txsize);
priv->dma_rx_size = STMMAC_ALIGN(dma_rxsize);
Expand All @@ -933,15 +991,6 @@ static int stmmac_open(struct net_device *dev)
/* Initialize the MAC Core */
priv->hw->mac->core_init(priv->ioaddr);

stmmac_get_synopsys_id(priv);

stmmac_get_hw_features(priv);

priv->rx_coe = priv->hw->mac->rx_coe(priv->ioaddr);
if (priv->rx_coe)
pr_info("stmmac: Rx Checksum Offload Engine supported\n");
if (priv->plat->tx_coe)
pr_info("\tTX Checksum insertion supported\n");
netdev_update_features(dev);

/* Request the IRQ lines */
Expand Down Expand Up @@ -1556,7 +1605,7 @@ 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)) {
if (!priv->hw_cap_support) {
seq_printf(seq, "DMA HW features not supported\n");
return 0;
}
Expand Down Expand Up @@ -1764,12 +1813,6 @@ static int stmmac_mac_device_setup(struct net_device *dev)
if (!device)
return -ENOMEM;

if (priv->plat->enh_desc) {
device->desc = &enh_desc_ops;
pr_info("\tEnhanced descriptor structure\n");
} else
device->desc = &ndesc_ops;

priv->hw = device;
priv->hw->ring = &ring_mode_ops;

Expand Down Expand Up @@ -1843,11 +1886,6 @@ static int stmmac_dvr_probe(struct platform_device *pdev)

priv->ioaddr = addr;

/* PMT module is not integrated in all the MAC devices. */
if (plat_dat->pmt) {
pr_info("\tPMT module supported\n");
device_set_wakeup_capable(&pdev->dev, 1);
}
/*
* On some platforms e.g. SPEAr the wake up irq differs from the mac irq
* The external wake up irq can be passed through the platform code
Expand All @@ -1860,7 +1898,6 @@ static int stmmac_dvr_probe(struct platform_device *pdev)
if (priv->wol_irq == -ENXIO)
priv->wol_irq = ndev->irq;


platform_set_drvdata(pdev, ndev);

/* Set the I/O base addr */
Expand All @@ -1873,7 +1910,7 @@ static int stmmac_dvr_probe(struct platform_device *pdev)
goto out_free_ndev;
}

/* MAC HW revice detection */
/* MAC HW device detection */
ret = stmmac_mac_device_setup(ndev);
if (ret < 0)
goto out_plat_exit;
Expand Down

0 comments on commit 19e30c1

Please sign in to comment.