Skip to content

Commit

Permalink
Merge branch 'amd-xgbe'
Browse files Browse the repository at this point in the history
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: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Aug 5, 2014
2 parents c2a1985 + 88131a8 commit 0ca58d6
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 101 deletions.
122 changes: 121 additions & 1 deletion drivers/net/ethernet/amd/xgbe/xgbe-drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -1047,6 +1161,9 @@ static int xgbe_open(struct net_device *netdev)
err_sysclk:
clk_disable_unprepare(pdata->sysclk);

err_phy_init:
xgbe_phy_exit(pdata);

return ret;
}

Expand Down Expand Up @@ -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;
Expand Down
7 changes: 5 additions & 2 deletions drivers/net/ethernet/amd/xgbe/xgbe-main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
98 changes: 0 additions & 98 deletions drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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");
Expand Down Expand Up @@ -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;
Expand All @@ -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);

Expand All @@ -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);
Expand Down

0 comments on commit 0ca58d6

Please sign in to comment.