aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2016-07-25 21:51:44 -0700
committerDavid S. Miller <davem@davemloft.net>2016-07-25 21:51:44 -0700
commitee591f46a5a0ca0caaeb72b79ec5e012c6e3c9ef (patch)
treeed3f955b3ce6ab5c4170b7c16a56915ef775c5c9 /drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
parentMerge branch 'refactor-tc_action-structs' (diff)
parentMAINTAINERS: xgene: Add driver and documentation path (diff)
downloadlinux-dev-ee591f46a5a0ca0caaeb72b79ec5e012c6e3c9ef.tar.xz
linux-dev-ee591f46a5a0ca0caaeb72b79ec5e012c6e3c9ef.zip
Merge branch 'xgene-fix-mod-crash-and-1g-hotplug'
Iyappan Subramanian says: ==================== drivers: net: xgene: Fix module crash and 1G hot-plug This patchset addresses the following issues, 1. Fixes the kernel crash when the driver loaded as an kernel module - by fixing hardware cleanups and rearrange kernel API calls 2. Hot-plug issue on the SGMII 1G interface - by adding a driver for MDIO management Signed-off-by: Iyappan Subramanian <isubramanian@apm.com> Tested-by: Fushen Chen <fchen@apm.com> Tested-by: Toan Le <toanle@apm.com> --- v7: Address review comments from v6 - fixed kbuild warnings - unmapped DMA memory on xgene_enet_delete_bufpool() - delete descriptor rings and buffer pools on cle_init() failure - fixed error deconstruction path on probe v6: Address review comments from v5 - changed to use devm_ioremap_resource - changed to return PTR_ERR(clk) on failure - cleaned up and removed indirections - exported mdio read/write and phy_register functions - changed mii_bus is to indicate interface instance - changed to call the exported mdio read/write and phy_register functions v5: Address review comments from v4 - Fixed clock reset sequence by adding delay - Fixed clock count by adding clk_unprepare_disable() in port shutdown v4: Address review comments from v3 - Reorganized into smaller patches - Added wrapper functions for sgmii_control_reset and sgmii_tbi_control_reset - Removed clk_get warning info - mdio: Changed the order of 'if' statements and removed the 'else' statement - mdio: Removed the mdio_read(write) indirection wrapper functions - ethtool: Fixed SGMII 1G get_settings and set_settings - Documentation: dtb: Added MDIO node information - MAINTAINERS: Added MDIO driver and documentation path v3: Address review comments from v2 - Add comment about hardware clock reset sequence on xgene_mdio_reset v2: Address review comments from v1 - Fixed patch 1 compilation error - Fixed mdio@1f610000 xge0clk reference - Squashed dtb patches - Added PORT_OFFSET macro v1: - Initial version ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to '')
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c66
1 files changed, 63 insertions, 3 deletions
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
index ba030dc1940b..9c6ad0dce00f 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
@@ -258,13 +258,29 @@ static void xgene_xgmac_tx_disable(struct xgene_enet_pdata *pdata)
static int xgene_enet_reset(struct xgene_enet_pdata *pdata)
{
+ struct device *dev = &pdata->pdev->dev;
+
if (!xgene_ring_mgr_init(pdata))
return -ENODEV;
- if (!IS_ERR(pdata->clk)) {
+ if (dev->of_node) {
clk_prepare_enable(pdata->clk);
+ udelay(5);
clk_disable_unprepare(pdata->clk);
+ udelay(5);
clk_prepare_enable(pdata->clk);
+ udelay(5);
+ } else {
+#ifdef CONFIG_ACPI
+ if (acpi_has_method(ACPI_HANDLE(&pdata->pdev->dev), "_RST")) {
+ acpi_evaluate_object(ACPI_HANDLE(&pdata->pdev->dev),
+ "_RST", NULL, NULL);
+ } else if (acpi_has_method(ACPI_HANDLE(&pdata->pdev->dev),
+ "_INI")) {
+ acpi_evaluate_object(ACPI_HANDLE(&pdata->pdev->dev),
+ "_INI", NULL, NULL);
+ }
+#endif
}
xgene_enet_ecc_init(pdata);
@@ -292,8 +308,51 @@ static void xgene_enet_xgcle_bypass(struct xgene_enet_pdata *pdata,
static void xgene_enet_shutdown(struct xgene_enet_pdata *pdata)
{
- if (!IS_ERR(pdata->clk))
- clk_disable_unprepare(pdata->clk);
+ struct device *dev = &pdata->pdev->dev;
+ struct xgene_enet_desc_ring *ring;
+ u32 pb, val;
+ int i;
+
+ pb = 0;
+ for (i = 0; i < pdata->rxq_cnt; i++) {
+ ring = pdata->rx_ring[i]->buf_pool;
+
+ val = xgene_enet_ring_bufnum(ring->id);
+ pb |= BIT(val - 0x20);
+ }
+ xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIFPRESET_ADDR, pb);
+
+ pb = 0;
+ for (i = 0; i < pdata->txq_cnt; i++) {
+ ring = pdata->tx_ring[i];
+
+ val = xgene_enet_ring_bufnum(ring->id);
+ pb |= BIT(val);
+ }
+ xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIWQRESET_ADDR, pb);
+
+ if (dev->of_node) {
+ if (!IS_ERR(pdata->clk))
+ clk_disable_unprepare(pdata->clk);
+ }
+}
+
+static void xgene_enet_clear(struct xgene_enet_pdata *pdata,
+ struct xgene_enet_desc_ring *ring)
+{
+ u32 addr, val, data;
+
+ val = xgene_enet_ring_bufnum(ring->id);
+
+ if (xgene_enet_is_bufpool(ring->id)) {
+ addr = ENET_CFGSSQMIFPRESET_ADDR;
+ data = BIT(val - 0x20);
+ } else {
+ addr = ENET_CFGSSQMIWQRESET_ADDR;
+ data = BIT(val);
+ }
+
+ xgene_enet_wr_ring_if(pdata, addr, data);
}
static void xgene_enet_link_state(struct work_struct *work)
@@ -340,6 +399,7 @@ const struct xgene_mac_ops xgene_xgmac_ops = {
const struct xgene_port_ops xgene_xgport_ops = {
.reset = xgene_enet_reset,
+ .clear = xgene_enet_clear,
.cle_bypass = xgene_enet_xgcle_bypass,
.shutdown = xgene_enet_shutdown,
};