Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0ca58d62 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'amd-xgbe'



Tom Lendacky says:

====================
amd-xgbe: AMD XGBE driver update 2014-08-05

The following series of patches includes fixes/updates to the driver.

- Use dma_set_mask_and_coherent to set the DMA mask
- Move the phy connect/disconnect logic to allow for module unloading

Changes in V2:
- Check the return value of the dma_set_mask_and_coherent call
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents c2a19856 88131a81
Loading
Loading
Loading
Loading
+121 −1
Original line number Diff line number Diff line
@@ -122,6 +122,7 @@
#include <linux/clk.h>
#include <linux/if_ether.h>
#include <linux/net_tstamp.h>
#include <linux/phy.h>

#include "xgbe.h"
#include "xgbe-common.h"
@@ -521,6 +522,114 @@ static void xgbe_free_rx_skbuff(struct xgbe_prv_data *pdata)
	DBGPR("<--xgbe_free_rx_skbuff\n");
}

static void xgbe_adjust_link(struct net_device *netdev)
{
	struct xgbe_prv_data *pdata = netdev_priv(netdev);
	struct xgbe_hw_if *hw_if = &pdata->hw_if;
	struct phy_device *phydev = pdata->phydev;
	int new_state = 0;

	if (phydev == NULL)
		return;

	if (phydev->link) {
		/* Flow control support */
		if (pdata->pause_autoneg) {
			if (phydev->pause || phydev->asym_pause) {
				pdata->tx_pause = 1;
				pdata->rx_pause = 1;
			} else {
				pdata->tx_pause = 0;
				pdata->rx_pause = 0;
			}
		}

		if (pdata->tx_pause != pdata->phy_tx_pause) {
			hw_if->config_tx_flow_control(pdata);
			pdata->phy_tx_pause = pdata->tx_pause;
		}

		if (pdata->rx_pause != pdata->phy_rx_pause) {
			hw_if->config_rx_flow_control(pdata);
			pdata->phy_rx_pause = pdata->rx_pause;
		}

		/* Speed support */
		if (phydev->speed != pdata->phy_speed) {
			new_state = 1;

			switch (phydev->speed) {
			case SPEED_10000:
				hw_if->set_xgmii_speed(pdata);
				break;

			case SPEED_2500:
				hw_if->set_gmii_2500_speed(pdata);
				break;

			case SPEED_1000:
				hw_if->set_gmii_speed(pdata);
				break;
			}
			pdata->phy_speed = phydev->speed;
		}

		if (phydev->link != pdata->phy_link) {
			new_state = 1;
			pdata->phy_link = 1;
		}
	} else if (pdata->phy_link) {
		new_state = 1;
		pdata->phy_link = 0;
		pdata->phy_speed = SPEED_UNKNOWN;
	}

	if (new_state)
		phy_print_status(phydev);
}

static int xgbe_phy_init(struct xgbe_prv_data *pdata)
{
	struct net_device *netdev = pdata->netdev;
	struct phy_device *phydev = pdata->phydev;
	int ret;

	pdata->phy_link = -1;
	pdata->phy_speed = SPEED_UNKNOWN;
	pdata->phy_tx_pause = pdata->tx_pause;
	pdata->phy_rx_pause = pdata->rx_pause;

	ret = phy_connect_direct(netdev, phydev, &xgbe_adjust_link,
				 pdata->phy_mode);
	if (ret) {
		netdev_err(netdev, "phy_connect_direct failed\n");
		return ret;
	}

	if (!phydev->drv || (phydev->drv->phy_id == 0)) {
		netdev_err(netdev, "phy_id not valid\n");
		ret = -ENODEV;
		goto err_phy_connect;
	}
	DBGPR("  phy_connect_direct succeeded for PHY %s, link=%d\n",
	      dev_name(&phydev->dev), phydev->link);

	return 0;

err_phy_connect:
	phy_disconnect(phydev);

	return ret;
}

static void xgbe_phy_exit(struct xgbe_prv_data *pdata)
{
	if (!pdata->phydev)
		return;

	phy_disconnect(pdata->phydev);
}

int xgbe_powerdown(struct net_device *netdev, unsigned int caller)
{
	struct xgbe_prv_data *pdata = netdev_priv(netdev);
@@ -986,11 +1095,16 @@ static int xgbe_open(struct net_device *netdev)

	DBGPR("-->xgbe_open\n");

	/* Initialize the phy */
	ret = xgbe_phy_init(pdata);
	if (ret)
		return ret;

	/* Enable the clocks */
	ret = clk_prepare_enable(pdata->sysclk);
	if (ret) {
		netdev_alert(netdev, "dma clk_prepare_enable failed\n");
		return ret;
		goto err_phy_init;
	}

	ret = clk_prepare_enable(pdata->ptpclk);
@@ -1047,6 +1161,9 @@ err_ptpclk:
err_sysclk:
	clk_disable_unprepare(pdata->sysclk);

err_phy_init:
	xgbe_phy_exit(pdata);

	return ret;
}

@@ -1077,6 +1194,9 @@ static int xgbe_close(struct net_device *netdev)
	clk_disable_unprepare(pdata->ptpclk);
	clk_disable_unprepare(pdata->sysclk);

	/* Release the phy */
	xgbe_phy_exit(pdata);

	DBGPR("<--xgbe_close\n");

	return 0;
+5 −2
Original line number Diff line number Diff line
@@ -303,8 +303,11 @@ static int xgbe_probe(struct platform_device *pdev)
	/* Set the DMA mask */
	if (!dev->dma_mask)
		dev->dma_mask = &dev->coherent_dma_mask;
	*(dev->dma_mask) = DMA_BIT_MASK(40);
	dev->coherent_dma_mask = DMA_BIT_MASK(40);
	ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(40));
	if (ret) {
		dev_err(dev, "dma_set_mask_and_coherent failed\n");
		goto err_io;
	}

	if (of_property_read_bool(dev->of_node, "dma-coherent")) {
		pdata->axdomain = XGBE_DMA_OS_AXDOMAIN;
+0 −98
Original line number Diff line number Diff line
@@ -116,7 +116,6 @@

#include <linux/module.h>
#include <linux/kmod.h>
#include <linux/spinlock.h>
#include <linux/mdio.h>
#include <linux/phy.h>
#include <linux/of.h>
@@ -158,77 +157,6 @@ static int xgbe_mdio_write(struct mii_bus *mii, int prtad, int mmd_reg,
	return 0;
}

static void xgbe_adjust_link(struct net_device *netdev)
{
	struct xgbe_prv_data *pdata = netdev_priv(netdev);
	struct xgbe_hw_if *hw_if = &pdata->hw_if;
	struct phy_device *phydev = pdata->phydev;
	int new_state = 0;

	if (phydev == NULL)
		return;

	DBGPR_MDIO("-->xgbe_adjust_link: address=%d, newlink=%d, curlink=%d\n",
		   phydev->addr, phydev->link, pdata->phy_link);

	if (phydev->link) {
		/* Flow control support */
		if (pdata->pause_autoneg) {
			if (phydev->pause || phydev->asym_pause) {
				pdata->tx_pause = 1;
				pdata->rx_pause = 1;
			} else {
				pdata->tx_pause = 0;
				pdata->rx_pause = 0;
			}
		}

		if (pdata->tx_pause != pdata->phy_tx_pause) {
			hw_if->config_tx_flow_control(pdata);
			pdata->phy_tx_pause = pdata->tx_pause;
		}

		if (pdata->rx_pause != pdata->phy_rx_pause) {
			hw_if->config_rx_flow_control(pdata);
			pdata->phy_rx_pause = pdata->rx_pause;
		}

		/* Speed support */
		if (phydev->speed != pdata->phy_speed) {
			new_state = 1;

			switch (phydev->speed) {
			case SPEED_10000:
				hw_if->set_xgmii_speed(pdata);
				break;

			case SPEED_2500:
				hw_if->set_gmii_2500_speed(pdata);
				break;

			case SPEED_1000:
				hw_if->set_gmii_speed(pdata);
				break;
			}
			pdata->phy_speed = phydev->speed;
		}

		if (phydev->link != pdata->phy_link) {
			new_state = 1;
			pdata->phy_link = 1;
		}
	} else if (pdata->phy_link) {
		new_state = 1;
		pdata->phy_link = 0;
		pdata->phy_speed = SPEED_UNKNOWN;
	}

	if (new_state)
		phy_print_status(phydev);

	DBGPR_MDIO("<--xgbe_adjust_link\n");
}

void xgbe_dump_phy_registers(struct xgbe_prv_data *pdata)
{
	struct device *dev = pdata->dev;
@@ -278,7 +206,6 @@ void xgbe_dump_phy_registers(struct xgbe_prv_data *pdata)

int xgbe_mdio_register(struct xgbe_prv_data *pdata)
{
	struct net_device *netdev = pdata->netdev;
	struct device_node *phy_node;
	struct mii_bus *mii;
	struct phy_device *phydev;
@@ -293,7 +220,6 @@ int xgbe_mdio_register(struct xgbe_prv_data *pdata)
		return -EINVAL;
	}

	/* Register with the MDIO bus */
	mii = mdiobus_alloc();
	if (mii == NULL) {
		dev_err(pdata->dev, "mdiobus_alloc failed\n");
@@ -348,26 +274,6 @@ int xgbe_mdio_register(struct xgbe_prv_data *pdata)
	pdata->mii = mii;
	pdata->mdio_mmd = MDIO_MMD_PCS;

	pdata->phy_link = -1;
	pdata->phy_speed = SPEED_UNKNOWN;
	pdata->phy_tx_pause = pdata->tx_pause;
	pdata->phy_rx_pause = pdata->rx_pause;

	ret = phy_connect_direct(netdev, phydev, &xgbe_adjust_link,
				 pdata->phy_mode);
	if (ret) {
		netdev_err(netdev, "phy_connect_direct failed\n");
		goto err_phy_device;
	}

	if (!phydev->drv || (phydev->drv->phy_id == 0)) {
		netdev_err(netdev, "phy_id not valid\n");
		ret = -ENODEV;
		goto err_phy_connect;
	}
	DBGPR("  phy_connect_direct succeeded for PHY %s, link=%d\n",
	      dev_name(&phydev->dev), phydev->link);

	phydev->autoneg = pdata->default_autoneg;
	if (phydev->autoneg == AUTONEG_DISABLE) {
		phydev->speed = pdata->default_speed;
@@ -386,9 +292,6 @@ int xgbe_mdio_register(struct xgbe_prv_data *pdata)

	return 0;

err_phy_connect:
	phy_disconnect(phydev);

err_phy_device:
	phy_device_free(phydev);

@@ -408,7 +311,6 @@ void xgbe_mdio_unregister(struct xgbe_prv_data *pdata)
{
	DBGPR("-->xgbe_mdio_unregister\n");

	phy_disconnect(pdata->phydev);
	pdata->phydev = NULL;

	module_put(pdata->phy_module);