[PATCH 3/3] drivers: net: xgene: Remove return statement from void function

2017-09-05 Thread Iyappan Subramanian
commit 183db4 ("drivers: net: xgene: Correct probe sequence handling")
changed the return type of xgene_enet_check_phy_handle() to void.

This patch, removes the return statement from the last line.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index 655c0fc..3b889ef 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -1674,8 +1674,6 @@ static void xgene_enet_check_phy_handle(struct 
xgene_enet_pdata *pdata)
ret = xgene_enet_phy_connect(pdata->ndev);
if (!ret)
pdata->mdio_driver = true;
-
-   return;
 }
 
 static void xgene_enet_gpiod_get(struct xgene_enet_pdata *pdata)
-- 
2.7.4



[PATCH 1/3] drivers: net: xgene: Read tx/rx delay for ACPI

2017-09-05 Thread Iyappan Subramanian
This patch fixes reading tx/rx delay values for ACPI.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
Signed-off-by: Quan Nguyen <qngu...@apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index 6e253d9..655c0fc 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -1591,7 +1591,7 @@ static int xgene_get_tx_delay(struct xgene_enet_pdata 
*pdata)
struct device *dev = >pdev->dev;
int delay, ret;
 
-   ret = of_property_read_u32(dev->of_node, "tx-delay", );
+   ret = device_property_read_u32(dev, "tx-delay", );
if (ret) {
pdata->tx_delay = 4;
return 0;
@@ -1612,7 +1612,7 @@ static int xgene_get_rx_delay(struct xgene_enet_pdata 
*pdata)
struct device *dev = >pdev->dev;
int delay, ret;
 
-   ret = of_property_read_u32(dev->of_node, "rx-delay", );
+   ret = device_property_read_u32(dev, "rx-delay", );
if (ret) {
pdata->rx_delay = 2;
return 0;
-- 
2.7.4



[PATCH 0/3] drivers: net: xgene: Misc bug fixes

2017-09-05 Thread Iyappan Subramanian
This patch set fixes bugs related to handling the case for ACPI for,
reading and programming tx/rx delay values.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---

Iyappan Subramanian (2):
  drivers: net: xgene: Read tx/rx delay for ACPI
  drivers: net: xgene: Remove return statement from void function

Quan Nguyen (1):
  drivers: net: xgene: Configure tx/rx delay for ACPI

 drivers/net/ethernet/apm/xgene/xgene_enet_hw.c   | 7 ++-
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 6 ++
 2 files changed, 4 insertions(+), 9 deletions(-)

-- 
2.7.4



[PATCH 2/3] drivers: net: xgene: Configure tx/rx delay for ACPI

2017-09-05 Thread Iyappan Subramanian
From: Quan Nguyen <qngu...@apm.com>

This patch fixes configuring tx/rx delay values for ACPI.

Signed-off-by: Quan Nguyen <qngu...@apm.com>
Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.c | 7 ++-
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
index e45b587..3188f55 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
@@ -468,7 +468,6 @@ static void xgene_enet_configure_clock(struct 
xgene_enet_pdata *pdata)
 
 static void xgene_gmac_set_speed(struct xgene_enet_pdata *pdata)
 {
-   struct device *dev = >pdev->dev;
u32 icm0, icm2, mc2;
u32 intf_ctl, rgmii, value;
 
@@ -500,10 +499,8 @@ static void xgene_gmac_set_speed(struct xgene_enet_pdata 
*pdata)
intf_ctl |= ENET_GHD_MODE;
CFG_MACMODE_SET(, 2);
CFG_WAITASYNCRD_SET(, 0);
-   if (dev->of_node) {
-   CFG_TXCLK_MUXSEL0_SET(, pdata->tx_delay);
-   CFG_RXCLK_MUXSEL0_SET(, pdata->rx_delay);
-   }
+   CFG_TXCLK_MUXSEL0_SET(, pdata->tx_delay);
+   CFG_RXCLK_MUXSEL0_SET(, pdata->rx_delay);
rgmii |= CFG_SPEED_1250;
 
xgene_enet_rd_csr(pdata, DEBUG_REG_ADDR, );
-- 
2.7.4



[PATCH] drivers: net: xgene: Correct probe sequence handling

2017-08-29 Thread Iyappan Subramanian
From: Quan Nguyen <qngu...@apm.com>

The phy is connected at early stage of probe but not properly
disconnected if error occurs.  This patch fixes the issue.

Also changing the return type of xgene_enet_check_phy_handle(),
since this function always returns success.

Signed-off-by: Quan Nguyen <qngu...@apm.com>
Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 27 
 1 file changed, 13 insertions(+), 14 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index 1d307f2..6e253d9 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -1661,21 +1661,21 @@ static int xgene_enet_get_irqs(struct xgene_enet_pdata 
*pdata)
return 0;
 }
 
-static int xgene_enet_check_phy_handle(struct xgene_enet_pdata *pdata)
+static void xgene_enet_check_phy_handle(struct xgene_enet_pdata *pdata)
 {
int ret;
 
if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII)
-   return 0;
+   return;
 
if (!IS_ENABLED(CONFIG_MDIO_XGENE))
-   return 0;
+   return;
 
ret = xgene_enet_phy_connect(pdata->ndev);
if (!ret)
pdata->mdio_driver = true;
 
-   return 0;
+   return;
 }
 
 static void xgene_enet_gpiod_get(struct xgene_enet_pdata *pdata)
@@ -1779,10 +1779,6 @@ static int xgene_enet_get_resources(struct 
xgene_enet_pdata *pdata)
if (ret)
return ret;
 
-   ret = xgene_enet_check_phy_handle(pdata);
-   if (ret)
-   return ret;
-
xgene_enet_gpiod_get(pdata);
 
pdata->clk = devm_clk_get(>dev, NULL);
@@ -2097,9 +2093,11 @@ static int xgene_enet_probe(struct platform_device *pdev)
goto err;
}
 
+   xgene_enet_check_phy_handle(pdata);
+
ret = xgene_enet_init_hw(pdata);
if (ret)
-   goto err;
+   goto err2;
 
link_state = pdata->mac_ops->link_state;
if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) {
@@ -2117,29 +2115,30 @@ static int xgene_enet_probe(struct platform_device 
*pdev)
spin_lock_init(>stats_lock);
ret = xgene_extd_stats_init(pdata);
if (ret)
-   goto err2;
+   goto err1;
 
xgene_enet_napi_add(pdata);
ret = register_netdev(ndev);
if (ret) {
netdev_err(ndev, "Failed to register netdev\n");
-   goto err2;
+   goto err1;
}
 
return 0;
 
-err2:
+err1:
/*
 * If necessary, free_netdev() will call netif_napi_del() and undo
 * the effects of xgene_enet_napi_add()'s calls to netif_napi_add().
 */
 
+   xgene_enet_delete_desc_rings(pdata);
+
+err2:
if (pdata->mdio_driver)
xgene_enet_phy_disconnect(pdata);
else if (phy_interface_mode_is_rgmii(pdata->phy_mode))
xgene_enet_mdio_remove(pdata);
-err1:
-   xgene_enet_delete_desc_rings(pdata);
 err:
free_netdev(ndev);
return ret;
-- 
2.7.4



Re: [PATCH 2/2] drivers: net: xgene: Clean up all outstanding tx descriptors

2017-08-28 Thread Iyappan Subramanian
Hi Andrew,

On Fri, Aug 25, 2017 at 4:10 PM, Andrew Lunn <and...@lunn.ch> wrote:
> On Fri, Aug 25, 2017 at 03:23:30PM -0700, Iyappan Subramanian wrote:
>> When xgene_enet is rmmod'd and there are still outstanding tx descriptors
>> that have been setup but have not completed, it is possible on the next
>> modprobe of the driver to receive the oldest of such tx descriptors. This
>> results in a kernel NULL pointer dereference.
>>
>> This patch attempts to clean up (by tearing down) all outstanding tx
>> descriptors when the xgene_enet driver is being rmmod'd.
>>
>> Given that, on the next modprobe it should be safe to ignore any such tx
>> descriptors received that map to a NULL skb pointer.
>
> This does not sound correct. Before the module is allowed to be
> removed, everything needs to be finished. You need to wait for all the
> tx descriptors to be returned before unloading. How can you free the
> memory for the descriptor if it is still in use? How can you free the
> skbuf the descriptor points to, if it is still in use...

Thanks for pointing out the issue.  It is an error, we will fix the issue.

Since the two patches are unrelated, I'm going to post them separately.

Thanks,
Iyappan

>
>   Andrew


[PATCH 1/2] drivers: net: xgene: Correct probe sequence handling

2017-08-25 Thread Iyappan Subramanian
From: Quan Nguyen <qngu...@apm.com>

The phy is connected at early stage of probe but not properly
disconnected if error occurs.  This patch fixes the issue.

Also changing the return type of xgene_enet_check_phy_handle(),
since this function always returns success.

Signed-off-by: Quan Nguyen <qngu...@apm.com>
Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 27 
 1 file changed, 13 insertions(+), 14 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index 1d307f2..6e253d9 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -1661,21 +1661,21 @@ static int xgene_enet_get_irqs(struct xgene_enet_pdata 
*pdata)
return 0;
 }
 
-static int xgene_enet_check_phy_handle(struct xgene_enet_pdata *pdata)
+static void xgene_enet_check_phy_handle(struct xgene_enet_pdata *pdata)
 {
int ret;
 
if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII)
-   return 0;
+   return;
 
if (!IS_ENABLED(CONFIG_MDIO_XGENE))
-   return 0;
+   return;
 
ret = xgene_enet_phy_connect(pdata->ndev);
if (!ret)
pdata->mdio_driver = true;
 
-   return 0;
+   return;
 }
 
 static void xgene_enet_gpiod_get(struct xgene_enet_pdata *pdata)
@@ -1779,10 +1779,6 @@ static int xgene_enet_get_resources(struct 
xgene_enet_pdata *pdata)
if (ret)
return ret;
 
-   ret = xgene_enet_check_phy_handle(pdata);
-   if (ret)
-   return ret;
-
xgene_enet_gpiod_get(pdata);
 
pdata->clk = devm_clk_get(>dev, NULL);
@@ -2097,9 +2093,11 @@ static int xgene_enet_probe(struct platform_device *pdev)
goto err;
}
 
+   xgene_enet_check_phy_handle(pdata);
+
ret = xgene_enet_init_hw(pdata);
if (ret)
-   goto err;
+   goto err2;
 
link_state = pdata->mac_ops->link_state;
if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) {
@@ -2117,29 +2115,30 @@ static int xgene_enet_probe(struct platform_device 
*pdev)
spin_lock_init(>stats_lock);
ret = xgene_extd_stats_init(pdata);
if (ret)
-   goto err2;
+   goto err1;
 
xgene_enet_napi_add(pdata);
ret = register_netdev(ndev);
if (ret) {
netdev_err(ndev, "Failed to register netdev\n");
-   goto err2;
+   goto err1;
}
 
return 0;
 
-err2:
+err1:
/*
 * If necessary, free_netdev() will call netif_napi_del() and undo
 * the effects of xgene_enet_napi_add()'s calls to netif_napi_add().
 */
 
+   xgene_enet_delete_desc_rings(pdata);
+
+err2:
if (pdata->mdio_driver)
xgene_enet_phy_disconnect(pdata);
else if (phy_interface_mode_is_rgmii(pdata->phy_mode))
xgene_enet_mdio_remove(pdata);
-err1:
-   xgene_enet_delete_desc_rings(pdata);
 err:
free_netdev(ndev);
return ret;
-- 
2.7.4



[PATCH 0/2] drivers: net: xgene: Misc bug fixes

2017-08-25 Thread Iyappan Subramanian
This patch set,

 1. Adds call to PHY disconnect in the case of error
 2. Cleans up all outstanding TX descriptors when the driver is
being rmmod'd

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---

Iyappan Subramanian (1):
  drivers: net: xgene: Clean up all outstanding tx descriptors

Quan Nguyen (1):
  drivers: net: xgene: Correct probe sequence handling

 drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 147 ---
 1 file changed, 102 insertions(+), 45 deletions(-)

-- 
2.7.4



[PATCH 2/2] drivers: net: xgene: Clean up all outstanding tx descriptors

2017-08-25 Thread Iyappan Subramanian
When xgene_enet is rmmod'd and there are still outstanding tx descriptors
that have been setup but have not completed, it is possible on the next
modprobe of the driver to receive the oldest of such tx descriptors. This
results in a kernel NULL pointer dereference.

This patch attempts to clean up (by tearing down) all outstanding tx
descriptors when the xgene_enet driver is being rmmod'd.

Given that, on the next modprobe it should be safe to ignore any such tx
descriptors received that map to a NULL skb pointer.

Additionally this patch removes redundant call to dev_kfree_skb_any() from
xgene_enet_setup_tx_desc(). The only caller of xgene_enet_setup_tx_desc()
will call dev_kfree_skb_any() upon return of an error. Nothing is gained by
calling it twice in a row.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
Signed-off-by: Dean Nelson <dnel...@redhat.com>
Tested-by: Quan Nguyen <qngu...@apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 120 +--
 1 file changed, 89 insertions(+), 31 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index 6e253d9..76e2903 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -237,22 +237,24 @@ static irqreturn_t xgene_enet_rx_irq(const int irq, void 
*data)
return IRQ_HANDLED;
 }
 
-static int xgene_enet_tx_completion(struct xgene_enet_desc_ring *cp_ring,
-   struct xgene_enet_raw_desc *raw_desc)
+static dma_addr_t *xgene_get_frag_dma_array(struct xgene_enet_desc_ring *ring,
+   u16 skb_index)
 {
-   struct xgene_enet_pdata *pdata = netdev_priv(cp_ring->ndev);
-   struct sk_buff *skb;
+   return >frag_dma_addr[skb_index * MAX_SKB_FRAGS];
+}
+
+static void xgene_enet_teardown_tx_desc(struct xgene_enet_desc_ring *cp_ring,
+   struct xgene_enet_raw_desc *raw_desc,
+   struct xgene_enet_raw_desc *exp_desc,
+   struct sk_buff *skb,
+   u16 skb_index)
+{
+   dma_addr_t dma_addr, *frag_dma_addr;
struct device *dev;
skb_frag_t *frag;
-   dma_addr_t *frag_dma_addr;
-   u16 skb_index;
-   u8 mss_index;
-   u8 status;
int i;
 
-   skb_index = GET_VAL(USERINFO, le64_to_cpu(raw_desc->m0));
-   skb = cp_ring->cp_skb[skb_index];
-   frag_dma_addr = _ring->frag_dma_addr[skb_index * MAX_SKB_FRAGS];
+   frag_dma_addr = xgene_get_frag_dma_array(cp_ring, skb_index);
 
dev = ndev_to_dev(cp_ring->ndev);
dma_unmap_single(dev, GET_VAL(DATAADDR, le64_to_cpu(raw_desc->m1)),
@@ -265,6 +267,36 @@ static int xgene_enet_tx_completion(struct 
xgene_enet_desc_ring *cp_ring,
   DMA_TO_DEVICE);
}
 
+   if (exp_desc && GET_VAL(LL_BYTES_LSB, le64_to_cpu(raw_desc->m2))) {
+   dma_addr = GET_VAL(DATAADDR, le64_to_cpu(exp_desc->m2));
+   dma_unmap_single(dev, dma_addr, sizeof(u64) * MAX_EXP_BUFFS,
+DMA_TO_DEVICE);
+   }
+
+   dev_kfree_skb_any(skb);
+}
+
+static int xgene_enet_tx_completion(struct xgene_enet_desc_ring *cp_ring,
+   struct xgene_enet_raw_desc *raw_desc,
+   struct xgene_enet_raw_desc *exp_desc)
+{
+   struct xgene_enet_pdata *pdata = netdev_priv(cp_ring->ndev);
+   struct sk_buff *skb;
+   u16 skb_index;
+   u8 status;
+   u8 mss_index;
+
+   skb_index = GET_VAL(USERINFO, le64_to_cpu(raw_desc->m0));
+   skb = cp_ring->cp_skb[skb_index];
+   if (unlikely(!skb)) {
+   netdev_err(cp_ring->ndev, "completion skb is NULL\n");
+   return -EIO;
+   }
+   cp_ring->cp_skb[skb_index] = NULL;
+
+   xgene_enet_teardown_tx_desc(cp_ring, raw_desc, exp_desc, skb,
+   skb_index);
+
if (GET_BIT(ET, le64_to_cpu(raw_desc->m3))) {
mss_index = GET_VAL(MSS, le64_to_cpu(raw_desc->m3));
spin_lock(>mss_lock);
@@ -279,12 +311,6 @@ static int xgene_enet_tx_completion(struct 
xgene_enet_desc_ring *cp_ring,
cp_ring->tx_errors++;
}
 
-   if (likely(skb)) {
-   dev_kfree_skb_any(skb);
-   } else {
-   netdev_err(cp_ring->ndev, "completion skb is NULL\n");
-   }
-
return 0;
 }
 
@@ -412,11 +438,6 @@ static __le64 *xgene_enet_get_exp_bufs(struct 
xgene_enet_desc_ring *ring)
return exp_bufs;
 }
 
-static dma_addr_t *xgene_get_frag_dma_array(struct xgene_enet_desc_ring *ring)
-{
-   return >cp_ring->frag_dma_add

Re: [PATCH net] xgene: Don't fail probe, if there is no clk resource for SGMII interfaces

2017-07-28 Thread Iyappan Subramanian
On Fri, Jul 28, 2017 at 7:23 AM, Tom Bogendoerfer
<tsbog...@alpha.franken.de> wrote:
> On Thu, Jul 27, 2017 at 03:39:58PM -0700, Laura Abbott wrote:
>> I don't know the intricacies of the Mustang hardware but external
>> aborts have been a symptom of missing clocks on other hardware.
>
> you are right, it's a missing clock. For SGMII ports the driver
> doesn't really use the clock source other then doing the one
> devm_clk_get(), but this is enough to get the clock going.
>
> Below patch fixes the crash and brings back the second SGMII port
> (even without a clock source in device tree, I guess it uses clock
> from first port).  From a correctness standpoint there should probably
> be a clk_prepare_enable(), if port is SGMII.
>
> Could you test the patch ? If it works, I'll submit it.
>
> Thomas.
>
> diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c 
> b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
> index 86058a9f3417..1d307f2def2d 100644
> --- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
> +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
> @@ -1785,9 +1785,9 @@ static int xgene_enet_get_resources(struct 
> xgene_enet_pdata *pdata)
>
> xgene_enet_gpiod_get(pdata);
>
> -   if (pdata->phy_mode != PHY_INTERFACE_MODE_SGMII) {
> -   pdata->clk = devm_clk_get(>dev, NULL);
> -   if (IS_ERR(pdata->clk)) {
> +   pdata->clk = devm_clk_get(>dev, NULL);
> +   if (IS_ERR(pdata->clk)) {
> +   if (pdata->phy_mode != PHY_INTERFACE_MODE_SGMII) {
> /* Abort if the clock is defined but couldn't be
>  * retrived. Always abort if the clock is missing on
>  * DT system as the driver can't cope with this case.
>
> --

Thanks for the patch.

Acked-by: Iyappan Subramanian <isubraman...@apm.com>

> Crap can work. Given enough thrust pigs will fly, but it's not necessarily a
> good idea.[ RFC1925, 2.3 ]


Re: [PATCH v2 net-next 1/2] include: linux: Add helper function to check phy interface mode

2017-05-18 Thread Iyappan Subramanian
On Thu, May 18, 2017 at 3:19 PM, Florian Fainelli <f.faine...@gmail.com> wrote:
> On 05/18/2017 03:13 PM, Iyappan Subramanian wrote:
>> Added helper function that checks phy_mode is RGMII (all variants)
>> 'bool phy_interface_mode_is_rgmii(phy_interface_t mode)'
>>
>> Changed the following function, to use the above.
>> 'bool phy_interface_is_rgmii(struct phy_device *phydev)'
>>
>> Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
>> Suggested-by: Florian Fainelli <f.faine...@gmail.com>
>> Suggested-by: Andrew Lunn <and...@lunn.ch>
>
> Not sure why you have chosen include: linux as the subject since all
> changes done to that file typically had the "phy: " prefix, but the code
> changes are fine, thanks!

Thanks Florian.  I'll keep that in mind for future header file patches.  :-)

For now, if David Miller requests for the subject line change, I'll
re-post the patch.

>
> Reviewed-by: Florian Fainelli <f.faine...@gmail.com>
>
>> ---
>>  include/linux/phy.h | 14 --
>>  1 file changed, 12 insertions(+), 2 deletions(-)
>>
>> diff --git a/include/linux/phy.h b/include/linux/phy.h
>> index 54ef458..5a808a2 100644
>> --- a/include/linux/phy.h
>> +++ b/include/linux/phy.h
>> @@ -716,14 +716,24 @@ static inline bool phy_is_internal(struct phy_device 
>> *phydev)
>>  }
>>
>>  /**
>> + * phy_interface_mode_is_rgmii - Convenience function for testing if a
>> + * PHY interface mode is RGMII (all variants)
>> + * @mode: the phy_interface_t enum
>> + */
>> +static inline bool phy_interface_mode_is_rgmii(phy_interface_t mode)
>> +{
>> + return mode >= PHY_INTERFACE_MODE_RGMII &&
>> + mode <= PHY_INTERFACE_MODE_RGMII_TXID;
>> +};
>> +
>> +/**
>>   * phy_interface_is_rgmii - Convenience function for testing if a PHY 
>> interface
>>   * is RGMII (all variants)
>>   * @phydev: the phy_device struct
>>   */
>>  static inline bool phy_interface_is_rgmii(struct phy_device *phydev)
>>  {
>> - return phydev->interface >= PHY_INTERFACE_MODE_RGMII &&
>> - phydev->interface <= PHY_INTERFACE_MODE_RGMII_TXID;
>> + return phy_interface_mode_is_rgmii(phydev->interface);
>>  };
>>
>>  /*
>>
>
>
> --
> Florian


[PATCH v2 net-next 2/2] drivers: net: xgene: Check all RGMII phy mode variants

2017-05-18 Thread Iyappan Subramanian
This patch addresses the review comment from the previous patch set,
by using phy_interface_mode_is_rgmii() helper function to address
all RGMII phy mode variants.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
Signed-off-by: Quan Nguyen <qngu...@apm.com>
---

Review comment reference:
http://www.spinics.net/lists/netdev/msg434649.html
---
 drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c |  6 +++---
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.c  | 12 ++--
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c| 15 +--
 3 files changed, 18 insertions(+), 15 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
index 0fdec78..559963b 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
@@ -127,7 +127,7 @@ static int xgene_get_link_ksettings(struct net_device *ndev,
struct phy_device *phydev = ndev->phydev;
u32 supported;
 
-   if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) {
+   if (phy_interface_mode_is_rgmii(pdata->phy_mode)) {
if (phydev == NULL)
return -ENODEV;
 
@@ -177,7 +177,7 @@ static int xgene_set_link_ksettings(struct net_device *ndev,
struct xgene_enet_pdata *pdata = netdev_priv(ndev);
struct phy_device *phydev = ndev->phydev;
 
-   if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) {
+   if (phy_interface_mode_is_rgmii(pdata->phy_mode)) {
if (!phydev)
return -ENODEV;
 
@@ -304,7 +304,7 @@ static int xgene_set_pauseparam(struct net_device *ndev,
struct phy_device *phydev = ndev->phydev;
u32 oldadv, newadv;
 
-   if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII ||
+   if (phy_interface_mode_is_rgmii(pdata->phy_mode) ||
pdata->phy_mode == PHY_INTERFACE_MODE_SGMII) {
if (!phydev)
return -EINVAL;
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
index 6ac27c7..e45b587 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
@@ -272,7 +272,7 @@ void xgene_enet_wr_mac(struct xgene_enet_pdata *pdata, u32 
wr_addr, u32 wr_data)
u32 done;
 
if (pdata->mdio_driver && ndev->phydev &&
-   pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) {
+   phy_interface_mode_is_rgmii(pdata->phy_mode)) {
struct mii_bus *bus = ndev->phydev->mdio.bus;
 
return xgene_mdio_wr_mac(bus->priv, wr_addr, wr_data);
@@ -326,12 +326,13 @@ static void xgene_enet_rd_mcx_csr(struct xgene_enet_pdata 
*pdata,
 u32 xgene_enet_rd_mac(struct xgene_enet_pdata *pdata, u32 rd_addr)
 {
void __iomem *addr, *rd, *cmd, *cmd_done;
+   struct net_device *ndev = pdata->ndev;
u32 done, rd_data;
u8 wait = 10;
 
-   if (pdata->mdio_driver && pdata->ndev->phydev &&
-   pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) {
-   struct mii_bus *bus = pdata->ndev->phydev->mdio.bus;
+   if (pdata->mdio_driver && ndev->phydev &&
+   phy_interface_mode_is_rgmii(pdata->phy_mode)) {
+   struct mii_bus *bus = ndev->phydev->mdio.bus;
 
return xgene_mdio_rd_mac(bus->priv, rd_addr);
}
@@ -349,8 +350,7 @@ u32 xgene_enet_rd_mac(struct xgene_enet_pdata *pdata, u32 
rd_addr)
udelay(1);
 
if (!done)
-   netdev_err(pdata->ndev, "mac read failed, addr: %04x\n",
-  rd_addr);
+   netdev_err(ndev, "mac read failed, addr: %04x\n", rd_addr);
 
rd_data = ioread32(rd);
iowrite32(0, cmd);
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index 21cd4ef..d3906f6 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -1634,7 +1634,7 @@ static int xgene_enet_get_irqs(struct xgene_enet_pdata 
*pdata)
struct device *dev = >dev;
int i, ret, max_irqs;
 
-   if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII)
+   if (phy_interface_mode_is_rgmii(pdata->phy_mode))
max_irqs = 1;
else if (pdata->phy_mode == PHY_INTERFACE_MODE_SGMII)
max_irqs = 2;
@@ -1760,7 +1760,7 @@ static int xgene_enet_get_resources(struct 
xgene_enet_pdata *pdata)
dev_err(dev, "Unable to get phy-connection-type\n");
return pdata->phy_mode;
}
-   if (pdata->phy_mode != PHY_INTERFACE_MODE_RGMII &&
+   if (!phy_interface_mode_is_rgmii(pdata->p

[PATCH v2 net-next 1/2] include: linux: Add helper function to check phy interface mode

2017-05-18 Thread Iyappan Subramanian
Added helper function that checks phy_mode is RGMII (all variants)
'bool phy_interface_mode_is_rgmii(phy_interface_t mode)'

Changed the following function, to use the above.
'bool phy_interface_is_rgmii(struct phy_device *phydev)'

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
Suggested-by: Florian Fainelli <f.faine...@gmail.com>
Suggested-by: Andrew Lunn <and...@lunn.ch>
---
 include/linux/phy.h | 14 --
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/include/linux/phy.h b/include/linux/phy.h
index 54ef458..5a808a2 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -716,14 +716,24 @@ static inline bool phy_is_internal(struct phy_device 
*phydev)
 }
 
 /**
+ * phy_interface_mode_is_rgmii - Convenience function for testing if a
+ * PHY interface mode is RGMII (all variants)
+ * @mode: the phy_interface_t enum
+ */
+static inline bool phy_interface_mode_is_rgmii(phy_interface_t mode)
+{
+   return mode >= PHY_INTERFACE_MODE_RGMII &&
+   mode <= PHY_INTERFACE_MODE_RGMII_TXID;
+};
+
+/**
  * phy_interface_is_rgmii - Convenience function for testing if a PHY interface
  * is RGMII (all variants)
  * @phydev: the phy_device struct
  */
 static inline bool phy_interface_is_rgmii(struct phy_device *phydev)
 {
-   return phydev->interface >= PHY_INTERFACE_MODE_RGMII &&
-   phydev->interface <= PHY_INTERFACE_MODE_RGMII_TXID;
+   return phy_interface_mode_is_rgmii(phydev->interface);
 };
 
 /*
-- 
1.9.1



[PATCH v2 net-next 0/2] Check all RGMII phy mode variants

2017-05-18 Thread Iyappan Subramanian
This patch set,
 - adds phy_interface_mode_is_rgmii() helper function
 - addresses review comment from previous patch set, by calling
   phy_interface_mode_is_rgmii() to address all RGMII variants

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
v2: Address review comments from v1
 - adds phy_interface_mode_is_rgmii() helper function
 - addresses review comment from previous patch set, by calling
   phy_interface_mode_is_rgmii() to address all RGMII variants
v1:
 - Initial version
---

Iyappan Subramanian (2):
  include: linux: Add helper function to check phy interface mode
  drivers: net: xgene: Check all RGMII phy mode variants

 drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c |  6 +++---
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.c  | 12 ++--
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c| 15 +--
 include/linux/phy.h | 14 --
 4 files changed, 30 insertions(+), 17 deletions(-)

-- 
1.9.1



Re: [PATCH net-next] drivers: net: xgene: Check all RGMII phy mode variants

2017-05-17 Thread Iyappan Subramanian
On Wed, May 17, 2017 at 1:26 PM, Andrew Lunn  wrote:
>> +bool is_xgene_enet_phy_mode_rgmii(struct net_device *ndev)
>> +{
>> + struct xgene_enet_pdata *pdata = netdev_priv(ndev);
>> + int phy_mode = pdata->phy_mode;
>> + bool ret;
>> +
>> + ret = phy_mode == PHY_INTERFACE_MODE_RGMII ||
>> +   phy_mode == PHY_INTERFACE_MODE_RGMII_ID ||
>> +   phy_mode == PHY_INTERFACE_MODE_RGMII_RXID ||
>> +   phy_mode == PHY_INTERFACE_MODE_RGMII_TXID;
>> +
>> + return ret;
>> +}
>
> include/linux/phy.h:
>
> /**
>  * phy_interface_is_rgmii - Convenience function for testing if a PHY 
> interface
>  * is RGMII (all variants)
>  * @phydev: the phy_device struct
>  */
> static inline bool phy_interface_is_rgmii(struct phy_device *phydev)
> {
> return phydev->interface >= PHY_INTERFACE_MODE_RGMII &&
> phydev->interface <= PHY_INTERFACE_MODE_RGMII_TXID;
> };

Thanks.  I'll use this helper function.

>
> Andrew


[PATCH net-next] drivers: net: xgene: Check all RGMII phy mode variants

2017-05-17 Thread Iyappan Subramanian
This patch addresses the review comment from the previous patch set,
by adding a helper function to address all RGMII phy mode variants.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
Signed-off-by: Quan Nguyen <qngu...@apm.com>
---

Review comment reference:
http://www.spinics.net/lists/netdev/msg434649.html
---
 .../net/ethernet/apm/xgene/xgene_enet_ethtool.c|  6 ++---
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.c | 26 +-
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.h |  1 +
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c   | 15 -
 4 files changed, 33 insertions(+), 15 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
index 0fdec78..a0c9ddc 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
@@ -127,7 +127,7 @@ static int xgene_get_link_ksettings(struct net_device *ndev,
struct phy_device *phydev = ndev->phydev;
u32 supported;
 
-   if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) {
+   if (is_xgene_enet_phy_mode_rgmii(ndev)) {
if (phydev == NULL)
return -ENODEV;
 
@@ -177,7 +177,7 @@ static int xgene_set_link_ksettings(struct net_device *ndev,
struct xgene_enet_pdata *pdata = netdev_priv(ndev);
struct phy_device *phydev = ndev->phydev;
 
-   if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) {
+   if (is_xgene_enet_phy_mode_rgmii(ndev)) {
if (!phydev)
return -ENODEV;
 
@@ -304,7 +304,7 @@ static int xgene_set_pauseparam(struct net_device *ndev,
struct phy_device *phydev = ndev->phydev;
u32 oldadv, newadv;
 
-   if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII ||
+   if (is_xgene_enet_phy_mode_rgmii(ndev) ||
pdata->phy_mode == PHY_INTERFACE_MODE_SGMII) {
if (!phydev)
return -EINVAL;
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
index 6ac27c7..00f313d 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
@@ -264,6 +264,20 @@ static void xgene_enet_wr_mcx_csr(struct xgene_enet_pdata 
*pdata,
iowrite32(val, addr);
 }
 
+bool is_xgene_enet_phy_mode_rgmii(struct net_device *ndev)
+{
+   struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+   int phy_mode = pdata->phy_mode;
+   bool ret;
+
+   ret = phy_mode == PHY_INTERFACE_MODE_RGMII ||
+ phy_mode == PHY_INTERFACE_MODE_RGMII_ID ||
+ phy_mode == PHY_INTERFACE_MODE_RGMII_RXID ||
+ phy_mode == PHY_INTERFACE_MODE_RGMII_TXID;
+
+   return ret;
+}
+
 void xgene_enet_wr_mac(struct xgene_enet_pdata *pdata, u32 wr_addr, u32 
wr_data)
 {
void __iomem *addr, *wr, *cmd, *cmd_done;
@@ -272,7 +286,7 @@ void xgene_enet_wr_mac(struct xgene_enet_pdata *pdata, u32 
wr_addr, u32 wr_data)
u32 done;
 
if (pdata->mdio_driver && ndev->phydev &&
-   pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) {
+   is_xgene_enet_phy_mode_rgmii(ndev)) {
struct mii_bus *bus = ndev->phydev->mdio.bus;
 
return xgene_mdio_wr_mac(bus->priv, wr_addr, wr_data);
@@ -326,12 +340,13 @@ static void xgene_enet_rd_mcx_csr(struct xgene_enet_pdata 
*pdata,
 u32 xgene_enet_rd_mac(struct xgene_enet_pdata *pdata, u32 rd_addr)
 {
void __iomem *addr, *rd, *cmd, *cmd_done;
+   struct net_device *ndev = pdata->ndev;
u32 done, rd_data;
u8 wait = 10;
 
-   if (pdata->mdio_driver && pdata->ndev->phydev &&
-   pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) {
-   struct mii_bus *bus = pdata->ndev->phydev->mdio.bus;
+   if (pdata->mdio_driver && ndev->phydev &&
+   is_xgene_enet_phy_mode_rgmii(ndev)) {
+   struct mii_bus *bus = ndev->phydev->mdio.bus;
 
return xgene_mdio_rd_mac(bus->priv, rd_addr);
}
@@ -349,8 +364,7 @@ u32 xgene_enet_rd_mac(struct xgene_enet_pdata *pdata, u32 
rd_addr)
udelay(1);
 
if (!done)
-   netdev_err(pdata->ndev, "mac read failed, addr: %04x\n",
-  rd_addr);
+   netdev_err(ndev, "mac read failed, addr: %04x\n", rd_addr);
 
rd_data = ioread32(rd);
iowrite32(0, cmd);
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h 
b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
index 5d3e18d..5c54f65 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
@@ -431,6 +431,7 @@ static inline u16 xgene_enet_get_numslots(u16 id, u32 size)
 

[PATCH v2 net-next 07/12] drivers: net: xgene: Extend ethtool statistics

2017-05-10 Thread Iyappan Subramanian
From: Quan Nguyen <qngu...@apm.com>

This patch adds extended ethtool statistics support.

Signed-off-by: Quan Nguyen <qngu...@apm.com>
Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
 .../net/ethernet/apm/xgene/xgene_enet_ethtool.c| 89 +-
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.c | 29 +++
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.h | 51 +
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c   |  8 ++
 drivers/net/ethernet/apm/xgene/xgene_enet_main.h   |  4 +
 drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h  |  1 +
 6 files changed, 181 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
index 217cde8..a7eed3b 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
@@ -23,9 +23,17 @@
 struct xgene_gstrings_stats {
char name[ETH_GSTRING_LEN];
int offset;
+   u32 addr;
+   u32 mask;
 };
 
 #define XGENE_STAT(m) { #m, offsetof(struct rtnl_link_stats64, m) }
+#define XGENE_EXTD_STAT(s, a, m)   \
+   {   \
+   .name = #s, \
+   .addr = a ## _ADDR, \
+   .mask = m   \
+   }
 
 static const struct xgene_gstrings_stats gstrings_stats[] = {
XGENE_STAT(rx_packets),
@@ -40,7 +48,51 @@ struct xgene_gstrings_stats {
XGENE_STAT(rx_fifo_errors)
 };
 
+static const struct xgene_gstrings_stats gstrings_extd_stats[] = {
+   XGENE_EXTD_STAT(tx_rx_64b_frame_cntr, TR64, 31),
+   XGENE_EXTD_STAT(tx_rx_127b_frame_cntr, TR127, 31),
+   XGENE_EXTD_STAT(tx_rx_255b_frame_cntr, TR255, 31),
+   XGENE_EXTD_STAT(tx_rx_511b_frame_cntr, TR511, 31),
+   XGENE_EXTD_STAT(tx_rx_1023b_frame_cntr, TR1K, 31),
+   XGENE_EXTD_STAT(tx_rx_1518b_frame_cntr, TRMAX, 31),
+   XGENE_EXTD_STAT(tx_rx_1522b_frame_cntr, TRMGV, 31),
+   XGENE_EXTD_STAT(rx_fcs_error_cntr, RFCS, 16),
+   XGENE_EXTD_STAT(rx_multicast_pkt_cntr, RMCA, 31),
+   XGENE_EXTD_STAT(rx_broadcast_pkt_cntr, RBCA, 31),
+   XGENE_EXTD_STAT(rx_ctrl_frame_pkt_cntr, RXCF, 16),
+   XGENE_EXTD_STAT(rx_pause_frame_pkt_cntr, RXPF, 16),
+   XGENE_EXTD_STAT(rx_unk_opcode_cntr, RXUO, 16),
+   XGENE_EXTD_STAT(rx_align_err_cntr, RALN, 16),
+   XGENE_EXTD_STAT(rx_frame_len_err_cntr, RFLR, 16),
+   XGENE_EXTD_STAT(rx_code_err_cntr, RCDE, 16),
+   XGENE_EXTD_STAT(rx_carrier_sense_err_cntr, RCSE, 16),
+   XGENE_EXTD_STAT(rx_undersize_pkt_cntr, RUND, 16),
+   XGENE_EXTD_STAT(rx_oversize_pkt_cntr, ROVR, 16),
+   XGENE_EXTD_STAT(rx_fragments_cntr, RFRG, 16),
+   XGENE_EXTD_STAT(rx_jabber_cntr, RJBR, 16),
+   XGENE_EXTD_STAT(rx_dropped_pkt_cntr, RDRP, 16),
+   XGENE_EXTD_STAT(tx_multicast_pkt_cntr, TMCA, 31),
+   XGENE_EXTD_STAT(tx_broadcast_pkt_cntr, TBCA, 31),
+   XGENE_EXTD_STAT(tx_pause_ctrl_frame_cntr, TXPF, 16),
+   XGENE_EXTD_STAT(tx_defer_pkt_cntr, TDFR, 31),
+   XGENE_EXTD_STAT(tx_excv_defer_pkt_cntr, TEDF, 31),
+   XGENE_EXTD_STAT(tx_single_col_pkt_cntr, TSCL, 31),
+   XGENE_EXTD_STAT(tx_multi_col_pkt_cntr, TMCL, 31),
+   XGENE_EXTD_STAT(tx_late_col_pkt_cntr, TLCL, 31),
+   XGENE_EXTD_STAT(tx_excv_col_pkt_cntr, TXCL, 31),
+   XGENE_EXTD_STAT(tx_total_col_cntr, TNCL, 31),
+   XGENE_EXTD_STAT(tx_pause_frames_hnrd_cntr, TPFH, 16),
+   XGENE_EXTD_STAT(tx_drop_frame_cntr, TDRP, 16),
+   XGENE_EXTD_STAT(tx_jabber_frame_cntr, TJBR, 12),
+   XGENE_EXTD_STAT(tx_fcs_error_cntr, TFCS, 12),
+   XGENE_EXTD_STAT(tx_ctrl_frame_cntr, TXCF, 12),
+   XGENE_EXTD_STAT(tx_oversize_frame_cntr, TOVR, 12),
+   XGENE_EXTD_STAT(tx_undersize_frame_cntr, TUND, 12),
+   XGENE_EXTD_STAT(tx_fragments_cntr, TFRG, 12)
+};
+
 #define XGENE_STATS_LENARRAY_SIZE(gstrings_stats)
+#define XGENE_EXTD_STATS_LEN   ARRAY_SIZE(gstrings_extd_stats)
 
 static void xgene_get_drvinfo(struct net_device *ndev,
  struct ethtool_drvinfo *info)
@@ -142,6 +194,11 @@ static void xgene_get_strings(struct net_device *ndev, u32 
stringset, u8 *data)
memcpy(p, gstrings_stats[i].name, ETH_GSTRING_LEN);
p += ETH_GSTRING_LEN;
}
+
+   for (i = 0; i < XGENE_EXTD_STATS_LEN; i++) {
+   memcpy(p, gstrings_extd_stats[i].name, ETH_GSTRING_LEN);
+   p += ETH_GSTRING_LEN;
+   }
 }
 
 static int xgene_get_sset_count(struct net_device *ndev, int sset)
@@ -149,19 +206,49 @@ static int xgene_get_sset_count(struct net_device *ndev, 
int sset)
if (sset != ETH_SS_STATS)
return -EINVAL;
 
-   return XGENE_STATS_LEN;
+   return XGENE_STATS_LEN + XGENE_EXTD_STATS_LEN;
+}
+
+static void xgene_get_extd_stats(struct xgene_enet_pdata *pdata)
+{
+   u32 tmp;
+   in

[PATCH v2 net-next 06/12] drivers: net: xgene: Remove unused macros

2017-05-10 Thread Iyappan Subramanian
From: Quan Nguyen <qngu...@apm.com>

This patch cleans up unused macros to improve readability.

Signed-off-by: Quan Nguyen <qngu...@apm.com>
Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.h | 6 --
 1 file changed, 6 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h 
b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
index 3ce349f..ed51005 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
@@ -217,12 +217,6 @@ enum xgene_enet_rm {
 #define FULL_DUPLEX2   BIT(0)
 #define PAD_CRCBIT(2)
 #define LENGTH_CHK BIT(4)
-#define SCAN_AUTO_INCR BIT(5)
-#define TBYT_ADDR  0x38
-#define TPKT_ADDR  0x39
-#define TDRP_ADDR  0x45
-#define TFCS_ADDR  0x47
-#define TUND_ADDR  0x4a
 
 #define TSO_IPPROTO_TCP1
 
-- 
1.9.1



[PATCH v2 net-next 01/12] drivers: net: xgene: Protect indirect MAC access

2017-05-10 Thread Iyappan Subramanian
This patch,

 - refactors mac read/write functions
 - adds lock to protect indirect mac access

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
Signed-off-by: Quan Nguyen <qngu...@apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.c| 119 +-
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.h|   3 +
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c  |   1 +
 drivers/net/ethernet/apm/xgene/xgene_enet_main.h  |   1 +
 drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c |  71 -
 drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c |  44 ++--
 6 files changed, 62 insertions(+), 177 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
index 2a835e0..2050c58 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
@@ -270,42 +270,32 @@ static void xgene_enet_wr_mcx_csr(struct xgene_enet_pdata 
*pdata,
iowrite32(val, addr);
 }
 
-static bool xgene_enet_wr_indirect(void __iomem *addr, void __iomem *wr,
-  void __iomem *cmd, void __iomem *cmd_done,
-  u32 wr_addr, u32 wr_data)
+void xgene_enet_wr_mac(struct xgene_enet_pdata *pdata, u32 wr_addr, u32 
wr_data)
 {
-   u32 done;
+   void __iomem *addr, *wr, *cmd, *cmd_done;
+   struct net_device *ndev = pdata->ndev;
u8 wait = 10;
+   u32 done;
 
+   addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET;
+   wr = pdata->mcx_mac_addr + MAC_WRITE_REG_OFFSET;
+   cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET;
+   cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET;
+
+   spin_lock(>mac_lock);
iowrite32(wr_addr, addr);
iowrite32(wr_data, wr);
iowrite32(XGENE_ENET_WR_CMD, cmd);
 
-   /* wait for write command to complete */
while (!(done = ioread32(cmd_done)) && wait--)
udelay(1);
 
if (!done)
-   return false;
+   netdev_err(ndev, "mac write failed, addr: %04x data: %08x\n",
+  wr_addr, wr_data);
 
iowrite32(0, cmd);
-
-   return true;
-}
-
-static void xgene_enet_wr_mcx_mac(struct xgene_enet_pdata *pdata,
- u32 wr_addr, u32 wr_data)
-{
-   void __iomem *addr, *wr, *cmd, *cmd_done;
-
-   addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET;
-   wr = pdata->mcx_mac_addr + MAC_WRITE_REG_OFFSET;
-   cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET;
-   cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET;
-
-   if (!xgene_enet_wr_indirect(addr, wr, cmd, cmd_done, wr_addr, wr_data))
-   netdev_err(pdata->ndev, "MCX mac write failed, addr: %04x\n",
-  wr_addr);
+   spin_unlock(>mac_lock);
 }
 
 static void xgene_enet_rd_csr(struct xgene_enet_pdata *pdata,
@@ -332,42 +322,33 @@ static void xgene_enet_rd_mcx_csr(struct xgene_enet_pdata 
*pdata,
*val = ioread32(addr);
 }
 
-static bool xgene_enet_rd_indirect(void __iomem *addr, void __iomem *rd,
-  void __iomem *cmd, void __iomem *cmd_done,
-  u32 rd_addr, u32 *rd_data)
+u32 xgene_enet_rd_mac(struct xgene_enet_pdata *pdata, u32 rd_addr)
 {
-   u32 done;
+   void __iomem *addr, *rd, *cmd, *cmd_done;
+   u32 done, rd_data;
u8 wait = 10;
 
+   addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET;
+   rd = pdata->mcx_mac_addr + MAC_READ_REG_OFFSET;
+   cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET;
+   cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET;
+
+   spin_lock(>mac_lock);
iowrite32(rd_addr, addr);
iowrite32(XGENE_ENET_RD_CMD, cmd);
 
-   /* wait for read command to complete */
while (!(done = ioread32(cmd_done)) && wait--)
udelay(1);
 
if (!done)
-   return false;
+   netdev_err(pdata->ndev, "mac read failed, addr: %04x\n",
+  rd_addr);
 
-   *rd_data = ioread32(rd);
+   rd_data = ioread32(rd);
iowrite32(0, cmd);
+   spin_unlock(>mac_lock);
 
-   return true;
-}
-
-static void xgene_enet_rd_mcx_mac(struct xgene_enet_pdata *pdata,
- u32 rd_addr, u32 *rd_data)
-{
-   void __iomem *addr, *rd, *cmd, *cmd_done;
-
-   addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET;
-   rd = pdata->mcx_mac_addr + MAC_READ_REG_OFFSET;
-   cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET;
-   cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET;
-
-   if (!xgene_enet_rd_indirect(addr, rd, cmd, cmd_done, rd_addr, rd_data))
-   netdev_err(pdata->ndev, "MCX mac re

[PATCH v2 net-next 00/12] drivers: net: xgene: Add ethtool stats and bug fixes

2017-05-10 Thread Iyappan Subramanian
This patch set,

- adds ethtool extended statistics support
- addresses errata workarounds
- fixes bugs related to statistics

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
Signed-off-by: Quan Nguyen <qngu...@apm.com>
---
v2: Address review comments from v1
- Adds lock to protect mdio-xgene indirect MAC access
- Refactors xgene-enet indirect MAC read/write functions
- Uses mdio-xgene MAC access routines, if xgene-enet port
  use the same HW.
v1:
- Initial version
---

Iyappan Subramanian (3):
  drivers: net: xgene: Protect indirect MAC access
  drivers: net: xgene: Add rx_overrun/tx_underrun statistics
  drivers: net: xgene: Fix redundant prefetch buffer cleanup

Quan Nguyen (9):
  drivers: net: phy: xgene: Add lock to protect mac access
  drivers: net: xgene: Use rgmii mdio mac access
  drivers: net: xgene: Remove redundant local stats
  drivers: net: xgene: Refactor statistics error parsing code
  drivers: net: xgene: Remove unused macros
  drivers: net: xgene: Extend ethtool statistics
  drivers: net: xgene: Workaround for HW errata 10GE_4
  drivers: net: xgene: Add frame recovered statistics counter for errata
10GE_8/ENET_11
  drivers: net: xgene: Workaround for HW errata 10GE_10/ENET_15

 .../net/ethernet/apm/xgene/xgene_enet_ethtool.c| 132 ++-
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.c | 188 +++--
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.h |  70 +++-
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c   |  59 +--
 drivers/net/ethernet/apm/xgene/xgene_enet_main.h   |  12 +-
 drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c  | 110 +++-
 drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c  |  77 +++--
 drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h  |   5 +
 drivers/net/phy/mdio-xgene.c   |  74 
 drivers/net/phy/mdio-xgene.h   |   3 +
 10 files changed, 428 insertions(+), 302 deletions(-)

-- 
1.9.1



[PATCH v2 net-next 12/12] drivers: net: xgene: Fix redundant prefetch buffer cleanup

2017-05-10 Thread Iyappan Subramanian
Prefetch buffer cleanup code was called twice, causing EDAC to
report errors during reboot.

[ 1130.972475] xgene-edac 7880.edac: IOB bridge agent (BA) transaction
error
[ 1130.979584] xgene-edac 7880.edac: IOB BA write response error
[ 1130.985648] xgene-edac 7880.edac: IOB BA write access at 0x00.
()
[ 1130.993612] xgene-edac 7880.edac: IOB BA requestor ID 0x2400
[ 1131.000242] xgene-edac 7880.edac: IOB bridge agent (BA) transaction
error
...

This patch fixes the errors by,

- removing the redundant prefetch buffer cleanup from port_ops->shutdown()
- moving port_ops->shutdown() after delete_rings()

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.c| 21 -
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c  |  2 +-
 drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c | 20 
 drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c | 20 
 4 files changed, 1 insertion(+), 62 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
index 3235d0c..6ac27c7 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
@@ -763,27 +763,6 @@ static void xgene_enet_clear(struct xgene_enet_pdata 
*pdata,
 static void xgene_gport_shutdown(struct xgene_enet_pdata *pdata)
 {
struct device *dev = >pdev->dev;
-   struct xgene_enet_desc_ring *ring;
-   u32 pb;
-   int i;
-
-   pb = 0;
-   for (i = 0; i < pdata->rxq_cnt; i++) {
-   ring = pdata->rx_ring[i]->buf_pool;
-   pb |= BIT(xgene_enet_get_fpsel(ring->id));
-   ring = pdata->rx_ring[i]->page_pool;
-   if (ring)
-   pb |= BIT(xgene_enet_get_fpsel(ring->id));
-
-   }
-   xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIFPRESET_ADDR, pb);
-
-   pb = 0;
-   for (i = 0; i < pdata->txq_cnt; i++) {
-   ring = pdata->tx_ring[i];
-   pb |= BIT(xgene_enet_ring_bufnum(ring->id));
-   }
-   xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIWQRESET_ADDR, pb);
 
if (dev->of_node) {
if (!IS_ERR(pdata->clk))
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index 01e389d..21cd4ef 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -2159,8 +2159,8 @@ static int xgene_enet_remove(struct platform_device *pdev)
xgene_enet_mdio_remove(pdata);
 
unregister_netdev(ndev);
-   pdata->port_ops->shutdown(pdata);
xgene_enet_delete_desc_rings(pdata);
+   pdata->port_ops->shutdown(pdata);
free_netdev(ndev);
 
return 0;
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
index 31df8f3..b1a83fd 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
@@ -534,26 +534,6 @@ static void xgene_enet_clear(struct xgene_enet_pdata 
*pdata,
 static void xgene_enet_shutdown(struct xgene_enet_pdata *p)
 {
struct device *dev = >pdev->dev;
-   struct xgene_enet_desc_ring *ring;
-   u32 pb;
-   int i;
-
-   pb = 0;
-   for (i = 0; i < p->rxq_cnt; i++) {
-   ring = p->rx_ring[i]->buf_pool;
-   pb |= BIT(xgene_enet_get_fpsel(ring->id));
-   ring = p->rx_ring[i]->page_pool;
-   if (ring)
-   pb |= BIT(xgene_enet_get_fpsel(ring->id));
-   }
-   xgene_enet_wr_ring_if(p, ENET_CFGSSQMIFPRESET_ADDR, pb);
-
-   pb = 0;
-   for (i = 0; i < p->txq_cnt; i++) {
-   ring = p->tx_ring[i];
-   pb |= BIT(xgene_enet_ring_bufnum(ring->id));
-   }
-   xgene_enet_wr_ring_if(p, ENET_CFGSSQMIWQRESET_ADDR, pb);
 
if (dev->of_node) {
if (!IS_ERR(p->clk))
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
index eab6f1c..b7d75d0 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
@@ -446,26 +446,6 @@ static void xgene_enet_xgcle_bypass(struct 
xgene_enet_pdata *pdata,
 static void xgene_enet_shutdown(struct xgene_enet_pdata *pdata)
 {
struct device *dev = >pdev->dev;
-   struct xgene_enet_desc_ring *ring;
-   u32 pb;
-   int i;
-
-   pb = 0;
-   for (i = 0; i < pdata->rxq_cnt; i++) {
-   ring = pdata->rx_ring[i]->buf_pool;
-   pb |= BIT(xgene_enet_get_fpsel(ring->id));
-   ring = pdata->rx_ring[i]->pa

[PATCH v2 net-next 02/12] drivers: net: phy: xgene: Add lock to protect mac access

2017-05-10 Thread Iyappan Subramanian
From: Quan Nguyen <qngu...@apm.com>

This patch,

- refactors mac access routine
- adds lock to protect mac indirect access

Signed-off-by: Quan Nguyen <qngu...@apm.com>
Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
 drivers/net/phy/mdio-xgene.c | 74 ++--
 drivers/net/phy/mdio-xgene.h |  3 ++
 2 files changed, 40 insertions(+), 37 deletions(-)

diff --git a/drivers/net/phy/mdio-xgene.c b/drivers/net/phy/mdio-xgene.c
index 3e2ac07..bfd3090 100644
--- a/drivers/net/phy/mdio-xgene.c
+++ b/drivers/net/phy/mdio-xgene.c
@@ -34,76 +34,73 @@
 
 static bool xgene_mdio_status;
 
-static u32 xgene_enet_rd_mac(void __iomem *base_addr, u32 rd_addr)
+u32 xgene_mdio_rd_mac(struct xgene_mdio_pdata *pdata, u32 rd_addr)
 {
void __iomem *addr, *rd, *cmd, *cmd_done;
u32 done, rd_data = BUSY_MASK;
u8 wait = 10;
 
-   addr = base_addr + MAC_ADDR_REG_OFFSET;
-   rd = base_addr + MAC_READ_REG_OFFSET;
-   cmd = base_addr + MAC_COMMAND_REG_OFFSET;
-   cmd_done = base_addr + MAC_COMMAND_DONE_REG_OFFSET;
+   addr = pdata->mac_csr_addr + MAC_ADDR_REG_OFFSET;
+   rd = pdata->mac_csr_addr + MAC_READ_REG_OFFSET;
+   cmd = pdata->mac_csr_addr + MAC_COMMAND_REG_OFFSET;
+   cmd_done = pdata->mac_csr_addr + MAC_COMMAND_DONE_REG_OFFSET;
 
+   spin_lock(>mac_lock);
iowrite32(rd_addr, addr);
iowrite32(XGENE_ENET_RD_CMD, cmd);
 
-   while (wait--) {
-   done = ioread32(cmd_done);
-   if (done)
-   break;
+   while (!(done = ioread32(cmd_done)) && wait--)
udelay(1);
-   }
 
-   if (!done)
-   return rd_data;
+   if (done)
+   rd_data = ioread32(rd);
 
-   rd_data = ioread32(rd);
iowrite32(0, cmd);
+   spin_unlock(>mac_lock);
 
return rd_data;
 }
+EXPORT_SYMBOL(xgene_mdio_rd_mac);
 
-static void xgene_enet_wr_mac(void __iomem *base_addr, u32 wr_addr, u32 
wr_data)
+void xgene_mdio_wr_mac(struct xgene_mdio_pdata *pdata, u32 wr_addr, u32 data)
 {
void __iomem *addr, *wr, *cmd, *cmd_done;
u8 wait = 10;
u32 done;
 
-   addr = base_addr + MAC_ADDR_REG_OFFSET;
-   wr = base_addr + MAC_WRITE_REG_OFFSET;
-   cmd = base_addr + MAC_COMMAND_REG_OFFSET;
-   cmd_done = base_addr + MAC_COMMAND_DONE_REG_OFFSET;
+   addr = pdata->mac_csr_addr + MAC_ADDR_REG_OFFSET;
+   wr = pdata->mac_csr_addr + MAC_WRITE_REG_OFFSET;
+   cmd = pdata->mac_csr_addr + MAC_COMMAND_REG_OFFSET;
+   cmd_done = pdata->mac_csr_addr + MAC_COMMAND_DONE_REG_OFFSET;
 
+   spin_lock(>mac_lock);
iowrite32(wr_addr, addr);
-   iowrite32(wr_data, wr);
+   iowrite32(data, wr);
iowrite32(XGENE_ENET_WR_CMD, cmd);
 
-   while (wait--) {
-   done = ioread32(cmd_done);
-   if (done)
-   break;
+   while (!(done = ioread32(cmd_done)) && wait--)
udelay(1);
-   }
 
if (!done)
pr_err("MCX mac write failed, addr: 0x%04x\n", wr_addr);
 
iowrite32(0, cmd);
+   spin_unlock(>mac_lock);
 }
+EXPORT_SYMBOL(xgene_mdio_wr_mac);
 
 int xgene_mdio_rgmii_read(struct mii_bus *bus, int phy_id, int reg)
 {
-   void __iomem *addr = (void __iomem *)bus->priv;
+   struct xgene_mdio_pdata *pdata = (struct xgene_mdio_pdata *)bus->priv;
u32 data, done;
u8 wait = 10;
 
data = SET_VAL(PHY_ADDR, phy_id) | SET_VAL(REG_ADDR, reg);
-   xgene_enet_wr_mac(addr, MII_MGMT_ADDRESS_ADDR, data);
-   xgene_enet_wr_mac(addr, MII_MGMT_COMMAND_ADDR, READ_CYCLE_MASK);
+   xgene_mdio_wr_mac(pdata, MII_MGMT_ADDRESS_ADDR, data);
+   xgene_mdio_wr_mac(pdata, MII_MGMT_COMMAND_ADDR, READ_CYCLE_MASK);
do {
usleep_range(5, 10);
-   done = xgene_enet_rd_mac(addr, MII_MGMT_INDICATORS_ADDR);
+   done = xgene_mdio_rd_mac(pdata, MII_MGMT_INDICATORS_ADDR);
} while ((done & BUSY_MASK) && wait--);
 
if (done & BUSY_MASK) {
@@ -111,8 +108,8 @@ int xgene_mdio_rgmii_read(struct mii_bus *bus, int phy_id, 
int reg)
return -EBUSY;
}
 
-   data = xgene_enet_rd_mac(addr, MII_MGMT_STATUS_ADDR);
-   xgene_enet_wr_mac(addr, MII_MGMT_COMMAND_ADDR, 0);
+   data = xgene_mdio_rd_mac(pdata, MII_MGMT_STATUS_ADDR);
+   xgene_mdio_wr_mac(pdata, MII_MGMT_COMMAND_ADDR, 0);
 
return data;
 }
@@ -120,17 +117,17 @@ int xgene_mdio_rgmii_read(struct mii_bus *bus, int 
phy_id, int reg)
 
 int xgene_mdio_rgmii_write(struct mii_bus *bus, int phy_id, int reg, u16 data)
 {
-   void __iomem *addr = (void __iomem *)bus->priv;
+   struct xgene_mdio_pdata *pdata = (struct xgene_mdio_pdata *)bus->priv;
u32 val, done;
u8 wait = 10;
 
val = SE

[PATCH v2 net-next 11/12] drivers: net: xgene: Workaround for HW errata 10GE_10/ENET_15

2017-05-10 Thread Iyappan Subramanian
From: Quan Nguyen <qngu...@apm.com>

This patch adds workaround for HW errata 10GE_10 and ENET_15:
"HW statistic counters value are duplicated".

- RFCS duplicates RALN counter
- RFLR duplicates RUND counter
- TFCS duplicates TFRG counter
- RALN should be intepreted as 0 in 10G mode

Signed-off-by: Quan Nguyen <qngu...@apm.com>
Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
 .../net/ethernet/apm/xgene/xgene_enet_ethtool.c| 33 ++
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c   | 20 +++--
 drivers/net/ethernet/apm/xgene/xgene_enet_main.h   |  2 ++
 3 files changed, 46 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
index 5c2c84a..0fdec78 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
@@ -71,6 +71,7 @@ struct xgene_gstrings_stats {
XGENE_EXTD_STAT(rx_oversize_pkt_cntr, ROVR, 16),
XGENE_EXTD_STAT(rx_fragments_cntr, RFRG, 16),
XGENE_EXTD_STAT(rx_jabber_cntr, RJBR, 16),
+   XGENE_EXTD_STAT(rx_jabber_recov_cntr, DUMP, 0),
XGENE_EXTD_STAT(rx_dropped_pkt_cntr, RDRP, 16),
XGENE_EXTD_STAT(rx_overrun_cntr, DUMP, 0),
XGENE_EXTD_STAT(tx_multicast_pkt_cntr, TMCA, 31),
@@ -96,9 +97,16 @@ struct xgene_gstrings_stats {
 
 #define XGENE_STATS_LENARRAY_SIZE(gstrings_stats)
 #define XGENE_EXTD_STATS_LEN   ARRAY_SIZE(gstrings_extd_stats)
+#define RFCS_IDX   7
+#define RALN_IDX   13
+#define RFLR_IDX   14
 #define FALSE_RFLR_IDX 15
-#define RX_OVERRUN_IDX 23
-#define TX_UNDERRUN_IDX42
+#define RUND_IDX   18
+#define FALSE_RJBR_IDX 22
+#define RX_OVERRUN_IDX 24
+#define TFCS_IDX   38
+#define TFRG_IDX   42
+#define TX_UNDERRUN_IDX43
 
 static void xgene_get_drvinfo(struct net_device *ndev,
  struct ethtool_drvinfo *info)
@@ -218,14 +226,25 @@ static int xgene_get_sset_count(struct net_device *ndev, 
int sset)
 static void xgene_get_extd_stats(struct xgene_enet_pdata *pdata)
 {
u32 rx_drop, tx_drop;
-   u32 tmp;
+   u32 mask, tmp;
int i;
 
for (i = 0; i < XGENE_EXTD_STATS_LEN; i++) {
tmp = xgene_enet_rd_stat(pdata, gstrings_extd_stats[i].addr);
-   if (gstrings_extd_stats[i].mask)
-   pdata->extd_stats[i] += tmp &
-   GENMASK(gstrings_extd_stats[i].mask - 1, 0);
+   if (gstrings_extd_stats[i].mask) {
+   mask = GENMASK(gstrings_extd_stats[i].mask - 1, 0);
+   pdata->extd_stats[i] += (tmp & mask);
+   }
+   }
+
+   if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) {
+   /* Errata 10GE_10 - SW should intepret RALN as 0 */
+   pdata->extd_stats[RALN_IDX] = 0;
+   } else {
+   /* Errata ENET_15 - Fixes RFCS, RFLR, TFCS counter */
+   pdata->extd_stats[RFCS_IDX] -= pdata->extd_stats[RALN_IDX];
+   pdata->extd_stats[RFLR_IDX] -= pdata->extd_stats[RUND_IDX];
+   pdata->extd_stats[TFCS_IDX] -= pdata->extd_stats[TFRG_IDX];
}
 
pdata->mac_ops->get_drop_cnt(pdata, _drop, _drop);
@@ -234,6 +253,8 @@ static void xgene_get_extd_stats(struct xgene_enet_pdata 
*pdata)
 
/* Errata 10GE_8 -  Update Frame recovered from Errata 10GE_8/ENET_11 */
pdata->extd_stats[FALSE_RFLR_IDX] = pdata->false_rflr;
+   /* Errata ENET_15 - Jabber Frame recov'ed from Errata 10GE_10/ENET_15 */
+   pdata->extd_stats[FALSE_RJBR_IDX] = pdata->vlan_rjbr;
 }
 
 int xgene_extd_stats_init(struct xgene_enet_pdata *pdata)
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index c2d38da..01e389d 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -656,6 +656,18 @@ static void xgene_enet_free_pagepool(struct 
xgene_enet_desc_ring *buf_pool,
buf_pool->head = head;
 }
 
+/* Errata 10GE_10 and ENET_15 - Fix duplicated HW statistic counters */
+static bool xgene_enet_errata_10GE_10(struct sk_buff *skb, u32 len, u8 status)
+{
+   if (status == INGRESS_CRC &&
+   len >= (ETHER_STD_PACKET + 1) &&
+   len <= (ETHER_STD_PACKET + 4) &&
+   skb->protocol == htons(ETH_P_8021Q))
+   return true;
+
+   return false;
+}
+
 /* Errata 10GE_8 and ENET_11 - allow packet with length <=64B */
 static bool xgene_enet_errata_10GE_8(struct sk_buff *skb, u32 len, u8 status)
 {
@@ -706,14 +718,16 @@ static int xgene_enet_rx_frame(struct 
xgene_enet

[PATCH v2 net-next 08/12] drivers: net: xgene: Add rx_overrun/tx_underrun statistics

2017-05-10 Thread Iyappan Subramanian
This patch adds rx_overrun and tx_underrun ethtool statistic counters.

Signed-off-by: Quan Nguyen <qngu...@apm.com>
Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c | 16 +---
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.c  | 11 +++
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.h  |  8 
 drivers/net/ethernet/apm/xgene/xgene_enet_main.h|  1 +
 drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c   | 14 ++
 drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c   | 11 +++
 drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h   |  4 
 7 files changed, 62 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
index a7eed3b..6b2a4b9 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
@@ -71,6 +71,7 @@ struct xgene_gstrings_stats {
XGENE_EXTD_STAT(rx_fragments_cntr, RFRG, 16),
XGENE_EXTD_STAT(rx_jabber_cntr, RJBR, 16),
XGENE_EXTD_STAT(rx_dropped_pkt_cntr, RDRP, 16),
+   XGENE_EXTD_STAT(rx_overrun_cntr, DUMP, 0),
XGENE_EXTD_STAT(tx_multicast_pkt_cntr, TMCA, 31),
XGENE_EXTD_STAT(tx_broadcast_pkt_cntr, TBCA, 31),
XGENE_EXTD_STAT(tx_pause_ctrl_frame_cntr, TXPF, 16),
@@ -88,11 +89,14 @@ struct xgene_gstrings_stats {
XGENE_EXTD_STAT(tx_ctrl_frame_cntr, TXCF, 12),
XGENE_EXTD_STAT(tx_oversize_frame_cntr, TOVR, 12),
XGENE_EXTD_STAT(tx_undersize_frame_cntr, TUND, 12),
-   XGENE_EXTD_STAT(tx_fragments_cntr, TFRG, 12)
+   XGENE_EXTD_STAT(tx_fragments_cntr, TFRG, 12),
+   XGENE_EXTD_STAT(tx_underrun_cntr, DUMP, 0)
 };
 
 #define XGENE_STATS_LENARRAY_SIZE(gstrings_stats)
 #define XGENE_EXTD_STATS_LEN   ARRAY_SIZE(gstrings_extd_stats)
+#define RX_OVERRUN_IDX 22
+#define TX_UNDERRUN_IDX41
 
 static void xgene_get_drvinfo(struct net_device *ndev,
  struct ethtool_drvinfo *info)
@@ -211,14 +215,20 @@ static int xgene_get_sset_count(struct net_device *ndev, 
int sset)
 
 static void xgene_get_extd_stats(struct xgene_enet_pdata *pdata)
 {
+   u32 rx_drop, tx_drop;
u32 tmp;
int i;
 
for (i = 0; i < XGENE_EXTD_STATS_LEN; i++) {
tmp = xgene_enet_rd_stat(pdata, gstrings_extd_stats[i].addr);
-   pdata->extd_stats[i] += tmp &
-   GENMASK(gstrings_extd_stats[i].mask - 1, 0);
+   if (gstrings_extd_stats[i].mask)
+   pdata->extd_stats[i] += tmp &
+   GENMASK(gstrings_extd_stats[i].mask - 1, 0);
}
+
+   pdata->mac_ops->get_drop_cnt(pdata, _drop, _drop);
+   pdata->extd_stats[RX_OVERRUN_IDX] += rx_drop;
+   pdata->extd_stats[TX_UNDERRUN_IDX] += tx_drop;
 }
 
 int xgene_extd_stats_init(struct xgene_enet_pdata *pdata)
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
index 9e89193..5278d62 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
@@ -618,6 +618,16 @@ static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
xgene_enet_wr_csr(pdata, CFG_BYPASS_ADDR, RESUME_TX);
 }
 
+static void xgene_gmac_get_drop_cnt(struct xgene_enet_pdata *pdata,
+   u32 *rx, u32 *tx)
+{
+   u32 count;
+
+   xgene_enet_rd_mcx_csr(pdata, ICM_ECM_DROP_COUNT_REG0_ADDR, );
+   *rx = ICM_DROP_COUNT(count);
+   *tx = ECM_DROP_COUNT(count);
+}
+
 static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *pdata)
 {
u32 val = 0x;
@@ -1027,6 +1037,7 @@ void xgene_enet_mdio_remove(struct xgene_enet_pdata 
*pdata)
.tx_enable = xgene_gmac_tx_enable,
.rx_disable = xgene_gmac_rx_disable,
.tx_disable = xgene_gmac_tx_disable,
+   .get_drop_cnt = xgene_gmac_get_drop_cnt,
.set_speed = xgene_gmac_set_speed,
.set_mac_addr = xgene_gmac_set_mac_addr,
.set_framesize = xgene_enet_set_frame_size,
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h 
b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
index f1a4cfa..5d3e18d 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
@@ -192,6 +192,10 @@ enum xgene_enet_rm {
 #define CFG_CLE_NXTFPSEL0(val) (((val) << 20) & GENMASK(23, 20))
 #define ICM_CONFIG0_REG_0_ADDR 0x0400
 #define ICM_CONFIG2_REG_0_ADDR 0x0410
+#define ECM_CONFIG0_REG_0_ADDR 0x0500
+#define ECM_CONFIG0_REG_1_ADDR 0x0504
+#define ICM_ECM_DROP_COUNT_REG0_ADDR   0x0508
+#define ICM_ECM_DROP_COUNT_REG1_ADDR   0x050c
 #define RX_DV_GATE_REG_0_ADDR  0x05fc
 #define TX_DV_GATE

[PATCH v2 net-next 03/12] drivers: net: xgene: Use rgmii mdio mac access

2017-05-10 Thread Iyappan Subramanian
From: Quan Nguyen <qngu...@apm.com>

This patch switches to use rgmii mdio mac access routines if available,
as they share the same HW.

Signed-off-by: Quan Nguyen <qngu...@apm.com>
Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.c | 14 ++
 1 file changed, 14 insertions(+)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
index 2050c58..47c5b75 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
@@ -277,6 +277,13 @@ void xgene_enet_wr_mac(struct xgene_enet_pdata *pdata, u32 
wr_addr, u32 wr_data)
u8 wait = 10;
u32 done;
 
+   if (pdata->mdio_driver && ndev->phydev &&
+   pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) {
+   struct mii_bus *bus = ndev->phydev->mdio.bus;
+
+   return xgene_mdio_wr_mac(bus->priv, wr_addr, wr_data);
+   }
+
addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET;
wr = pdata->mcx_mac_addr + MAC_WRITE_REG_OFFSET;
cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET;
@@ -328,6 +335,13 @@ u32 xgene_enet_rd_mac(struct xgene_enet_pdata *pdata, u32 
rd_addr)
u32 done, rd_data;
u8 wait = 10;
 
+   if (pdata->mdio_driver && pdata->ndev->phydev &&
+   pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) {
+   struct mii_bus *bus = pdata->ndev->phydev->mdio.bus;
+
+   return xgene_mdio_rd_mac(bus->priv, rd_addr);
+   }
+
addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET;
rd = pdata->mcx_mac_addr + MAC_READ_REG_OFFSET;
cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET;
-- 
1.9.1



[PATCH v2 net-next 10/12] drivers: net: xgene: Add frame recovered statistics counter for errata 10GE_8/ENET_11

2017-05-10 Thread Iyappan Subramanian
From: Quan Nguyen <qngu...@apm.com>

This patch adds statistic counter for frames recovered from HW errata
10GE_8 and ENET_11:
"HW reports Length error for valid 64 byte frames with len <46 bytes".

Signed-off-by: Quan Nguyen <qngu...@apm.com>
Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c | 9 +++--
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c| 2 ++
 drivers/net/ethernet/apm/xgene/xgene_enet_main.h| 1 +
 3 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
index 6b2a4b9..5c2c84a 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
@@ -64,6 +64,7 @@ struct xgene_gstrings_stats {
XGENE_EXTD_STAT(rx_unk_opcode_cntr, RXUO, 16),
XGENE_EXTD_STAT(rx_align_err_cntr, RALN, 16),
XGENE_EXTD_STAT(rx_frame_len_err_cntr, RFLR, 16),
+   XGENE_EXTD_STAT(rx_frame_len_err_recov_cntr, DUMP, 0),
XGENE_EXTD_STAT(rx_code_err_cntr, RCDE, 16),
XGENE_EXTD_STAT(rx_carrier_sense_err_cntr, RCSE, 16),
XGENE_EXTD_STAT(rx_undersize_pkt_cntr, RUND, 16),
@@ -95,8 +96,9 @@ struct xgene_gstrings_stats {
 
 #define XGENE_STATS_LENARRAY_SIZE(gstrings_stats)
 #define XGENE_EXTD_STATS_LEN   ARRAY_SIZE(gstrings_extd_stats)
-#define RX_OVERRUN_IDX 22
-#define TX_UNDERRUN_IDX41
+#define FALSE_RFLR_IDX 15
+#define RX_OVERRUN_IDX 23
+#define TX_UNDERRUN_IDX42
 
 static void xgene_get_drvinfo(struct net_device *ndev,
  struct ethtool_drvinfo *info)
@@ -229,6 +231,9 @@ static void xgene_get_extd_stats(struct xgene_enet_pdata 
*pdata)
pdata->mac_ops->get_drop_cnt(pdata, _drop, _drop);
pdata->extd_stats[RX_OVERRUN_IDX] += rx_drop;
pdata->extd_stats[TX_UNDERRUN_IDX] += tx_drop;
+
+   /* Errata 10GE_8 -  Update Frame recovered from Errata 10GE_8/ENET_11 */
+   pdata->extd_stats[FALSE_RFLR_IDX] = pdata->false_rflr;
 }
 
 int xgene_extd_stats_init(struct xgene_enet_pdata *pdata)
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index bd2486e..c2d38da 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -712,6 +712,8 @@ static int xgene_enet_rx_frame(struct xgene_enet_desc_ring 
*rx_ring,
xgene_enet_parse_error(rx_ring, status);
rx_ring->rx_dropped++;
goto out;
+   } else {
+   pdata->false_rflr++;
}
}
 
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h 
b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
index cabe54e..0f5f0b0 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
@@ -224,6 +224,7 @@ struct xgene_enet_pdata {
enum xgene_enet_rm rm;
struct xgene_enet_cle cle;
u64 *extd_stats;
+   u64 false_rflr;
spinlock_t stats_lock; /* statistics lock */
const struct xgene_mac_ops *mac_ops;
spinlock_t mac_lock; /* mac lock */
-- 
1.9.1



[PATCH v2 net-next 05/12] drivers: net: xgene: Refactor statistics error parsing code

2017-05-10 Thread Iyappan Subramanian
From: Quan Nguyen <qngu...@apm.com>

This patch fixes the tx error counters and adds more rx error counters.

Signed-off-by: Quan Nguyen <qngu...@apm.com>
Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.c   |  6 --
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.h   |  2 --
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 26 +++-
 drivers/net/ethernet/apm/xgene/xgene_enet_main.h |  2 ++
 4 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
index 47c5b75..02df577 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
@@ -205,30 +205,24 @@ static u32 xgene_enet_ring_len(struct 
xgene_enet_desc_ring *ring)
 }
 
 void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring,
-   struct xgene_enet_pdata *pdata,
enum xgene_enet_err_code status)
 {
switch (status) {
case INGRESS_CRC:
ring->rx_crc_errors++;
-   ring->rx_dropped++;
break;
case INGRESS_CHECKSUM:
case INGRESS_CHECKSUM_COMPUTE:
ring->rx_errors++;
-   ring->rx_dropped++;
break;
case INGRESS_TRUNC_FRAME:
ring->rx_frame_errors++;
-   ring->rx_dropped++;
break;
case INGRESS_PKT_LEN:
ring->rx_length_errors++;
-   ring->rx_dropped++;
break;
case INGRESS_PKT_UNDER:
ring->rx_frame_errors++;
-   ring->rx_dropped++;
break;
case INGRESS_FIFO_OVERRUN:
ring->rx_fifo_errors++;
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h 
b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
index 057f951..3ce349f 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
@@ -380,9 +380,7 @@ static inline u16 xgene_enet_get_numslots(u16 id, u32 size)
 }
 
 void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring,
-   struct xgene_enet_pdata *pdata,
enum xgene_enet_err_code status);
-
 int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata);
 void xgene_enet_mdio_remove(struct xgene_enet_pdata *pdata);
 bool xgene_ring_mgr_init(struct xgene_enet_pdata *p);
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index e4f2ef2..3f24b83 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -246,9 +246,9 @@ static int xgene_enet_tx_completion(struct 
xgene_enet_desc_ring *cp_ring,
skb_frag_t *frag;
dma_addr_t *frag_dma_addr;
u16 skb_index;
-   u8 status;
-   int i, ret = 0;
u8 mss_index;
+   u8 status;
+   int i;
 
skb_index = GET_VAL(USERINFO, le64_to_cpu(raw_desc->m0));
skb = cp_ring->cp_skb[skb_index];
@@ -275,19 +275,17 @@ static int xgene_enet_tx_completion(struct 
xgene_enet_desc_ring *cp_ring,
/* Checking for error */
status = GET_VAL(LERR, le64_to_cpu(raw_desc->m0));
if (unlikely(status > 2)) {
-   xgene_enet_parse_error(cp_ring, netdev_priv(cp_ring->ndev),
-  status);
-   ret = -EIO;
+   cp_ring->tx_dropped++;
+   cp_ring->tx_errors++;
}
 
if (likely(skb)) {
dev_kfree_skb_any(skb);
} else {
netdev_err(cp_ring->ndev, "completion skb is NULL\n");
-   ret = -EIO;
}
 
-   return ret;
+   return 0;
 }
 
 static int xgene_enet_setup_mss(struct net_device *ndev, u32 mss)
@@ -711,7 +709,8 @@ static int xgene_enet_rx_frame(struct xgene_enet_desc_ring 
*rx_ring,
if (!xgene_enet_errata_10GE_8(skb, datalen, status)) {
dev_kfree_skb_any(skb);
xgene_enet_free_pagepool(page_pool, raw_desc, exp_desc);
-   xgene_enet_parse_error(rx_ring, pdata, status);
+   xgene_enet_parse_error(rx_ring, status);
+   rx_ring->rx_dropped++;
goto out;
}
}
@@ -1477,6 +1476,8 @@ static void xgene_enet_get_stats64(
if (ring) {
stats->tx_packets += ring->tx_packets;
stats->tx_bytes += ring->tx_bytes;
+   stats->tx_dropped += ring->tx_dropped;
+   stats->tx_errors += ring->tx_errors;
}
}
 
@@ -1485,11 +1486,16 @@ s

[PATCH v2 net-next 04/12] drivers: net: xgene: Remove redundant local stats

2017-05-10 Thread Iyappan Subramanian
From: Quan Nguyen <qngu...@apm.com>

Commit 5944701df90d ("net: remove useless memset's in drivers get_stats64")
makes the pdata->stats redundant. This patch removes pdata->stats and
updates get_stats64() callback accordingly.

Signed-off-by: Quan Nguyen <qngu...@apm.com>
Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c | 7 ---
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c| 4 +---
 drivers/net/ethernet/apm/xgene/xgene_enet_main.h| 1 -
 3 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
index 28fdedc..217cde8 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
@@ -25,7 +25,7 @@ struct xgene_gstrings_stats {
int offset;
 };
 
-#define XGENE_STAT(m) { #m, offsetof(struct xgene_enet_pdata, stats.m) }
+#define XGENE_STAT(m) { #m, offsetof(struct rtnl_link_stats64, m) }
 
 static const struct xgene_gstrings_stats gstrings_stats[] = {
XGENE_STAT(rx_packets),
@@ -156,11 +156,12 @@ static void xgene_get_ethtool_stats(struct net_device 
*ndev,
struct ethtool_stats *dummy,
u64 *data)
 {
-   void *pdata = netdev_priv(ndev);
+   struct rtnl_link_stats64 stats;
int i;
 
+   dev_get_stats(ndev, );
for (i = 0; i < XGENE_STATS_LEN; i++)
-   *data++ = *(u64 *)(pdata + gstrings_stats[i].offset);
+   data[i] = *(u64 *)((char *) + gstrings_stats[i].offset);
 }
 
 static void xgene_get_pauseparam(struct net_device *ndev,
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index 9a28ac3..e4f2ef2 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -1466,10 +1466,9 @@ static int xgene_enet_create_desc_rings(struct 
net_device *ndev)
 
 static void xgene_enet_get_stats64(
struct net_device *ndev,
-   struct rtnl_link_stats64 *storage)
+   struct rtnl_link_stats64 *stats)
 {
struct xgene_enet_pdata *pdata = netdev_priv(ndev);
-   struct rtnl_link_stats64 *stats = >stats;
struct xgene_enet_desc_ring *ring;
int i;
 
@@ -1493,7 +1492,6 @@ static void xgene_enet_get_stats64(
stats->rx_dropped += ring->rx_dropped;
}
}
-   memcpy(storage, stats, sizeof(struct rtnl_link_stats64));
 }
 
 static int xgene_enet_set_mac_address(struct net_device *ndev, void *addr)
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h 
b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
index 827b33d..5e6fd71 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
@@ -219,7 +219,6 @@ struct xgene_enet_pdata {
int phy_mode;
enum xgene_enet_rm rm;
struct xgene_enet_cle cle;
-   struct rtnl_link_stats64 stats;
const struct xgene_mac_ops *mac_ops;
spinlock_t mac_lock; /* mac lock */
const struct xgene_port_ops *port_ops;
-- 
1.9.1



[PATCH v2 net-next 09/12] drivers: net: xgene: Workaround for HW errata 10GE_4

2017-05-10 Thread Iyappan Subramanian
From: Quan Nguyen <qngu...@apm.com>

This patch adds workaround for HW errata 10GE_4:
"XGENET_ICM_ECM_DROP_COUNT_REG_0 reg not clear on read".

Signed-off-by: Quan Nguyen <qngu...@apm.com>
Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.c| 2 ++
 drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c | 5 +
 drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c | 2 ++
 3 files changed, 9 insertions(+)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
index 5278d62..3235d0c 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
@@ -626,6 +626,8 @@ static void xgene_gmac_get_drop_cnt(struct xgene_enet_pdata 
*pdata,
xgene_enet_rd_mcx_csr(pdata, ICM_ECM_DROP_COUNT_REG0_ADDR, );
*rx = ICM_DROP_COUNT(count);
*tx = ECM_DROP_COUNT(count);
+   /* Errata: 10GE_4 - Fix ICM_ECM_DROP_COUNT not clear-on-read */
+   xgene_enet_rd_mcx_csr(pdata, ECM_CONFIG0_REG_0_ADDR, );
 }
 
 static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *pdata)
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
index 2919d3e..31df8f3 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
@@ -106,6 +106,11 @@ static void xgene_sgmac_get_drop_cnt(struct 
xgene_enet_pdata *pdata,
count = xgene_enet_rd_mcx_csr(pdata, addr);
*rx = ICM_DROP_COUNT(count);
*tx = ECM_DROP_COUNT(count);
+   /* Errata: 10GE_4 - ICM_ECM_DROP_COUNT not clear-on-read */
+   addr = (pdata->enet_id != XGENE_ENET1) ?
+   XG_MCX_ECM_CONFIG0_REG_0_ADDR :
+   ECM_CONFIG0_REG_0_ADDR + pdata->port_id * OFFSET_4;
+   xgene_enet_rd_mcx_csr(pdata, addr);
 }
 
 static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *p)
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
index 56dff38..eab6f1c 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
@@ -188,6 +188,8 @@ static void xgene_xgmac_get_drop_cnt(struct 
xgene_enet_pdata *pdata,
xgene_enet_rd_axg_csr(pdata, XGENET_ICM_ECM_DROP_COUNT_REG0, );
*rx = ICM_DROP_COUNT(count);
*tx = ECM_DROP_COUNT(count);
+   /* Errata: 10GE_4 - ICM_ECM_DROP_COUNT not clear-on-read */
+   xgene_enet_rd_axg_csr(pdata, XGENET_ECM_CONFIG0_REG_0, );
 }
 
 static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *pdata)
-- 
1.9.1



Re: [PATCH net-next 1/9] drivers: net: xgene: Protect indirect MAC access

2017-04-26 Thread Iyappan Subramanian
On Wed, Apr 26, 2017 at 5:06 PM, Florian Fainelli <f.faine...@gmail.com> wrote:
> On 04/26/2017 04:38 PM, Iyappan Subramanian wrote:
>> From: Quan Nguyen <qngu...@apm.com>
>>
>> This patch adds lock to protect indirect mac access sequence.
>>
>> Signed-off-by: Quan Nguyen <qngu...@apm.com>
>> Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
>> ---
>>  drivers/net/ethernet/apm/xgene/xgene_enet_hw.c| 2 ++
>>  drivers/net/ethernet/apm/xgene/xgene_enet_main.c  | 1 +
>>  drivers/net/ethernet/apm/xgene/xgene_enet_main.h  | 1 +
>>  drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c | 7 ++-
>>  drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c | 2 ++
>>  5 files changed, 12 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c 
>> b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
>> index 2a835e0..3697ba7 100644
>> --- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
>> +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
>> @@ -365,9 +365,11 @@ static void xgene_enet_rd_mcx_mac(struct 
>> xgene_enet_pdata *pdata,
>>   cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET;
>>   cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET;
>>
>> + spin_lock(>mac_lock);
>>   if (!xgene_enet_rd_indirect(addr, rd, cmd, cmd_done, rd_addr, rd_data))
>>   netdev_err(pdata->ndev, "MCX mac read failed, addr: %04x\n",
>>  rd_addr);
>> + spin_unlock(>mac_lock);
>
> Why not fold the spinlock manipulation within xgenet_enet_rd_indirect()?
> That way the caller does not have to know that acquiring the spinlock is
> required and you avoid potential bugs in the future where you are
> missing the spinlock on indirect accesses?

Thanks.  We'll do that and post the next version.

> --
> Florian


[PATCH net-next 7/9] drivers: net: xgene: Workaround for HW errata 10GE_4

2017-04-26 Thread Iyappan Subramanian
From: Quan Nguyen <qngu...@apm.com>

This patch adds workaround for HW errata 10GE_4:
"XGENET_ICM_ECM_DROP_COUNT_REG_0 reg not clear on read".

Signed-off-by: Quan Nguyen <qngu...@apm.com>
Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.c| 2 ++
 drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c | 5 +
 drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c | 2 ++
 3 files changed, 9 insertions(+)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
index f79eb78..60b1a07 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
@@ -623,6 +623,8 @@ static void xgene_gmac_get_drop_cnt(struct xgene_enet_pdata 
*pdata,
xgene_enet_rd_mcx_csr(pdata, ICM_ECM_DROP_COUNT_REG0_ADDR, );
*rx = ICM_DROP_COUNT(count);
*tx = ECM_DROP_COUNT(count);
+   /* Errata: 10GE_4 - Fix ICM_ECM_DROP_COUNT not clear-on-read */
+   xgene_enet_rd_mcx_csr(pdata, ECM_CONFIG0_REG_0_ADDR, );
 }
 
 static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *pdata)
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
index b253069..ca1f723 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
@@ -197,6 +197,11 @@ static void xgene_sgmac_get_drop_cnt(struct 
xgene_enet_pdata *pdata,
count = xgene_enet_rd_mcx_csr(pdata, addr);
*rx = ICM_DROP_COUNT(count);
*tx = ECM_DROP_COUNT(count);
+   /* Errata: 10GE_4 - ICM_ECM_DROP_COUNT not clear-on-read */
+   addr = (pdata->enet_id != XGENE_ENET1) ?
+   XG_MCX_ECM_CONFIG0_REG_0_ADDR :
+   ECM_CONFIG0_REG_0_ADDR + pdata->port_id * OFFSET_4;
+   xgene_enet_rd_mcx_csr(pdata, addr);
 }
 
 static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *p)
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
index a317596..3e4cd79 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
@@ -239,6 +239,8 @@ static void xgene_xgmac_get_drop_cnt(struct 
xgene_enet_pdata *pdata,
xgene_enet_rd_axg_csr(pdata, XGENET_ICM_ECM_DROP_COUNT_REG0, );
*rx = ICM_DROP_COUNT(count);
*tx = ECM_DROP_COUNT(count);
+   /* Errata: 10GE_4 - ICM_ECM_DROP_COUNT not clear-on-read */
+   xgene_enet_rd_axg_csr(pdata, XGENET_ECM_CONFIG0_REG_0, );
 }
 
 static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *pdata)
-- 
1.9.1



[PATCH net-next 9/9] drivers: net: xgene: Workaround for HW errata 10GE_10/ENET_15

2017-04-26 Thread Iyappan Subramanian
From: Quan Nguyen <qngu...@apm.com>

This patch adds workaround for HW errata 10GE_10 and ENET_15:
"HW statistic counters value are duplicated".

- RFCS duplicates RALN counter
- RFLR duplicates RUND counter
- TFCS duplicates TFRG counter
- RALN should be intepreted as 0 in 10G mode

Signed-off-by: Quan Nguyen <qngu...@apm.com>
Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
 .../net/ethernet/apm/xgene/xgene_enet_ethtool.c| 30 ++
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c   | 20 ---
 drivers/net/ethernet/apm/xgene/xgene_enet_main.h   |  2 ++
 3 files changed, 44 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
index 5e8660e..8d9ed2b 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
@@ -71,6 +71,7 @@ struct xgene_gstrings_stats {
XGENE_EXTD_STAT(rx_oversize_pkt_cntr, ROVR, 16),
XGENE_EXTD_STAT(rx_fragments_cntr, RFRG, 16),
XGENE_EXTD_STAT(rx_jabber_cntr, RJBR, 16),
+   XGENE_EXTD_STAT(rx_jabber_recov_cntr, DUMP, 0),
XGENE_EXTD_STAT(rx_dropped_pkt_cntr, RDRP, 16),
XGENE_EXTD_STAT(rx_overrun_cntr, DUMP, 0),
XGENE_EXTD_STAT(tx_multicast_pkt_cntr, TMCA, 31),
@@ -96,9 +97,16 @@ struct xgene_gstrings_stats {
 
 #define XGENE_STATS_LENARRAY_SIZE(gstrings_stats)
 #define XGENE_EXTD_STATS_LEN   ARRAY_SIZE(gstrings_extd_stats)
+#define RFCS_IDX   7
+#define RALN_IDX   13
+#define RFLR_IDX   14
 #define FALSE_RFLR_IDX 15
-#define RX_OVERRUN_IDX 23
-#define TX_UNDERRUN_IDX42
+#define RUND_IDX   18
+#define FALSE_RJBR_IDX 22
+#define RX_OVERRUN_IDX 24
+#define TFCS_IDX   38
+#define TFRG_IDX   42
+#define TX_UNDERRUN_IDX43
 
 static void xgene_get_drvinfo(struct net_device *ndev,
  struct ethtool_drvinfo *info)
@@ -217,24 +225,36 @@ static int xgene_get_sset_count(struct net_device *ndev, 
int sset)
 
 static void xgene_get_extd_stats(struct xgene_enet_pdata *pdata)
 {
+   u32 tmp[XGENE_EXTD_STATS_LEN];
u32 rx_drop, tx_drop;
-   u32 tmp;
int i;
 
for (i = 0; i < XGENE_EXTD_STATS_LEN; i++) {
pdata->mac_ops->read_stats(pdata,
-  gstrings_extd_stats[i].addr, );
+   gstrings_extd_stats[i].addr, [i]);
if (gstrings_extd_stats[i].mask)
-   pdata->extd_stats[i] += tmp &
+   pdata->extd_stats[i] += tmp[i] &
GENMASK(gstrings_extd_stats[i].mask - 1, 0);
}
 
+   if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) {
+   /* Errata 10GE_10 - SW should intepret RALN as 0 */
+   pdata->extd_stats[RALN_IDX] = 0;
+   } else {
+   /* Errata ENET_15 - Fixes RFCS, RFLR, TFCS counter */
+   pdata->extd_stats[RFCS_IDX] -= tmp[RALN_IDX];
+   pdata->extd_stats[RFLR_IDX] -= tmp[RUND_IDX];
+   pdata->extd_stats[TFCS_IDX] -= tmp[TFRG_IDX];
+   }
+
pdata->mac_ops->get_drop_cnt(pdata, _drop, _drop);
pdata->extd_stats[RX_OVERRUN_IDX] += rx_drop;
pdata->extd_stats[TX_UNDERRUN_IDX] += tx_drop;
 
/* Errata 10GE_8 -  Update Frame recovered from Errata 10GE_8/ENET_11 */
pdata->extd_stats[FALSE_RFLR_IDX] = pdata->false_rflr;
+   /* Errata ENET_15 - Jabber Frame recov'ed from Errata 10GE_10/ENET_15 */
+   pdata->extd_stats[FALSE_RJBR_IDX] = pdata->vlan_rjbr;
 }
 
 int xgene_extd_stats_init(struct xgene_enet_pdata *pdata)
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index c2d38da..01e389d 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -656,6 +656,18 @@ static void xgene_enet_free_pagepool(struct 
xgene_enet_desc_ring *buf_pool,
buf_pool->head = head;
 }
 
+/* Errata 10GE_10 and ENET_15 - Fix duplicated HW statistic counters */
+static bool xgene_enet_errata_10GE_10(struct sk_buff *skb, u32 len, u8 status)
+{
+   if (status == INGRESS_CRC &&
+   len >= (ETHER_STD_PACKET + 1) &&
+   len <= (ETHER_STD_PACKET + 4) &&
+   skb->protocol == htons(ETH_P_8021Q))
+   return true;
+
+   return false;
+}
+
 /* Errata 10GE_8 and ENET_11 - allow packet with length <=64B */
 static bool xgene_enet_errata_10GE_8(struct sk_buff *skb, u32 len, u8 status)
 {
@@ -706,14 +718,16 @@ static int xgene_enet_rx_frame(struct 
xgene_enet_desc_ring *rx_ring,
  

[PATCH net-next 6/9] drivers: net: xgene: Add rx_overrun/tx_underrun statistic

2017-04-26 Thread Iyappan Subramanian
From: Quan Nguyen <qngu...@apm.com>

This patch adds rx_overrun and tx_underrun ethtool statistic counters.

Signed-off-by: Quan Nguyen <qngu...@apm.com>
Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c | 16 +---
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.c  | 11 +++
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.h  |  8 
 drivers/net/ethernet/apm/xgene/xgene_enet_main.h|  1 +
 drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c   | 14 ++
 drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c   | 11 +++
 drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h   |  4 
 7 files changed, 62 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
index bbc90b6..369658b 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
@@ -71,6 +71,7 @@ struct xgene_gstrings_stats {
XGENE_EXTD_STAT(rx_fragments_cntr, RFRG, 16),
XGENE_EXTD_STAT(rx_jabber_cntr, RJBR, 16),
XGENE_EXTD_STAT(rx_dropped_pkt_cntr, RDRP, 16),
+   XGENE_EXTD_STAT(rx_overrun_cntr, DUMP, 0),
XGENE_EXTD_STAT(tx_multicast_pkt_cntr, TMCA, 31),
XGENE_EXTD_STAT(tx_broadcast_pkt_cntr, TBCA, 31),
XGENE_EXTD_STAT(tx_pause_ctrl_frame_cntr, TXPF, 16),
@@ -88,11 +89,14 @@ struct xgene_gstrings_stats {
XGENE_EXTD_STAT(tx_ctrl_frame_cntr, TXCF, 12),
XGENE_EXTD_STAT(tx_oversize_frame_cntr, TOVR, 12),
XGENE_EXTD_STAT(tx_undersize_frame_cntr, TUND, 12),
-   XGENE_EXTD_STAT(tx_fragments_cntr, TFRG, 12)
+   XGENE_EXTD_STAT(tx_fragments_cntr, TFRG, 12),
+   XGENE_EXTD_STAT(tx_underrun_cntr, DUMP, 0)
 };
 
 #define XGENE_STATS_LENARRAY_SIZE(gstrings_stats)
 #define XGENE_EXTD_STATS_LEN   ARRAY_SIZE(gstrings_extd_stats)
+#define RX_OVERRUN_IDX 22
+#define TX_UNDERRUN_IDX41
 
 static void xgene_get_drvinfo(struct net_device *ndev,
  struct ethtool_drvinfo *info)
@@ -211,15 +215,21 @@ static int xgene_get_sset_count(struct net_device *ndev, 
int sset)
 
 static void xgene_get_extd_stats(struct xgene_enet_pdata *pdata)
 {
+   u32 rx_drop, tx_drop;
u32 tmp;
int i;
 
for (i = 0; i < XGENE_EXTD_STATS_LEN; i++) {
pdata->mac_ops->read_stats(pdata,
   gstrings_extd_stats[i].addr, );
-   pdata->extd_stats[i] += tmp &
-   GENMASK(gstrings_extd_stats[i].mask - 1, 0);
+   if (gstrings_extd_stats[i].mask)
+   pdata->extd_stats[i] += tmp &
+   GENMASK(gstrings_extd_stats[i].mask - 1, 0);
}
+
+   pdata->mac_ops->get_drop_cnt(pdata, _drop, _drop);
+   pdata->extd_stats[RX_OVERRUN_IDX] += rx_drop;
+   pdata->extd_stats[TX_UNDERRUN_IDX] += tx_drop;
 }
 
 int xgene_extd_stats_init(struct xgene_enet_pdata *pdata)
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
index ec5f61f..f79eb78 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
@@ -615,6 +615,16 @@ static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
xgene_enet_wr_csr(pdata, CFG_BYPASS_ADDR, RESUME_TX);
 }
 
+static void xgene_gmac_get_drop_cnt(struct xgene_enet_pdata *pdata,
+   u32 *rx, u32 *tx)
+{
+   u32 count;
+
+   xgene_enet_rd_mcx_csr(pdata, ICM_ECM_DROP_COUNT_REG0_ADDR, );
+   *rx = ICM_DROP_COUNT(count);
+   *tx = ECM_DROP_COUNT(count);
+}
+
 static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *pdata)
 {
u32 val = 0x;
@@ -1025,6 +1035,7 @@ void xgene_enet_mdio_remove(struct xgene_enet_pdata 
*pdata)
.rx_disable = xgene_gmac_rx_disable,
.tx_disable = xgene_gmac_tx_disable,
.read_stats = xgene_enet_rd_mcx_stats,
+   .get_drop_cnt = xgene_gmac_get_drop_cnt,
.set_speed = xgene_gmac_set_speed,
.set_mac_addr = xgene_gmac_set_mac_addr,
.set_framesize = xgene_enet_set_frame_size,
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h 
b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
index 9130c05..c5672df 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
@@ -192,6 +192,10 @@ enum xgene_enet_rm {
 #define CFG_CLE_NXTFPSEL0(val) (((val) << 20) & GENMASK(23, 20))
 #define ICM_CONFIG0_REG_0_ADDR 0x0400
 #define ICM_CONFIG2_REG_0_ADDR 0x0410
+#define ECM_CONFIG0_REG_0_ADDR 0x0500
+#define ECM_CONFIG0_REG_1_ADDR 0x0504
+#define ICM_ECM_DROP_COUNT_REG0_ADDR   0x0508
+#define ICM_E

[PATCH net-next 5/9] drivers: net: xgene: Extend ethtool statistics

2017-04-26 Thread Iyappan Subramanian
From: Quan Nguyen <qngu...@apm.com>

This patch adds extended ethtool statistics support.

Signed-off-by: Quan Nguyen <qngu...@apm.com>
Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
 .../net/ethernet/apm/xgene/xgene_enet_ethtool.c| 90 +-
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.c | 20 +
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.h | 50 
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c   |  8 ++
 drivers/net/ethernet/apm/xgene/xgene_enet_main.h   |  5 ++
 drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c  | 16 
 drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c  | 20 +
 drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h  |  1 +
 8 files changed, 209 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
index 217cde8..bbc90b6 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
@@ -23,9 +23,17 @@
 struct xgene_gstrings_stats {
char name[ETH_GSTRING_LEN];
int offset;
+   u32 addr;
+   u32 mask;
 };
 
 #define XGENE_STAT(m) { #m, offsetof(struct rtnl_link_stats64, m) }
+#define XGENE_EXTD_STAT(s, a, m)   \
+   {   \
+   .name = #s, \
+   .addr = a ## _ADDR, \
+   .mask = m   \
+   }
 
 static const struct xgene_gstrings_stats gstrings_stats[] = {
XGENE_STAT(rx_packets),
@@ -40,7 +48,51 @@ struct xgene_gstrings_stats {
XGENE_STAT(rx_fifo_errors)
 };
 
+static const struct xgene_gstrings_stats gstrings_extd_stats[] = {
+   XGENE_EXTD_STAT(tx_rx_64b_frame_cntr, TR64, 31),
+   XGENE_EXTD_STAT(tx_rx_127b_frame_cntr, TR127, 31),
+   XGENE_EXTD_STAT(tx_rx_255b_frame_cntr, TR255, 31),
+   XGENE_EXTD_STAT(tx_rx_511b_frame_cntr, TR511, 31),
+   XGENE_EXTD_STAT(tx_rx_1023b_frame_cntr, TR1K, 31),
+   XGENE_EXTD_STAT(tx_rx_1518b_frame_cntr, TRMAX, 31),
+   XGENE_EXTD_STAT(tx_rx_1522b_frame_cntr, TRMGV, 31),
+   XGENE_EXTD_STAT(rx_fcs_error_cntr, RFCS, 16),
+   XGENE_EXTD_STAT(rx_multicast_pkt_cntr, RMCA, 31),
+   XGENE_EXTD_STAT(rx_broadcast_pkt_cntr, RBCA, 31),
+   XGENE_EXTD_STAT(rx_ctrl_frame_pkt_cntr, RXCF, 16),
+   XGENE_EXTD_STAT(rx_pause_frame_pkt_cntr, RXPF, 16),
+   XGENE_EXTD_STAT(rx_unk_opcode_cntr, RXUO, 16),
+   XGENE_EXTD_STAT(rx_align_err_cntr, RALN, 16),
+   XGENE_EXTD_STAT(rx_frame_len_err_cntr, RFLR, 16),
+   XGENE_EXTD_STAT(rx_code_err_cntr, RCDE, 16),
+   XGENE_EXTD_STAT(rx_carrier_sense_err_cntr, RCSE, 16),
+   XGENE_EXTD_STAT(rx_undersize_pkt_cntr, RUND, 16),
+   XGENE_EXTD_STAT(rx_oversize_pkt_cntr, ROVR, 16),
+   XGENE_EXTD_STAT(rx_fragments_cntr, RFRG, 16),
+   XGENE_EXTD_STAT(rx_jabber_cntr, RJBR, 16),
+   XGENE_EXTD_STAT(rx_dropped_pkt_cntr, RDRP, 16),
+   XGENE_EXTD_STAT(tx_multicast_pkt_cntr, TMCA, 31),
+   XGENE_EXTD_STAT(tx_broadcast_pkt_cntr, TBCA, 31),
+   XGENE_EXTD_STAT(tx_pause_ctrl_frame_cntr, TXPF, 16),
+   XGENE_EXTD_STAT(tx_defer_pkt_cntr, TDFR, 31),
+   XGENE_EXTD_STAT(tx_excv_defer_pkt_cntr, TEDF, 31),
+   XGENE_EXTD_STAT(tx_single_col_pkt_cntr, TSCL, 31),
+   XGENE_EXTD_STAT(tx_multi_col_pkt_cntr, TMCL, 31),
+   XGENE_EXTD_STAT(tx_late_col_pkt_cntr, TLCL, 31),
+   XGENE_EXTD_STAT(tx_excv_col_pkt_cntr, TXCL, 31),
+   XGENE_EXTD_STAT(tx_total_col_cntr, TNCL, 31),
+   XGENE_EXTD_STAT(tx_pause_frames_hnrd_cntr, TPFH, 16),
+   XGENE_EXTD_STAT(tx_drop_frame_cntr, TDRP, 16),
+   XGENE_EXTD_STAT(tx_jabber_frame_cntr, TJBR, 12),
+   XGENE_EXTD_STAT(tx_fcs_error_cntr, TFCS, 12),
+   XGENE_EXTD_STAT(tx_ctrl_frame_cntr, TXCF, 12),
+   XGENE_EXTD_STAT(tx_oversize_frame_cntr, TOVR, 12),
+   XGENE_EXTD_STAT(tx_undersize_frame_cntr, TUND, 12),
+   XGENE_EXTD_STAT(tx_fragments_cntr, TFRG, 12)
+};
+
 #define XGENE_STATS_LENARRAY_SIZE(gstrings_stats)
+#define XGENE_EXTD_STATS_LEN   ARRAY_SIZE(gstrings_extd_stats)
 
 static void xgene_get_drvinfo(struct net_device *ndev,
  struct ethtool_drvinfo *info)
@@ -142,6 +194,11 @@ static void xgene_get_strings(struct net_device *ndev, u32 
stringset, u8 *data)
memcpy(p, gstrings_stats[i].name, ETH_GSTRING_LEN);
p += ETH_GSTRING_LEN;
}
+
+   for (i = 0; i < XGENE_EXTD_STATS_LEN; i++) {
+   memcpy(p, gstrings_extd_stats[i].name, ETH_GSTRING_LEN);
+   p += ETH_GSTRING_LEN;
+   }
 }
 
 static int xgene_get_sset_count(struct net_device *ndev, int sset)
@@ -149,19 +206,50 @@ static int xgene_get_sset_count(struct net_device *ndev, 
int sset)
if (sset != ETH_SS_STATS)
return -EINVAL;
 
-   return XGENE_STATS_LEN;
+   return XGENE_STATS_LEN +

[PATCH net-next 8/9] drivers: net: xgene: Add frame recovered statistics counter for errata 10GE_8/ENET_11

2017-04-26 Thread Iyappan Subramanian
From: Quan Nguyen <qngu...@apm.com>

This patch adds statistic counter for frames recovered from HW errata
10GE_8 and ENET_11:
"HW reports Length error for valid 64 byte frames with len <46 bytes".

Signed-off-by: Quan Nguyen <qngu...@apm.com>
Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c | 9 +++--
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c| 2 ++
 drivers/net/ethernet/apm/xgene/xgene_enet_main.h| 1 +
 3 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
index 369658b..5e8660e 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
@@ -64,6 +64,7 @@ struct xgene_gstrings_stats {
XGENE_EXTD_STAT(rx_unk_opcode_cntr, RXUO, 16),
XGENE_EXTD_STAT(rx_align_err_cntr, RALN, 16),
XGENE_EXTD_STAT(rx_frame_len_err_cntr, RFLR, 16),
+   XGENE_EXTD_STAT(rx_frame_len_err_recov_cntr, DUMP, 0),
XGENE_EXTD_STAT(rx_code_err_cntr, RCDE, 16),
XGENE_EXTD_STAT(rx_carrier_sense_err_cntr, RCSE, 16),
XGENE_EXTD_STAT(rx_undersize_pkt_cntr, RUND, 16),
@@ -95,8 +96,9 @@ struct xgene_gstrings_stats {
 
 #define XGENE_STATS_LENARRAY_SIZE(gstrings_stats)
 #define XGENE_EXTD_STATS_LEN   ARRAY_SIZE(gstrings_extd_stats)
-#define RX_OVERRUN_IDX 22
-#define TX_UNDERRUN_IDX41
+#define FALSE_RFLR_IDX 15
+#define RX_OVERRUN_IDX 23
+#define TX_UNDERRUN_IDX42
 
 static void xgene_get_drvinfo(struct net_device *ndev,
  struct ethtool_drvinfo *info)
@@ -230,6 +232,9 @@ static void xgene_get_extd_stats(struct xgene_enet_pdata 
*pdata)
pdata->mac_ops->get_drop_cnt(pdata, _drop, _drop);
pdata->extd_stats[RX_OVERRUN_IDX] += rx_drop;
pdata->extd_stats[TX_UNDERRUN_IDX] += tx_drop;
+
+   /* Errata 10GE_8 -  Update Frame recovered from Errata 10GE_8/ENET_11 */
+   pdata->extd_stats[FALSE_RFLR_IDX] = pdata->false_rflr;
 }
 
 int xgene_extd_stats_init(struct xgene_enet_pdata *pdata)
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index bd2486e..c2d38da 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -712,6 +712,8 @@ static int xgene_enet_rx_frame(struct xgene_enet_desc_ring 
*rx_ring,
xgene_enet_parse_error(rx_ring, status);
rx_ring->rx_dropped++;
goto out;
+   } else {
+   pdata->false_rflr++;
}
}
 
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h 
b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
index e4b7786..8afae57 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
@@ -225,6 +225,7 @@ struct xgene_enet_pdata {
enum xgene_enet_rm rm;
struct xgene_enet_cle cle;
u64 *extd_stats;
+   u64 false_rflr;
spinlock_t stats_lock; /* statistics lock */
const struct xgene_mac_ops *mac_ops;
spinlock_t mac_lock; /* mac lock */
-- 
1.9.1



[PATCH net-next 3/9] drivers: net: xgene: Refactor statistics error parsing code

2017-04-26 Thread Iyappan Subramanian
From: Quan Nguyen <qngu...@apm.com>

This patch fixes the tx error counters and adds more rx error counters.

Signed-off-by: Quan Nguyen <qngu...@apm.com>
Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.c   |  6 --
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.h   |  2 --
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 26 +++-
 drivers/net/ethernet/apm/xgene/xgene_enet_main.h |  2 ++
 4 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
index 3697ba7..06bef14 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
@@ -205,30 +205,24 @@ static u32 xgene_enet_ring_len(struct 
xgene_enet_desc_ring *ring)
 }
 
 void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring,
-   struct xgene_enet_pdata *pdata,
enum xgene_enet_err_code status)
 {
switch (status) {
case INGRESS_CRC:
ring->rx_crc_errors++;
-   ring->rx_dropped++;
break;
case INGRESS_CHECKSUM:
case INGRESS_CHECKSUM_COMPUTE:
ring->rx_errors++;
-   ring->rx_dropped++;
break;
case INGRESS_TRUNC_FRAME:
ring->rx_frame_errors++;
-   ring->rx_dropped++;
break;
case INGRESS_PKT_LEN:
ring->rx_length_errors++;
-   ring->rx_dropped++;
break;
case INGRESS_PKT_UNDER:
ring->rx_frame_errors++;
-   ring->rx_dropped++;
break;
case INGRESS_FIFO_OVERRUN:
ring->rx_fifo_errors++;
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h 
b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
index d250bfe..c6b5bbd 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
@@ -380,9 +380,7 @@ static inline u16 xgene_enet_get_numslots(u16 id, u32 size)
 }
 
 void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring,
-   struct xgene_enet_pdata *pdata,
enum xgene_enet_err_code status);
-
 int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata);
 void xgene_enet_mdio_remove(struct xgene_enet_pdata *pdata);
 bool xgene_ring_mgr_init(struct xgene_enet_pdata *p);
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index e4f2ef2..3f24b83 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -246,9 +246,9 @@ static int xgene_enet_tx_completion(struct 
xgene_enet_desc_ring *cp_ring,
skb_frag_t *frag;
dma_addr_t *frag_dma_addr;
u16 skb_index;
-   u8 status;
-   int i, ret = 0;
u8 mss_index;
+   u8 status;
+   int i;
 
skb_index = GET_VAL(USERINFO, le64_to_cpu(raw_desc->m0));
skb = cp_ring->cp_skb[skb_index];
@@ -275,19 +275,17 @@ static int xgene_enet_tx_completion(struct 
xgene_enet_desc_ring *cp_ring,
/* Checking for error */
status = GET_VAL(LERR, le64_to_cpu(raw_desc->m0));
if (unlikely(status > 2)) {
-   xgene_enet_parse_error(cp_ring, netdev_priv(cp_ring->ndev),
-  status);
-   ret = -EIO;
+   cp_ring->tx_dropped++;
+   cp_ring->tx_errors++;
}
 
if (likely(skb)) {
dev_kfree_skb_any(skb);
} else {
netdev_err(cp_ring->ndev, "completion skb is NULL\n");
-   ret = -EIO;
}
 
-   return ret;
+   return 0;
 }
 
 static int xgene_enet_setup_mss(struct net_device *ndev, u32 mss)
@@ -711,7 +709,8 @@ static int xgene_enet_rx_frame(struct xgene_enet_desc_ring 
*rx_ring,
if (!xgene_enet_errata_10GE_8(skb, datalen, status)) {
dev_kfree_skb_any(skb);
xgene_enet_free_pagepool(page_pool, raw_desc, exp_desc);
-   xgene_enet_parse_error(rx_ring, pdata, status);
+   xgene_enet_parse_error(rx_ring, status);
+   rx_ring->rx_dropped++;
goto out;
}
}
@@ -1477,6 +1476,8 @@ static void xgene_enet_get_stats64(
if (ring) {
stats->tx_packets += ring->tx_packets;
stats->tx_bytes += ring->tx_bytes;
+   stats->tx_dropped += ring->tx_dropped;
+   stats->tx_errors += ring->tx_errors;
}
}
 
@@ -1485,11 +1486,16 @@ s

[PATCH net-next 1/9] drivers: net: xgene: Protect indirect MAC access

2017-04-26 Thread Iyappan Subramanian
From: Quan Nguyen <qngu...@apm.com>

This patch adds lock to protect indirect mac access sequence.

Signed-off-by: Quan Nguyen <qngu...@apm.com>
Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.c| 2 ++
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c  | 1 +
 drivers/net/ethernet/apm/xgene/xgene_enet_main.h  | 1 +
 drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c | 7 ++-
 drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c | 2 ++
 5 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
index 2a835e0..3697ba7 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
@@ -365,9 +365,11 @@ static void xgene_enet_rd_mcx_mac(struct xgene_enet_pdata 
*pdata,
cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET;
cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET;
 
+   spin_lock(>mac_lock);
if (!xgene_enet_rd_indirect(addr, rd, cmd, cmd_done, rd_addr, rd_data))
netdev_err(pdata->ndev, "MCX mac read failed, addr: %04x\n",
   rd_addr);
+   spin_unlock(>mac_lock);
 }
 
 static void xgene_gmac_set_mac_addr(struct xgene_enet_pdata *pdata)
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index 5f37ed3..9a28ac3 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -2055,6 +2055,7 @@ static int xgene_enet_probe(struct platform_device *pdev)
goto err;
 
xgene_enet_setup_ops(pdata);
+   spin_lock_init(>mac_lock);
 
if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) {
ndev->features |= NETIF_F_TSO | NETIF_F_RXCSUM;
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h 
b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
index 0d4be24..827b33d 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
@@ -221,6 +221,7 @@ struct xgene_enet_pdata {
struct xgene_enet_cle cle;
struct rtnl_link_stats64 stats;
const struct xgene_mac_ops *mac_ops;
+   spinlock_t mac_lock; /* mac lock */
const struct xgene_port_ops *port_ops;
struct xgene_ring_ops *ring_ops;
const struct xgene_cle_ops *cle_ops;
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
index a8e063b..4dd41f5 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
@@ -130,6 +130,7 @@ static u32 xgene_enet_rd_indirect(struct xgene_indirect_ctl 
*ctl, u32 rd_addr)
 
 static u32 xgene_enet_rd_mac(struct xgene_enet_pdata *p, u32 rd_addr)
 {
+   u32 val;
struct xgene_indirect_ctl ctl = {
.addr = p->mcx_mac_addr + MAC_ADDR_REG_OFFSET,
.ctl = p->mcx_mac_addr + MAC_READ_REG_OFFSET,
@@ -137,7 +138,11 @@ static u32 xgene_enet_rd_mac(struct xgene_enet_pdata *p, 
u32 rd_addr)
.cmd_done = p->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET
};
 
-   return xgene_enet_rd_indirect(, rd_addr);
+   spin_lock(>mac_lock);
+   val = xgene_enet_rd_indirect(, rd_addr);
+   spin_unlock(>mac_lock);
+
+   return val;
 }
 
 static int xgene_enet_ecc_init(struct xgene_enet_pdata *p)
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
index 423240c..9a2d0ca 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
@@ -158,9 +158,11 @@ static void xgene_enet_rd_mac(struct xgene_enet_pdata 
*pdata,
cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET;
cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET;
 
+   spin_lock(>mac_lock);
if (!xgene_enet_rd_indirect(addr, rd, cmd, cmd_done, rd_addr, rd_data))
netdev_err(pdata->ndev, "MCX mac read failed, addr: %04x\n",
   rd_addr);
+   spin_unlock(>mac_lock);
 }
 
 static bool xgene_enet_rd_pcs(struct xgene_enet_pdata *pdata,
-- 
1.9.1



[PATCH net-next 2/9] drivers: net: xgene: Remove redundant local stats

2017-04-26 Thread Iyappan Subramanian
From: Quan Nguyen <qngu...@apm.com>

Commit 5944701df90d ("net: remove useless memset's in drivers get_stats64")
makes the pdata->stats redundant. This patch removes pdata->stats and
updates get_stats64() callback accordingly.

Signed-off-by: Quan Nguyen <qngu...@apm.com>
Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c | 7 ---
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c| 4 +---
 drivers/net/ethernet/apm/xgene/xgene_enet_main.h| 1 -
 3 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
index 28fdedc..217cde8 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
@@ -25,7 +25,7 @@ struct xgene_gstrings_stats {
int offset;
 };
 
-#define XGENE_STAT(m) { #m, offsetof(struct xgene_enet_pdata, stats.m) }
+#define XGENE_STAT(m) { #m, offsetof(struct rtnl_link_stats64, m) }
 
 static const struct xgene_gstrings_stats gstrings_stats[] = {
XGENE_STAT(rx_packets),
@@ -156,11 +156,12 @@ static void xgene_get_ethtool_stats(struct net_device 
*ndev,
struct ethtool_stats *dummy,
u64 *data)
 {
-   void *pdata = netdev_priv(ndev);
+   struct rtnl_link_stats64 stats;
int i;
 
+   dev_get_stats(ndev, );
for (i = 0; i < XGENE_STATS_LEN; i++)
-   *data++ = *(u64 *)(pdata + gstrings_stats[i].offset);
+   data[i] = *(u64 *)((char *) + gstrings_stats[i].offset);
 }
 
 static void xgene_get_pauseparam(struct net_device *ndev,
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index 9a28ac3..e4f2ef2 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -1466,10 +1466,9 @@ static int xgene_enet_create_desc_rings(struct 
net_device *ndev)
 
 static void xgene_enet_get_stats64(
struct net_device *ndev,
-   struct rtnl_link_stats64 *storage)
+   struct rtnl_link_stats64 *stats)
 {
struct xgene_enet_pdata *pdata = netdev_priv(ndev);
-   struct rtnl_link_stats64 *stats = >stats;
struct xgene_enet_desc_ring *ring;
int i;
 
@@ -1493,7 +1492,6 @@ static void xgene_enet_get_stats64(
stats->rx_dropped += ring->rx_dropped;
}
}
-   memcpy(storage, stats, sizeof(struct rtnl_link_stats64));
 }
 
 static int xgene_enet_set_mac_address(struct net_device *ndev, void *addr)
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h 
b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
index 827b33d..5e6fd71 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
@@ -219,7 +219,6 @@ struct xgene_enet_pdata {
int phy_mode;
enum xgene_enet_rm rm;
struct xgene_enet_cle cle;
-   struct rtnl_link_stats64 stats;
const struct xgene_mac_ops *mac_ops;
spinlock_t mac_lock; /* mac lock */
const struct xgene_port_ops *port_ops;
-- 
1.9.1



[PATCH net-next 4/9] drivers: net: xgene: Remove unused macros

2017-04-26 Thread Iyappan Subramanian
From: Quan Nguyen <qngu...@apm.com>

This patch cleans up unused macros to improve readability.

Signed-off-by: Quan Nguyen <qngu...@apm.com>
Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.h | 6 --
 1 file changed, 6 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h 
b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
index c6b5bbd..5a9f9d5 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
@@ -217,12 +217,6 @@ enum xgene_enet_rm {
 #define FULL_DUPLEX2   BIT(0)
 #define PAD_CRCBIT(2)
 #define LENGTH_CHK BIT(4)
-#define SCAN_AUTO_INCR BIT(5)
-#define TBYT_ADDR  0x38
-#define TPKT_ADDR  0x39
-#define TDRP_ADDR  0x45
-#define TFCS_ADDR  0x47
-#define TUND_ADDR  0x4a
 
 #define TSO_IPPROTO_TCP1
 
-- 
1.9.1



[PATCH net-next 0/9] drivers: net: xgene: Add ethtool stats and bug fixes

2017-04-26 Thread Iyappan Subramanian
This patch set,

- adds ethtool extended statistics support
- addresses errata workarounds
- fixes bugs related to statistics

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
Signed-off-by: Quan Nguyen <qngu...@apm.com>
---

Quan Nguyen (9):
  drivers: net: xgene: Protect indirect MAC access
  drivers: net: xgene: Remove redundant local stats
  drivers: net: xgene: Refactor statistics error parsing code
  drivers: net: xgene: Remove unused macros
  drivers: net: xgene: Extend ethtool statistics
  drivers: net: xgene: Add rx_overrun/tx_underrun statistic
  drivers: net: xgene: Workaround for HW errata 10GE_4
  drivers: net: xgene: Add frame recovered statistics counter for errata
10GE_8/ENET_11
  drivers: net: xgene: Workaround for HW errata 10GE_10/ENET_15

 .../net/ethernet/apm/xgene/xgene_enet_ethtool.c| 132 -
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.c |  41 ++-
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.h |  66 +--
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c   |  57 ++---
 drivers/net/ethernet/apm/xgene/xgene_enet_main.h   |  13 +-
 drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c  |  42 ++-
 drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c  |  35 ++
 drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h  |   5 +
 8 files changed, 357 insertions(+), 34 deletions(-)

-- 
1.9.1



[PATCH v2 net-next] drivers: net: xgene-v2: Extend ethtool statistics

2017-04-17 Thread Iyappan Subramanian
This patch adds extended statistics reporting to ethtool.

In summary, this patch,

   - adds ethtool.h with the statistics register definitions
   - adds 'struct xge_gstrings_extd_stats' to gather extended stats
   - modifies xge_get_strings(), get_sset_count() and
 get_ethtool_stats() accordingly
   - moves 'struct xge_gstrings_stats' to ethtool.h

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
v2: Address review comments from v1
- removed duplicate statistics counters that were reported by
  xge_get_stats64()
v1:
- Initial version
---

 drivers/net/ethernet/apm/xgene-v2/ethtool.c | 78 ++---
 drivers/net/ethernet/apm/xgene-v2/ethtool.h | 78 +
 drivers/net/ethernet/apm/xgene-v2/mac.h |  3 --
 drivers/net/ethernet/apm/xgene-v2/main.h|  2 +-
 4 files changed, 151 insertions(+), 10 deletions(-)
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/ethtool.h

diff --git a/drivers/net/ethernet/apm/xgene-v2/ethtool.c 
b/drivers/net/ethernet/apm/xgene-v2/ethtool.c
index 0c426f5..be4 100644
--- a/drivers/net/ethernet/apm/xgene-v2/ethtool.c
+++ b/drivers/net/ethernet/apm/xgene-v2/ethtool.c
@@ -21,12 +21,13 @@
 
 #include "main.h"
 
-struct xge_gstrings_stats {
-   char name[ETH_GSTRING_LEN];
-   int offset;
-};
-
 #define XGE_STAT(m){ #m, offsetof(struct xge_pdata, stats.m) }
+#define XGE_EXTD_STAT(m, n)\
+   {   \
+   #m, \
+   n,  \
+   0   \
+   }
 
 static const struct xge_gstrings_stats gstrings_stats[] = {
XGE_STAT(rx_packets),
@@ -36,7 +37,62 @@ struct xge_gstrings_stats {
XGE_STAT(rx_errors)
 };
 
+static struct xge_gstrings_extd_stats gstrings_extd_stats[] = {
+   XGE_EXTD_STAT(tx_rx_64b_frame_cntr, TR64),
+   XGE_EXTD_STAT(tx_rx_127b_frame_cntr, TR127),
+   XGE_EXTD_STAT(tx_rx_255b_frame_cntr, TR255),
+   XGE_EXTD_STAT(tx_rx_511b_frame_cntr, TR511),
+   XGE_EXTD_STAT(tx_rx_1023b_frame_cntr, TR1K),
+   XGE_EXTD_STAT(tx_rx_1518b_frame_cntr, TRMAX),
+   XGE_EXTD_STAT(tx_rx_1522b_frame_cntr, TRMGV),
+   XGE_EXTD_STAT(rx_fcs_error_cntr, RFCS),
+   XGE_EXTD_STAT(rx_multicast_pkt_cntr, RMCA),
+   XGE_EXTD_STAT(rx_broadcast_pkt_cntr, RBCA),
+   XGE_EXTD_STAT(rx_ctrl_frame_pkt_cntr, RXCF),
+   XGE_EXTD_STAT(rx_pause_frame_pkt_cntr, RXPF),
+   XGE_EXTD_STAT(rx_unk_opcode_cntr, RXUO),
+   XGE_EXTD_STAT(rx_align_err_cntr, RALN),
+   XGE_EXTD_STAT(rx_frame_len_err_cntr, RFLR),
+   XGE_EXTD_STAT(rx_code_err_cntr, RCDE),
+   XGE_EXTD_STAT(rx_carrier_sense_err_cntr, RCSE),
+   XGE_EXTD_STAT(rx_undersize_pkt_cntr, RUND),
+   XGE_EXTD_STAT(rx_oversize_pkt_cntr, ROVR),
+   XGE_EXTD_STAT(rx_fragments_cntr, RFRG),
+   XGE_EXTD_STAT(rx_jabber_cntr, RJBR),
+   XGE_EXTD_STAT(rx_dropped_pkt_cntr, RDRP),
+   XGE_EXTD_STAT(tx_multicast_pkt_cntr, TMCA),
+   XGE_EXTD_STAT(tx_broadcast_pkt_cntr, TBCA),
+   XGE_EXTD_STAT(tx_pause_ctrl_frame_cntr, TXPF),
+   XGE_EXTD_STAT(tx_defer_pkt_cntr, TDFR),
+   XGE_EXTD_STAT(tx_excv_defer_pkt_cntr, TEDF),
+   XGE_EXTD_STAT(tx_single_col_pkt_cntr, TSCL),
+   XGE_EXTD_STAT(tx_multi_col_pkt_cntr, TMCL),
+   XGE_EXTD_STAT(tx_late_col_pkt_cntr, TLCL),
+   XGE_EXTD_STAT(tx_excv_col_pkt_cntr, TXCL),
+   XGE_EXTD_STAT(tx_total_col_cntr, TNCL),
+   XGE_EXTD_STAT(tx_pause_frames_hnrd_cntr, TPFH),
+   XGE_EXTD_STAT(tx_drop_frame_cntr, TDRP),
+   XGE_EXTD_STAT(tx_jabber_frame_cntr, TJBR),
+   XGE_EXTD_STAT(tx_fcs_error_cntr, TFCS),
+   XGE_EXTD_STAT(tx_ctrl_frame_cntr, TXCF),
+   XGE_EXTD_STAT(tx_oversize_frame_cntr, TOVR),
+   XGE_EXTD_STAT(tx_undersize_frame_cntr, TUND),
+   XGE_EXTD_STAT(tx_fragments_cntr, TFRG)
+};
+
 #define XGE_STATS_LEN  ARRAY_SIZE(gstrings_stats)
+#define XGE_EXTD_STATS_LEN ARRAY_SIZE(gstrings_extd_stats)
+
+static void xge_mac_get_extd_stats(struct xge_pdata *pdata)
+{
+   u32 data;
+   int i;
+
+   for (i = 0; i < XGE_EXTD_STATS_LEN; i++) {
+   data = xge_rd_csr(pdata, gstrings_extd_stats[i].addr);
+   gstrings_extd_stats[i].value += data;
+   }
+}
 
 static void xge_get_drvinfo(struct net_device *ndev,
struct ethtool_drvinfo *info)
@@ -62,6 +118,11 @@ static void xge_get_strings(struct net_device *ndev, u32 
stringset, u8 *data)
memcpy(p, gstrings_stats[i].name, ETH_GSTRING_LEN);
p += ETH_GSTRING_LEN;
}
+
+   for (i = 0; i < XGE_EXTD_STATS_LEN; i++) {
+   memcpy(p, gstrings_extd_stats[i].name, ETH_GSTRING_LEN);
+   p += ETH_GSTRING_LEN;
+   

[PATCH net-next] drivers: net: xgene-v2: Extend ethtool statistics

2017-04-14 Thread Iyappan Subramanian
This patch adds extended statistics reporting to ethtool.

In summary, this patch,

   - adds ethtool.h with the statistics register definitions
   - adds 'struct xge_gstrings_extd_stats' to gather extended stats
   - modifies xge_get_strings(), get_sset_count() and
 get_ethtool_stats() accordingly
   - moves 'struct xge_gstrings_stats' to ethtool.h

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
 drivers/net/ethernet/apm/xgene-v2/ethtool.c | 82 ++---
 drivers/net/ethernet/apm/xgene-v2/ethtool.h | 82 +
 drivers/net/ethernet/apm/xgene-v2/mac.h |  3 --
 drivers/net/ethernet/apm/xgene-v2/main.h|  2 +-
 4 files changed, 159 insertions(+), 10 deletions(-)
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/ethtool.h

diff --git a/drivers/net/ethernet/apm/xgene-v2/ethtool.c 
b/drivers/net/ethernet/apm/xgene-v2/ethtool.c
index 0c426f5..421b1dd 100644
--- a/drivers/net/ethernet/apm/xgene-v2/ethtool.c
+++ b/drivers/net/ethernet/apm/xgene-v2/ethtool.c
@@ -21,12 +21,13 @@
 
 #include "main.h"
 
-struct xge_gstrings_stats {
-   char name[ETH_GSTRING_LEN];
-   int offset;
-};
-
 #define XGE_STAT(m){ #m, offsetof(struct xge_pdata, stats.m) }
+#define XGE_EXTD_STAT(m, n)\
+   {   \
+   #m, \
+   n,  \
+   0   \
+   }
 
 static const struct xge_gstrings_stats gstrings_stats[] = {
XGE_STAT(rx_packets),
@@ -36,7 +37,66 @@ struct xge_gstrings_stats {
XGE_STAT(rx_errors)
 };
 
+static struct xge_gstrings_extd_stats gstrings_extd_stats[] = {
+   XGE_EXTD_STAT(tx_rx_64b_frame_cntr, TR64),
+   XGE_EXTD_STAT(tx_rx_127b_frame_cntr, TR127),
+   XGE_EXTD_STAT(tx_rx_255b_frame_cntr, TR255),
+   XGE_EXTD_STAT(tx_rx_511b_frame_cntr, TR511),
+   XGE_EXTD_STAT(tx_rx_1023b_frame_cntr, TR1K),
+   XGE_EXTD_STAT(tx_rx_1518b_frame_cntr, TRMAX),
+   XGE_EXTD_STAT(tx_rx_1522b_frame_cntr, TRMGV),
+   XGE_EXTD_STAT(rx_byte_cntr, RBYT),
+   XGE_EXTD_STAT(rx_pkt_cntr, RPKT),
+   XGE_EXTD_STAT(rx_fcs_error_cntr, RFCS),
+   XGE_EXTD_STAT(rx_multicast_pkt_cntr, RMCA),
+   XGE_EXTD_STAT(rx_broadcast_pkt_cntr, RBCA),
+   XGE_EXTD_STAT(rx_ctrl_frame_pkt_cntr, RXCF),
+   XGE_EXTD_STAT(rx_pause_frame_pkt_cntr, RXPF),
+   XGE_EXTD_STAT(rx_unk_opcode_cntr, RXUO),
+   XGE_EXTD_STAT(rx_align_err_cntr, RALN),
+   XGE_EXTD_STAT(rx_frame_len_err_cntr, RFLR),
+   XGE_EXTD_STAT(rx_code_err_cntr, RCDE),
+   XGE_EXTD_STAT(rx_carrier_sense_err_cntr, RCSE),
+   XGE_EXTD_STAT(rx_undersize_pkt_cntr, RUND),
+   XGE_EXTD_STAT(rx_oversize_pkt_cntr, ROVR),
+   XGE_EXTD_STAT(rx_fragments_cntr, RFRG),
+   XGE_EXTD_STAT(rx_jabber_cntr, RJBR),
+   XGE_EXTD_STAT(rx_dropped_pkt_cntr, RDRP),
+   XGE_EXTD_STAT(tx_byte_cntr, TBYT),
+   XGE_EXTD_STAT(tx_pkt_cntr, TPKT),
+   XGE_EXTD_STAT(tx_multicast_pkt_cntr, TMCA),
+   XGE_EXTD_STAT(tx_broadcast_pkt_cntr, TBCA),
+   XGE_EXTD_STAT(tx_pause_ctrl_frame_cntr, TXPF),
+   XGE_EXTD_STAT(tx_defer_pkt_cntr, TDFR),
+   XGE_EXTD_STAT(tx_excv_defer_pkt_cntr, TEDF),
+   XGE_EXTD_STAT(tx_single_col_pkt_cntr, TSCL),
+   XGE_EXTD_STAT(tx_multi_col_pkt_cntr, TMCL),
+   XGE_EXTD_STAT(tx_late_col_pkt_cntr, TLCL),
+   XGE_EXTD_STAT(tx_excv_col_pkt_cntr, TXCL),
+   XGE_EXTD_STAT(tx_total_col_cntr, TNCL),
+   XGE_EXTD_STAT(tx_pause_frames_hnrd_cntr, TPFH),
+   XGE_EXTD_STAT(tx_drop_frame_cntr, TDRP),
+   XGE_EXTD_STAT(tx_jabber_frame_cntr, TJBR),
+   XGE_EXTD_STAT(tx_fcs_error_cntr, TFCS),
+   XGE_EXTD_STAT(tx_ctrl_frame_cntr, TXCF),
+   XGE_EXTD_STAT(tx_oversize_frame_cntr, TOVR),
+   XGE_EXTD_STAT(tx_undersize_frame_cntr, TUND),
+   XGE_EXTD_STAT(tx_fragments_cntr, TFRG)
+};
+
 #define XGE_STATS_LEN  ARRAY_SIZE(gstrings_stats)
+#define XGE_EXTD_STATS_LEN ARRAY_SIZE(gstrings_extd_stats)
+
+static void xge_mac_get_extd_stats(struct xge_pdata *pdata)
+{
+   u32 data;
+   int i;
+
+   for (i = 0; i < XGE_EXTD_STATS_LEN; i++) {
+   data = xge_rd_csr(pdata, gstrings_extd_stats[i].addr);
+   gstrings_extd_stats[i].value += data;
+   }
+}
 
 static void xge_get_drvinfo(struct net_device *ndev,
struct ethtool_drvinfo *info)
@@ -62,6 +122,11 @@ static void xge_get_strings(struct net_device *ndev, u32 
stringset, u8 *data)
memcpy(p, gstrings_stats[i].name, ETH_GSTRING_LEN);
p += ETH_GSTRING_LEN;
}
+
+   for (i = 0; i < XGE_EXTD_STATS_LEN; i++) {
+   memcpy(p, gstrings_extd_stats[i].name, ETH_GSTRING_LEN);
+   p += ETH_GSTRING_LEN;
+   

[PATCH v2 net-next 1/4] drivers: net: xgene-v2: Add MDIO support

2017-03-21 Thread Iyappan Subramanian
Added phy management support by using phy abstraction layer APIs.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
 drivers/net/ethernet/apm/xgene-v2/Makefile |   2 +-
 drivers/net/ethernet/apm/xgene-v2/mac.c|   2 +-
 drivers/net/ethernet/apm/xgene-v2/mac.h|   1 +
 drivers/net/ethernet/apm/xgene-v2/main.c   |  11 +-
 drivers/net/ethernet/apm/xgene-v2/main.h   |   4 +
 drivers/net/ethernet/apm/xgene-v2/mdio.c   | 167 +
 6 files changed, 182 insertions(+), 5 deletions(-)
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/mdio.c

diff --git a/drivers/net/ethernet/apm/xgene-v2/Makefile 
b/drivers/net/ethernet/apm/xgene-v2/Makefile
index 735309c..0fa5975 100644
--- a/drivers/net/ethernet/apm/xgene-v2/Makefile
+++ b/drivers/net/ethernet/apm/xgene-v2/Makefile
@@ -2,5 +2,5 @@
 # Makefile for APM X-Gene Ethernet v2 driver
 #
 
-xgene-enet-v2-objs := main.o mac.o enet.o ring.o
+xgene-enet-v2-objs := main.o mac.o enet.o ring.o mdio.o
 obj-$(CONFIG_NET_XGENE_V2) += xgene-enet-v2.o
diff --git a/drivers/net/ethernet/apm/xgene-v2/mac.c 
b/drivers/net/ethernet/apm/xgene-v2/mac.c
index c3189de..ee431e3 100644
--- a/drivers/net/ethernet/apm/xgene-v2/mac.c
+++ b/drivers/net/ethernet/apm/xgene-v2/mac.c
@@ -27,7 +27,7 @@ void xge_mac_reset(struct xge_pdata *pdata)
xge_wr_csr(pdata, MAC_CONFIG_1, 0);
 }
 
-static void xge_mac_set_speed(struct xge_pdata *pdata)
+void xge_mac_set_speed(struct xge_pdata *pdata)
 {
u32 icm0, icm2, ecm0, mc2;
u32 intf_ctrl, rgmii;
diff --git a/drivers/net/ethernet/apm/xgene-v2/mac.h 
b/drivers/net/ethernet/apm/xgene-v2/mac.h
index 0fce6ae..74397c9 100644
--- a/drivers/net/ethernet/apm/xgene-v2/mac.h
+++ b/drivers/net/ethernet/apm/xgene-v2/mac.h
@@ -101,6 +101,7 @@ static inline u32 xgene_get_reg_bits(u32 var, int pos, int 
len)
 struct xge_pdata;
 
 void xge_mac_reset(struct xge_pdata *pdata);
+void xge_mac_set_speed(struct xge_pdata *pdata);
 void xge_mac_enable(struct xge_pdata *pdata);
 void xge_mac_disable(struct xge_pdata *pdata);
 void xge_mac_init(struct xge_pdata *pdata);
diff --git a/drivers/net/ethernet/apm/xgene-v2/main.c 
b/drivers/net/ethernet/apm/xgene-v2/main.c
index ae76977..82ac5b4 100644
--- a/drivers/net/ethernet/apm/xgene-v2/main.c
+++ b/drivers/net/ethernet/apm/xgene-v2/main.c
@@ -500,9 +500,10 @@ static int xge_open(struct net_device *ndev)
 
xge_intr_enable(pdata);
xge_wr_csr(pdata, DMARXCTRL, 1);
+
+   phy_start(ndev->phydev);
xge_mac_enable(pdata);
netif_start_queue(ndev);
-   netif_carrier_on(ndev);
 
return 0;
 }
@@ -511,9 +512,9 @@ static int xge_close(struct net_device *ndev)
 {
struct xge_pdata *pdata = netdev_priv(ndev);
 
-   netif_carrier_off(ndev);
netif_stop_queue(ndev);
xge_mac_disable(pdata);
+   phy_stop(ndev->phydev);
 
xge_intr_disable(pdata);
xge_free_irq(ndev);
@@ -683,9 +684,12 @@ static int xge_probe(struct platform_device *pdev)
if (ret)
goto err;
 
+   ret = xge_mdio_config(ndev);
+   if (ret)
+   goto err;
+
netif_napi_add(ndev, >napi, xge_napi, NAPI_POLL_WEIGHT);
 
-   netif_carrier_off(ndev);
ret = register_netdev(ndev);
if (ret) {
netdev_err(ndev, "Failed to register netdev\n");
@@ -713,6 +717,7 @@ static int xge_remove(struct platform_device *pdev)
dev_close(ndev);
rtnl_unlock();
 
+   xge_mdio_remove(ndev);
unregister_netdev(ndev);
free_netdev(ndev);
 
diff --git a/drivers/net/ethernet/apm/xgene-v2/main.h 
b/drivers/net/ethernet/apm/xgene-v2/main.h
index ada7b0e..777f254 100644
--- a/drivers/net/ethernet/apm/xgene-v2/main.h
+++ b/drivers/net/ethernet/apm/xgene-v2/main.h
@@ -65,6 +65,7 @@ struct xge_pdata {
struct xge_desc_ring *rx_ring;
struct platform_device *pdev;
char irq_name[IRQ_ID_SIZE];
+   struct mii_bus *mdio_bus;
struct net_device *ndev;
struct napi_struct napi;
struct xge_stats stats;
@@ -72,4 +73,7 @@ struct xge_pdata {
u8 nbufs;
 };
 
+int xge_mdio_config(struct net_device *ndev);
+void xge_mdio_remove(struct net_device *ndev);
+
 #endif /* __XGENE_ENET_V2_MAIN_H__ */
diff --git a/drivers/net/ethernet/apm/xgene-v2/mdio.c 
b/drivers/net/ethernet/apm/xgene-v2/mdio.c
new file mode 100644
index 000..a583c6a
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/mdio.c
@@ -0,0 +1,167 @@
+/*
+ * Applied Micro X-Gene SoC Ethernet v2 Driver
+ *
+ * Copyright (c) 2017, Applied Micro Circuits Corporation
+ * Author(s): Iyappan Subramanian <isubraman...@apm.com>
+ *   Keyur Chudgar <kchud...@apm.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (

[PATCH v2 net-next 0/4] drivers: net: xgene-v2: Add MDIO and ethtool support

2017-03-21 Thread Iyappan Subramanian
This patch set,

- adds phy management and ethtool support
- fixes ethernet reset
- addresses review comments from previous patch set

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
v2: Address review comments from v1
- removed mdio_lock, since there is a top level lock in mdio_bus.c

v1:
- Initial version
---

Iyappan Subramanian (4):
  drivers: net: xgene-v2: Add MDIO support
  drivers: net: xgene-v2: Add ethtool support
  drivers: net: xgene-v2: Fix port reset
  drivers: net: xgene-v2: misc fixes

 drivers/net/ethernet/apm/xgene-v2/Makefile  |   2 +-
 drivers/net/ethernet/apm/xgene-v2/enet.c|  24 +++-
 drivers/net/ethernet/apm/xgene-v2/enet.h|   2 +
 drivers/net/ethernet/apm/xgene-v2/ethtool.c | 121 
 drivers/net/ethernet/apm/xgene-v2/mac.c |   2 +-
 drivers/net/ethernet/apm/xgene-v2/mac.h |   2 +-
 drivers/net/ethernet/apm/xgene-v2/main.c|  67 +--
 drivers/net/ethernet/apm/xgene-v2/main.h|   5 +
 drivers/net/ethernet/apm/xgene-v2/mdio.c| 167 
 9 files changed, 351 insertions(+), 41 deletions(-)
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/ethtool.c
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/mdio.c

-- 
1.9.1



[PATCH v2 net-next 4/4] drivers: net: xgene-v2: misc fixes

2017-03-21 Thread Iyappan Subramanian
Fixed review comments from the previous patch-set.

- changed return value check of platform_get_irq() to < 0
- replaced devm_request(free)_irq() calls by request(free)_irq() since
  they are called from open() and close()
- changed sizeof(struct mystruct) to sizeof(*mystruct)
- reduced indentation on tx_timeout()

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
 drivers/net/ethernet/apm/xgene-v2/main.c | 55 +++-
 1 file changed, 26 insertions(+), 29 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene-v2/main.c 
b/drivers/net/ethernet/apm/xgene-v2/main.c
index e764e58..0f2ad50 100644
--- a/drivers/net/ethernet/apm/xgene-v2/main.c
+++ b/drivers/net/ethernet/apm/xgene-v2/main.c
@@ -66,9 +66,8 @@ static int xge_get_resources(struct xge_pdata *pdata)
}
 
ret = platform_get_irq(pdev, 0);
-   if (ret <= 0) {
-   dev_err(dev, "Unable to get ENET IRQ\n");
-   ret = ret ? : -ENXIO;
+   if (ret < 0) {
+   dev_err(dev, "Unable to get irq\n");
return ret;
}
pdata->resources.irq = ret;
@@ -156,13 +155,12 @@ static irqreturn_t xge_irq(const int irq, void *data)
 static int xge_request_irq(struct net_device *ndev)
 {
struct xge_pdata *pdata = netdev_priv(ndev);
-   struct device *dev = >pdev->dev;
int ret;
 
snprintf(pdata->irq_name, IRQ_ID_SIZE, "%s", ndev->name);
 
-   ret = devm_request_irq(dev, pdata->resources.irq, xge_irq,
-  0, pdata->irq_name, pdata);
+   ret = request_irq(pdata->resources.irq, xge_irq, 0, pdata->irq_name,
+ pdata);
if (ret)
netdev_err(ndev, "Failed to request irq %s\n", pdata->irq_name);
 
@@ -172,9 +170,8 @@ static int xge_request_irq(struct net_device *ndev)
 static void xge_free_irq(struct net_device *ndev)
 {
struct xge_pdata *pdata = netdev_priv(ndev);
-   struct device *dev = >pdev->dev;
 
-   devm_free_irq(dev, pdata->resources.irq, pdata);
+   free_irq(pdata->resources.irq, pdata);
 }
 
 static bool is_tx_slot_available(struct xge_raw_desc *raw_desc)
@@ -424,7 +421,7 @@ static struct xge_desc_ring *xge_create_desc_ring(struct 
net_device *ndev)
struct xge_desc_ring *ring;
u16 size;
 
-   ring = kzalloc(sizeof(struct xge_desc_ring), GFP_KERNEL);
+   ring = kzalloc(sizeof(*ring), GFP_KERNEL);
if (!ring)
return NULL;
 
@@ -436,7 +433,7 @@ static struct xge_desc_ring *xge_create_desc_ring(struct 
net_device *ndev)
if (!ring->desc_addr)
goto err;
 
-   ring->pkt_info = kcalloc(XGENE_ENET_NUM_DESC, sizeof(struct pkt_info),
+   ring->pkt_info = kcalloc(XGENE_ENET_NUM_DESC, sizeof(*ring->pkt_info),
 GFP_KERNEL);
if (!ring->pkt_info)
goto err;
@@ -598,28 +595,28 @@ static void xge_timeout(struct net_device *ndev)
 
rtnl_lock();
 
-   if (netif_running(ndev)) {
-   netif_carrier_off(ndev);
-   netif_stop_queue(ndev);
-   xge_intr_disable(pdata);
-   napi_disable(>napi);
+   if (!netif_running(ndev))
+   goto out;
 
-   xge_wr_csr(pdata, DMATXCTRL, 0);
-   xge_txc_poll(ndev);
-   xge_free_pending_skb(ndev);
-   xge_wr_csr(pdata, DMATXSTATUS, ~0U);
+   netif_stop_queue(ndev);
+   xge_intr_disable(pdata);
+   napi_disable(>napi);
 
-   xge_setup_desc(pdata->tx_ring);
-   xge_update_tx_desc_addr(pdata);
-   xge_mac_init(pdata);
+   xge_wr_csr(pdata, DMATXCTRL, 0);
+   xge_txc_poll(ndev);
+   xge_free_pending_skb(ndev);
+   xge_wr_csr(pdata, DMATXSTATUS, ~0U);
 
-   napi_enable(>napi);
-   xge_intr_enable(pdata);
-   xge_mac_enable(pdata);
-   netif_start_queue(ndev);
-   netif_carrier_on(ndev);
-   }
+   xge_setup_desc(pdata->tx_ring);
+   xge_update_tx_desc_addr(pdata);
+   xge_mac_init(pdata);
+
+   napi_enable(>napi);
+   xge_intr_enable(pdata);
+   xge_mac_enable(pdata);
+   netif_start_queue(ndev);
 
+out:
rtnl_unlock();
 }
 
@@ -653,7 +650,7 @@ static int xge_probe(struct platform_device *pdev)
struct xge_pdata *pdata;
int ret;
 
-   ndev = alloc_etherdev(sizeof(struct xge_pdata));
+   ndev = alloc_etherdev(sizeof(*pdata));
if (!ndev)
return -ENOMEM;
 
-- 
1.9.1



[PATCH v2 net-next 2/4] drivers: net: xgene-v2: Add ethtool support

2017-03-21 Thread Iyappan Subramanian
Added basic ethtool support.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
 drivers/net/ethernet/apm/xgene-v2/Makefile  |   2 +-
 drivers/net/ethernet/apm/xgene-v2/ethtool.c | 121 
 drivers/net/ethernet/apm/xgene-v2/main.c|   1 +
 drivers/net/ethernet/apm/xgene-v2/main.h|   1 +
 4 files changed, 124 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/ethtool.c

diff --git a/drivers/net/ethernet/apm/xgene-v2/Makefile 
b/drivers/net/ethernet/apm/xgene-v2/Makefile
index 0fa5975..f16a2b3 100644
--- a/drivers/net/ethernet/apm/xgene-v2/Makefile
+++ b/drivers/net/ethernet/apm/xgene-v2/Makefile
@@ -2,5 +2,5 @@
 # Makefile for APM X-Gene Ethernet v2 driver
 #
 
-xgene-enet-v2-objs := main.o mac.o enet.o ring.o mdio.o
+xgene-enet-v2-objs := main.o mac.o enet.o ring.o mdio.o ethtool.o
 obj-$(CONFIG_NET_XGENE_V2) += xgene-enet-v2.o
diff --git a/drivers/net/ethernet/apm/xgene-v2/ethtool.c 
b/drivers/net/ethernet/apm/xgene-v2/ethtool.c
new file mode 100644
index 000..0c426f5
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/ethtool.c
@@ -0,0 +1,121 @@
+/*
+ * Applied Micro X-Gene SoC Ethernet v2 Driver
+ *
+ * Copyright (c) 2017, Applied Micro Circuits Corporation
+ * Author(s): Iyappan Subramanian <isubraman...@apm.com>
+ *   Keyur Chudgar <kchud...@apm.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "main.h"
+
+struct xge_gstrings_stats {
+   char name[ETH_GSTRING_LEN];
+   int offset;
+};
+
+#define XGE_STAT(m){ #m, offsetof(struct xge_pdata, stats.m) }
+
+static const struct xge_gstrings_stats gstrings_stats[] = {
+   XGE_STAT(rx_packets),
+   XGE_STAT(tx_packets),
+   XGE_STAT(rx_bytes),
+   XGE_STAT(tx_bytes),
+   XGE_STAT(rx_errors)
+};
+
+#define XGE_STATS_LEN  ARRAY_SIZE(gstrings_stats)
+
+static void xge_get_drvinfo(struct net_device *ndev,
+   struct ethtool_drvinfo *info)
+{
+   struct xge_pdata *pdata = netdev_priv(ndev);
+   struct platform_device *pdev = pdata->pdev;
+
+   strcpy(info->driver, "xgene-enet-v2");
+   strcpy(info->version, XGENE_ENET_V2_VERSION);
+   snprintf(info->fw_version, ETHTOOL_FWVERS_LEN, "N/A");
+   sprintf(info->bus_info, "%s", pdev->name);
+}
+
+static void xge_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
+{
+   u8 *p = data;
+   int i;
+
+   if (stringset != ETH_SS_STATS)
+   return;
+
+   for (i = 0; i < XGE_STATS_LEN; i++) {
+   memcpy(p, gstrings_stats[i].name, ETH_GSTRING_LEN);
+   p += ETH_GSTRING_LEN;
+   }
+}
+
+static int xge_get_sset_count(struct net_device *ndev, int sset)
+{
+   if (sset != ETH_SS_STATS)
+   return -EINVAL;
+
+   return XGE_STATS_LEN;
+}
+
+static void xge_get_ethtool_stats(struct net_device *ndev,
+ struct ethtool_stats *dummy,
+ u64 *data)
+{
+   void *pdata = netdev_priv(ndev);
+   int i;
+
+   for (i = 0; i < XGE_STATS_LEN; i++)
+   *data++ = *(u64 *)(pdata + gstrings_stats[i].offset);
+}
+
+static int xge_get_link_ksettings(struct net_device *ndev,
+ struct ethtool_link_ksettings *cmd)
+{
+   struct phy_device *phydev = ndev->phydev;
+
+   if (!phydev)
+   return -ENODEV;
+
+   return phy_ethtool_ksettings_get(phydev, cmd);
+}
+
+static int xge_set_link_ksettings(struct net_device *ndev,
+ const struct ethtool_link_ksettings *cmd)
+{
+   struct phy_device *phydev = ndev->phydev;
+
+   if (!phydev)
+   return -ENODEV;
+
+   return phy_ethtool_ksettings_set(phydev, cmd);
+}
+
+static const struct ethtool_ops xge_ethtool_ops = {
+   .get_drvinfo = xge_get_drvinfo,
+   .get_link = ethtool_op_get_link,
+   .get_strings = xge_get_strings,
+   .get_sset_count = xge_get_sset_count,
+   .get_ethtool_stats = xge_get_ethtool_stats,
+   .get_link_ksettings = xge_get_link_ksettings,
+   .set_link_ksettings = xge_set_link_ksettings,
+};
+
+void xge_set_ethtool_ops(struct net_device *ndev)
+{
+   ndev->ethtool_ops = _ethtool_o

[PATCH v2 net-next 3/4] drivers: net: xgene-v2: Fix port reset

2017-03-21 Thread Iyappan Subramanian
Fixed port reset sequence by adding ECC init.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
 drivers/net/ethernet/apm/xgene-v2/enet.c | 24 ++--
 drivers/net/ethernet/apm/xgene-v2/enet.h |  2 ++
 drivers/net/ethernet/apm/xgene-v2/mac.h  |  1 -
 3 files changed, 20 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene-v2/enet.c 
b/drivers/net/ethernet/apm/xgene-v2/enet.c
index b49edee..5998da0 100644
--- a/drivers/net/ethernet/apm/xgene-v2/enet.c
+++ b/drivers/net/ethernet/apm/xgene-v2/enet.c
@@ -38,10 +38,24 @@ u32 xge_rd_csr(struct xge_pdata *pdata, u32 offset)
 int xge_port_reset(struct net_device *ndev)
 {
struct xge_pdata *pdata = netdev_priv(ndev);
+   struct device *dev = >pdev->dev;
+   u32 data, wait = 10;
 
-   xge_wr_csr(pdata, ENET_SRST, 0x3);
-   xge_wr_csr(pdata, ENET_SRST, 0x2);
-   xge_wr_csr(pdata, ENET_SRST, 0x0);
+   xge_wr_csr(pdata, ENET_CLKEN, 0x3);
+   xge_wr_csr(pdata, ENET_SRST, 0xf);
+   xge_wr_csr(pdata, ENET_SRST, 0);
+   xge_wr_csr(pdata, CFG_MEM_RAM_SHUTDOWN, 1);
+   xge_wr_csr(pdata, CFG_MEM_RAM_SHUTDOWN, 0);
+
+   do {
+   usleep_range(100, 110);
+   data = xge_rd_csr(pdata, BLOCK_MEM_RDY);
+   } while (data != MEM_RDY && wait--);
+
+   if (data != MEM_RDY) {
+   dev_err(dev, "ECC init failed: %x\n", data);
+   return -ETIMEDOUT;
+   }
 
xge_wr_csr(pdata, ENET_SHIM, DEVM_ARAUX_COH | DEVM_AWAUX_COH);
 
@@ -59,13 +73,11 @@ static void xge_traffic_resume(struct net_device *ndev)
xge_wr_csr(pdata, RX_DV_GATE_REG, 1);
 }
 
-int xge_port_init(struct net_device *ndev)
+void xge_port_init(struct net_device *ndev)
 {
struct xge_pdata *pdata = netdev_priv(ndev);
 
pdata->phy_speed = SPEED_1000;
xge_mac_init(pdata);
xge_traffic_resume(ndev);
-
-   return 0;
 }
diff --git a/drivers/net/ethernet/apm/xgene-v2/enet.h 
b/drivers/net/ethernet/apm/xgene-v2/enet.h
index 40371cf..3fd36dc6 100644
--- a/drivers/net/ethernet/apm/xgene-v2/enet.h
+++ b/drivers/net/ethernet/apm/xgene-v2/enet.h
@@ -28,6 +28,7 @@
 #define CFG_MEM_RAM_SHUTDOWN   0xd070
 #define BLOCK_MEM_RDY  0xd074
 
+#define MEM_RDY0x
 #define DEVM_ARAUX_COH BIT(19)
 #define DEVM_AWAUX_COH BIT(3)
 
@@ -39,5 +40,6 @@
 void xge_wr_csr(struct xge_pdata *pdata, u32 offset, u32 val);
 u32 xge_rd_csr(struct xge_pdata *pdata, u32 offset);
 int xge_port_reset(struct net_device *ndev);
+void xge_port_init(struct net_device *ndev);
 
 #endif  /* __XGENE_ENET_V2_ENET__H__ */
diff --git a/drivers/net/ethernet/apm/xgene-v2/mac.h 
b/drivers/net/ethernet/apm/xgene-v2/mac.h
index 74397c9..18a9c9d 100644
--- a/drivers/net/ethernet/apm/xgene-v2/mac.h
+++ b/drivers/net/ethernet/apm/xgene-v2/mac.h
@@ -105,7 +105,6 @@ static inline u32 xgene_get_reg_bits(u32 var, int pos, int 
len)
 void xge_mac_enable(struct xge_pdata *pdata);
 void xge_mac_disable(struct xge_pdata *pdata);
 void xge_mac_init(struct xge_pdata *pdata);
-int xge_port_init(struct net_device *ndev);
 void xge_mac_set_station_addr(struct xge_pdata *pdata);
 
 #endif /* __XGENE_ENET_V2_MAC_H__ */
-- 
1.9.1



Re: [PATCH net-next 1/4] drivers: net: xgene-v2: Add MDIO support

2017-03-21 Thread Iyappan Subramanian
On Tue, Mar 21, 2017 at 1:35 PM, Andrew Lunn  wrote:
>> @@ -511,9 +512,9 @@ static int xge_close(struct net_device *ndev)
>>  {
>>   struct xge_pdata *pdata = netdev_priv(ndev);
>>
>> - netif_carrier_off(ndev);
>>   netif_stop_queue(ndev);
>>   xge_mac_disable(pdata);
>> + phy_stop(ndev->phydev);
>>
>>   xge_intr_disable(pdata);
>>   xge_free_irq(ndev);
>> @@ -683,9 +684,14 @@ static int xge_probe(struct platform_device *pdev)
>>   if (ret)
>>   goto err;
>>
>> + spin_lock_init(>mdio_lock);
>> +
>
> ...
>
>> +static int xge_mdio_write(struct mii_bus *bus, int phy_id, int reg, u16 
>> data)
>> +{
>> + struct xge_pdata *pdata = bus->priv;
>> + u32 done, val = 0;
>> + u8 wait = 10;
>> + int ret = 0;
>> +
>> + spin_lock(>mdio_lock);
>> +
>> + SET_REG_BITS(, PHY_ADDR, phy_id);
>> + SET_REG_BITS(, REG_ADDR, reg);
>> + xge_wr_csr(pdata, MII_MGMT_ADDRESS, val);
>> +
>> + xge_wr_csr(pdata, MII_MGMT_CONTROL, data);
>> + do {
>> + usleep_range(5, 10);
>> + done = xge_rd_csr(pdata, MII_MGMT_INDICATORS);
>> + } while ((done & MII_MGMT_BUSY) && wait--);
>> +
>> + if (done & MII_MGMT_BUSY) {
>> + dev_err(>dev, "MII_MGMT write failed\n");
>> + ret = -ETIMEDOUT;
>> + }
>> +
>> + spin_unlock(>mdio_lock);
>> +
>> + return ret;
>> +}
>> +
>> +static int xge_mdio_read(struct mii_bus *bus, int phy_id, int reg)
>> +{
>> + struct xge_pdata *pdata = bus->priv;
>> + u32 data, done, val = 0;
>> + u8 wait = 10;
>> +
>> + spin_lock(>mdio_lock);
>> +
>
> Hi Iyappan
>
> Please could you explain what this lock is protecting which the
> mii_bus mdio_lock in mdio_bus.c is not protecting?

Hi Keyur,

Please could you explain what this lock is protecting which the
mii_bus mdio_lock in mdio_bus.c is not protecting?

I agree with him.  Actually there is a mutex on mdio_bus.  So the mdio
bus read and write are locked.  we don't need the lock.

Do you agree ?


>
> Thanks
> Andrew


[PATCH net-next 4/4] drivers: net: xgene-v2: misc fixes

2017-03-21 Thread Iyappan Subramanian
Fixed review comments from the previous patch-set.

- changed return value check of platform_get_irq() to < 0
- replaced devm_request(free)_irq() calls by request(free)_irq() since
  they are called from open() and close()
- changed sizeof(struct mystruct) to sizeof(*mystruct)
- reduced indentation on tx_timeout()

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
 drivers/net/ethernet/apm/xgene-v2/main.c | 55 +++-
 1 file changed, 26 insertions(+), 29 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene-v2/main.c 
b/drivers/net/ethernet/apm/xgene-v2/main.c
index 9a5a5ec..ce31c47 100644
--- a/drivers/net/ethernet/apm/xgene-v2/main.c
+++ b/drivers/net/ethernet/apm/xgene-v2/main.c
@@ -66,9 +66,8 @@ static int xge_get_resources(struct xge_pdata *pdata)
}
 
ret = platform_get_irq(pdev, 0);
-   if (ret <= 0) {
-   dev_err(dev, "Unable to get ENET IRQ\n");
-   ret = ret ? : -ENXIO;
+   if (ret < 0) {
+   dev_err(dev, "Unable to get irq\n");
return ret;
}
pdata->resources.irq = ret;
@@ -156,13 +155,12 @@ static irqreturn_t xge_irq(const int irq, void *data)
 static int xge_request_irq(struct net_device *ndev)
 {
struct xge_pdata *pdata = netdev_priv(ndev);
-   struct device *dev = >pdev->dev;
int ret;
 
snprintf(pdata->irq_name, IRQ_ID_SIZE, "%s", ndev->name);
 
-   ret = devm_request_irq(dev, pdata->resources.irq, xge_irq,
-  0, pdata->irq_name, pdata);
+   ret = request_irq(pdata->resources.irq, xge_irq, 0, pdata->irq_name,
+ pdata);
if (ret)
netdev_err(ndev, "Failed to request irq %s\n", pdata->irq_name);
 
@@ -172,9 +170,8 @@ static int xge_request_irq(struct net_device *ndev)
 static void xge_free_irq(struct net_device *ndev)
 {
struct xge_pdata *pdata = netdev_priv(ndev);
-   struct device *dev = >pdev->dev;
 
-   devm_free_irq(dev, pdata->resources.irq, pdata);
+   free_irq(pdata->resources.irq, pdata);
 }
 
 static bool is_tx_slot_available(struct xge_raw_desc *raw_desc)
@@ -424,7 +421,7 @@ static struct xge_desc_ring *xge_create_desc_ring(struct 
net_device *ndev)
struct xge_desc_ring *ring;
u16 size;
 
-   ring = kzalloc(sizeof(struct xge_desc_ring), GFP_KERNEL);
+   ring = kzalloc(sizeof(*ring), GFP_KERNEL);
if (!ring)
return NULL;
 
@@ -436,7 +433,7 @@ static struct xge_desc_ring *xge_create_desc_ring(struct 
net_device *ndev)
if (!ring->desc_addr)
goto err;
 
-   ring->pkt_info = kcalloc(XGENE_ENET_NUM_DESC, sizeof(struct pkt_info),
+   ring->pkt_info = kcalloc(XGENE_ENET_NUM_DESC, sizeof(*ring->pkt_info),
 GFP_KERNEL);
if (!ring->pkt_info)
goto err;
@@ -598,28 +595,28 @@ static void xge_timeout(struct net_device *ndev)
 
rtnl_lock();
 
-   if (netif_running(ndev)) {
-   netif_carrier_off(ndev);
-   netif_stop_queue(ndev);
-   xge_intr_disable(pdata);
-   napi_disable(>napi);
+   if (!netif_running(ndev))
+   goto out;
 
-   xge_wr_csr(pdata, DMATXCTRL, 0);
-   xge_txc_poll(ndev);
-   xge_free_pending_skb(ndev);
-   xge_wr_csr(pdata, DMATXSTATUS, ~0U);
+   netif_stop_queue(ndev);
+   xge_intr_disable(pdata);
+   napi_disable(>napi);
 
-   xge_setup_desc(pdata->tx_ring);
-   xge_update_tx_desc_addr(pdata);
-   xge_mac_init(pdata);
+   xge_wr_csr(pdata, DMATXCTRL, 0);
+   xge_txc_poll(ndev);
+   xge_free_pending_skb(ndev);
+   xge_wr_csr(pdata, DMATXSTATUS, ~0U);
 
-   napi_enable(>napi);
-   xge_intr_enable(pdata);
-   xge_mac_enable(pdata);
-   netif_start_queue(ndev);
-   netif_carrier_on(ndev);
-   }
+   xge_setup_desc(pdata->tx_ring);
+   xge_update_tx_desc_addr(pdata);
+   xge_mac_init(pdata);
+
+   napi_enable(>napi);
+   xge_intr_enable(pdata);
+   xge_mac_enable(pdata);
+   netif_start_queue(ndev);
 
+out:
rtnl_unlock();
 }
 
@@ -653,7 +650,7 @@ static int xge_probe(struct platform_device *pdev)
struct xge_pdata *pdata;
int ret;
 
-   ndev = alloc_etherdev(sizeof(struct xge_pdata));
+   ndev = alloc_etherdev(sizeof(*pdata));
if (!ndev)
return -ENOMEM;
 
-- 
1.9.1



[PATCH net-next 3/4] drivers: net: xgene-v2: Fix port reset

2017-03-21 Thread Iyappan Subramanian
Fixed port reset sequence by adding ECC init.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
 drivers/net/ethernet/apm/xgene-v2/enet.c | 24 ++--
 drivers/net/ethernet/apm/xgene-v2/enet.h |  2 ++
 drivers/net/ethernet/apm/xgene-v2/mac.h  |  1 -
 3 files changed, 20 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene-v2/enet.c 
b/drivers/net/ethernet/apm/xgene-v2/enet.c
index b49edee..5998da0 100644
--- a/drivers/net/ethernet/apm/xgene-v2/enet.c
+++ b/drivers/net/ethernet/apm/xgene-v2/enet.c
@@ -38,10 +38,24 @@ u32 xge_rd_csr(struct xge_pdata *pdata, u32 offset)
 int xge_port_reset(struct net_device *ndev)
 {
struct xge_pdata *pdata = netdev_priv(ndev);
+   struct device *dev = >pdev->dev;
+   u32 data, wait = 10;
 
-   xge_wr_csr(pdata, ENET_SRST, 0x3);
-   xge_wr_csr(pdata, ENET_SRST, 0x2);
-   xge_wr_csr(pdata, ENET_SRST, 0x0);
+   xge_wr_csr(pdata, ENET_CLKEN, 0x3);
+   xge_wr_csr(pdata, ENET_SRST, 0xf);
+   xge_wr_csr(pdata, ENET_SRST, 0);
+   xge_wr_csr(pdata, CFG_MEM_RAM_SHUTDOWN, 1);
+   xge_wr_csr(pdata, CFG_MEM_RAM_SHUTDOWN, 0);
+
+   do {
+   usleep_range(100, 110);
+   data = xge_rd_csr(pdata, BLOCK_MEM_RDY);
+   } while (data != MEM_RDY && wait--);
+
+   if (data != MEM_RDY) {
+   dev_err(dev, "ECC init failed: %x\n", data);
+   return -ETIMEDOUT;
+   }
 
xge_wr_csr(pdata, ENET_SHIM, DEVM_ARAUX_COH | DEVM_AWAUX_COH);
 
@@ -59,13 +73,11 @@ static void xge_traffic_resume(struct net_device *ndev)
xge_wr_csr(pdata, RX_DV_GATE_REG, 1);
 }
 
-int xge_port_init(struct net_device *ndev)
+void xge_port_init(struct net_device *ndev)
 {
struct xge_pdata *pdata = netdev_priv(ndev);
 
pdata->phy_speed = SPEED_1000;
xge_mac_init(pdata);
xge_traffic_resume(ndev);
-
-   return 0;
 }
diff --git a/drivers/net/ethernet/apm/xgene-v2/enet.h 
b/drivers/net/ethernet/apm/xgene-v2/enet.h
index 40371cf..3fd36dc6 100644
--- a/drivers/net/ethernet/apm/xgene-v2/enet.h
+++ b/drivers/net/ethernet/apm/xgene-v2/enet.h
@@ -28,6 +28,7 @@
 #define CFG_MEM_RAM_SHUTDOWN   0xd070
 #define BLOCK_MEM_RDY  0xd074
 
+#define MEM_RDY0x
 #define DEVM_ARAUX_COH BIT(19)
 #define DEVM_AWAUX_COH BIT(3)
 
@@ -39,5 +40,6 @@
 void xge_wr_csr(struct xge_pdata *pdata, u32 offset, u32 val);
 u32 xge_rd_csr(struct xge_pdata *pdata, u32 offset);
 int xge_port_reset(struct net_device *ndev);
+void xge_port_init(struct net_device *ndev);
 
 #endif  /* __XGENE_ENET_V2_ENET__H__ */
diff --git a/drivers/net/ethernet/apm/xgene-v2/mac.h 
b/drivers/net/ethernet/apm/xgene-v2/mac.h
index 74397c9..18a9c9d 100644
--- a/drivers/net/ethernet/apm/xgene-v2/mac.h
+++ b/drivers/net/ethernet/apm/xgene-v2/mac.h
@@ -105,7 +105,6 @@ static inline u32 xgene_get_reg_bits(u32 var, int pos, int 
len)
 void xge_mac_enable(struct xge_pdata *pdata);
 void xge_mac_disable(struct xge_pdata *pdata);
 void xge_mac_init(struct xge_pdata *pdata);
-int xge_port_init(struct net_device *ndev);
 void xge_mac_set_station_addr(struct xge_pdata *pdata);
 
 #endif /* __XGENE_ENET_V2_MAC_H__ */
-- 
1.9.1



[PATCH net-next 2/4] drivers: net: xgene-v2: Add ethtool support

2017-03-21 Thread Iyappan Subramanian
Added basic ethtool support.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
 drivers/net/ethernet/apm/xgene-v2/Makefile  |   2 +-
 drivers/net/ethernet/apm/xgene-v2/ethtool.c | 121 
 drivers/net/ethernet/apm/xgene-v2/main.c|   1 +
 drivers/net/ethernet/apm/xgene-v2/main.h|   1 +
 4 files changed, 124 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/ethtool.c

diff --git a/drivers/net/ethernet/apm/xgene-v2/Makefile 
b/drivers/net/ethernet/apm/xgene-v2/Makefile
index 0fa5975..f16a2b3 100644
--- a/drivers/net/ethernet/apm/xgene-v2/Makefile
+++ b/drivers/net/ethernet/apm/xgene-v2/Makefile
@@ -2,5 +2,5 @@
 # Makefile for APM X-Gene Ethernet v2 driver
 #
 
-xgene-enet-v2-objs := main.o mac.o enet.o ring.o mdio.o
+xgene-enet-v2-objs := main.o mac.o enet.o ring.o mdio.o ethtool.o
 obj-$(CONFIG_NET_XGENE_V2) += xgene-enet-v2.o
diff --git a/drivers/net/ethernet/apm/xgene-v2/ethtool.c 
b/drivers/net/ethernet/apm/xgene-v2/ethtool.c
new file mode 100644
index 000..0c426f5
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/ethtool.c
@@ -0,0 +1,121 @@
+/*
+ * Applied Micro X-Gene SoC Ethernet v2 Driver
+ *
+ * Copyright (c) 2017, Applied Micro Circuits Corporation
+ * Author(s): Iyappan Subramanian <isubraman...@apm.com>
+ *   Keyur Chudgar <kchud...@apm.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "main.h"
+
+struct xge_gstrings_stats {
+   char name[ETH_GSTRING_LEN];
+   int offset;
+};
+
+#define XGE_STAT(m){ #m, offsetof(struct xge_pdata, stats.m) }
+
+static const struct xge_gstrings_stats gstrings_stats[] = {
+   XGE_STAT(rx_packets),
+   XGE_STAT(tx_packets),
+   XGE_STAT(rx_bytes),
+   XGE_STAT(tx_bytes),
+   XGE_STAT(rx_errors)
+};
+
+#define XGE_STATS_LEN  ARRAY_SIZE(gstrings_stats)
+
+static void xge_get_drvinfo(struct net_device *ndev,
+   struct ethtool_drvinfo *info)
+{
+   struct xge_pdata *pdata = netdev_priv(ndev);
+   struct platform_device *pdev = pdata->pdev;
+
+   strcpy(info->driver, "xgene-enet-v2");
+   strcpy(info->version, XGENE_ENET_V2_VERSION);
+   snprintf(info->fw_version, ETHTOOL_FWVERS_LEN, "N/A");
+   sprintf(info->bus_info, "%s", pdev->name);
+}
+
+static void xge_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
+{
+   u8 *p = data;
+   int i;
+
+   if (stringset != ETH_SS_STATS)
+   return;
+
+   for (i = 0; i < XGE_STATS_LEN; i++) {
+   memcpy(p, gstrings_stats[i].name, ETH_GSTRING_LEN);
+   p += ETH_GSTRING_LEN;
+   }
+}
+
+static int xge_get_sset_count(struct net_device *ndev, int sset)
+{
+   if (sset != ETH_SS_STATS)
+   return -EINVAL;
+
+   return XGE_STATS_LEN;
+}
+
+static void xge_get_ethtool_stats(struct net_device *ndev,
+ struct ethtool_stats *dummy,
+ u64 *data)
+{
+   void *pdata = netdev_priv(ndev);
+   int i;
+
+   for (i = 0; i < XGE_STATS_LEN; i++)
+   *data++ = *(u64 *)(pdata + gstrings_stats[i].offset);
+}
+
+static int xge_get_link_ksettings(struct net_device *ndev,
+ struct ethtool_link_ksettings *cmd)
+{
+   struct phy_device *phydev = ndev->phydev;
+
+   if (!phydev)
+   return -ENODEV;
+
+   return phy_ethtool_ksettings_get(phydev, cmd);
+}
+
+static int xge_set_link_ksettings(struct net_device *ndev,
+ const struct ethtool_link_ksettings *cmd)
+{
+   struct phy_device *phydev = ndev->phydev;
+
+   if (!phydev)
+   return -ENODEV;
+
+   return phy_ethtool_ksettings_set(phydev, cmd);
+}
+
+static const struct ethtool_ops xge_ethtool_ops = {
+   .get_drvinfo = xge_get_drvinfo,
+   .get_link = ethtool_op_get_link,
+   .get_strings = xge_get_strings,
+   .get_sset_count = xge_get_sset_count,
+   .get_ethtool_stats = xge_get_ethtool_stats,
+   .get_link_ksettings = xge_get_link_ksettings,
+   .set_link_ksettings = xge_set_link_ksettings,
+};
+
+void xge_set_ethtool_ops(struct net_device *ndev)
+{
+   ndev->ethtool_ops = _ethtool_o

[PATCH net-next 0/4] drivers: net: xgene-v2: Add MDIO and ethtool support

2017-03-21 Thread Iyappan Subramanian
This patch set,

- adds phy management and ethtool support
- fixes ethernet reset
- addresses review comments from previous patch set

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---

Iyappan Subramanian (4):
  drivers: net: xgene-v2: Add MDIO support
  drivers: net: xgene-v2: Add ethtool support
  drivers: net: xgene-v2: Fix port reset
  drivers: net: xgene-v2: misc fixes

 drivers/net/ethernet/apm/xgene-v2/Makefile  |   2 +-
 drivers/net/ethernet/apm/xgene-v2/enet.c|  24 +++-
 drivers/net/ethernet/apm/xgene-v2/enet.h|   2 +
 drivers/net/ethernet/apm/xgene-v2/ethtool.c | 121 +++
 drivers/net/ethernet/apm/xgene-v2/mac.c |   2 +-
 drivers/net/ethernet/apm/xgene-v2/mac.h |   2 +-
 drivers/net/ethernet/apm/xgene-v2/main.c|  69 ++-
 drivers/net/ethernet/apm/xgene-v2/main.h|   6 +
 drivers/net/ethernet/apm/xgene-v2/mdio.c| 178 
 9 files changed, 365 insertions(+), 41 deletions(-)
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/ethtool.c
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/mdio.c

-- 
1.9.1



[PATCH net-next 1/4] drivers: net: xgene-v2: Add MDIO support

2017-03-21 Thread Iyappan Subramanian
Added phy management support by using phy abstraction layer APIs.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
 drivers/net/ethernet/apm/xgene-v2/Makefile |   2 +-
 drivers/net/ethernet/apm/xgene-v2/mac.c|   2 +-
 drivers/net/ethernet/apm/xgene-v2/mac.h|   1 +
 drivers/net/ethernet/apm/xgene-v2/main.c   |  13 ++-
 drivers/net/ethernet/apm/xgene-v2/main.h   |   5 +
 drivers/net/ethernet/apm/xgene-v2/mdio.c   | 178 +
 6 files changed, 196 insertions(+), 5 deletions(-)
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/mdio.c

diff --git a/drivers/net/ethernet/apm/xgene-v2/Makefile 
b/drivers/net/ethernet/apm/xgene-v2/Makefile
index 735309c..0fa5975 100644
--- a/drivers/net/ethernet/apm/xgene-v2/Makefile
+++ b/drivers/net/ethernet/apm/xgene-v2/Makefile
@@ -2,5 +2,5 @@
 # Makefile for APM X-Gene Ethernet v2 driver
 #
 
-xgene-enet-v2-objs := main.o mac.o enet.o ring.o
+xgene-enet-v2-objs := main.o mac.o enet.o ring.o mdio.o
 obj-$(CONFIG_NET_XGENE_V2) += xgene-enet-v2.o
diff --git a/drivers/net/ethernet/apm/xgene-v2/mac.c 
b/drivers/net/ethernet/apm/xgene-v2/mac.c
index c3189de..ee431e3 100644
--- a/drivers/net/ethernet/apm/xgene-v2/mac.c
+++ b/drivers/net/ethernet/apm/xgene-v2/mac.c
@@ -27,7 +27,7 @@ void xge_mac_reset(struct xge_pdata *pdata)
xge_wr_csr(pdata, MAC_CONFIG_1, 0);
 }
 
-static void xge_mac_set_speed(struct xge_pdata *pdata)
+void xge_mac_set_speed(struct xge_pdata *pdata)
 {
u32 icm0, icm2, ecm0, mc2;
u32 intf_ctrl, rgmii;
diff --git a/drivers/net/ethernet/apm/xgene-v2/mac.h 
b/drivers/net/ethernet/apm/xgene-v2/mac.h
index 0fce6ae..74397c9 100644
--- a/drivers/net/ethernet/apm/xgene-v2/mac.h
+++ b/drivers/net/ethernet/apm/xgene-v2/mac.h
@@ -101,6 +101,7 @@ static inline u32 xgene_get_reg_bits(u32 var, int pos, int 
len)
 struct xge_pdata;
 
 void xge_mac_reset(struct xge_pdata *pdata);
+void xge_mac_set_speed(struct xge_pdata *pdata);
 void xge_mac_enable(struct xge_pdata *pdata);
 void xge_mac_disable(struct xge_pdata *pdata);
 void xge_mac_init(struct xge_pdata *pdata);
diff --git a/drivers/net/ethernet/apm/xgene-v2/main.c 
b/drivers/net/ethernet/apm/xgene-v2/main.c
index ae76977..10d4aff 100644
--- a/drivers/net/ethernet/apm/xgene-v2/main.c
+++ b/drivers/net/ethernet/apm/xgene-v2/main.c
@@ -500,9 +500,10 @@ static int xge_open(struct net_device *ndev)
 
xge_intr_enable(pdata);
xge_wr_csr(pdata, DMARXCTRL, 1);
+
+   phy_start(ndev->phydev);
xge_mac_enable(pdata);
netif_start_queue(ndev);
-   netif_carrier_on(ndev);
 
return 0;
 }
@@ -511,9 +512,9 @@ static int xge_close(struct net_device *ndev)
 {
struct xge_pdata *pdata = netdev_priv(ndev);
 
-   netif_carrier_off(ndev);
netif_stop_queue(ndev);
xge_mac_disable(pdata);
+   phy_stop(ndev->phydev);
 
xge_intr_disable(pdata);
xge_free_irq(ndev);
@@ -683,9 +684,14 @@ static int xge_probe(struct platform_device *pdev)
if (ret)
goto err;
 
+   spin_lock_init(>mdio_lock);
+
+   ret = xge_mdio_config(ndev);
+   if (ret)
+   goto err;
+
netif_napi_add(ndev, >napi, xge_napi, NAPI_POLL_WEIGHT);
 
-   netif_carrier_off(ndev);
ret = register_netdev(ndev);
if (ret) {
netdev_err(ndev, "Failed to register netdev\n");
@@ -713,6 +719,7 @@ static int xge_remove(struct platform_device *pdev)
dev_close(ndev);
rtnl_unlock();
 
+   xge_mdio_remove(ndev);
unregister_netdev(ndev);
free_netdev(ndev);
 
diff --git a/drivers/net/ethernet/apm/xgene-v2/main.h 
b/drivers/net/ethernet/apm/xgene-v2/main.h
index ada7b0e..3e98bb4 100644
--- a/drivers/net/ethernet/apm/xgene-v2/main.h
+++ b/drivers/net/ethernet/apm/xgene-v2/main.h
@@ -65,11 +65,16 @@ struct xge_pdata {
struct xge_desc_ring *rx_ring;
struct platform_device *pdev;
char irq_name[IRQ_ID_SIZE];
+   struct mii_bus *mdio_bus;
struct net_device *ndev;
struct napi_struct napi;
struct xge_stats stats;
+   spinlock_t mdio_lock; /* mdio lock */
int phy_speed;
u8 nbufs;
 };
 
+int xge_mdio_config(struct net_device *ndev);
+void xge_mdio_remove(struct net_device *ndev);
+
 #endif /* __XGENE_ENET_V2_MAIN_H__ */
diff --git a/drivers/net/ethernet/apm/xgene-v2/mdio.c 
b/drivers/net/ethernet/apm/xgene-v2/mdio.c
new file mode 100644
index 000..43f454d
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/mdio.c
@@ -0,0 +1,178 @@
+/*
+ * Applied Micro X-Gene SoC Ethernet v2 Driver
+ *
+ * Copyright (c) 2017, Applied Micro Circuits Corporation
+ * Author(s): Iyappan Subramanian <isubraman...@apm.com>
+ *   Keyur Chudgar <kchud...@apm.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Fre

[PATCH net-next 5/7] drivers: net: xgene: Add workaround for errata 10GE_1

2017-03-15 Thread Iyappan Subramanian
From: Quan Nguyen <qngu...@apm.com>

This patch implements workaround for errata 10GE_1:
10Gb Ethernet port FIFO threshold default values are incorrect.

Signed-off-by: Quan Nguyen <qngu...@apm.com>
Signed-off-by: Toan Le <toa...@apm.com>
Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
Tested-by: Fushen Chen <fc...@apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c | 7 +++
 drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h | 5 +
 2 files changed, 12 insertions(+)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
index ece19e6..423240c 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
@@ -341,8 +341,15 @@ static void xgene_xgmac_init(struct xgene_enet_pdata 
*pdata)
 
xgene_enet_rd_csr(pdata, XG_RSIF_CONFIG_REG_ADDR, );
data |= CFG_RSIF_FPBUFF_TIMEOUT_EN;
+   /* Errata 10GE_1 - FIFO threshold default value incorrect */
+   RSIF_CLE_BUFF_THRESH_SET(, XG_RSIF_CLE_BUFF_THRESH);
xgene_enet_wr_csr(pdata, XG_RSIF_CONFIG_REG_ADDR, data);
 
+   /* Errata 10GE_1 - FIFO threshold default value incorrect */
+   xgene_enet_rd_csr(pdata, XG_RSIF_CONFIG1_REG_ADDR, );
+   RSIF_PLC_CLE_BUFF_THRESH_SET(, XG_RSIF_PLC_CLE_BUFF_THRESH);
+   xgene_enet_wr_csr(pdata, XG_RSIF_CONFIG1_REG_ADDR, data);
+
xgene_enet_rd_csr(pdata, XG_ENET_SPARE_CFG_REG_ADDR, );
data |= BIT(12);
xgene_enet_wr_csr(pdata, XG_ENET_SPARE_CFG_REG_ADDR, data);
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h 
b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h
index 03b847a..e644a42 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h
@@ -65,6 +65,11 @@
 #define XG_DEF_PAUSE_THRES 0x390
 #define XG_DEF_PAUSE_OFF_THRES 0x2c0
 #define XG_RSIF_CONFIG_REG_ADDR0x00a0
+#define XG_RSIF_CLE_BUFF_THRESH0x3
+#define RSIF_CLE_BUFF_THRESH_SET(dst, val) xgene_set_bits(dst, val, 0, 3)
+#define XG_RSIF_CONFIG1_REG_ADDR   0x00b8
+#define XG_RSIF_PLC_CLE_BUFF_THRESH0x1
+#define RSIF_PLC_CLE_BUFF_THRESH_SET(dst, val) xgene_set_bits(dst, val, 0, 2)
 #define XCLE_BYPASS_REG0_ADDR   0x0160
 #define XCLE_BYPASS_REG1_ADDR   0x0164
 #define XG_CFG_BYPASS_ADDR 0x0204
-- 
1.9.1



[PATCH net-next 6/7] drivers: net: xgene: Add workaround for errata 10GE_8/ENET_11

2017-03-15 Thread Iyappan Subramanian
This patch implements workaround for errata 10GE_8 and ENET_11:
"HW reports length error for valid 64 byte frames with len <46 bytes"
by recovering them from error.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
Signed-off-by: Quan Nguyen <qngu...@apm.com>
Signed-off-by: Toan Le <toa...@apm.com>
Tested-by: Fushen Chen <fc...@apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.c   |  2 +-
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.h   |  1 +
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 43 +++-
 drivers/net/ethernet/apm/xgene/xgene_enet_main.h |  1 +
 4 files changed, 30 insertions(+), 17 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
index c72a17e..2a835e0 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
@@ -494,7 +494,7 @@ static void xgene_gmac_set_speed(struct xgene_enet_pdata 
*pdata)
break;
}
 
-   mc2 |= FULL_DUPLEX2 | PAD_CRC;
+   mc2 |= FULL_DUPLEX2 | PAD_CRC | LENGTH_CHK;
xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_2_ADDR, mc2);
xgene_enet_wr_mcx_mac(pdata, INTERFACE_CONTROL_ADDR, intf_ctl);
xgene_enet_wr_csr(pdata, RGMII_REG_0_ADDR, rgmii);
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h 
b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
index b6cd625..d250bfe 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
@@ -216,6 +216,7 @@ enum xgene_enet_rm {
 #define ENET_GHD_MODE  BIT(26)
 #define FULL_DUPLEX2   BIT(0)
 #define PAD_CRCBIT(2)
+#define LENGTH_CHK BIT(4)
 #define SCAN_AUTO_INCR BIT(5)
 #define TBYT_ADDR  0x38
 #define TPKT_ADDR  0x39
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index e881365..5f37ed3 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -658,12 +658,24 @@ static void xgene_enet_free_pagepool(struct 
xgene_enet_desc_ring *buf_pool,
buf_pool->head = head;
 }
 
+/* Errata 10GE_8 and ENET_11 - allow packet with length <=64B */
+static bool xgene_enet_errata_10GE_8(struct sk_buff *skb, u32 len, u8 status)
+{
+   if (status == INGRESS_PKT_LEN && len == ETHER_MIN_PACKET) {
+   if (ntohs(eth_hdr(skb)->h_proto) < 46)
+   return true;
+   }
+
+   return false;
+}
+
 static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring,
   struct xgene_enet_raw_desc *raw_desc,
   struct xgene_enet_raw_desc *exp_desc)
 {
struct xgene_enet_desc_ring *buf_pool, *page_pool;
u32 datalen, frag_size, skb_index;
+   struct xgene_enet_pdata *pdata;
struct net_device *ndev;
dma_addr_t dma_addr;
struct sk_buff *skb;
@@ -676,6 +688,7 @@ static int xgene_enet_rx_frame(struct xgene_enet_desc_ring 
*rx_ring,
bool nv;
 
ndev = rx_ring->ndev;
+   pdata = netdev_priv(ndev);
dev = ndev_to_dev(rx_ring->ndev);
buf_pool = rx_ring->buf_pool;
page_pool = rx_ring->page_pool;
@@ -686,30 +699,29 @@ static int xgene_enet_rx_frame(struct 
xgene_enet_desc_ring *rx_ring,
skb = buf_pool->rx_skb[skb_index];
buf_pool->rx_skb[skb_index] = NULL;
 
+   datalen = xgene_enet_get_data_len(le64_to_cpu(raw_desc->m1));
+   skb_put(skb, datalen);
+   prefetch(skb->data - NET_IP_ALIGN);
+   skb->protocol = eth_type_trans(skb, ndev);
+
/* checking for error */
status = (GET_VAL(ELERR, le64_to_cpu(raw_desc->m0)) << LERR_LEN) |
  GET_VAL(LERR, le64_to_cpu(raw_desc->m0));
if (unlikely(status)) {
-   dev_kfree_skb_any(skb);
-   xgene_enet_free_pagepool(page_pool, raw_desc, exp_desc);
-   xgene_enet_parse_error(rx_ring, netdev_priv(rx_ring->ndev),
-  status);
-   ret = -EIO;
-   goto out;
+   if (!xgene_enet_errata_10GE_8(skb, datalen, status)) {
+   dev_kfree_skb_any(skb);
+   xgene_enet_free_pagepool(page_pool, raw_desc, exp_desc);
+   xgene_enet_parse_error(rx_ring, pdata, status);
+   goto out;
+   }
}
 
-   /* strip off CRC as HW isn't doing this */
-   datalen = xgene_enet_get_data_len(le64_to_cpu(raw_desc->m1));
-
nv = GET_VAL(NV, le64_to_cpu(raw_desc->m0));
-   if (!nv)
+   if (!nv) {
+   /* strip off CRC as HW isn't doing this */

[PATCH net-next 4/7] drivers: net: xgene: Fix Rx checksum validation logic

2017-03-15 Thread Iyappan Subramanian
This patch fixes Rx checksum validation logic and
adds NETIF_F_RXCSUM flag.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 27 +++-
 1 file changed, 17 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index ec43278..e881365 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -601,14 +601,24 @@ static netdev_tx_t xgene_enet_start_xmit(struct sk_buff 
*skb,
return NETDEV_TX_OK;
 }
 
-static void xgene_enet_skip_csum(struct sk_buff *skb)
+static void xgene_enet_rx_csum(struct sk_buff *skb)
 {
+   struct net_device *ndev = skb->dev;
struct iphdr *iph = ip_hdr(skb);
 
-   if (!ip_is_fragment(iph) ||
-   (iph->protocol != IPPROTO_TCP && iph->protocol != IPPROTO_UDP)) {
-   skb->ip_summed = CHECKSUM_UNNECESSARY;
-   }
+   if (!(ndev->features & NETIF_F_RXCSUM))
+   return;
+
+   if (skb->protocol != htons(ETH_P_IP))
+   return;
+
+   if (ip_is_fragment(iph))
+   return;
+
+   if (iph->protocol != IPPROTO_TCP && iph->protocol != IPPROTO_UDP)
+   return;
+
+   skb->ip_summed = CHECKSUM_UNNECESSARY;
 }
 
 static void xgene_enet_free_pagepool(struct xgene_enet_desc_ring *buf_pool,
@@ -729,10 +739,7 @@ static int xgene_enet_rx_frame(struct xgene_enet_desc_ring 
*rx_ring,
 skip_jumbo:
skb_checksum_none_assert(skb);
skb->protocol = eth_type_trans(skb, ndev);
-   if (likely((ndev->features & NETIF_F_IP_CSUM) &&
-  skb->protocol == htons(ETH_P_IP))) {
-   xgene_enet_skip_csum(skb);
-   }
+   xgene_enet_rx_csum(skb);
 
rx_ring->rx_packets++;
rx_ring->rx_bytes += datalen;
@@ -2039,7 +2046,7 @@ static int xgene_enet_probe(struct platform_device *pdev)
xgene_enet_setup_ops(pdata);
 
if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) {
-   ndev->features |= NETIF_F_TSO;
+   ndev->features |= NETIF_F_TSO | NETIF_F_RXCSUM;
spin_lock_init(>mss_lock);
}
ndev->hw_features = ndev->features;
-- 
1.9.1



[PATCH net-next 3/7] drivers: net: xgene: Fix wrong logical operation

2017-03-15 Thread Iyappan Subramanian
From: Quan Nguyen <qngu...@apm.com>

This patch fixes the wrong logical OR operation by changing it to
bit-wise OR operation.

Fixes: 3bb502f83080 ("drivers: net: xgene: fix statistics counters race 
condition")
Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
Signed-off-by: Quan Nguyen <qngu...@apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index b3568c4..ec43278 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -677,9 +677,9 @@ static int xgene_enet_rx_frame(struct xgene_enet_desc_ring 
*rx_ring,
buf_pool->rx_skb[skb_index] = NULL;
 
/* checking for error */
-   status = (GET_VAL(ELERR, le64_to_cpu(raw_desc->m0)) << LERR_LEN) ||
+   status = (GET_VAL(ELERR, le64_to_cpu(raw_desc->m0)) << LERR_LEN) |
  GET_VAL(LERR, le64_to_cpu(raw_desc->m0));
-   if (unlikely(status > 2)) {
+   if (unlikely(status)) {
dev_kfree_skb_any(skb);
xgene_enet_free_pagepool(page_pool, raw_desc, exp_desc);
xgene_enet_parse_error(rx_ring, netdev_priv(rx_ring->ndev),
-- 
1.9.1



[PATCH net-next 0/7] drivers: net: xgene: Bug fixes and errata workarounds

2017-03-15 Thread Iyappan Subramanian
This patch set addresses bug fixes and errata workarounds.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
Signed-off-by: Quan Nguyen <qngu...@apm.com>
---

Iyappan Subramanian (3):
  drivers: net: xgene: Fix Rx checksum validation logic
  drivers: net: xgene: Add workaround for errata 10GE_8/ENET_11
  MAINTAINERS: Update X-Gene SoC ethernet maintainer

Quan Nguyen (4):
  drivers: net: phy: xgene: Fix mdio write
  drivers: net: xgene: Fix hardware checksum setting
  drivers: net: xgene: Fix wrong logical operation
  drivers: net: xgene: Add workaround for errata 10GE_1

 MAINTAINERS   |  1 +
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.c|  3 +-
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.h|  2 +
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c  | 74 ++-
 drivers/net/ethernet/apm/xgene/xgene_enet_main.h  |  1 +
 drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c |  7 +++
 drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h |  5 ++
 drivers/net/phy/mdio-xgene.c  |  2 +-
 8 files changed, 65 insertions(+), 30 deletions(-)

-- 
1.9.1



[PATCH net-next 2/7] drivers: net: xgene: Fix hardware checksum setting

2017-03-15 Thread Iyappan Subramanian
From: Quan Nguyen <qngu...@apm.com>

This patch fixes the hardware checksum settings by properly program
the classifier. Otherwise, packet may be received with checksum error
on X-Gene1 SoC.

Signed-off-by: Quan Nguyen <qngu...@apm.com>
Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.c | 1 +
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.h | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
index 06e6816..c72a17e 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
@@ -623,6 +623,7 @@ static void xgene_enet_cle_bypass(struct xgene_enet_pdata 
*pdata,
xgene_enet_rd_csr(pdata, CLE_BYPASS_REG0_0_ADDR, );
cb |= CFG_CLE_BYPASS_EN0;
CFG_CLE_IP_PROTOCOL0_SET(, 3);
+   CFG_CLE_IP_HDR_LEN_SET(, 0);
xgene_enet_wr_csr(pdata, CLE_BYPASS_REG0_0_ADDR, cb);
 
xgene_enet_rd_csr(pdata, CLE_BYPASS_REG1_0_ADDR, );
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h 
b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
index 5f83037..b6cd625 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
@@ -163,6 +163,7 @@ enum xgene_enet_rm {
 #define CFG_RXCLK_MUXSEL0_SET(dst, val)xgene_set_bits(dst, val, 26, 3)
 
 #define CFG_CLE_IP_PROTOCOL0_SET(dst, val) xgene_set_bits(dst, val, 16, 2)
+#define CFG_CLE_IP_HDR_LEN_SET(dst, val)   xgene_set_bits(dst, val, 8, 5)
 #define CFG_CLE_DSTQID0_SET(dst, val)  xgene_set_bits(dst, val, 0, 12)
 #define CFG_CLE_FPSEL0_SET(dst, val)   xgene_set_bits(dst, val, 16, 4)
 #define CFG_CLE_NXTFPSEL0_SET(dst, val)xgene_set_bits(dst, 
val, 20, 4)
-- 
1.9.1



[PATCH net-next 1/7] drivers: net: phy: xgene: Fix mdio write

2017-03-15 Thread Iyappan Subramanian
From: Quan Nguyen <qngu...@apm.com>

This patches fixes a typo in the argument to xgene_enet_wr_mdio_csr().

Signed-off-by: Quan Nguyen <qngu...@apm.com>
Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
 drivers/net/phy/mdio-xgene.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/phy/mdio-xgene.c b/drivers/net/phy/mdio-xgene.c
index f095051..3e2ac07 100644
--- a/drivers/net/phy/mdio-xgene.c
+++ b/drivers/net/phy/mdio-xgene.c
@@ -229,7 +229,7 @@ static int xgene_xfi_mdio_write(struct mii_bus *bus, int 
phy_id,
 
val = SET_VAL(HSTPHYADX, phy_id) | SET_VAL(HSTREGADX, reg) |
  SET_VAL(HSTMIIMWRDAT, data);
-   xgene_enet_wr_mdio_csr(addr, MIIM_FIELD_ADDR, data);
+   xgene_enet_wr_mdio_csr(addr, MIIM_FIELD_ADDR, val);
 
val = HSTLDCMD | SET_VAL(HSTMIIMCMD, MIIM_CMD_LEGACY_WRITE);
xgene_enet_wr_mdio_csr(addr, MIIM_COMMAND_ADDR, val);
-- 
1.9.1



[PATCH net-next 7/7] MAINTAINERS: Update X-Gene SoC ethernet maintainer

2017-03-15 Thread Iyappan Subramanian
Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
Signed-off-by: Keyur Chudgar <kchud...@apm.com>
Signed-off-by: Quan Nguyen <qngu...@apm.com>
---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index cefda30..632e762 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -896,6 +896,7 @@ F:  arch/arm64/boot/dts/apm/
 APPLIED MICRO (APM) X-GENE SOC ETHERNET DRIVER
 M: Iyappan Subramanian <isubraman...@apm.com>
 M: Keyur Chudgar <kchud...@apm.com>
+M: Quan Nguyen <qngu...@apm.com>
 S: Supported
 F: drivers/net/ethernet/apm/xgene/
 F: drivers/net/phy/mdio-xgene.c
-- 
1.9.1



[PATCH v4 net-next 5/6] drivers: net: xgene-v2: Add transmit and receive

2017-03-07 Thread Iyappan Subramanian
This patch adds,
- Transmit
- Transmit completion poll
- Receive poll
- NAPI handler

and enables the driver.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
Signed-off-by: Keyur Chudgar <kchud...@apm.com>
---
 drivers/net/ethernet/apm/Kconfig   |   1 +
 drivers/net/ethernet/apm/Makefile  |   1 +
 drivers/net/ethernet/apm/xgene-v2/Kconfig  |  11 ++
 drivers/net/ethernet/apm/xgene-v2/Makefile |   6 +
 drivers/net/ethernet/apm/xgene-v2/main.c   | 248 -
 drivers/net/ethernet/apm/xgene-v2/main.h   |   1 +
 6 files changed, 267 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/Kconfig
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/Makefile

diff --git a/drivers/net/ethernet/apm/Kconfig b/drivers/net/ethernet/apm/Kconfig
index ec63d70..59efe5b 100644
--- a/drivers/net/ethernet/apm/Kconfig
+++ b/drivers/net/ethernet/apm/Kconfig
@@ -1 +1,2 @@
 source "drivers/net/ethernet/apm/xgene/Kconfig"
+source "drivers/net/ethernet/apm/xgene-v2/Kconfig"
diff --git a/drivers/net/ethernet/apm/Makefile 
b/drivers/net/ethernet/apm/Makefile
index 65ce32a..946b2a4 100644
--- a/drivers/net/ethernet/apm/Makefile
+++ b/drivers/net/ethernet/apm/Makefile
@@ -3,3 +3,4 @@
 #
 
 obj-$(CONFIG_NET_XGENE) += xgene/
+obj-$(CONFIG_NET_XGENE_V2) += xgene-v2/
diff --git a/drivers/net/ethernet/apm/xgene-v2/Kconfig 
b/drivers/net/ethernet/apm/xgene-v2/Kconfig
new file mode 100644
index 000..1205861
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/Kconfig
@@ -0,0 +1,11 @@
+config NET_XGENE_V2
+   tristate "APM X-Gene SoC Ethernet-v2 Driver"
+   depends on HAS_DMA
+   depends on ARCH_XGENE || COMPILE_TEST
+   help
+ This is the Ethernet driver for the on-chip ethernet interface
+ which uses a linked list of DMA descriptor architecture (v2) for
+ APM X-Gene SoCs.
+
+ To compile this driver as a module, choose M here. This module will
+ be called xgene-enet-v2.
diff --git a/drivers/net/ethernet/apm/xgene-v2/Makefile 
b/drivers/net/ethernet/apm/xgene-v2/Makefile
new file mode 100644
index 000..735309c
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for APM X-Gene Ethernet v2 driver
+#
+
+xgene-enet-v2-objs := main.o mac.o enet.o ring.o
+obj-$(CONFIG_NET_XGENE_V2) += xgene-enet-v2.o
diff --git a/drivers/net/ethernet/apm/xgene-v2/main.c 
b/drivers/net/ethernet/apm/xgene-v2/main.c
index c96b4cc..b16ef43 100644
--- a/drivers/net/ethernet/apm/xgene-v2/main.c
+++ b/drivers/net/ethernet/apm/xgene-v2/main.c
@@ -113,7 +113,7 @@ static int xge_refill_buffers(struct net_device *ndev, u32 
nbuf)
raw_desc->m1 = cpu_to_le64(SET_BITS(NEXT_DESC_ADDRL, addr_lo) |
   SET_BITS(NEXT_DESC_ADDRH, addr_hi) |
   SET_BITS(PKT_ADDRH,
-   dma_addr >> PKT_ADDRL_LEN));
+   upper_32_bits(dma_addr)));
 
dma_wmb();
raw_desc->m0 = cpu_to_le64(SET_BITS(PKT_ADDRL, dma_addr) |
@@ -177,6 +177,194 @@ static void xge_free_irq(struct net_device *ndev)
devm_free_irq(dev, pdata->resources.irq, pdata);
 }
 
+static bool is_tx_slot_available(struct xge_raw_desc *raw_desc)
+{
+   if (GET_BITS(E, le64_to_cpu(raw_desc->m0)) &&
+   (GET_BITS(PKT_SIZE, le64_to_cpu(raw_desc->m0)) == SLOT_EMPTY))
+   return true;
+
+   return false;
+}
+
+static netdev_tx_t xge_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+   struct xge_pdata *pdata = netdev_priv(ndev);
+   struct device *dev = >pdev->dev;
+   static dma_addr_t dma_addr;
+   struct xge_desc_ring *tx_ring;
+   struct xge_raw_desc *raw_desc;
+   u64 addr_lo, addr_hi;
+   void *pkt_buf;
+   u8 tail;
+   u16 len;
+
+   tx_ring = pdata->tx_ring;
+   tail = tx_ring->tail;
+   len = skb_headlen(skb);
+   raw_desc = _ring->raw_desc[tail];
+
+   if (!is_tx_slot_available(raw_desc)) {
+   netif_stop_queue(ndev);
+   return NETDEV_TX_BUSY;
+   }
+
+   /* Packet buffers should be 64B aligned */
+   pkt_buf = dma_zalloc_coherent(dev, XGENE_ENET_STD_MTU, _addr,
+ GFP_ATOMIC);
+   if (unlikely(!pkt_buf)) {
+   dev_kfree_skb_any(skb);
+   return NETDEV_TX_OK;
+   }
+   memcpy(pkt_buf, skb->data, len);
+
+   addr_hi = GET_BITS(NEXT_DESC_ADDRH, le64_to_cpu(raw_desc->m1));
+   addr_lo = GET_BITS(NEXT_DESC_ADDRL, le64_to_cpu(raw_desc->m1));
+   raw_desc->m1 = cpu_to_le64(SET_BITS(NEXT_DESC_ADDRL, addr_lo) |
+  SET_BITS(NEXT_DESC_ADDRH, addr_hi) |
+  

[PATCH v4 net-next 0/6] drivers: net: xgene-v2: Add RGMII based 1G driver

2017-03-07 Thread Iyappan Subramanian
This patch set adds support for RGMII based 1GbE hardware which uses a linked
list of DMA descriptor architecture (v2) for APM X-Gene SoCs.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
v4: Address review comments from v3
- fixed local variable declarations to reverse christmas tree order

v3: Address review comments from v2
- fixed kbuild warnings (this 'if' clause does not guard)

v2: Address review comments from v1
- moved create_desc_ring and delete_desc_ring to open() and close()
  respectively
- changed to use dma_zalloc APIs
- fixed tx_timeout()
- removed tx completion polling upper bound
- added error checking on rx packets
- added netif_stop_queue() and netif_wake_queue()

v1:
- Initial version
---

Iyappan Subramanian (6):
  drivers: net: xgene-v2: Add DMA descriptor
  drivers: net: xgene-v2: Add mac configuration
  drivers: net: xgene-v2: Add ethernet hardware configuration
  drivers: net: xgene-v2: Add base driver
  drivers: net: xgene-v2: Add transmit and receive
  MAINTAINERS: Add entry for APM X-Gene SoC Ethernet (v2) driver

 MAINTAINERS|   6 +
 drivers/net/ethernet/apm/Kconfig   |   1 +
 drivers/net/ethernet/apm/Makefile  |   1 +
 drivers/net/ethernet/apm/xgene-v2/Kconfig  |  11 +
 drivers/net/ethernet/apm/xgene-v2/Makefile |   6 +
 drivers/net/ethernet/apm/xgene-v2/enet.c   |  71 +++
 drivers/net/ethernet/apm/xgene-v2/enet.h   |  43 ++
 drivers/net/ethernet/apm/xgene-v2/mac.c| 116 +
 drivers/net/ethernet/apm/xgene-v2/mac.h| 110 +
 drivers/net/ethernet/apm/xgene-v2/main.c   | 756 +
 drivers/net/ethernet/apm/xgene-v2/main.h   |  75 +++
 drivers/net/ethernet/apm/xgene-v2/ring.c   |  81 
 drivers/net/ethernet/apm/xgene-v2/ring.h   | 119 +
 13 files changed, 1396 insertions(+)
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/Kconfig
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/Makefile
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/enet.c
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/enet.h
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/mac.c
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/mac.h
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/main.c
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/main.h
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/ring.c
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/ring.h

-- 
1.9.1



[PATCH v4 net-next 4/6] drivers: net: xgene-v2: Add base driver

2017-03-07 Thread Iyappan Subramanian
This patch adds,

 - probe, remove, shutdown
 - open, close and stats
 - create and delete ring
 - request and delete irq

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
Signed-off-by: Keyur Chudgar <kchud...@apm.com>
---
 drivers/net/ethernet/apm/xgene-v2/main.c | 510 +++
 1 file changed, 510 insertions(+)
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/main.c

diff --git a/drivers/net/ethernet/apm/xgene-v2/main.c 
b/drivers/net/ethernet/apm/xgene-v2/main.c
new file mode 100644
index 000..c96b4cc
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/main.c
@@ -0,0 +1,510 @@
+/*
+ * Applied Micro X-Gene SoC Ethernet v2 Driver
+ *
+ * Copyright (c) 2017, Applied Micro Circuits Corporation
+ * Author(s): Iyappan Subramanian <isubraman...@apm.com>
+ *   Keyur Chudgar <kchud...@apm.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "main.h"
+
+static const struct acpi_device_id xge_acpi_match[];
+
+static int xge_get_resources(struct xge_pdata *pdata)
+{
+   struct platform_device *pdev;
+   struct net_device *ndev;
+   struct device *dev;
+   struct resource *res;
+   int phy_mode, ret = 0;
+
+   pdev = pdata->pdev;
+   dev = >dev;
+   ndev = pdata->ndev;
+
+   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   if (!res) {
+   dev_err(dev, "Resource enet_csr not defined\n");
+   return -ENODEV;
+   }
+
+   pdata->resources.base_addr = devm_ioremap(dev, res->start,
+ resource_size(res));
+   if (!pdata->resources.base_addr) {
+   dev_err(dev, "Unable to retrieve ENET Port CSR region\n");
+   return -ENOMEM;
+   }
+
+   if (!device_get_mac_address(dev, ndev->dev_addr, ETH_ALEN))
+   eth_hw_addr_random(ndev);
+
+   memcpy(ndev->perm_addr, ndev->dev_addr, ndev->addr_len);
+
+   phy_mode = device_get_phy_mode(dev);
+   if (phy_mode < 0) {
+   dev_err(dev, "Unable to get phy-connection-type\n");
+   return phy_mode;
+   }
+   pdata->resources.phy_mode = phy_mode;
+
+   if (pdata->resources.phy_mode != PHY_INTERFACE_MODE_RGMII) {
+   dev_err(dev, "Incorrect phy-connection-type specified\n");
+   return -ENODEV;
+   }
+
+   ret = platform_get_irq(pdev, 0);
+   if (ret <= 0) {
+   dev_err(dev, "Unable to get ENET IRQ\n");
+   ret = ret ? : -ENXIO;
+   return ret;
+   }
+   pdata->resources.irq = ret;
+
+   return 0;
+}
+
+static int xge_refill_buffers(struct net_device *ndev, u32 nbuf)
+{
+   struct xge_pdata *pdata = netdev_priv(ndev);
+   struct xge_desc_ring *ring = pdata->rx_ring;
+   const u8 slots = XGENE_ENET_NUM_DESC - 1;
+   struct device *dev = >pdev->dev;
+   struct xge_raw_desc *raw_desc;
+   u64 addr_lo, addr_hi;
+   u8 tail = ring->tail;
+   struct sk_buff *skb;
+   dma_addr_t dma_addr;
+   u16 len;
+   int i;
+
+   for (i = 0; i < nbuf; i++) {
+   raw_desc = >raw_desc[tail];
+
+   len = XGENE_ENET_STD_MTU;
+   skb = netdev_alloc_skb(ndev, len);
+   if (unlikely(!skb))
+   return -ENOMEM;
+
+   dma_addr = dma_map_single(dev, skb->data, len, DMA_FROM_DEVICE);
+   if (dma_mapping_error(dev, dma_addr)) {
+   netdev_err(ndev, "DMA mapping error\n");
+   dev_kfree_skb_any(skb);
+   return -EINVAL;
+   }
+
+   ring->pkt_info[tail].skb = skb;
+   ring->pkt_info[tail].dma_addr = dma_addr;
+
+   addr_hi = GET_BITS(NEXT_DESC_ADDRH, le64_to_cpu(raw_desc->m1));
+   addr_lo = GET_BITS(NEXT_DESC_ADDRL, le64_to_cpu(raw_desc->m1));
+   raw_desc->m1 = cpu_to_le64(SET_BITS(NEXT_DESC_ADDRL, addr_lo) |
+  SET_BITS(NEXT_DESC_ADDRH, addr_hi) |
+  SET_BITS(PKT_ADDRH,

[PATCH v4 net-next 6/6] MAINTAINERS: Add entry for APM X-Gene SoC Ethernet (v2) driver

2017-03-07 Thread Iyappan Subramanian
This patch adds a MAINTAINERS entry for the ethernet driver for
the on-chip ethernet interface which uses a linked list of DMA
descriptor architecture (v2) for APM X-Gene SoCs.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
Signed-off-by: Keyur Chudgar <kchud...@apm.com>
---
 MAINTAINERS  | 6 ++
 drivers/net/ethernet/apm/xgene-v2/mac.c  | 2 +-
 drivers/net/ethernet/apm/xgene-v2/main.c | 8 
 3 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index c265a5f..e04d3a6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -902,6 +902,12 @@ F: drivers/net/phy/mdio-xgene.c
 F: Documentation/devicetree/bindings/net/apm-xgene-enet.txt
 F: Documentation/devicetree/bindings/net/apm-xgene-mdio.txt
 
+APPLIED MICRO (APM) X-GENE SOC ETHERNET (V2) DRIVER
+M: Iyappan Subramanian <isubraman...@apm.com>
+M: Keyur Chudgar <kchud...@apm.com>
+S: Supported
+F: drivers/net/ethernet/apm/xgene-v2/
+
 APPLIED MICRO (APM) X-GENE SOC PMU
 M: Tai Nguyen <ttngu...@apm.com>
 S: Supported
diff --git a/drivers/net/ethernet/apm/xgene-v2/mac.c 
b/drivers/net/ethernet/apm/xgene-v2/mac.c
index 9c3d32d..c3189de 100644
--- a/drivers/net/ethernet/apm/xgene-v2/mac.c
+++ b/drivers/net/ethernet/apm/xgene-v2/mac.c
@@ -77,8 +77,8 @@ static void xge_mac_set_speed(struct xge_pdata *pdata)
 
 void xge_mac_set_station_addr(struct xge_pdata *pdata)
 {
-   u32 addr0, addr1;
u8 *dev_addr = pdata->ndev->dev_addr;
+   u32 addr0, addr1;
 
addr0 = (dev_addr[3] << 24) | (dev_addr[2] << 16) |
(dev_addr[1] << 8) | dev_addr[0];
diff --git a/drivers/net/ethernet/apm/xgene-v2/main.c 
b/drivers/net/ethernet/apm/xgene-v2/main.c
index b16ef43..ae76977 100644
--- a/drivers/net/ethernet/apm/xgene-v2/main.c
+++ b/drivers/net/ethernet/apm/xgene-v2/main.c
@@ -27,9 +27,9 @@ static int xge_get_resources(struct xge_pdata *pdata)
 {
struct platform_device *pdev;
struct net_device *ndev;
-   struct device *dev;
-   struct resource *res;
int phy_mode, ret = 0;
+   struct resource *res;
+   struct device *dev;
 
pdev = pdata->pdev;
dev = >dev;
@@ -190,9 +190,9 @@ static netdev_tx_t xge_start_xmit(struct sk_buff *skb, 
struct net_device *ndev)
 {
struct xge_pdata *pdata = netdev_priv(ndev);
struct device *dev = >pdev->dev;
-   static dma_addr_t dma_addr;
struct xge_desc_ring *tx_ring;
struct xge_raw_desc *raw_desc;
+   static dma_addr_t dma_addr;
u64 addr_lo, addr_hi;
void *pkt_buf;
u8 tail;
@@ -526,7 +526,7 @@ static int xge_close(struct net_device *ndev)
 static int xge_napi(struct napi_struct *napi, const int budget)
 {
struct net_device *ndev = napi->dev;
-   struct xge_pdata *pdata = netdev_priv(ndev);
+   struct xge_pdata *pdata;
int processed;
 
pdata = netdev_priv(ndev);
-- 
1.9.1



[PATCH v4 net-next 3/6] drivers: net: xgene-v2: Add ethernet hardware configuration

2017-03-07 Thread Iyappan Subramanian
This patch adds functions to configure ethernet hardware.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
Signed-off-by: Keyur Chudgar <kchud...@apm.com>
---
 drivers/net/ethernet/apm/xgene-v2/enet.c | 71 
 drivers/net/ethernet/apm/xgene-v2/enet.h | 43 +++
 2 files changed, 114 insertions(+)
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/enet.c
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/enet.h

diff --git a/drivers/net/ethernet/apm/xgene-v2/enet.c 
b/drivers/net/ethernet/apm/xgene-v2/enet.c
new file mode 100644
index 000..b49edee
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/enet.c
@@ -0,0 +1,71 @@
+/*
+ * Applied Micro X-Gene SoC Ethernet v2 Driver
+ *
+ * Copyright (c) 2017, Applied Micro Circuits Corporation
+ * Author(s): Iyappan Subramanian <isubraman...@apm.com>
+ *   Keyur Chudgar <kchud...@apm.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "main.h"
+
+void xge_wr_csr(struct xge_pdata *pdata, u32 offset, u32 val)
+{
+   void __iomem *addr = pdata->resources.base_addr + offset;
+
+   iowrite32(val, addr);
+}
+
+u32 xge_rd_csr(struct xge_pdata *pdata, u32 offset)
+{
+   void __iomem *addr = pdata->resources.base_addr + offset;
+
+   return ioread32(addr);
+}
+
+int xge_port_reset(struct net_device *ndev)
+{
+   struct xge_pdata *pdata = netdev_priv(ndev);
+
+   xge_wr_csr(pdata, ENET_SRST, 0x3);
+   xge_wr_csr(pdata, ENET_SRST, 0x2);
+   xge_wr_csr(pdata, ENET_SRST, 0x0);
+
+   xge_wr_csr(pdata, ENET_SHIM, DEVM_ARAUX_COH | DEVM_AWAUX_COH);
+
+   return 0;
+}
+
+static void xge_traffic_resume(struct net_device *ndev)
+{
+   struct xge_pdata *pdata = netdev_priv(ndev);
+
+   xge_wr_csr(pdata, CFG_FORCE_LINK_STATUS_EN, 1);
+   xge_wr_csr(pdata, FORCE_LINK_STATUS, 1);
+
+   xge_wr_csr(pdata, CFG_LINK_AGGR_RESUME, 1);
+   xge_wr_csr(pdata, RX_DV_GATE_REG, 1);
+}
+
+int xge_port_init(struct net_device *ndev)
+{
+   struct xge_pdata *pdata = netdev_priv(ndev);
+
+   pdata->phy_speed = SPEED_1000;
+   xge_mac_init(pdata);
+   xge_traffic_resume(ndev);
+
+   return 0;
+}
diff --git a/drivers/net/ethernet/apm/xgene-v2/enet.h 
b/drivers/net/ethernet/apm/xgene-v2/enet.h
new file mode 100644
index 000..40371cf
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/enet.h
@@ -0,0 +1,43 @@
+/*
+ * Applied Micro X-Gene SoC Ethernet v2 Driver
+ *
+ * Copyright (c) 2017, Applied Micro Circuits Corporation
+ * Author(s): Iyappan Subramanian <isubraman...@apm.com>
+ *   Keyur Chudgar <kchud...@apm.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __XGENE_ENET_V2_ENET_H__
+#define __XGENE_ENET_V2_ENET_H__
+
+#define ENET_CLKEN 0xc008
+#define ENET_SRST  0xc000
+#define ENET_SHIM  0xc010
+#define CFG_MEM_RAM_SHUTDOWN   0xd070
+#define BLOCK_MEM_RDY  0xd074
+
+#define DEVM_ARAUX_COH BIT(19)
+#define DEVM_AWAUX_COH BIT(3)
+
+#define CFG_FORCE_LINK_STATUS_EN   0x229c
+#define FORCE_LINK_STATUS  0x22a0
+#define CFG_LINK_AGGR_RESUME   0x27c8
+#define RX_DV_GATE_REG 0x2dfc
+
+void xge_wr_csr(struct xge_pdata *pdata, u32 offset, u32 val);
+u32 xge_rd_csr(struct xge_pdata *pdata, u32 offset);
+int xge_port_reset(struct net_device *ndev);
+
+#endif  /* __XGENE_ENET_V2_ENET__H__ */
-- 
1.9.1



[PATCH v4 net-next 2/6] drivers: net: xgene-v2: Add mac configuration

2017-03-07 Thread Iyappan Subramanian
This patch adds functions to configure and control mac.  This
patch also adds helper functions to get/set registers.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
Signed-off-by: Keyur Chudgar <kchud...@apm.com>
---
 drivers/net/ethernet/apm/xgene-v2/mac.c | 116 
 drivers/net/ethernet/apm/xgene-v2/mac.h | 110 ++
 2 files changed, 226 insertions(+)
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/mac.c
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/mac.h

diff --git a/drivers/net/ethernet/apm/xgene-v2/mac.c 
b/drivers/net/ethernet/apm/xgene-v2/mac.c
new file mode 100644
index 000..9c3d32d
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/mac.c
@@ -0,0 +1,116 @@
+/*
+ * Applied Micro X-Gene SoC Ethernet v2 Driver
+ *
+ * Copyright (c) 2017, Applied Micro Circuits Corporation
+ * Author(s): Iyappan Subramanian <isubraman...@apm.com>
+ *   Keyur Chudgar <kchud...@apm.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "main.h"
+
+void xge_mac_reset(struct xge_pdata *pdata)
+{
+   xge_wr_csr(pdata, MAC_CONFIG_1, SOFT_RESET);
+   xge_wr_csr(pdata, MAC_CONFIG_1, 0);
+}
+
+static void xge_mac_set_speed(struct xge_pdata *pdata)
+{
+   u32 icm0, icm2, ecm0, mc2;
+   u32 intf_ctrl, rgmii;
+
+   icm0 = xge_rd_csr(pdata, ICM_CONFIG0_REG_0);
+   icm2 = xge_rd_csr(pdata, ICM_CONFIG2_REG_0);
+   ecm0 = xge_rd_csr(pdata, ECM_CONFIG0_REG_0);
+   rgmii = xge_rd_csr(pdata, RGMII_REG_0);
+   mc2 = xge_rd_csr(pdata, MAC_CONFIG_2);
+   intf_ctrl = xge_rd_csr(pdata, INTERFACE_CONTROL);
+   icm2 |= CFG_WAITASYNCRD_EN;
+
+   switch (pdata->phy_speed) {
+   case SPEED_10:
+   SET_REG_BITS(, INTF_MODE, 1);
+   SET_REG_BITS(_ctrl, HD_MODE, 0);
+   SET_REG_BITS(, CFG_MACMODE, 0);
+   SET_REG_BITS(, CFG_WAITASYNCRD, 500);
+   SET_REG_BIT(, CFG_SPEED_125, 0);
+   break;
+   case SPEED_100:
+   SET_REG_BITS(, INTF_MODE, 1);
+   SET_REG_BITS(_ctrl, HD_MODE, 1);
+   SET_REG_BITS(, CFG_MACMODE, 1);
+   SET_REG_BITS(, CFG_WAITASYNCRD, 80);
+   SET_REG_BIT(, CFG_SPEED_125, 0);
+   break;
+   default:
+   SET_REG_BITS(, INTF_MODE, 2);
+   SET_REG_BITS(_ctrl, HD_MODE, 2);
+   SET_REG_BITS(, CFG_MACMODE, 2);
+   SET_REG_BITS(, CFG_WAITASYNCRD, 16);
+   SET_REG_BIT(, CFG_SPEED_125, 1);
+   break;
+   }
+
+   mc2 |= FULL_DUPLEX | CRC_EN | PAD_CRC;
+   SET_REG_BITS(, CFG_WFIFOFULLTHR, 0x32);
+
+   xge_wr_csr(pdata, MAC_CONFIG_2, mc2);
+   xge_wr_csr(pdata, INTERFACE_CONTROL, intf_ctrl);
+   xge_wr_csr(pdata, RGMII_REG_0, rgmii);
+   xge_wr_csr(pdata, ICM_CONFIG0_REG_0, icm0);
+   xge_wr_csr(pdata, ICM_CONFIG2_REG_0, icm2);
+   xge_wr_csr(pdata, ECM_CONFIG0_REG_0, ecm0);
+}
+
+void xge_mac_set_station_addr(struct xge_pdata *pdata)
+{
+   u32 addr0, addr1;
+   u8 *dev_addr = pdata->ndev->dev_addr;
+
+   addr0 = (dev_addr[3] << 24) | (dev_addr[2] << 16) |
+   (dev_addr[1] << 8) | dev_addr[0];
+   addr1 = (dev_addr[5] << 24) | (dev_addr[4] << 16);
+
+   xge_wr_csr(pdata, STATION_ADDR0, addr0);
+   xge_wr_csr(pdata, STATION_ADDR1, addr1);
+}
+
+void xge_mac_init(struct xge_pdata *pdata)
+{
+   xge_mac_reset(pdata);
+   xge_mac_set_speed(pdata);
+   xge_mac_set_station_addr(pdata);
+}
+
+void xge_mac_enable(struct xge_pdata *pdata)
+{
+   u32 data;
+
+   data = xge_rd_csr(pdata, MAC_CONFIG_1);
+   data |= TX_EN | RX_EN;
+   xge_wr_csr(pdata, MAC_CONFIG_1, data);
+
+   data = xge_rd_csr(pdata, MAC_CONFIG_1);
+}
+
+void xge_mac_disable(struct xge_pdata *pdata)
+{
+   u32 data;
+
+   data = xge_rd_csr(pdata, MAC_CONFIG_1);
+   data &= ~(TX_EN | RX_EN);
+   xge_wr_csr(pdata, MAC_CONFIG_1, data);
+}
diff --git a/drivers/net/ethernet/apm/xgene-v2/mac.h 
b/drivers/net/ethernet/apm/xgene-v2/mac.h
new file mode 100644
index 000..0fce6ae
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/mac.h
@@ -0,0 +1,110 @@
+/*
+ * Applied Micro X-Gene SoC Ethernet v2 Driver
+ 

[PATCH v4 net-next 1/6] drivers: net: xgene-v2: Add DMA descriptor

2017-03-07 Thread Iyappan Subramanian
This patch adds DMA descriptor setup and interrupt enable/disable
functions.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
Signed-off-by: Keyur Chudgar <kchud...@apm.com>
---
 drivers/net/ethernet/apm/xgene-v2/main.h |  74 +++
 drivers/net/ethernet/apm/xgene-v2/ring.c |  81 +
 drivers/net/ethernet/apm/xgene-v2/ring.h | 119 +++
 3 files changed, 274 insertions(+)
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/main.h
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/ring.c
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/ring.h

diff --git a/drivers/net/ethernet/apm/xgene-v2/main.h 
b/drivers/net/ethernet/apm/xgene-v2/main.h
new file mode 100644
index 000..a2f8712
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/main.h
@@ -0,0 +1,74 @@
+/*
+ * Applied Micro X-Gene SoC Ethernet v2 Driver
+ *
+ * Copyright (c) 2017, Applied Micro Circuits Corporation
+ * Author(s): Iyappan Subramanian <isubraman...@apm.com>
+ *   Keyur Chudgar <kchud...@apm.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __XGENE_ENET_V2_MAIN_H__
+#define __XGENE_ENET_V2_MAIN_H__
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "mac.h"
+#include "enet.h"
+#include "ring.h"
+
+#define XGENE_ENET_V2_VERSION  "v1.0"
+#define XGENE_ENET_STD_MTU 1536
+#define XGENE_ENET_MIN_FRAME   60
+#define IRQ_ID_SIZE 16
+
+struct xge_resource {
+   void __iomem *base_addr;
+   int phy_mode;
+   u32 irq;
+};
+
+struct xge_stats {
+   u64 tx_packets;
+   u64 tx_bytes;
+   u64 rx_packets;
+   u64 rx_bytes;
+};
+
+/* ethernet private data */
+struct xge_pdata {
+   struct xge_resource resources;
+   struct xge_desc_ring *tx_ring;
+   struct xge_desc_ring *rx_ring;
+   struct platform_device *pdev;
+   char irq_name[IRQ_ID_SIZE];
+   struct net_device *ndev;
+   struct napi_struct napi;
+   struct xge_stats stats;
+   int phy_speed;
+   u8 nbufs;
+};
+
+#endif /* __XGENE_ENET_V2_MAIN_H__ */
diff --git a/drivers/net/ethernet/apm/xgene-v2/ring.c 
b/drivers/net/ethernet/apm/xgene-v2/ring.c
new file mode 100644
index 000..3881082
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/ring.c
@@ -0,0 +1,81 @@
+/*
+ * Applied Micro X-Gene SoC Ethernet v2 Driver
+ *
+ * Copyright (c) 2017, Applied Micro Circuits Corporation
+ * Author(s): Iyappan Subramanian <isubraman...@apm.com>
+ *   Keyur Chudgar <kchud...@apm.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "main.h"
+
+/* create circular linked list of descriptors */
+void xge_setup_desc(struct xge_desc_ring *ring)
+{
+   struct xge_raw_desc *raw_desc;
+   dma_addr_t dma_h, next_dma;
+   u16 offset;
+   int i;
+
+   for (i = 0; i < XGENE_ENET_NUM_DESC; i++) {
+   raw_desc = >raw_desc[i];
+
+   offset = (i + 1) & (XGENE_ENET_NUM_DESC - 1);
+   next_dma = ring->dma_addr + (offset * XGENE_ENET_DESC_SIZE);
+
+   raw_desc->m0 = cpu_to_le64(SET_BITS(E, 1) |
+  SET_BITS(PKT_SIZE, SLOT_EMPTY));
+   dma_h = upper_32_bits(next_dma);
+   raw_desc->m1 = cpu_to_le64(SET_BITS(NEXT_DESC_ADDRL, next_dma) |
+  SET_BITS(NEXT_DESC_ADDRH, dma_h));
+   }
+}
+
+void xge_update_tx_desc_addr(struct xge_pdata *pdata)
+{
+   struct xge_desc_ring *ring = pdata->tx_ring;
+   dma_a

[PATCH v3 net-next 6/6] MAINTAINERS: Add entry for APM X-Gene SoC Ethernet (v2) driver

2017-03-03 Thread Iyappan Subramanian
This patch adds a MAINTAINERS entry for the ethernet driver for
the on-chip ethernet interface which uses a linked list of DMA
descriptor architecture (v2) for APM X-Gene SoCs.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
Signed-off-by: Keyur Chudgar <kchud...@apm.com>
---
 MAINTAINERS | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 846f97a..ccb9814 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -902,6 +902,12 @@ F: drivers/net/phy/mdio-xgene.c
 F: Documentation/devicetree/bindings/net/apm-xgene-enet.txt
 F: Documentation/devicetree/bindings/net/apm-xgene-mdio.txt
 
+APPLIED MICRO (APM) X-GENE SOC ETHERNET (V2) DRIVER
+M: Iyappan Subramanian <isubraman...@apm.com>
+M: Keyur Chudgar <kchud...@apm.com>
+S: Supported
+F: drivers/net/ethernet/apm/xgene-v2/
+
 APPLIED MICRO (APM) X-GENE SOC PMU
 M: Tai Nguyen <ttngu...@apm.com>
 S: Supported
-- 
1.9.1



[PATCH v3 net-next 4/6] drivers: net: xgene-v2: Add base driver

2017-03-03 Thread Iyappan Subramanian
This patch adds,

 - probe, remove, shutdown
 - open, close and stats
 - create and delete ring
 - request and delete irq

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
Signed-off-by: Keyur Chudgar <kchud...@apm.com>
---
 drivers/net/ethernet/apm/xgene-v2/main.c | 510 +++
 1 file changed, 510 insertions(+)
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/main.c

diff --git a/drivers/net/ethernet/apm/xgene-v2/main.c 
b/drivers/net/ethernet/apm/xgene-v2/main.c
new file mode 100644
index 000..c96b4cc
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/main.c
@@ -0,0 +1,510 @@
+/*
+ * Applied Micro X-Gene SoC Ethernet v2 Driver
+ *
+ * Copyright (c) 2017, Applied Micro Circuits Corporation
+ * Author(s): Iyappan Subramanian <isubraman...@apm.com>
+ *   Keyur Chudgar <kchud...@apm.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "main.h"
+
+static const struct acpi_device_id xge_acpi_match[];
+
+static int xge_get_resources(struct xge_pdata *pdata)
+{
+   struct platform_device *pdev;
+   struct net_device *ndev;
+   struct device *dev;
+   struct resource *res;
+   int phy_mode, ret = 0;
+
+   pdev = pdata->pdev;
+   dev = >dev;
+   ndev = pdata->ndev;
+
+   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   if (!res) {
+   dev_err(dev, "Resource enet_csr not defined\n");
+   return -ENODEV;
+   }
+
+   pdata->resources.base_addr = devm_ioremap(dev, res->start,
+ resource_size(res));
+   if (!pdata->resources.base_addr) {
+   dev_err(dev, "Unable to retrieve ENET Port CSR region\n");
+   return -ENOMEM;
+   }
+
+   if (!device_get_mac_address(dev, ndev->dev_addr, ETH_ALEN))
+   eth_hw_addr_random(ndev);
+
+   memcpy(ndev->perm_addr, ndev->dev_addr, ndev->addr_len);
+
+   phy_mode = device_get_phy_mode(dev);
+   if (phy_mode < 0) {
+   dev_err(dev, "Unable to get phy-connection-type\n");
+   return phy_mode;
+   }
+   pdata->resources.phy_mode = phy_mode;
+
+   if (pdata->resources.phy_mode != PHY_INTERFACE_MODE_RGMII) {
+   dev_err(dev, "Incorrect phy-connection-type specified\n");
+   return -ENODEV;
+   }
+
+   ret = platform_get_irq(pdev, 0);
+   if (ret <= 0) {
+   dev_err(dev, "Unable to get ENET IRQ\n");
+   ret = ret ? : -ENXIO;
+   return ret;
+   }
+   pdata->resources.irq = ret;
+
+   return 0;
+}
+
+static int xge_refill_buffers(struct net_device *ndev, u32 nbuf)
+{
+   struct xge_pdata *pdata = netdev_priv(ndev);
+   struct xge_desc_ring *ring = pdata->rx_ring;
+   const u8 slots = XGENE_ENET_NUM_DESC - 1;
+   struct device *dev = >pdev->dev;
+   struct xge_raw_desc *raw_desc;
+   u64 addr_lo, addr_hi;
+   u8 tail = ring->tail;
+   struct sk_buff *skb;
+   dma_addr_t dma_addr;
+   u16 len;
+   int i;
+
+   for (i = 0; i < nbuf; i++) {
+   raw_desc = >raw_desc[tail];
+
+   len = XGENE_ENET_STD_MTU;
+   skb = netdev_alloc_skb(ndev, len);
+   if (unlikely(!skb))
+   return -ENOMEM;
+
+   dma_addr = dma_map_single(dev, skb->data, len, DMA_FROM_DEVICE);
+   if (dma_mapping_error(dev, dma_addr)) {
+   netdev_err(ndev, "DMA mapping error\n");
+   dev_kfree_skb_any(skb);
+   return -EINVAL;
+   }
+
+   ring->pkt_info[tail].skb = skb;
+   ring->pkt_info[tail].dma_addr = dma_addr;
+
+   addr_hi = GET_BITS(NEXT_DESC_ADDRH, le64_to_cpu(raw_desc->m1));
+   addr_lo = GET_BITS(NEXT_DESC_ADDRL, le64_to_cpu(raw_desc->m1));
+   raw_desc->m1 = cpu_to_le64(SET_BITS(NEXT_DESC_ADDRL, addr_lo) |
+  SET_BITS(NEXT_DESC_ADDRH, addr_hi) |
+  SET_BITS(PKT_ADDRH,

[PATCH v3 net-next 3/6] drivers: net: xgene-v2: Add ethernet hardware configuration

2017-03-03 Thread Iyappan Subramanian
This patch adds functions to configure ethernet hardware.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
Signed-off-by: Keyur Chudgar <kchud...@apm.com>
---
 drivers/net/ethernet/apm/xgene-v2/enet.c | 71 
 drivers/net/ethernet/apm/xgene-v2/enet.h | 43 +++
 2 files changed, 114 insertions(+)
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/enet.c
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/enet.h

diff --git a/drivers/net/ethernet/apm/xgene-v2/enet.c 
b/drivers/net/ethernet/apm/xgene-v2/enet.c
new file mode 100644
index 000..b49edee
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/enet.c
@@ -0,0 +1,71 @@
+/*
+ * Applied Micro X-Gene SoC Ethernet v2 Driver
+ *
+ * Copyright (c) 2017, Applied Micro Circuits Corporation
+ * Author(s): Iyappan Subramanian <isubraman...@apm.com>
+ *   Keyur Chudgar <kchud...@apm.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "main.h"
+
+void xge_wr_csr(struct xge_pdata *pdata, u32 offset, u32 val)
+{
+   void __iomem *addr = pdata->resources.base_addr + offset;
+
+   iowrite32(val, addr);
+}
+
+u32 xge_rd_csr(struct xge_pdata *pdata, u32 offset)
+{
+   void __iomem *addr = pdata->resources.base_addr + offset;
+
+   return ioread32(addr);
+}
+
+int xge_port_reset(struct net_device *ndev)
+{
+   struct xge_pdata *pdata = netdev_priv(ndev);
+
+   xge_wr_csr(pdata, ENET_SRST, 0x3);
+   xge_wr_csr(pdata, ENET_SRST, 0x2);
+   xge_wr_csr(pdata, ENET_SRST, 0x0);
+
+   xge_wr_csr(pdata, ENET_SHIM, DEVM_ARAUX_COH | DEVM_AWAUX_COH);
+
+   return 0;
+}
+
+static void xge_traffic_resume(struct net_device *ndev)
+{
+   struct xge_pdata *pdata = netdev_priv(ndev);
+
+   xge_wr_csr(pdata, CFG_FORCE_LINK_STATUS_EN, 1);
+   xge_wr_csr(pdata, FORCE_LINK_STATUS, 1);
+
+   xge_wr_csr(pdata, CFG_LINK_AGGR_RESUME, 1);
+   xge_wr_csr(pdata, RX_DV_GATE_REG, 1);
+}
+
+int xge_port_init(struct net_device *ndev)
+{
+   struct xge_pdata *pdata = netdev_priv(ndev);
+
+   pdata->phy_speed = SPEED_1000;
+   xge_mac_init(pdata);
+   xge_traffic_resume(ndev);
+
+   return 0;
+}
diff --git a/drivers/net/ethernet/apm/xgene-v2/enet.h 
b/drivers/net/ethernet/apm/xgene-v2/enet.h
new file mode 100644
index 000..40371cf
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/enet.h
@@ -0,0 +1,43 @@
+/*
+ * Applied Micro X-Gene SoC Ethernet v2 Driver
+ *
+ * Copyright (c) 2017, Applied Micro Circuits Corporation
+ * Author(s): Iyappan Subramanian <isubraman...@apm.com>
+ *   Keyur Chudgar <kchud...@apm.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __XGENE_ENET_V2_ENET_H__
+#define __XGENE_ENET_V2_ENET_H__
+
+#define ENET_CLKEN 0xc008
+#define ENET_SRST  0xc000
+#define ENET_SHIM  0xc010
+#define CFG_MEM_RAM_SHUTDOWN   0xd070
+#define BLOCK_MEM_RDY  0xd074
+
+#define DEVM_ARAUX_COH BIT(19)
+#define DEVM_AWAUX_COH BIT(3)
+
+#define CFG_FORCE_LINK_STATUS_EN   0x229c
+#define FORCE_LINK_STATUS  0x22a0
+#define CFG_LINK_AGGR_RESUME   0x27c8
+#define RX_DV_GATE_REG 0x2dfc
+
+void xge_wr_csr(struct xge_pdata *pdata, u32 offset, u32 val);
+u32 xge_rd_csr(struct xge_pdata *pdata, u32 offset);
+int xge_port_reset(struct net_device *ndev);
+
+#endif  /* __XGENE_ENET_V2_ENET__H__ */
-- 
1.9.1



[PATCH v3 net-next 1/6] drivers: net: xgene-v2: Add DMA descriptor

2017-03-03 Thread Iyappan Subramanian
This patch adds DMA descriptor setup and interrupt enable/disable
functions.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
Signed-off-by: Keyur Chudgar <kchud...@apm.com>
---
 drivers/net/ethernet/apm/xgene-v2/main.h |  74 +++
 drivers/net/ethernet/apm/xgene-v2/ring.c |  81 +
 drivers/net/ethernet/apm/xgene-v2/ring.h | 119 +++
 3 files changed, 274 insertions(+)
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/main.h
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/ring.c
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/ring.h

diff --git a/drivers/net/ethernet/apm/xgene-v2/main.h 
b/drivers/net/ethernet/apm/xgene-v2/main.h
new file mode 100644
index 000..a2f8712
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/main.h
@@ -0,0 +1,74 @@
+/*
+ * Applied Micro X-Gene SoC Ethernet v2 Driver
+ *
+ * Copyright (c) 2017, Applied Micro Circuits Corporation
+ * Author(s): Iyappan Subramanian <isubraman...@apm.com>
+ *   Keyur Chudgar <kchud...@apm.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __XGENE_ENET_V2_MAIN_H__
+#define __XGENE_ENET_V2_MAIN_H__
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "mac.h"
+#include "enet.h"
+#include "ring.h"
+
+#define XGENE_ENET_V2_VERSION  "v1.0"
+#define XGENE_ENET_STD_MTU 1536
+#define XGENE_ENET_MIN_FRAME   60
+#define IRQ_ID_SIZE 16
+
+struct xge_resource {
+   void __iomem *base_addr;
+   int phy_mode;
+   u32 irq;
+};
+
+struct xge_stats {
+   u64 tx_packets;
+   u64 tx_bytes;
+   u64 rx_packets;
+   u64 rx_bytes;
+};
+
+/* ethernet private data */
+struct xge_pdata {
+   struct xge_resource resources;
+   struct xge_desc_ring *tx_ring;
+   struct xge_desc_ring *rx_ring;
+   struct platform_device *pdev;
+   char irq_name[IRQ_ID_SIZE];
+   struct net_device *ndev;
+   struct napi_struct napi;
+   struct xge_stats stats;
+   int phy_speed;
+   u8 nbufs;
+};
+
+#endif /* __XGENE_ENET_V2_MAIN_H__ */
diff --git a/drivers/net/ethernet/apm/xgene-v2/ring.c 
b/drivers/net/ethernet/apm/xgene-v2/ring.c
new file mode 100644
index 000..3881082
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/ring.c
@@ -0,0 +1,81 @@
+/*
+ * Applied Micro X-Gene SoC Ethernet v2 Driver
+ *
+ * Copyright (c) 2017, Applied Micro Circuits Corporation
+ * Author(s): Iyappan Subramanian <isubraman...@apm.com>
+ *   Keyur Chudgar <kchud...@apm.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "main.h"
+
+/* create circular linked list of descriptors */
+void xge_setup_desc(struct xge_desc_ring *ring)
+{
+   struct xge_raw_desc *raw_desc;
+   dma_addr_t dma_h, next_dma;
+   u16 offset;
+   int i;
+
+   for (i = 0; i < XGENE_ENET_NUM_DESC; i++) {
+   raw_desc = >raw_desc[i];
+
+   offset = (i + 1) & (XGENE_ENET_NUM_DESC - 1);
+   next_dma = ring->dma_addr + (offset * XGENE_ENET_DESC_SIZE);
+
+   raw_desc->m0 = cpu_to_le64(SET_BITS(E, 1) |
+  SET_BITS(PKT_SIZE, SLOT_EMPTY));
+   dma_h = upper_32_bits(next_dma);
+   raw_desc->m1 = cpu_to_le64(SET_BITS(NEXT_DESC_ADDRL, next_dma) |
+  SET_BITS(NEXT_DESC_ADDRH, dma_h));
+   }
+}
+
+void xge_update_tx_desc_addr(struct xge_pdata *pdata)
+{
+   struct xge_desc_ring *ring = pdata->tx_ring;
+   dma_a

[PATCH v3 net-next 2/6] drivers: net: xgene-v2: Add mac configuration

2017-03-03 Thread Iyappan Subramanian
This patch adds functions to configure and control mac.  This
patch also adds helper functions to get/set registers.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
Signed-off-by: Keyur Chudgar <kchud...@apm.com>
---
 drivers/net/ethernet/apm/xgene-v2/mac.c | 116 
 drivers/net/ethernet/apm/xgene-v2/mac.h | 110 ++
 2 files changed, 226 insertions(+)
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/mac.c
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/mac.h

diff --git a/drivers/net/ethernet/apm/xgene-v2/mac.c 
b/drivers/net/ethernet/apm/xgene-v2/mac.c
new file mode 100644
index 000..9c3d32d
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/mac.c
@@ -0,0 +1,116 @@
+/*
+ * Applied Micro X-Gene SoC Ethernet v2 Driver
+ *
+ * Copyright (c) 2017, Applied Micro Circuits Corporation
+ * Author(s): Iyappan Subramanian <isubraman...@apm.com>
+ *   Keyur Chudgar <kchud...@apm.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "main.h"
+
+void xge_mac_reset(struct xge_pdata *pdata)
+{
+   xge_wr_csr(pdata, MAC_CONFIG_1, SOFT_RESET);
+   xge_wr_csr(pdata, MAC_CONFIG_1, 0);
+}
+
+static void xge_mac_set_speed(struct xge_pdata *pdata)
+{
+   u32 icm0, icm2, ecm0, mc2;
+   u32 intf_ctrl, rgmii;
+
+   icm0 = xge_rd_csr(pdata, ICM_CONFIG0_REG_0);
+   icm2 = xge_rd_csr(pdata, ICM_CONFIG2_REG_0);
+   ecm0 = xge_rd_csr(pdata, ECM_CONFIG0_REG_0);
+   rgmii = xge_rd_csr(pdata, RGMII_REG_0);
+   mc2 = xge_rd_csr(pdata, MAC_CONFIG_2);
+   intf_ctrl = xge_rd_csr(pdata, INTERFACE_CONTROL);
+   icm2 |= CFG_WAITASYNCRD_EN;
+
+   switch (pdata->phy_speed) {
+   case SPEED_10:
+   SET_REG_BITS(, INTF_MODE, 1);
+   SET_REG_BITS(_ctrl, HD_MODE, 0);
+   SET_REG_BITS(, CFG_MACMODE, 0);
+   SET_REG_BITS(, CFG_WAITASYNCRD, 500);
+   SET_REG_BIT(, CFG_SPEED_125, 0);
+   break;
+   case SPEED_100:
+   SET_REG_BITS(, INTF_MODE, 1);
+   SET_REG_BITS(_ctrl, HD_MODE, 1);
+   SET_REG_BITS(, CFG_MACMODE, 1);
+   SET_REG_BITS(, CFG_WAITASYNCRD, 80);
+   SET_REG_BIT(, CFG_SPEED_125, 0);
+   break;
+   default:
+   SET_REG_BITS(, INTF_MODE, 2);
+   SET_REG_BITS(_ctrl, HD_MODE, 2);
+   SET_REG_BITS(, CFG_MACMODE, 2);
+   SET_REG_BITS(, CFG_WAITASYNCRD, 16);
+   SET_REG_BIT(, CFG_SPEED_125, 1);
+   break;
+   }
+
+   mc2 |= FULL_DUPLEX | CRC_EN | PAD_CRC;
+   SET_REG_BITS(, CFG_WFIFOFULLTHR, 0x32);
+
+   xge_wr_csr(pdata, MAC_CONFIG_2, mc2);
+   xge_wr_csr(pdata, INTERFACE_CONTROL, intf_ctrl);
+   xge_wr_csr(pdata, RGMII_REG_0, rgmii);
+   xge_wr_csr(pdata, ICM_CONFIG0_REG_0, icm0);
+   xge_wr_csr(pdata, ICM_CONFIG2_REG_0, icm2);
+   xge_wr_csr(pdata, ECM_CONFIG0_REG_0, ecm0);
+}
+
+void xge_mac_set_station_addr(struct xge_pdata *pdata)
+{
+   u32 addr0, addr1;
+   u8 *dev_addr = pdata->ndev->dev_addr;
+
+   addr0 = (dev_addr[3] << 24) | (dev_addr[2] << 16) |
+   (dev_addr[1] << 8) | dev_addr[0];
+   addr1 = (dev_addr[5] << 24) | (dev_addr[4] << 16);
+
+   xge_wr_csr(pdata, STATION_ADDR0, addr0);
+   xge_wr_csr(pdata, STATION_ADDR1, addr1);
+}
+
+void xge_mac_init(struct xge_pdata *pdata)
+{
+   xge_mac_reset(pdata);
+   xge_mac_set_speed(pdata);
+   xge_mac_set_station_addr(pdata);
+}
+
+void xge_mac_enable(struct xge_pdata *pdata)
+{
+   u32 data;
+
+   data = xge_rd_csr(pdata, MAC_CONFIG_1);
+   data |= TX_EN | RX_EN;
+   xge_wr_csr(pdata, MAC_CONFIG_1, data);
+
+   data = xge_rd_csr(pdata, MAC_CONFIG_1);
+}
+
+void xge_mac_disable(struct xge_pdata *pdata)
+{
+   u32 data;
+
+   data = xge_rd_csr(pdata, MAC_CONFIG_1);
+   data &= ~(TX_EN | RX_EN);
+   xge_wr_csr(pdata, MAC_CONFIG_1, data);
+}
diff --git a/drivers/net/ethernet/apm/xgene-v2/mac.h 
b/drivers/net/ethernet/apm/xgene-v2/mac.h
new file mode 100644
index 000..0fce6ae
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/mac.h
@@ -0,0 +1,110 @@
+/*
+ * Applied Micro X-Gene SoC Ethernet v2 Driver
+ 

[PATCH v3 net-next 0/6] drivers: net: xgene-v2: Add RGMII based 1G driver

2017-03-03 Thread Iyappan Subramanian
This patch set adds support for RGMII based 1GbE hardware which uses a linked
list of DMA descriptor architecture (v2) for APM X-Gene SoCs.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
v3: Address review comments from v2
- fix kbuild warnings (this 'if' clause does not guard)

v2: Address review comments from v1
- moved create_desc_ring and delete_desc_ring to open() and close()
  respectively
- changed to use dma_zalloc APIs
- fixed tx_timeout()
- removed tx completion polling upper bound
- added error checking on rx packets
- added netif_stop_queue() and netif_wake_queue()

v1:
- Initial version
---

Iyappan Subramanian (6):
  drivers: net: xgene-v2: Add DMA descriptor
  drivers: net: xgene-v2: Add mac configuration
  drivers: net: xgene-v2: Add ethernet hardware configuration
  drivers: net: xgene-v2: Add base driver
  drivers: net: xgene-v2: Add transmit and receive
  MAINTAINERS: Add entry for APM X-Gene SoC Ethernet (v2) driver

 MAINTAINERS|   6 +
 drivers/net/ethernet/apm/Kconfig   |   1 +
 drivers/net/ethernet/apm/Makefile  |   1 +
 drivers/net/ethernet/apm/xgene-v2/Kconfig  |  11 +
 drivers/net/ethernet/apm/xgene-v2/Makefile |   6 +
 drivers/net/ethernet/apm/xgene-v2/enet.c   |  71 +++
 drivers/net/ethernet/apm/xgene-v2/enet.h   |  43 ++
 drivers/net/ethernet/apm/xgene-v2/mac.c| 116 +
 drivers/net/ethernet/apm/xgene-v2/mac.h| 110 +
 drivers/net/ethernet/apm/xgene-v2/main.c   | 756 +
 drivers/net/ethernet/apm/xgene-v2/main.h   |  75 +++
 drivers/net/ethernet/apm/xgene-v2/ring.c   |  81 
 drivers/net/ethernet/apm/xgene-v2/ring.h   | 119 +
 13 files changed, 1396 insertions(+)
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/Kconfig
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/Makefile
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/enet.c
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/enet.h
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/mac.c
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/mac.h
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/main.c
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/main.h
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/ring.c
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/ring.h

-- 
1.9.1



[PATCH v3 net-next 5/6] drivers: net: xgene-v2: Add transmit and receive

2017-03-03 Thread Iyappan Subramanian
This patch adds,
- Transmit
- Transmit completion poll
- Receive poll
- NAPI handler

and enables the driver.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
Signed-off-by: Keyur Chudgar <kchud...@apm.com>
---
 drivers/net/ethernet/apm/Kconfig   |   1 +
 drivers/net/ethernet/apm/Makefile  |   1 +
 drivers/net/ethernet/apm/xgene-v2/Kconfig  |  11 ++
 drivers/net/ethernet/apm/xgene-v2/Makefile |   6 +
 drivers/net/ethernet/apm/xgene-v2/main.c   | 248 -
 drivers/net/ethernet/apm/xgene-v2/main.h   |   1 +
 6 files changed, 267 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/Kconfig
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/Makefile

diff --git a/drivers/net/ethernet/apm/Kconfig b/drivers/net/ethernet/apm/Kconfig
index ec63d70..59efe5b 100644
--- a/drivers/net/ethernet/apm/Kconfig
+++ b/drivers/net/ethernet/apm/Kconfig
@@ -1 +1,2 @@
 source "drivers/net/ethernet/apm/xgene/Kconfig"
+source "drivers/net/ethernet/apm/xgene-v2/Kconfig"
diff --git a/drivers/net/ethernet/apm/Makefile 
b/drivers/net/ethernet/apm/Makefile
index 65ce32a..946b2a4 100644
--- a/drivers/net/ethernet/apm/Makefile
+++ b/drivers/net/ethernet/apm/Makefile
@@ -3,3 +3,4 @@
 #
 
 obj-$(CONFIG_NET_XGENE) += xgene/
+obj-$(CONFIG_NET_XGENE_V2) += xgene-v2/
diff --git a/drivers/net/ethernet/apm/xgene-v2/Kconfig 
b/drivers/net/ethernet/apm/xgene-v2/Kconfig
new file mode 100644
index 000..1205861
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/Kconfig
@@ -0,0 +1,11 @@
+config NET_XGENE_V2
+   tristate "APM X-Gene SoC Ethernet-v2 Driver"
+   depends on HAS_DMA
+   depends on ARCH_XGENE || COMPILE_TEST
+   help
+ This is the Ethernet driver for the on-chip ethernet interface
+ which uses a linked list of DMA descriptor architecture (v2) for
+ APM X-Gene SoCs.
+
+ To compile this driver as a module, choose M here. This module will
+ be called xgene-enet-v2.
diff --git a/drivers/net/ethernet/apm/xgene-v2/Makefile 
b/drivers/net/ethernet/apm/xgene-v2/Makefile
new file mode 100644
index 000..735309c
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for APM X-Gene Ethernet v2 driver
+#
+
+xgene-enet-v2-objs := main.o mac.o enet.o ring.o
+obj-$(CONFIG_NET_XGENE_V2) += xgene-enet-v2.o
diff --git a/drivers/net/ethernet/apm/xgene-v2/main.c 
b/drivers/net/ethernet/apm/xgene-v2/main.c
index c96b4cc..b16ef43 100644
--- a/drivers/net/ethernet/apm/xgene-v2/main.c
+++ b/drivers/net/ethernet/apm/xgene-v2/main.c
@@ -113,7 +113,7 @@ static int xge_refill_buffers(struct net_device *ndev, u32 
nbuf)
raw_desc->m1 = cpu_to_le64(SET_BITS(NEXT_DESC_ADDRL, addr_lo) |
   SET_BITS(NEXT_DESC_ADDRH, addr_hi) |
   SET_BITS(PKT_ADDRH,
-   dma_addr >> PKT_ADDRL_LEN));
+   upper_32_bits(dma_addr)));
 
dma_wmb();
raw_desc->m0 = cpu_to_le64(SET_BITS(PKT_ADDRL, dma_addr) |
@@ -177,6 +177,194 @@ static void xge_free_irq(struct net_device *ndev)
devm_free_irq(dev, pdata->resources.irq, pdata);
 }
 
+static bool is_tx_slot_available(struct xge_raw_desc *raw_desc)
+{
+   if (GET_BITS(E, le64_to_cpu(raw_desc->m0)) &&
+   (GET_BITS(PKT_SIZE, le64_to_cpu(raw_desc->m0)) == SLOT_EMPTY))
+   return true;
+
+   return false;
+}
+
+static netdev_tx_t xge_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+   struct xge_pdata *pdata = netdev_priv(ndev);
+   struct device *dev = >pdev->dev;
+   static dma_addr_t dma_addr;
+   struct xge_desc_ring *tx_ring;
+   struct xge_raw_desc *raw_desc;
+   u64 addr_lo, addr_hi;
+   void *pkt_buf;
+   u8 tail;
+   u16 len;
+
+   tx_ring = pdata->tx_ring;
+   tail = tx_ring->tail;
+   len = skb_headlen(skb);
+   raw_desc = _ring->raw_desc[tail];
+
+   if (!is_tx_slot_available(raw_desc)) {
+   netif_stop_queue(ndev);
+   return NETDEV_TX_BUSY;
+   }
+
+   /* Packet buffers should be 64B aligned */
+   pkt_buf = dma_zalloc_coherent(dev, XGENE_ENET_STD_MTU, _addr,
+ GFP_ATOMIC);
+   if (unlikely(!pkt_buf)) {
+   dev_kfree_skb_any(skb);
+   return NETDEV_TX_OK;
+   }
+   memcpy(pkt_buf, skb->data, len);
+
+   addr_hi = GET_BITS(NEXT_DESC_ADDRH, le64_to_cpu(raw_desc->m1));
+   addr_lo = GET_BITS(NEXT_DESC_ADDRL, le64_to_cpu(raw_desc->m1));
+   raw_desc->m1 = cpu_to_le64(SET_BITS(NEXT_DESC_ADDRL, addr_lo) |
+  SET_BITS(NEXT_DESC_ADDRH, addr_hi) |
+  

Re: [PATCH] drivers: net: xgene: Fix crash on DT systems

2017-02-28 Thread Iyappan Subramanian
On Tue, Feb 28, 2017 at 9:08 AM, Alban Bedel
<alban.be...@avionic-design.de> wrote:
> On DT systems the driver require a clock, but the probe just print a
> warning and continue, leading to a crash when resetting the device.
> To fix this crash and properly handle probe deferals only ignore the
> missing clock if DT isn't used or if the clock doesn't exist.
>
> Signed-off-by: Alban Bedel <alban.be...@avionic-design.de>
> ---
>  drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 6 ++
>  1 file changed, 6 insertions(+)
>
> diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c 
> b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
> index d0d0d12b531f..68b48edc5921 100644
> --- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
> +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
> @@ -1756,6 +1756,12 @@ static int xgene_enet_get_resources(struct 
> xgene_enet_pdata *pdata)
>
> pdata->clk = devm_clk_get(>dev, NULL);
> if (IS_ERR(pdata->clk)) {
> +   /* Abort if the clock is defined but couldn't be retrived.
> +* Always abort if the clock is missing on DT system as
> +* the driver can't cope with this case.
> +*/
> +   if (PTR_ERR(pdata->clk) != -ENOENT || dev->of_node)
> +   return PTR_ERR(pdata->clk);
> /* Firmware may have set up the clock already. */
>     dev_info(dev, "clocks have been setup already\n");
> }
> --
> 2.11.0
>

Thanks, Alban.

Acked-by: Iyappan Subramanian <isubraman...@apm.com>


[PATCH v2 net-next 4/6] drivers: net: xgene-v2: Add base driver

2017-02-27 Thread Iyappan Subramanian
This patch adds,

 - probe, remove, shutdown
 - open, close and stats
 - create and delete ring
 - request and delete irq

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
Signed-off-by: Keyur Chudgar <kchud...@apm.com>
---
 drivers/net/ethernet/apm/xgene-v2/main.c | 510 +++
 1 file changed, 510 insertions(+)
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/main.c

diff --git a/drivers/net/ethernet/apm/xgene-v2/main.c 
b/drivers/net/ethernet/apm/xgene-v2/main.c
new file mode 100644
index 000..c96b4cc
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/main.c
@@ -0,0 +1,510 @@
+/*
+ * Applied Micro X-Gene SoC Ethernet v2 Driver
+ *
+ * Copyright (c) 2017, Applied Micro Circuits Corporation
+ * Author(s): Iyappan Subramanian <isubraman...@apm.com>
+ *   Keyur Chudgar <kchud...@apm.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "main.h"
+
+static const struct acpi_device_id xge_acpi_match[];
+
+static int xge_get_resources(struct xge_pdata *pdata)
+{
+   struct platform_device *pdev;
+   struct net_device *ndev;
+   struct device *dev;
+   struct resource *res;
+   int phy_mode, ret = 0;
+
+   pdev = pdata->pdev;
+   dev = >dev;
+   ndev = pdata->ndev;
+
+   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   if (!res) {
+   dev_err(dev, "Resource enet_csr not defined\n");
+   return -ENODEV;
+   }
+
+   pdata->resources.base_addr = devm_ioremap(dev, res->start,
+ resource_size(res));
+   if (!pdata->resources.base_addr) {
+   dev_err(dev, "Unable to retrieve ENET Port CSR region\n");
+   return -ENOMEM;
+   }
+
+   if (!device_get_mac_address(dev, ndev->dev_addr, ETH_ALEN))
+   eth_hw_addr_random(ndev);
+
+   memcpy(ndev->perm_addr, ndev->dev_addr, ndev->addr_len);
+
+   phy_mode = device_get_phy_mode(dev);
+   if (phy_mode < 0) {
+   dev_err(dev, "Unable to get phy-connection-type\n");
+   return phy_mode;
+   }
+   pdata->resources.phy_mode = phy_mode;
+
+   if (pdata->resources.phy_mode != PHY_INTERFACE_MODE_RGMII) {
+   dev_err(dev, "Incorrect phy-connection-type specified\n");
+   return -ENODEV;
+   }
+
+   ret = platform_get_irq(pdev, 0);
+   if (ret <= 0) {
+   dev_err(dev, "Unable to get ENET IRQ\n");
+   ret = ret ? : -ENXIO;
+   return ret;
+   }
+   pdata->resources.irq = ret;
+
+   return 0;
+}
+
+static int xge_refill_buffers(struct net_device *ndev, u32 nbuf)
+{
+   struct xge_pdata *pdata = netdev_priv(ndev);
+   struct xge_desc_ring *ring = pdata->rx_ring;
+   const u8 slots = XGENE_ENET_NUM_DESC - 1;
+   struct device *dev = >pdev->dev;
+   struct xge_raw_desc *raw_desc;
+   u64 addr_lo, addr_hi;
+   u8 tail = ring->tail;
+   struct sk_buff *skb;
+   dma_addr_t dma_addr;
+   u16 len;
+   int i;
+
+   for (i = 0; i < nbuf; i++) {
+   raw_desc = >raw_desc[tail];
+
+   len = XGENE_ENET_STD_MTU;
+   skb = netdev_alloc_skb(ndev, len);
+   if (unlikely(!skb))
+   return -ENOMEM;
+
+   dma_addr = dma_map_single(dev, skb->data, len, DMA_FROM_DEVICE);
+   if (dma_mapping_error(dev, dma_addr)) {
+   netdev_err(ndev, "DMA mapping error\n");
+   dev_kfree_skb_any(skb);
+   return -EINVAL;
+   }
+
+   ring->pkt_info[tail].skb = skb;
+   ring->pkt_info[tail].dma_addr = dma_addr;
+
+   addr_hi = GET_BITS(NEXT_DESC_ADDRH, le64_to_cpu(raw_desc->m1));
+   addr_lo = GET_BITS(NEXT_DESC_ADDRL, le64_to_cpu(raw_desc->m1));
+   raw_desc->m1 = cpu_to_le64(SET_BITS(NEXT_DESC_ADDRL, addr_lo) |
+  SET_BITS(NEXT_DESC_ADDRH, addr_hi) |
+  SET_BITS(PKT_ADDRH,

[PATCH v2 net-next 0/6] drivers: net: xgene-v2: Add RGMII based 1G driver

2017-02-26 Thread Iyappan Subramanian
This patch set adds support for RGMII based 1GbE hardware which uses a linked
list of DMA descriptor architecture (v2) for APM X-Gene SoCs.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
v2: Address review comments from v1
- moved create_desc_ring and delete_desc_ring to open() and close()
  respectively
- changed to use dma_zalloc APIs
- fixed tx_timeout()
- removed tx completion polling upper bound
- added error checking on rx packets
- added netif_stop_queue() and netif_wake_queue()

v1:
- Initial version
---

Iyappan Subramanian (6):
  drivers: net: xgene-v2: Add DMA descriptor
  drivers: net: xgene-v2: Add mac configuration
  drivers: net: xgene-v2: Add ethernet hardware configuration
  drivers: net: xgene-v2: Add base driver
  drivers: net: xgene-v2: Add transmit and receive
  MAINTAINERS: Add entry for APM X-Gene SoC Ethernet (v2) driver

 MAINTAINERS|   6 +
 drivers/net/ethernet/apm/Kconfig   |   1 +
 drivers/net/ethernet/apm/Makefile  |   1 +
 drivers/net/ethernet/apm/xgene-v2/Kconfig  |  11 +
 drivers/net/ethernet/apm/xgene-v2/Makefile |   6 +
 drivers/net/ethernet/apm/xgene-v2/enet.c   |  71 +++
 drivers/net/ethernet/apm/xgene-v2/enet.h   |  43 ++
 drivers/net/ethernet/apm/xgene-v2/mac.c| 116 +
 drivers/net/ethernet/apm/xgene-v2/mac.h| 110 +
 drivers/net/ethernet/apm/xgene-v2/main.c   | 756 +
 drivers/net/ethernet/apm/xgene-v2/main.h   |  75 +++
 drivers/net/ethernet/apm/xgene-v2/ring.c   |  81 
 drivers/net/ethernet/apm/xgene-v2/ring.h   | 119 +
 13 files changed, 1396 insertions(+)
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/Kconfig
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/Makefile
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/enet.c
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/enet.h
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/mac.c
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/mac.h
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/main.c
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/main.h
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/ring.c
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/ring.h

-- 
1.9.1



[PATCH v2 net-next 5/6] drivers: net: xgene-v2: Add transmit and receive

2017-02-26 Thread Iyappan Subramanian
This patch adds,
- Transmit
- Transmit completion poll
- Receive poll
- NAPI handler

and enables the driver.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
Signed-off-by: Keyur Chudgar <kchud...@apm.com>
---
 drivers/net/ethernet/apm/Kconfig   |   1 +
 drivers/net/ethernet/apm/Makefile  |   1 +
 drivers/net/ethernet/apm/xgene-v2/Kconfig  |  11 ++
 drivers/net/ethernet/apm/xgene-v2/Makefile |   6 +
 drivers/net/ethernet/apm/xgene-v2/main.c   | 248 -
 drivers/net/ethernet/apm/xgene-v2/main.h   |   1 +
 6 files changed, 267 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/Kconfig
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/Makefile

diff --git a/drivers/net/ethernet/apm/Kconfig b/drivers/net/ethernet/apm/Kconfig
index ec63d70..59efe5b 100644
--- a/drivers/net/ethernet/apm/Kconfig
+++ b/drivers/net/ethernet/apm/Kconfig
@@ -1 +1,2 @@
 source "drivers/net/ethernet/apm/xgene/Kconfig"
+source "drivers/net/ethernet/apm/xgene-v2/Kconfig"
diff --git a/drivers/net/ethernet/apm/Makefile 
b/drivers/net/ethernet/apm/Makefile
index 65ce32a..946b2a4 100644
--- a/drivers/net/ethernet/apm/Makefile
+++ b/drivers/net/ethernet/apm/Makefile
@@ -3,3 +3,4 @@
 #
 
 obj-$(CONFIG_NET_XGENE) += xgene/
+obj-$(CONFIG_NET_XGENE_V2) += xgene-v2/
diff --git a/drivers/net/ethernet/apm/xgene-v2/Kconfig 
b/drivers/net/ethernet/apm/xgene-v2/Kconfig
new file mode 100644
index 000..1205861
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/Kconfig
@@ -0,0 +1,11 @@
+config NET_XGENE_V2
+   tristate "APM X-Gene SoC Ethernet-v2 Driver"
+   depends on HAS_DMA
+   depends on ARCH_XGENE || COMPILE_TEST
+   help
+ This is the Ethernet driver for the on-chip ethernet interface
+ which uses a linked list of DMA descriptor architecture (v2) for
+ APM X-Gene SoCs.
+
+ To compile this driver as a module, choose M here. This module will
+ be called xgene-enet-v2.
diff --git a/drivers/net/ethernet/apm/xgene-v2/Makefile 
b/drivers/net/ethernet/apm/xgene-v2/Makefile
new file mode 100644
index 000..735309c
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for APM X-Gene Ethernet v2 driver
+#
+
+xgene-enet-v2-objs := main.o mac.o enet.o ring.o
+obj-$(CONFIG_NET_XGENE_V2) += xgene-enet-v2.o
diff --git a/drivers/net/ethernet/apm/xgene-v2/main.c 
b/drivers/net/ethernet/apm/xgene-v2/main.c
index c96b4cc..f613a78 100644
--- a/drivers/net/ethernet/apm/xgene-v2/main.c
+++ b/drivers/net/ethernet/apm/xgene-v2/main.c
@@ -113,7 +113,7 @@ static int xge_refill_buffers(struct net_device *ndev, u32 
nbuf)
raw_desc->m1 = cpu_to_le64(SET_BITS(NEXT_DESC_ADDRL, addr_lo) |
   SET_BITS(NEXT_DESC_ADDRH, addr_hi) |
   SET_BITS(PKT_ADDRH,
-   dma_addr >> PKT_ADDRL_LEN));
+   upper_32_bits(dma_addr)));
 
dma_wmb();
raw_desc->m0 = cpu_to_le64(SET_BITS(PKT_ADDRL, dma_addr) |
@@ -177,6 +177,194 @@ static void xge_free_irq(struct net_device *ndev)
devm_free_irq(dev, pdata->resources.irq, pdata);
 }
 
+static bool is_tx_slot_available(struct xge_raw_desc *raw_desc)
+{
+   if (GET_BITS(E, le64_to_cpu(raw_desc->m0)) &&
+   (GET_BITS(PKT_SIZE, le64_to_cpu(raw_desc->m0)) == SLOT_EMPTY))
+   return true;
+
+   return false;
+}
+
+static netdev_tx_t xge_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+   struct xge_pdata *pdata = netdev_priv(ndev);
+   struct device *dev = >pdev->dev;
+   static dma_addr_t dma_addr;
+   struct xge_desc_ring *tx_ring;
+   struct xge_raw_desc *raw_desc;
+   u64 addr_lo, addr_hi;
+   void *pkt_buf;
+   u8 tail;
+   u16 len;
+
+   tx_ring = pdata->tx_ring;
+   tail = tx_ring->tail;
+   len = skb_headlen(skb);
+   raw_desc = _ring->raw_desc[tail];
+
+   if (!is_tx_slot_available(raw_desc)) {
+   netif_stop_queue(ndev);
+   return NETDEV_TX_BUSY;
+   }
+
+   /* Packet buffers should be 64B aligned */
+   pkt_buf = dma_zalloc_coherent(dev, XGENE_ENET_STD_MTU, _addr,
+ GFP_ATOMIC);
+   if (unlikely(!pkt_buf)) {
+   dev_kfree_skb_any(skb);
+   return NETDEV_TX_OK;
+   }
+   memcpy(pkt_buf, skb->data, len);
+
+   addr_hi = GET_BITS(NEXT_DESC_ADDRH, le64_to_cpu(raw_desc->m1));
+   addr_lo = GET_BITS(NEXT_DESC_ADDRL, le64_to_cpu(raw_desc->m1));
+   raw_desc->m1 = cpu_to_le64(SET_BITS(NEXT_DESC_ADDRL, addr_lo) |
+  SET_BITS(NEXT_DESC_ADDRH, addr_hi) |
+  

[PATCH v2 net-next 1/6] drivers: net: xgene-v2: Add DMA descriptor

2017-02-26 Thread Iyappan Subramanian
This patch adds DMA descriptor setup and interrupt enable/disable
functions.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
Signed-off-by: Keyur Chudgar <kchud...@apm.com>
---
 drivers/net/ethernet/apm/xgene-v2/main.h |  74 +++
 drivers/net/ethernet/apm/xgene-v2/ring.c |  81 +
 drivers/net/ethernet/apm/xgene-v2/ring.h | 119 +++
 3 files changed, 274 insertions(+)
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/main.h
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/ring.c
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/ring.h

diff --git a/drivers/net/ethernet/apm/xgene-v2/main.h 
b/drivers/net/ethernet/apm/xgene-v2/main.h
new file mode 100644
index 000..a2f8712
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/main.h
@@ -0,0 +1,74 @@
+/*
+ * Applied Micro X-Gene SoC Ethernet v2 Driver
+ *
+ * Copyright (c) 2017, Applied Micro Circuits Corporation
+ * Author(s): Iyappan Subramanian <isubraman...@apm.com>
+ *   Keyur Chudgar <kchud...@apm.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __XGENE_ENET_V2_MAIN_H__
+#define __XGENE_ENET_V2_MAIN_H__
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "mac.h"
+#include "enet.h"
+#include "ring.h"
+
+#define XGENE_ENET_V2_VERSION  "v1.0"
+#define XGENE_ENET_STD_MTU 1536
+#define XGENE_ENET_MIN_FRAME   60
+#define IRQ_ID_SIZE 16
+
+struct xge_resource {
+   void __iomem *base_addr;
+   int phy_mode;
+   u32 irq;
+};
+
+struct xge_stats {
+   u64 tx_packets;
+   u64 tx_bytes;
+   u64 rx_packets;
+   u64 rx_bytes;
+};
+
+/* ethernet private data */
+struct xge_pdata {
+   struct xge_resource resources;
+   struct xge_desc_ring *tx_ring;
+   struct xge_desc_ring *rx_ring;
+   struct platform_device *pdev;
+   char irq_name[IRQ_ID_SIZE];
+   struct net_device *ndev;
+   struct napi_struct napi;
+   struct xge_stats stats;
+   int phy_speed;
+   u8 nbufs;
+};
+
+#endif /* __XGENE_ENET_V2_MAIN_H__ */
diff --git a/drivers/net/ethernet/apm/xgene-v2/ring.c 
b/drivers/net/ethernet/apm/xgene-v2/ring.c
new file mode 100644
index 000..3881082
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/ring.c
@@ -0,0 +1,81 @@
+/*
+ * Applied Micro X-Gene SoC Ethernet v2 Driver
+ *
+ * Copyright (c) 2017, Applied Micro Circuits Corporation
+ * Author(s): Iyappan Subramanian <isubraman...@apm.com>
+ *   Keyur Chudgar <kchud...@apm.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "main.h"
+
+/* create circular linked list of descriptors */
+void xge_setup_desc(struct xge_desc_ring *ring)
+{
+   struct xge_raw_desc *raw_desc;
+   dma_addr_t dma_h, next_dma;
+   u16 offset;
+   int i;
+
+   for (i = 0; i < XGENE_ENET_NUM_DESC; i++) {
+   raw_desc = >raw_desc[i];
+
+   offset = (i + 1) & (XGENE_ENET_NUM_DESC - 1);
+   next_dma = ring->dma_addr + (offset * XGENE_ENET_DESC_SIZE);
+
+   raw_desc->m0 = cpu_to_le64(SET_BITS(E, 1) |
+  SET_BITS(PKT_SIZE, SLOT_EMPTY));
+   dma_h = upper_32_bits(next_dma);
+   raw_desc->m1 = cpu_to_le64(SET_BITS(NEXT_DESC_ADDRL, next_dma) |
+  SET_BITS(NEXT_DESC_ADDRH, dma_h));
+   }
+}
+
+void xge_update_tx_desc_addr(struct xge_pdata *pdata)
+{
+   struct xge_desc_ring *ring = pdata->tx_ring;
+   dma_a

[PATCH v2 net-next 2/6] drivers: net: xgene-v2: Add mac configuration

2017-02-26 Thread Iyappan Subramanian
This patch adds functions to configure and control mac.  This
patch also adds helper functions to get/set registers.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
Signed-off-by: Keyur Chudgar <kchud...@apm.com>
---
 drivers/net/ethernet/apm/xgene-v2/mac.c | 116 
 drivers/net/ethernet/apm/xgene-v2/mac.h | 110 ++
 2 files changed, 226 insertions(+)
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/mac.c
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/mac.h

diff --git a/drivers/net/ethernet/apm/xgene-v2/mac.c 
b/drivers/net/ethernet/apm/xgene-v2/mac.c
new file mode 100644
index 000..9c3d32d
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/mac.c
@@ -0,0 +1,116 @@
+/*
+ * Applied Micro X-Gene SoC Ethernet v2 Driver
+ *
+ * Copyright (c) 2017, Applied Micro Circuits Corporation
+ * Author(s): Iyappan Subramanian <isubraman...@apm.com>
+ *   Keyur Chudgar <kchud...@apm.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "main.h"
+
+void xge_mac_reset(struct xge_pdata *pdata)
+{
+   xge_wr_csr(pdata, MAC_CONFIG_1, SOFT_RESET);
+   xge_wr_csr(pdata, MAC_CONFIG_1, 0);
+}
+
+static void xge_mac_set_speed(struct xge_pdata *pdata)
+{
+   u32 icm0, icm2, ecm0, mc2;
+   u32 intf_ctrl, rgmii;
+
+   icm0 = xge_rd_csr(pdata, ICM_CONFIG0_REG_0);
+   icm2 = xge_rd_csr(pdata, ICM_CONFIG2_REG_0);
+   ecm0 = xge_rd_csr(pdata, ECM_CONFIG0_REG_0);
+   rgmii = xge_rd_csr(pdata, RGMII_REG_0);
+   mc2 = xge_rd_csr(pdata, MAC_CONFIG_2);
+   intf_ctrl = xge_rd_csr(pdata, INTERFACE_CONTROL);
+   icm2 |= CFG_WAITASYNCRD_EN;
+
+   switch (pdata->phy_speed) {
+   case SPEED_10:
+   SET_REG_BITS(, INTF_MODE, 1);
+   SET_REG_BITS(_ctrl, HD_MODE, 0);
+   SET_REG_BITS(, CFG_MACMODE, 0);
+   SET_REG_BITS(, CFG_WAITASYNCRD, 500);
+   SET_REG_BIT(, CFG_SPEED_125, 0);
+   break;
+   case SPEED_100:
+   SET_REG_BITS(, INTF_MODE, 1);
+   SET_REG_BITS(_ctrl, HD_MODE, 1);
+   SET_REG_BITS(, CFG_MACMODE, 1);
+   SET_REG_BITS(, CFG_WAITASYNCRD, 80);
+   SET_REG_BIT(, CFG_SPEED_125, 0);
+   break;
+   default:
+   SET_REG_BITS(, INTF_MODE, 2);
+   SET_REG_BITS(_ctrl, HD_MODE, 2);
+   SET_REG_BITS(, CFG_MACMODE, 2);
+   SET_REG_BITS(, CFG_WAITASYNCRD, 16);
+   SET_REG_BIT(, CFG_SPEED_125, 1);
+   break;
+   }
+
+   mc2 |= FULL_DUPLEX | CRC_EN | PAD_CRC;
+   SET_REG_BITS(, CFG_WFIFOFULLTHR, 0x32);
+
+   xge_wr_csr(pdata, MAC_CONFIG_2, mc2);
+   xge_wr_csr(pdata, INTERFACE_CONTROL, intf_ctrl);
+   xge_wr_csr(pdata, RGMII_REG_0, rgmii);
+   xge_wr_csr(pdata, ICM_CONFIG0_REG_0, icm0);
+   xge_wr_csr(pdata, ICM_CONFIG2_REG_0, icm2);
+   xge_wr_csr(pdata, ECM_CONFIG0_REG_0, ecm0);
+}
+
+void xge_mac_set_station_addr(struct xge_pdata *pdata)
+{
+   u32 addr0, addr1;
+   u8 *dev_addr = pdata->ndev->dev_addr;
+
+   addr0 = (dev_addr[3] << 24) | (dev_addr[2] << 16) |
+   (dev_addr[1] << 8) | dev_addr[0];
+   addr1 = (dev_addr[5] << 24) | (dev_addr[4] << 16);
+
+   xge_wr_csr(pdata, STATION_ADDR0, addr0);
+   xge_wr_csr(pdata, STATION_ADDR1, addr1);
+}
+
+void xge_mac_init(struct xge_pdata *pdata)
+{
+   xge_mac_reset(pdata);
+   xge_mac_set_speed(pdata);
+   xge_mac_set_station_addr(pdata);
+}
+
+void xge_mac_enable(struct xge_pdata *pdata)
+{
+   u32 data;
+
+   data = xge_rd_csr(pdata, MAC_CONFIG_1);
+   data |= TX_EN | RX_EN;
+   xge_wr_csr(pdata, MAC_CONFIG_1, data);
+
+   data = xge_rd_csr(pdata, MAC_CONFIG_1);
+}
+
+void xge_mac_disable(struct xge_pdata *pdata)
+{
+   u32 data;
+
+   data = xge_rd_csr(pdata, MAC_CONFIG_1);
+   data &= ~(TX_EN | RX_EN);
+   xge_wr_csr(pdata, MAC_CONFIG_1, data);
+}
diff --git a/drivers/net/ethernet/apm/xgene-v2/mac.h 
b/drivers/net/ethernet/apm/xgene-v2/mac.h
new file mode 100644
index 000..0fce6ae
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/mac.h
@@ -0,0 +1,110 @@
+/*
+ * Applied Micro X-Gene SoC Ethernet v2 Driver
+ 

[PATCH v2 net-next 6/6] MAINTAINERS: Add entry for APM X-Gene SoC Ethernet (v2) driver

2017-02-26 Thread Iyappan Subramanian
This patch adds a MAINTAINERS entry for the ethernet driver for
the on-chip ethernet interface which uses a linked list of DMA
descriptor architecture (v2) for APM X-Gene SoCs.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
Signed-off-by: Keyur Chudgar <kchud...@apm.com>
---
 MAINTAINERS | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 4b03c47..359fc34 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -902,6 +902,12 @@ F: drivers/net/phy/mdio-xgene.c
 F: Documentation/devicetree/bindings/net/apm-xgene-enet.txt
 F: Documentation/devicetree/bindings/net/apm-xgene-mdio.txt
 
+APPLIED MICRO (APM) X-GENE SOC ETHERNET (V2) DRIVER
+M: Iyappan Subramanian <isubraman...@apm.com>
+M: Keyur Chudgar <kchud...@apm.com>
+S: Supported
+F: drivers/net/ethernet/apm/xgene-v2/
+
 APPLIED MICRO (APM) X-GENE SOC PMU
 M: Tai Nguyen <ttngu...@apm.com>
 S: Supported
-- 
1.9.1



Re: [PATCH net-next 4/6] drivers: net: xgene-v2: Add base driver

2017-02-26 Thread Iyappan Subramanian
Hi Andrew,

On Tue, Jan 31, 2017 at 12:01 PM, Andrew Lunn  wrote:
>> + phy_mode = device_get_phy_mode(dev);
>> + if (phy_mode < 0) {
>> + dev_err(dev, "Unable to get phy-connection-type\n");
>> + return phy_mode;
>> + }
>> + pdata->resources.phy_mode = phy_mode;
>> +
>> + if (pdata->resources.phy_mode != PHY_INTERFACE_MODE_RGMII) {
>> + dev_err(dev, "Incorrect phy-connection-type specified\n");
>> + return -ENODEV;
>> + }
>
> This seems a bit limiting. What if you need to use:
>
> PHY_INTERFACE_MODE_RGMII_ID,
> PHY_INTERFACE_MODE_RGMII_RXID,
> PHY_INTERFACE_MODE_RGMII_TXID,
>
> in order to set the RGMII delays.

This version of the driver doesn't support setting delays.  The delay
support will be added in the future.

>
>Andrew
>


Re: [PATCH net-next 4/6] drivers: net: xgene-v2: Add base driver

2017-02-26 Thread Iyappan Subramanian
Hi Florian,

On Tue, Jan 31, 2017 at 12:31 PM, Florian Fainelli <f.faine...@gmail.com> wrote:
> On 01/31/2017 11:03 AM, Iyappan Subramanian wrote:
>> This patch adds,
>>
>>  - probe, remove, shutdown
>>  - open, close and stats
>>  - create and delete ring
>>  - request and delete irq
>>
>> Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
>> Signed-off-by: Keyur Chudgar <kchud...@apm.com>
>> ---
>
>> +static void xge_delete_desc_rings(struct net_device *ndev)
>> +{
>> + struct xge_pdata *pdata = netdev_priv(ndev);
>> + struct device *dev = >pdev->dev;
>> + struct xge_desc_ring *ring;
>> +
>> + ring = pdata->tx_ring;
>> + if (ring) {
>> + if (ring->skbs)
>> + devm_kfree(dev, ring->skbs);
>> + if (ring->pkt_bufs)
>> + devm_kfree(dev, ring->pkt_bufs);
>> + devm_kfree(dev, ring);
>> + }
>
> The very fact that you have to do the devm_kfree suggests that the way
> you manage the lifetime of the ring is not appropriate, and in fact, if
> we look at how xge_create_desc_ring() is called, in the driver's probe
> function indicates that if the network interface is never openeded, we
> are just wasting memory sitting there and doing nothing. You should
> consider moving this to the ndo_open(), resp. ndo_close() functions to
> optimize memory consumption wrt. the network interface state.

I will move these to open and close functions and will use dma_zalloc() APIs.

>
>> +
>> + ring = pdata->rx_ring;
>> + if (ring) {
>> + if (ring->skbs)
>> + devm_kfree(dev, ring->skbs);
>> + devm_kfree(dev, ring);
>> + }
>> +}
>> +
>> +static struct xge_desc_ring *xge_create_desc_ring(struct net_device *ndev)
>> +{
>> + struct xge_pdata *pdata = netdev_priv(ndev);
>> + struct device *dev = >pdev->dev;
>> + struct xge_desc_ring *ring;
>> + u16 size;
>> +
>> + ring = devm_kzalloc(dev, sizeof(struct xge_desc_ring), GFP_KERNEL);
>> + if (!ring)
>> + return NULL;
>> +
>> + ring->ndev = ndev;
>> +
>> + size = XGENE_ENET_DESC_SIZE * XGENE_ENET_NUM_DESC;
>> + ring->desc_addr = dmam_alloc_coherent(dev, size, >dma_addr,
>> +   GFP_KERNEL | __GFP_ZERO);
>
> There is no dmam_zalloc_coherent()? Then again, that seems to be a
> candidate for dma_zalloc_coherent() and moving this to the ndo_open()
> function.
>
>> + if (!ring->desc_addr) {
>> + devm_kfree(dev, ring);
>> + return NULL;
>> + }
>> +
>> + xge_setup_desc(ring);
>> +
>> + return ring;
>> +}
>> +
>> +static int xge_refill_buffers(struct net_device *ndev, u32 nbuf)
>> +{
>> + struct xge_pdata *pdata = netdev_priv(ndev);
>> + struct xge_desc_ring *ring = pdata->rx_ring;
>> + const u8 slots = XGENE_ENET_NUM_DESC - 1;
>> + struct device *dev = >pdev->dev;
>> + struct xge_raw_desc *raw_desc;
>> + u64 addr_lo, addr_hi;
>> + u8 tail = ring->tail;
>> + struct sk_buff *skb;
>> + dma_addr_t dma_addr;
>> + u16 len;
>> + int i;
>> +
>> + for (i = 0; i < nbuf; i++) {
>> + raw_desc = >raw_desc[tail];
>> +
>> + len = XGENE_ENET_STD_MTU;
>> + skb = netdev_alloc_skb(ndev, len);
>> + if (unlikely(!skb))
>> + return -ENOMEM;
>
> Are not you leaving holes in your RX ring if you do that?

No.  The probe will fail and clean up the unused buffers.

>
>> +
>> + dma_addr = dma_map_single(dev, skb->data, len, 
>> DMA_FROM_DEVICE);
>> + if (dma_mapping_error(dev, dma_addr)) {
>> + netdev_err(ndev, "DMA mapping error\n");
>> + dev_kfree_skb_any(skb);
>> + return -EINVAL;
>> + }
>
>
>> +static void xge_timeout(struct net_device *ndev)
>> +{
>> + struct xge_pdata *pdata = netdev_priv(ndev);
>> + struct netdev_queue *txq;
>> +
>> + xge_mac_reset(pdata);
>> +
>> + txq = netdev_get_tx_queue(ndev, 0);
>> + txq->trans_start = jiffies;
>> + netif_tx_start_queue(txq);
>
> It most likely is not that simple, don't you want to walk the lis

Re: [PATCH net-next 5/6] drivers: net: xgene-v2: Add transmit and receive

2017-02-26 Thread Iyappan Subramanian
Hi Florian,

On Tue, Jan 31, 2017 at 12:33 PM, Florian Fainelli <f.faine...@gmail.com> wrote:
> On 01/31/2017 11:03 AM, Iyappan Subramanian wrote:
>> This patch adds,
>> - Transmit
>> - Transmit completion poll
>> - Receive poll
>> - NAPI handler
>>
>> and enables the driver.
>>
>> Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
>> Signed-off-by: Keyur Chudgar <kchud...@apm.com>
>> ---
>
>> +
>> + tx_ring = pdata->tx_ring;
>> + tail = tx_ring->tail;
>> + len = skb_headlen(skb);
>> + raw_desc = _ring->raw_desc[tail];
>> +
>> + /* Tx descriptor not available */
>> + if (!GET_BITS(E, le64_to_cpu(raw_desc->m0)) ||
>> + GET_BITS(PKT_SIZE, le64_to_cpu(raw_desc->m0)))
>> + return NETDEV_TX_BUSY;
>> +
>> + /* Packet buffers should be 64B aligned */
>> + pkt_buf = dma_alloc_coherent(dev, XGENE_ENET_STD_MTU, _addr,
>> +  GFP_ATOMIC);
>> + if (unlikely(!pkt_buf))
>> + goto out;
>
> Can't you obtain a DMA-API mapping for skb->data and pass it down to the
> hardware? This copy here is inefficient.

This hardware requires 64-byte alignment.

>
>> +
>> + memcpy(pkt_buf, skb->data, len);
>> +
>> + addr_hi = GET_BITS(NEXT_DESC_ADDRH, le64_to_cpu(raw_desc->m1));
>> + addr_lo = GET_BITS(NEXT_DESC_ADDRL, le64_to_cpu(raw_desc->m1));
>> + raw_desc->m1 = cpu_to_le64(SET_BITS(NEXT_DESC_ADDRL, addr_lo) |
>> +SET_BITS(NEXT_DESC_ADDRH, addr_hi) |
>> +SET_BITS(PKT_ADDRH,
>> + dma_addr >> PKT_ADDRL_LEN));
>> +
>> + dma_wmb();
>> +
>> + raw_desc->m0 = cpu_to_le64(SET_BITS(PKT_ADDRL, dma_addr) |
>> +SET_BITS(PKT_SIZE, len) |
>> +SET_BITS(E, 0));
>> +
>> + skb_tx_timestamp(skb);
>> + xge_wr_csr(pdata, DMATXCTRL, 1);
>> +
>> + pdata->stats.tx_packets++;
>> + pdata->stats.tx_bytes += skb->len;
>
> This is both racy and incorrect. Racy because after you wrote DMATXCTRL,
> your TX completion can run, and it can do that while interrupting your
> CPU presumably, and free the SKB, therefore making you access a freed
> SKB (or it should, if it does not), it's also incorrect, because before
> you get signaled a TX completion, there is no guarantee that the packets
> did actually make it through, you must update your stats in the TX
> completion handler.

Thanks.  I'll move the tx stats part to Tx completion.

>
>> +
>> + tx_ring->skbs[tail] = skb;
>> + tx_ring->pkt_bufs[tail] = pkt_buf;
>> + tx_ring->tail = (tail + 1) & (XGENE_ENET_NUM_DESC - 1);
>> +
>> +out:
>> + dev_kfree_skb_any(skb);
>
> Don't do this, remember a pointer to the SKB, free the SKB in TX
> completion handler, preferably in NAPI context.

I'll implement this.

>
>> +
>> + return NETDEV_TX_OK;
>> +}
>> +
>> +static void xge_txc_poll(struct net_device *ndev, unsigned int budget)
>> +{
>> + struct xge_pdata *pdata = netdev_priv(ndev);
>> + struct device *dev = >pdev->dev;
>> + struct xge_desc_ring *tx_ring;
>> + struct xge_raw_desc *raw_desc;
>> + u64 addr_lo, addr_hi;
>> + dma_addr_t dma_addr;
>> + void *pkt_buf;
>> + bool pktsent;
>> + u32 data;
>> + u8 head;
>> + int i;
>> +
>> + tx_ring = pdata->tx_ring;
>> + head = tx_ring->head;
>> +
>> + data = xge_rd_csr(pdata, DMATXSTATUS);
>> + pktsent = data & TX_PKT_SENT;
>> + if (unlikely(!pktsent))
>> + return;
>> +
>> + for (i = 0; i < budget; i++) {
>
> TX completion handlers should run unbound and free the entire TX ring,
> don't make it obey to an upper bound.

I'll do as suggested.

>
>> + raw_desc = _ring->raw_desc[head];
>> +
>> + if (!GET_BITS(E, le64_to_cpu(raw_desc->m0)))
>> + break;
>> +
>> + dma_rmb();
>> +
>> + addr_hi = GET_BITS(PKT_ADDRH, le64_to_cpu(raw_desc->m1));
>> + addr_lo = GET_BITS(PKT_ADDRL, le64_to_cpu(raw_desc->m0));
>> + dma_addr = (addr_hi << PKT_ADDRL_LEN) | addr_lo;
>> +
>> + pkt_buf = tx_ring->pkt_bufs[head];
>> +
>> + 

[PATCH v2 net-next 3/6] drivers: net: xgene-v2: Add ethernet hardware configuration

2017-02-26 Thread Iyappan Subramanian
This patch adds functions to configure ethernet hardware.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
Signed-off-by: Keyur Chudgar <kchud...@apm.com>
---
 drivers/net/ethernet/apm/xgene-v2/enet.c | 71 
 drivers/net/ethernet/apm/xgene-v2/enet.h | 43 +++
 2 files changed, 114 insertions(+)
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/enet.c
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/enet.h

diff --git a/drivers/net/ethernet/apm/xgene-v2/enet.c 
b/drivers/net/ethernet/apm/xgene-v2/enet.c
new file mode 100644
index 000..b49edee
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/enet.c
@@ -0,0 +1,71 @@
+/*
+ * Applied Micro X-Gene SoC Ethernet v2 Driver
+ *
+ * Copyright (c) 2017, Applied Micro Circuits Corporation
+ * Author(s): Iyappan Subramanian <isubraman...@apm.com>
+ *   Keyur Chudgar <kchud...@apm.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "main.h"
+
+void xge_wr_csr(struct xge_pdata *pdata, u32 offset, u32 val)
+{
+   void __iomem *addr = pdata->resources.base_addr + offset;
+
+   iowrite32(val, addr);
+}
+
+u32 xge_rd_csr(struct xge_pdata *pdata, u32 offset)
+{
+   void __iomem *addr = pdata->resources.base_addr + offset;
+
+   return ioread32(addr);
+}
+
+int xge_port_reset(struct net_device *ndev)
+{
+   struct xge_pdata *pdata = netdev_priv(ndev);
+
+   xge_wr_csr(pdata, ENET_SRST, 0x3);
+   xge_wr_csr(pdata, ENET_SRST, 0x2);
+   xge_wr_csr(pdata, ENET_SRST, 0x0);
+
+   xge_wr_csr(pdata, ENET_SHIM, DEVM_ARAUX_COH | DEVM_AWAUX_COH);
+
+   return 0;
+}
+
+static void xge_traffic_resume(struct net_device *ndev)
+{
+   struct xge_pdata *pdata = netdev_priv(ndev);
+
+   xge_wr_csr(pdata, CFG_FORCE_LINK_STATUS_EN, 1);
+   xge_wr_csr(pdata, FORCE_LINK_STATUS, 1);
+
+   xge_wr_csr(pdata, CFG_LINK_AGGR_RESUME, 1);
+   xge_wr_csr(pdata, RX_DV_GATE_REG, 1);
+}
+
+int xge_port_init(struct net_device *ndev)
+{
+   struct xge_pdata *pdata = netdev_priv(ndev);
+
+   pdata->phy_speed = SPEED_1000;
+   xge_mac_init(pdata);
+   xge_traffic_resume(ndev);
+
+   return 0;
+}
diff --git a/drivers/net/ethernet/apm/xgene-v2/enet.h 
b/drivers/net/ethernet/apm/xgene-v2/enet.h
new file mode 100644
index 000..40371cf
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/enet.h
@@ -0,0 +1,43 @@
+/*
+ * Applied Micro X-Gene SoC Ethernet v2 Driver
+ *
+ * Copyright (c) 2017, Applied Micro Circuits Corporation
+ * Author(s): Iyappan Subramanian <isubraman...@apm.com>
+ *   Keyur Chudgar <kchud...@apm.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __XGENE_ENET_V2_ENET_H__
+#define __XGENE_ENET_V2_ENET_H__
+
+#define ENET_CLKEN 0xc008
+#define ENET_SRST  0xc000
+#define ENET_SHIM  0xc010
+#define CFG_MEM_RAM_SHUTDOWN   0xd070
+#define BLOCK_MEM_RDY  0xd074
+
+#define DEVM_ARAUX_COH BIT(19)
+#define DEVM_AWAUX_COH BIT(3)
+
+#define CFG_FORCE_LINK_STATUS_EN   0x229c
+#define FORCE_LINK_STATUS  0x22a0
+#define CFG_LINK_AGGR_RESUME   0x27c8
+#define RX_DV_GATE_REG 0x2dfc
+
+void xge_wr_csr(struct xge_pdata *pdata, u32 offset, u32 val);
+u32 xge_rd_csr(struct xge_pdata *pdata, u32 offset);
+int xge_port_reset(struct net_device *ndev);
+
+#endif  /* __XGENE_ENET_V2_ENET__H__ */
-- 
1.9.1



Re: [PATCH net-next 5/6] drivers: net: xgene-v2: Add transmit and receive

2017-02-26 Thread Iyappan Subramanian
On Wed, Feb 1, 2017 at 3:09 AM, David Laight <david.lai...@aculab.com> wrote:
> From Florian Fainelli
>> Sent: 31 January 2017 20:33
>> On 01/31/2017 11:03 AM, Iyappan Subramanian wrote:
>> > This patch adds,
>> > - Transmit
>> > - Transmit completion poll
>> > - Receive poll
>> > - NAPI handler
>> >
>> > and enables the driver.
>> >
>> > Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
>> > Signed-off-by: Keyur Chudgar <kchud...@apm.com>
>> > ---
>>
>> > +
>> > +   tx_ring = pdata->tx_ring;
>> > +   tail = tx_ring->tail;
>> > +   len = skb_headlen(skb);
>> > +   raw_desc = _ring->raw_desc[tail];
>> > +
>> > +   /* Tx descriptor not available */
>> > +   if (!GET_BITS(E, le64_to_cpu(raw_desc->m0)) ||
>> > +   GET_BITS(PKT_SIZE, le64_to_cpu(raw_desc->m0)))
>> > +   return NETDEV_TX_BUSY;
>
> Aren't you supposed to detect 'ring full' and stop the code
> giving you packets to transmit.

I'll add stop queue and wake queue.

>
>> > +
>> > +   /* Packet buffers should be 64B aligned */
>
> Is that really a requirement of the hardware?
> Almost all ethernet frames are 4n+2 aligned.

Yes, it's a hardware requirement.

>
>> > +   pkt_buf = dma_alloc_coherent(dev, XGENE_ENET_STD_MTU, _addr,
>> > +GFP_ATOMIC);
>> > +   if (unlikely(!pkt_buf))
>> > +   goto out;
>>
>> Can't you obtain a DMA-API mapping for skb->data and pass it down to the
>> hardware? This copy here is inefficient.
>>
>> > +
>> > +   memcpy(pkt_buf, skb->data, len);
>
> You really need to verify that the len <= XGENE_ENET_STD_MTU.

This version of the driver, doesn't support jumbo frame.  So, the
check is not required.

>
> Isn't this code only transmitting the 'head' of the packet?
> What about the fragments??

This driver doesn't enable SG yet.

> ...
> David
>


Re: [PATCH] drivers: net: xgene: Simplify xgene_enet_setup_mss() to kill warning

2017-02-24 Thread Iyappan Subramanian
On Fri, Feb 24, 2017 at 2:30 AM, Geert Uytterhoeven
<ge...@linux-m68k.org> wrote:
> With gcc-4.1.2 and -Os:
>
> drivers/net/ethernet/apm/xgene/xgene_enet_main.c: In function 
> ‘xgene_enet_start_xmit’:
> drivers/net/ethernet/apm/xgene/xgene_enet_main.c:297: warning: 
> ‘mss_index’ may be used uninitialized in this function
>
> Using a separate variable to track success may confuse the compiler.
> Preinitialize mss_index with -EBUSY and check for negative error values
> instead to kill the warning.
>
> Signed-off-by: Geert Uytterhoeven <ge...@linux-m68k.org>
> ---
> Compile-tested only.
>
>  drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 13 +++--
>  1 file changed, 3 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c 
> b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
> index d0d0d12b531fc683..e536301acfdec9fd 100644
> --- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
> +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
> @@ -293,36 +293,29 @@ static int xgene_enet_tx_completion(struct 
> xgene_enet_desc_ring *cp_ring,
>  static int xgene_enet_setup_mss(struct net_device *ndev, u32 mss)
>  {
> struct xgene_enet_pdata *pdata = netdev_priv(ndev);
> -   bool mss_index_found = false;
> -   int mss_index;
> +   int mss_index = -EBUSY;
> int i;
>
> spin_lock(>mss_lock);
>
> /* Reuse the slot if MSS matches */
> -   for (i = 0; !mss_index_found && i < NUM_MSS_REG; i++) {
> +   for (i = 0; mss_index < 0 && i < NUM_MSS_REG; i++) {
> if (pdata->mss[i] == mss) {
> pdata->mss_refcnt[i]++;
> mss_index = i;
> -   mss_index_found = true;
> }
> }
>
> /* Overwrite the slot with ref_count = 0 */
> -   for (i = 0; !mss_index_found && i < NUM_MSS_REG; i++) {
> +   for (i = 0; mss_index < 0 && i < NUM_MSS_REG; i++) {
> if (!pdata->mss_refcnt[i]) {
> pdata->mss_refcnt[i]++;
> pdata->mac_ops->set_mss(pdata, mss, i);
> pdata->mss[i] = mss;
> mss_index = i;
> -   mss_index_found = true;
> }
>     }
>
> -   /* No slots with ref_count = 0 available, return busy */
> -   if (!mss_index_found)
> -   mss_index = -EBUSY;
> -
> spin_unlock(>mss_lock);
>
> return mss_index;
> --
> 2.7.4
>

Thanks.

Acked-by: Iyappan Subramanian <isubraman...@apm.com>


[PATCH net-next 3/6] drivers: net: xgene-v2: Add ethernet hardware configuration

2017-01-31 Thread Iyappan Subramanian
This patch adds functions to configure ethernet hardware.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
Signed-off-by: Keyur Chudgar <kchud...@apm.com>
---
 drivers/net/ethernet/apm/xgene-v2/enet.c | 71 
 drivers/net/ethernet/apm/xgene-v2/enet.h | 43 +++
 2 files changed, 114 insertions(+)
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/enet.c
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/enet.h

diff --git a/drivers/net/ethernet/apm/xgene-v2/enet.c 
b/drivers/net/ethernet/apm/xgene-v2/enet.c
new file mode 100644
index 000..b49edee
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/enet.c
@@ -0,0 +1,71 @@
+/*
+ * Applied Micro X-Gene SoC Ethernet v2 Driver
+ *
+ * Copyright (c) 2017, Applied Micro Circuits Corporation
+ * Author(s): Iyappan Subramanian <isubraman...@apm.com>
+ *   Keyur Chudgar <kchud...@apm.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "main.h"
+
+void xge_wr_csr(struct xge_pdata *pdata, u32 offset, u32 val)
+{
+   void __iomem *addr = pdata->resources.base_addr + offset;
+
+   iowrite32(val, addr);
+}
+
+u32 xge_rd_csr(struct xge_pdata *pdata, u32 offset)
+{
+   void __iomem *addr = pdata->resources.base_addr + offset;
+
+   return ioread32(addr);
+}
+
+int xge_port_reset(struct net_device *ndev)
+{
+   struct xge_pdata *pdata = netdev_priv(ndev);
+
+   xge_wr_csr(pdata, ENET_SRST, 0x3);
+   xge_wr_csr(pdata, ENET_SRST, 0x2);
+   xge_wr_csr(pdata, ENET_SRST, 0x0);
+
+   xge_wr_csr(pdata, ENET_SHIM, DEVM_ARAUX_COH | DEVM_AWAUX_COH);
+
+   return 0;
+}
+
+static void xge_traffic_resume(struct net_device *ndev)
+{
+   struct xge_pdata *pdata = netdev_priv(ndev);
+
+   xge_wr_csr(pdata, CFG_FORCE_LINK_STATUS_EN, 1);
+   xge_wr_csr(pdata, FORCE_LINK_STATUS, 1);
+
+   xge_wr_csr(pdata, CFG_LINK_AGGR_RESUME, 1);
+   xge_wr_csr(pdata, RX_DV_GATE_REG, 1);
+}
+
+int xge_port_init(struct net_device *ndev)
+{
+   struct xge_pdata *pdata = netdev_priv(ndev);
+
+   pdata->phy_speed = SPEED_1000;
+   xge_mac_init(pdata);
+   xge_traffic_resume(ndev);
+
+   return 0;
+}
diff --git a/drivers/net/ethernet/apm/xgene-v2/enet.h 
b/drivers/net/ethernet/apm/xgene-v2/enet.h
new file mode 100644
index 000..40371cf
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/enet.h
@@ -0,0 +1,43 @@
+/*
+ * Applied Micro X-Gene SoC Ethernet v2 Driver
+ *
+ * Copyright (c) 2017, Applied Micro Circuits Corporation
+ * Author(s): Iyappan Subramanian <isubraman...@apm.com>
+ *   Keyur Chudgar <kchud...@apm.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __XGENE_ENET_V2_ENET_H__
+#define __XGENE_ENET_V2_ENET_H__
+
+#define ENET_CLKEN 0xc008
+#define ENET_SRST  0xc000
+#define ENET_SHIM  0xc010
+#define CFG_MEM_RAM_SHUTDOWN   0xd070
+#define BLOCK_MEM_RDY  0xd074
+
+#define DEVM_ARAUX_COH BIT(19)
+#define DEVM_AWAUX_COH BIT(3)
+
+#define CFG_FORCE_LINK_STATUS_EN   0x229c
+#define FORCE_LINK_STATUS  0x22a0
+#define CFG_LINK_AGGR_RESUME   0x27c8
+#define RX_DV_GATE_REG 0x2dfc
+
+void xge_wr_csr(struct xge_pdata *pdata, u32 offset, u32 val);
+u32 xge_rd_csr(struct xge_pdata *pdata, u32 offset);
+int xge_port_reset(struct net_device *ndev);
+
+#endif  /* __XGENE_ENET_V2_ENET__H__ */
-- 
1.9.1



[PATCH net-next 1/6] drivers: net: xgene-v2: Add DMA descriptor

2017-01-31 Thread Iyappan Subramanian
This patch adds DMA descriptor setup and interrupt enable/disable
functions.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
Signed-off-by: Keyur Chudgar <kchud...@apm.com>
---
 drivers/net/ethernet/apm/xgene-v2/main.h | 88 
 drivers/net/ethernet/apm/xgene-v2/ring.c | 73 ++
 drivers/net/ethernet/apm/xgene-v2/ring.h | 77 
 3 files changed, 238 insertions(+)
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/main.h
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/ring.c
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/ring.h

diff --git a/drivers/net/ethernet/apm/xgene-v2/main.h 
b/drivers/net/ethernet/apm/xgene-v2/main.h
new file mode 100644
index 000..c8a40af
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/main.h
@@ -0,0 +1,88 @@
+/*
+ * Applied Micro X-Gene SoC Ethernet v2 Driver
+ *
+ * Copyright (c) 2017, Applied Micro Circuits Corporation
+ * Author(s): Iyappan Subramanian <isubraman...@apm.com>
+ *   Keyur Chudgar <kchud...@apm.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __XGENE_ENET_V2_MAIN_H__
+#define __XGENE_ENET_V2_MAIN_H__
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "mac.h"
+#include "enet.h"
+#include "ring.h"
+
+#define XGENE_ENET_V2_VERSION  "v1.0"
+#define XGENE_ENET_STD_MTU 1536
+#define XGENE_ENET_MIN_FRAME   60
+#define IRQ_ID_SIZE 16
+
+struct xge_resource {
+   void __iomem *base_addr;
+   int phy_mode;
+   u32 irq;
+};
+
+struct xge_stats {
+   u64 tx_packets;
+   u64 tx_bytes;
+   u64 rx_packets;
+   u64 rx_bytes;
+};
+
+/* software context of a descriptor ring */
+struct xge_desc_ring {
+   struct net_device *ndev;
+   dma_addr_t dma_addr;
+   u8 head;
+   u8 tail;
+   union {
+   void *desc_addr;
+   struct xge_raw_desc *raw_desc;
+   };
+   struct sk_buff *(*skbs);
+   void *(*pkt_bufs);
+};
+
+/* ethernet private data */
+struct xge_pdata {
+   struct xge_resource resources;
+   struct xge_desc_ring *tx_ring;
+   struct xge_desc_ring *rx_ring;
+   struct platform_device *pdev;
+   char irq_name[IRQ_ID_SIZE];
+   struct net_device *ndev;
+   struct napi_struct napi;
+   struct xge_stats stats;
+   int phy_speed;
+   u8 nbufs;
+};
+
+#endif /* __XGENE_ENET_V2_MAIN_H__ */
diff --git a/drivers/net/ethernet/apm/xgene-v2/ring.c 
b/drivers/net/ethernet/apm/xgene-v2/ring.c
new file mode 100644
index 000..3289bf3
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/ring.c
@@ -0,0 +1,73 @@
+/*
+ * Applied Micro X-Gene SoC Ethernet v2 Driver
+ *
+ * Copyright (c) 2017, Applied Micro Circuits Corporation
+ * Author(s): Iyappan Subramanian <isubraman...@apm.com>
+ *   Keyur Chudgar <kchud...@apm.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "main.h"
+
+/* create circular linked list of descriptors */
+void xge_setup_desc(struct xge_desc_ring *ring)
+{
+   struct xge_raw_desc *raw_desc;
+   dma_addr_t dma_h, next_dma;
+   u16 offset;
+   int i;
+
+   for (i = 0; i < XGENE_ENET_NUM_DESC; i++) {
+   raw_desc = >raw_desc[i];
+
+   offset = (i + 1) & (XGENE_ENET_NUM_DESC - 1);
+   next_dma = ring->dma_addr + (offset * XGENE_ENET_DESC_SIZE);
+
+   raw_desc->m0 = cpu_to_le64(SET_BITS(E, 1) |
+  SET_BITS(PKT_SIZE, 0));
+ 

[PATCH net-next 2/6] drivers: net: xgene-v2: Add mac configuration

2017-01-31 Thread Iyappan Subramanian
This patch adds functions to configure and control mac.  This
patch also adds helper functions to get/set registers.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
Signed-off-by: Keyur Chudgar <kchud...@apm.com>
---
 drivers/net/ethernet/apm/xgene-v2/mac.c | 116 
 drivers/net/ethernet/apm/xgene-v2/mac.h | 132 
 2 files changed, 248 insertions(+)
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/mac.c
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/mac.h

diff --git a/drivers/net/ethernet/apm/xgene-v2/mac.c 
b/drivers/net/ethernet/apm/xgene-v2/mac.c
new file mode 100644
index 000..9c3d32d
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/mac.c
@@ -0,0 +1,116 @@
+/*
+ * Applied Micro X-Gene SoC Ethernet v2 Driver
+ *
+ * Copyright (c) 2017, Applied Micro Circuits Corporation
+ * Author(s): Iyappan Subramanian <isubraman...@apm.com>
+ *   Keyur Chudgar <kchud...@apm.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "main.h"
+
+void xge_mac_reset(struct xge_pdata *pdata)
+{
+   xge_wr_csr(pdata, MAC_CONFIG_1, SOFT_RESET);
+   xge_wr_csr(pdata, MAC_CONFIG_1, 0);
+}
+
+static void xge_mac_set_speed(struct xge_pdata *pdata)
+{
+   u32 icm0, icm2, ecm0, mc2;
+   u32 intf_ctrl, rgmii;
+
+   icm0 = xge_rd_csr(pdata, ICM_CONFIG0_REG_0);
+   icm2 = xge_rd_csr(pdata, ICM_CONFIG2_REG_0);
+   ecm0 = xge_rd_csr(pdata, ECM_CONFIG0_REG_0);
+   rgmii = xge_rd_csr(pdata, RGMII_REG_0);
+   mc2 = xge_rd_csr(pdata, MAC_CONFIG_2);
+   intf_ctrl = xge_rd_csr(pdata, INTERFACE_CONTROL);
+   icm2 |= CFG_WAITASYNCRD_EN;
+
+   switch (pdata->phy_speed) {
+   case SPEED_10:
+   SET_REG_BITS(, INTF_MODE, 1);
+   SET_REG_BITS(_ctrl, HD_MODE, 0);
+   SET_REG_BITS(, CFG_MACMODE, 0);
+   SET_REG_BITS(, CFG_WAITASYNCRD, 500);
+   SET_REG_BIT(, CFG_SPEED_125, 0);
+   break;
+   case SPEED_100:
+   SET_REG_BITS(, INTF_MODE, 1);
+   SET_REG_BITS(_ctrl, HD_MODE, 1);
+   SET_REG_BITS(, CFG_MACMODE, 1);
+   SET_REG_BITS(, CFG_WAITASYNCRD, 80);
+   SET_REG_BIT(, CFG_SPEED_125, 0);
+   break;
+   default:
+   SET_REG_BITS(, INTF_MODE, 2);
+   SET_REG_BITS(_ctrl, HD_MODE, 2);
+   SET_REG_BITS(, CFG_MACMODE, 2);
+   SET_REG_BITS(, CFG_WAITASYNCRD, 16);
+   SET_REG_BIT(, CFG_SPEED_125, 1);
+   break;
+   }
+
+   mc2 |= FULL_DUPLEX | CRC_EN | PAD_CRC;
+   SET_REG_BITS(, CFG_WFIFOFULLTHR, 0x32);
+
+   xge_wr_csr(pdata, MAC_CONFIG_2, mc2);
+   xge_wr_csr(pdata, INTERFACE_CONTROL, intf_ctrl);
+   xge_wr_csr(pdata, RGMII_REG_0, rgmii);
+   xge_wr_csr(pdata, ICM_CONFIG0_REG_0, icm0);
+   xge_wr_csr(pdata, ICM_CONFIG2_REG_0, icm2);
+   xge_wr_csr(pdata, ECM_CONFIG0_REG_0, ecm0);
+}
+
+void xge_mac_set_station_addr(struct xge_pdata *pdata)
+{
+   u32 addr0, addr1;
+   u8 *dev_addr = pdata->ndev->dev_addr;
+
+   addr0 = (dev_addr[3] << 24) | (dev_addr[2] << 16) |
+   (dev_addr[1] << 8) | dev_addr[0];
+   addr1 = (dev_addr[5] << 24) | (dev_addr[4] << 16);
+
+   xge_wr_csr(pdata, STATION_ADDR0, addr0);
+   xge_wr_csr(pdata, STATION_ADDR1, addr1);
+}
+
+void xge_mac_init(struct xge_pdata *pdata)
+{
+   xge_mac_reset(pdata);
+   xge_mac_set_speed(pdata);
+   xge_mac_set_station_addr(pdata);
+}
+
+void xge_mac_enable(struct xge_pdata *pdata)
+{
+   u32 data;
+
+   data = xge_rd_csr(pdata, MAC_CONFIG_1);
+   data |= TX_EN | RX_EN;
+   xge_wr_csr(pdata, MAC_CONFIG_1, data);
+
+   data = xge_rd_csr(pdata, MAC_CONFIG_1);
+}
+
+void xge_mac_disable(struct xge_pdata *pdata)
+{
+   u32 data;
+
+   data = xge_rd_csr(pdata, MAC_CONFIG_1);
+   data &= ~(TX_EN | RX_EN);
+   xge_wr_csr(pdata, MAC_CONFIG_1, data);
+}
diff --git a/drivers/net/ethernet/apm/xgene-v2/mac.h 
b/drivers/net/ethernet/apm/xgene-v2/mac.h
new file mode 100644
index 000..6237eb2
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/mac.h
@@ -0,0 +1,132 @@
+/*
+ * Applied Micro X-Gene SoC Ethernet v2 Driver
+ 

[PATCH net-next 6/6] MAINTAINERS: Add entry for APM X-Gene SoC Ethernet (v2) driver

2017-01-31 Thread Iyappan Subramanian
This patch adds a MAINTAINERS entry for the ethernet driver for
the on-chip ethernet interface which uses a linked list of DMA
descriptor architecture (v2) for APM X-Gene SoCs.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
Signed-off-by: Keyur Chudgar <kchud...@apm.com>
---
 MAINTAINERS | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index cc106f7..35f4eeb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -896,6 +896,12 @@ F: drivers/net/phy/mdio-xgene.c
 F: Documentation/devicetree/bindings/net/apm-xgene-enet.txt
 F: Documentation/devicetree/bindings/net/apm-xgene-mdio.txt
 
+APPLIED MICRO (APM) X-GENE SOC ETHERNET (V2) DRIVER
+M: Iyappan Subramanian <isubraman...@apm.com>
+M: Keyur Chudgar <kchud...@apm.com>
+S: Supported
+F: drivers/net/ethernet/apm/xgene-v2/
+
 APPLIED MICRO (APM) X-GENE SOC PMU
 M: Tai Nguyen <ttngu...@apm.com>
 S: Supported
-- 
1.9.1



[PATCH net-next 5/6] drivers: net: xgene-v2: Add transmit and receive

2017-01-31 Thread Iyappan Subramanian
This patch adds,
- Transmit
- Transmit completion poll
- Receive poll
- NAPI handler

and enables the driver.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
Signed-off-by: Keyur Chudgar <kchud...@apm.com>
---
 drivers/net/ethernet/apm/Kconfig   |   1 +
 drivers/net/ethernet/apm/Makefile  |   1 +
 drivers/net/ethernet/apm/xgene-v2/Kconfig  |  11 ++
 drivers/net/ethernet/apm/xgene-v2/Makefile |   6 +
 drivers/net/ethernet/apm/xgene-v2/main.c   | 200 -
 5 files changed, 218 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/Kconfig
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/Makefile

diff --git a/drivers/net/ethernet/apm/Kconfig b/drivers/net/ethernet/apm/Kconfig
index ec63d70..59efe5b 100644
--- a/drivers/net/ethernet/apm/Kconfig
+++ b/drivers/net/ethernet/apm/Kconfig
@@ -1 +1,2 @@
 source "drivers/net/ethernet/apm/xgene/Kconfig"
+source "drivers/net/ethernet/apm/xgene-v2/Kconfig"
diff --git a/drivers/net/ethernet/apm/Makefile 
b/drivers/net/ethernet/apm/Makefile
index 65ce32a..946b2a4 100644
--- a/drivers/net/ethernet/apm/Makefile
+++ b/drivers/net/ethernet/apm/Makefile
@@ -3,3 +3,4 @@
 #
 
 obj-$(CONFIG_NET_XGENE) += xgene/
+obj-$(CONFIG_NET_XGENE_V2) += xgene-v2/
diff --git a/drivers/net/ethernet/apm/xgene-v2/Kconfig 
b/drivers/net/ethernet/apm/xgene-v2/Kconfig
new file mode 100644
index 000..1205861
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/Kconfig
@@ -0,0 +1,11 @@
+config NET_XGENE_V2
+   tristate "APM X-Gene SoC Ethernet-v2 Driver"
+   depends on HAS_DMA
+   depends on ARCH_XGENE || COMPILE_TEST
+   help
+ This is the Ethernet driver for the on-chip ethernet interface
+ which uses a linked list of DMA descriptor architecture (v2) for
+ APM X-Gene SoCs.
+
+ To compile this driver as a module, choose M here. This module will
+ be called xgene-enet-v2.
diff --git a/drivers/net/ethernet/apm/xgene-v2/Makefile 
b/drivers/net/ethernet/apm/xgene-v2/Makefile
new file mode 100644
index 000..735309c
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for APM X-Gene Ethernet v2 driver
+#
+
+xgene-enet-v2-objs := main.o mac.o enet.o ring.o
+obj-$(CONFIG_NET_XGENE_V2) += xgene-enet-v2.o
diff --git a/drivers/net/ethernet/apm/xgene-v2/main.c 
b/drivers/net/ethernet/apm/xgene-v2/main.c
index 3881f27..fc90298 100644
--- a/drivers/net/ethernet/apm/xgene-v2/main.c
+++ b/drivers/net/ethernet/apm/xgene-v2/main.c
@@ -164,9 +164,11 @@ static int xge_refill_buffers(struct net_device *ndev, u32 
nbuf)
dma_wmb();
raw_desc->m0 = cpu_to_le64(SET_BITS(PKT_ADDRL, dma_addr) |
   SET_BITS(E, 1));
+
ring->skbs[tail] = skb;
tail = (tail + 1) & slots;
}
+   xge_wr_csr(pdata, DMARXCTRL, 1);
 
ring->tail = tail;
 
@@ -278,13 +280,14 @@ static int xge_open(struct net_device *ndev)
struct xge_pdata *pdata = netdev_priv(ndev);
int ret;
 
+   napi_enable(>napi);
+
ret = xge_request_irq(ndev);
if (ret)
return ret;
 
xge_intr_enable(pdata);
 
-   xge_wr_csr(pdata, DMARXCTRL, 1);
xge_mac_enable(pdata);
netif_start_queue(ndev);
 
@@ -298,11 +301,204 @@ static int xge_close(struct net_device *ndev)
netif_stop_queue(ndev);
xge_mac_disable(pdata);
 
+   xge_intr_disable(pdata);
xge_free_irq(ndev);
+   napi_disable(>napi);
 
return 0;
 }
 
+static netdev_tx_t xge_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+   struct xge_pdata *pdata = netdev_priv(ndev);
+   struct device *dev = >pdev->dev;
+   static dma_addr_t dma_addr;
+   struct xge_desc_ring *tx_ring;
+   struct xge_raw_desc *raw_desc;
+   u64 addr_lo, addr_hi;
+   void *pkt_buf;
+   u8 tail;
+   u16 len;
+
+   tx_ring = pdata->tx_ring;
+   tail = tx_ring->tail;
+   len = skb_headlen(skb);
+   raw_desc = _ring->raw_desc[tail];
+
+   /* Tx descriptor not available */
+   if (!GET_BITS(E, le64_to_cpu(raw_desc->m0)) ||
+   GET_BITS(PKT_SIZE, le64_to_cpu(raw_desc->m0)))
+   return NETDEV_TX_BUSY;
+
+   /* Packet buffers should be 64B aligned */
+   pkt_buf = dma_alloc_coherent(dev, XGENE_ENET_STD_MTU, _addr,
+GFP_ATOMIC);
+   if (unlikely(!pkt_buf))
+   goto out;
+
+   memcpy(pkt_buf, skb->data, len);
+
+   addr_hi = GET_BITS(NEXT_DESC_ADDRH, le64_to_cpu(raw_desc->m1));
+   addr_lo = GET_BITS(NEXT_DESC_ADDRL, le64_to_cpu(raw_desc->m1));
+   raw_desc->m1 = cpu_to_le64(SET_BITS(NEXT_DESC_ADDRL, addr_lo) |
+  

[PATCH net-next 4/6] drivers: net: xgene-v2: Add base driver

2017-01-31 Thread Iyappan Subramanian
This patch adds,

 - probe, remove, shutdown
 - open, close and stats
 - create and delete ring
 - request and delete irq

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
Signed-off-by: Keyur Chudgar <kchud...@apm.com>
---
 drivers/net/ethernet/apm/xgene-v2/main.c | 459 +++
 1 file changed, 459 insertions(+)
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/main.c

diff --git a/drivers/net/ethernet/apm/xgene-v2/main.c 
b/drivers/net/ethernet/apm/xgene-v2/main.c
new file mode 100644
index 000..3881f27
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene-v2/main.c
@@ -0,0 +1,459 @@
+/*
+ * Applied Micro X-Gene SoC Ethernet v2 Driver
+ *
+ * Copyright (c) 2017, Applied Micro Circuits Corporation
+ * Author(s): Iyappan Subramanian <isubraman...@apm.com>
+ *   Keyur Chudgar <kchud...@apm.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "main.h"
+
+static const struct acpi_device_id xge_acpi_match[];
+
+static int xge_get_resources(struct xge_pdata *pdata)
+{
+   struct platform_device *pdev;
+   struct net_device *ndev;
+   struct device *dev;
+   struct resource *res;
+   int phy_mode, ret = 0;
+
+   pdev = pdata->pdev;
+   dev = >dev;
+   ndev = pdata->ndev;
+
+   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   if (!res) {
+   dev_err(dev, "Resource enet_csr not defined\n");
+   return -ENODEV;
+   }
+
+   pdata->resources.base_addr = devm_ioremap(dev, res->start,
+ resource_size(res));
+   if (!pdata->resources.base_addr) {
+   dev_err(dev, "Unable to retrieve ENET Port CSR region\n");
+   return -ENOMEM;
+   }
+
+   if (!device_get_mac_address(dev, ndev->dev_addr, ETH_ALEN))
+   eth_hw_addr_random(ndev);
+
+   memcpy(ndev->perm_addr, ndev->dev_addr, ndev->addr_len);
+
+   phy_mode = device_get_phy_mode(dev);
+   if (phy_mode < 0) {
+   dev_err(dev, "Unable to get phy-connection-type\n");
+   return phy_mode;
+   }
+   pdata->resources.phy_mode = phy_mode;
+
+   if (pdata->resources.phy_mode != PHY_INTERFACE_MODE_RGMII) {
+   dev_err(dev, "Incorrect phy-connection-type specified\n");
+   return -ENODEV;
+   }
+
+   ret = platform_get_irq(pdev, 0);
+   if (ret <= 0) {
+   dev_err(dev, "Unable to get ENET IRQ\n");
+   ret = ret ? : -ENXIO;
+   return ret;
+   }
+   pdata->resources.irq = ret;
+
+   return 0;
+}
+
+static void xge_delete_desc_rings(struct net_device *ndev)
+{
+   struct xge_pdata *pdata = netdev_priv(ndev);
+   struct device *dev = >pdev->dev;
+   struct xge_desc_ring *ring;
+
+   ring = pdata->tx_ring;
+   if (ring) {
+   if (ring->skbs)
+   devm_kfree(dev, ring->skbs);
+   if (ring->pkt_bufs)
+   devm_kfree(dev, ring->pkt_bufs);
+   devm_kfree(dev, ring);
+   }
+
+   ring = pdata->rx_ring;
+   if (ring) {
+   if (ring->skbs)
+   devm_kfree(dev, ring->skbs);
+   devm_kfree(dev, ring);
+   }
+}
+
+static struct xge_desc_ring *xge_create_desc_ring(struct net_device *ndev)
+{
+   struct xge_pdata *pdata = netdev_priv(ndev);
+   struct device *dev = >pdev->dev;
+   struct xge_desc_ring *ring;
+   u16 size;
+
+   ring = devm_kzalloc(dev, sizeof(struct xge_desc_ring), GFP_KERNEL);
+   if (!ring)
+   return NULL;
+
+   ring->ndev = ndev;
+
+   size = XGENE_ENET_DESC_SIZE * XGENE_ENET_NUM_DESC;
+   ring->desc_addr = dmam_alloc_coherent(dev, size, >dma_addr,
+ GFP_KERNEL | __GFP_ZERO);
+   if (!ring->desc_addr) {
+   devm_kfree(dev, ring);
+   return NULL;
+   }
+
+   xge_setup_desc(ring);
+
+   return ring;
+}
+
+static int xge_refill_buffers(struct net_device *ndev, u32 nbuf)
+{
+   struct xge_pdata *pdata = netdev_priv(ndev)

[PATCH net-next 0/6] drivers: net: xgene-v2: Add RGMII based 1G driver

2017-01-31 Thread Iyappan Subramanian
This patch set adds support for RGMII based 1GbE hardware which uses a linked
list of DMA descriptor architecture (v2) for APM X-Gene SoCs.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---

Iyappan Subramanian (6):
  drivers: net: xgene-v2: Add DMA descriptor
  drivers: net: xgene-v2: Add mac configuration
  drivers: net: xgene-v2: Add ethernet hardware configuration
  drivers: net: xgene-v2: Add base driver
  drivers: net: xgene-v2: Add transmit and receive
  MAINTAINERS: Add entry for APM X-Gene SoC Ethernet (v2) driver

 MAINTAINERS|   6 +
 drivers/net/ethernet/apm/Kconfig   |   1 +
 drivers/net/ethernet/apm/Makefile  |   1 +
 drivers/net/ethernet/apm/xgene-v2/Kconfig  |  11 +
 drivers/net/ethernet/apm/xgene-v2/Makefile |   6 +
 drivers/net/ethernet/apm/xgene-v2/enet.c   |  71 
 drivers/net/ethernet/apm/xgene-v2/enet.h   |  43 ++
 drivers/net/ethernet/apm/xgene-v2/mac.c| 116 +
 drivers/net/ethernet/apm/xgene-v2/mac.h| 132 ++
 drivers/net/ethernet/apm/xgene-v2/main.c   | 657 +
 drivers/net/ethernet/apm/xgene-v2/main.h   |  88 
 drivers/net/ethernet/apm/xgene-v2/ring.c   |  73 
 drivers/net/ethernet/apm/xgene-v2/ring.h   |  77 
 13 files changed, 1282 insertions(+)
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/Kconfig
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/Makefile
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/enet.c
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/enet.h
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/mac.c
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/mac.h
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/main.c
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/main.h
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/ring.c
 create mode 100644 drivers/net/ethernet/apm/xgene-v2/ring.h

-- 
1.9.1



Re: [PATCH] drivers: net: xgene: initialize slots

2016-12-08 Thread Iyappan Subramanian
On Thu, Dec 8, 2016 at 3:17 AM, Colin King  wrote:
> From: Colin Ian King 
>
> static analysis using cppcheck detected that slots was uninitialized.
> Fix this by initializing it to buf_pool->slots - 1
>
> Found using static analysis with CoverityScan, CID #1387620
>
> Fixes: a9380b0f7be818 ("drivers: net: xgene: Add support for Jumbo frame")
> Signed-off-by: Colin Ian King 
> ---
>  drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c 
> b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
> index 6c7eea8..899163c 100644
> --- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
> +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
> @@ -636,6 +636,7 @@ static void xgene_enet_free_pagepool(struct 
> xgene_enet_desc_ring *buf_pool,
>
> dev = ndev_to_dev(buf_pool->ndev);
> head = buf_pool->head;
> +   slots = buf_pool->slots - 1;
>
> for (i = 0; i < 4; i++) {
> frag_size = xgene_enet_get_data_len(le64_to_cpu(desc[i ^ 1]));

Thanks, Colin.

Dan Carpenter  posted the fix already and
got accepted.
http://marc.info/?l=linux-netdev=148110980224343=2

> --
> 2.10.2
>


Re: [patch] drivers: net: xgene: uninitialized variable in xgene_enet_free_pagepool()

2016-12-07 Thread Iyappan Subramanian
On Wed, Dec 7, 2016 at 3:14 AM, Dan Carpenter <dan.carpen...@oracle.com> wrote:
> We never set "slots" in this function.
>
> Fixes: a9380b0f7be8 ("drivers: net: xgene: Add support for Jumbo frame")
> Signed-off-by: Dan Carpenter <dan.carpen...@oracle.com>
> ---
> I copied how slots gets set in xgene_enet_rx_frame().  Static analysis.
> Not tested.
>
> diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c 
> b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
> index 6c7eea8b36af..884a334e82d0 100644
> --- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
> +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
> @@ -635,6 +635,7 @@ static void xgene_enet_free_pagepool(struct 
> xgene_enet_desc_ring *buf_pool,
> return;
>
> dev = ndev_to_dev(buf_pool->ndev);
> +   slots = buf_pool->slots - 1;
> head = buf_pool->head;
>
> for (i = 0; i < 4; i++) {

Thanks.

Acked-by: Iyappan Subramanian <isubraman...@apm.com>


[PATCH net-next 2/8] drivers: net: xgene: Configure classifier with pagepool

2016-12-01 Thread Iyappan Subramanian
This patch configures classifier with the pagepool information.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
Signed-off-by: Quan Nguyen <qngu...@apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_cle.c   | 16 ++--
 drivers/net/ethernet/apm/xgene/xgene_enet_cle.h   |  2 ++
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.c|  7 +--
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.h|  6 --
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c  | 11 +--
 drivers/net/ethernet/apm/xgene/xgene_enet_main.h  |  3 ++-
 drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c |  9 ++---
 drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c |  7 +--
 8 files changed, 47 insertions(+), 14 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c
index 7aac0fb..caa55bd 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c
@@ -52,6 +52,7 @@ static void xgene_cle_dbptr_to_hw(struct xgene_enet_pdata 
*pdata,
 {
buf[0] = SET_VAL(CLE_DROP, dbptr->drop);
buf[4] = SET_VAL(CLE_FPSEL, dbptr->fpsel) |
+SET_VAL(CLE_NFPSEL, dbptr->nxtfpsel) |
 SET_VAL(CLE_DSTQIDL, dbptr->dstqid);
 
buf[5] = SET_VAL(CLE_DSTQIDH, (u32)dbptr->dstqid >> CLE_DSTQIDL_LEN) |
@@ -349,8 +350,12 @@ static int xgene_cle_set_rss_idt(struct xgene_enet_pdata 
*pdata)
fpsel = xgene_enet_get_fpsel(pool_id);
dstqid = xgene_enet_dst_ring_num(pdata->rx_ring[idx]);
nfpsel = 0;
-   idt_reg = 0;
+   if (pdata->rx_ring[idx]->page_pool) {
+   pool_id = pdata->rx_ring[idx]->page_pool->id;
+   nfpsel = xgene_enet_get_fpsel(pool_id);
+   }
 
+   idt_reg = 0;
xgene_cle_idt_to_hw(pdata, dstqid, fpsel, nfpsel, _reg);
ret = xgene_cle_dram_wr(>cle, _reg, 1, i,
RSS_IDT, CLE_CMD_WR);
@@ -400,9 +405,9 @@ static int xgene_cle_setup_rss(struct xgene_enet_pdata 
*pdata)
 static int xgene_enet_cle_init(struct xgene_enet_pdata *pdata)
 {
struct xgene_enet_cle *enet_cle = >cle;
+   u32 def_qid, def_fpsel, def_nxtfpsel, pool_id;
struct xgene_cle_dbptr dbptr[DB_MAX_PTRS];
struct xgene_cle_ptree_branch *br;
-   u32 def_qid, def_fpsel, pool_id;
struct xgene_cle_ptree *ptree;
struct xgene_cle_ptree_kn kn;
int ret;
@@ -707,13 +712,20 @@ static int xgene_enet_cle_init(struct xgene_enet_pdata 
*pdata)
def_qid = xgene_enet_dst_ring_num(pdata->rx_ring[0]);
pool_id = pdata->rx_ring[0]->buf_pool->id;
def_fpsel = xgene_enet_get_fpsel(pool_id);
+   def_nxtfpsel = 0;
+   if (pdata->rx_ring[0]->page_pool) {
+   pool_id = pdata->rx_ring[0]->page_pool->id;
+   def_nxtfpsel = xgene_enet_get_fpsel(pool_id);
+   }
 
memset(dbptr, 0, sizeof(struct xgene_cle_dbptr) * DB_MAX_PTRS);
dbptr[DB_RES_ACCEPT].fpsel =  def_fpsel;
+   dbptr[DB_RES_ACCEPT].nxtfpsel = def_nxtfpsel;
dbptr[DB_RES_ACCEPT].dstqid = def_qid;
dbptr[DB_RES_ACCEPT].cle_priority = 1;
 
dbptr[DB_RES_DEF].fpsel = def_fpsel;
+   dbptr[DB_RES_DEF].nxtfpsel = def_nxtfpsel;
dbptr[DB_RES_DEF].dstqid = def_qid;
dbptr[DB_RES_DEF].cle_priority = 7;
xgene_cle_setup_def_dbptr(pdata, enet_cle, [DB_RES_DEF],
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_cle.h 
b/drivers/net/ethernet/apm/xgene/xgene_enet_cle.h
index 9ac9f8e..903be0c 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_cle.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_cle.h
@@ -91,6 +91,8 @@
 #define CLE_DSTQIDH_LEN5
 #define CLE_FPSEL_POS  21
 #define CLE_FPSEL_LEN  4
+#define CLE_NFPSEL_POS 17
+#define CLE_NFPSEL_LEN 4
 #define CLE_PRIORITY_POS   5
 #define CLE_PRIORITY_LEN   3
 
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
index 1007074..c395df3 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
@@ -550,12 +550,14 @@ static void xgene_enet_config_ring_if_assoc(struct 
xgene_enet_pdata *pdata)
 }
 
 static void xgene_enet_cle_bypass(struct xgene_enet_pdata *pdata,
- u32 dst_ring_num, u16 bufpool_id)
+ u32 dst_ring_num, u16 bufpool_id,
+ u16 nxtbufpool_id)
 {
u32 cb;
-   u32 fpsel;
+   u32 fpsel, nxtfpsel;
 
fpsel = xgene_enet_get_fpsel(bufpool_id);
+   nxtfpsel = xgene_enet_get_fpsel(nxtbufpool_id);
 
xgene_enet_rd_csr(pdata, CLE_BYPASS_REG0_0_ADDR, );
cb

[PATCH net-next 5/8] drivers: net: xgene: fix: RSS for non-TCP/UDP

2016-12-01 Thread Iyappan Subramanian
This patch fixes RSS feature, for non-TCP/UDP packets.

Signed-off-by: Khuong Dinh <kd...@apm.com>
Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_cle.c | 90 -
 drivers/net/ethernet/apm/xgene/xgene_enet_cle.h |  1 +
 2 files changed, 89 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c
index caa55bd..1dc6c20 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c
@@ -485,11 +485,11 @@ static int xgene_enet_cle_init(struct xgene_enet_pdata 
*pdata)
},
{
.valid = 0,
-   .next_packet_pointer = 260,
+   .next_packet_pointer = 26,
.jump_bw = JMP_FW,
.jump_rel = JMP_ABS,
.operation = EQT,
-   .next_node = LAST_NODE,
+   .next_node = RSS_IPV4_OTHERS_NODE,
.next_branch = 0,
.data = 0x0,
.mask = 0x
@@ -667,6 +667,92 @@ static int xgene_enet_cle_init(struct xgene_enet_pdata 
*pdata)
}
},
{
+   /* RSS_IPV4_OTHERS_NODE */
+   .node_type = EWDN,
+   .last_node = 0,
+   .hdr_len_store = 1,
+   .hdr_extn = NO_BYTE,
+   .byte_store = NO_BYTE,
+   .search_byte_store = BOTH_BYTES,
+   .result_pointer = DB_RES_DROP,
+   .num_branches = 6,
+   .branch = {
+   {
+   /* SRC IPV4 B01 */
+   .valid = 0,
+   .next_packet_pointer = 28,
+   .jump_bw = JMP_FW,
+   .jump_rel = JMP_ABS,
+   .operation = EQT,
+   .next_node = RSS_IPV4_OTHERS_NODE,
+   .next_branch = 1,
+   .data = 0x0,
+   .mask = 0x
+   },
+   {
+   /* SRC IPV4 B23 */
+   .valid = 0,
+   .next_packet_pointer = 30,
+   .jump_bw = JMP_FW,
+   .jump_rel = JMP_ABS,
+   .operation = EQT,
+   .next_node = RSS_IPV4_OTHERS_NODE,
+   .next_branch = 2,
+   .data = 0x0,
+   .mask = 0x
+   },
+   {
+   /* DST IPV4 B01 */
+   .valid = 0,
+   .next_packet_pointer = 32,
+   .jump_bw = JMP_FW,
+   .jump_rel = JMP_ABS,
+   .operation = EQT,
+   .next_node = RSS_IPV4_OTHERS_NODE,
+   .next_branch = 3,
+   .data = 0x0,
+   .mask = 0x
+   },
+   {
+   /* DST IPV4 B23 */
+   .valid = 0,
+   .next_packet_pointer = 34,
+   .jump_bw = JMP_FW,
+   .jump_rel = JMP_ABS,
+   .operation = EQT,
+   .next_node = RSS_IPV4_OTHERS_NODE,
+   .next_branch = 4,
+   .data = 0x0,
+   .mask = 0x
+   },
+   {
+   /* TCP SRC Port */
+   .valid = 0,
+   .next_packet_pointer = 36,
+   .jump

[PATCH net-next 7/8] drivers: net: xgene: Add flow control initialization

2016-12-01 Thread Iyappan Subramanian
This patch adds flow control/pause frame initialization and
advertising capabilities.

Signed-off-by: Iyappan Subramanian <isubraman...@apm.com>
Signed-off-by: Quan Nguyen <qngu...@apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.c| 57 +++
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.h|  7 +++
 drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c | 44 -
 drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c | 17 +++
 drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h |  7 +++
 5 files changed, 131 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c 
b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
index 23a0175..06e6816 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
@@ -577,6 +577,17 @@ static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
/* Rtype should be copied from FP */
xgene_enet_wr_csr(pdata, RSIF_RAM_DBG_REG0_ADDR, 0);
 
+   /* Configure HW pause frame generation */
+   xgene_enet_rd_mcx_csr(pdata, CSR_MULTI_DPF0_ADDR, );
+   value = (DEF_QUANTA << 16) | (value & 0x);
+   xgene_enet_wr_mcx_csr(pdata, CSR_MULTI_DPF0_ADDR, value);
+
+   xgene_enet_wr_csr(pdata, RXBUF_PAUSE_THRESH, DEF_PAUSE_THRES);
+   xgene_enet_wr_csr(pdata, RXBUF_PAUSE_OFF_THRESH, DEF_PAUSE_OFF_THRES);
+
+   xgene_gmac_flowctl_tx(pdata, pdata->tx_pause);
+   xgene_gmac_flowctl_rx(pdata, pdata->rx_pause);
+
/* Rx-Tx traffic resume */
xgene_enet_wr_csr(pdata, CFG_LINK_AGGR_RESUME_0_ADDR, TX_PORT0);
 
@@ -749,6 +760,48 @@ static void xgene_gport_shutdown(struct xgene_enet_pdata 
*pdata)
}
 }
 
+static u32 xgene_enet_flowctrl_cfg(struct net_device *ndev)
+{
+   struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+   struct phy_device *phydev = ndev->phydev;
+   u16 lcladv, rmtadv = 0;
+   u32 rx_pause, tx_pause;
+   u8 flowctl = 0;
+
+   if (!phydev->duplex || !pdata->pause_autoneg)
+   return 0;
+
+   if (pdata->tx_pause)
+   flowctl |= FLOW_CTRL_TX;
+
+   if (pdata->rx_pause)
+   flowctl |= FLOW_CTRL_RX;
+
+   lcladv = mii_advertise_flowctrl(flowctl);
+
+   if (phydev->pause)
+   rmtadv = LPA_PAUSE_CAP;
+
+   if (phydev->asym_pause)
+   rmtadv |= LPA_PAUSE_ASYM;
+
+   flowctl = mii_resolve_flowctrl_fdx(lcladv, rmtadv);
+   tx_pause = !!(flowctl & FLOW_CTRL_TX);
+   rx_pause = !!(flowctl & FLOW_CTRL_RX);
+
+   if (tx_pause != pdata->tx_pause) {
+   pdata->tx_pause = tx_pause;
+   pdata->mac_ops->flowctl_tx(pdata, pdata->tx_pause);
+   }
+
+   if (rx_pause != pdata->rx_pause) {
+   pdata->rx_pause = rx_pause;
+   pdata->mac_ops->flowctl_rx(pdata, pdata->rx_pause);
+   }
+
+   return 0;
+}
+
 static void xgene_enet_adjust_link(struct net_device *ndev)
 {
struct xgene_enet_pdata *pdata = netdev_priv(ndev);
@@ -763,6 +816,8 @@ static void xgene_enet_adjust_link(struct net_device *ndev)
mac_ops->tx_enable(pdata);
phy_print_status(phydev);
}
+
+   xgene_enet_flowctrl_cfg(ndev);
} else {
mac_ops->rx_disable(pdata);
mac_ops->tx_disable(pdata);
@@ -836,6 +891,8 @@ int xgene_enet_phy_connect(struct net_device *ndev)
phy_dev->supported &= ~SUPPORTED_10baseT_Half &
  ~SUPPORTED_100baseT_Half &
  ~SUPPORTED_1000baseT_Half;
+   phy_dev->supported |= SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause;
phy_dev->advertising = phy_dev->supported;
 
return 0;
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h 
b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
index 7ba649d..5f83037 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
@@ -172,6 +172,13 @@ enum xgene_enet_rm {
 #define CFG_CLE_FPSEL0(val)(((val) << 16) & GENMASK(19, 16))
 #define CSR_ECM_CFG_0_ADDR 0x0220
 #define CSR_ECM_CFG_1_ADDR 0x0224
+#define CSR_MULTI_DPF0_ADDR0x0230
+#define RXBUF_PAUSE_THRESH 0x0534
+#define RXBUF_PAUSE_OFF_THRESH 0x0540
+#define DEF_PAUSE_THRES0x7d
+#define DEF_PAUSE_OFF_THRES0x6d
+#define DEF_QUANTA 0x8000
+#define NORM_PAUSE_OPCODE  0x0001
 #define PAUSE_XON_EN   BIT(30)
 #define MULTI_DPF_AUTOCTRL BIT(28)
 #define CFG_CLE_NXTFPSEL0(val) (((val) << 20) & GENMASK(23, 20))
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c 
b/drivers/net/e

  1   2   3   >