Re: C45 support and mdiobus_scan

2018-08-10 Thread Tom Lendacky
On 8/9/2018 10:25 AM, Andrew Lunn wrote:
>>> The PCIe core will look in the device tree and when it creates the
>>> platform device for the i210 on the pcie bus, it points
>>> pdev->dev.of_node at this node. So long as you are using a platform
>>> with DT, you can do this. I hope you are not using x86..
>>
>> Yes I am :( Any possible solution for this?

I haven't looked too closely, but maybe you can add a new mdiobus_scan
function for 10G that attempts get_phy_device() with is_c45 set to true
and if nothing is found falls back to get_phy_device() with is_c45 set to
false.  I don't know what would happen if you have a non-c45 phy attached,
but it's worth a shot to try it and see for each situation.

Thanks,
Tom

> 
> Well, DT can be used with x86. I think Edison did that. But i assume
> your PCIe host is in ACPI, not DT. So getting this linking working
> will not be easy.
> 
> There has been some work to add an ACPI binding for PHYs. I don't know
> if it actually got far enough that you can hack your DSDT to add a
> PHY. But i'm sure it did not get far enough that you can describe an
> MDIO bus in DSDT, so it probably is not going to help you.
> 
>> I guess in ultimate case I will have to switch to ARM based setup.
> 
> Yes, or MIPS.
> 
>  Andrew
> 


[PATCH net-next v2 08/12] amd-xgbe: Add ethtool show/set channels support

2018-05-23 Thread Tom Lendacky
Add ethtool support to show and set the device channel configuration.
Changing the channel configuration will result in a device restart.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c |   25 +
 drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c |  134 ++
 drivers/net/ethernet/amd/xgbe/xgbe.h |4 +
 3 files changed, 163 insertions(+)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index 397e3a0..24f1053 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -1329,6 +1329,17 @@ static int xgbe_alloc_memory(struct xgbe_prv_data *pdata)
struct net_device *netdev = pdata->netdev;
int ret;
 
+   if (pdata->new_tx_ring_count) {
+   pdata->tx_ring_count = pdata->new_tx_ring_count;
+   pdata->tx_q_count = pdata->tx_ring_count;
+   pdata->new_tx_ring_count = 0;
+   }
+
+   if (pdata->new_rx_ring_count) {
+   pdata->rx_ring_count = pdata->new_rx_ring_count;
+   pdata->new_rx_ring_count = 0;
+   }
+
/* Calculate the Rx buffer size before allocating rings */
pdata->rx_buf_size = xgbe_calc_rx_buf_size(netdev, netdev->mtu);
 
@@ -1482,6 +1493,20 @@ static void xgbe_stopdev(struct work_struct *work)
netdev_alert(pdata->netdev, "device stopped\n");
 }
 
+void xgbe_full_restart_dev(struct xgbe_prv_data *pdata)
+{
+   /* If not running, "restart" will happen on open */
+   if (!netif_running(pdata->netdev))
+   return;
+
+   xgbe_stop(pdata);
+
+   xgbe_free_memory(pdata);
+   xgbe_alloc_memory(pdata);
+
+   xgbe_start(pdata);
+}
+
 void xgbe_restart_dev(struct xgbe_prv_data *pdata)
 {
/* If not running, "restart" will happen on open */
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
index d12f982..a880f10 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
@@ -705,6 +705,138 @@ static int xgbe_set_ringparam(struct net_device *netdev,
return 0;
 }
 
+static void xgbe_get_channels(struct net_device *netdev,
+ struct ethtool_channels *channels)
+{
+   struct xgbe_prv_data *pdata = netdev_priv(netdev);
+   unsigned int rx, tx, combined;
+
+   /* Calculate maximums allowed:
+*   - Take into account the number of available IRQs
+*   - Do not take into account the number of online CPUs so that
+* the user can over-subscribe if desired
+*   - Tx is additionally limited by the number of hardware queues
+*/
+   rx = min(pdata->hw_feat.rx_ch_cnt, pdata->rx_max_channel_count);
+   rx = min(rx, pdata->channel_irq_count);
+   tx = min(pdata->hw_feat.tx_ch_cnt, pdata->tx_max_channel_count);
+   tx = min(tx, pdata->channel_irq_count);
+   tx = min(tx, pdata->tx_max_q_count);
+
+   combined = min(rx, tx);
+
+   channels->max_combined = combined;
+   channels->max_rx = rx ? rx - 1 : 0;
+   channels->max_tx = tx ? tx - 1 : 0;
+
+   /* Get current settings based on device state */
+   rx = pdata->new_rx_ring_count ? : pdata->rx_ring_count;
+   tx = pdata->new_tx_ring_count ? : pdata->tx_ring_count;
+
+   combined = min(rx, tx);
+   rx -= combined;
+   tx -= combined;
+
+   channels->combined_count = combined;
+   channels->rx_count = rx;
+   channels->tx_count = tx;
+}
+
+static void xgbe_print_set_channels_input(struct net_device *netdev,
+ struct ethtool_channels *channels)
+{
+   netdev_err(netdev, "channel inputs: combined=%u, rx-only=%u, 
tx-only=%u\n",
+  channels->combined_count, channels->rx_count,
+  channels->tx_count);
+}
+
+static int xgbe_set_channels(struct net_device *netdev,
+struct ethtool_channels *channels)
+{
+   struct xgbe_prv_data *pdata = netdev_priv(netdev);
+   unsigned int rx, rx_curr, tx, tx_curr, combined;
+
+   /* Calculate maximums allowed:
+*   - Take into account the number of available IRQs
+*   - Do not take into account the number of online CPUs so that
+* the user can over-subscribe if desired
+*   - Tx is additionally limited by the number of hardware queues
+*/
+   rx = min(pdata->hw_feat.rx_ch_cnt, pdata->rx_max_channel_count);
+   rx = min(rx, pdata->channel_irq_count);
+   tx = min(pdata->hw_feat.tx_ch_cnt, pdata->tx_max_channel_count);
+   tx = min(tx, pdata->tx_max_q_count);
+   tx = min(tx, pdata->channel_irq_count);
+
+   combine

[PATCH net-next v2 12/12] amd-xgbe: Improve SFP 100Mbps auto-negotiation

2018-05-23 Thread Tom Lendacky
After changing speed to 100Mbps as a result of auto-negotiation (AN),
some 10/100/1000Mbps SFPs indicate a successful link (no faults or loss
of signal), but cannot successfully transmit or receive data.  These
SFPs required an extra auto-negotiation (AN) after the speed change in
order to operate properly.  Add a quirk for these SFPs so that if the
outcome of the AN actually results in changing to a new speed, re-initiate
AN at that new speed.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-mdio.c   |   77 +++
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c |6 ++
 drivers/net/ethernet/amd/xgbe/xgbe.h|1 
 3 files changed, 50 insertions(+), 34 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
index 450b89c..4b5d625 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
@@ -331,13 +331,15 @@ static void xgbe_switch_mode(struct xgbe_prv_data *pdata)
xgbe_change_mode(pdata, pdata->phy_if.phy_impl.switch_mode(pdata));
 }
 
-static void xgbe_set_mode(struct xgbe_prv_data *pdata,
+static bool xgbe_set_mode(struct xgbe_prv_data *pdata,
  enum xgbe_mode mode)
 {
if (mode == xgbe_cur_mode(pdata))
-   return;
+   return false;
 
xgbe_change_mode(pdata, mode);
+
+   return true;
 }
 
 static bool xgbe_use_mode(struct xgbe_prv_data *pdata,
@@ -1178,21 +1180,23 @@ static int xgbe_phy_config_fixed(struct xgbe_prv_data 
*pdata)
return 0;
 }
 
-static int __xgbe_phy_config_aneg(struct xgbe_prv_data *pdata)
+static int __xgbe_phy_config_aneg(struct xgbe_prv_data *pdata, bool set_mode)
 {
int ret;
 
+   mutex_lock(>an_mutex);
+
set_bit(XGBE_LINK_INIT, >dev_state);
pdata->link_check = jiffies;
 
ret = pdata->phy_if.phy_impl.an_config(pdata);
if (ret)
-   return ret;
+   goto out;
 
if (pdata->phy.autoneg != AUTONEG_ENABLE) {
ret = xgbe_phy_config_fixed(pdata);
if (ret || !pdata->kr_redrv)
-   return ret;
+   goto out;
 
netif_dbg(pdata, link, pdata->netdev, "AN redriver support\n");
} else {
@@ -1202,24 +1206,27 @@ static int __xgbe_phy_config_aneg(struct xgbe_prv_data 
*pdata)
/* Disable auto-negotiation interrupt */
disable_irq(pdata->an_irq);
 
-   /* Start auto-negotiation in a supported mode */
-   if (xgbe_use_mode(pdata, XGBE_MODE_KR)) {
-   xgbe_set_mode(pdata, XGBE_MODE_KR);
-   } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_2500)) {
-   xgbe_set_mode(pdata, XGBE_MODE_KX_2500);
-   } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_1000)) {
-   xgbe_set_mode(pdata, XGBE_MODE_KX_1000);
-   } else if (xgbe_use_mode(pdata, XGBE_MODE_SFI)) {
-   xgbe_set_mode(pdata, XGBE_MODE_SFI);
-   } else if (xgbe_use_mode(pdata, XGBE_MODE_X)) {
-   xgbe_set_mode(pdata, XGBE_MODE_X);
-   } else if (xgbe_use_mode(pdata, XGBE_MODE_SGMII_1000)) {
-   xgbe_set_mode(pdata, XGBE_MODE_SGMII_1000);
-   } else if (xgbe_use_mode(pdata, XGBE_MODE_SGMII_100)) {
-   xgbe_set_mode(pdata, XGBE_MODE_SGMII_100);
-   } else {
-   enable_irq(pdata->an_irq);
-   return -EINVAL;
+   if (set_mode) {
+   /* Start auto-negotiation in a supported mode */
+   if (xgbe_use_mode(pdata, XGBE_MODE_KR)) {
+   xgbe_set_mode(pdata, XGBE_MODE_KR);
+   } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_2500)) {
+   xgbe_set_mode(pdata, XGBE_MODE_KX_2500);
+   } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_1000)) {
+   xgbe_set_mode(pdata, XGBE_MODE_KX_1000);
+   } else if (xgbe_use_mode(pdata, XGBE_MODE_SFI)) {
+   xgbe_set_mode(pdata, XGBE_MODE_SFI);
+   } else if (xgbe_use_mode(pdata, XGBE_MODE_X)) {
+   xgbe_set_mode(pdata, XGBE_MODE_X);
+   } else if (xgbe_use_mode(pdata, XGBE_MODE_SGMII_1000)) {
+   xgbe_set_mode(pdata, XGBE_MODE_SGMII_1000);
+   } else if (xgbe_use_mode(pdata, XGBE_MODE_SGMII_100)) {
+   xgbe_set_mode(pdata, XGBE_MODE_SGMII_100);
+   } else {
+   enable_irq(pdata->an_irq);
+   ret = -EINVAL;
+   goto out;
+   }
}
 
/* Disable and stop any in progress auto-negotiation */
@@ -1239,16 +1246,7 @@ static int __xgbe_phy_config_aneg(struct xgbe_prv_data 
*pdata)
xgbe_an_init(pdata);
xgbe_an_restart(pdata);
 
-   return 0;
-}
-
-static int xgbe_phy_config_ane

[PATCH net-next v2 09/12] amd-xgbe: Always attempt link training in KR mode

2018-05-23 Thread Tom Lendacky
Link training is always attempted when in KR mode, but the code is
structured to check if link training has been enabled before attempting
to perform it.  Since that check will always be true, simplify the code
to always enable and start link training during KR auto-negotiation.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-mdio.c |   69 +++--
 1 file changed, 16 insertions(+), 53 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
index 9c39c72..450b89c 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
@@ -216,31 +216,8 @@ static void xgbe_an_clear_interrupts_all(struct 
xgbe_prv_data *pdata)
xgbe_an37_clear_interrupts(pdata);
 }
 
-static void xgbe_an73_enable_kr_training(struct xgbe_prv_data *pdata)
-{
-   unsigned int reg;
-
-   reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL);
-
-   reg |= XGBE_KR_TRAINING_ENABLE;
-   XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg);
-}
-
-static void xgbe_an73_disable_kr_training(struct xgbe_prv_data *pdata)
-{
-   unsigned int reg;
-
-   reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL);
-
-   reg &= ~XGBE_KR_TRAINING_ENABLE;
-   XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg);
-}
-
 static void xgbe_kr_mode(struct xgbe_prv_data *pdata)
 {
-   /* Enable KR training */
-   xgbe_an73_enable_kr_training(pdata);
-
/* Set MAC to 10G speed */
pdata->hw_if.set_speed(pdata, SPEED_1);
 
@@ -250,9 +227,6 @@ static void xgbe_kr_mode(struct xgbe_prv_data *pdata)
 
 static void xgbe_kx_2500_mode(struct xgbe_prv_data *pdata)
 {
-   /* Disable KR training */
-   xgbe_an73_disable_kr_training(pdata);
-
/* Set MAC to 2.5G speed */
pdata->hw_if.set_speed(pdata, SPEED_2500);
 
@@ -262,9 +236,6 @@ static void xgbe_kx_2500_mode(struct xgbe_prv_data *pdata)
 
 static void xgbe_kx_1000_mode(struct xgbe_prv_data *pdata)
 {
-   /* Disable KR training */
-   xgbe_an73_disable_kr_training(pdata);
-
/* Set MAC to 1G speed */
pdata->hw_if.set_speed(pdata, SPEED_1000);
 
@@ -278,9 +249,6 @@ static void xgbe_sfi_mode(struct xgbe_prv_data *pdata)
if (pdata->kr_redrv)
return xgbe_kr_mode(pdata);
 
-   /* Disable KR training */
-   xgbe_an73_disable_kr_training(pdata);
-
/* Set MAC to 10G speed */
pdata->hw_if.set_speed(pdata, SPEED_1);
 
@@ -290,9 +258,6 @@ static void xgbe_sfi_mode(struct xgbe_prv_data *pdata)
 
 static void xgbe_x_mode(struct xgbe_prv_data *pdata)
 {
-   /* Disable KR training */
-   xgbe_an73_disable_kr_training(pdata);
-
/* Set MAC to 1G speed */
pdata->hw_if.set_speed(pdata, SPEED_1000);
 
@@ -302,9 +267,6 @@ static void xgbe_x_mode(struct xgbe_prv_data *pdata)
 
 static void xgbe_sgmii_1000_mode(struct xgbe_prv_data *pdata)
 {
-   /* Disable KR training */
-   xgbe_an73_disable_kr_training(pdata);
-
/* Set MAC to 1G speed */
pdata->hw_if.set_speed(pdata, SPEED_1000);
 
@@ -314,9 +276,6 @@ static void xgbe_sgmii_1000_mode(struct xgbe_prv_data 
*pdata)
 
 static void xgbe_sgmii_100_mode(struct xgbe_prv_data *pdata)
 {
-   /* Disable KR training */
-   xgbe_an73_disable_kr_training(pdata);
-
/* Set MAC to 1G speed */
pdata->hw_if.set_speed(pdata, SPEED_1000);
 
@@ -425,6 +384,12 @@ static void xgbe_an73_set(struct xgbe_prv_data *pdata, 
bool enable,
 {
unsigned int reg;
 
+   /* Disable KR training for now */
+   reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL);
+   reg &= ~XGBE_KR_TRAINING_ENABLE;
+   XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg);
+
+   /* Update AN settings */
reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_CTRL1);
reg &= ~MDIO_AN_CTRL1_ENABLE;
 
@@ -522,21 +487,19 @@ static enum xgbe_an xgbe_an73_tx_training(struct 
xgbe_prv_data *pdata,
XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_FECCTRL, reg);
 
/* Start KR training */
-   reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL);
-   if (reg & XGBE_KR_TRAINING_ENABLE) {
-   if (pdata->phy_if.phy_impl.kr_training_pre)
-   pdata->phy_if.phy_impl.kr_training_pre(pdata);
+   if (pdata->phy_if.phy_impl.kr_training_pre)
+   pdata->phy_if.phy_impl.kr_training_pre(pdata);
 
-   reg |= XGBE_KR_TRAINING_START;
-   XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL,
-   reg);
+   reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL);
+   reg |= XGBE_KR_TRAINING_ENABLE;
+   reg |= XGBE_KR_TRAINING_START;
+   XMDIO_

[PATCH net-next v2 11/12] amd-xgbe: Update the BelFuse quirk to support SGMII

2018-05-23 Thread Tom Lendacky
Instead of using a quirk to make the BelFuse 1GBT-SFP06 part look like
a 1000baseX part, program the SFP PHY to support SGMII and 10/100/1000
baseT.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c |  109 +++
 1 file changed, 75 insertions(+), 34 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
index dd747f6..194a569 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
@@ -860,6 +860,9 @@ static bool xgbe_phy_finisar_phy_quirks(struct 
xgbe_prv_data *pdata)
struct xgbe_phy_data *phy_data = pdata->phy_data;
unsigned int phy_id = phy_data->phydev->phy_id;
 
+   if (phy_data->port_mode != XGBE_PORT_MODE_SFP)
+   return false;
+
if ((phy_id & 0xfff0) != 0x01ff0cc0)
return false;
 
@@ -885,8 +888,80 @@ static bool xgbe_phy_finisar_phy_quirks(struct 
xgbe_prv_data *pdata)
return true;
 }
 
+static bool xgbe_phy_belfuse_phy_quirks(struct xgbe_prv_data *pdata)
+{
+   struct xgbe_phy_data *phy_data = pdata->phy_data;
+   struct xgbe_sfp_eeprom *sfp_eeprom = _data->sfp_eeprom;
+   unsigned int phy_id = phy_data->phydev->phy_id;
+   int reg;
+
+   if (phy_data->port_mode != XGBE_PORT_MODE_SFP)
+   return false;
+
+   if (memcmp(_eeprom->base[XGBE_SFP_BASE_VENDOR_NAME],
+  XGBE_BEL_FUSE_VENDOR, XGBE_SFP_BASE_VENDOR_NAME_LEN))
+   return false;
+
+   if (memcmp(_eeprom->base[XGBE_SFP_BASE_VENDOR_PN],
+  XGBE_BEL_FUSE_PARTNO, XGBE_SFP_BASE_VENDOR_PN_LEN))
+   return false;
+
+   if ((phy_id & 0xfff0) != 0x03625d10)
+   return false;
+
+   /* Disable RGMII mode */
+   phy_write(phy_data->phydev, 0x18, 0x7007);
+   reg = phy_read(phy_data->phydev, 0x18);
+   phy_write(phy_data->phydev, 0x18, reg & ~0x0080);
+
+   /* Enable fiber register bank */
+   phy_write(phy_data->phydev, 0x1c, 0x7c00);
+   reg = phy_read(phy_data->phydev, 0x1c);
+   reg &= 0x03ff;
+   reg &= ~0x0001;
+   phy_write(phy_data->phydev, 0x1c, 0x8000 | 0x7c00 | reg | 0x0001);
+
+   /* Power down SerDes */
+   reg = phy_read(phy_data->phydev, 0x00);
+   phy_write(phy_data->phydev, 0x00, reg | 0x00800);
+
+   /* Configure SGMII-to-Copper mode */
+   phy_write(phy_data->phydev, 0x1c, 0x7c00);
+   reg = phy_read(phy_data->phydev, 0x1c);
+   reg &= 0x03ff;
+   reg &= ~0x0006;
+   phy_write(phy_data->phydev, 0x1c, 0x8000 | 0x7c00 | reg | 0x0004);
+
+   /* Power up SerDes */
+   reg = phy_read(phy_data->phydev, 0x00);
+   phy_write(phy_data->phydev, 0x00, reg & ~0x00800);
+
+   /* Enable copper register bank */
+   phy_write(phy_data->phydev, 0x1c, 0x7c00);
+   reg = phy_read(phy_data->phydev, 0x1c);
+   reg &= 0x03ff;
+   reg &= ~0x0001;
+   phy_write(phy_data->phydev, 0x1c, 0x8000 | 0x7c00 | reg);
+
+   /* Power up SerDes */
+   reg = phy_read(phy_data->phydev, 0x00);
+   phy_write(phy_data->phydev, 0x00, reg & ~0x00800);
+
+   phy_data->phydev->supported = PHY_GBIT_FEATURES;
+   phy_data->phydev->supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
+   phy_data->phydev->advertising = phy_data->phydev->supported;
+
+   netif_dbg(pdata, drv, pdata->netdev,
+ "BelFuse PHY quirk in place\n");
+
+   return true;
+}
+
 static void xgbe_phy_external_phy_quirks(struct xgbe_prv_data *pdata)
 {
+   if (xgbe_phy_belfuse_phy_quirks(pdata))
+   return;
+
if (xgbe_phy_finisar_phy_quirks(pdata))
return;
 }
@@ -1027,37 +1102,6 @@ static bool xgbe_phy_check_sfp_mod_absent(struct 
xgbe_phy_data *phy_data)
return false;
 }
 
-static bool xgbe_phy_belfuse_parse_quirks(struct xgbe_prv_data *pdata)
-{
-   struct xgbe_phy_data *phy_data = pdata->phy_data;
-   struct xgbe_sfp_eeprom *sfp_eeprom = _data->sfp_eeprom;
-
-   if (memcmp(_eeprom->base[XGBE_SFP_BASE_VENDOR_NAME],
-  XGBE_BEL_FUSE_VENDOR, XGBE_SFP_BASE_VENDOR_NAME_LEN))
-   return false;
-
-   if (!memcmp(_eeprom->base[XGBE_SFP_BASE_VENDOR_PN],
-   XGBE_BEL_FUSE_PARTNO, XGBE_SFP_BASE_VENDOR_PN_LEN)) {
-   phy_data->sfp_base = XGBE_SFP_BASE_1000_SX;
-   phy_data->sfp_cable = XGBE_SFP_CABLE_ACTIVE;
-   phy_data->sfp_speed = XGBE_SFP_SPEED_1000;
-   if (phy_data->sfp_changed)
-   netif_dbg(pdata, drv, pdata->netdev,
- "Bel-Fuse SFP quirk in place\n");
-   return 

[PATCH net-next v2 10/12] amd-xgbe: Advertise FEC support with the KR re-driver

2018-05-23 Thread Tom Lendacky
When a KR re-driver is present, indicate the FEC support is available
during auto-negotiation.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c |4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
index 141bb13..dd747f6 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
@@ -1720,6 +1720,10 @@ static void xgbe_phy_an_advertising(struct xgbe_prv_data 
*pdata,
XGBE_CLR_ADV(dlks, 1000baseKX_Full);
XGBE_CLR_ADV(dlks, 1baseKR_Full);
 
+   /* Advertise FEC support is present */
+   if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE)
+   XGBE_SET_ADV(dlks, 1baseR_FEC);
+
switch (phy_data->port_mode) {
case XGBE_PORT_MODE_BACKPLANE:
XGBE_SET_ADV(dlks, 1baseKR_Full);



[PATCH net-next v2 07/12] amd-xgbe: Prepare for ethtool set-channel support

2018-05-23 Thread Tom Lendacky
In order to support being able to dynamically set/change the number of
Rx and Tx channels, update the code to:
 - Move alloc and free of device memory into callable functions
 - Move setting of the real number of Rx and Tx channels to device startup
 - Move mapping of the RSS channels to device startup

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c  |  108 ++---
 drivers/net/ethernet/amd/xgbe/xgbe-main.c |   20 -
 2 files changed, 68 insertions(+), 60 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index 2646c08..397e3a0 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -1312,14 +1312,72 @@ int xgbe_powerup(struct net_device *netdev, unsigned 
int caller)
return 0;
 }
 
+static void xgbe_free_memory(struct xgbe_prv_data *pdata)
+{
+   struct xgbe_desc_if *desc_if = >desc_if;
+
+   /* Free the ring descriptors and buffers */
+   desc_if->free_ring_resources(pdata);
+
+   /* Free the channel and ring structures */
+   xgbe_free_channels(pdata);
+}
+
+static int xgbe_alloc_memory(struct xgbe_prv_data *pdata)
+{
+   struct xgbe_desc_if *desc_if = >desc_if;
+   struct net_device *netdev = pdata->netdev;
+   int ret;
+
+   /* Calculate the Rx buffer size before allocating rings */
+   pdata->rx_buf_size = xgbe_calc_rx_buf_size(netdev, netdev->mtu);
+
+   /* Allocate the channel and ring structures */
+   ret = xgbe_alloc_channels(pdata);
+   if (ret)
+   return ret;
+
+   /* Allocate the ring descriptors and buffers */
+   ret = desc_if->alloc_ring_resources(pdata);
+   if (ret)
+   goto err_channels;
+
+   /* Initialize the service and Tx timers */
+   xgbe_init_timers(pdata);
+
+   return 0;
+
+err_channels:
+   xgbe_free_memory(pdata);
+
+   return ret;
+}
+
 static int xgbe_start(struct xgbe_prv_data *pdata)
 {
struct xgbe_hw_if *hw_if = >hw_if;
struct xgbe_phy_if *phy_if = >phy_if;
struct net_device *netdev = pdata->netdev;
+   unsigned int i;
int ret;
 
-   DBGPR("-->xgbe_start\n");
+   /* Set the number of queues */
+   ret = netif_set_real_num_tx_queues(netdev, pdata->tx_ring_count);
+   if (ret) {
+   netdev_err(netdev, "error setting real tx queue count\n");
+   return ret;
+   }
+
+   ret = netif_set_real_num_rx_queues(netdev, pdata->rx_ring_count);
+   if (ret) {
+   netdev_err(netdev, "error setting real rx queue count\n");
+   return ret;
+   }
+
+   /* Set RSS lookup table data for programming */
+   for (i = 0; i < XGBE_RSS_MAX_TABLE_SIZE; i++)
+   XGMAC_SET_BITS(pdata->rss_table[i], MAC_RSSDR, DMCH,
+  i % pdata->rx_ring_count);
 
ret = hw_if->init(pdata);
if (ret)
@@ -1347,8 +1405,6 @@ static int xgbe_start(struct xgbe_prv_data *pdata)
 
clear_bit(XGBE_STOPPED, >dev_state);
 
-   DBGPR("<--xgbe_start\n");
-
return 0;
 
 err_irqs:
@@ -1823,11 +1879,8 @@ static void xgbe_packet_info(struct xgbe_prv_data *pdata,
 static int xgbe_open(struct net_device *netdev)
 {
struct xgbe_prv_data *pdata = netdev_priv(netdev);
-   struct xgbe_desc_if *desc_if = >desc_if;
int ret;
 
-   DBGPR("-->xgbe_open\n");
-
/* Create the various names based on netdev name */
snprintf(pdata->an_name, sizeof(pdata->an_name) - 1, "%s-pcs",
 netdev_name(netdev));
@@ -1872,43 +1925,25 @@ static int xgbe_open(struct net_device *netdev)
goto err_sysclk;
}
 
-   /* Calculate the Rx buffer size before allocating rings */
-   ret = xgbe_calc_rx_buf_size(netdev, netdev->mtu);
-   if (ret < 0)
-   goto err_ptpclk;
-   pdata->rx_buf_size = ret;
-
-   /* Allocate the channel and ring structures */
-   ret = xgbe_alloc_channels(pdata);
-   if (ret)
-   goto err_ptpclk;
-
-   /* Allocate the ring descriptors and buffers */
-   ret = desc_if->alloc_ring_resources(pdata);
-   if (ret)
-   goto err_channels;
-
INIT_WORK(>service_work, xgbe_service);
INIT_WORK(>restart_work, xgbe_restart);
INIT_WORK(>stopdev_work, xgbe_stopdev);
INIT_WORK(>tx_tstamp_work, xgbe_tx_tstamp);
-   xgbe_init_timers(pdata);
+
+   ret = xgbe_alloc_memory(pdata);
+   if (ret)
+   goto err_ptpclk;
 
ret = xgbe_start(pdata);
if (ret)
-   goto err_rings;
+   goto err_mem;
 
clear_bit(XGBE_DOWN, >dev_state);
 
-   DBGPR("<--xgbe_open\

[PATCH net-next v2 05/12] amd-xgbe: Add ethtool support to retrieve SFP module info

2018-05-23 Thread Tom Lendacky
Add support to get SFP module information using ethtool.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c |   18 +++
 drivers/net/ethernet/amd/xgbe/xgbe-mdio.c|   21 
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c  |  137 ++
 drivers/net/ethernet/amd/xgbe/xgbe.h |   13 ++
 4 files changed, 189 insertions(+)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
index ff397bb..57394b77 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
@@ -626,6 +626,22 @@ static int xgbe_get_ts_info(struct net_device *netdev,
return 0;
 }
 
+static int xgbe_get_module_info(struct net_device *netdev,
+   struct ethtool_modinfo *modinfo)
+{
+   struct xgbe_prv_data *pdata = netdev_priv(netdev);
+
+   return pdata->phy_if.module_info(pdata, modinfo);
+}
+
+static int xgbe_get_module_eeprom(struct net_device *netdev,
+ struct ethtool_eeprom *eeprom, u8 *data)
+{
+   struct xgbe_prv_data *pdata = netdev_priv(netdev);
+
+   return pdata->phy_if.module_eeprom(pdata, eeprom, data);
+}
+
 static const struct ethtool_ops xgbe_ethtool_ops = {
.get_drvinfo = xgbe_get_drvinfo,
.get_msglevel = xgbe_get_msglevel,
@@ -646,6 +662,8 @@ static int xgbe_get_ts_info(struct net_device *netdev,
.get_ts_info = xgbe_get_ts_info,
.get_link_ksettings = xgbe_get_link_ksettings,
.set_link_ksettings = xgbe_set_link_ksettings,
+   .get_module_info = xgbe_get_module_info,
+   .get_module_eeprom = xgbe_get_module_eeprom,
 };
 
 const struct ethtool_ops *xgbe_get_ethtool_ops(void)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
index 1b45cd7..9c39c72 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
@@ -126,6 +126,24 @@
 #include "xgbe.h"
 #include "xgbe-common.h"
 
+static int xgbe_phy_module_eeprom(struct xgbe_prv_data *pdata,
+ struct ethtool_eeprom *eeprom, u8 *data)
+{
+   if (!pdata->phy_if.phy_impl.module_eeprom)
+   return -ENXIO;
+
+   return pdata->phy_if.phy_impl.module_eeprom(pdata, eeprom, data);
+}
+
+static int xgbe_phy_module_info(struct xgbe_prv_data *pdata,
+   struct ethtool_modinfo *modinfo)
+{
+   if (!pdata->phy_if.phy_impl.module_info)
+   return -ENXIO;
+
+   return pdata->phy_if.phy_impl.module_info(pdata, modinfo);
+}
+
 static void xgbe_an37_clear_interrupts(struct xgbe_prv_data *pdata)
 {
int reg;
@@ -1639,4 +1657,7 @@ void xgbe_init_function_ptrs_phy(struct xgbe_phy_if 
*phy_if)
phy_if->phy_valid_speed = xgbe_phy_valid_speed;
 
phy_if->an_isr  = xgbe_an_combined_isr;
+
+   phy_if->module_info = xgbe_phy_module_info;
+   phy_if->module_eeprom   = xgbe_phy_module_eeprom;
 }
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
index cb15caf..141bb13 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
@@ -119,6 +119,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "xgbe.h"
 #include "xgbe-common.h"
@@ -270,6 +271,15 @@ struct xgbe_sfp_eeprom {
u8 vendor[32];
 };
 
+#define XGBE_SFP_DIAGS_SUPPORTED(_x)   \
+   ((_x)->extd[XGBE_SFP_EXTD_SFF_8472] &&  \
+!((_x)->extd[XGBE_SFP_EXTD_DIAG] & XGBE_SFP_EXTD_DIAG_ADDR_CHANGE))
+
+#define XGBE_SFP_EEPROM_BASE_LEN   256
+#define XGBE_SFP_EEPROM_DIAG_LEN   256
+#define XGBE_SFP_EEPROM_MAX(XGBE_SFP_EEPROM_BASE_LEN + \
+XGBE_SFP_EEPROM_DIAG_LEN)
+
 #define XGBE_BEL_FUSE_VENDOR   "BEL-FUSE"
 #define XGBE_BEL_FUSE_PARTNO   "1GBT-SFP06  "
 
@@ -1301,6 +1311,130 @@ static void xgbe_phy_sfp_detect(struct xgbe_prv_data 
*pdata)
xgbe_phy_put_comm_ownership(pdata);
 }
 
+static int xgbe_phy_module_eeprom(struct xgbe_prv_data *pdata,
+ struct ethtool_eeprom *eeprom, u8 *data)
+{
+   struct xgbe_phy_data *phy_data = pdata->phy_data;
+   u8 eeprom_addr, eeprom_data[XGBE_SFP_EEPROM_MAX];
+   struct xgbe_sfp_eeprom *sfp_eeprom;
+   unsigned int i, j, rem;
+   int ret;
+
+   rem = eeprom->len;
+
+   if (!eeprom->len) {
+   ret = -EINVAL;
+   goto done;
+   }
+
+   if ((eeprom->offset + eeprom->len) > XGBE_SFP_EEPROM_MAX) {
+   ret = -EINVAL;
+   goto done;
+   }
+
+   if (phy_data->port_mode != XGBE_PORT_MODE_SFP) {
+

[PATCH net-next v2 06/12] amd-xgbe: Add ethtool show/set ring parameter support

2018-05-23 Thread Tom Lendacky
Add ethtool support to show and set the number of the Rx and Tx ring
descriptors.  Changing the ring configuration will result in a device
restart.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c |6 --
 drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c |   65 ++
 drivers/net/ethernet/amd/xgbe/xgbe.h |6 ++
 3 files changed, 72 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index 7c204f0..2646c08 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -1426,10 +1426,8 @@ static void xgbe_stopdev(struct work_struct *work)
netdev_alert(pdata->netdev, "device stopped\n");
 }
 
-static void xgbe_restart_dev(struct xgbe_prv_data *pdata)
+void xgbe_restart_dev(struct xgbe_prv_data *pdata)
 {
-   DBGPR("-->xgbe_restart_dev\n");
-
/* If not running, "restart" will happen on open */
if (!netif_running(pdata->netdev))
return;
@@ -1440,8 +1438,6 @@ static void xgbe_restart_dev(struct xgbe_prv_data *pdata)
xgbe_free_rx_data(pdata);
 
xgbe_start(pdata);
-
-   DBGPR("<--xgbe_restart_dev\n");
 }
 
 static void xgbe_restart(struct work_struct *work)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
index 57394b77..d12f982 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
@@ -642,6 +642,69 @@ static int xgbe_get_module_eeprom(struct net_device 
*netdev,
return pdata->phy_if.module_eeprom(pdata, eeprom, data);
 }
 
+static void xgbe_get_ringparam(struct net_device *netdev,
+  struct ethtool_ringparam *ringparam)
+{
+   struct xgbe_prv_data *pdata = netdev_priv(netdev);
+
+   ringparam->rx_max_pending = XGBE_RX_DESC_CNT_MAX;
+   ringparam->tx_max_pending = XGBE_TX_DESC_CNT_MAX;
+   ringparam->rx_pending = pdata->rx_desc_count;
+   ringparam->tx_pending = pdata->tx_desc_count;
+}
+
+static int xgbe_set_ringparam(struct net_device *netdev,
+ struct ethtool_ringparam *ringparam)
+{
+   struct xgbe_prv_data *pdata = netdev_priv(netdev);
+   unsigned int rx, tx;
+
+   if (ringparam->rx_mini_pending || ringparam->rx_jumbo_pending) {
+   netdev_err(netdev, "unsupported ring parameter\n");
+   return -EINVAL;
+   }
+
+   if ((ringparam->rx_pending < XGBE_RX_DESC_CNT_MIN) ||
+   (ringparam->rx_pending > XGBE_RX_DESC_CNT_MAX)) {
+   netdev_err(netdev,
+  "rx ring parameter must be between %u and %u\n",
+  XGBE_RX_DESC_CNT_MIN, XGBE_RX_DESC_CNT_MAX);
+   return -EINVAL;
+   }
+
+   if ((ringparam->tx_pending < XGBE_TX_DESC_CNT_MIN) ||
+   (ringparam->tx_pending > XGBE_TX_DESC_CNT_MAX)) {
+   netdev_err(netdev,
+  "tx ring parameter must be between %u and %u\n",
+  XGBE_TX_DESC_CNT_MIN, XGBE_TX_DESC_CNT_MAX);
+   return -EINVAL;
+   }
+
+   rx = __rounddown_pow_of_two(ringparam->rx_pending);
+   if (rx != ringparam->rx_pending)
+   netdev_notice(netdev,
+ "rx ring parameter rounded to power of two: %u\n",
+ rx);
+
+   tx = __rounddown_pow_of_two(ringparam->tx_pending);
+   if (tx != ringparam->tx_pending)
+   netdev_notice(netdev,
+ "tx ring parameter rounded to power of two: %u\n",
+ tx);
+
+   if ((rx == pdata->rx_desc_count) &&
+   (tx == pdata->tx_desc_count))
+   goto out;
+
+   pdata->rx_desc_count = rx;
+   pdata->tx_desc_count = tx;
+
+   xgbe_restart_dev(pdata);
+
+out:
+   return 0;
+}
+
 static const struct ethtool_ops xgbe_ethtool_ops = {
.get_drvinfo = xgbe_get_drvinfo,
.get_msglevel = xgbe_get_msglevel,
@@ -664,6 +727,8 @@ static int xgbe_get_module_eeprom(struct net_device *netdev,
.set_link_ksettings = xgbe_set_link_ksettings,
.get_module_info = xgbe_get_module_info,
.get_module_eeprom = xgbe_get_module_eeprom,
+   .get_ringparam = xgbe_get_ringparam,
+   .set_ringparam = xgbe_set_ringparam,
 };
 
 const struct ethtool_ops *xgbe_get_ethtool_ops(void)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h 
b/drivers/net/ethernet/amd/xgbe/xgbe.h
index f0f455b..7dc0fac 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe.h
@@ -144,6 +144,11 @@
 #define XGBE_TX_DESC_MAX_PROC  (XGBE_T

[PATCH net-next v2 03/12] amd-xgbe: Remove use of comm_owned field

2018-05-23 Thread Tom Lendacky
The comm_owned field can hide logic where double locking is attempted
and prevent multiple threads for the same device from accessing the
mutex properly.  Remove the comm_owned field and use the mutex API
exclusively for gaining ownership.  The current driver has been audited
and is obtaining communications ownership properly.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c |   16 
 1 file changed, 16 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
index 123ceb0..05003be 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
@@ -327,8 +327,6 @@ struct xgbe_phy_data {
 
unsigned int mdio_addr;
 
-   unsigned int comm_owned;
-
/* SFP Support */
enum xgbe_sfp_comm sfp_comm;
unsigned int sfp_mux_address;
@@ -382,12 +380,6 @@ struct xgbe_phy_data {
 static int xgbe_phy_i2c_xfer(struct xgbe_prv_data *pdata,
 struct xgbe_i2c_op *i2c_op)
 {
-   struct xgbe_phy_data *phy_data = pdata->phy_data;
-
-   /* Be sure we own the bus */
-   if (WARN_ON(!phy_data->comm_owned))
-   return -EIO;
-
return pdata->i2c_if.i2c_xfer(pdata, i2c_op);
 }
 
@@ -549,10 +541,6 @@ static int xgbe_phy_sfp_get_mux(struct xgbe_prv_data 
*pdata)
 
 static void xgbe_phy_put_comm_ownership(struct xgbe_prv_data *pdata)
 {
-   struct xgbe_phy_data *phy_data = pdata->phy_data;
-
-   phy_data->comm_owned = 0;
-
mutex_unlock(_phy_comm_lock);
 }
 
@@ -562,9 +550,6 @@ static int xgbe_phy_get_comm_ownership(struct xgbe_prv_data 
*pdata)
unsigned long timeout;
unsigned int mutex_id;
 
-   if (phy_data->comm_owned)
-   return 0;
-
/* The I2C and MDIO/GPIO bus is multiplexed between multiple devices,
 * the driver needs to take the software mutex and then the hardware
 * mutexes before being able to use the busses.
@@ -593,7 +578,6 @@ static int xgbe_phy_get_comm_ownership(struct xgbe_prv_data 
*pdata)
XP_IOWRITE(pdata, XP_I2C_MUTEX, mutex_id);
XP_IOWRITE(pdata, XP_MDIO_MUTEX, mutex_id);
 
-   phy_data->comm_owned = 1;
return 0;
}
 



[PATCH net-next v2 04/12] amd-xgbe: Remove field that indicates SFP diagnostic support

2018-05-23 Thread Tom Lendacky
The driver currently sets an indication of whether the SFP supports, and
that the driver can obtain, diagnostics data.  This isn't currently used
by the driver and the logic to set this indicator is flawed because the
field is cleared each time the SFP is checked and only set when a new SFP
is detected.  Remove this field and the logic supporting it.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c |9 -
 1 file changed, 9 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
index 05003be..cb15caf 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
@@ -343,7 +343,6 @@ struct xgbe_phy_data {
unsigned int sfp_rx_los;
unsigned int sfp_tx_fault;
unsigned int sfp_mod_absent;
-   unsigned int sfp_diags;
unsigned int sfp_changed;
unsigned int sfp_phy_avail;
unsigned int sfp_cable_len;
@@ -1211,13 +1210,6 @@ static int xgbe_phy_sfp_read_eeprom(struct xgbe_prv_data 
*pdata)
 
memcpy(_data->sfp_eeprom, _eeprom, sizeof(sfp_eeprom));
 
-   if (sfp_eeprom.extd[XGBE_SFP_EXTD_SFF_8472]) {
-   u8 diag_type = sfp_eeprom.extd[XGBE_SFP_EXTD_DIAG];
-
-   if (!(diag_type & XGBE_SFP_EXTD_DIAG_ADDR_CHANGE))
-   phy_data->sfp_diags = 1;
-   }
-
xgbe_phy_free_phy_device(pdata);
} else {
phy_data->sfp_changed = 0;
@@ -1267,7 +1259,6 @@ static void xgbe_phy_sfp_reset(struct xgbe_phy_data 
*phy_data)
phy_data->sfp_rx_los = 0;
phy_data->sfp_tx_fault = 0;
phy_data->sfp_mod_absent = 1;
-   phy_data->sfp_diags = 0;
phy_data->sfp_base = XGBE_SFP_BASE_UNKNOWN;
phy_data->sfp_cable = XGBE_SFP_CABLE_UNKNOWN;
phy_data->sfp_speed = XGBE_SFP_SPEED_UNKNOWN;



[PATCH net-next v2 02/12] amd-xgbe: Read and save the port property registers during probe

2018-05-23 Thread Tom Lendacky
Read and save the port property registers once during the device probe
and then use the saved values as they are needed.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-pci.c|   34 ++
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c |   68 ---
 drivers/net/ethernet/amd/xgbe/xgbe.h|7 +++
 3 files changed, 62 insertions(+), 47 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c
index 7b63521..7b86240 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c
@@ -335,12 +335,29 @@ static int xgbe_pci_probe(struct pci_dev *pdev, const 
struct pci_device_id *id)
pdata->awcr = XGBE_DMA_PCI_AWCR;
pdata->awarcr = XGBE_DMA_PCI_AWARCR;
 
+   /* Read the port property registers */
+   pdata->pp0 = XP_IOREAD(pdata, XP_PROP_0);
+   pdata->pp1 = XP_IOREAD(pdata, XP_PROP_1);
+   pdata->pp2 = XP_IOREAD(pdata, XP_PROP_2);
+   pdata->pp3 = XP_IOREAD(pdata, XP_PROP_3);
+   pdata->pp4 = XP_IOREAD(pdata, XP_PROP_4);
+   if (netif_msg_probe(pdata)) {
+   dev_dbg(dev, "port property 0 = %#010x\n", pdata->pp0);
+   dev_dbg(dev, "port property 1 = %#010x\n", pdata->pp1);
+   dev_dbg(dev, "port property 2 = %#010x\n", pdata->pp2);
+   dev_dbg(dev, "port property 3 = %#010x\n", pdata->pp3);
+   dev_dbg(dev, "port property 4 = %#010x\n", pdata->pp4);
+   }
+
/* Set the maximum channels and queues */
-   reg = XP_IOREAD(pdata, XP_PROP_1);
-   pdata->tx_max_channel_count = XP_GET_BITS(reg, XP_PROP_1, MAX_TX_DMA);
-   pdata->rx_max_channel_count = XP_GET_BITS(reg, XP_PROP_1, MAX_RX_DMA);
-   pdata->tx_max_q_count = XP_GET_BITS(reg, XP_PROP_1, MAX_TX_QUEUES);
-   pdata->rx_max_q_count = XP_GET_BITS(reg, XP_PROP_1, MAX_RX_QUEUES);
+   pdata->tx_max_channel_count = XP_GET_BITS(pdata->pp1, XP_PROP_1,
+ MAX_TX_DMA);
+   pdata->rx_max_channel_count = XP_GET_BITS(pdata->pp1, XP_PROP_1,
+ MAX_RX_DMA);
+   pdata->tx_max_q_count = XP_GET_BITS(pdata->pp1, XP_PROP_1,
+   MAX_TX_QUEUES);
+   pdata->rx_max_q_count = XP_GET_BITS(pdata->pp1, XP_PROP_1,
+   MAX_RX_QUEUES);
if (netif_msg_probe(pdata)) {
dev_dbg(dev, "max tx/rx channel count = %u/%u\n",
pdata->tx_max_channel_count,
@@ -353,12 +370,13 @@ static int xgbe_pci_probe(struct pci_dev *pdev, const 
struct pci_device_id *id)
xgbe_set_counts(pdata);
 
/* Set the maximum fifo amounts */
-   reg = XP_IOREAD(pdata, XP_PROP_2);
-   pdata->tx_max_fifo_size = XP_GET_BITS(reg, XP_PROP_2, TX_FIFO_SIZE);
+   pdata->tx_max_fifo_size = XP_GET_BITS(pdata->pp2, XP_PROP_2,
+ TX_FIFO_SIZE);
pdata->tx_max_fifo_size *= 16384;
pdata->tx_max_fifo_size = min(pdata->tx_max_fifo_size,
  pdata->vdata->tx_max_fifo_size);
-   pdata->rx_max_fifo_size = XP_GET_BITS(reg, XP_PROP_2, RX_FIFO_SIZE);
+   pdata->rx_max_fifo_size = XP_GET_BITS(pdata->pp2, XP_PROP_2,
+ RX_FIFO_SIZE);
pdata->rx_max_fifo_size *= 16384;
pdata->rx_max_fifo_size = min(pdata->rx_max_fifo_size,
  pdata->vdata->rx_max_fifo_size);
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
index aac8843..123ceb0 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
@@ -2421,22 +2421,21 @@ static int xgbe_phy_link_status(struct xgbe_prv_data 
*pdata, int *an_restart)
 static void xgbe_phy_sfp_gpio_setup(struct xgbe_prv_data *pdata)
 {
struct xgbe_phy_data *phy_data = pdata->phy_data;
-   unsigned int reg;
-
-   reg = XP_IOREAD(pdata, XP_PROP_3);
 
phy_data->sfp_gpio_address = XGBE_GPIO_ADDRESS_PCA9555 +
-XP_GET_BITS(reg, XP_PROP_3, GPIO_ADDR);
+XP_GET_BITS(pdata->pp3, XP_PROP_3,
+GPIO_ADDR);
 
-   phy_data->sfp_gpio_mask = XP_GET_BITS(reg, XP_PROP_3, GPIO_MASK);
+   phy_data->sfp_gpio_mask = XP_GET_BITS(pdata->pp3, XP_PROP_3,
+ GPIO_MASK);
 
-   phy_data->sfp_gpio_rx_los = XP_GET_BITS(reg, XP_PROP_3,
+   phy_data->sfp_gpio_rx_los = XP_GET_BITS(pdata->

[PATCH net-next v2 00/12] amd-xgbe: AMD XGBE driver updates 2018-05-21

2018-05-23 Thread Tom Lendacky
The following updates are included in this driver update series:

- Fix the debug output for the max channels count
- Read (once) and save the port property registers during probe
- Remove the use of the comm_owned field
- Remove unused SFP diagnostic support indicator field
- Add ethtool --module-info support
- Add ethtool --show-ring/--set-ring support
- Update the driver in preparation for ethtool --set-channels support
- Add ethtool --show-channels/--set-channels support
- Update the driver to always perform link training in KR mode
- Advertise FEC support when using a KR re-driver
- Update the BelFuse quirk to now support SGMII
- Improve 100Mbps auto-negotiation for BelFuse parts

This patch series is based on net-next.

---

Changes since v1:
- Update the --set-channels support to the use of the combined, rx and
  tx options as specified in the ethtool man page (in other words, don't
  create combined channels based on the min of the tx and rx channels
  specified).

Tom Lendacky (12):
  amd-xgbe: Fix debug output of max channel counts
  amd-xgbe: Read and save the port property registers during probe
  amd-xgbe: Remove use of comm_owned field
  amd-xgbe: Remove field that indicates SFP diagnostic support
  amd-xgbe: Add ethtool support to retrieve SFP module info
  amd-xgbe: Add ethtool show/set ring parameter support
  amd-xgbe: Prepare for ethtool set-channel support
  amd-xgbe: Add ethtool show/set channels support
  amd-xgbe: Always attempt link training in KR mode
  amd-xgbe: Advertise FEC support with the KR re-driver
  amd-xgbe: Update the BelFuse quirk to support SGMII
  amd-xgbe: Improve SFP 100Mbps auto-negotiation


 drivers/net/ethernet/amd/xgbe/xgbe-drv.c |  137 +++---
 drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c |  217 
 drivers/net/ethernet/amd/xgbe/xgbe-main.c|   20 -
 drivers/net/ethernet/amd/xgbe/xgbe-mdio.c|  167 ++--
 drivers/net/ethernet/amd/xgbe/xgbe-pci.c |   36 ++-
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c  |  349 +++---
 drivers/net/ethernet/amd/xgbe/xgbe.h |   31 ++
 7 files changed, 699 insertions(+), 258 deletions(-)

-- 
Tom Lendacky


[PATCH net-next v2 01/12] amd-xgbe: Fix debug output of max channel counts

2018-05-23 Thread Tom Lendacky
A debug output print statement uses the wrong variable to output the
maximum Rx channel count (cut and paste error, basically).  Fix the
statement to use the proper variable.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-pci.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c
index 82d1f41..7b63521 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c
@@ -344,7 +344,7 @@ static int xgbe_pci_probe(struct pci_dev *pdev, const 
struct pci_device_id *id)
if (netif_msg_probe(pdata)) {
dev_dbg(dev, "max tx/rx channel count = %u/%u\n",
pdata->tx_max_channel_count,
-   pdata->tx_max_channel_count);
+   pdata->rx_max_channel_count);
dev_dbg(dev, "max tx/rx hw queue count = %u/%u\n",
pdata->tx_max_q_count, pdata->rx_max_q_count);
}



Re: [PATCH net-next 08/12] amd-xgbe: Add ethtool show/set channels support

2018-05-22 Thread Tom Lendacky
On 5/22/2018 8:29 AM, Edward Cree wrote:
> On 22/05/18 14:24, Tom Lendacky wrote:
>> The amd-xgbe driver is not designed to allocate separate IRQs for Rx and
>> Tx.  In general, there is one IRQ for a channel of which Tx and Rx are
>> shared.  You can have more Tx channels than Rx channels or vice-versa, but
>> the min() of those numbers will be a combined Tx/Rx with the excess being
>> Tx or Rx only: e.g. combined 0 tx 8 rx 10 results in 8 combined channels
>> plus two Rx only channels.
> If you cannot allocate the channels requested by the user, surely the correct
>  thing is not to fudge it into something similar, but rather to return an
>  error from the ethtool set_channels() op.

Ok, another vote on changing the logic.  I'll update it and submit a v2.

Thanks,
Tom

> 
> -Ed
> 


Re: [PATCH net-next 08/12] amd-xgbe: Add ethtool show/set channels support

2018-05-22 Thread Tom Lendacky
On 5/22/2018 12:35 AM, Jakub Kicinski wrote:
> On Mon, 21 May 2018 16:59:37 -0500, Tom Lendacky wrote:
>> +rx = combined + channels->rx_count;
>> +tx = combined + channels->tx_count;
>> +netdev_notice(netdev, "final channel count assignment: combined=%u, 
>> rx-only=%u, tx-only=%u\n",
>> +  min(rx, tx), rx - min(rx, tx), tx - min(rx, tx));
> 
> If user requests combined 0 rx 8 tx 8 they will end up with combined 8
> rx 0 tx 0.  Is that expected?

Yes, which is the reason that I issue the final channel count message. I
debated on how to do all this and looked at other drivers as well as the
ethtool man page and decided on this logic.

> 
> The man page clearly sayeth:
> 
>-L --set-channels
>   Changes the numbers of channels of the specified network device.
> 
>rx N   Changes the number of channels with only receive queues.
> 
>tx N   Changes the number of channels with only transmit queues.
> 
>other N
>   Changes the number of channels used only for other  purposes
>   e.g. link interrupts or SR-IOV co-ordination.
> 
>combined N
>   Changes the number of multi-purpose channels.
> 
> Note the use of word *only*.  There are drivers in tree which adhere to
> this interpretation and dutifully allocate separate IRQs if RX and TX
> channels are requested separately.

The amd-xgbe driver is not designed to allocate separate IRQs for Rx and
Tx.  In general, there is one IRQ for a channel of which Tx and Rx are
shared.  You can have more Tx channels than Rx channels or vice-versa, but
the min() of those numbers will be a combined Tx/Rx with the excess being
Tx or Rx only: e.g. combined 0 tx 8 rx 10 results in 8 combined channels
plus two Rx only channels.

I thought this was the most reasonable way to do this, please let me know
if there's a strong objection to this.

Thanks,
Tom

> 
> Which is not to claim that majority of existing drivers adhere to this
> wording :)
> 


[PATCH net-next 09/12] amd-xgbe: Always attempt link training in KR mode

2018-05-21 Thread Tom Lendacky
Link training is always attempted when in KR mode, but the code is
structured to check if link training has been enabled before attempting
to perform it.  Since that check will always be true, simplify the code
to always enable and start link training during KR auto-negotiation.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-mdio.c |   69 +++--
 1 file changed, 16 insertions(+), 53 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
index 9c39c72..450b89c 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
@@ -216,31 +216,8 @@ static void xgbe_an_clear_interrupts_all(struct 
xgbe_prv_data *pdata)
xgbe_an37_clear_interrupts(pdata);
 }
 
-static void xgbe_an73_enable_kr_training(struct xgbe_prv_data *pdata)
-{
-   unsigned int reg;
-
-   reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL);
-
-   reg |= XGBE_KR_TRAINING_ENABLE;
-   XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg);
-}
-
-static void xgbe_an73_disable_kr_training(struct xgbe_prv_data *pdata)
-{
-   unsigned int reg;
-
-   reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL);
-
-   reg &= ~XGBE_KR_TRAINING_ENABLE;
-   XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg);
-}
-
 static void xgbe_kr_mode(struct xgbe_prv_data *pdata)
 {
-   /* Enable KR training */
-   xgbe_an73_enable_kr_training(pdata);
-
/* Set MAC to 10G speed */
pdata->hw_if.set_speed(pdata, SPEED_1);
 
@@ -250,9 +227,6 @@ static void xgbe_kr_mode(struct xgbe_prv_data *pdata)
 
 static void xgbe_kx_2500_mode(struct xgbe_prv_data *pdata)
 {
-   /* Disable KR training */
-   xgbe_an73_disable_kr_training(pdata);
-
/* Set MAC to 2.5G speed */
pdata->hw_if.set_speed(pdata, SPEED_2500);
 
@@ -262,9 +236,6 @@ static void xgbe_kx_2500_mode(struct xgbe_prv_data *pdata)
 
 static void xgbe_kx_1000_mode(struct xgbe_prv_data *pdata)
 {
-   /* Disable KR training */
-   xgbe_an73_disable_kr_training(pdata);
-
/* Set MAC to 1G speed */
pdata->hw_if.set_speed(pdata, SPEED_1000);
 
@@ -278,9 +249,6 @@ static void xgbe_sfi_mode(struct xgbe_prv_data *pdata)
if (pdata->kr_redrv)
return xgbe_kr_mode(pdata);
 
-   /* Disable KR training */
-   xgbe_an73_disable_kr_training(pdata);
-
/* Set MAC to 10G speed */
pdata->hw_if.set_speed(pdata, SPEED_1);
 
@@ -290,9 +258,6 @@ static void xgbe_sfi_mode(struct xgbe_prv_data *pdata)
 
 static void xgbe_x_mode(struct xgbe_prv_data *pdata)
 {
-   /* Disable KR training */
-   xgbe_an73_disable_kr_training(pdata);
-
/* Set MAC to 1G speed */
pdata->hw_if.set_speed(pdata, SPEED_1000);
 
@@ -302,9 +267,6 @@ static void xgbe_x_mode(struct xgbe_prv_data *pdata)
 
 static void xgbe_sgmii_1000_mode(struct xgbe_prv_data *pdata)
 {
-   /* Disable KR training */
-   xgbe_an73_disable_kr_training(pdata);
-
/* Set MAC to 1G speed */
pdata->hw_if.set_speed(pdata, SPEED_1000);
 
@@ -314,9 +276,6 @@ static void xgbe_sgmii_1000_mode(struct xgbe_prv_data 
*pdata)
 
 static void xgbe_sgmii_100_mode(struct xgbe_prv_data *pdata)
 {
-   /* Disable KR training */
-   xgbe_an73_disable_kr_training(pdata);
-
/* Set MAC to 1G speed */
pdata->hw_if.set_speed(pdata, SPEED_1000);
 
@@ -425,6 +384,12 @@ static void xgbe_an73_set(struct xgbe_prv_data *pdata, 
bool enable,
 {
unsigned int reg;
 
+   /* Disable KR training for now */
+   reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL);
+   reg &= ~XGBE_KR_TRAINING_ENABLE;
+   XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg);
+
+   /* Update AN settings */
reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_CTRL1);
reg &= ~MDIO_AN_CTRL1_ENABLE;
 
@@ -522,21 +487,19 @@ static enum xgbe_an xgbe_an73_tx_training(struct 
xgbe_prv_data *pdata,
XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_FECCTRL, reg);
 
/* Start KR training */
-   reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL);
-   if (reg & XGBE_KR_TRAINING_ENABLE) {
-   if (pdata->phy_if.phy_impl.kr_training_pre)
-   pdata->phy_if.phy_impl.kr_training_pre(pdata);
+   if (pdata->phy_if.phy_impl.kr_training_pre)
+   pdata->phy_if.phy_impl.kr_training_pre(pdata);
 
-   reg |= XGBE_KR_TRAINING_START;
-   XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL,
-   reg);
+   reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL);
+   reg |= XGBE_KR_TRAINING_ENABLE;
+   reg |= XGBE_KR_TRAINING_START;
+   XMDIO_

[PATCH net-next 11/12] amd-xgbe: Update the BelFuse quirk to support SGMII

2018-05-21 Thread Tom Lendacky
Instead of using a quirk to make the BelFuse 1GBT-SFP06 part look like
a 1000baseX part, program the SFP PHY to support SGMII and 10/100/1000
baseT.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c |  109 +++
 1 file changed, 75 insertions(+), 34 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
index dd747f6..194a569 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
@@ -860,6 +860,9 @@ static bool xgbe_phy_finisar_phy_quirks(struct 
xgbe_prv_data *pdata)
struct xgbe_phy_data *phy_data = pdata->phy_data;
unsigned int phy_id = phy_data->phydev->phy_id;
 
+   if (phy_data->port_mode != XGBE_PORT_MODE_SFP)
+   return false;
+
if ((phy_id & 0xfff0) != 0x01ff0cc0)
return false;
 
@@ -885,8 +888,80 @@ static bool xgbe_phy_finisar_phy_quirks(struct 
xgbe_prv_data *pdata)
return true;
 }
 
+static bool xgbe_phy_belfuse_phy_quirks(struct xgbe_prv_data *pdata)
+{
+   struct xgbe_phy_data *phy_data = pdata->phy_data;
+   struct xgbe_sfp_eeprom *sfp_eeprom = _data->sfp_eeprom;
+   unsigned int phy_id = phy_data->phydev->phy_id;
+   int reg;
+
+   if (phy_data->port_mode != XGBE_PORT_MODE_SFP)
+   return false;
+
+   if (memcmp(_eeprom->base[XGBE_SFP_BASE_VENDOR_NAME],
+  XGBE_BEL_FUSE_VENDOR, XGBE_SFP_BASE_VENDOR_NAME_LEN))
+   return false;
+
+   if (memcmp(_eeprom->base[XGBE_SFP_BASE_VENDOR_PN],
+  XGBE_BEL_FUSE_PARTNO, XGBE_SFP_BASE_VENDOR_PN_LEN))
+   return false;
+
+   if ((phy_id & 0xfff0) != 0x03625d10)
+   return false;
+
+   /* Disable RGMII mode */
+   phy_write(phy_data->phydev, 0x18, 0x7007);
+   reg = phy_read(phy_data->phydev, 0x18);
+   phy_write(phy_data->phydev, 0x18, reg & ~0x0080);
+
+   /* Enable fiber register bank */
+   phy_write(phy_data->phydev, 0x1c, 0x7c00);
+   reg = phy_read(phy_data->phydev, 0x1c);
+   reg &= 0x03ff;
+   reg &= ~0x0001;
+   phy_write(phy_data->phydev, 0x1c, 0x8000 | 0x7c00 | reg | 0x0001);
+
+   /* Power down SerDes */
+   reg = phy_read(phy_data->phydev, 0x00);
+   phy_write(phy_data->phydev, 0x00, reg | 0x00800);
+
+   /* Configure SGMII-to-Copper mode */
+   phy_write(phy_data->phydev, 0x1c, 0x7c00);
+   reg = phy_read(phy_data->phydev, 0x1c);
+   reg &= 0x03ff;
+   reg &= ~0x0006;
+   phy_write(phy_data->phydev, 0x1c, 0x8000 | 0x7c00 | reg | 0x0004);
+
+   /* Power up SerDes */
+   reg = phy_read(phy_data->phydev, 0x00);
+   phy_write(phy_data->phydev, 0x00, reg & ~0x00800);
+
+   /* Enable copper register bank */
+   phy_write(phy_data->phydev, 0x1c, 0x7c00);
+   reg = phy_read(phy_data->phydev, 0x1c);
+   reg &= 0x03ff;
+   reg &= ~0x0001;
+   phy_write(phy_data->phydev, 0x1c, 0x8000 | 0x7c00 | reg);
+
+   /* Power up SerDes */
+   reg = phy_read(phy_data->phydev, 0x00);
+   phy_write(phy_data->phydev, 0x00, reg & ~0x00800);
+
+   phy_data->phydev->supported = PHY_GBIT_FEATURES;
+   phy_data->phydev->supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
+   phy_data->phydev->advertising = phy_data->phydev->supported;
+
+   netif_dbg(pdata, drv, pdata->netdev,
+ "BelFuse PHY quirk in place\n");
+
+   return true;
+}
+
 static void xgbe_phy_external_phy_quirks(struct xgbe_prv_data *pdata)
 {
+   if (xgbe_phy_belfuse_phy_quirks(pdata))
+   return;
+
if (xgbe_phy_finisar_phy_quirks(pdata))
return;
 }
@@ -1027,37 +1102,6 @@ static bool xgbe_phy_check_sfp_mod_absent(struct 
xgbe_phy_data *phy_data)
return false;
 }
 
-static bool xgbe_phy_belfuse_parse_quirks(struct xgbe_prv_data *pdata)
-{
-   struct xgbe_phy_data *phy_data = pdata->phy_data;
-   struct xgbe_sfp_eeprom *sfp_eeprom = _data->sfp_eeprom;
-
-   if (memcmp(_eeprom->base[XGBE_SFP_BASE_VENDOR_NAME],
-  XGBE_BEL_FUSE_VENDOR, XGBE_SFP_BASE_VENDOR_NAME_LEN))
-   return false;
-
-   if (!memcmp(_eeprom->base[XGBE_SFP_BASE_VENDOR_PN],
-   XGBE_BEL_FUSE_PARTNO, XGBE_SFP_BASE_VENDOR_PN_LEN)) {
-   phy_data->sfp_base = XGBE_SFP_BASE_1000_SX;
-   phy_data->sfp_cable = XGBE_SFP_CABLE_ACTIVE;
-   phy_data->sfp_speed = XGBE_SFP_SPEED_1000;
-   if (phy_data->sfp_changed)
-   netif_dbg(pdata, drv, pdata->netdev,
- "Bel-Fuse SFP quirk in place\n");
-   return 

[PATCH net-next 12/12] amd-xgbe: Improve SFP 100Mbps auto-negotiation

2018-05-21 Thread Tom Lendacky
After changing speed to 100Mbps as a result of auto-negotiation (AN),
some 10/100/1000Mbps SFPs indicate a successful link (no faults or loss
of signal), but cannot successfully transmit or receive data.  These
SFPs required an extra auto-negotiation (AN) after the speed change in
order to operate properly.  Add a quirk for these SFPs so that if the
outcome of the AN actually results in changing to a new speed, re-initiate
AN at that new speed.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-mdio.c   |   77 +++
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c |6 ++
 drivers/net/ethernet/amd/xgbe/xgbe.h|1 
 3 files changed, 50 insertions(+), 34 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
index 450b89c..4b5d625 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
@@ -331,13 +331,15 @@ static void xgbe_switch_mode(struct xgbe_prv_data *pdata)
xgbe_change_mode(pdata, pdata->phy_if.phy_impl.switch_mode(pdata));
 }
 
-static void xgbe_set_mode(struct xgbe_prv_data *pdata,
+static bool xgbe_set_mode(struct xgbe_prv_data *pdata,
  enum xgbe_mode mode)
 {
if (mode == xgbe_cur_mode(pdata))
-   return;
+   return false;
 
xgbe_change_mode(pdata, mode);
+
+   return true;
 }
 
 static bool xgbe_use_mode(struct xgbe_prv_data *pdata,
@@ -1178,21 +1180,23 @@ static int xgbe_phy_config_fixed(struct xgbe_prv_data 
*pdata)
return 0;
 }
 
-static int __xgbe_phy_config_aneg(struct xgbe_prv_data *pdata)
+static int __xgbe_phy_config_aneg(struct xgbe_prv_data *pdata, bool set_mode)
 {
int ret;
 
+   mutex_lock(>an_mutex);
+
set_bit(XGBE_LINK_INIT, >dev_state);
pdata->link_check = jiffies;
 
ret = pdata->phy_if.phy_impl.an_config(pdata);
if (ret)
-   return ret;
+   goto out;
 
if (pdata->phy.autoneg != AUTONEG_ENABLE) {
ret = xgbe_phy_config_fixed(pdata);
if (ret || !pdata->kr_redrv)
-   return ret;
+   goto out;
 
netif_dbg(pdata, link, pdata->netdev, "AN redriver support\n");
} else {
@@ -1202,24 +1206,27 @@ static int __xgbe_phy_config_aneg(struct xgbe_prv_data 
*pdata)
/* Disable auto-negotiation interrupt */
disable_irq(pdata->an_irq);
 
-   /* Start auto-negotiation in a supported mode */
-   if (xgbe_use_mode(pdata, XGBE_MODE_KR)) {
-   xgbe_set_mode(pdata, XGBE_MODE_KR);
-   } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_2500)) {
-   xgbe_set_mode(pdata, XGBE_MODE_KX_2500);
-   } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_1000)) {
-   xgbe_set_mode(pdata, XGBE_MODE_KX_1000);
-   } else if (xgbe_use_mode(pdata, XGBE_MODE_SFI)) {
-   xgbe_set_mode(pdata, XGBE_MODE_SFI);
-   } else if (xgbe_use_mode(pdata, XGBE_MODE_X)) {
-   xgbe_set_mode(pdata, XGBE_MODE_X);
-   } else if (xgbe_use_mode(pdata, XGBE_MODE_SGMII_1000)) {
-   xgbe_set_mode(pdata, XGBE_MODE_SGMII_1000);
-   } else if (xgbe_use_mode(pdata, XGBE_MODE_SGMII_100)) {
-   xgbe_set_mode(pdata, XGBE_MODE_SGMII_100);
-   } else {
-   enable_irq(pdata->an_irq);
-   return -EINVAL;
+   if (set_mode) {
+   /* Start auto-negotiation in a supported mode */
+   if (xgbe_use_mode(pdata, XGBE_MODE_KR)) {
+   xgbe_set_mode(pdata, XGBE_MODE_KR);
+   } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_2500)) {
+   xgbe_set_mode(pdata, XGBE_MODE_KX_2500);
+   } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_1000)) {
+   xgbe_set_mode(pdata, XGBE_MODE_KX_1000);
+   } else if (xgbe_use_mode(pdata, XGBE_MODE_SFI)) {
+   xgbe_set_mode(pdata, XGBE_MODE_SFI);
+   } else if (xgbe_use_mode(pdata, XGBE_MODE_X)) {
+   xgbe_set_mode(pdata, XGBE_MODE_X);
+   } else if (xgbe_use_mode(pdata, XGBE_MODE_SGMII_1000)) {
+   xgbe_set_mode(pdata, XGBE_MODE_SGMII_1000);
+   } else if (xgbe_use_mode(pdata, XGBE_MODE_SGMII_100)) {
+   xgbe_set_mode(pdata, XGBE_MODE_SGMII_100);
+   } else {
+   enable_irq(pdata->an_irq);
+   ret = -EINVAL;
+   goto out;
+   }
}
 
/* Disable and stop any in progress auto-negotiation */
@@ -1239,16 +1246,7 @@ static int __xgbe_phy_config_aneg(struct xgbe_prv_data 
*pdata)
xgbe_an_init(pdata);
xgbe_an_restart(pdata);
 
-   return 0;
-}
-
-static int xgbe_phy_config_ane

[PATCH net-next 10/12] amd-xgbe: Advertise FEC support with the KR re-driver

2018-05-21 Thread Tom Lendacky
When a KR re-driver is present, indicate the FEC support is available
during auto-negotiation.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c |4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
index 141bb13..dd747f6 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
@@ -1720,6 +1720,10 @@ static void xgbe_phy_an_advertising(struct xgbe_prv_data 
*pdata,
XGBE_CLR_ADV(dlks, 1000baseKX_Full);
XGBE_CLR_ADV(dlks, 1baseKR_Full);
 
+   /* Advertise FEC support is present */
+   if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE)
+   XGBE_SET_ADV(dlks, 1baseR_FEC);
+
switch (phy_data->port_mode) {
case XGBE_PORT_MODE_BACKPLANE:
XGBE_SET_ADV(dlks, 1baseKR_Full);



[PATCH net-next 08/12] amd-xgbe: Add ethtool show/set channels support

2018-05-21 Thread Tom Lendacky
Add ethtool support to show and set the device channel configuration.
Changing the channel configuration will result in a device restart.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c |   25 +
 drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c |  131 ++
 drivers/net/ethernet/amd/xgbe/xgbe.h |4 +
 3 files changed, 160 insertions(+)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index 397e3a0..24f1053 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -1329,6 +1329,17 @@ static int xgbe_alloc_memory(struct xgbe_prv_data *pdata)
struct net_device *netdev = pdata->netdev;
int ret;
 
+   if (pdata->new_tx_ring_count) {
+   pdata->tx_ring_count = pdata->new_tx_ring_count;
+   pdata->tx_q_count = pdata->tx_ring_count;
+   pdata->new_tx_ring_count = 0;
+   }
+
+   if (pdata->new_rx_ring_count) {
+   pdata->rx_ring_count = pdata->new_rx_ring_count;
+   pdata->new_rx_ring_count = 0;
+   }
+
/* Calculate the Rx buffer size before allocating rings */
pdata->rx_buf_size = xgbe_calc_rx_buf_size(netdev, netdev->mtu);
 
@@ -1482,6 +1493,20 @@ static void xgbe_stopdev(struct work_struct *work)
netdev_alert(pdata->netdev, "device stopped\n");
 }
 
+void xgbe_full_restart_dev(struct xgbe_prv_data *pdata)
+{
+   /* If not running, "restart" will happen on open */
+   if (!netif_running(pdata->netdev))
+   return;
+
+   xgbe_stop(pdata);
+
+   xgbe_free_memory(pdata);
+   xgbe_alloc_memory(pdata);
+
+   xgbe_start(pdata);
+}
+
 void xgbe_restart_dev(struct xgbe_prv_data *pdata)
 {
/* If not running, "restart" will happen on open */
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
index d12f982..d26fd95 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
@@ -705,6 +705,135 @@ static int xgbe_set_ringparam(struct net_device *netdev,
return 0;
 }
 
+static void xgbe_get_channels(struct net_device *netdev,
+ struct ethtool_channels *channels)
+{
+   struct xgbe_prv_data *pdata = netdev_priv(netdev);
+   unsigned int rx, tx, combined;
+
+   /* Calculate maximums allowed:
+*   - Take into account the number of available IRQs
+*   - Do not take into account the number of online CPUs so that
+* the user can over-subscribe if desired
+*   - Tx is additionally limited by the number of hardware queues
+*/
+   rx = min(pdata->hw_feat.rx_ch_cnt, pdata->rx_max_channel_count);
+   rx = min(rx, pdata->channel_irq_count);
+   tx = min(pdata->hw_feat.tx_ch_cnt, pdata->tx_max_channel_count);
+   tx = min(tx, pdata->channel_irq_count);
+   tx = min(tx, pdata->tx_max_q_count);
+
+   combined = min(rx, tx);
+
+   channels->max_combined = combined;
+   channels->max_rx = rx;
+   channels->max_tx = tx;
+
+   /* Current running settings */
+   rx = pdata->rx_ring_count;
+   tx = pdata->tx_ring_count;
+
+   combined = min(rx, tx);
+   rx -= combined;
+   tx -= combined;
+
+   channels->combined_count = combined;
+   channels->rx_count = rx;
+   channels->tx_count = tx;
+}
+
+static void xgbe_print_set_channels_input(struct net_device *netdev,
+ struct ethtool_channels *channels)
+{
+   netdev_err(netdev, "channel inputs: combined=%u, rx-only=%u, 
tx-only=%u\n",
+  channels->combined_count, channels->rx_count,
+  channels->tx_count);
+}
+
+static int xgbe_set_channels(struct net_device *netdev,
+struct ethtool_channels *channels)
+{
+   struct xgbe_prv_data *pdata = netdev_priv(netdev);
+   unsigned int rx, tx, combined;
+
+   /* Calculate maximums allowed:
+*   - Take into account the number of available IRQs
+*   - Do not take into account the number of online CPUs so that
+* the user can over-subscribe if desired
+*   - Tx is additionally limited by the number of hardware queues
+*/
+   rx = min(pdata->hw_feat.rx_ch_cnt, pdata->rx_max_channel_count);
+   rx = min(rx, pdata->channel_irq_count);
+   tx = min(pdata->hw_feat.tx_ch_cnt, pdata->tx_max_channel_count);
+   tx = min(tx, pdata->tx_max_q_count);
+   tx = min(tx, pdata->channel_irq_count);
+
+   combined = min(rx, tx);
+
+   /* Should not be setting other count */
+   if (channels->other_count) {
+   n

[PATCH net-next 05/12] amd-xgbe: Add ethtool support to retrieve SFP module info

2018-05-21 Thread Tom Lendacky
Add support to get SFP module information using ethtool.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c |   18 +++
 drivers/net/ethernet/amd/xgbe/xgbe-mdio.c|   21 
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c  |  137 ++
 drivers/net/ethernet/amd/xgbe/xgbe.h |   13 ++
 4 files changed, 189 insertions(+)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
index ff397bb..57394b77 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
@@ -626,6 +626,22 @@ static int xgbe_get_ts_info(struct net_device *netdev,
return 0;
 }
 
+static int xgbe_get_module_info(struct net_device *netdev,
+   struct ethtool_modinfo *modinfo)
+{
+   struct xgbe_prv_data *pdata = netdev_priv(netdev);
+
+   return pdata->phy_if.module_info(pdata, modinfo);
+}
+
+static int xgbe_get_module_eeprom(struct net_device *netdev,
+ struct ethtool_eeprom *eeprom, u8 *data)
+{
+   struct xgbe_prv_data *pdata = netdev_priv(netdev);
+
+   return pdata->phy_if.module_eeprom(pdata, eeprom, data);
+}
+
 static const struct ethtool_ops xgbe_ethtool_ops = {
.get_drvinfo = xgbe_get_drvinfo,
.get_msglevel = xgbe_get_msglevel,
@@ -646,6 +662,8 @@ static int xgbe_get_ts_info(struct net_device *netdev,
.get_ts_info = xgbe_get_ts_info,
.get_link_ksettings = xgbe_get_link_ksettings,
.set_link_ksettings = xgbe_set_link_ksettings,
+   .get_module_info = xgbe_get_module_info,
+   .get_module_eeprom = xgbe_get_module_eeprom,
 };
 
 const struct ethtool_ops *xgbe_get_ethtool_ops(void)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
index 1b45cd7..9c39c72 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
@@ -126,6 +126,24 @@
 #include "xgbe.h"
 #include "xgbe-common.h"
 
+static int xgbe_phy_module_eeprom(struct xgbe_prv_data *pdata,
+ struct ethtool_eeprom *eeprom, u8 *data)
+{
+   if (!pdata->phy_if.phy_impl.module_eeprom)
+   return -ENXIO;
+
+   return pdata->phy_if.phy_impl.module_eeprom(pdata, eeprom, data);
+}
+
+static int xgbe_phy_module_info(struct xgbe_prv_data *pdata,
+   struct ethtool_modinfo *modinfo)
+{
+   if (!pdata->phy_if.phy_impl.module_info)
+   return -ENXIO;
+
+   return pdata->phy_if.phy_impl.module_info(pdata, modinfo);
+}
+
 static void xgbe_an37_clear_interrupts(struct xgbe_prv_data *pdata)
 {
int reg;
@@ -1639,4 +1657,7 @@ void xgbe_init_function_ptrs_phy(struct xgbe_phy_if 
*phy_if)
phy_if->phy_valid_speed = xgbe_phy_valid_speed;
 
phy_if->an_isr  = xgbe_an_combined_isr;
+
+   phy_if->module_info = xgbe_phy_module_info;
+   phy_if->module_eeprom   = xgbe_phy_module_eeprom;
 }
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
index cb15caf..141bb13 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
@@ -119,6 +119,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "xgbe.h"
 #include "xgbe-common.h"
@@ -270,6 +271,15 @@ struct xgbe_sfp_eeprom {
u8 vendor[32];
 };
 
+#define XGBE_SFP_DIAGS_SUPPORTED(_x)   \
+   ((_x)->extd[XGBE_SFP_EXTD_SFF_8472] &&  \
+!((_x)->extd[XGBE_SFP_EXTD_DIAG] & XGBE_SFP_EXTD_DIAG_ADDR_CHANGE))
+
+#define XGBE_SFP_EEPROM_BASE_LEN   256
+#define XGBE_SFP_EEPROM_DIAG_LEN   256
+#define XGBE_SFP_EEPROM_MAX(XGBE_SFP_EEPROM_BASE_LEN + \
+XGBE_SFP_EEPROM_DIAG_LEN)
+
 #define XGBE_BEL_FUSE_VENDOR   "BEL-FUSE"
 #define XGBE_BEL_FUSE_PARTNO   "1GBT-SFP06  "
 
@@ -1301,6 +1311,130 @@ static void xgbe_phy_sfp_detect(struct xgbe_prv_data 
*pdata)
xgbe_phy_put_comm_ownership(pdata);
 }
 
+static int xgbe_phy_module_eeprom(struct xgbe_prv_data *pdata,
+ struct ethtool_eeprom *eeprom, u8 *data)
+{
+   struct xgbe_phy_data *phy_data = pdata->phy_data;
+   u8 eeprom_addr, eeprom_data[XGBE_SFP_EEPROM_MAX];
+   struct xgbe_sfp_eeprom *sfp_eeprom;
+   unsigned int i, j, rem;
+   int ret;
+
+   rem = eeprom->len;
+
+   if (!eeprom->len) {
+   ret = -EINVAL;
+   goto done;
+   }
+
+   if ((eeprom->offset + eeprom->len) > XGBE_SFP_EEPROM_MAX) {
+   ret = -EINVAL;
+   goto done;
+   }
+
+   if (phy_data->port_mode != XGBE_PORT_MODE_SFP) {
+

[PATCH net-next 07/12] amd-xgbe: Prepare for ethtool set-channel support

2018-05-21 Thread Tom Lendacky
In order to support being able to dynamically set/change the number of
Rx and Tx channels, update the code to:
 - Move alloc and free of device memory into callable functions
 - Move setting of the real number of Rx and Tx channels to device startup
 - Move mapping of the RSS channels to device startup

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c  |  108 ++---
 drivers/net/ethernet/amd/xgbe/xgbe-main.c |   20 -
 2 files changed, 68 insertions(+), 60 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index 2646c08..397e3a0 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -1312,14 +1312,72 @@ int xgbe_powerup(struct net_device *netdev, unsigned 
int caller)
return 0;
 }
 
+static void xgbe_free_memory(struct xgbe_prv_data *pdata)
+{
+   struct xgbe_desc_if *desc_if = >desc_if;
+
+   /* Free the ring descriptors and buffers */
+   desc_if->free_ring_resources(pdata);
+
+   /* Free the channel and ring structures */
+   xgbe_free_channels(pdata);
+}
+
+static int xgbe_alloc_memory(struct xgbe_prv_data *pdata)
+{
+   struct xgbe_desc_if *desc_if = >desc_if;
+   struct net_device *netdev = pdata->netdev;
+   int ret;
+
+   /* Calculate the Rx buffer size before allocating rings */
+   pdata->rx_buf_size = xgbe_calc_rx_buf_size(netdev, netdev->mtu);
+
+   /* Allocate the channel and ring structures */
+   ret = xgbe_alloc_channels(pdata);
+   if (ret)
+   return ret;
+
+   /* Allocate the ring descriptors and buffers */
+   ret = desc_if->alloc_ring_resources(pdata);
+   if (ret)
+   goto err_channels;
+
+   /* Initialize the service and Tx timers */
+   xgbe_init_timers(pdata);
+
+   return 0;
+
+err_channels:
+   xgbe_free_memory(pdata);
+
+   return ret;
+}
+
 static int xgbe_start(struct xgbe_prv_data *pdata)
 {
struct xgbe_hw_if *hw_if = >hw_if;
struct xgbe_phy_if *phy_if = >phy_if;
struct net_device *netdev = pdata->netdev;
+   unsigned int i;
int ret;
 
-   DBGPR("-->xgbe_start\n");
+   /* Set the number of queues */
+   ret = netif_set_real_num_tx_queues(netdev, pdata->tx_ring_count);
+   if (ret) {
+   netdev_err(netdev, "error setting real tx queue count\n");
+   return ret;
+   }
+
+   ret = netif_set_real_num_rx_queues(netdev, pdata->rx_ring_count);
+   if (ret) {
+   netdev_err(netdev, "error setting real rx queue count\n");
+   return ret;
+   }
+
+   /* Set RSS lookup table data for programming */
+   for (i = 0; i < XGBE_RSS_MAX_TABLE_SIZE; i++)
+   XGMAC_SET_BITS(pdata->rss_table[i], MAC_RSSDR, DMCH,
+  i % pdata->rx_ring_count);
 
ret = hw_if->init(pdata);
if (ret)
@@ -1347,8 +1405,6 @@ static int xgbe_start(struct xgbe_prv_data *pdata)
 
clear_bit(XGBE_STOPPED, >dev_state);
 
-   DBGPR("<--xgbe_start\n");
-
return 0;
 
 err_irqs:
@@ -1823,11 +1879,8 @@ static void xgbe_packet_info(struct xgbe_prv_data *pdata,
 static int xgbe_open(struct net_device *netdev)
 {
struct xgbe_prv_data *pdata = netdev_priv(netdev);
-   struct xgbe_desc_if *desc_if = >desc_if;
int ret;
 
-   DBGPR("-->xgbe_open\n");
-
/* Create the various names based on netdev name */
snprintf(pdata->an_name, sizeof(pdata->an_name) - 1, "%s-pcs",
 netdev_name(netdev));
@@ -1872,43 +1925,25 @@ static int xgbe_open(struct net_device *netdev)
goto err_sysclk;
}
 
-   /* Calculate the Rx buffer size before allocating rings */
-   ret = xgbe_calc_rx_buf_size(netdev, netdev->mtu);
-   if (ret < 0)
-   goto err_ptpclk;
-   pdata->rx_buf_size = ret;
-
-   /* Allocate the channel and ring structures */
-   ret = xgbe_alloc_channels(pdata);
-   if (ret)
-   goto err_ptpclk;
-
-   /* Allocate the ring descriptors and buffers */
-   ret = desc_if->alloc_ring_resources(pdata);
-   if (ret)
-   goto err_channels;
-
INIT_WORK(>service_work, xgbe_service);
INIT_WORK(>restart_work, xgbe_restart);
INIT_WORK(>stopdev_work, xgbe_stopdev);
INIT_WORK(>tx_tstamp_work, xgbe_tx_tstamp);
-   xgbe_init_timers(pdata);
+
+   ret = xgbe_alloc_memory(pdata);
+   if (ret)
+   goto err_ptpclk;
 
ret = xgbe_start(pdata);
if (ret)
-   goto err_rings;
+   goto err_mem;
 
clear_bit(XGBE_DOWN, >dev_state);
 
-   DBGPR("<--xgbe_open\

[PATCH net-next 06/12] amd-xgbe: Add ethtool show/set ring parameter support

2018-05-21 Thread Tom Lendacky
Add ethtool support to show and set the number of the Rx and Tx ring
descriptors.  Changing the ring configuration will result in a device
restart.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c |6 --
 drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c |   65 ++
 drivers/net/ethernet/amd/xgbe/xgbe.h |6 ++
 3 files changed, 72 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index 7c204f0..2646c08 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -1426,10 +1426,8 @@ static void xgbe_stopdev(struct work_struct *work)
netdev_alert(pdata->netdev, "device stopped\n");
 }
 
-static void xgbe_restart_dev(struct xgbe_prv_data *pdata)
+void xgbe_restart_dev(struct xgbe_prv_data *pdata)
 {
-   DBGPR("-->xgbe_restart_dev\n");
-
/* If not running, "restart" will happen on open */
if (!netif_running(pdata->netdev))
return;
@@ -1440,8 +1438,6 @@ static void xgbe_restart_dev(struct xgbe_prv_data *pdata)
xgbe_free_rx_data(pdata);
 
xgbe_start(pdata);
-
-   DBGPR("<--xgbe_restart_dev\n");
 }
 
 static void xgbe_restart(struct work_struct *work)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
index 57394b77..d12f982 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
@@ -642,6 +642,69 @@ static int xgbe_get_module_eeprom(struct net_device 
*netdev,
return pdata->phy_if.module_eeprom(pdata, eeprom, data);
 }
 
+static void xgbe_get_ringparam(struct net_device *netdev,
+  struct ethtool_ringparam *ringparam)
+{
+   struct xgbe_prv_data *pdata = netdev_priv(netdev);
+
+   ringparam->rx_max_pending = XGBE_RX_DESC_CNT_MAX;
+   ringparam->tx_max_pending = XGBE_TX_DESC_CNT_MAX;
+   ringparam->rx_pending = pdata->rx_desc_count;
+   ringparam->tx_pending = pdata->tx_desc_count;
+}
+
+static int xgbe_set_ringparam(struct net_device *netdev,
+ struct ethtool_ringparam *ringparam)
+{
+   struct xgbe_prv_data *pdata = netdev_priv(netdev);
+   unsigned int rx, tx;
+
+   if (ringparam->rx_mini_pending || ringparam->rx_jumbo_pending) {
+   netdev_err(netdev, "unsupported ring parameter\n");
+   return -EINVAL;
+   }
+
+   if ((ringparam->rx_pending < XGBE_RX_DESC_CNT_MIN) ||
+   (ringparam->rx_pending > XGBE_RX_DESC_CNT_MAX)) {
+   netdev_err(netdev,
+  "rx ring parameter must be between %u and %u\n",
+  XGBE_RX_DESC_CNT_MIN, XGBE_RX_DESC_CNT_MAX);
+   return -EINVAL;
+   }
+
+   if ((ringparam->tx_pending < XGBE_TX_DESC_CNT_MIN) ||
+   (ringparam->tx_pending > XGBE_TX_DESC_CNT_MAX)) {
+   netdev_err(netdev,
+  "tx ring parameter must be between %u and %u\n",
+  XGBE_TX_DESC_CNT_MIN, XGBE_TX_DESC_CNT_MAX);
+   return -EINVAL;
+   }
+
+   rx = __rounddown_pow_of_two(ringparam->rx_pending);
+   if (rx != ringparam->rx_pending)
+   netdev_notice(netdev,
+ "rx ring parameter rounded to power of two: %u\n",
+ rx);
+
+   tx = __rounddown_pow_of_two(ringparam->tx_pending);
+   if (tx != ringparam->tx_pending)
+   netdev_notice(netdev,
+ "tx ring parameter rounded to power of two: %u\n",
+ tx);
+
+   if ((rx == pdata->rx_desc_count) &&
+   (tx == pdata->tx_desc_count))
+   goto out;
+
+   pdata->rx_desc_count = rx;
+   pdata->tx_desc_count = tx;
+
+   xgbe_restart_dev(pdata);
+
+out:
+   return 0;
+}
+
 static const struct ethtool_ops xgbe_ethtool_ops = {
.get_drvinfo = xgbe_get_drvinfo,
.get_msglevel = xgbe_get_msglevel,
@@ -664,6 +727,8 @@ static int xgbe_get_module_eeprom(struct net_device *netdev,
.set_link_ksettings = xgbe_set_link_ksettings,
.get_module_info = xgbe_get_module_info,
.get_module_eeprom = xgbe_get_module_eeprom,
+   .get_ringparam = xgbe_get_ringparam,
+   .set_ringparam = xgbe_set_ringparam,
 };
 
 const struct ethtool_ops *xgbe_get_ethtool_ops(void)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h 
b/drivers/net/ethernet/amd/xgbe/xgbe.h
index f0f455b..7dc0fac 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe.h
@@ -144,6 +144,11 @@
 #define XGBE_TX_DESC_MAX_PROC  (XGBE_T

[PATCH net-next 04/12] amd-xgbe: Remove field that indicates SFP diagnostic support

2018-05-21 Thread Tom Lendacky
The driver currently sets an indication of whether the SFP supports, and
that the driver can obtain, diagnostics data.  This isn't currently used
by the driver and the logic to set this indicator is flawed because the
field is cleared each time the SFP is checked and only set when a new SFP
is detected.  Remove this field and the logic supporting it.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c |9 -
 1 file changed, 9 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
index 05003be..cb15caf 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
@@ -343,7 +343,6 @@ struct xgbe_phy_data {
unsigned int sfp_rx_los;
unsigned int sfp_tx_fault;
unsigned int sfp_mod_absent;
-   unsigned int sfp_diags;
unsigned int sfp_changed;
unsigned int sfp_phy_avail;
unsigned int sfp_cable_len;
@@ -1211,13 +1210,6 @@ static int xgbe_phy_sfp_read_eeprom(struct xgbe_prv_data 
*pdata)
 
memcpy(_data->sfp_eeprom, _eeprom, sizeof(sfp_eeprom));
 
-   if (sfp_eeprom.extd[XGBE_SFP_EXTD_SFF_8472]) {
-   u8 diag_type = sfp_eeprom.extd[XGBE_SFP_EXTD_DIAG];
-
-   if (!(diag_type & XGBE_SFP_EXTD_DIAG_ADDR_CHANGE))
-   phy_data->sfp_diags = 1;
-   }
-
xgbe_phy_free_phy_device(pdata);
} else {
phy_data->sfp_changed = 0;
@@ -1267,7 +1259,6 @@ static void xgbe_phy_sfp_reset(struct xgbe_phy_data 
*phy_data)
phy_data->sfp_rx_los = 0;
phy_data->sfp_tx_fault = 0;
phy_data->sfp_mod_absent = 1;
-   phy_data->sfp_diags = 0;
phy_data->sfp_base = XGBE_SFP_BASE_UNKNOWN;
phy_data->sfp_cable = XGBE_SFP_CABLE_UNKNOWN;
phy_data->sfp_speed = XGBE_SFP_SPEED_UNKNOWN;



[PATCH net-next 03/12] amd-xgbe: Remove use of comm_owned field

2018-05-21 Thread Tom Lendacky
The comm_owned field can hide logic where double locking is attempted
and prevent multiple threads for the same device from accessing the
mutex properly.  Remove the comm_owned field and use the mutex API
exclusively for gaining ownership.  The current driver has been audited
and is obtaining communications ownership properly.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c |   16 
 1 file changed, 16 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
index 123ceb0..05003be 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
@@ -327,8 +327,6 @@ struct xgbe_phy_data {
 
unsigned int mdio_addr;
 
-   unsigned int comm_owned;
-
/* SFP Support */
enum xgbe_sfp_comm sfp_comm;
unsigned int sfp_mux_address;
@@ -382,12 +380,6 @@ struct xgbe_phy_data {
 static int xgbe_phy_i2c_xfer(struct xgbe_prv_data *pdata,
 struct xgbe_i2c_op *i2c_op)
 {
-   struct xgbe_phy_data *phy_data = pdata->phy_data;
-
-   /* Be sure we own the bus */
-   if (WARN_ON(!phy_data->comm_owned))
-   return -EIO;
-
return pdata->i2c_if.i2c_xfer(pdata, i2c_op);
 }
 
@@ -549,10 +541,6 @@ static int xgbe_phy_sfp_get_mux(struct xgbe_prv_data 
*pdata)
 
 static void xgbe_phy_put_comm_ownership(struct xgbe_prv_data *pdata)
 {
-   struct xgbe_phy_data *phy_data = pdata->phy_data;
-
-   phy_data->comm_owned = 0;
-
mutex_unlock(_phy_comm_lock);
 }
 
@@ -562,9 +550,6 @@ static int xgbe_phy_get_comm_ownership(struct xgbe_prv_data 
*pdata)
unsigned long timeout;
unsigned int mutex_id;
 
-   if (phy_data->comm_owned)
-   return 0;
-
/* The I2C and MDIO/GPIO bus is multiplexed between multiple devices,
 * the driver needs to take the software mutex and then the hardware
 * mutexes before being able to use the busses.
@@ -593,7 +578,6 @@ static int xgbe_phy_get_comm_ownership(struct xgbe_prv_data 
*pdata)
XP_IOWRITE(pdata, XP_I2C_MUTEX, mutex_id);
XP_IOWRITE(pdata, XP_MDIO_MUTEX, mutex_id);
 
-   phy_data->comm_owned = 1;
return 0;
}
 



[PATCH net-next 02/12] amd-xgbe: Read and save the port property registers during probe

2018-05-21 Thread Tom Lendacky
Read and save the port property registers once during the device probe
and then use the saved values as they are needed.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-pci.c|   34 ++
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c |   68 ---
 drivers/net/ethernet/amd/xgbe/xgbe.h|7 +++
 3 files changed, 62 insertions(+), 47 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c
index 7b63521..7b86240 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c
@@ -335,12 +335,29 @@ static int xgbe_pci_probe(struct pci_dev *pdev, const 
struct pci_device_id *id)
pdata->awcr = XGBE_DMA_PCI_AWCR;
pdata->awarcr = XGBE_DMA_PCI_AWARCR;
 
+   /* Read the port property registers */
+   pdata->pp0 = XP_IOREAD(pdata, XP_PROP_0);
+   pdata->pp1 = XP_IOREAD(pdata, XP_PROP_1);
+   pdata->pp2 = XP_IOREAD(pdata, XP_PROP_2);
+   pdata->pp3 = XP_IOREAD(pdata, XP_PROP_3);
+   pdata->pp4 = XP_IOREAD(pdata, XP_PROP_4);
+   if (netif_msg_probe(pdata)) {
+   dev_dbg(dev, "port property 0 = %#010x\n", pdata->pp0);
+   dev_dbg(dev, "port property 1 = %#010x\n", pdata->pp1);
+   dev_dbg(dev, "port property 2 = %#010x\n", pdata->pp2);
+   dev_dbg(dev, "port property 3 = %#010x\n", pdata->pp3);
+   dev_dbg(dev, "port property 4 = %#010x\n", pdata->pp4);
+   }
+
/* Set the maximum channels and queues */
-   reg = XP_IOREAD(pdata, XP_PROP_1);
-   pdata->tx_max_channel_count = XP_GET_BITS(reg, XP_PROP_1, MAX_TX_DMA);
-   pdata->rx_max_channel_count = XP_GET_BITS(reg, XP_PROP_1, MAX_RX_DMA);
-   pdata->tx_max_q_count = XP_GET_BITS(reg, XP_PROP_1, MAX_TX_QUEUES);
-   pdata->rx_max_q_count = XP_GET_BITS(reg, XP_PROP_1, MAX_RX_QUEUES);
+   pdata->tx_max_channel_count = XP_GET_BITS(pdata->pp1, XP_PROP_1,
+ MAX_TX_DMA);
+   pdata->rx_max_channel_count = XP_GET_BITS(pdata->pp1, XP_PROP_1,
+ MAX_RX_DMA);
+   pdata->tx_max_q_count = XP_GET_BITS(pdata->pp1, XP_PROP_1,
+   MAX_TX_QUEUES);
+   pdata->rx_max_q_count = XP_GET_BITS(pdata->pp1, XP_PROP_1,
+   MAX_RX_QUEUES);
if (netif_msg_probe(pdata)) {
dev_dbg(dev, "max tx/rx channel count = %u/%u\n",
pdata->tx_max_channel_count,
@@ -353,12 +370,13 @@ static int xgbe_pci_probe(struct pci_dev *pdev, const 
struct pci_device_id *id)
xgbe_set_counts(pdata);
 
/* Set the maximum fifo amounts */
-   reg = XP_IOREAD(pdata, XP_PROP_2);
-   pdata->tx_max_fifo_size = XP_GET_BITS(reg, XP_PROP_2, TX_FIFO_SIZE);
+   pdata->tx_max_fifo_size = XP_GET_BITS(pdata->pp2, XP_PROP_2,
+ TX_FIFO_SIZE);
pdata->tx_max_fifo_size *= 16384;
pdata->tx_max_fifo_size = min(pdata->tx_max_fifo_size,
  pdata->vdata->tx_max_fifo_size);
-   pdata->rx_max_fifo_size = XP_GET_BITS(reg, XP_PROP_2, RX_FIFO_SIZE);
+   pdata->rx_max_fifo_size = XP_GET_BITS(pdata->pp2, XP_PROP_2,
+ RX_FIFO_SIZE);
pdata->rx_max_fifo_size *= 16384;
pdata->rx_max_fifo_size = min(pdata->rx_max_fifo_size,
  pdata->vdata->rx_max_fifo_size);
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
index aac8843..123ceb0 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
@@ -2421,22 +2421,21 @@ static int xgbe_phy_link_status(struct xgbe_prv_data 
*pdata, int *an_restart)
 static void xgbe_phy_sfp_gpio_setup(struct xgbe_prv_data *pdata)
 {
struct xgbe_phy_data *phy_data = pdata->phy_data;
-   unsigned int reg;
-
-   reg = XP_IOREAD(pdata, XP_PROP_3);
 
phy_data->sfp_gpio_address = XGBE_GPIO_ADDRESS_PCA9555 +
-XP_GET_BITS(reg, XP_PROP_3, GPIO_ADDR);
+XP_GET_BITS(pdata->pp3, XP_PROP_3,
+GPIO_ADDR);
 
-   phy_data->sfp_gpio_mask = XP_GET_BITS(reg, XP_PROP_3, GPIO_MASK);
+   phy_data->sfp_gpio_mask = XP_GET_BITS(pdata->pp3, XP_PROP_3,
+ GPIO_MASK);
 
-   phy_data->sfp_gpio_rx_los = XP_GET_BITS(reg, XP_PROP_3,
+   phy_data->sfp_gpio_rx_los = XP_GET_BITS(pdata->

[PATCH net-next 00/12] amd-xgbe: AMD XGBE driver updates 2018-05-21

2018-05-21 Thread Tom Lendacky
The following updates are included in this driver update series:

- Fix the debug output for the max channels count
- Read (once) and save the port property registers during probe
- Remove the use of the comm_owned field
- Remove unused SFP diagnostic support indicator field
- Add ethtool --module-info support
- Add ethtool --show-ring/--set-ring support
- Update the driver in preparation for ethtool --set-channels support
- Add ethtool --show-channels/--set-channels support
- Update the driver to always perform link training in KR mode
- Advertise FEC support when using a KR re-driver
- Update the BelFuse quirk to now support SGMII
- Improve 100Mbps auto-negotiation for BelFuse parts

This patch series is based on net-next.

---

Tom Lendacky (12):
  amd-xgbe: Fix debug output of max channel counts
  amd-xgbe: Read and save the port property registers during probe
  amd-xgbe: Remove use of comm_owned field
  amd-xgbe: Remove field that indicates SFP diagnostic support
  amd-xgbe: Add ethtool support to retrieve SFP module info
  amd-xgbe: Add ethtool show/set ring parameter support
  amd-xgbe: Prepare for ethtool set-channel support
  amd-xgbe: Add ethtool show/set channels support
  amd-xgbe: Always attempt link training in KR mode
  amd-xgbe: Advertise FEC support with the KR re-driver
  amd-xgbe: Update the BelFuse quirk to support SGMII
  amd-xgbe: Improve SFP 100Mbps auto-negotiation


 drivers/net/ethernet/amd/xgbe/xgbe-drv.c |  137 +++---
 drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c |  214 
 drivers/net/ethernet/amd/xgbe/xgbe-main.c|   20 -
 drivers/net/ethernet/amd/xgbe/xgbe-mdio.c|  167 ++--
 drivers/net/ethernet/amd/xgbe/xgbe-pci.c |   36 ++-
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c  |  349 +++---
 drivers/net/ethernet/amd/xgbe/xgbe.h |   31 ++
 7 files changed, 696 insertions(+), 258 deletions(-)

-- 
Tom Lendacky


[PATCH net-next 01/12] amd-xgbe: Fix debug output of max channel counts

2018-05-21 Thread Tom Lendacky
A debug output print statement uses the wrong variable to output the
maximum Rx channel count (cut and paste error, basically).  Fix the
statement to use the proper variable.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-pci.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c
index 82d1f41..7b63521 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c
@@ -344,7 +344,7 @@ static int xgbe_pci_probe(struct pci_dev *pdev, const 
struct pci_device_id *id)
if (netif_msg_probe(pdata)) {
dev_dbg(dev, "max tx/rx channel count = %u/%u\n",
pdata->tx_max_channel_count,
-   pdata->tx_max_channel_count);
+   pdata->rx_max_channel_count);
dev_dbg(dev, "max tx/rx hw queue count = %u/%u\n",
pdata->tx_max_q_count, pdata->rx_max_q_count);
}



[PATCH net 3/3] amd-xgbe: Only use the SFP supported transceiver signals

2018-04-23 Thread Tom Lendacky
The SFP eeprom indicates the transceiver signals (Rx LOS, Tx Fault, etc.)
that it supports.  Update the driver to include checking the eeprom data
when deciding whether to use a transceiver signal.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c |   71 +--
 1 file changed, 54 insertions(+), 17 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
index b48efc0..aac8843 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
@@ -253,6 +253,10 @@ enum xgbe_sfp_speed {
 #define XGBE_SFP_BASE_VENDOR_SN4
 #define XGBE_SFP_BASE_VENDOR_SN_LEN16
 
+#define XGBE_SFP_EXTD_OPT1 1
+#define XGBE_SFP_EXTD_OPT1_RX_LOS  BIT(1)
+#define XGBE_SFP_EXTD_OPT1_TX_FAULTBIT(3)
+
 #define XGBE_SFP_EXTD_DIAG 28
 #define XGBE_SFP_EXTD_DIAG_ADDR_CHANGE BIT(2)
 
@@ -332,6 +336,7 @@ struct xgbe_phy_data {
 
unsigned int sfp_gpio_address;
unsigned int sfp_gpio_mask;
+   unsigned int sfp_gpio_inputs;
unsigned int sfp_gpio_rx_los;
unsigned int sfp_gpio_tx_fault;
unsigned int sfp_gpio_mod_absent;
@@ -986,6 +991,49 @@ static void xgbe_phy_sfp_external_phy(struct xgbe_prv_data 
*pdata)
phy_data->sfp_phy_avail = 1;
 }
 
+static bool xgbe_phy_check_sfp_rx_los(struct xgbe_phy_data *phy_data)
+{
+   u8 *sfp_extd = phy_data->sfp_eeprom.extd;
+
+   if (!(sfp_extd[XGBE_SFP_EXTD_OPT1] & XGBE_SFP_EXTD_OPT1_RX_LOS))
+   return false;
+
+   if (phy_data->sfp_gpio_mask & XGBE_GPIO_NO_RX_LOS)
+   return false;
+
+   if (phy_data->sfp_gpio_inputs & (1 << phy_data->sfp_gpio_rx_los))
+   return true;
+
+   return false;
+}
+
+static bool xgbe_phy_check_sfp_tx_fault(struct xgbe_phy_data *phy_data)
+{
+   u8 *sfp_extd = phy_data->sfp_eeprom.extd;
+
+   if (!(sfp_extd[XGBE_SFP_EXTD_OPT1] & XGBE_SFP_EXTD_OPT1_TX_FAULT))
+   return false;
+
+   if (phy_data->sfp_gpio_mask & XGBE_GPIO_NO_TX_FAULT)
+   return false;
+
+   if (phy_data->sfp_gpio_inputs & (1 << phy_data->sfp_gpio_tx_fault))
+   return true;
+
+   return false;
+}
+
+static bool xgbe_phy_check_sfp_mod_absent(struct xgbe_phy_data *phy_data)
+{
+   if (phy_data->sfp_gpio_mask & XGBE_GPIO_NO_MOD_ABSENT)
+   return false;
+
+   if (phy_data->sfp_gpio_inputs & (1 << phy_data->sfp_gpio_mod_absent))
+   return true;
+
+   return false;
+}
+
 static bool xgbe_phy_belfuse_parse_quirks(struct xgbe_prv_data *pdata)
 {
struct xgbe_phy_data *phy_data = pdata->phy_data;
@@ -1031,6 +1079,10 @@ static void xgbe_phy_sfp_parse_eeprom(struct 
xgbe_prv_data *pdata)
if (sfp_base[XGBE_SFP_BASE_EXT_ID] != XGBE_SFP_EXT_ID_SFP)
return;
 
+   /* Update transceiver signals (eeprom extd/options) */
+   phy_data->sfp_tx_fault = xgbe_phy_check_sfp_tx_fault(phy_data);
+   phy_data->sfp_rx_los = xgbe_phy_check_sfp_rx_los(phy_data);
+
if (xgbe_phy_sfp_parse_quirks(pdata))
return;
 
@@ -1196,7 +1248,6 @@ static int xgbe_phy_sfp_read_eeprom(struct xgbe_prv_data 
*pdata)
 static void xgbe_phy_sfp_signals(struct xgbe_prv_data *pdata)
 {
struct xgbe_phy_data *phy_data = pdata->phy_data;
-   unsigned int gpio_input;
u8 gpio_reg, gpio_ports[2];
int ret;
 
@@ -1211,23 +1262,9 @@ static void xgbe_phy_sfp_signals(struct xgbe_prv_data 
*pdata)
return;
}
 
-   gpio_input = (gpio_ports[1] << 8) | gpio_ports[0];
-
-   if (phy_data->sfp_gpio_mask & XGBE_GPIO_NO_MOD_ABSENT) {
-   /* No GPIO, just assume the module is present for now */
-   phy_data->sfp_mod_absent = 0;
-   } else {
-   if (!(gpio_input & (1 << phy_data->sfp_gpio_mod_absent)))
-   phy_data->sfp_mod_absent = 0;
-   }
-
-   if (!(phy_data->sfp_gpio_mask & XGBE_GPIO_NO_RX_LOS) &&
-   (gpio_input & (1 << phy_data->sfp_gpio_rx_los)))
-   phy_data->sfp_rx_los = 1;
+   phy_data->sfp_gpio_inputs = (gpio_ports[1] << 8) | gpio_ports[0];
 
-   if (!(phy_data->sfp_gpio_mask & XGBE_GPIO_NO_TX_FAULT) &&
-   (gpio_input & (1 << phy_data->sfp_gpio_tx_fault)))
-   phy_data->sfp_tx_fault = 1;
+   phy_data->sfp_mod_absent = xgbe_phy_check_sfp_mod_absent(phy_data);
 }
 
 static void xgbe_phy_sfp_mod_absent(struct xgbe_prv_data *pdata)



[PATCH net 2/3] amd-xgbe: Improve KR auto-negotiation and training

2018-04-23 Thread Tom Lendacky
Update xgbe-phy-v2.c to make use of the auto-negotiation (AN) phy hooks
to improve the ability to successfully complete Clause 73 AN when running
at 10gbps.  Hardware can sometimes have issues with CDR lock when the
AN DME page exchange is being performed.

The AN and KR training hooks are used as follows:
- The pre AN hook is used to disable CDR tracking in the PHY so that the
  DME page exchange can be successfully and consistently completed.
- The post KR training hook is used to re-enable the CDR tracking so that
  KR training can successfully complete.
- The post AN hook is used to check for an unsuccessful AN which will
  increase a CDR tracking enablement delay (up to a maximum value).

Add two debugfs entries to allow control over use of the CDR tracking
workaround.  The debugfs entries allow the CDR tracking workaround to
be disabled and determine whether to re-enable CDR tracking before or
after link training has been initiated.

Also, with these changes the receiver reset cycle that is performed during
the link status check can be performed less often.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-common.h  |8 ++
 drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c |   16 +++
 drivers/net/ethernet/amd/xgbe/xgbe-main.c|1 
 drivers/net/ethernet/amd/xgbe/xgbe-mdio.c|8 +-
 drivers/net/ethernet/amd/xgbe/xgbe-pci.c |2 
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c  |  125 ++
 drivers/net/ethernet/amd/xgbe/xgbe.h |4 +
 7 files changed, 160 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h 
b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
index 7ea72ef..d272dc6 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
@@ -1321,6 +1321,10 @@
 #define MDIO_VEND2_AN_STAT 0x8002
 #endif
 
+#ifndef MDIO_VEND2_PMA_CDR_CONTROL
+#define MDIO_VEND2_PMA_CDR_CONTROL 0x8056
+#endif
+
 #ifndef MDIO_CTRL1_SPEED1G
 #define MDIO_CTRL1_SPEED1G (MDIO_CTRL1_SPEED10G & ~BMCR_SPEED100)
 #endif
@@ -1369,6 +1373,10 @@
 #define XGBE_AN_CL37_TX_CONFIG_MASK0x08
 #define XGBE_AN_CL37_MII_CTRL_8BIT 0x0100
 
+#define XGBE_PMA_CDR_TRACK_EN_MASK 0x01
+#define XGBE_PMA_CDR_TRACK_EN_OFF  0x00
+#define XGBE_PMA_CDR_TRACK_EN_ON   0x01
+
 /* Bit setting and getting macros
  *  The get macro will extract the current bit field value from within
  *  the variable
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c
index 7d128be..b911439 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c
@@ -519,6 +519,22 @@ void xgbe_debugfs_init(struct xgbe_prv_data *pdata)
   "debugfs_create_file failed\n");
}
 
+   if (pdata->vdata->an_cdr_workaround) {
+   pfile = debugfs_create_bool("an_cdr_workaround", 0600,
+   pdata->xgbe_debugfs,
+   >debugfs_an_cdr_workaround);
+   if (!pfile)
+   netdev_err(pdata->netdev,
+  "debugfs_create_bool failed\n");
+
+   pfile = debugfs_create_bool("an_cdr_track_early", 0600,
+   pdata->xgbe_debugfs,
+   >debugfs_an_cdr_track_early);
+   if (!pfile)
+   netdev_err(pdata->netdev,
+  "debugfs_create_bool failed\n");
+   }
+
kfree(buf);
 }
 
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
index 795e556..441d0973 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
@@ -349,6 +349,7 @@ int xgbe_config_netdev(struct xgbe_prv_data *pdata)
XGMAC_SET_BITS(pdata->rss_options, MAC_RSSCR, UDP4TE, 1);
 
/* Call MDIO/PHY initialization routine */
+   pdata->debugfs_an_cdr_workaround = pdata->vdata->an_cdr_workaround;
ret = pdata->phy_if.phy_init(pdata);
if (ret)
return ret;
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
index e3d361e..1b45cd7 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
@@ -432,6 +432,8 @@ static void xgbe_an73_disable(struct xgbe_prv_data *pdata)
xgbe_an73_set(pdata, false, false);
xgbe_an73_disable_interrupts(pdata);
 
+   pdata->an_start = 0;
+
netif_dbg(pdata, link, pdata->netdev, "CL73 AN disabled\n");
 }
 
@@ -511,11 +513,11 @@ static enum xgbe_an xgbe_an73_tx_training(struct 
xgbe_prv_data *

[PATCH net 1/3] amd-xgbe: Add pre/post auto-negotiation phy hooks

2018-04-23 Thread Tom Lendacky
Add hooks to the driver auto-negotiation (AN) flow to allow the different
phy implementations to perform any steps necessary to improve AN.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-mdio.c |   16 ++--
 drivers/net/ethernet/amd/xgbe/xgbe.h  |5 +
 2 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
index 072b9f6..e3d361e 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
@@ -437,6 +437,9 @@ static void xgbe_an73_disable(struct xgbe_prv_data *pdata)
 
 static void xgbe_an_restart(struct xgbe_prv_data *pdata)
 {
+   if (pdata->phy_if.phy_impl.an_pre)
+   pdata->phy_if.phy_impl.an_pre(pdata);
+
switch (pdata->an_mode) {
case XGBE_AN_MODE_CL73:
case XGBE_AN_MODE_CL73_REDRV:
@@ -453,6 +456,9 @@ static void xgbe_an_restart(struct xgbe_prv_data *pdata)
 
 static void xgbe_an_disable(struct xgbe_prv_data *pdata)
 {
+   if (pdata->phy_if.phy_impl.an_post)
+   pdata->phy_if.phy_impl.an_post(pdata);
+
switch (pdata->an_mode) {
case XGBE_AN_MODE_CL73:
case XGBE_AN_MODE_CL73_REDRV:
@@ -637,11 +643,11 @@ static enum xgbe_an xgbe_an73_incompat_link(struct 
xgbe_prv_data *pdata)
return XGBE_AN_NO_LINK;
}
 
-   xgbe_an73_disable(pdata);
+   xgbe_an_disable(pdata);
 
xgbe_switch_mode(pdata);
 
-   xgbe_an73_restart(pdata);
+   xgbe_an_restart(pdata);
 
return XGBE_AN_INCOMPAT_LINK;
 }
@@ -820,6 +826,9 @@ static void xgbe_an37_state_machine(struct xgbe_prv_data 
*pdata)
pdata->an_result = pdata->an_state;
pdata->an_state = XGBE_AN_READY;
 
+   if (pdata->phy_if.phy_impl.an_post)
+   pdata->phy_if.phy_impl.an_post(pdata);
+
netif_dbg(pdata, link, pdata->netdev, "CL37 AN result: %s\n",
  xgbe_state_as_string(pdata->an_result));
}
@@ -903,6 +912,9 @@ static void xgbe_an73_state_machine(struct xgbe_prv_data 
*pdata)
pdata->kx_state = XGBE_RX_BPA;
pdata->an_start = 0;
 
+   if (pdata->phy_if.phy_impl.an_post)
+   pdata->phy_if.phy_impl.an_post(pdata);
+
netif_dbg(pdata, link, pdata->netdev, "CL73 AN result: %s\n",
  xgbe_state_as_string(pdata->an_result));
}
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h 
b/drivers/net/ethernet/amd/xgbe/xgbe.h
index ad102c8..fa0b51e 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe.h
@@ -833,6 +833,7 @@ struct xgbe_hw_if {
 /* This structure represents implementation specific routines for an
  * implementation of a PHY. All routines are required unless noted below.
  *   Optional routines:
+ * an_pre, an_post
  * kr_training_pre, kr_training_post
  */
 struct xgbe_phy_impl_if {
@@ -875,6 +876,10 @@ struct xgbe_phy_impl_if {
/* Process results of auto-negotiation */
enum xgbe_mode (*an_outcome)(struct xgbe_prv_data *);
 
+   /* Pre/Post auto-negotiation support */
+   void (*an_pre)(struct xgbe_prv_data *);
+   void (*an_post)(struct xgbe_prv_data *);
+
/* Pre/Post KR training enablement support */
void (*kr_training_pre)(struct xgbe_prv_data *);
void (*kr_training_post)(struct xgbe_prv_data *);



[PATCH net 0/3] amd-xgbe: AMD XGBE driver fixes 2018-04-23

2018-04-23 Thread Tom Lendacky
This patch series addresses some issues in the AMD XGBE driver.

The following fixes are included in this driver update series:

- Improve KR auto-negotiation and training (2 patches)
  - Add pre and post auto-negotiation hooks
  - Use the pre and post auto-negotiation hooks to disable CDR tracking
during auto-negotiation page exchange in KR mode
- Check for SFP tranceiver signal support and only use the signal if the
  SFP indicates that it is supported

This patch series is based on net.

---

Please queue this patch series up to stable releases 4.14 and above.

Tom Lendacky (3):
  amd-xgbe: Add pre/post auto-negotiation phy hooks
  amd-xgbe: Improve KR auto-negotiation and training
  amd-xgbe: Only use the SFP supported transceiver signals


 drivers/net/ethernet/amd/xgbe/xgbe-common.h  |8 +
 drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c |   16 ++
 drivers/net/ethernet/amd/xgbe/xgbe-main.c|1 
 drivers/net/ethernet/amd/xgbe/xgbe-mdio.c|   24 +++
 drivers/net/ethernet/amd/xgbe/xgbe-pci.c |2 
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c  |  196 --
 drivers/net/ethernet/amd/xgbe/xgbe.h |9 +
 7 files changed, 233 insertions(+), 23 deletions(-)

-- 
Tom Lendacky


[PATCH net] amd-xgbe: Restore PCI interrupt enablement setting on resume

2018-02-20 Thread Tom Lendacky
After resuming from suspend, the PCI device support must re-enable the
interrupt setting so that interrupts are actually delivered.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---

Please queue this patch up to stable releases 4.14 and above.

 drivers/net/ethernet/amd/xgbe/xgbe-pci.c |2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c
index 3e5833c..eb23f9b 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c
@@ -426,6 +426,8 @@ static int xgbe_pci_resume(struct pci_dev *pdev)
struct net_device *netdev = pdata->netdev;
int ret = 0;
 
+   XP_IOWRITE(pdata, XP_INT_EN, 0x1f);
+
pdata->lpm_ctrl &= ~MDIO_CTRL1_LPOWER;
XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, pdata->lpm_ctrl);
 



Re: [PATCH 4/4] net: amd-xgbe: fix comparison to bitshift when dealing with a mask

2018-02-05 Thread Tom Lendacky
On 2/5/2018 2:10 PM, Wolfram Sang wrote:
> Due to a typo, the mask was destroyed by a comparison instead of a bit
> shift.
> 
> Signed-off-by: Wolfram Sang <wsa+rene...@sang-engineering.com>

Excellent find.

Acked-by: Tom Lendacky <thomas.lenda...@amd.com>

David, this should also be applied to the 4.14 and 4.15 stable releases.

Thanks,
Tom

> ---
> Only build tested. To be applied individually per subsystem.
> 
>  drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c 
> b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
> index 7a3ebfd236f5eb..100adee778dfd6 100644
> --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
> +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
> @@ -595,7 +595,7 @@ static void xgbe_isr_task(unsigned long data)
>  
>   reissue_mask = 1 << 0;
>   if (!pdata->per_channel_irq)
> - reissue_mask |= 0x < 4;
> + reissue_mask |= 0x << 4;
>  
>   XP_IOWRITE(pdata, XP_INT_REISSUE_EN, reissue_mask);
>   }
> 


Re: [PATCH v1] net: amd-xgbe: Get rid of custom hex_dump_to_buffer()

2017-12-19 Thread Tom Lendacky
On 12/19/2017 12:02 PM, Andy Shevchenko wrote:
> Get rid of yet another custom hex_dump_to_buffer().
> 
> The output is slightly changed, i.e. each byte followed by white space.
> 
> Note, we don't use print_hex_dump() here since the original code uses
> nedev_dbg().
> 
> Signed-off-by: Andy Shevchenko <andriy.shevche...@linux.intel.com>
> ---
>  drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 23 ++-
>  1 file changed, 6 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c 
> b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
> index a74a8fbad53a..fc58dc43a5bd 100644
> --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
> +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
> @@ -2930,9 +2930,8 @@ void xgbe_dump_rx_desc(struct xgbe_prv_data *pdata, 
> struct xgbe_ring *ring,
>  void xgbe_print_pkt(struct net_device *netdev, struct sk_buff *skb, bool 
> tx_rx)
>  {
>   struct ethhdr *eth = (struct ethhdr *)skb->data;
> - unsigned char *buf = skb->data;
>   unsigned char buffer[128];
> - unsigned int i, j;
> + unsigned int i;
>  
>   netdev_dbg(netdev, "\n** SKB dump \n");
>  
> @@ -2943,22 +2942,12 @@ void xgbe_print_pkt(struct net_device *netdev, struct 
> sk_buff *skb, bool tx_rx)
>   netdev_dbg(netdev, "Src MAC addr: %pM\n", eth->h_source);
>   netdev_dbg(netdev, "Protocol: %#06hx\n", ntohs(eth->h_proto));
>  
> - for (i = 0, j = 0; i < skb->len;) {
> - j += snprintf(buffer + j, sizeof(buffer) - j, "%02hhx",
> -   buf[i++]);
> -
> - if ((i % 32) == 0) {
> - netdev_dbg(netdev, "  %#06x: %s\n", i - 32, buffer);
> - j = 0;
> - } else if ((i % 16) == 0) {
> - buffer[j++] = ' ';
> - buffer[j++] = ' ';
> - } else if ((i % 4) == 0) {
> - buffer[j++] = ' ';
> - }
> + for (i = 0; i < skb->len; i += 32) {
> + unsigned int len = min(skb->len - i, 32U);
> +
> + hex_dump_to_buffer(>data[i], len, 32, 1, buffer, 128, 
> false);

I'd prefer to see sizeof(buffer) vs the hard-coded 128 here.  Also, this
line exceeds 80 characters, so it should be split.

With those changes:

Acked-by: Tom Lendacky <thomas.lenda...@amd.com>

> + netdev_dbg(netdev, "  %#06x: %s\n", i, buffer);
>   }
> - if (i % 32)
> - netdev_dbg(netdev, "  %#06x: %s\n", i - (i % 32), buffer);
>  
>   netdev_dbg(netdev, "\n** SKB dump \n");
>  }
> 


[PATCH net-next v1] amd-xgbe: Interrupt summary bits are h/w version dependent

2017-08-28 Thread Tom Lendacky
There is a difference in the bit position of the normal interrupt summary
enable (NIE) and abnormal interrupt summary enable (AIE) between revisions
of the hardware.  For older revisions the NIE and AIE bits are positions
16 and 15 respectively.  For newer revisions the NIE and AIE bits are
positions 15 and 14.  The effect in changing the bit position is that
newer hardware won't receive AIE interrupts in the current version of the
driver.  Specifically, the driver uses this interrupt to collect
statistics on when a receive buffer unavailable event occurs and to
restart the driver/device when a fatal bus error occurs.

Update the driver to set the interrupt enable bit based on the reported
version of the hardware.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-common.h |8 ++--
 drivers/net/ethernet/amd/xgbe/xgbe-dev.c|   13 ++---
 2 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h 
b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
index 9431330..7ea72ef 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
@@ -210,11 +210,15 @@
 #define DMA_CH_CR_PBLX8_WIDTH  1
 #define DMA_CH_CR_SPH_INDEX24
 #define DMA_CH_CR_SPH_WIDTH1
-#define DMA_CH_IER_AIE_INDEX   15
+#define DMA_CH_IER_AIE20_INDEX 15
+#define DMA_CH_IER_AIE20_WIDTH 1
+#define DMA_CH_IER_AIE_INDEX   14
 #define DMA_CH_IER_AIE_WIDTH   1
 #define DMA_CH_IER_FBEE_INDEX  12
 #define DMA_CH_IER_FBEE_WIDTH  1
-#define DMA_CH_IER_NIE_INDEX   16
+#define DMA_CH_IER_NIE20_INDEX 16
+#define DMA_CH_IER_NIE20_WIDTH 1
+#define DMA_CH_IER_NIE_INDEX   15
 #define DMA_CH_IER_NIE_WIDTH   1
 #define DMA_CH_IER_RBUE_INDEX  7
 #define DMA_CH_IER_RBUE_WIDTH  1
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index 671203d..e107e18 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -649,13 +649,15 @@ static void xgbe_config_flow_control(struct xgbe_prv_data 
*pdata)
 static void xgbe_enable_dma_interrupts(struct xgbe_prv_data *pdata)
 {
struct xgbe_channel *channel;
-   unsigned int i;
+   unsigned int i, ver;
 
/* Set the interrupt mode if supported */
if (pdata->channel_irq_mode)
XGMAC_IOWRITE_BITS(pdata, DMA_MR, INTM,
   pdata->channel_irq_mode);
 
+   ver = XGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER);
+
for (i = 0; i < pdata->channel_count; i++) {
channel = pdata->channel[i];
 
@@ -671,8 +673,13 @@ static void xgbe_enable_dma_interrupts(struct 
xgbe_prv_data *pdata)
 *   AIE  - Abnormal Interrupt Summary Enable
 *   FBEE - Fatal Bus Error Enable
 */
-   XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, NIE, 1);
-   XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, AIE, 1);
+   if (ver < 0x21) {
+   XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, NIE20, 1);
+   XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, AIE20, 1);
+   } else {
+   XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, NIE, 1);
+   XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, AIE, 1);
+   }
XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, FBEE, 1);
 
if (channel->tx_ring) {



[PATCH net-next v2 13/13] amd-xgbe: Add additional ethtool statistics

2017-08-18 Thread Tom Lendacky
Add some additional statistics for tracking VXLAN packets and checksum
errors.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-dev.c |8 +++-
 drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c |4 
 drivers/net/ethernet/amd/xgbe/xgbe.h |5 +
 3 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index 1bf671e..671203d 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -1805,10 +1805,13 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
  packet->length);
}
 
-   if (vxlan)
+   if (vxlan) {
XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, VNP,
  TX_NORMAL_DESC3_VXLAN_PACKET);
 
+   pdata->ext_stats.tx_vxlan_packets += packet->tx_packets;
+   }
+
for (i = cur_index - start_index + 1; i < packet->rdesc_count; i++) {
cur_index++;
rdata = XGBE_GET_DESC_DATA(ring, cur_index);
@@ -1981,6 +1984,7 @@ static int xgbe_dev_read(struct xgbe_channel *channel)
if (XGMAC_GET_BITS_LE(rdesc->desc2, RX_NORMAL_DESC2, TNP)) {
XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
   TNP, 1);
+   pdata->ext_stats.rx_vxlan_packets++;
 
l34t = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, L34T);
switch (l34t) {
@@ -2018,11 +2022,13 @@ static int xgbe_dev_read(struct xgbe_channel *channel)
   CSUM_DONE, 0);
XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
   TNPCSUM_DONE, 0);
+   pdata->ext_stats.rx_csum_errors++;
} else if (tnp && ((etlt == 0x09) || (etlt == 0x0a))) {
XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
   CSUM_DONE, 0);
XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
   TNPCSUM_DONE, 0);
+   pdata->ext_stats.rx_vxlan_csum_errors++;
} else {
XGMAC_SET_BITS(packet->errors, RX_PACKET_ERRORS,
   FRAME, 1);
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
index cea25ac..ff397bb 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
@@ -146,6 +146,7 @@ struct xgbe_stats {
XGMAC_MMC_STAT("tx_broadcast_packets", txbroadcastframes_gb),
XGMAC_MMC_STAT("tx_multicast_packets", txmulticastframes_gb),
XGMAC_MMC_STAT("tx_vlan_packets", txvlanframes_g),
+   XGMAC_EXT_STAT("tx_vxlan_packets", tx_vxlan_packets),
XGMAC_EXT_STAT("tx_tso_packets", tx_tso_packets),
XGMAC_MMC_STAT("tx_64_byte_packets", tx64octets_gb),
XGMAC_MMC_STAT("tx_65_to_127_byte_packets", tx65to127octets_gb),
@@ -162,6 +163,7 @@ struct xgbe_stats {
XGMAC_MMC_STAT("rx_broadcast_packets", rxbroadcastframes_g),
XGMAC_MMC_STAT("rx_multicast_packets", rxmulticastframes_g),
XGMAC_MMC_STAT("rx_vlan_packets", rxvlanframes_gb),
+   XGMAC_EXT_STAT("rx_vxlan_packets", rx_vxlan_packets),
XGMAC_MMC_STAT("rx_64_byte_packets", rx64octets_gb),
XGMAC_MMC_STAT("rx_65_to_127_byte_packets", rx65to127octets_gb),
XGMAC_MMC_STAT("rx_128_to_255_byte_packets", rx128to255octets_gb),
@@ -177,6 +179,8 @@ struct xgbe_stats {
XGMAC_MMC_STAT("rx_out_of_range_errors", rxoutofrangetype),
XGMAC_MMC_STAT("rx_fifo_overflow_errors", rxfifooverflow),
XGMAC_MMC_STAT("rx_watchdog_errors", rxwatchdogerror),
+   XGMAC_EXT_STAT("rx_csum_errors", rx_csum_errors),
+   XGMAC_EXT_STAT("rx_vxlan_csum_errors", rx_vxlan_csum_errors),
XGMAC_MMC_STAT("rx_pause_frames", rxpauseframes),
XGMAC_EXT_STAT("rx_split_header_packets", rx_split_header_packets),
XGMAC_EXT_STAT("rx_buffer_unavailable", rx_buffer_unavailable),
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h 
b/drivers/net/ethernet/amd/xgbe/xgbe.h
index db155fe..ad102c8 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe.h
@@ -715,6 +715,11 @@ struct xgbe_ext_stats {
u64 txq_bytes[XGBE_MAX_DMA_CHANNELS];
u64 rxq_packets[XGBE_MAX_DMA_CHANNELS];
u64 rxq_bytes[XGBE_MAX_DMA_CHANNELS];
+
+   u64 tx_vxlan_packets;
+   u64 rx_vxlan_packets;
+   u64 rx_csum_errors;
+   u64 rx_vxlan_csum_errors;
 };
 
 struct xgbe_hw_if {



[PATCH net-next v2 12/13] amd-xgbe: Add support for VXLAN offload capabilities

2017-08-18 Thread Tom Lendacky
The hardware has the capability to perform checksum offload support
(both Tx and Rx) and TSO support for VXLAN packets. Add the support
required to enable this.

The hardware can only support a single VXLAN port for offload. If more
than one VXLAN port is added then the offload capabilities have to be
disabled and can no longer be advertised.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-common.h |   24 ++
 drivers/net/ethernet/amd/xgbe/xgbe-dev.c|   92 +++
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c|  365 +++
 drivers/net/ethernet/amd/xgbe/xgbe-main.c   |   23 ++
 drivers/net/ethernet/amd/xgbe/xgbe.h|   22 ++
 5 files changed, 520 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h 
b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
index d07edf9..9431330 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
@@ -298,6 +298,7 @@
 #define MAC_RWKPFR 0x00c4
 #define MAC_LPICSR 0x00d0
 #define MAC_LPITCR 0x00d4
+#define MAC_TIR0x00e0
 #define MAC_VR 0x0110
 #define MAC_DR 0x0114
 #define MAC_HWF0R  0x011c
@@ -364,6 +365,8 @@
 #define MAC_HWF0R_TXCOESEL_WIDTH   1
 #define MAC_HWF0R_VLHASH_INDEX 4
 #define MAC_HWF0R_VLHASH_WIDTH 1
+#define MAC_HWF0R_VXN_INDEX29
+#define MAC_HWF0R_VXN_WIDTH1
 #define MAC_HWF1R_ADDR64_INDEX 14
 #define MAC_HWF1R_ADDR64_WIDTH 2
 #define MAC_HWF1R_ADVTHWORD_INDEX  13
@@ -448,6 +451,8 @@
 #define MAC_PFR_PR_WIDTH   1
 #define MAC_PFR_VTFE_INDEX 16
 #define MAC_PFR_VTFE_WIDTH 1
+#define MAC_PFR_VUCC_INDEX 22
+#define MAC_PFR_VUCC_WIDTH 1
 #define MAC_PMTCSR_MGKPKTEN_INDEX  1
 #define MAC_PMTCSR_MGKPKTEN_WIDTH  1
 #define MAC_PMTCSR_PWRDWN_INDEX0
@@ -510,6 +515,12 @@
 #define MAC_TCR_SS_WIDTH   2
 #define MAC_TCR_TE_INDEX   0
 #define MAC_TCR_TE_WIDTH   1
+#define MAC_TCR_VNE_INDEX  24
+#define MAC_TCR_VNE_WIDTH  1
+#define MAC_TCR_VNM_INDEX  25
+#define MAC_TCR_VNM_WIDTH  1
+#define MAC_TIR_TNID_INDEX 0
+#define MAC_TIR_TNID_WIDTH 16
 #define MAC_TSCR_AV8021ASMEN_INDEX 28
 #define MAC_TSCR_AV8021ASMEN_WIDTH 1
 #define MAC_TSCR_SNAPTYPSEL_INDEX  16
@@ -1153,11 +1164,17 @@
 #define RX_PACKET_ATTRIBUTES_RSS_HASH_WIDTH1
 #define RX_PACKET_ATTRIBUTES_FIRST_INDEX   7
 #define RX_PACKET_ATTRIBUTES_FIRST_WIDTH   1
+#define RX_PACKET_ATTRIBUTES_TNP_INDEX 8
+#define RX_PACKET_ATTRIBUTES_TNP_WIDTH 1
+#define RX_PACKET_ATTRIBUTES_TNPCSUM_DONE_INDEX9
+#define RX_PACKET_ATTRIBUTES_TNPCSUM_DONE_WIDTH1
 
 #define RX_NORMAL_DESC0_OVT_INDEX  0
 #define RX_NORMAL_DESC0_OVT_WIDTH  16
 #define RX_NORMAL_DESC2_HL_INDEX   0
 #define RX_NORMAL_DESC2_HL_WIDTH   10
+#define RX_NORMAL_DESC2_TNP_INDEX  11
+#define RX_NORMAL_DESC2_TNP_WIDTH  1
 #define RX_NORMAL_DESC3_CDA_INDEX  27
 #define RX_NORMAL_DESC3_CDA_WIDTH  1
 #define RX_NORMAL_DESC3_CTXT_INDEX 30
@@ -1184,9 +1201,11 @@
 #define RX_DESC3_L34T_IPV4_TCP 1
 #define RX_DESC3_L34T_IPV4_UDP 2
 #define RX_DESC3_L34T_IPV4_ICMP3
+#define RX_DESC3_L34T_IPV4_UNKNOWN 7
 #define RX_DESC3_L34T_IPV6_TCP 9
 #define RX_DESC3_L34T_IPV6_UDP 10
 #define RX_DESC3_L34T_IPV6_ICMP11
+#define RX_DESC3_L34T_IPV6_UNKNOWN 15
 
 #define RX_CONTEXT_DESC3_TSA_INDEX 4
 #define RX_CONTEXT_DESC3_TSA_WIDTH 1
@@ -1201,6 +1220,8 @@
 #define TX_PACKET_ATTRIBUTES_VLAN_CTAG_WIDTH   1
 #define TX_PACKET_ATTRIBUTES_PTP_INDEX 3
 #define TX_PACKET_ATTRIBUTES_PTP_WIDTH 1
+#define TX_PACKET_ATTRIBUTES_VXLAN_INDEX   4
+#define TX_PACKET_ATTRIBUTES_VXLAN_WIDTH   1
 
 #define TX_CONTEXT_DESC2_MSS_INDEX 0
 #define TX_CONTEXT_DESC2_MSS_WIDTH 15
@@ -1241,8 +1262,11 @@
 #define TX_NORMAL_DESC3_TCPPL_WIDTH18
 #define TX_NORMAL_DESC3_TSE_INDEX  18
 #define TX_NORMAL_DESC3_TSE_WIDTH  1
+#define TX_NORMAL_DESC3_VNP_INDEX  23
+#define TX_NORMAL_DESC3_VNP_WIDTH  3
 
 #define TX_NORMAL_DESC2_VLAN_INSERT0x2
+#define TX_NORMAL_DESC3_VXLAN_PACKET   0x3
 
 /* MDIO undefined or vendor specific registers */
 #ifndef MDIO_PMA_10GBR_PMD_CTRL
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index a978408..1bf671e 100644
--- a/drivers/net/et

[PATCH net-next v2 11/13] amd-xgbe: Convert to using the new link mode settings

2017-08-18 Thread Tom Lendacky
Convert from using the old u32 supported, advertising, etc. link settings
to the new link mode settings that support bit positions / settings
greater than 32 bits.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c |   56 ++--
 drivers/net/ethernet/amd/xgbe/xgbe-mdio.c|   77 +++---
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v1.c  |   54 ++--
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c  |  350 ++
 drivers/net/ethernet/amd/xgbe/xgbe.h |   50 +++-
 5 files changed, 345 insertions(+), 242 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
index f80b186..cea25ac 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
@@ -267,6 +267,7 @@ static int xgbe_set_pauseparam(struct net_device *netdev,
   struct ethtool_pauseparam *pause)
 {
struct xgbe_prv_data *pdata = netdev_priv(netdev);
+   struct ethtool_link_ksettings *lks = >phy.lks;
int ret = 0;
 
if (pause->autoneg && (pdata->phy.autoneg != AUTONEG_ENABLE)) {
@@ -279,16 +280,21 @@ static int xgbe_set_pauseparam(struct net_device *netdev,
pdata->phy.tx_pause = pause->tx_pause;
pdata->phy.rx_pause = pause->rx_pause;
 
-   pdata->phy.advertising &= ~ADVERTISED_Pause;
-   pdata->phy.advertising &= ~ADVERTISED_Asym_Pause;
+   XGBE_CLR_ADV(lks, Pause);
+   XGBE_CLR_ADV(lks, Asym_Pause);
 
if (pause->rx_pause) {
-   pdata->phy.advertising |= ADVERTISED_Pause;
-   pdata->phy.advertising |= ADVERTISED_Asym_Pause;
+   XGBE_SET_ADV(lks, Pause);
+   XGBE_SET_ADV(lks, Asym_Pause);
}
 
-   if (pause->tx_pause)
-   pdata->phy.advertising ^= ADVERTISED_Asym_Pause;
+   if (pause->tx_pause) {
+   /* Equivalent to XOR of Asym_Pause */
+   if (XGBE_ADV(lks, Asym_Pause))
+   XGBE_CLR_ADV(lks, Asym_Pause);
+   else
+   XGBE_SET_ADV(lks, Asym_Pause);
+   }
 
if (netif_running(netdev))
ret = pdata->phy_if.phy_config_aneg(pdata);
@@ -300,22 +306,20 @@ static int xgbe_get_link_ksettings(struct net_device 
*netdev,
   struct ethtool_link_ksettings *cmd)
 {
struct xgbe_prv_data *pdata = netdev_priv(netdev);
+   struct ethtool_link_ksettings *lks = >phy.lks;
 
cmd->base.phy_address = pdata->phy.address;
 
-   ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
-   pdata->phy.supported);
-   ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
-   pdata->phy.advertising);
-   ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.lp_advertising,
-   pdata->phy.lp_advertising);
-
cmd->base.autoneg = pdata->phy.autoneg;
cmd->base.speed = pdata->phy.speed;
cmd->base.duplex = pdata->phy.duplex;
 
cmd->base.port = PORT_NONE;
 
+   XGBE_LM_COPY(cmd, supported, lks, supported);
+   XGBE_LM_COPY(cmd, advertising, lks, advertising);
+   XGBE_LM_COPY(cmd, lp_advertising, lks, lp_advertising);
+
return 0;
 }
 
@@ -323,7 +327,8 @@ static int xgbe_set_link_ksettings(struct net_device 
*netdev,
   const struct ethtool_link_ksettings *cmd)
 {
struct xgbe_prv_data *pdata = netdev_priv(netdev);
-   u32 advertising;
+   struct ethtool_link_ksettings *lks = >phy.lks;
+   __ETHTOOL_DECLARE_LINK_MODE_MASK(advertising);
u32 speed;
int ret;
 
@@ -355,15 +360,17 @@ static int xgbe_set_link_ksettings(struct net_device 
*netdev,
}
}
 
-   ethtool_convert_link_mode_to_legacy_u32(,
-   cmd->link_modes.advertising);
-
netif_dbg(pdata, link, netdev,
- "requested advertisement %#x, phy supported %#x\n",
- advertising, pdata->phy.supported);
+ "requested advertisement 0x%*pb, phy supported 0x%*pb\n",
+ __ETHTOOL_LINK_MODE_MASK_NBITS, cmd->link_modes.advertising,
+ __ETHTOOL_LINK_MODE_MASK_NBITS, lks->link_modes.supported);
+
+   bitmap_and(advertising,
+  cmd->link_modes.advertising, lks->link_modes.supported,
+  __ETHTOOL_LINK_MODE_MASK_NBITS);
 
-   advertising &= pdata->phy.supported;
-   if ((cmd->base.autoneg == AUTONEG_ENABLE) && !advertising) {
+   if ((cmd->base.autoneg == AUTONEG_ENABLE) &&
+  

[PATCH net-next v2 07/13] amd-xgbe: Optimize DMA channel interrupt enablement

2017-08-18 Thread Tom Lendacky
Currently whenever the driver needs to enable or disable interrupts for
a DMA channel it reads the interrupt enable register (IER), updates the
value and then writes the new value back to the IER. Since the hardware
does not change the IER, software can track this value and elimiate the
need to read it each time.

Add the IER value to the channel related data structure and use that as
the base for enabling and disabling interrupts, thus removing the need
for the MMIO read.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-dev.c |   77 ++
 drivers/net/ethernet/amd/xgbe/xgbe.h |4 +-
 2 files changed, 37 insertions(+), 44 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index bb60507..75a479c 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -605,7 +605,6 @@ static void xgbe_config_flow_control(struct xgbe_prv_data 
*pdata)
 static void xgbe_enable_dma_interrupts(struct xgbe_prv_data *pdata)
 {
struct xgbe_channel *channel;
-   unsigned int dma_ch_isr, dma_ch_ier;
unsigned int i;
 
/* Set the interrupt mode if supported */
@@ -617,20 +616,20 @@ static void xgbe_enable_dma_interrupts(struct 
xgbe_prv_data *pdata)
channel = pdata->channel[i];
 
/* Clear all the interrupts which are set */
-   dma_ch_isr = XGMAC_DMA_IOREAD(channel, DMA_CH_SR);
-   XGMAC_DMA_IOWRITE(channel, DMA_CH_SR, dma_ch_isr);
+   XGMAC_DMA_IOWRITE(channel, DMA_CH_SR,
+ XGMAC_DMA_IOREAD(channel, DMA_CH_SR));
 
/* Clear all interrupt enable bits */
-   dma_ch_ier = 0;
+   channel->curr_ier = 0;
 
/* Enable following interrupts
 *   NIE  - Normal Interrupt Summary Enable
 *   AIE  - Abnormal Interrupt Summary Enable
 *   FBEE - Fatal Bus Error Enable
 */
-   XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, NIE, 1);
-   XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, AIE, 1);
-   XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, FBEE, 1);
+   XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, NIE, 1);
+   XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, AIE, 1);
+   XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, FBEE, 1);
 
if (channel->tx_ring) {
/* Enable the following Tx interrupts
@@ -639,7 +638,8 @@ static void xgbe_enable_dma_interrupts(struct xgbe_prv_data 
*pdata)
 *  mode)
 */
if (!pdata->per_channel_irq || pdata->channel_irq_mode)
-   XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TIE, 1);
+   XGMAC_SET_BITS(channel->curr_ier,
+  DMA_CH_IER, TIE, 1);
}
if (channel->rx_ring) {
/* Enable following Rx interrupts
@@ -648,12 +648,13 @@ static void xgbe_enable_dma_interrupts(struct 
xgbe_prv_data *pdata)
 *  per channel interrupts in edge triggered
 *  mode)
 */
-   XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RBUE, 1);
+   XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, RBUE, 1);
if (!pdata->per_channel_irq || pdata->channel_irq_mode)
-   XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RIE, 1);
+   XGMAC_SET_BITS(channel->curr_ier,
+  DMA_CH_IER, RIE, 1);
}
 
-   XGMAC_DMA_IOWRITE(channel, DMA_CH_IER, dma_ch_ier);
+   XGMAC_DMA_IOWRITE(channel, DMA_CH_IER, channel->curr_ier);
}
 }
 
@@ -1964,44 +1965,40 @@ static int xgbe_is_last_desc(struct xgbe_ring_desc 
*rdesc)
 static int xgbe_enable_int(struct xgbe_channel *channel,
   enum xgbe_int int_id)
 {
-   unsigned int dma_ch_ier;
-
-   dma_ch_ier = XGMAC_DMA_IOREAD(channel, DMA_CH_IER);
-
switch (int_id) {
case XGMAC_INT_DMA_CH_SR_TI:
-   XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TIE, 1);
+   XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, TIE, 1);
break;
case XGMAC_INT_DMA_CH_SR_TPS:
-   XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TXSE, 1);
+   XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, TXSE, 1);
break;
case XGMAC_INT_DMA_CH_SR_TBU:
-   XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TBUE, 1);
+   XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, TBUE, 1)

[PATCH net-next v2 09/13] amd-xgbe: Add per queue Tx and Rx statistics

2017-08-18 Thread Tom Lendacky
Add per queue Tx and Rx packet and byte counts.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-dev.c |   23 ---
 drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c |   26 +-
 drivers/net/ethernet/amd/xgbe/xgbe.h |5 +
 3 files changed, 46 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index 75a479c..a978408 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -1609,6 +1609,7 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
struct xgbe_ring_data *rdata;
struct xgbe_ring_desc *rdesc;
struct xgbe_packet_data *packet = >packet_data;
+   unsigned int tx_packets, tx_bytes;
unsigned int csum, tso, vlan;
unsigned int tso_context, vlan_context;
unsigned int tx_set_ic;
@@ -1618,6 +1619,9 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
 
DBGPR("-->xgbe_dev_xmit\n");
 
+   tx_packets = packet->tx_packets;
+   tx_bytes = packet->tx_bytes;
+
csum = XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES,
  CSUM_ENABLE);
tso = XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES,
@@ -1645,13 +1649,12 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
 * - Addition of Tx frame count to the frame count since the
 *   last interrupt was set does not exceed the frame count setting
 */
-   ring->coalesce_count += packet->tx_packets;
+   ring->coalesce_count += tx_packets;
if (!pdata->tx_frames)
tx_set_ic = 0;
-   else if (packet->tx_packets > pdata->tx_frames)
+   else if (tx_packets > pdata->tx_frames)
tx_set_ic = 1;
-   else if ((ring->coalesce_count % pdata->tx_frames) <
-packet->tx_packets)
+   else if ((ring->coalesce_count % pdata->tx_frames) < tx_packets)
tx_set_ic = 1;
else
tx_set_ic = 0;
@@ -1741,7 +1744,7 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, TCPHDRLEN,
  packet->tcp_header_len / 4);
 
-   pdata->ext_stats.tx_tso_packets += packet->tx_packets;
+   pdata->ext_stats.tx_tso_packets += tx_packets;
} else {
/* Enable CRC and Pad Insertion */
XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, CPC, 0);
@@ -1789,8 +1792,11 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, IC, 1);
 
/* Save the Tx info to report back during cleanup */
-   rdata->tx.packets = packet->tx_packets;
-   rdata->tx.bytes = packet->tx_bytes;
+   rdata->tx.packets = tx_packets;
+   rdata->tx.bytes = tx_bytes;
+
+   pdata->ext_stats.txq_packets[channel->queue_index] += tx_packets;
+   pdata->ext_stats.txq_bytes[channel->queue_index] += tx_bytes;
 
/* In case the Tx DMA engine is running, make sure everything
 * is written to the descriptor(s) before setting the OWN bit
@@ -1944,6 +1950,9 @@ static int xgbe_dev_read(struct xgbe_channel *channel)
   FRAME, 1);
}
 
+   pdata->ext_stats.rxq_packets[channel->queue_index]++;
+   pdata->ext_stats.rxq_bytes[channel->queue_index] += rdata->rx.len;
+
DBGPR("<--xgbe_dev_read: %s - descriptor=%u (cur=%d)\n", channel->name,
  ring->cur & (ring->rdesc_count - 1), ring->cur);
 
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
index 67a2e52..f80b186 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
@@ -186,6 +186,7 @@ struct xgbe_stats {
 
 static void xgbe_get_strings(struct net_device *netdev, u32 stringset, u8 
*data)
 {
+   struct xgbe_prv_data *pdata = netdev_priv(netdev);
int i;
 
switch (stringset) {
@@ -195,6 +196,18 @@ static void xgbe_get_strings(struct net_device *netdev, 
u32 stringset, u8 *data)
   ETH_GSTRING_LEN);
data += ETH_GSTRING_LEN;
}
+   for (i = 0; i < pdata->tx_ring_count; i++) {
+   sprintf(data, "txq_%u_packets", i);
+   data += ETH_GSTRING_LEN;
+   sprintf(data, "txq_%u_bytes", i);
+   data += ETH_GSTRING_LEN;
+   }
+   for (i = 0; i < pdata->rx_ring_count; i++) {
+

[PATCH net-next v2 05/13] amd-xgbe: Add support to handle device renaming

2017-08-18 Thread Tom Lendacky
Many of the names used by the driver are based upon the name of the device
found during device probe.  Move the formatting of the names into the
device open function so that any renaming that occurs before the device is
brought up will be accounted for.  This also means moving the creation of
some named workqueues into the device open path.

Add support to register for net events so that if a device is renamed
the corresponding debugfs directory can be renamed.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c |   25 +
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c |   44 +++-
 drivers/net/ethernet/amd/xgbe/xgbe-main.c|   72 +++---
 drivers/net/ethernet/amd/xgbe/xgbe.h |5 +-
 4 files changed, 100 insertions(+), 46 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c
index 7546b66..7d128be 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c
@@ -527,3 +527,28 @@ void xgbe_debugfs_exit(struct xgbe_prv_data *pdata)
debugfs_remove_recursive(pdata->xgbe_debugfs);
pdata->xgbe_debugfs = NULL;
 }
+
+void xgbe_debugfs_rename(struct xgbe_prv_data *pdata)
+{
+   struct dentry *pfile;
+   char *buf;
+
+   if (!pdata->xgbe_debugfs)
+   return;
+
+   buf = kasprintf(GFP_KERNEL, "amd-xgbe-%s", pdata->netdev->name);
+   if (!buf)
+   return;
+
+   if (!strcmp(pdata->xgbe_debugfs->d_name.name, buf))
+   goto out;
+
+   pfile = debugfs_rename(pdata->xgbe_debugfs->d_parent,
+  pdata->xgbe_debugfs,
+  pdata->xgbe_debugfs->d_parent, buf);
+   if (!pfile)
+   netdev_err(pdata->netdev, "debugfs_rename failed\n");
+
+out:
+   kfree(buf);
+}
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index 2fd9b80..d6d29d8 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -887,7 +887,7 @@ static int xgbe_request_irqs(struct xgbe_prv_data *pdata)
 (unsigned long)pdata);
 
ret = devm_request_irq(pdata->dev, pdata->dev_irq, xgbe_isr, 0,
-  netdev->name, pdata);
+  netdev_name(netdev), pdata);
if (ret) {
netdev_alert(netdev, "error requesting irq %d\n",
 pdata->dev_irq);
@@ -1589,16 +1589,42 @@ static int xgbe_open(struct net_device *netdev)
 
DBGPR("-->xgbe_open\n");
 
+   /* Create the various names based on netdev name */
+   snprintf(pdata->an_name, sizeof(pdata->an_name) - 1, "%s-pcs",
+netdev_name(netdev));
+
+   snprintf(pdata->ecc_name, sizeof(pdata->ecc_name) - 1, "%s-ecc",
+netdev_name(netdev));
+
+   snprintf(pdata->i2c_name, sizeof(pdata->i2c_name) - 1, "%s-i2c",
+netdev_name(netdev));
+
+   /* Create workqueues */
+   pdata->dev_workqueue =
+   create_singlethread_workqueue(netdev_name(netdev));
+   if (!pdata->dev_workqueue) {
+   netdev_err(netdev, "device workqueue creation failed\n");
+   return -ENOMEM;
+   }
+
+   pdata->an_workqueue =
+   create_singlethread_workqueue(pdata->an_name);
+   if (!pdata->an_workqueue) {
+   netdev_err(netdev, "phy workqueue creation failed\n");
+   ret = -ENOMEM;
+   goto err_dev_wq;
+   }
+
/* Reset the phy settings */
ret = xgbe_phy_reset(pdata);
if (ret)
-   return ret;
+   goto err_an_wq;
 
/* Enable the clocks */
ret = clk_prepare_enable(pdata->sysclk);
if (ret) {
netdev_alert(netdev, "dma clk_prepare_enable failed\n");
-   return ret;
+   goto err_an_wq;
}
 
ret = clk_prepare_enable(pdata->ptpclk);
@@ -1651,6 +1677,12 @@ static int xgbe_open(struct net_device *netdev)
 err_sysclk:
clk_disable_unprepare(pdata->sysclk);
 
+err_an_wq:
+   destroy_workqueue(pdata->an_workqueue);
+
+err_dev_wq:
+   destroy_workqueue(pdata->dev_workqueue);
+
return ret;
 }
 
@@ -1674,6 +1706,12 @@ static int xgbe_close(struct net_device *netdev)
clk_disable_unprepare(pdata->ptpclk);
clk_disable_unprepare(pdata->sysclk);
 
+   flush_workqueue(pdata->an_workqueue);
+   destroy_workqueue(pdata->an_workqueue);
+
+   flush_workqueue(pdata->dev_workqueue);
+   destroy_workqueue(pdata->dev_workqueue);
+
set_bit

[PATCH net-next v2 02/13] amd-xgbe: Set the MII control width for the MAC interface

2017-08-18 Thread Tom Lendacky
When running in SGMII mode at speeds below 1000Mbps, the auto-negotition
control register must set the MII control width for the MAC interface
to be 8-bits wide.  By default the width is 4-bits.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-common.h |1 +
 drivers/net/ethernet/amd/xgbe/xgbe-mdio.c   |2 ++
 2 files changed, 3 insertions(+)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h 
b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
index 9795419..d07edf9 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
@@ -1339,6 +1339,7 @@
 #define XGBE_AN_CL37_PCS_MODE_BASEX0x00
 #define XGBE_AN_CL37_PCS_MODE_SGMII0x04
 #define XGBE_AN_CL37_TX_CONFIG_MASK0x08
+#define XGBE_AN_CL37_MII_CTRL_8BIT 0x0100
 
 /* Bit setting and getting macros
  *  The get macro will extract the current bit field value from within
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
index 8068491..bbf8 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
@@ -982,6 +982,8 @@ static void xgbe_an37_init(struct xgbe_prv_data *pdata)
break;
}
 
+   reg |= XGBE_AN_CL37_MII_CTRL_8BIT;
+
XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL, reg);
 
netif_dbg(pdata, link, pdata->netdev, "CL37 AN (%s) initialized\n",



[PATCH net-next v2 03/13] amd-xgbe: Be sure driver shuts down cleanly on module removal

2017-08-18 Thread Tom Lendacky
Sometimes when the driver is being unloaded while the devices are still
up the driver can issue errors.  This is based on timing and the double
invocation of some routines.  The phy_exit() call needs to be run after
the network device has been closed and unregistered from the system.
Also, the phy_exit() does not need to invoke phy_stop() since that will
be called as part of the device closing, so remove that call.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-main.c |4 ++--
 drivers/net/ethernet/amd/xgbe/xgbe-mdio.c |2 --
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
index 500147d..53a425c 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
@@ -458,6 +458,8 @@ void xgbe_deconfig_netdev(struct xgbe_prv_data *pdata)
if (IS_REACHABLE(CONFIG_PTP_1588_CLOCK))
xgbe_ptp_unregister(pdata);
 
+   unregister_netdev(netdev);
+
pdata->phy_if.phy_exit(pdata);
 
flush_workqueue(pdata->an_workqueue);
@@ -465,8 +467,6 @@ void xgbe_deconfig_netdev(struct xgbe_prv_data *pdata)
 
flush_workqueue(pdata->dev_workqueue);
destroy_workqueue(pdata->dev_workqueue);
-
-   unregister_netdev(netdev);
 }
 
 static int __init xgbe_mod_init(void)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
index bbf8..2409202 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
@@ -1533,8 +1533,6 @@ static int xgbe_phy_best_advertised_speed(struct 
xgbe_prv_data *pdata)
 
 static void xgbe_phy_exit(struct xgbe_prv_data *pdata)
 {
-   xgbe_phy_stop(pdata);
-
pdata->phy_if.phy_impl.exit(pdata);
 }
 



[PATCH net-next v2 01/13] amd-xgbe: Set the MDIO mode for 10000Base-T configuration

2017-08-18 Thread Tom Lendacky
Currently the MDIO mode is set to none for the 1Base-T, which is
incorrect.  The MDIO mode should for this configuration should be
clause 45.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
index 04b5c14..81c45fa 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
@@ -2921,7 +2921,7 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata)
phy_data->start_mode = XGBE_MODE_KR;
}
 
-   phy_data->phydev_mode = XGBE_MDIO_MODE_NONE;
+   phy_data->phydev_mode = XGBE_MDIO_MODE_CL45;
break;
 
/* 10GBase-R support */



[PATCH net-next v2 00/13] amd-xgbe: AMD XGBE driver updates 2017-08-17

2017-08-18 Thread Tom Lendacky
The following updates are included in this driver update series:

- Set the MDIO mode to clause 45 for the 10GBase-T configuration
- Set the MII control width to 8-bits for speeds less than 1Gbps
- Fix an issue to related to module removal when the devices are up
- Fix ethtool statistics related to packet counting of TSO packets
- Add support for device renaming
- Add additional dynamic debug output for the PCS window calculation
- Optimize reading of DMA channel interrupt enablement register
- Add additional dynamic debug output about the hardware features
- Add per queue Tx and Rx ethtool statistics
- Add a macro to clear ethtool_link_ksettings modes
- Convert the driver to use the ethtool_link_ksettings
- Add support for VXLAN offload capabilities
- Add additional ethtool statistics related to VXLAN

This patch series is based on net-next.

---

Changes since v1:
- Remove added debugfs support for reading SFP eeprom and phydev
  registers


Tom Lendacky (13):
  amd-xgbe: Set the MDIO mode for 1Base-T configuration
  amd-xgbe: Set the MII control width for the MAC interface
  amd-xgbe: Be sure driver shuts down cleanly on module removal
  amd-xgbe: Update TSO packet statistics accuracy
  amd-xgbe: Add support to handle device renaming
  amd-xgbe: Add additional dynamic debug messages
  amd-xgbe: Optimize DMA channel interrupt enablement
  amd-xgbe: Add hardware features debug output
  amd-xgbe: Add per queue Tx and Rx statistics
  net: ethtool: Add macro to clear a link mode setting
  amd-xgbe: Convert to using the new link mode settings
  amd-xgbe: Add support for VXLAN offload capabilities
  amd-xgbe: Add additional ethtool statistics


 drivers/net/ethernet/amd/xgbe/xgbe-common.h  |   25 +
 drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c |   25 +
 drivers/net/ethernet/amd/xgbe/xgbe-dev.c |  198 ---
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c |  487 ++
 drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c |   86 +++--
 drivers/net/ethernet/amd/xgbe/xgbe-main.c|   97 +++--
 drivers/net/ethernet/amd/xgbe/xgbe-mdio.c|   81 +++-
 drivers/net/ethernet/amd/xgbe/xgbe-pci.c |4 
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v1.c  |   54 ++-
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c  |  352 ++-
 drivers/net/ethernet/amd/xgbe/xgbe.h |   91 -
 include/linux/ethtool.h  |   11 +
 12 files changed, 1158 insertions(+), 353 deletions(-)

-- 
Tom Lendacky


Re: [PATCH net-next v1 05/14] amd-xgbe: Add additional debugfs support

2017-08-18 Thread Tom Lendacky

On 8/18/2017 12:02 AM, David Miller wrote:

From: Andrew Lunn <and...@lunn.ch>
Date: Fri, 18 Aug 2017 02:30:57 +0200


On Thu, Aug 17, 2017 at 07:02:50PM -0500, Tom Lendacky wrote:

Add additional debugfs support for reading / writing registers of any
attached external phy devices as well as the SFP eeprom data.


Hi Tom

What is wrong with using the standard APIs for this?

ethtool --moduile-info

ioctls SIOCGMIIREG and SIOCSMIIREG.


Yeah debugfs is a horrible choice for this.

debugfs in general should be strongly avoided.  We have rich eneough
facilities to export just about anything that is actually appropriate
and useful, and where we do not existing facilities should be extended
as needed rather than ignored.


I was intending this to be purely debugging and that's why I chose
debugfs as opposed to ethtool.  I can switch over to using ethtool
though.  I'll resubmit the series without this patch and look at
moving to this to ethtool as a separate patch later.

Thanks,
Tom





[PATCH net-next v1 13/14] amd-xgbe: Add support for VXLAN offload capabilities

2017-08-17 Thread Tom Lendacky
The hardware has the capability to perform checksum offload support
(both Tx and Rx) and TSO support for VXLAN packets. Add the support
required to enable this.

The hardware can only support a single VXLAN port for offload. If more
than one VXLAN port is added then the offload capabilities have to be
disabled and can no longer be advertised.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-common.h |   24 ++
 drivers/net/ethernet/amd/xgbe/xgbe-dev.c|   92 +++
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c|  365 +++
 drivers/net/ethernet/amd/xgbe/xgbe-main.c   |   23 ++
 drivers/net/ethernet/amd/xgbe/xgbe.h|   22 ++
 5 files changed, 520 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h 
b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
index d07edf9..9431330 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
@@ -298,6 +298,7 @@
 #define MAC_RWKPFR 0x00c4
 #define MAC_LPICSR 0x00d0
 #define MAC_LPITCR 0x00d4
+#define MAC_TIR0x00e0
 #define MAC_VR 0x0110
 #define MAC_DR 0x0114
 #define MAC_HWF0R  0x011c
@@ -364,6 +365,8 @@
 #define MAC_HWF0R_TXCOESEL_WIDTH   1
 #define MAC_HWF0R_VLHASH_INDEX 4
 #define MAC_HWF0R_VLHASH_WIDTH 1
+#define MAC_HWF0R_VXN_INDEX29
+#define MAC_HWF0R_VXN_WIDTH1
 #define MAC_HWF1R_ADDR64_INDEX 14
 #define MAC_HWF1R_ADDR64_WIDTH 2
 #define MAC_HWF1R_ADVTHWORD_INDEX  13
@@ -448,6 +451,8 @@
 #define MAC_PFR_PR_WIDTH   1
 #define MAC_PFR_VTFE_INDEX 16
 #define MAC_PFR_VTFE_WIDTH 1
+#define MAC_PFR_VUCC_INDEX 22
+#define MAC_PFR_VUCC_WIDTH 1
 #define MAC_PMTCSR_MGKPKTEN_INDEX  1
 #define MAC_PMTCSR_MGKPKTEN_WIDTH  1
 #define MAC_PMTCSR_PWRDWN_INDEX0
@@ -510,6 +515,12 @@
 #define MAC_TCR_SS_WIDTH   2
 #define MAC_TCR_TE_INDEX   0
 #define MAC_TCR_TE_WIDTH   1
+#define MAC_TCR_VNE_INDEX  24
+#define MAC_TCR_VNE_WIDTH  1
+#define MAC_TCR_VNM_INDEX  25
+#define MAC_TCR_VNM_WIDTH  1
+#define MAC_TIR_TNID_INDEX 0
+#define MAC_TIR_TNID_WIDTH 16
 #define MAC_TSCR_AV8021ASMEN_INDEX 28
 #define MAC_TSCR_AV8021ASMEN_WIDTH 1
 #define MAC_TSCR_SNAPTYPSEL_INDEX  16
@@ -1153,11 +1164,17 @@
 #define RX_PACKET_ATTRIBUTES_RSS_HASH_WIDTH1
 #define RX_PACKET_ATTRIBUTES_FIRST_INDEX   7
 #define RX_PACKET_ATTRIBUTES_FIRST_WIDTH   1
+#define RX_PACKET_ATTRIBUTES_TNP_INDEX 8
+#define RX_PACKET_ATTRIBUTES_TNP_WIDTH 1
+#define RX_PACKET_ATTRIBUTES_TNPCSUM_DONE_INDEX9
+#define RX_PACKET_ATTRIBUTES_TNPCSUM_DONE_WIDTH1
 
 #define RX_NORMAL_DESC0_OVT_INDEX  0
 #define RX_NORMAL_DESC0_OVT_WIDTH  16
 #define RX_NORMAL_DESC2_HL_INDEX   0
 #define RX_NORMAL_DESC2_HL_WIDTH   10
+#define RX_NORMAL_DESC2_TNP_INDEX  11
+#define RX_NORMAL_DESC2_TNP_WIDTH  1
 #define RX_NORMAL_DESC3_CDA_INDEX  27
 #define RX_NORMAL_DESC3_CDA_WIDTH  1
 #define RX_NORMAL_DESC3_CTXT_INDEX 30
@@ -1184,9 +1201,11 @@
 #define RX_DESC3_L34T_IPV4_TCP 1
 #define RX_DESC3_L34T_IPV4_UDP 2
 #define RX_DESC3_L34T_IPV4_ICMP3
+#define RX_DESC3_L34T_IPV4_UNKNOWN 7
 #define RX_DESC3_L34T_IPV6_TCP 9
 #define RX_DESC3_L34T_IPV6_UDP 10
 #define RX_DESC3_L34T_IPV6_ICMP11
+#define RX_DESC3_L34T_IPV6_UNKNOWN 15
 
 #define RX_CONTEXT_DESC3_TSA_INDEX 4
 #define RX_CONTEXT_DESC3_TSA_WIDTH 1
@@ -1201,6 +1220,8 @@
 #define TX_PACKET_ATTRIBUTES_VLAN_CTAG_WIDTH   1
 #define TX_PACKET_ATTRIBUTES_PTP_INDEX 3
 #define TX_PACKET_ATTRIBUTES_PTP_WIDTH 1
+#define TX_PACKET_ATTRIBUTES_VXLAN_INDEX   4
+#define TX_PACKET_ATTRIBUTES_VXLAN_WIDTH   1
 
 #define TX_CONTEXT_DESC2_MSS_INDEX 0
 #define TX_CONTEXT_DESC2_MSS_WIDTH 15
@@ -1241,8 +1262,11 @@
 #define TX_NORMAL_DESC3_TCPPL_WIDTH18
 #define TX_NORMAL_DESC3_TSE_INDEX  18
 #define TX_NORMAL_DESC3_TSE_WIDTH  1
+#define TX_NORMAL_DESC3_VNP_INDEX  23
+#define TX_NORMAL_DESC3_VNP_WIDTH  3
 
 #define TX_NORMAL_DESC2_VLAN_INSERT0x2
+#define TX_NORMAL_DESC3_VXLAN_PACKET   0x3
 
 /* MDIO undefined or vendor specific registers */
 #ifndef MDIO_PMA_10GBR_PMD_CTRL
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index a978408..1bf671e 100644
--- a/drivers/net/et

[PATCH net-next v1 08/14] amd-xgbe: Optimize DMA channel interrupt enablement

2017-08-17 Thread Tom Lendacky
Currently whenever the driver needs to enable or disable interrupts for
a DMA channel it reads the interrupt enable register (IER), updates the
value and then writes the new value back to the IER. Since the hardware
does not change the IER, software can track this value and elimiate the
need to read it each time.

Add the IER value to the channel related data structure and use that as
the base for enabling and disabling interrupts, thus removing the need
for the MMIO read.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-dev.c |   77 ++
 drivers/net/ethernet/amd/xgbe/xgbe.h |4 +-
 2 files changed, 37 insertions(+), 44 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index bb60507..75a479c 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -605,7 +605,6 @@ static void xgbe_config_flow_control(struct xgbe_prv_data 
*pdata)
 static void xgbe_enable_dma_interrupts(struct xgbe_prv_data *pdata)
 {
struct xgbe_channel *channel;
-   unsigned int dma_ch_isr, dma_ch_ier;
unsigned int i;
 
/* Set the interrupt mode if supported */
@@ -617,20 +616,20 @@ static void xgbe_enable_dma_interrupts(struct 
xgbe_prv_data *pdata)
channel = pdata->channel[i];
 
/* Clear all the interrupts which are set */
-   dma_ch_isr = XGMAC_DMA_IOREAD(channel, DMA_CH_SR);
-   XGMAC_DMA_IOWRITE(channel, DMA_CH_SR, dma_ch_isr);
+   XGMAC_DMA_IOWRITE(channel, DMA_CH_SR,
+ XGMAC_DMA_IOREAD(channel, DMA_CH_SR));
 
/* Clear all interrupt enable bits */
-   dma_ch_ier = 0;
+   channel->curr_ier = 0;
 
/* Enable following interrupts
 *   NIE  - Normal Interrupt Summary Enable
 *   AIE  - Abnormal Interrupt Summary Enable
 *   FBEE - Fatal Bus Error Enable
 */
-   XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, NIE, 1);
-   XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, AIE, 1);
-   XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, FBEE, 1);
+   XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, NIE, 1);
+   XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, AIE, 1);
+   XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, FBEE, 1);
 
if (channel->tx_ring) {
/* Enable the following Tx interrupts
@@ -639,7 +638,8 @@ static void xgbe_enable_dma_interrupts(struct xgbe_prv_data 
*pdata)
 *  mode)
 */
if (!pdata->per_channel_irq || pdata->channel_irq_mode)
-   XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TIE, 1);
+   XGMAC_SET_BITS(channel->curr_ier,
+  DMA_CH_IER, TIE, 1);
}
if (channel->rx_ring) {
/* Enable following Rx interrupts
@@ -648,12 +648,13 @@ static void xgbe_enable_dma_interrupts(struct 
xgbe_prv_data *pdata)
 *  per channel interrupts in edge triggered
 *  mode)
 */
-   XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RBUE, 1);
+   XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, RBUE, 1);
if (!pdata->per_channel_irq || pdata->channel_irq_mode)
-   XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RIE, 1);
+   XGMAC_SET_BITS(channel->curr_ier,
+  DMA_CH_IER, RIE, 1);
}
 
-   XGMAC_DMA_IOWRITE(channel, DMA_CH_IER, dma_ch_ier);
+   XGMAC_DMA_IOWRITE(channel, DMA_CH_IER, channel->curr_ier);
}
 }
 
@@ -1964,44 +1965,40 @@ static int xgbe_is_last_desc(struct xgbe_ring_desc 
*rdesc)
 static int xgbe_enable_int(struct xgbe_channel *channel,
   enum xgbe_int int_id)
 {
-   unsigned int dma_ch_ier;
-
-   dma_ch_ier = XGMAC_DMA_IOREAD(channel, DMA_CH_IER);
-
switch (int_id) {
case XGMAC_INT_DMA_CH_SR_TI:
-   XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TIE, 1);
+   XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, TIE, 1);
break;
case XGMAC_INT_DMA_CH_SR_TPS:
-   XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TXSE, 1);
+   XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, TXSE, 1);
break;
case XGMAC_INT_DMA_CH_SR_TBU:
-   XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TBUE, 1);
+   XGMAC_SET_BITS(channel->curr_ier, DMA_CH_IER, TBUE, 1)

[PATCH net-next v1 14/14] amd-xgbe: Add additional ethtool statistics

2017-08-17 Thread Tom Lendacky
Add some additional statistics for tracking VXLAN packets and checksum
errors.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-dev.c |8 +++-
 drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c |4 
 drivers/net/ethernet/amd/xgbe/xgbe.h |5 +
 3 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index 1bf671e..671203d 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -1805,10 +1805,13 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
  packet->length);
}
 
-   if (vxlan)
+   if (vxlan) {
XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, VNP,
  TX_NORMAL_DESC3_VXLAN_PACKET);
 
+   pdata->ext_stats.tx_vxlan_packets += packet->tx_packets;
+   }
+
for (i = cur_index - start_index + 1; i < packet->rdesc_count; i++) {
cur_index++;
rdata = XGBE_GET_DESC_DATA(ring, cur_index);
@@ -1981,6 +1984,7 @@ static int xgbe_dev_read(struct xgbe_channel *channel)
if (XGMAC_GET_BITS_LE(rdesc->desc2, RX_NORMAL_DESC2, TNP)) {
XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
   TNP, 1);
+   pdata->ext_stats.rx_vxlan_packets++;
 
l34t = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, L34T);
switch (l34t) {
@@ -2018,11 +2022,13 @@ static int xgbe_dev_read(struct xgbe_channel *channel)
   CSUM_DONE, 0);
XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
   TNPCSUM_DONE, 0);
+   pdata->ext_stats.rx_csum_errors++;
} else if (tnp && ((etlt == 0x09) || (etlt == 0x0a))) {
XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
   CSUM_DONE, 0);
XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
   TNPCSUM_DONE, 0);
+   pdata->ext_stats.rx_vxlan_csum_errors++;
} else {
XGMAC_SET_BITS(packet->errors, RX_PACKET_ERRORS,
   FRAME, 1);
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
index cea25ac..ff397bb 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
@@ -146,6 +146,7 @@ struct xgbe_stats {
XGMAC_MMC_STAT("tx_broadcast_packets", txbroadcastframes_gb),
XGMAC_MMC_STAT("tx_multicast_packets", txmulticastframes_gb),
XGMAC_MMC_STAT("tx_vlan_packets", txvlanframes_g),
+   XGMAC_EXT_STAT("tx_vxlan_packets", tx_vxlan_packets),
XGMAC_EXT_STAT("tx_tso_packets", tx_tso_packets),
XGMAC_MMC_STAT("tx_64_byte_packets", tx64octets_gb),
XGMAC_MMC_STAT("tx_65_to_127_byte_packets", tx65to127octets_gb),
@@ -162,6 +163,7 @@ struct xgbe_stats {
XGMAC_MMC_STAT("rx_broadcast_packets", rxbroadcastframes_g),
XGMAC_MMC_STAT("rx_multicast_packets", rxmulticastframes_g),
XGMAC_MMC_STAT("rx_vlan_packets", rxvlanframes_gb),
+   XGMAC_EXT_STAT("rx_vxlan_packets", rx_vxlan_packets),
XGMAC_MMC_STAT("rx_64_byte_packets", rx64octets_gb),
XGMAC_MMC_STAT("rx_65_to_127_byte_packets", rx65to127octets_gb),
XGMAC_MMC_STAT("rx_128_to_255_byte_packets", rx128to255octets_gb),
@@ -177,6 +179,8 @@ struct xgbe_stats {
XGMAC_MMC_STAT("rx_out_of_range_errors", rxoutofrangetype),
XGMAC_MMC_STAT("rx_fifo_overflow_errors", rxfifooverflow),
XGMAC_MMC_STAT("rx_watchdog_errors", rxwatchdogerror),
+   XGMAC_EXT_STAT("rx_csum_errors", rx_csum_errors),
+   XGMAC_EXT_STAT("rx_vxlan_csum_errors", rx_vxlan_csum_errors),
XGMAC_MMC_STAT("rx_pause_frames", rxpauseframes),
XGMAC_EXT_STAT("rx_split_header_packets", rx_split_header_packets),
XGMAC_EXT_STAT("rx_buffer_unavailable", rx_buffer_unavailable),
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h 
b/drivers/net/ethernet/amd/xgbe/xgbe.h
index 6d4057a..c0c78ee 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe.h
@@ -715,6 +715,11 @@ struct xgbe_ext_stats {
u64 txq_bytes[XGBE_MAX_DMA_CHANNELS];
u64 rxq_packets[XGBE_MAX_DMA_CHANNELS];
u64 rxq_bytes[XGBE_MAX_DMA_CHANNELS];
+
+   u64 tx_vxlan_packets;
+   u64 rx_vxlan_packets;
+   u64 rx_csum_errors;
+   u64 rx_vxlan_csum_errors;
 };
 
 struct xgbe_hw_if {



[PATCH net-next v1 12/14] amd-xgbe: Convert to using the new link mode settings

2017-08-17 Thread Tom Lendacky
Convert from using the old u32 supported, advertising, etc. link settings
to the new link mode settings that support bit positions / settings
greater than 32 bits.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c |   56 ++--
 drivers/net/ethernet/amd/xgbe/xgbe-mdio.c|   77 +++---
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v1.c  |   54 ++--
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c  |  350 ++
 drivers/net/ethernet/amd/xgbe/xgbe.h |   50 +++-
 5 files changed, 345 insertions(+), 242 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
index f80b186..cea25ac 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
@@ -267,6 +267,7 @@ static int xgbe_set_pauseparam(struct net_device *netdev,
   struct ethtool_pauseparam *pause)
 {
struct xgbe_prv_data *pdata = netdev_priv(netdev);
+   struct ethtool_link_ksettings *lks = >phy.lks;
int ret = 0;
 
if (pause->autoneg && (pdata->phy.autoneg != AUTONEG_ENABLE)) {
@@ -279,16 +280,21 @@ static int xgbe_set_pauseparam(struct net_device *netdev,
pdata->phy.tx_pause = pause->tx_pause;
pdata->phy.rx_pause = pause->rx_pause;
 
-   pdata->phy.advertising &= ~ADVERTISED_Pause;
-   pdata->phy.advertising &= ~ADVERTISED_Asym_Pause;
+   XGBE_CLR_ADV(lks, Pause);
+   XGBE_CLR_ADV(lks, Asym_Pause);
 
if (pause->rx_pause) {
-   pdata->phy.advertising |= ADVERTISED_Pause;
-   pdata->phy.advertising |= ADVERTISED_Asym_Pause;
+   XGBE_SET_ADV(lks, Pause);
+   XGBE_SET_ADV(lks, Asym_Pause);
}
 
-   if (pause->tx_pause)
-   pdata->phy.advertising ^= ADVERTISED_Asym_Pause;
+   if (pause->tx_pause) {
+   /* Equivalent to XOR of Asym_Pause */
+   if (XGBE_ADV(lks, Asym_Pause))
+   XGBE_CLR_ADV(lks, Asym_Pause);
+   else
+   XGBE_SET_ADV(lks, Asym_Pause);
+   }
 
if (netif_running(netdev))
ret = pdata->phy_if.phy_config_aneg(pdata);
@@ -300,22 +306,20 @@ static int xgbe_get_link_ksettings(struct net_device 
*netdev,
   struct ethtool_link_ksettings *cmd)
 {
struct xgbe_prv_data *pdata = netdev_priv(netdev);
+   struct ethtool_link_ksettings *lks = >phy.lks;
 
cmd->base.phy_address = pdata->phy.address;
 
-   ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
-   pdata->phy.supported);
-   ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
-   pdata->phy.advertising);
-   ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.lp_advertising,
-   pdata->phy.lp_advertising);
-
cmd->base.autoneg = pdata->phy.autoneg;
cmd->base.speed = pdata->phy.speed;
cmd->base.duplex = pdata->phy.duplex;
 
cmd->base.port = PORT_NONE;
 
+   XGBE_LM_COPY(cmd, supported, lks, supported);
+   XGBE_LM_COPY(cmd, advertising, lks, advertising);
+   XGBE_LM_COPY(cmd, lp_advertising, lks, lp_advertising);
+
return 0;
 }
 
@@ -323,7 +327,8 @@ static int xgbe_set_link_ksettings(struct net_device 
*netdev,
   const struct ethtool_link_ksettings *cmd)
 {
struct xgbe_prv_data *pdata = netdev_priv(netdev);
-   u32 advertising;
+   struct ethtool_link_ksettings *lks = >phy.lks;
+   __ETHTOOL_DECLARE_LINK_MODE_MASK(advertising);
u32 speed;
int ret;
 
@@ -355,15 +360,17 @@ static int xgbe_set_link_ksettings(struct net_device 
*netdev,
}
}
 
-   ethtool_convert_link_mode_to_legacy_u32(,
-   cmd->link_modes.advertising);
-
netif_dbg(pdata, link, netdev,
- "requested advertisement %#x, phy supported %#x\n",
- advertising, pdata->phy.supported);
+ "requested advertisement 0x%*pb, phy supported 0x%*pb\n",
+ __ETHTOOL_LINK_MODE_MASK_NBITS, cmd->link_modes.advertising,
+ __ETHTOOL_LINK_MODE_MASK_NBITS, lks->link_modes.supported);
+
+   bitmap_and(advertising,
+  cmd->link_modes.advertising, lks->link_modes.supported,
+  __ETHTOOL_LINK_MODE_MASK_NBITS);
 
-   advertising &= pdata->phy.supported;
-   if ((cmd->base.autoneg == AUTONEG_ENABLE) && !advertising) {
+   if ((cmd->base.autoneg == AUTONEG_ENABLE) &&
+  

[PATCH net-next v1 09/14] amd-xgbe: Add hardware features debug output

2017-08-17 Thread Tom Lendacky
Use the dynamic debug support to output information about the hardware
features reported by the device.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c |   78 +-
 1 file changed, 75 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index d6d29d8..7498bb8 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -732,8 +732,6 @@ void xgbe_get_all_hw_features(struct xgbe_prv_data *pdata)
unsigned int mac_hfr0, mac_hfr1, mac_hfr2;
struct xgbe_hw_features *hw_feat = >hw_feat;
 
-   DBGPR("-->xgbe_get_all_hw_features\n");
-
mac_hfr0 = XGMAC_IOREAD(pdata, MAC_HWF0R);
mac_hfr1 = XGMAC_IOREAD(pdata, MAC_HWF1R);
mac_hfr2 = XGMAC_IOREAD(pdata, MAC_HWF2R);
@@ -828,7 +826,81 @@ void xgbe_get_all_hw_features(struct xgbe_prv_data *pdata)
hw_feat->rx_fifo_size = 1 << (hw_feat->rx_fifo_size + 7);
hw_feat->tx_fifo_size = 1 << (hw_feat->tx_fifo_size + 7);
 
-   DBGPR("<--xgbe_get_all_hw_features\n");
+   if (netif_msg_probe(pdata)) {
+   dev_dbg(pdata->dev, "Hardware features:\n");
+
+   /* Hardware feature register 0 */
+   dev_dbg(pdata->dev, "  1GbE support  : %s\n",
+   hw_feat->gmii ? "yes" : "no");
+   dev_dbg(pdata->dev, "  VLAN hash filter  : %s\n",
+   hw_feat->vlhash ? "yes" : "no");
+   dev_dbg(pdata->dev, "  MDIO interface: %s\n",
+   hw_feat->sma ? "yes" : "no");
+   dev_dbg(pdata->dev, "  Wake-up packet support: %s\n",
+   hw_feat->rwk ? "yes" : "no");
+   dev_dbg(pdata->dev, "  Magic packet support  : %s\n",
+   hw_feat->mgk ? "yes" : "no");
+   dev_dbg(pdata->dev, "  Management counters   : %s\n",
+   hw_feat->mmc ? "yes" : "no");
+   dev_dbg(pdata->dev, "  ARP offload   : %s\n",
+   hw_feat->aoe ? "yes" : "no");
+   dev_dbg(pdata->dev, "  IEEE 1588-2008 Timestamp  : %s\n",
+   hw_feat->ts ? "yes" : "no");
+   dev_dbg(pdata->dev, "  Energy Efficient Ethernet : %s\n",
+   hw_feat->eee ? "yes" : "no");
+   dev_dbg(pdata->dev, "  TX checksum offload   : %s\n",
+   hw_feat->tx_coe ? "yes" : "no");
+   dev_dbg(pdata->dev, "  RX checksum offload   : %s\n",
+   hw_feat->rx_coe ? "yes" : "no");
+   dev_dbg(pdata->dev, "  Additional MAC addresses  : %u\n",
+   hw_feat->addn_mac);
+   dev_dbg(pdata->dev, "  Timestamp source  : %s\n",
+   (hw_feat->ts_src == 1) ? "internal" :
+   (hw_feat->ts_src == 2) ? "external" :
+   (hw_feat->ts_src == 3) ? "internal/external" : "n/a");
+   dev_dbg(pdata->dev, "  SA/VLAN insertion : %s\n",
+   hw_feat->sa_vlan_ins ? "yes" : "no");
+
+   /* Hardware feature register 1 */
+   dev_dbg(pdata->dev, "  RX fifo size  : %u\n",
+   hw_feat->rx_fifo_size);
+   dev_dbg(pdata->dev, "  TX fifo size  : %u\n",
+   hw_feat->tx_fifo_size);
+   dev_dbg(pdata->dev, "  IEEE 1588 high word   : %s\n",
+   hw_feat->adv_ts_hi ? "yes" : "no");
+   dev_dbg(pdata->dev, "  DMA width : %u\n",
+   hw_feat->dma_width);
+   dev_dbg(pdata->dev, "  Data Center Bridging  : %s\n",
+   hw_feat->dcb ? "yes" : "no");
+   dev_dbg(pdata->dev, "  Split header  : %s\n",
+   hw_feat->sph ? "yes" : "no");
+   dev_dbg(pdata->dev, "  TCP Segmentation Offload  : %s\n",
+   hw_feat->tso ? "yes" : "no");
+   dev_d

[PATCH net-next v1 11/14] net: ethtool: Add macro to clear a link mode setting

2017-08-17 Thread Tom Lendacky
There are currently macros to set and test an ETHTOOL_LINK_MODE_ setting,
but not to clear one. Add a macro to clear an ETHTOOL_LINK_MODE_ setting.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 include/linux/ethtool.h |   11 +++
 1 file changed, 11 insertions(+)

diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index afdbb70..4587a4c 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -137,6 +137,17 @@ struct ethtool_link_ksettings {
__set_bit(ETHTOOL_LINK_MODE_ ## mode ## _BIT, (ptr)->link_modes.name)
 
 /**
+ * ethtool_link_ksettings_del_link_mode - clear bit in link_ksettings
+ * link mode mask
+ *   @ptr : pointer to struct ethtool_link_ksettings
+ *   @name : one of supported/advertising/lp_advertising
+ *   @mode : one of the ETHTOOL_LINK_MODE_*_BIT
+ * (not atomic, no bound checking)
+ */
+#define ethtool_link_ksettings_del_link_mode(ptr, name, mode)  \
+   __clear_bit(ETHTOOL_LINK_MODE_ ## mode ## _BIT, (ptr)->link_modes.name)
+
+/**
  * ethtool_link_ksettings_test_link_mode - test bit in ksettings link mode mask
  *   @ptr : pointer to struct ethtool_link_ksettings
  *   @name : one of supported/advertising/lp_advertising



[PATCH net-next v1 10/14] amd-xgbe: Add per queue Tx and Rx statistics

2017-08-17 Thread Tom Lendacky
Add per queue Tx and Rx packet and byte counts.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-dev.c |   23 ---
 drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c |   26 +-
 drivers/net/ethernet/amd/xgbe/xgbe.h |5 +
 3 files changed, 46 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index 75a479c..a978408 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -1609,6 +1609,7 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
struct xgbe_ring_data *rdata;
struct xgbe_ring_desc *rdesc;
struct xgbe_packet_data *packet = >packet_data;
+   unsigned int tx_packets, tx_bytes;
unsigned int csum, tso, vlan;
unsigned int tso_context, vlan_context;
unsigned int tx_set_ic;
@@ -1618,6 +1619,9 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
 
DBGPR("-->xgbe_dev_xmit\n");
 
+   tx_packets = packet->tx_packets;
+   tx_bytes = packet->tx_bytes;
+
csum = XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES,
  CSUM_ENABLE);
tso = XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES,
@@ -1645,13 +1649,12 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
 * - Addition of Tx frame count to the frame count since the
 *   last interrupt was set does not exceed the frame count setting
 */
-   ring->coalesce_count += packet->tx_packets;
+   ring->coalesce_count += tx_packets;
if (!pdata->tx_frames)
tx_set_ic = 0;
-   else if (packet->tx_packets > pdata->tx_frames)
+   else if (tx_packets > pdata->tx_frames)
tx_set_ic = 1;
-   else if ((ring->coalesce_count % pdata->tx_frames) <
-packet->tx_packets)
+   else if ((ring->coalesce_count % pdata->tx_frames) < tx_packets)
tx_set_ic = 1;
else
tx_set_ic = 0;
@@ -1741,7 +1744,7 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, TCPHDRLEN,
  packet->tcp_header_len / 4);
 
-   pdata->ext_stats.tx_tso_packets += packet->tx_packets;
+   pdata->ext_stats.tx_tso_packets += tx_packets;
} else {
/* Enable CRC and Pad Insertion */
XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, CPC, 0);
@@ -1789,8 +1792,11 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, IC, 1);
 
/* Save the Tx info to report back during cleanup */
-   rdata->tx.packets = packet->tx_packets;
-   rdata->tx.bytes = packet->tx_bytes;
+   rdata->tx.packets = tx_packets;
+   rdata->tx.bytes = tx_bytes;
+
+   pdata->ext_stats.txq_packets[channel->queue_index] += tx_packets;
+   pdata->ext_stats.txq_bytes[channel->queue_index] += tx_bytes;
 
/* In case the Tx DMA engine is running, make sure everything
 * is written to the descriptor(s) before setting the OWN bit
@@ -1944,6 +1950,9 @@ static int xgbe_dev_read(struct xgbe_channel *channel)
   FRAME, 1);
}
 
+   pdata->ext_stats.rxq_packets[channel->queue_index]++;
+   pdata->ext_stats.rxq_bytes[channel->queue_index] += rdata->rx.len;
+
DBGPR("<--xgbe_dev_read: %s - descriptor=%u (cur=%d)\n", channel->name,
  ring->cur & (ring->rdesc_count - 1), ring->cur);
 
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
index 67a2e52..f80b186 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
@@ -186,6 +186,7 @@ struct xgbe_stats {
 
 static void xgbe_get_strings(struct net_device *netdev, u32 stringset, u8 
*data)
 {
+   struct xgbe_prv_data *pdata = netdev_priv(netdev);
int i;
 
switch (stringset) {
@@ -195,6 +196,18 @@ static void xgbe_get_strings(struct net_device *netdev, 
u32 stringset, u8 *data)
   ETH_GSTRING_LEN);
data += ETH_GSTRING_LEN;
}
+   for (i = 0; i < pdata->tx_ring_count; i++) {
+   sprintf(data, "txq_%u_packets", i);
+   data += ETH_GSTRING_LEN;
+   sprintf(data, "txq_%u_bytes", i);
+   data += ETH_GSTRING_LEN;
+   }
+   for (i = 0; i < pdata->rx_ring_count; i++) {
+

[PATCH net-next v1 06/14] amd-xgbe: Add support to handle device renaming

2017-08-17 Thread Tom Lendacky
Many of the names used by the driver are based upon the name of the device
found during device probe.  Move the formatting of the names into the
device open function so that any renaming that occurs before the device is
brought up will be accounted for.  This also means moving the creation of
some named workqueues into the device open path.

Add support to register for net events so that if a device is renamed
the corresponding debugfs directory can be renamed.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c |   25 +
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c |   44 +++-
 drivers/net/ethernet/amd/xgbe/xgbe-main.c|   72 +++---
 drivers/net/ethernet/amd/xgbe/xgbe.h |5 +-
 4 files changed, 100 insertions(+), 46 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c
index 7409705..e79a0bd 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c
@@ -678,3 +678,28 @@ void xgbe_debugfs_exit(struct xgbe_prv_data *pdata)
debugfs_remove_recursive(pdata->xgbe_debugfs);
pdata->xgbe_debugfs = NULL;
 }
+
+void xgbe_debugfs_rename(struct xgbe_prv_data *pdata)
+{
+   struct dentry *pfile;
+   char *buf;
+
+   if (!pdata->xgbe_debugfs)
+   return;
+
+   buf = kasprintf(GFP_KERNEL, "amd-xgbe-%s", pdata->netdev->name);
+   if (!buf)
+   return;
+
+   if (!strcmp(pdata->xgbe_debugfs->d_name.name, buf))
+   goto out;
+
+   pfile = debugfs_rename(pdata->xgbe_debugfs->d_parent,
+  pdata->xgbe_debugfs,
+  pdata->xgbe_debugfs->d_parent, buf);
+   if (!pfile)
+   netdev_err(pdata->netdev, "debugfs_rename failed\n");
+
+out:
+   kfree(buf);
+}
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index 2fd9b80..d6d29d8 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -887,7 +887,7 @@ static int xgbe_request_irqs(struct xgbe_prv_data *pdata)
 (unsigned long)pdata);
 
ret = devm_request_irq(pdata->dev, pdata->dev_irq, xgbe_isr, 0,
-  netdev->name, pdata);
+  netdev_name(netdev), pdata);
if (ret) {
netdev_alert(netdev, "error requesting irq %d\n",
 pdata->dev_irq);
@@ -1589,16 +1589,42 @@ static int xgbe_open(struct net_device *netdev)
 
DBGPR("-->xgbe_open\n");
 
+   /* Create the various names based on netdev name */
+   snprintf(pdata->an_name, sizeof(pdata->an_name) - 1, "%s-pcs",
+netdev_name(netdev));
+
+   snprintf(pdata->ecc_name, sizeof(pdata->ecc_name) - 1, "%s-ecc",
+netdev_name(netdev));
+
+   snprintf(pdata->i2c_name, sizeof(pdata->i2c_name) - 1, "%s-i2c",
+netdev_name(netdev));
+
+   /* Create workqueues */
+   pdata->dev_workqueue =
+   create_singlethread_workqueue(netdev_name(netdev));
+   if (!pdata->dev_workqueue) {
+   netdev_err(netdev, "device workqueue creation failed\n");
+   return -ENOMEM;
+   }
+
+   pdata->an_workqueue =
+   create_singlethread_workqueue(pdata->an_name);
+   if (!pdata->an_workqueue) {
+   netdev_err(netdev, "phy workqueue creation failed\n");
+   ret = -ENOMEM;
+   goto err_dev_wq;
+   }
+
/* Reset the phy settings */
ret = xgbe_phy_reset(pdata);
if (ret)
-   return ret;
+   goto err_an_wq;
 
/* Enable the clocks */
ret = clk_prepare_enable(pdata->sysclk);
if (ret) {
netdev_alert(netdev, "dma clk_prepare_enable failed\n");
-   return ret;
+   goto err_an_wq;
}
 
ret = clk_prepare_enable(pdata->ptpclk);
@@ -1651,6 +1677,12 @@ static int xgbe_open(struct net_device *netdev)
 err_sysclk:
clk_disable_unprepare(pdata->sysclk);
 
+err_an_wq:
+   destroy_workqueue(pdata->an_workqueue);
+
+err_dev_wq:
+   destroy_workqueue(pdata->dev_workqueue);
+
return ret;
 }
 
@@ -1674,6 +1706,12 @@ static int xgbe_close(struct net_device *netdev)
clk_disable_unprepare(pdata->ptpclk);
clk_disable_unprepare(pdata->sysclk);
 
+   flush_workqueue(pdata->an_workqueue);
+   destroy_workqueue(pdata->an_workqueue);
+
+   flush_workqueue(pdata->dev_workqueue);
+   destroy_workqueue(pdata->dev_workqueue);
+
set_bit

[PATCH net-next v1 07/14] amd-xgbe: Add additional dynamic debug messages

2017-08-17 Thread Tom Lendacky
Add some additional dynamic debug message to the driver. The new messages
will provide additional information about the PCS window calculation.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-pci.c |4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c
index 1e56ad7..3e5833c 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c
@@ -292,6 +292,10 @@ static int xgbe_pci_probe(struct pci_dev *pdev, const 
struct pci_device_id *id)
pdata->xpcs_window_size = 1 << (pdata->xpcs_window_size + 7);
pdata->xpcs_window_mask = pdata->xpcs_window_size - 1;
if (netif_msg_probe(pdata)) {
+   dev_dbg(dev, "xpcs window def  = %#010x\n",
+   pdata->xpcs_window_def_reg);
+   dev_dbg(dev, "xpcs window sel  = %#010x\n",
+   pdata->xpcs_window_sel_reg);
dev_dbg(dev, "xpcs window  = %#010x\n",
pdata->xpcs_window);
dev_dbg(dev, "xpcs window size = %#010x\n",



[PATCH net-next v1 05/14] amd-xgbe: Add additional debugfs support

2017-08-17 Thread Tom Lendacky
Add additional debugfs support for reading / writing registers of any
attached external phy devices as well as the SFP eeprom data.

These debugfs files will only be created if the phy implementation
supports them.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c |  151 ++
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c  |   87 +++
 drivers/net/ethernet/amd/xgbe/xgbe.h |   12 ++
 3 files changed, 250 insertions(+)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c
index 7546b66..7409705 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c
@@ -436,6 +436,126 @@ static ssize_t xi2c_reg_value_write(struct file *filp,
.write = xi2c_reg_value_write,
 };
 
+static ssize_t sfp_eeprom_read(struct file *filp, char __user *buffer,
+  size_t count, loff_t *ppos)
+{
+   struct xgbe_prv_data *pdata = filp->private_data;
+   struct xgbe_phy_impl_if *phy_impl;
+   unsigned char *eeprom;
+   ssize_t len;
+
+   phy_impl = >phy_if.phy_impl;
+   eeprom = phy_impl->sfp_eeprom(pdata);
+   if (!eeprom)
+   return 0;
+
+   len = simple_read_from_buffer(buffer, count, ppos,
+ eeprom, strlen(eeprom));
+
+   kfree(eeprom);
+
+   return len;
+}
+
+static const struct file_operations sfp_eeprom_fops = {
+   .owner = THIS_MODULE,
+   .open = simple_open,
+   .read = sfp_eeprom_read,
+};
+
+static ssize_t phydev_mmd_read(struct file *filp, char __user *buffer,
+  size_t count, loff_t *ppos)
+{
+   struct xgbe_prv_data *pdata = filp->private_data;
+
+   return xgbe_common_read(buffer, count, ppos, pdata->debugfs_phydev_mmd);
+}
+
+static ssize_t phydev_mmd_write(struct file *filp, const char __user *buffer,
+   size_t count, loff_t *ppos)
+{
+   struct xgbe_prv_data *pdata = filp->private_data;
+
+   return xgbe_common_write(buffer, count, ppos,
+>debugfs_phydev_mmd);
+}
+
+static ssize_t phydev_reg_addr_read(struct file *filp, char __user *buffer,
+   size_t count, loff_t *ppos)
+{
+   struct xgbe_prv_data *pdata = filp->private_data;
+
+   return xgbe_common_read(buffer, count, ppos, pdata->debugfs_phydev_reg);
+}
+
+static ssize_t phydev_reg_addr_write(struct file *filp,
+const char __user *buffer,
+size_t count, loff_t *ppos)
+{
+   struct xgbe_prv_data *pdata = filp->private_data;
+
+   return xgbe_common_write(buffer, count, ppos,
+>debugfs_phydev_reg);
+}
+
+static ssize_t phydev_reg_value_read(struct file *filp, char __user *buffer,
+size_t count, loff_t *ppos)
+{
+   struct xgbe_prv_data *pdata = filp->private_data;
+   struct xgbe_phy_impl_if *phy_impl;
+   unsigned int value;
+
+   phy_impl = >phy_if.phy_impl;
+   value = phy_impl->phydev_read(pdata,
+ pdata->debugfs_phydev_mmd,
+ pdata->debugfs_phydev_reg);
+
+   return xgbe_common_read(buffer, count, ppos, value);
+}
+
+static ssize_t phydev_reg_value_write(struct file *filp,
+ const char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+   struct xgbe_prv_data *pdata = filp->private_data;
+   struct xgbe_phy_impl_if *phy_impl;
+   unsigned int value;
+   ssize_t len;
+
+   len = xgbe_common_write(buffer, count, ppos, );
+   if (len < 0)
+   return len;
+
+   phy_impl = >phy_if.phy_impl;
+   phy_impl->phydev_write(pdata,
+  pdata->debugfs_phydev_mmd,
+  pdata->debugfs_phydev_reg,
+  value);
+
+   return len;
+}
+
+static const struct file_operations phydev_mmd_fops = {
+   .owner = THIS_MODULE,
+   .open = simple_open,
+   .read = phydev_mmd_read,
+   .write = phydev_mmd_write,
+};
+
+static const struct file_operations phydev_reg_addr_fops = {
+   .owner = THIS_MODULE,
+   .open = simple_open,
+   .read = phydev_reg_addr_read,
+   .write = phydev_reg_addr_write,
+};
+
+static const struct file_operations phydev_reg_value_fops = {
+   .owner = THIS_MODULE,
+   .open = simple_open,
+   .read = phydev_reg_value_read,
+   .write = phydev_reg_value_write,
+};
+
 void xgbe_debugfs_init(struct xgbe_prv_data *pdata)
 {
struct dentry *pfile;
@@ -445,6 +565,8 @@ void xgbe_debugfs_init(struct xgbe_prv_data *pdata)
pdata-&g

[PATCH net-next v1 01/14] amd-xgbe: Set the MDIO mode for 10000Base-T configuration

2017-08-17 Thread Tom Lendacky
Currently the MDIO mode is set to none for the 1Base-T, which is
incorrect.  The MDIO mode should for this configuration should be
clause 45.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
index 04b5c14..81c45fa 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
@@ -2921,7 +2921,7 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata)
phy_data->start_mode = XGBE_MODE_KR;
}
 
-   phy_data->phydev_mode = XGBE_MDIO_MODE_NONE;
+   phy_data->phydev_mode = XGBE_MDIO_MODE_CL45;
break;
 
/* 10GBase-R support */



[PATCH net-next v1 03/14] amd-xgbe: Be sure driver shuts down cleanly on module removal

2017-08-17 Thread Tom Lendacky
Sometimes when the driver is being unloaded while the devices are still
up the driver can issue errors.  This is based on timing and the double
invocation of some routines.  The phy_exit() call needs to be run after
the network device has been closed and unregistered from the system.
Also, the phy_exit() does not need to invoke phy_stop() since that will
be called as part of the device closing, so remove that call.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-main.c |4 ++--
 drivers/net/ethernet/amd/xgbe/xgbe-mdio.c |2 --
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
index 500147d..53a425c 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
@@ -458,6 +458,8 @@ void xgbe_deconfig_netdev(struct xgbe_prv_data *pdata)
if (IS_REACHABLE(CONFIG_PTP_1588_CLOCK))
xgbe_ptp_unregister(pdata);
 
+   unregister_netdev(netdev);
+
pdata->phy_if.phy_exit(pdata);
 
flush_workqueue(pdata->an_workqueue);
@@ -465,8 +467,6 @@ void xgbe_deconfig_netdev(struct xgbe_prv_data *pdata)
 
flush_workqueue(pdata->dev_workqueue);
destroy_workqueue(pdata->dev_workqueue);
-
-   unregister_netdev(netdev);
 }
 
 static int __init xgbe_mod_init(void)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
index bbf8..2409202 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
@@ -1533,8 +1533,6 @@ static int xgbe_phy_best_advertised_speed(struct 
xgbe_prv_data *pdata)
 
 static void xgbe_phy_exit(struct xgbe_prv_data *pdata)
 {
-   xgbe_phy_stop(pdata);
-
pdata->phy_if.phy_impl.exit(pdata);
 }
 



[PATCH net-next v1 02/14] amd-xgbe: Set the MII control width for the MAC interface

2017-08-17 Thread Tom Lendacky
When running in SGMII mode at speeds below 1000Mbps, the auto-negotition
control register must set the MII control width for the MAC interface
to be 8-bits wide.  By default the width is 4-bits.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-common.h |1 +
 drivers/net/ethernet/amd/xgbe/xgbe-mdio.c   |2 ++
 2 files changed, 3 insertions(+)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h 
b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
index 9795419..d07edf9 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
@@ -1339,6 +1339,7 @@
 #define XGBE_AN_CL37_PCS_MODE_BASEX0x00
 #define XGBE_AN_CL37_PCS_MODE_SGMII0x04
 #define XGBE_AN_CL37_TX_CONFIG_MASK0x08
+#define XGBE_AN_CL37_MII_CTRL_8BIT 0x0100
 
 /* Bit setting and getting macros
  *  The get macro will extract the current bit field value from within
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
index 8068491..bbf8 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
@@ -982,6 +982,8 @@ static void xgbe_an37_init(struct xgbe_prv_data *pdata)
break;
}
 
+   reg |= XGBE_AN_CL37_MII_CTRL_8BIT;
+
XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL, reg);
 
netif_dbg(pdata, link, pdata->netdev, "CL37 AN (%s) initialized\n",



[PATCH net-next v1 04/14] amd-xgbe: Update TSO packet statistics accuracy

2017-08-17 Thread Tom Lendacky
When transmitting a TSO packet, the driver only increments the TSO packet
statistic by one rather than the number of total packets that were sent.
Update the driver to record the total number of packets that resulted from
TSO transmit.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-dev.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index 06f953e..bb60507 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -1740,7 +1740,7 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, TCPHDRLEN,
  packet->tcp_header_len / 4);
 
-   pdata->ext_stats.tx_tso_packets++;
+   pdata->ext_stats.tx_tso_packets += packet->tx_packets;
} else {
/* Enable CRC and Pad Insertion */
XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, CPC, 0);



[PATCH net-next v1 00/14] amd-xgbe: AMD XGBE driver updates 2017-08-17

2017-08-17 Thread Tom Lendacky
The following updates are included in this driver update series:

- Set the MDIO mode to clause 45 for the 10GBase-T configuration
- Set the MII control width to 8-bits for speeds less than 1Gbps
- Fix an issue to related to module removal when the devices are up
- Fix ethtool statistics related to packet counting of TSO packets
- Add additional debugfs support
- Add support for device renaming
- Add additional dynamic debug output for the PCS window calculation
- Optimize reading of DMA channel interrupt enablement register
- Add additional dynamic debug output about the hardware features
- Add per queue Tx and Rx ethtool statistics
- Add a macro to clear ethtool_link_ksettings modes
- Convert the driver to use the ethtool_link_ksettings
- Add support for VXLAN offload capabilities
- Add additional ethtool statistics related to VXLAN

This patch series is based on net-next.

---

Tom Lendacky (14):
  amd-xgbe: Set the MDIO mode for 1Base-T configuration
  amd-xgbe: Set the MII control width for the MAC interface
  amd-xgbe: Be sure driver shuts down cleanly on module removal
  amd-xgbe: Update TSO packet statistics accuracy
  amd-xgbe: Add additional debugfs support
  amd-xgbe: Add support to handle device renaming
  amd-xgbe: Add additional dynamic debug messages
  amd-xgbe: Optimize DMA channel interrupt enablement
  amd-xgbe: Add hardware features debug output
  amd-xgbe: Add per queue Tx and Rx statistics
  net: ethtool: Add macro to clear a link mode setting
  amd-xgbe: Convert to using the new link mode settings
  amd-xgbe: Add support for VXLAN offload capabilities
  amd-xgbe: Add additional ethtool statistics


 drivers/net/ethernet/amd/xgbe/xgbe-common.h  |   25 +
 drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c |  176 +
 drivers/net/ethernet/amd/xgbe/xgbe-dev.c |  198 ---
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c |  487 ++
 drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c |   86 +++--
 drivers/net/ethernet/amd/xgbe/xgbe-main.c|   97 +++--
 drivers/net/ethernet/amd/xgbe/xgbe-mdio.c|   81 +++-
 drivers/net/ethernet/amd/xgbe/xgbe-pci.c |4 
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v1.c  |   54 ++-
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c  |  439 +++
 drivers/net/ethernet/amd/xgbe/xgbe.h |  103 +
 include/linux/ethtool.h  |   11 +
 12 files changed, 1408 insertions(+), 353 deletions(-)

-- 
Tom Lendacky


[PATCH net-next v1 13/14] amd-xgbe: Simplify the burst length settings

2017-06-28 Thread Tom Lendacky
Currently the driver hardcodes the PBLx8 setting.  Remove the need for
specifying the PBLx8 setting and automatically calculate based on the
specified PBL value. Since the PBLx8 setting applies to both Tx and Rx
use the same PBL value for both of them.

Also, the driver currently uses a bit field to set the AXI master burst
len setting. Change to the full bit field range and set the burst length
based on the specified value.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-common.h |   11 
 drivers/net/ethernet/amd/xgbe/xgbe-dev.c|   67 +++
 drivers/net/ethernet/amd/xgbe/xgbe-main.c   |5 +-
 drivers/net/ethernet/amd/xgbe/xgbe.h|   12 +
 4 files changed, 31 insertions(+), 64 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h 
b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
index dc09883..6b5c72d 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
@@ -137,12 +137,19 @@
 #define DMA_MR_SWR_WIDTH   1
 #define DMA_SBMR_EAME_INDEX11
 #define DMA_SBMR_EAME_WIDTH1
-#define DMA_SBMR_BLEN_256_INDEX7
-#define DMA_SBMR_BLEN_256_WIDTH1
+#define DMA_SBMR_BLEN_INDEX1
+#define DMA_SBMR_BLEN_WIDTH7
 #define DMA_SBMR_UNDEF_INDEX   0
 #define DMA_SBMR_UNDEF_WIDTH   1
 
 /* DMA register values */
+#define DMA_SBMR_BLEN_256  256
+#define DMA_SBMR_BLEN_128  128
+#define DMA_SBMR_BLEN_64   64
+#define DMA_SBMR_BLEN_32   32
+#define DMA_SBMR_BLEN_16   16
+#define DMA_SBMR_BLEN_88
+#define DMA_SBMR_BLEN_44
 #define DMA_DSR_RPS_WIDTH  4
 #define DMA_DSR_TPS_WIDTH  4
 #define DMA_DSR_Q_WIDTH(DMA_DSR_RPS_WIDTH + 
DMA_DSR_TPS_WIDTH)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index 98da249..a51ece5 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -174,52 +174,30 @@ static unsigned int xgbe_riwt_to_usec(struct 
xgbe_prv_data *pdata,
return ret;
 }
 
-static int xgbe_config_pblx8(struct xgbe_prv_data *pdata)
+static int xgbe_config_pbl_val(struct xgbe_prv_data *pdata)
 {
+   unsigned int pblx8, pbl;
unsigned int i;
 
-   for (i = 0; i < pdata->channel_count; i++)
-   XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_CR, PBLX8,
-  pdata->pblx8);
-
-   return 0;
-}
-
-static int xgbe_get_tx_pbl_val(struct xgbe_prv_data *pdata)
-{
-   return XGMAC_DMA_IOREAD_BITS(pdata->channel[0], DMA_CH_TCR, PBL);
-}
-
-static int xgbe_config_tx_pbl_val(struct xgbe_prv_data *pdata)
-{
-   unsigned int i;
-
-   for (i = 0; i < pdata->channel_count; i++) {
-   if (!pdata->channel[i]->tx_ring)
-   break;
+   pblx8 = DMA_PBL_X8_DISABLE;
+   pbl = pdata->pbl;
 
-   XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_TCR, PBL,
-  pdata->tx_pbl);
+   if (pdata->pbl > 32) {
+   pblx8 = DMA_PBL_X8_ENABLE;
+   pbl >>= 3;
}
 
-   return 0;
-}
-
-static int xgbe_get_rx_pbl_val(struct xgbe_prv_data *pdata)
-{
-   return XGMAC_DMA_IOREAD_BITS(pdata->channel[0], DMA_CH_RCR, PBL);
-}
-
-static int xgbe_config_rx_pbl_val(struct xgbe_prv_data *pdata)
-{
-   unsigned int i;
-
for (i = 0; i < pdata->channel_count; i++) {
-   if (!pdata->channel[i]->rx_ring)
-   break;
+   XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_CR, PBLX8,
+  pblx8);
+
+   if (pdata->channel[i]->tx_ring)
+   XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_TCR,
+  PBL, pbl);
 
-   XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_RCR, PBL,
-  pdata->rx_pbl);
+   if (pdata->channel[i]->rx_ring)
+   XGMAC_DMA_IOWRITE_BITS(pdata->channel[i], DMA_CH_RCR,
+  PBL, pbl);
}
 
return 0;
@@ -2141,7 +2119,7 @@ static void xgbe_config_dma_bus(struct xgbe_prv_data 
*pdata)
 
/* Set the System Bus mode */
XGMAC_IOWRITE_BITS(pdata, DMA_SBMR, UNDEF, 1);
-   XGMAC_IOWRITE_BITS(pdata, DMA_SBMR, BLEN_256, 1);
+   XGMAC_IOWRITE_BITS(pdata, DMA_SBMR, BLEN, pdata->blen >> 2);
 }
 
 static void xgbe_config_dma_cache(struct xgbe_prv_data *pdata)
@@ -3381,9 +3359,7 @@ static int xgbe_init(struct xgbe_prv_data *pdata)
xgbe_config_dma_bus(pdata);
 

[PATCH net-next v1 14/14] amd-xgbe: Adjust register settings to improve performance

2017-06-28 Thread Tom Lendacky
Add support to change some general performance settings and to provide
some performance settings based on the device that is probed.

This includes:

- Setting the maximum read/write outstanding request limit
- Reducing the AXI interface burst length size
- Selectively setting the Tx and Rx descriptor pre-fetch threshold
- Selectively setting additional cache coherency controls

Tested and verified on all versions of the hardware.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-common.h |   13 +
 drivers/net/ethernet/amd/xgbe/xgbe-dev.c|   26 +++---
 drivers/net/ethernet/amd/xgbe/xgbe-main.c   |5 -
 drivers/net/ethernet/amd/xgbe/xgbe-pci.c|9 +++--
 drivers/net/ethernet/amd/xgbe/xgbe.h|   11 +++
 5 files changed, 58 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h 
b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
index 6b5c72d..9795419 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
@@ -123,8 +123,11 @@
 #define DMA_ISR0x3008
 #define DMA_AXIARCR0x3010
 #define DMA_AXIAWCR0x3018
+#define DMA_AXIAWARCR  0x301c
 #define DMA_DSR0   0x3020
 #define DMA_DSR1   0x3024
+#define DMA_TXEDMACR   0x3040
+#define DMA_RXEDMACR   0x3044
 
 /* DMA register entry bit positions and sizes */
 #define DMA_ISR_MACIS_INDEX17
@@ -135,12 +138,22 @@
 #define DMA_MR_INTM_WIDTH  2
 #define DMA_MR_SWR_INDEX   0
 #define DMA_MR_SWR_WIDTH   1
+#define DMA_RXEDMACR_RDPS_INDEX0
+#define DMA_RXEDMACR_RDPS_WIDTH3
+#define DMA_SBMR_AAL_INDEX 12
+#define DMA_SBMR_AAL_WIDTH 1
 #define DMA_SBMR_EAME_INDEX11
 #define DMA_SBMR_EAME_WIDTH1
 #define DMA_SBMR_BLEN_INDEX1
 #define DMA_SBMR_BLEN_WIDTH7
+#define DMA_SBMR_RD_OSR_LMT_INDEX  16
+#define DMA_SBMR_RD_OSR_LMT_WIDTH  6
 #define DMA_SBMR_UNDEF_INDEX   0
 #define DMA_SBMR_UNDEF_WIDTH   1
+#define DMA_SBMR_WR_OSR_LMT_INDEX  24
+#define DMA_SBMR_WR_OSR_LMT_WIDTH  6
+#define DMA_TXEDMACR_TDPS_INDEX0
+#define DMA_TXEDMACR_TDPS_WIDTH3
 
 /* DMA register values */
 #define DMA_SBMR_BLEN_256  256
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index a51ece5..06f953e 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -2114,18 +2114,38 @@ static int xgbe_flush_tx_queues(struct xgbe_prv_data 
*pdata)
 
 static void xgbe_config_dma_bus(struct xgbe_prv_data *pdata)
 {
+   unsigned int sbmr;
+
+   sbmr = XGMAC_IOREAD(pdata, DMA_SBMR);
+
/* Set enhanced addressing mode */
-   XGMAC_IOWRITE_BITS(pdata, DMA_SBMR, EAME, 1);
+   XGMAC_SET_BITS(sbmr, DMA_SBMR, EAME, 1);
 
/* Set the System Bus mode */
-   XGMAC_IOWRITE_BITS(pdata, DMA_SBMR, UNDEF, 1);
-   XGMAC_IOWRITE_BITS(pdata, DMA_SBMR, BLEN, pdata->blen >> 2);
+   XGMAC_SET_BITS(sbmr, DMA_SBMR, UNDEF, 1);
+   XGMAC_SET_BITS(sbmr, DMA_SBMR, BLEN, pdata->blen >> 2);
+   XGMAC_SET_BITS(sbmr, DMA_SBMR, AAL, pdata->aal);
+   XGMAC_SET_BITS(sbmr, DMA_SBMR, RD_OSR_LMT, pdata->rd_osr_limit - 1);
+   XGMAC_SET_BITS(sbmr, DMA_SBMR, WR_OSR_LMT, pdata->wr_osr_limit - 1);
+
+   XGMAC_IOWRITE(pdata, DMA_SBMR, sbmr);
+
+   /* Set descriptor fetching threshold */
+   if (pdata->vdata->tx_desc_prefetch)
+   XGMAC_IOWRITE_BITS(pdata, DMA_TXEDMACR, TDPS,
+  pdata->vdata->tx_desc_prefetch);
+
+   if (pdata->vdata->rx_desc_prefetch)
+   XGMAC_IOWRITE_BITS(pdata, DMA_RXEDMACR, RDPS,
+  pdata->vdata->rx_desc_prefetch);
 }
 
 static void xgbe_config_dma_cache(struct xgbe_prv_data *pdata)
 {
XGMAC_IOWRITE(pdata, DMA_AXIARCR, pdata->arcr);
XGMAC_IOWRITE(pdata, DMA_AXIAWCR, pdata->awcr);
+   if (pdata->awarcr)
+   XGMAC_IOWRITE(pdata, DMA_AXIAWARCR, pdata->awarcr);
 }
 
 static void xgbe_config_mtl_mode(struct xgbe_prv_data *pdata)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
index 8eec9f5..500147d 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
@@ -140,8 +140,11 @@ static void xgbe_default_config(struct xgbe_prv_data 
*pdata)
 {
DBGPR("-->xgbe_default_config\n");
 
-   pdata->blen = DMA_SBMR_BLEN_256;
+   pdata->blen = DMA_SBMR_BLEN_64;
pdata->pbl = DMA_PBL_128;
+   pdat

[PATCH net-next v1 11/14] amd-xgbe: Add NUMA affinity support for IRQ hints

2017-06-28 Thread Tom Lendacky
For IRQ affinity, set the affinity hints for the IRQs to be (initially) on
the processors corresponding to the NUMA node of the device.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c |   18 +++---
 drivers/net/ethernet/amd/xgbe/xgbe.h |2 ++
 2 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index 43b84ff..ecef3ee 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -192,12 +192,17 @@ static int xgbe_alloc_channels(struct xgbe_prv_data 
*pdata)
struct xgbe_channel *channel;
struct xgbe_ring *ring;
unsigned int count, i;
+   unsigned int cpu;
int node;
 
-   node = dev_to_node(pdata->dev);
-
count = max_t(unsigned int, pdata->tx_ring_count, pdata->rx_ring_count);
for (i = 0; i < count; i++) {
+   /* Attempt to use a CPU on the node the device is on */
+   cpu = cpumask_local_spread(i, dev_to_node(pdata->dev));
+
+   /* Set the allocation node based on the returned CPU */
+   node = cpu_to_node(cpu);
+
channel = xgbe_alloc_node(sizeof(*channel), node);
if (!channel)
goto err_mem;
@@ -209,6 +214,7 @@ static int xgbe_alloc_channels(struct xgbe_prv_data *pdata)
channel->dma_regs = pdata->xgmac_regs + DMA_CH_BASE +
(DMA_CH_INC * i);
channel->node = node;
+   cpumask_set_cpu(cpu, >affinity_mask);
 
if (pdata->per_channel_irq)
channel->dma_irq = pdata->channel_irq[i];
@@ -236,7 +242,7 @@ static int xgbe_alloc_channels(struct xgbe_prv_data *pdata)
}
 
netif_dbg(pdata, drv, pdata->netdev,
- "%s: node=%d\n", channel->name, node);
+ "%s: cpu=%u, node=%d\n", channel->name, cpu, node);
 
netif_dbg(pdata, drv, pdata->netdev,
  "%s: dma_regs=%p, dma_irq=%d, tx=%p, rx=%p\n",
@@ -916,6 +922,9 @@ static int xgbe_request_irqs(struct xgbe_prv_data *pdata)
 channel->dma_irq);
goto err_dma_irq;
}
+
+   irq_set_affinity_hint(channel->dma_irq,
+ >affinity_mask);
}
 
return 0;
@@ -925,6 +934,7 @@ static int xgbe_request_irqs(struct xgbe_prv_data *pdata)
for (i--; i < pdata->channel_count; i--) {
channel = pdata->channel[i];
 
+   irq_set_affinity_hint(channel->dma_irq, NULL);
devm_free_irq(pdata->dev, channel->dma_irq, channel);
}
 
@@ -952,6 +962,8 @@ static void xgbe_free_irqs(struct xgbe_prv_data *pdata)
 
for (i = 0; i < pdata->channel_count; i++) {
channel = pdata->channel[i];
+
+   irq_set_affinity_hint(channel->dma_irq, NULL);
devm_free_irq(pdata->dev, channel->dma_irq, channel);
}
 }
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h 
b/drivers/net/ethernet/amd/xgbe/xgbe.h
index ac3b558..7b50469 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe.h
@@ -128,6 +128,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #define XGBE_DRV_NAME  "amd-xgbe"
 #define XGBE_DRV_VERSION   "1.0.3"
@@ -465,6 +466,7 @@ struct xgbe_channel {
struct xgbe_ring *rx_ring;
 
int node;
+   cpumask_t affinity_mask;
 } cacheline_aligned;
 
 enum xgbe_state {



[PATCH net-next v1 12/14] amd-xgbe: Prepare for more fine grained cache coherency controls

2017-06-28 Thread Tom Lendacky
In prep for setting fine grained read and write DMA cache coherency
controls, allow specific values to be used to set the cache coherency
registers.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-common.h   |   28 -
 drivers/net/ethernet/amd/xgbe/xgbe-dev.c  |   23 ++---
 drivers/net/ethernet/amd/xgbe/xgbe-pci.c  |5 ++--
 drivers/net/ethernet/amd/xgbe/xgbe-platform.c |   10 -
 drivers/net/ethernet/amd/xgbe/xgbe.h  |   15 +
 5 files changed, 14 insertions(+), 67 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h 
b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
index e7b6804..dc09883 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
@@ -127,34 +127,6 @@
 #define DMA_DSR1   0x3024
 
 /* DMA register entry bit positions and sizes */
-#define DMA_AXIARCR_DRC_INDEX  0
-#define DMA_AXIARCR_DRC_WIDTH  4
-#define DMA_AXIARCR_DRD_INDEX  4
-#define DMA_AXIARCR_DRD_WIDTH  2
-#define DMA_AXIARCR_TEC_INDEX  8
-#define DMA_AXIARCR_TEC_WIDTH  4
-#define DMA_AXIARCR_TED_INDEX  12
-#define DMA_AXIARCR_TED_WIDTH  2
-#define DMA_AXIARCR_THC_INDEX  16
-#define DMA_AXIARCR_THC_WIDTH  4
-#define DMA_AXIARCR_THD_INDEX  20
-#define DMA_AXIARCR_THD_WIDTH  2
-#define DMA_AXIAWCR_DWC_INDEX  0
-#define DMA_AXIAWCR_DWC_WIDTH  4
-#define DMA_AXIAWCR_DWD_INDEX  4
-#define DMA_AXIAWCR_DWD_WIDTH  2
-#define DMA_AXIAWCR_RPC_INDEX  8
-#define DMA_AXIAWCR_RPC_WIDTH  4
-#define DMA_AXIAWCR_RPD_INDEX  12
-#define DMA_AXIAWCR_RPD_WIDTH  2
-#define DMA_AXIAWCR_RHC_INDEX  16
-#define DMA_AXIAWCR_RHC_WIDTH  4
-#define DMA_AXIAWCR_RHD_INDEX  20
-#define DMA_AXIAWCR_RHD_WIDTH  2
-#define DMA_AXIAWCR_TDC_INDEX  24
-#define DMA_AXIAWCR_TDC_WIDTH  4
-#define DMA_AXIAWCR_TDD_INDEX  28
-#define DMA_AXIAWCR_TDD_WIDTH  2
 #define DMA_ISR_MACIS_INDEX17
 #define DMA_ISR_MACIS_WIDTH1
 #define DMA_ISR_MTLIS_INDEX16
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index b05393f..98da249 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -2146,27 +2146,8 @@ static void xgbe_config_dma_bus(struct xgbe_prv_data 
*pdata)
 
 static void xgbe_config_dma_cache(struct xgbe_prv_data *pdata)
 {
-   unsigned int arcache, awcache;
-
-   arcache = 0;
-   XGMAC_SET_BITS(arcache, DMA_AXIARCR, DRC, pdata->arcache);
-   XGMAC_SET_BITS(arcache, DMA_AXIARCR, DRD, pdata->axdomain);
-   XGMAC_SET_BITS(arcache, DMA_AXIARCR, TEC, pdata->arcache);
-   XGMAC_SET_BITS(arcache, DMA_AXIARCR, TED, pdata->axdomain);
-   XGMAC_SET_BITS(arcache, DMA_AXIARCR, THC, pdata->arcache);
-   XGMAC_SET_BITS(arcache, DMA_AXIARCR, THD, pdata->axdomain);
-   XGMAC_IOWRITE(pdata, DMA_AXIARCR, arcache);
-
-   awcache = 0;
-   XGMAC_SET_BITS(awcache, DMA_AXIAWCR, DWC, pdata->awcache);
-   XGMAC_SET_BITS(awcache, DMA_AXIAWCR, DWD, pdata->axdomain);
-   XGMAC_SET_BITS(awcache, DMA_AXIAWCR, RPC, pdata->awcache);
-   XGMAC_SET_BITS(awcache, DMA_AXIAWCR, RPD, pdata->axdomain);
-   XGMAC_SET_BITS(awcache, DMA_AXIAWCR, RHC, pdata->awcache);
-   XGMAC_SET_BITS(awcache, DMA_AXIAWCR, RHD, pdata->axdomain);
-   XGMAC_SET_BITS(awcache, DMA_AXIAWCR, TDC, pdata->awcache);
-   XGMAC_SET_BITS(awcache, DMA_AXIAWCR, TDD, pdata->axdomain);
-   XGMAC_IOWRITE(pdata, DMA_AXIAWCR, awcache);
+   XGMAC_IOWRITE(pdata, DMA_AXIARCR, pdata->arcr);
+   XGMAC_IOWRITE(pdata, DMA_AXIAWCR, pdata->awcr);
 }
 
 static void xgbe_config_mtl_mode(struct xgbe_prv_data *pdata)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c
index f0c2e88..1e73768 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c
@@ -327,9 +327,8 @@ static int xgbe_pci_probe(struct pci_dev *pdev, const 
struct pci_device_id *id)
 
/* Set the DMA coherency values */
pdata->coherent = 1;
-   pdata->axdomain = XGBE_DMA_OS_AXDOMAIN;
-   pdata->arcache = XGBE_DMA_OS_ARCACHE;
-   pdata->awcache = XGBE_DMA_OS_AWCACHE;
+   pdata->arcr = XGBE_DMA_OS_ARCR;
+   pdata->awcr = XGBE_DMA_OS_AWCR;
 
/* Set the maximum channels and queues */
reg = XP_IOREAD(pdata, XP_PROP_1);
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-platform.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-platform.c
index 84d4c51..d0f3dfb 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-platform.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-platform.c
@@ 

[PATCH net-next v1 10/14] amd-xgbe: Add NUMA affinity support for memory allocations

2017-06-28 Thread Tom Lendacky
Add support to perform memory allocations on the node of the device. The
original allocation or the ring structure and Tx/Rx queues allocated all
of the memory at once and then carved it up for each channel and queue.
To best ensure that we get as much memory from the NUMA node as we can,
break the channel and ring allocations into individual allocations.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-desc.c |   94 ++-
 drivers/net/ethernet/amd/xgbe/xgbe-dev.c  |  135 +-
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c  |  177 -
 drivers/net/ethernet/amd/xgbe/xgbe.h  |5 +
 4 files changed, 217 insertions(+), 194 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c
index 0a98c36..45d9230 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c
@@ -176,8 +176,8 @@ static void xgbe_free_ring_resources(struct xgbe_prv_data 
*pdata)
 
DBGPR("-->xgbe_free_ring_resources\n");
 
-   channel = pdata->channel;
-   for (i = 0; i < pdata->channel_count; i++, channel++) {
+   for (i = 0; i < pdata->channel_count; i++) {
+   channel = pdata->channel[i];
xgbe_free_ring(pdata, channel->tx_ring);
xgbe_free_ring(pdata, channel->rx_ring);
}
@@ -185,34 +185,60 @@ static void xgbe_free_ring_resources(struct xgbe_prv_data 
*pdata)
DBGPR("<--xgbe_free_ring_resources\n");
 }
 
+static void *xgbe_alloc_node(size_t size, int node)
+{
+   void *mem;
+
+   mem = kzalloc_node(size, GFP_KERNEL, node);
+   if (!mem)
+   mem = kzalloc(size, GFP_KERNEL);
+
+   return mem;
+}
+
+static void *xgbe_dma_alloc_node(struct device *dev, size_t size,
+dma_addr_t *dma, int node)
+{
+   void *mem;
+   int cur_node = dev_to_node(dev);
+
+   set_dev_node(dev, node);
+   mem = dma_alloc_coherent(dev, size, dma, GFP_KERNEL);
+   set_dev_node(dev, cur_node);
+
+   if (!mem)
+   mem = dma_alloc_coherent(dev, size, dma, GFP_KERNEL);
+
+   return mem;
+}
+
 static int xgbe_init_ring(struct xgbe_prv_data *pdata,
  struct xgbe_ring *ring, unsigned int rdesc_count)
 {
-   DBGPR("-->xgbe_init_ring\n");
+   size_t size;
 
if (!ring)
return 0;
 
/* Descriptors */
+   size = rdesc_count * sizeof(struct xgbe_ring_desc);
+
ring->rdesc_count = rdesc_count;
-   ring->rdesc = dma_alloc_coherent(pdata->dev,
-(sizeof(struct xgbe_ring_desc) *
- rdesc_count), >rdesc_dma,
-GFP_KERNEL);
+   ring->rdesc = xgbe_dma_alloc_node(pdata->dev, size, >rdesc_dma,
+ ring->node);
if (!ring->rdesc)
return -ENOMEM;
 
/* Descriptor information */
-   ring->rdata = kcalloc(rdesc_count, sizeof(struct xgbe_ring_data),
- GFP_KERNEL);
+   size = rdesc_count * sizeof(struct xgbe_ring_data);
+
+   ring->rdata = xgbe_alloc_node(size, ring->node);
if (!ring->rdata)
return -ENOMEM;
 
netif_dbg(pdata, drv, pdata->netdev,
- "rdesc=%p, rdesc_dma=%pad, rdata=%p\n",
- ring->rdesc, >rdesc_dma, ring->rdata);
-
-   DBGPR("<--xgbe_init_ring\n");
+ "rdesc=%p, rdesc_dma=%pad, rdata=%p, node=%d\n",
+ ring->rdesc, >rdesc_dma, ring->rdata, ring->node);
 
return 0;
 }
@@ -223,10 +249,8 @@ static int xgbe_alloc_ring_resources(struct xgbe_prv_data 
*pdata)
unsigned int i;
int ret;
 
-   DBGPR("-->xgbe_alloc_ring_resources\n");
-
-   channel = pdata->channel;
-   for (i = 0; i < pdata->channel_count; i++, channel++) {
+   for (i = 0; i < pdata->channel_count; i++) {
+   channel = pdata->channel[i];
netif_dbg(pdata, drv, pdata->netdev, "%s - Tx ring:\n",
  channel->name);
 
@@ -250,8 +274,6 @@ static int xgbe_alloc_ring_resources(struct xgbe_prv_data 
*pdata)
}
}
 
-   DBGPR("<--xgbe_alloc_ring_resources\n");
-
return 0;
 
 err_ring:
@@ -261,21 +283,33 @@ static int xgbe_alloc_ring_resources(struct xgbe_prv_data 
*pdata)
 }
 
 static int xgbe_alloc_pages(struct xgbe_prv_data *pdata,
-   struct xgbe_page_alloc *pa, gfp_t gfp, int order)
+   struct xgbe_page_alloc *pa, int alloc_order,
+   int node)
 {
  

[PATCH net-next v1 09/14] amd-xgbe: Re-issue interrupt if interrupt status not cleared

2017-06-28 Thread Tom Lendacky
Some of the device interrupts should function as level interrupts. For
some hardware configurations this requires setting some control bits
so that if the interrupt status has not been cleared the interrupt
should be reissued.

Additionally, when using MSI or MSI-X interrupts, run the interrupt
service routine as a tasklet so that the re-issuance of the interrupt
is handled properly.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-common.h |1 +
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c|   53 +++
 drivers/net/ethernet/amd/xgbe/xgbe-i2c.c|   30 +--
 drivers/net/ethernet/amd/xgbe/xgbe-mdio.c   |   33 +++--
 drivers/net/ethernet/amd/xgbe/xgbe-pci.c|4 ++
 drivers/net/ethernet/amd/xgbe/xgbe.h|   11 +-
 6 files changed, 115 insertions(+), 17 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h 
b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
index 127adbe..e7b6804 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
@@ -959,6 +959,7 @@
 #define XP_DRIVER_INT_RO   0x0064
 #define XP_DRIVER_SCRATCH_00x0068
 #define XP_DRIVER_SCRATCH_10x006c
+#define XP_INT_REISSUE_EN  0x0074
 #define XP_INT_EN  0x0078
 #define XP_I2C_MUTEX   0x0080
 #define XP_MDIO_MUTEX  0x0084
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index 2068510..ff6d204 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -382,9 +382,9 @@ static bool xgbe_ecc_ded(struct xgbe_prv_data *pdata, 
unsigned long *period,
return false;
 }
 
-static irqreturn_t xgbe_ecc_isr(int irq, void *data)
+static void xgbe_ecc_isr_task(unsigned long data)
 {
-   struct xgbe_prv_data *pdata = data;
+   struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data;
unsigned int ecc_isr;
bool stop = false;
 
@@ -435,12 +435,26 @@ static irqreturn_t xgbe_ecc_isr(int irq, void *data)
/* Clear all ECC interrupts */
XP_IOWRITE(pdata, XP_ECC_ISR, ecc_isr);
 
-   return IRQ_HANDLED;
+   /* Reissue interrupt if status is not clear */
+   if (pdata->vdata->irq_reissue_support)
+   XP_IOWRITE(pdata, XP_INT_REISSUE_EN, 1 << 1);
 }
 
-static irqreturn_t xgbe_isr(int irq, void *data)
+static irqreturn_t xgbe_ecc_isr(int irq, void *data)
 {
struct xgbe_prv_data *pdata = data;
+
+   if (pdata->isr_as_tasklet)
+   tasklet_schedule(>tasklet_ecc);
+   else
+   xgbe_ecc_isr_task((unsigned long)pdata);
+
+   return IRQ_HANDLED;
+}
+
+static void xgbe_isr_task(unsigned long data)
+{
+   struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data;
struct xgbe_hw_if *hw_if = >hw_if;
struct xgbe_channel *channel;
unsigned int dma_isr, dma_ch_isr;
@@ -543,15 +557,36 @@ static irqreturn_t xgbe_isr(int irq, void *data)
 isr_done:
/* If there is not a separate AN irq, handle it here */
if (pdata->dev_irq == pdata->an_irq)
-   pdata->phy_if.an_isr(irq, pdata);
+   pdata->phy_if.an_isr(pdata);
 
/* If there is not a separate ECC irq, handle it here */
if (pdata->vdata->ecc_support && (pdata->dev_irq == pdata->ecc_irq))
-   xgbe_ecc_isr(irq, pdata);
+   xgbe_ecc_isr_task((unsigned long)pdata);
 
/* If there is not a separate I2C irq, handle it here */
if (pdata->vdata->i2c_support && (pdata->dev_irq == pdata->i2c_irq))
-   pdata->i2c_if.i2c_isr(irq, pdata);
+   pdata->i2c_if.i2c_isr(pdata);
+
+   /* Reissue interrupt if status is not clear */
+   if (pdata->vdata->irq_reissue_support) {
+   unsigned int reissue_mask;
+
+   reissue_mask = 1 << 0;
+   if (!pdata->per_channel_irq)
+   reissue_mask |= 0x < 4;
+
+   XP_IOWRITE(pdata, XP_INT_REISSUE_EN, reissue_mask);
+   }
+}
+
+static irqreturn_t xgbe_isr(int irq, void *data)
+{
+   struct xgbe_prv_data *pdata = data;
+
+   if (pdata->isr_as_tasklet)
+   tasklet_schedule(>tasklet_dev);
+   else
+   xgbe_isr_task((unsigned long)pdata);
 
return IRQ_HANDLED;
 }
@@ -826,6 +861,10 @@ static int xgbe_request_irqs(struct xgbe_prv_data *pdata)
unsigned int i;
int ret;
 
+   tasklet_init(>tasklet_dev, xgbe_isr_task, (unsigned long)pdata);
+   tasklet_init(>tasklet_ecc, xgbe_ecc_isr_task,
+(unsigned long)pdata);
+
ret = devm_request_irq(pdata->dev, pdata->dev_irq, xgbe_isr, 0,
   netdev->name, 

[PATCH net-next v1 04/14] amd-xgbe: Add a check for an skb in the timestamp path

2017-06-28 Thread Tom Lendacky
Spurious Tx timestamp interrupts can cause an oops in the Tx timestamp
processing function if a Tx timestamp skb is NULL. Add a check to insure
a Tx timestamp skb is present before attempting to use it.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c |7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index a934bd5..2068510 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -1212,6 +1212,10 @@ static void xgbe_tx_tstamp(struct work_struct *work)
u64 nsec;
unsigned long flags;
 
+   spin_lock_irqsave(>tstamp_lock, flags);
+   if (!pdata->tx_tstamp_skb)
+   goto unlock;
+
if (pdata->tx_tstamp) {
nsec = timecounter_cyc2time(>tstamp_tc,
pdata->tx_tstamp);
@@ -1223,8 +1227,9 @@ static void xgbe_tx_tstamp(struct work_struct *work)
 
dev_kfree_skb_any(pdata->tx_tstamp_skb);
 
-   spin_lock_irqsave(>tstamp_lock, flags);
pdata->tx_tstamp_skb = NULL;
+
+unlock:
spin_unlock_irqrestore(>tstamp_lock, flags);
 }
 



[PATCH net-next v1 08/14] amd-xgbe: Limit the I2C error messages that are output

2017-06-28 Thread Tom Lendacky
When I2C communication fails, it tends to always fail. Rather than
continuously issue an error message (once per second in most cases),
change the message to be issued just once.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c |9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
index b8be62e..04b5c14 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
@@ -1121,7 +1121,8 @@ static int xgbe_phy_sfp_read_eeprom(struct xgbe_prv_data 
*pdata)
 
ret = xgbe_phy_sfp_get_mux(pdata);
if (ret) {
-   netdev_err(pdata->netdev, "I2C error setting SFP MUX\n");
+   dev_err_once(pdata->dev, "%s: I2C error setting SFP MUX\n",
+netdev_name(pdata->netdev));
return ret;
}
 
@@ -1131,7 +1132,8 @@ static int xgbe_phy_sfp_read_eeprom(struct xgbe_prv_data 
*pdata)
_addr, sizeof(eeprom_addr),
_eeprom, sizeof(sfp_eeprom));
if (ret) {
-   netdev_err(pdata->netdev, "I2C error reading SFP EEPROM\n");
+   dev_err_once(pdata->dev, "%s: I2C error reading SFP EEPROM\n",
+netdev_name(pdata->netdev));
goto put;
}
 
@@ -1190,7 +1192,8 @@ static void xgbe_phy_sfp_signals(struct xgbe_prv_data 
*pdata)
_reg, sizeof(gpio_reg),
gpio_ports, sizeof(gpio_ports));
if (ret) {
-   netdev_err(pdata->netdev, "I2C error reading SFP GPIOs\n");
+   dev_err_once(pdata->dev, "%s: I2C error reading SFP GPIOs\n",
+netdev_name(pdata->netdev));
return;
}
 



[PATCH net-next v1 06/14] amd-xgbe: Handle return code from software reset function

2017-06-28 Thread Tom Lendacky
Currently the function that performs a software reset of the hardware
provides a return code.  During driver probe check this return code and
exit with an error if the software reset fails.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-main.c |6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
index 17ac8f9..982368b 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
@@ -277,7 +277,11 @@ int xgbe_config_netdev(struct xgbe_prv_data *pdata)
pdata->desc_ded_period = jiffies;
 
/* Issue software reset to device */
-   pdata->hw_if.exit(pdata);
+   ret = pdata->hw_if.exit(pdata);
+   if (ret) {
+   dev_err(dev, "software reset failed\n");
+   return ret;
+   }
 
/* Set default configuration data */
xgbe_default_config(pdata);



[PATCH net-next v1 07/14] amd-xgbe: Fixes for working with PHYs that support 2.5GbE

2017-06-28 Thread Tom Lendacky
The driver has some missing functionality when operating in the mode that
supports 2.5GbE.  Fix the driver to fully recognize and support this speed.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c |7 +++
 1 file changed, 7 insertions(+)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
index 756e116..b8be62e 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
@@ -1966,6 +1966,8 @@ static enum xgbe_mode xgbe_phy_get_baset_mode(struct 
xgbe_phy_data *phy_data,
return XGBE_MODE_SGMII_100;
case SPEED_1000:
return XGBE_MODE_SGMII_1000;
+   case SPEED_2500:
+   return XGBE_MODE_KX_2500;
case SPEED_1:
return XGBE_MODE_KR;
default:
@@ -2109,6 +2111,9 @@ static bool xgbe_phy_use_baset_mode(struct xgbe_prv_data 
*pdata,
case XGBE_MODE_SGMII_1000:
return xgbe_phy_check_mode(pdata, mode,
   ADVERTISED_1000baseT_Full);
+   case XGBE_MODE_KX_2500:
+   return xgbe_phy_check_mode(pdata, mode,
+  ADVERTISED_2500baseX_Full);
case XGBE_MODE_KR:
return xgbe_phy_check_mode(pdata, mode,
   ADVERTISED_1baseT_Full);
@@ -2218,6 +2223,8 @@ static bool xgbe_phy_valid_speed_baset_mode(struct 
xgbe_phy_data *phy_data,
case SPEED_100:
case SPEED_1000:
return true;
+   case SPEED_2500:
+   return (phy_data->port_mode == XGBE_PORT_MODE_NBASE_T);
case SPEED_1:
return (phy_data->port_mode == XGBE_PORT_MODE_10GBASE_T);
default:



[PATCH net-next v1 05/14] amd-xgbe: Prevent looping forever if timestamp update fails

2017-06-28 Thread Tom Lendacky
Just to be on the safe side, should the update of the timestamp registers
not complete, issue a warning rather than looping forever waiting for the
update to complete.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-dev.c |   15 +--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index 24a687c..3ad4036 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -1497,26 +1497,37 @@ static void xgbe_rx_desc_init(struct xgbe_channel 
*channel)
 static void xgbe_update_tstamp_addend(struct xgbe_prv_data *pdata,
  unsigned int addend)
 {
+   unsigned int count = 1;
+
/* Set the addend register value and tell the device */
XGMAC_IOWRITE(pdata, MAC_TSAR, addend);
XGMAC_IOWRITE_BITS(pdata, MAC_TSCR, TSADDREG, 1);
 
/* Wait for addend update to complete */
-   while (XGMAC_IOREAD_BITS(pdata, MAC_TSCR, TSADDREG))
+   while (--count && XGMAC_IOREAD_BITS(pdata, MAC_TSCR, TSADDREG))
udelay(5);
+
+   if (!count)
+   netdev_err(pdata->netdev,
+  "timed out updating timestamp addend register\n");
 }
 
 static void xgbe_set_tstamp_time(struct xgbe_prv_data *pdata, unsigned int sec,
 unsigned int nsec)
 {
+   unsigned int count = 1;
+
/* Set the time values and tell the device */
XGMAC_IOWRITE(pdata, MAC_STSUR, sec);
XGMAC_IOWRITE(pdata, MAC_STNUR, nsec);
XGMAC_IOWRITE_BITS(pdata, MAC_TSCR, TSINIT, 1);
 
/* Wait for time update to complete */
-   while (XGMAC_IOREAD_BITS(pdata, MAC_TSCR, TSINIT))
+   while (--count && XGMAC_IOREAD_BITS(pdata, MAC_TSCR, TSINIT))
udelay(5);
+
+   if (!count)
+   netdev_err(pdata->netdev, "timed out initializing timestamp\n");
 }
 
 static u64 xgbe_get_tstamp_time(struct xgbe_prv_data *pdata)



[PATCH net-next v1 01/14] amd-xgbe: Simplify mailbox interface rate change code

2017-06-28 Thread Tom Lendacky
Simplify and centralize the mailbox command rate change interface by
having a single function perform the writes to the mailbox registers
to issue the request.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c |  155 +--
 1 file changed, 29 insertions(+), 126 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
index e707c49..0429840 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
@@ -1694,19 +1694,25 @@ static void xgbe_phy_set_redrv_mode(struct 
xgbe_prv_data *pdata)
xgbe_phy_put_comm_ownership(pdata);
 }
 
-static void xgbe_phy_start_ratechange(struct xgbe_prv_data *pdata)
+static void xgbe_phy_perform_ratechange(struct xgbe_prv_data *pdata,
+   unsigned int cmd, unsigned int sub_cmd)
 {
-   if (!XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS))
-   return;
+   unsigned int s0 = 0;
+   unsigned int wait;
 
/* Log if a previous command did not complete */
-   netif_dbg(pdata, link, pdata->netdev,
- "firmware mailbox not ready for command\n");
-}
+   if (XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS))
+   netif_dbg(pdata, link, pdata->netdev,
+ "firmware mailbox not ready for command\n");
 
-static void xgbe_phy_complete_ratechange(struct xgbe_prv_data *pdata)
-{
-   unsigned int wait;
+   /* Construct the command */
+   XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, cmd);
+   XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, sub_cmd);
+
+   /* Issue the command */
+   XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, s0);
+   XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0);
+   XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1);
 
/* Wait for command to complete */
wait = XGBE_RATECHANGE_COUNT;
@@ -1723,21 +1729,8 @@ static void xgbe_phy_complete_ratechange(struct 
xgbe_prv_data *pdata)
 
 static void xgbe_phy_rrc(struct xgbe_prv_data *pdata)
 {
-   unsigned int s0;
-
-   xgbe_phy_start_ratechange(pdata);
-
/* Receiver Reset Cycle */
-   s0 = 0;
-   XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, 5);
-   XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 0);
-
-   /* Call FW to make the change */
-   XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, s0);
-   XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0);
-   XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1);
-
-   xgbe_phy_complete_ratechange(pdata);
+   xgbe_phy_perform_ratechange(pdata, 5, 0);
 
netif_dbg(pdata, link, pdata->netdev, "receiver reset complete\n");
 }
@@ -1746,14 +1739,8 @@ static void xgbe_phy_power_off(struct xgbe_prv_data 
*pdata)
 {
struct xgbe_phy_data *phy_data = pdata->phy_data;
 
-   xgbe_phy_start_ratechange(pdata);
-
-   /* Call FW to make the change */
-   XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, 0);
-   XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0);
-   XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1);
-
-   xgbe_phy_complete_ratechange(pdata);
+   /* Power off */
+   xgbe_phy_perform_ratechange(pdata, 0, 0);
 
phy_data->cur_mode = XGBE_MODE_UNKNOWN;
 
@@ -1763,33 +1750,21 @@ static void xgbe_phy_power_off(struct xgbe_prv_data 
*pdata)
 static void xgbe_phy_sfi_mode(struct xgbe_prv_data *pdata)
 {
struct xgbe_phy_data *phy_data = pdata->phy_data;
-   unsigned int s0;
 
xgbe_phy_set_redrv_mode(pdata);
 
-   xgbe_phy_start_ratechange(pdata);
-
/* 10G/SFI */
-   s0 = 0;
-   XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, 3);
if (phy_data->sfp_cable != XGBE_SFP_CABLE_PASSIVE) {
-   XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 0);
+   xgbe_phy_perform_ratechange(pdata, 3, 0);
} else {
if (phy_data->sfp_cable_len <= 1)
-   XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 1);
+   xgbe_phy_perform_ratechange(pdata, 3, 1);
else if (phy_data->sfp_cable_len <= 3)
-   XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 2);
+   xgbe_phy_perform_ratechange(pdata, 3, 2);
else
-   XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 3);
+   xgbe_phy_perform_ratechange(pdata, 3, 3);
}
 
-   /* Call FW to make the change */
-   XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, s0);
-   XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0);
-   XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1);
-
-   xgbe_phy_complete_ratechange(pdata);
-
phy_data->cur_mode = XGBE_MODE_SFI;
 
netif_dbg(pdata, link, pdata->netdev, "10GbE SFI mode set\n"

[PATCH net-next v1 02/14] amd-xgbe: Fix SFP PHY supported/advertised settings

2017-06-28 Thread Tom Lendacky
When using SFPs, the supported and advertised settings should be initially
based on the SFP that has been detected.  The code currently indicates the
overall support of the device as opposed to what the SFP is capable of.
Update the code to change the supported link modes, auto-negotiation, etc.
to be based on the installed SFP.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c |   69 ++-
 1 file changed, 47 insertions(+), 22 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
index 0429840..756e116 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
@@ -711,23 +711,39 @@ static void xgbe_phy_sfp_phy_settings(struct 
xgbe_prv_data *pdata)
 {
struct xgbe_phy_data *phy_data = pdata->phy_data;
 
+   if (!phy_data->sfp_mod_absent && !phy_data->sfp_changed)
+   return;
+
+   pdata->phy.supported &= ~SUPPORTED_Autoneg;
+   pdata->phy.supported &= ~(SUPPORTED_Pause | SUPPORTED_Asym_Pause);
+   pdata->phy.supported &= ~SUPPORTED_TP;
+   pdata->phy.supported &= ~SUPPORTED_FIBRE;
+   pdata->phy.supported &= ~SUPPORTED_100baseT_Full;
+   pdata->phy.supported &= ~SUPPORTED_1000baseT_Full;
+   pdata->phy.supported &= ~SUPPORTED_1baseT_Full;
+
if (phy_data->sfp_mod_absent) {
pdata->phy.speed = SPEED_UNKNOWN;
pdata->phy.duplex = DUPLEX_UNKNOWN;
pdata->phy.autoneg = AUTONEG_ENABLE;
+   pdata->phy.pause_autoneg = AUTONEG_ENABLE;
+
+   pdata->phy.supported |= SUPPORTED_Autoneg;
+   pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
+   pdata->phy.supported |= SUPPORTED_TP;
+   pdata->phy.supported |= SUPPORTED_FIBRE;
+   if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100)
+   pdata->phy.supported |= SUPPORTED_100baseT_Full;
+   if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000)
+   pdata->phy.supported |= SUPPORTED_1000baseT_Full;
+   if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1)
+   pdata->phy.supported |= SUPPORTED_1baseT_Full;
+
pdata->phy.advertising = pdata->phy.supported;
 
return;
}
 
-   pdata->phy.advertising &= ~ADVERTISED_Autoneg;
-   pdata->phy.advertising &= ~ADVERTISED_TP;
-   pdata->phy.advertising &= ~ADVERTISED_FIBRE;
-   pdata->phy.advertising &= ~ADVERTISED_100baseT_Full;
-   pdata->phy.advertising &= ~ADVERTISED_1000baseT_Full;
-   pdata->phy.advertising &= ~ADVERTISED_1baseT_Full;
-   pdata->phy.advertising &= ~ADVERTISED_1baseR_FEC;
-
switch (phy_data->sfp_base) {
case XGBE_SFP_BASE_1000_T:
case XGBE_SFP_BASE_1000_SX:
@@ -736,17 +752,25 @@ static void xgbe_phy_sfp_phy_settings(struct 
xgbe_prv_data *pdata)
pdata->phy.speed = SPEED_UNKNOWN;
pdata->phy.duplex = DUPLEX_UNKNOWN;
pdata->phy.autoneg = AUTONEG_ENABLE;
-   pdata->phy.advertising |= ADVERTISED_Autoneg;
+   pdata->phy.pause_autoneg = AUTONEG_ENABLE;
+   pdata->phy.supported |= SUPPORTED_Autoneg;
+   pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
break;
case XGBE_SFP_BASE_1_SR:
case XGBE_SFP_BASE_1_LR:
case XGBE_SFP_BASE_1_LRM:
case XGBE_SFP_BASE_1_ER:
case XGBE_SFP_BASE_1_CR:
-   default:
pdata->phy.speed = SPEED_1;
pdata->phy.duplex = DUPLEX_FULL;
pdata->phy.autoneg = AUTONEG_DISABLE;
+   pdata->phy.pause_autoneg = AUTONEG_DISABLE;
+   break;
+   default:
+   pdata->phy.speed = SPEED_UNKNOWN;
+   pdata->phy.duplex = DUPLEX_UNKNOWN;
+   pdata->phy.autoneg = AUTONEG_DISABLE;
+   pdata->phy.pause_autoneg = AUTONEG_DISABLE;
break;
}
 
@@ -754,36 +778,38 @@ static void xgbe_phy_sfp_phy_settings(struct 
xgbe_prv_data *pdata)
case XGBE_SFP_BASE_1000_T:
case XGBE_SFP_BASE_1000_CX:
case XGBE_SFP_BASE_1_CR:
-   pdata->phy.advertising |= ADVERTISED_TP;
+   pdata->phy.supported |= SUPPORTED_TP;
break;
default:
-   pdata->phy.advertising |= ADVERTISED_FIBRE;
+   pdata->phy.supported |= SUPPORTED_FIBRE;
}
 
switch (phy_data->sfp_speed) {
case XGBE_SFP_SPEED_100_1000:

[PATCH net-next v1 03/14] amd-xgbe: Use the proper register during PTP initialization

2017-06-28 Thread Tom Lendacky
During PTP initialization, the Timestamp Control register should be
cleared and not the Tx Configuration register.  While this typo causes
the wrong register to be cleared, the default value of each register and
and the fact that the Tx Configuration register is programmed afterwards
doesn't result in a bug, hence only fixing in net-next.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-ptp.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c
index a533a6c..d06d260 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c
@@ -267,7 +267,7 @@ void xgbe_ptp_register(struct xgbe_prv_data *pdata)
 ktime_to_ns(ktime_get_real()));
 
/* Disable all timestamping to start */
-   XGMAC_IOWRITE(pdata, MAC_TCR, 0);
+   XGMAC_IOWRITE(pdata, MAC_TSCR, 0);
pdata->tstamp_config.tx_type = HWTSTAMP_TX_OFF;
pdata->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE;
 }



[PATCH net-next v1 00/14] amd-xgbe: AMD XGBE driver updates 2016-06-28

2017-06-28 Thread Tom Lendacky
The following updates and fixes are included in this driver update series:

- Simplify mailbox interface code
- Fix SFP supported and advertising settings
- Fix PTP initialization register usage
- Insure there is timestamp skb present before using it
- Add a timeout to timestamp register updates
- Handle return code from software reset function
- Some fixes for handling 2.5Gbps rates
- Limit I2C error messages
- Fix non-DMA interrupt handling through tasklet usage
- Add NUMA affinity support for memory allocations
- Add NUMA affinity support for interrupts
- Prepare for more fine-grained cache coherency controls
- Simplify setting the DMA burst length programming
- Performance improvements

This patch series is based on net-next.

---

Tom Lendacky (14):
  amd-xgbe: Simplify mailbox interface rate change code
  amd-xgbe: Fix SFP PHY supported/advertised settings
  amd-xgbe: Use the proper register during PTP initialization
  amd-xgbe: Add a check for an skb in the timestamp path
  amd-xgbe: Prevent looping forever if timestamp update fails
  amd-xgbe: Handle return code from software reset function
  amd-xgbe: Fixes for working with PHYs that support 2.5GbE
  amd-xgbe: Limit the I2C error messages that are output
  amd-xgbe: Re-issue interrupt if interrupt status not cleared
  amd-xgbe: Add NUMA affinity support for memory allocations
  amd-xgbe: Add NUMA affinity support for IRQ hints
  amd-xgbe: Prepare for more fine grained cache coherency controls
  amd-xgbe: Simplify the burst length settings
  amd-xgbe: Adjust register settings to improve performance


 drivers/net/ethernet/amd/xgbe/xgbe-common.h   |   53 ++---
 drivers/net/ethernet/amd/xgbe/xgbe-desc.c |   94 +++---
 drivers/net/ethernet/amd/xgbe/xgbe-dev.c  |  244 ++---
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c  |  245 -
 drivers/net/ethernet/amd/xgbe/xgbe-i2c.c  |   30 +++
 drivers/net/ethernet/amd/xgbe/xgbe-main.c |   14 +
 drivers/net/ethernet/amd/xgbe/xgbe-mdio.c |   33 +++
 drivers/net/ethernet/amd/xgbe/xgbe-pci.c  |   14 +
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c   |  240 +---
 drivers/net/ethernet/amd/xgbe/xgbe-platform.c |   10 -
 drivers/net/ethernet/amd/xgbe/xgbe-ptp.c  |2 
 drivers/net/ethernet/amd/xgbe/xgbe.h  |   56 +++---
 12 files changed, 547 insertions(+), 488 deletions(-)

-- 
Tom Lendacky


Re: [PATCH] amd-xgbe: use PAGE_ALLOC_COSTLY_ORDER in xgbe_map_rx_buffer

2017-06-02 Thread Tom Lendacky

On 6/2/2017 10:54 AM, Michal Hocko wrote:

From: Michal Hocko <mho...@suse.com>

xgbe_map_rx_buffer is rather confused about what PAGE_ALLOC_COSTLY_ORDER
means. It uses PAGE_ALLOC_COSTLY_ORDER-1 assuming that
PAGE_ALLOC_COSTLY_ORDER is the first costly order which is not the case
actually because orders larger than that are costly. And even that
applies only to sleeping allocations which is not the case here. We
simply do not perform any costly operations like reclaim or compaction
for those. Simplify the code by dropping the order calculation and use
PAGE_ALLOC_COSTLY_ORDER directly.

Signed-off-by: Michal Hocko <mho...@suse.com>


Acked-by: Tom Lendacky <thomas.lenda...@amd.com>


---
  drivers/net/ethernet/amd/xgbe/xgbe-desc.c | 5 ++---
  1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c
index b3bc87fe3764..0a98c369df20 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c
@@ -324,7 +324,7 @@ static int xgbe_map_rx_buffer(struct xgbe_prv_data *pdata,
  struct xgbe_ring *ring,
  struct xgbe_ring_data *rdata)
  {
-   int order, ret;
+   int ret;
  
  	if (!ring->rx_hdr_pa.pages) {

ret = xgbe_alloc_pages(pdata, >rx_hdr_pa, GFP_ATOMIC, 0);
@@ -333,9 +333,8 @@ static int xgbe_map_rx_buffer(struct xgbe_prv_data *pdata,
}
  
  	if (!ring->rx_buf_pa.pages) {

-   order = max_t(int, PAGE_ALLOC_COSTLY_ORDER - 1, 0);
ret = xgbe_alloc_pages(pdata, >rx_buf_pa, GFP_ATOMIC,
-  order);
+  PAGE_ALLOC_COSTLY_ORDER);
if (ret)
return ret;
}



[PATCH net] amd-xgbe: Fix the ECC-related bit position definitions

2017-03-22 Thread Tom Lendacky
The ECC bit positions that describe whether the ECC interrupt is for
Tx, Rx or descriptor memory and whether the it is a single correctable
or double detected error were defined in incorrectly (reversed order).
Fix the bit position definitions for these settings so that the proper
ECC handling is performed.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---

Please queue this patch up for 4.10-stable.

 drivers/net/ethernet/amd/xgbe/xgbe-common.h |   24 
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h 
b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
index 86f1626..127adbe 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
@@ -984,29 +984,29 @@
 #define XP_ECC_CNT1_DESC_DED_WIDTH 8
 #define XP_ECC_CNT1_DESC_SEC_INDEX 0
 #define XP_ECC_CNT1_DESC_SEC_WIDTH 8
-#define XP_ECC_IER_DESC_DED_INDEX  0
+#define XP_ECC_IER_DESC_DED_INDEX  5
 #define XP_ECC_IER_DESC_DED_WIDTH  1
-#define XP_ECC_IER_DESC_SEC_INDEX  1
+#define XP_ECC_IER_DESC_SEC_INDEX  4
 #define XP_ECC_IER_DESC_SEC_WIDTH  1
-#define XP_ECC_IER_RX_DED_INDEX2
+#define XP_ECC_IER_RX_DED_INDEX3
 #define XP_ECC_IER_RX_DED_WIDTH1
-#define XP_ECC_IER_RX_SEC_INDEX3
+#define XP_ECC_IER_RX_SEC_INDEX2
 #define XP_ECC_IER_RX_SEC_WIDTH1
-#define XP_ECC_IER_TX_DED_INDEX4
+#define XP_ECC_IER_TX_DED_INDEX1
 #define XP_ECC_IER_TX_DED_WIDTH1
-#define XP_ECC_IER_TX_SEC_INDEX5
+#define XP_ECC_IER_TX_SEC_INDEX0
 #define XP_ECC_IER_TX_SEC_WIDTH1
-#define XP_ECC_ISR_DESC_DED_INDEX  0
+#define XP_ECC_ISR_DESC_DED_INDEX  5
 #define XP_ECC_ISR_DESC_DED_WIDTH  1
-#define XP_ECC_ISR_DESC_SEC_INDEX  1
+#define XP_ECC_ISR_DESC_SEC_INDEX  4
 #define XP_ECC_ISR_DESC_SEC_WIDTH  1
-#define XP_ECC_ISR_RX_DED_INDEX2
+#define XP_ECC_ISR_RX_DED_INDEX3
 #define XP_ECC_ISR_RX_DED_WIDTH1
-#define XP_ECC_ISR_RX_SEC_INDEX3
+#define XP_ECC_ISR_RX_SEC_INDEX2
 #define XP_ECC_ISR_RX_SEC_WIDTH1
-#define XP_ECC_ISR_TX_DED_INDEX4
+#define XP_ECC_ISR_TX_DED_INDEX1
 #define XP_ECC_ISR_TX_DED_WIDTH1
-#define XP_ECC_ISR_TX_SEC_INDEX5
+#define XP_ECC_ISR_TX_SEC_INDEX0
 #define XP_ECC_ISR_TX_SEC_WIDTH1
 #define XP_I2C_MUTEX_BUSY_INDEX31
 #define XP_I2C_MUTEX_BUSY_WIDTH1



Re: [PATCH net] amd-xgbe: Fix jumbo MTU processing on newer hardware

2017-03-15 Thread Tom Lendacky

On 3/15/2017 5:52 PM, Tom Lendacky wrote:

On 3/15/2017 5:41 PM, David Miller wrote:

From: Tom Lendacky <thomas.lenda...@amd.com>
Date: Wed, 15 Mar 2017 17:40:51 -0500


On 3/15/2017 5:37 PM, David Miller wrote:

From: Tom Lendacky <thomas.lenda...@amd.com>
Date: Wed, 15 Mar 2017 15:11:23 -0500


Newer hardware does not provide a cumulative payload length when
multiple
descriptors are needed to handle the data. Once the MTU increases
beyond
the size that can be handled by a single descriptor, the SKB does not
get
built properly by the driver.

The driver will now calculate the size of the data buffers used by the
hardware.  The first buffer of the first descriptor is for packet
headers
or packet headers and data when the headers can't be split. Subsequent
descriptors in a multi-descriptor chain will not use the first
buffer. The
second buffer is used by all the descriptors in the chain for payload
data.
Based on whether the driver is processing the first, intermediate, or
last
descriptor it can calculate the buffer usage and build the SKB
properly.

Tested and verified on both old and new hardware.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>


Applied, thanks Tom.


Thanks David.  This is another patch for 4.10 stable. Can you please
queue it up?


Can you properly state this in your patch postings, instead of always
mentioning it later?



Sorry, yes, I can do that.  I didn't realize you preferred it that way.
Do you want the "Cc" tag to stable included in the patch or just
mention the stable targets in the patch description?  I know you
coordinate the stable submissions and I don't want to mess anything up.



Never mind, just found the section in the netdev-FAQ.txt file that talks
about it.  Sorry to bother you.

Thanks,
Tom


Thanks,
Tom



Thank you.



Re: [PATCH net] amd-xgbe: Fix jumbo MTU processing on newer hardware

2017-03-15 Thread Tom Lendacky

On 3/15/2017 5:37 PM, David Miller wrote:

From: Tom Lendacky <thomas.lenda...@amd.com>
Date: Wed, 15 Mar 2017 15:11:23 -0500


Newer hardware does not provide a cumulative payload length when multiple
descriptors are needed to handle the data. Once the MTU increases beyond
the size that can be handled by a single descriptor, the SKB does not get
built properly by the driver.

The driver will now calculate the size of the data buffers used by the
hardware.  The first buffer of the first descriptor is for packet headers
or packet headers and data when the headers can't be split. Subsequent
descriptors in a multi-descriptor chain will not use the first buffer. The
second buffer is used by all the descriptors in the chain for payload data.
Based on whether the driver is processing the first, intermediate, or last
descriptor it can calculate the buffer usage and build the SKB properly.

Tested and verified on both old and new hardware.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>


Applied, thanks Tom.


Thanks David.  This is another patch for 4.10 stable. Can you please
queue it up?

Thanks,
Tom





Re: [PATCH net] amd-xgbe: Fix jumbo MTU processing on newer hardware

2017-03-15 Thread Tom Lendacky

On 3/15/2017 5:41 PM, David Miller wrote:

From: Tom Lendacky <thomas.lenda...@amd.com>
Date: Wed, 15 Mar 2017 17:40:51 -0500


On 3/15/2017 5:37 PM, David Miller wrote:

From: Tom Lendacky <thomas.lenda...@amd.com>
Date: Wed, 15 Mar 2017 15:11:23 -0500


Newer hardware does not provide a cumulative payload length when
multiple
descriptors are needed to handle the data. Once the MTU increases
beyond
the size that can be handled by a single descriptor, the SKB does not
get
built properly by the driver.

The driver will now calculate the size of the data buffers used by the
hardware.  The first buffer of the first descriptor is for packet
headers
or packet headers and data when the headers can't be split. Subsequent
descriptors in a multi-descriptor chain will not use the first
buffer. The
second buffer is used by all the descriptors in the chain for payload
data.
Based on whether the driver is processing the first, intermediate, or
last
descriptor it can calculate the buffer usage and build the SKB
properly.

Tested and verified on both old and new hardware.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>


Applied, thanks Tom.


Thanks David.  This is another patch for 4.10 stable. Can you please
queue it up?


Can you properly state this in your patch postings, instead of always
mentioning it later?



Sorry, yes, I can do that.  I didn't realize you preferred it that way.
Do you want the "Cc" tag to stable included in the patch or just
mention the stable targets in the patch description?  I know you
coordinate the stable submissions and I don't want to mess anything up.

Thanks,
Tom



Thank you.



[PATCH net] amd-xgbe: Fix jumbo MTU processing on newer hardware

2017-03-15 Thread Tom Lendacky
Newer hardware does not provide a cumulative payload length when multiple
descriptors are needed to handle the data. Once the MTU increases beyond
the size that can be handled by a single descriptor, the SKB does not get
built properly by the driver.

The driver will now calculate the size of the data buffers used by the
hardware.  The first buffer of the first descriptor is for packet headers
or packet headers and data when the headers can't be split. Subsequent
descriptors in a multi-descriptor chain will not use the first buffer. The
second buffer is used by all the descriptors in the chain for payload data.
Based on whether the driver is processing the first, intermediate, or last
descriptor it can calculate the buffer usage and build the SKB properly.

Tested and verified on both old and new hardware.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-common.h |6 +-
 drivers/net/ethernet/amd/xgbe/xgbe-dev.c|   20 +++--
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c|  102 +--
 3 files changed, 78 insertions(+), 50 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h 
b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
index 8a280e7..86f1626 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
@@ -1148,8 +1148,8 @@
 #define RX_PACKET_ATTRIBUTES_CSUM_DONE_WIDTH   1
 #define RX_PACKET_ATTRIBUTES_VLAN_CTAG_INDEX   1
 #define RX_PACKET_ATTRIBUTES_VLAN_CTAG_WIDTH   1
-#define RX_PACKET_ATTRIBUTES_INCOMPLETE_INDEX  2
-#define RX_PACKET_ATTRIBUTES_INCOMPLETE_WIDTH  1
+#define RX_PACKET_ATTRIBUTES_LAST_INDEX2
+#define RX_PACKET_ATTRIBUTES_LAST_WIDTH1
 #define RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_INDEX3
 #define RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_WIDTH1
 #define RX_PACKET_ATTRIBUTES_CONTEXT_INDEX 4
@@ -1158,6 +1158,8 @@
 #define RX_PACKET_ATTRIBUTES_RX_TSTAMP_WIDTH   1
 #define RX_PACKET_ATTRIBUTES_RSS_HASH_INDEX6
 #define RX_PACKET_ATTRIBUTES_RSS_HASH_WIDTH1
+#define RX_PACKET_ATTRIBUTES_FIRST_INDEX   7
+#define RX_PACKET_ATTRIBUTES_FIRST_WIDTH   1
 
 #define RX_NORMAL_DESC0_OVT_INDEX  0
 #define RX_NORMAL_DESC0_OVT_WIDTH  16
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index 937f37a..24a687c 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -1896,10 +1896,15 @@ static int xgbe_dev_read(struct xgbe_channel *channel)
 
/* Get the header length */
if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, FD)) {
+   XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
+  FIRST, 1);
rdata->rx.hdr_len = XGMAC_GET_BITS_LE(rdesc->desc2,
  RX_NORMAL_DESC2, HL);
if (rdata->rx.hdr_len)
pdata->ext_stats.rx_split_header_packets++;
+   } else {
+   XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
+  FIRST, 0);
}
 
/* Get the RSS hash */
@@ -1922,19 +1927,16 @@ static int xgbe_dev_read(struct xgbe_channel *channel)
}
}
 
-   /* Get the packet length */
-   rdata->rx.len = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, PL);
-
-   if (!XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, LD)) {
-   /* Not all the data has been transferred for this packet */
-   XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
-  INCOMPLETE, 1);
+   /* Not all the data has been transferred for this packet */
+   if (!XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, LD))
return 0;
-   }
 
/* This is the last of the data for this packet */
XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
-  INCOMPLETE, 0);
+  LAST, 1);
+
+   /* Get the packet length */
+   rdata->rx.len = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, PL);
 
/* Set checksum done indicator as appropriate */
if (netdev->features & NETIF_F_RXCSUM)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index ffea985..a713abd 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -1971,13 +1971,12 @@ static struct sk_buff *xgbe_create_skb(struct 
xgbe_prv_data *pdata,
 {
struct sk_buff *skb;
u8 *packet;
-   unsigned int copy_len;
 
skb = napi_alloc_skb(napi, rdata->rx.hdr.dma_len);
if (!skb)
return NULL;
 
-   /* Start with the header buffer which may contain just the header
+   /* Pull in the header buffer wh

Re: amd-xgbe: unbalanced irq enable in v4.11-rc1

2017-03-10 Thread Tom Lendacky

On 3/10/2017 11:19 AM, Mark Rutland wrote:

Hi,

I'm seeing the below splat when transferring data over the network, using
v4.11-rc1 on an AMD Seattle platform. I don't see the splat with v4.10.

Looking at just the driver, I couldn't see any suspicious changes. Reverting
commit 402168b4c2dc0734 ("amd-xgbe: Stop the PHY before releasing interrupts")
doesn't change matters.

Any ideas?


Yes, patch submitted.  Please see:

http://marc.info/?l=linux-netdev=148910333810442=2

Thanks,
Tom



Thanks,
Mark.

[  106.114135] Unbalanced enable for IRQ 34
[  106.118157] [ cut here ]
[  106.122793] WARNING: CPU: 0 PID: 0 at kernel/irq/manage.c:529 
__enable_irq+0x168/0x1d8
[  106.130708] Modules linked in:
[  106.133766]
[  106.135262] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 
4.11.0-rc1-1-g2411f70 #5
[  106.142830] Hardware name: AMD Seattle (Rev.B0) Development Board 
(Overdrive) (DT)
[  106.150398] task: 2a9e2000 task.stack: 2a9c
[  106.156320] PC is at __enable_irq+0x168/0x1d8
[  106.160679] LR is at __enable_irq+0x168/0x1d8
[  106.165036] pc : [] lr : [] pstate: 
01c5
[  106.172428] sp : 8003fff17c50
[  106.175742] x29: 8003fff17c50 x28: 800359255160
[  106.181063] x27: 10006b24aa2d x26: 800359255170
[  106.186385] x25: 2a9ca000 x24: 800359255168
[  106.191706] x23: 80036902ca80 x22: 80036bbe8f78
[  106.197027] x21: 10006d77d1ef x20: 
[  106.202348] x19: 80036bbe8f00 x18: 2a9e27b8
[  106.207668] x17: 7e2b5d90 x16: 
[  106.212989] x15: 1fffe4000153c4f7 x14: 6003f559
[  106.218310] x13: 2ac45000 x12: 2b803000
[  106.223631] x11: 1fffe40001ba7a8d x10: 
[  106.228951] x9 : 10007ffe2ee0 x8 : 2a9e27e8
[  106.234272] x7 : 2d2d3000 x6 : 
[  106.239592] x5 : 41b58ab3 x4 : 1fffe40001ba3a10
[  106.244913] x3 : 1fffe40001ba3a10 x2 : dfff2000
[  106.250234] x1 : 10007ffe2f58 x0 : 001c
[  106.23]
[  106.257044] ---[ end trace 86935ef2e5e5c498 ]---
[  106.261658] Call trace:
[  106.264106] Exception stack(0x8003fff17a00 to 0x8003fff17b30)
[  106.270550] 7a00: 80036bbe8f00 0001 8003fff17c50 
282a1340
[  106.278383] 7a20: 01c5 003d 2a9ca000 
800359255170
[  106.286216] 7a40: 10006b24aa2d 2a9e2000 8003fff17b60 
73870f20
[  106.294048] 7a60: 41b58ab3 2a7164f0 28081ac8 
2a05d4a0
[  106.301881] 7a80: 80036902ca80 800359255168 2a9ca000 
800359255170
[  106.309713] 7aa0: 8003fff17c50 8003fff17c50 8003fff17c10 
ffc8
[  106.317546] 7ac0: 41b58ab3 2a72a340 28299380 
2a9e2000
[  106.325379] 7ae0: 8003fff17b20 28bf8f08 80036bbe8f00 
80036d8002c0
[  106.333211] 7b00: 80036d8003f8 10007ffe2f70  

[  106.341040] 7b20: 001c 10007ffe2f58
[  106.345921] [] __enable_irq+0x168/0x1d8
[  106.351323] [] enable_irq+0xa8/0x118
[  106.356467] [] xgbe_one_poll+0x190/0x280
[  106.361956] [] net_rx_action+0x6ac/0xd88
[  106.367444] [] __do_softirq+0x324/0xb70
[  106.372845] [] irq_exit+0x1cc/0x338
[  106.377900] [] __handle_domain_irq+0xdc/0x230
[  106.383821] [] gic_handle_irq+0x6c/0xe0
[  106.389220] Exception stack(0x2a9c3d40 to 0x2a9c3e70)
[  106.395663] 3d40: 2a9e27bc 0007  
1fffe4000153c4f7
[  106.403495] 3d60: 0004   
2d2d3000
[  106.411327] 3d80: 2a9e27c0 040001538762  
0003
[  106.419160] 3da0: 2b803000 2ac45000 10007ffe4281 
1fffe4000153c4f7
[  106.426992] 3dc0:  7e2b5d90 2a9e27b8 
2a9e2000
[  106.434824] 3de0: 2a9e2000  2a9cfeb0 
0003
[  106.442656] 3e00: 00ff 2a9cfe18 2a901058 

[  106.450488] 3e20: 008004810018 2a9c3e70 2808a1d8 
2a9c3e70
[  106.458321] 3e40: 2808a1dc 6145  
2a901058
[  106.466150] 3e60:  2808a1d8
[  106.471029] [] el1_irq+0xb8/0x130
[  106.475909] [] arch_cpu_idle+0x1c/0x28
[  106.481225] [] default_idle_call+0x34/0x78
[  106.486888] [] do_idle+0x21c/0x3c0
[  106.491856] [] cpu_startup_entry+0x24/0x28
[  106.497517] [] rest_init+0x1ec/0x200
[  106.502659] [] start_kernel+0x5d8/0x604
[  106.508061] [] __primary_switched+0x6c/0x74



Re: [PATCH net] amd-xgbe: Enable IRQs only if napi_complete_done() is true

2017-03-10 Thread Tom Lendacky

On 3/9/2017 8:31 PM, David Miller wrote:

From: Tom Lendacky <thomas.lenda...@amd.com>
Date: Thu, 9 Mar 2017 17:48:23 -0600


Depending on the hardware, the amd-xgbe driver may use disable_irq_nosync()
and enable_irq() when an interrupt is received to process Rx packets. If
the napi_complete_done() return value isn't checked an unbalanced enable
for the IRQ could result, generating a warning stack trace.

Update the driver to only enable interrupts if napi_complete_done() returns
true.

Reported-by: Jeremy Linton <jeremy.lin...@arm.com>
Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>


Applied, thanks.


Thanks David!  The change to napi_complete_done() from void to bool
occurred in 4.10, can you queue this fix up against 4.10 stable?

Thanks,
Tom





[PATCH net] amd-xgbe: Enable IRQs only if napi_complete_done() is true

2017-03-09 Thread Tom Lendacky
Depending on the hardware, the amd-xgbe driver may use disable_irq_nosync()
and enable_irq() when an interrupt is received to process Rx packets. If
the napi_complete_done() return value isn't checked an unbalanced enable
for the IRQ could result, generating a warning stack trace.

Update the driver to only enable interrupts if napi_complete_done() returns
true.

Reported-by: Jeremy Linton <jeremy.lin...@arm.com>
Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c |   10 ++
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index 248f60d..ffea985 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -2272,10 +2272,7 @@ static int xgbe_one_poll(struct napi_struct *napi, int 
budget)
processed = xgbe_rx_poll(channel, budget);
 
/* If we processed everything, we are done */
-   if (processed < budget) {
-   /* Turn off polling */
-   napi_complete_done(napi, processed);
-
+   if ((processed < budget) && napi_complete_done(napi, processed)) {
/* Enable Tx and Rx interrupts */
if (pdata->channel_irq_mode)
xgbe_enable_rx_tx_int(pdata, channel);
@@ -2317,10 +2314,7 @@ static int xgbe_all_poll(struct napi_struct *napi, int 
budget)
} while ((processed < budget) && (processed != last_processed));
 
/* If we processed everything, we are done */
-   if (processed < budget) {
-   /* Turn off polling */
-   napi_complete_done(napi, processed);
-
+   if ((processed < budget) && napi_complete_done(napi, processed)) {
/* Enable Tx and Rx interrupts */
xgbe_enable_rx_tx_ints(pdata);
}



Re: xgbe unbalanced enable for IRQ XX in 4.11-rc1

2017-03-09 Thread Tom Lendacky

On 3/9/2017 5:06 PM, Eric Dumazet wrote:

On Thu, 2017-03-09 at 16:35 -0600, Tom Lendacky wrote:

On 3/9/2017 4:17 PM, Jeremy Linton wrote:

Hi,

On 03/09/2017 03:39 PM, Tom Lendacky wrote:

On 3/9/2017 3:26 PM, Jeremy Linton wrote:

Hi,


Hi Jeremy,

I'll have a look at it.  Can you send me your kernel config just in
case?


Sure, i will send it to you off list to avoid spamming everyone with a
43k gziped file.



I'm able to recreate the problem with my current config.  If I revert
patch 39e6c8208d7b ("net: solve a NAPI race"), then the problem goes
away.

Eric, any thoughts on this?  I'm guessing the driver should check that
napi_complete_done returns true before enabling IRQs...

Thanks,
Tom


Yes, it seems this driver has a conditional disable_irq_nosync()
following the napi_schedule_prep()

So it probably needs the same for the enable_irq() side.


I verified that the issue goes away when the return value for
napi_complete_done() is checked.  I'll prepare a patch for
both calls in the driver.



This would be broken with busy polling anyway, before my patch.


Yes, I see that busy polling went into 4.10 so I'll submit it back
to 4.10 stable as well.

Thanks,
Tom



diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index 
248f60d171a5a0ce76744a95e2d59039939e6538..c47a3a93f034ab608286d1ae343e9b7778063df8
 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -2272,9 +2272,8 @@ static int xgbe_one_poll(struct napi_struct *napi, int 
budget)
processed = xgbe_rx_poll(channel, budget);

/* If we processed everything, we are done */
-   if (processed < budget) {
-   /* Turn off polling */
-   napi_complete_done(napi, processed);
+   if (processed < budget &&
+   napi_complete_done(napi, processed)) {

/* Enable Tx and Rx interrupts */
if (pdata->channel_irq_mode)




Re: xgbe unbalanced enable for IRQ XX in 4.11-rc1

2017-03-09 Thread Tom Lendacky

On 3/9/2017 4:17 PM, Jeremy Linton wrote:

Hi,

On 03/09/2017 03:39 PM, Tom Lendacky wrote:

On 3/9/2017 3:26 PM, Jeremy Linton wrote:

Hi,


Hi Jeremy,

I'll have a look at it.  Can you send me your kernel config just in
case?


Sure, i will send it to you off list to avoid spamming everyone with a
43k gziped file.



I'm able to recreate the problem with my current config.  If I revert
patch 39e6c8208d7b ("net: solve a NAPI race"), then the problem goes
away.

Eric, any thoughts on this?  I'm guessing the driver should check that
napi_complete_done returns true before enabling IRQs...

Thanks,
Tom


Thanks,



Thanks,
Tom



I have a softiron 3k and under network load (nfs copies, vnc with gnome,
etc) it is now throwing these messages as fast as the console will
accept them. This is booted DT mode.


[  430.111324] Unbalanced enable for IRQ 33
[  430.115239] [ cut here ]
[  430.119849] WARNING: CPU: 0 PID: 6 at kernel/irq/manage.c:529
__enable_irq+0x7c/0x88
[  430.127583] Modules linked in: fuse xt_CHECKSUM ipt_MASQUERADE
nf_nat_masquerade_ipv4 tun ip6t_rpfilter ip6t_REJECT nf_reject_ipv6
xt_conntrack ip_set nfnetlink ebtable_nat ebtable_broute bridge stp llc
ip6table_nat nf_conntrack_ipv6 nf_defrag_ipv6 nf_nat_ipv6
ip6table_mangle ip6table_raw ip6table_security iptable_nat
nf_conntrack_ipv4 nf_defrag_ipv4 nf_nat_ipv4 nf_nat nf_conntrack
iptable_mangle iptable_raw iptable_security ebtable_filter ebtables
ip6table_filter ip6_tables vfat fat crc32_ce crct10dif_ce amd_xgbe
ghash_ce ptp pps_core spi_pl022 ipmi_si i2c_designware_platform
ipmi_devintf i2c_designware_core ccp ipmi_msghandler nfsd auth_rpcgss
nfs_acl lockd grace sunrpc xfs libcrc32c
[  430.188350]
[  430.189833] CPU: 0 PID: 6 Comm: ksoftirqd/0 Tainted: GW I
4.11.0-0.rc1.git0.1.fc27.aarch64 #1
[  430.199391] Hardware name: AMD Overdrive/Supercharger/Default string,
BIOS ROD1002C 04/08/2016
[  430.207994] task: 8003e4057900 task.stack: 8003f459
[  430.213904] PC is at __enable_irq+0x7c/0x88
[  430.218078] LR is at __enable_irq+0x7c/0x88
[  430.52] pc : [] lr : []
pstate: 01c5
[  430.229639] sp : 8003f4593c50
[  430.232944] x29: 8003f4593c50 x28: 8003dfeddce0
[  430.238248] x27: 0002 x26: 0001
[  430.243551] x25: 0040 x24: 8003f60a
[  430.248855] x23: 8003d5d0a900 x22: 0040
[  430.254158] x21: 0001 x20: 0021
[  430.259462] x19: 8003dc507200 x18: 
[  430.264765] x17:  x16: 
[  430.270069] x15: 0010 x14: 89005e7f
[  430.275372] x13: 09005e8d x12: 08e8d000
[  430.280676] x11: 08e65458 x10: 085adce8
[  430.285979] x9 : ffd0 x8 : 0005
[  430.291283] x7 : 636e616c61626e55 x6 : 8003fee74d98
[  430.296586] x5 : 8003fee74d98 x4 : 
[  430.301890] x3 : 8003fee88730 x2 : 8003fee74d98
[  430.307193] x1 : 8003f60a x0 : 001c
[  430.312496]
[  430.313978] ---[ end trace 5664787410723389 ]---
[  430.318586] Call trace:
[  430.321023] Exception stack(0x8003f4593a80 to 0x8003f4593bb0)
[  430.327454] 3a80: 8003dc507200 0001 8003f4593c50
08137b14
[  430.335277] 3aa0: 8003f4593c50 8003f4593c50 8003f4593c10
ffc8
[  430.343099] 3ac0: 8003f4593b00 08134838 08b7a570
8003f4593bd0
[  430.350921] 3ae0: 8003f4593c50 8003f4593c50 8003f4593c10
ffc8
[  430.358743] 3b00: 8003f4593bb0 081f8130 0001
0021
[  430.366566] 3b20: 001c 8003f60a 8003fee74d98
8003fee88730
[  430.374388] 3b40:  8003fee74d98 8003fee74d98
636e616c61626e55
[  430.382210] 3b60: 0005 ffd0 085adce8
08e65458
[  430.390033] 3b80: 08e8d000 09005e8d 89005e7f
0010
[  430.397854] 3ba0:  
[  430.402723] [] __enable_irq+0x7c/0x88
[  430.407939] [] enable_irq+0x40/0x78
[  430.412999] [] xgbe_one_poll+0xc0/0xe8 [amd_xgbe]
[  430.419257] [] net_rx_action+0x150/0x3c8
[  430.424734] [] __do_softirq+0x138/0x358
[  430.430123] [] run_ksoftirqd+0x4c/0x78
[  430.435426] [] smpboot_thread_fn+0x184/0x1b8
[  430.441249] [] kthread+0x12c/0x130
[  430.446205] [] ret_from_fork+0x10/0x20
[  430.451600] Unbalanced enable for IRQ 33
[  430.455516] [ cut here ]




Re: xgbe unbalanced enable for IRQ XX in 4.11-rc1

2017-03-09 Thread Tom Lendacky

On 3/9/2017 3:26 PM, Jeremy Linton wrote:

Hi,


Hi Jeremy,

I'll have a look at it.  Can you send me your kernel config just in
case?

Thanks,
Tom



I have a softiron 3k and under network load (nfs copies, vnc with gnome,
etc) it is now throwing these messages as fast as the console will
accept them. This is booted DT mode.


[  430.111324] Unbalanced enable for IRQ 33
[  430.115239] [ cut here ]
[  430.119849] WARNING: CPU: 0 PID: 6 at kernel/irq/manage.c:529
__enable_irq+0x7c/0x88
[  430.127583] Modules linked in: fuse xt_CHECKSUM ipt_MASQUERADE
nf_nat_masquerade_ipv4 tun ip6t_rpfilter ip6t_REJECT nf_reject_ipv6
xt_conntrack ip_set nfnetlink ebtable_nat ebtable_broute bridge stp llc
ip6table_nat nf_conntrack_ipv6 nf_defrag_ipv6 nf_nat_ipv6
ip6table_mangle ip6table_raw ip6table_security iptable_nat
nf_conntrack_ipv4 nf_defrag_ipv4 nf_nat_ipv4 nf_nat nf_conntrack
iptable_mangle iptable_raw iptable_security ebtable_filter ebtables
ip6table_filter ip6_tables vfat fat crc32_ce crct10dif_ce amd_xgbe
ghash_ce ptp pps_core spi_pl022 ipmi_si i2c_designware_platform
ipmi_devintf i2c_designware_core ccp ipmi_msghandler nfsd auth_rpcgss
nfs_acl lockd grace sunrpc xfs libcrc32c
[  430.188350]
[  430.189833] CPU: 0 PID: 6 Comm: ksoftirqd/0 Tainted: GW I
4.11.0-0.rc1.git0.1.fc27.aarch64 #1
[  430.199391] Hardware name: AMD Overdrive/Supercharger/Default string,
BIOS ROD1002C 04/08/2016
[  430.207994] task: 8003e4057900 task.stack: 8003f459
[  430.213904] PC is at __enable_irq+0x7c/0x88
[  430.218078] LR is at __enable_irq+0x7c/0x88
[  430.52] pc : [] lr : []
pstate: 01c5
[  430.229639] sp : 8003f4593c50
[  430.232944] x29: 8003f4593c50 x28: 8003dfeddce0
[  430.238248] x27: 0002 x26: 0001
[  430.243551] x25: 0040 x24: 8003f60a
[  430.248855] x23: 8003d5d0a900 x22: 0040
[  430.254158] x21: 0001 x20: 0021
[  430.259462] x19: 8003dc507200 x18: 
[  430.264765] x17:  x16: 
[  430.270069] x15: 0010 x14: 89005e7f
[  430.275372] x13: 09005e8d x12: 08e8d000
[  430.280676] x11: 08e65458 x10: 085adce8
[  430.285979] x9 : ffd0 x8 : 0005
[  430.291283] x7 : 636e616c61626e55 x6 : 8003fee74d98
[  430.296586] x5 : 8003fee74d98 x4 : 
[  430.301890] x3 : 8003fee88730 x2 : 8003fee74d98
[  430.307193] x1 : 8003f60a x0 : 001c
[  430.312496]
[  430.313978] ---[ end trace 5664787410723389 ]---
[  430.318586] Call trace:
[  430.321023] Exception stack(0x8003f4593a80 to 0x8003f4593bb0)
[  430.327454] 3a80: 8003dc507200 0001 8003f4593c50
08137b14
[  430.335277] 3aa0: 8003f4593c50 8003f4593c50 8003f4593c10
ffc8
[  430.343099] 3ac0: 8003f4593b00 08134838 08b7a570
8003f4593bd0
[  430.350921] 3ae0: 8003f4593c50 8003f4593c50 8003f4593c10
ffc8
[  430.358743] 3b00: 8003f4593bb0 081f8130 0001
0021
[  430.366566] 3b20: 001c 8003f60a 8003fee74d98
8003fee88730
[  430.374388] 3b40:  8003fee74d98 8003fee74d98
636e616c61626e55
[  430.382210] 3b60: 0005 ffd0 085adce8
08e65458
[  430.390033] 3b80: 08e8d000 09005e8d 89005e7f
0010
[  430.397854] 3ba0:  
[  430.402723] [] __enable_irq+0x7c/0x88
[  430.407939] [] enable_irq+0x40/0x78
[  430.412999] [] xgbe_one_poll+0xc0/0xe8 [amd_xgbe]
[  430.419257] [] net_rx_action+0x150/0x3c8
[  430.424734] [] __do_softirq+0x138/0x358
[  430.430123] [] run_ksoftirqd+0x4c/0x78
[  430.435426] [] smpboot_thread_fn+0x184/0x1b8
[  430.441249] [] kthread+0x12c/0x130
[  430.446205] [] ret_from_fork+0x10/0x20
[  430.451600] Unbalanced enable for IRQ 33
[  430.455516] [ cut here ]


Re: [PATCH net v1 0/3] amd-xgbe: AMD XGBE driver fixes 2017-02-28

2017-03-02 Thread Tom Lendacky

On 3/2/2017 3:02 PM, David Miller wrote:

From: Tom Lendacky <thomas.lenda...@amd.com>
Date: Tue, 28 Feb 2017 15:02:42 -0600


This patch series addresses some issues in the AMD XGBE driver.

The following fixes are included in this driver update series:

- Stop the PHY before disabling and releasing device interrupts so that
  MDIO requests issued by the device can be properly handled
- Set the MDIO communication mode on device startup, not just device
  probe
- Do not overwrite SFP settings when mod_absent is detected

This patch series is based on net.


Series applied, thanks.


Thanks David!

Could you queue these fixes up against 4.10 stable. Nothing early than
that is needed.

Thanks,
Tom





[PATCH net v1 3/3] amd-xgbe: Don't overwrite SFP PHY mod_absent settings

2017-02-28 Thread Tom Lendacky
If an SFP module is not present, xgbe_phy_sfp_phy_settings() should
return after applying the default settings. Currently there is no return
statement and the default settings are overwritten.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c |2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
index 04804cb..e707c49 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
@@ -716,6 +716,8 @@ static void xgbe_phy_sfp_phy_settings(struct xgbe_prv_data 
*pdata)
pdata->phy.duplex = DUPLEX_UNKNOWN;
pdata->phy.autoneg = AUTONEG_ENABLE;
pdata->phy.advertising = pdata->phy.supported;
+
+   return;
}
 
pdata->phy.advertising &= ~ADVERTISED_Autoneg;



[PATCH net v1 0/3] amd-xgbe: AMD XGBE driver fixes 2017-02-28

2017-02-28 Thread Tom Lendacky
This patch series addresses some issues in the AMD XGBE driver.

The following fixes are included in this driver update series:

- Stop the PHY before disabling and releasing device interrupts so that
  MDIO requests issued by the device can be properly handled
- Set the MDIO communication mode on device startup, not just device
  probe
- Do not overwrite SFP settings when mod_absent is detected

This patch series is based on net.

---

Tom Lendacky (3):
  amd-xgbe: Stop the PHY before releasing interrupts
  amd-xgbe: Be sure to set MDIO modes on device (re)start
  amd-xgbe: Don't overwrite SFP PHY mod_absent settings


 drivers/net/ethernet/amd/xgbe/xgbe-dev.c|2 +-
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c|4 ++--
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c |   24 
 3 files changed, 27 insertions(+), 3 deletions(-)

-- 
Tom Lendacky


[PATCH net v1 1/3] amd-xgbe: Stop the PHY before releasing interrupts

2017-02-28 Thread Tom Lendacky
Some configurations require the use of the hardware's MDIO support to
communicate with external PHYs. The MDIO commands indicate completion
through the device interrupt. When bringing down the device the interrupts
were released before stopping the external PHY, resulting in MDIO command
timeouts. Move the stopping of the PHY to before the releasing of the
interrupts.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c |4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index 3aa457c..248f60d 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -1131,12 +1131,12 @@ static void xgbe_stop(struct xgbe_prv_data *pdata)
hw_if->disable_tx(pdata);
hw_if->disable_rx(pdata);
 
+   phy_if->phy_stop(pdata);
+
xgbe_free_irqs(pdata);
 
xgbe_napi_disable(pdata, 1);
 
-   phy_if->phy_stop(pdata);
-
hw_if->exit(pdata);
 
channel = pdata->channel;



[PATCH net v1 2/3] amd-xgbe: Be sure to set MDIO modes on device (re)start

2017-02-28 Thread Tom Lendacky
The MDIO register mode is set when the device is probed. But when the
device is brought down and then back up, the MDIO register mode has been
reset.  Be sure to reset the mode during device startup and only change
the mode of the address specified.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-dev.c|2 +-
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c |   22 ++
 2 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index a7d16db..937f37a 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -1323,7 +1323,7 @@ static int xgbe_read_ext_mii_regs(struct xgbe_prv_data 
*pdata, int addr,
 static int xgbe_set_ext_mii_mode(struct xgbe_prv_data *pdata, unsigned int 
port,
 enum xgbe_mdio_mode mode)
 {
-   unsigned int reg_val = 0;
+   unsigned int reg_val = XGMAC_IOREAD(pdata, MAC_MDIOCL22R);
 
switch (mode) {
case XGBE_MDIO_MODE_CL22:
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
index 9d8c9530..04804cb 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
@@ -875,6 +875,16 @@ static int xgbe_phy_find_phy_device(struct xgbe_prv_data 
*pdata)
!phy_data->sfp_phy_avail)
return 0;
 
+   /* Set the proper MDIO mode for the PHY */
+   ret = pdata->hw_if.set_ext_mii_mode(pdata, phy_data->mdio_addr,
+   phy_data->phydev_mode);
+   if (ret) {
+   netdev_err(pdata->netdev,
+  "mdio port/clause not compatible (%u/%u)\n",
+  phy_data->mdio_addr, phy_data->phydev_mode);
+   return ret;
+   }
+
/* Create and connect to the PHY device */
phydev = get_phy_device(phy_data->mii, phy_data->mdio_addr,
(phy_data->phydev_mode == XGBE_MDIO_MODE_CL45));
@@ -2722,6 +2732,18 @@ static int xgbe_phy_start(struct xgbe_prv_data *pdata)
if (ret)
return ret;
 
+   /* Set the proper MDIO mode for the re-driver */
+   if (phy_data->redrv && !phy_data->redrv_if) {
+   ret = pdata->hw_if.set_ext_mii_mode(pdata, phy_data->redrv_addr,
+   XGBE_MDIO_MODE_CL22);
+   if (ret) {
+   netdev_err(pdata->netdev,
+  "redriver mdio port not compatible (%u)\n",
+  phy_data->redrv_addr);
+   return ret;
+   }
+   }
+
/* Start in highest supported mode */
xgbe_phy_set_mode(pdata, phy_data->start_mode);
 



[PATCH net v1 2/2] amd-xgbe: Check xgbe_init() return code

2017-01-20 Thread Tom Lendacky
The xgbe_init() routine returns a return code indicating success or
failure, but the return code is not checked. Add code to xgbe_init()
to issue a message when failures are seen and add code to check the
xgbe_init() return code.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-dev.c |4 +++-
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c |4 +++-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index c8e8a4a..a7d16db 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -3407,8 +3407,10 @@ static int xgbe_init(struct xgbe_prv_data *pdata)
 
/* Flush Tx queues */
ret = xgbe_flush_tx_queues(pdata);
-   if (ret)
+   if (ret) {
+   netdev_err(pdata->netdev, "error flushing TX queues\n");
return ret;
+   }
 
/*
 * Initialize DMA related features
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index 9943629..1c87cc2 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -1070,7 +1070,9 @@ static int xgbe_start(struct xgbe_prv_data *pdata)
 
DBGPR("-->xgbe_start\n");
 
-   hw_if->init(pdata);
+   ret = hw_if->init(pdata);
+   if (ret)
+   return ret;
 
xgbe_napi_enable(pdata, 1);
 



[PATCH net v1 0/2] amd-xgbe: AMD XGBE driver fixes 2017-01-20

2017-01-20 Thread Tom Lendacky
This patch series addresses some issues in the AMD XGBE driver.

The following fixes are included in this driver update series:

- Add a fix for a version of the hardware that uses different register
  offset values for a device with the same PCI device ID
- Add support to check the return code from the xgbe_init() function

This patch series is based on net.

---

Tom Lendacky (2):
  amd-xgbe: Add a hardware quirk for register definitions
  amd-xgbe: Check xgbe_init() return code


 drivers/net/ethernet/amd/xgbe/xgbe-common.h |2 ++
 drivers/net/ethernet/amd/xgbe/xgbe-dev.c|8 +---
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c|4 +++-
 drivers/net/ethernet/amd/xgbe/xgbe-pci.c|   15 ++-
 drivers/net/ethernet/amd/xgbe/xgbe.h|2 ++
 5 files changed, 26 insertions(+), 5 deletions(-)

-- 
Tom Lendacky


[PATCH net v1 1/2] amd-xgbe: Add a hardware quirk for register definitions

2017-01-20 Thread Tom Lendacky
A newer version of the hardware is using the same PCI ids for the network
device but has altered register definitions for determining the window
settings for the indirect PCS access.  Add support to check for this
hardware and if found use the new register values.

Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-common.h |2 ++
 drivers/net/ethernet/amd/xgbe/xgbe-dev.c|4 ++--
 drivers/net/ethernet/amd/xgbe/xgbe-pci.c|   15 ++-
 drivers/net/ethernet/amd/xgbe/xgbe.h|2 ++
 4 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h 
b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
index 5b7ba25..8a280e7 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
@@ -891,6 +891,8 @@
 #define PCS_V1_WINDOW_SELECT   0x03fc
 #define PCS_V2_WINDOW_DEF  0x9060
 #define PCS_V2_WINDOW_SELECT   0x9064
+#define PCS_V2_RV_WINDOW_DEF   0x1060
+#define PCS_V2_RV_WINDOW_SELECT0x1064
 
 /* PCS register entry bit positions and sizes */
 #define PCS_V2_WINDOW_DEF_OFFSET_INDEX 6
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index aaf0350..c8e8a4a 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -1151,7 +1151,7 @@ static int xgbe_read_mmd_regs_v2(struct xgbe_prv_data 
*pdata, int prtad,
offset = pdata->xpcs_window + (mmd_address & pdata->xpcs_window_mask);
 
spin_lock_irqsave(>xpcs_lock, flags);
-   XPCS32_IOWRITE(pdata, PCS_V2_WINDOW_SELECT, index);
+   XPCS32_IOWRITE(pdata, pdata->xpcs_window_sel_reg, index);
mmd_data = XPCS16_IOREAD(pdata, offset);
spin_unlock_irqrestore(>xpcs_lock, flags);
 
@@ -1183,7 +1183,7 @@ static void xgbe_write_mmd_regs_v2(struct xgbe_prv_data 
*pdata, int prtad,
offset = pdata->xpcs_window + (mmd_address & pdata->xpcs_window_mask);
 
spin_lock_irqsave(>xpcs_lock, flags);
-   XPCS32_IOWRITE(pdata, PCS_V2_WINDOW_SELECT, index);
+   XPCS32_IOWRITE(pdata, pdata->xpcs_window_sel_reg, index);
XPCS16_IOWRITE(pdata, offset, mmd_data);
spin_unlock_irqrestore(>xpcs_lock, flags);
 }
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c
index e76b7f6..c2730f1 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c
@@ -265,6 +265,7 @@ static int xgbe_pci_probe(struct pci_dev *pdev, const 
struct pci_device_id *id)
struct xgbe_prv_data *pdata;
struct device *dev = >dev;
void __iomem * const *iomap_table;
+   struct pci_dev *rdev;
unsigned int ma_lo, ma_hi;
unsigned int reg;
int bar_mask;
@@ -326,8 +327,20 @@ static int xgbe_pci_probe(struct pci_dev *pdev, const 
struct pci_device_id *id)
if (netif_msg_probe(pdata))
dev_dbg(dev, "xpcs_regs  = %p\n", pdata->xpcs_regs);
 
+   /* Set the PCS indirect addressing definition registers */
+   rdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0, 0));
+   if (rdev &&
+   (rdev->vendor == PCI_VENDOR_ID_AMD) && (rdev->device == 0x15d0)) {
+   pdata->xpcs_window_def_reg = PCS_V2_RV_WINDOW_DEF;
+   pdata->xpcs_window_sel_reg = PCS_V2_RV_WINDOW_SELECT;
+   } else {
+   pdata->xpcs_window_def_reg = PCS_V2_WINDOW_DEF;
+   pdata->xpcs_window_sel_reg = PCS_V2_WINDOW_SELECT;
+   }
+   pci_dev_put(rdev);
+
/* Configure the PCS indirect addressing support */
-   reg = XPCS32_IOREAD(pdata, PCS_V2_WINDOW_DEF);
+   reg = XPCS32_IOREAD(pdata, pdata->xpcs_window_def_reg);
pdata->xpcs_window = XPCS_GET_BITS(reg, PCS_V2_WINDOW_DEF, OFFSET);
pdata->xpcs_window <<= 6;
pdata->xpcs_window_size = XPCS_GET_BITS(reg, PCS_V2_WINDOW_DEF, SIZE);
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h 
b/drivers/net/ethernet/amd/xgbe/xgbe.h
index f52a9bd..0010881 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe.h
@@ -955,6 +955,8 @@ struct xgbe_prv_data {
 
/* XPCS indirect addressing lock */
spinlock_t xpcs_lock;
+   unsigned int xpcs_window_def_reg;
+   unsigned int xpcs_window_sel_reg;
unsigned int xpcs_window;
unsigned int xpcs_window_size;
unsigned int xpcs_window_mask;



Re: kill off pci_enable_msi_{exact,range}

2017-01-13 Thread Tom Lendacky
On 1/13/2017 11:15 AM, Christoph Hellwig wrote:
> On Fri, Jan 13, 2017 at 11:13:21AM -0600, Bjorn Helgaas wrote:
>> I dropped the empty commit and replaced the xgbe patch with the one below.
>> Can you take a look at [1] and make sure it's what you expected?
> 
> This looks great, thanks!
> 

Christoph and Bjorn, thanks for taking care of this!

Tom


Re: [PATCH 2/3] xgbe: switch to pci_irq_alloc_vectors

2017-01-11 Thread Tom Lendacky
On 1/11/2017 3:03 AM, Christoph Hellwig wrote:
> On Tue, Jan 10, 2017 at 12:40:10PM -0600, Tom Lendacky wrote:
>> On 1/9/2017 2:37 PM, Christoph Hellwig wrote:
>>> The newly added xgbe drivers uses the deprecated pci_enable_msi_exact
>>> and pci_enable_msix_range interfaces.  Switch it to use
>>> pci_irq_alloc_vectors instead.
>>
>> I was just working on switching over to this API with some additional
>> changes / simplification.  I'm ok with using this patch so that you get
>> the API removal accomplished.  Going through the PCI tree just means
>> it will probably be easier for me to hold off on the additional changes
>> I wanted to make until later.
> 
> Hi Tom,

Hi Christoph,

> 
> if you have a better patch I'd be more than happy to use that one instead,
> this one was intended as a stupid search and replace.  The important
> part for me is to get the two conversions and the interface removal
> in together.

That sounds good, I'll send the patch to you in a separate email for use
in your series.

Thanks,
Tom

> 
> E.g. I've alreayd wondered why the driver requires the exact vector
> number for MSI and a variable one for MSI-X, and there certainly is
> all kinds of opportunity for cosmetic cleanup.
> 


  1   2   3   >