All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] Dual EMAC mode implementation of CPSW
@ 2013-02-11 19:52 ` Mugunthan V N
  0 siblings, 0 replies; 48+ messages in thread
From: Mugunthan V N @ 2013-02-11 19:52 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-arm-kernel, linux-omap, Mugunthan V N

This patch series implements Dual EMAC mode implementation of CPSW
which acts as two standalone EMAC by segregating the switch using VIDs
and port VLAN

Mugunthan V N (3):
  driver: net: ethernet: davinci_cpdma: add support for directed packet
    and source port detection
  driver: net: ethernet: cpsw: make cpts as pointer
  driver: net: ethernet: cpsw: dual emac interface implementation

 Documentation/devicetree/bindings/net/cpsw.txt |    2 +
 drivers/net/ethernet/ti/cpsw.c                 |  387 +++++++++++++++++++-----
 drivers/net/ethernet/ti/davinci_cpdma.c        |   17 +-
 drivers/net/ethernet/ti/davinci_cpdma.h        |    4 +-
 drivers/net/ethernet/ti/davinci_emac.c         |    6 +-
 include/linux/platform_data/cpsw.h             |    3 +
 6 files changed, 338 insertions(+), 81 deletions(-)

-- 
1.7.9.5

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH 0/3] Dual EMAC mode implementation of CPSW
@ 2013-02-11 19:52 ` Mugunthan V N
  0 siblings, 0 replies; 48+ messages in thread
From: Mugunthan V N @ 2013-02-11 19:52 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-arm-kernel, linux-omap, Mugunthan V N

This patch series implements Dual EMAC mode implementation of CPSW
which acts as two standalone EMAC by segregating the switch using VIDs
and port VLAN

Mugunthan V N (3):
  driver: net: ethernet: davinci_cpdma: add support for directed packet
    and source port detection
  driver: net: ethernet: cpsw: make cpts as pointer
  driver: net: ethernet: cpsw: dual emac interface implementation

 Documentation/devicetree/bindings/net/cpsw.txt |    2 +
 drivers/net/ethernet/ti/cpsw.c                 |  387 +++++++++++++++++++-----
 drivers/net/ethernet/ti/davinci_cpdma.c        |   17 +-
 drivers/net/ethernet/ti/davinci_cpdma.h        |    4 +-
 drivers/net/ethernet/ti/davinci_emac.c         |    6 +-
 include/linux/platform_data/cpsw.h             |    3 +
 6 files changed, 338 insertions(+), 81 deletions(-)

-- 
1.7.9.5

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH 0/3] Dual EMAC mode implementation of CPSW
@ 2013-02-11 19:52 ` Mugunthan V N
  0 siblings, 0 replies; 48+ messages in thread
From: Mugunthan V N @ 2013-02-11 19:52 UTC (permalink / raw)
  To: linux-arm-kernel

This patch series implements Dual EMAC mode implementation of CPSW
which acts as two standalone EMAC by segregating the switch using VIDs
and port VLAN

Mugunthan V N (3):
  driver: net: ethernet: davinci_cpdma: add support for directed packet
    and source port detection
  driver: net: ethernet: cpsw: make cpts as pointer
  driver: net: ethernet: cpsw: dual emac interface implementation

 Documentation/devicetree/bindings/net/cpsw.txt |    2 +
 drivers/net/ethernet/ti/cpsw.c                 |  387 +++++++++++++++++++-----
 drivers/net/ethernet/ti/davinci_cpdma.c        |   17 +-
 drivers/net/ethernet/ti/davinci_cpdma.h        |    4 +-
 drivers/net/ethernet/ti/davinci_emac.c         |    6 +-
 include/linux/platform_data/cpsw.h             |    3 +
 6 files changed, 338 insertions(+), 81 deletions(-)

-- 
1.7.9.5

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH 1/3] driver: net: ethernet: davinci_cpdma: add support for directed packet and source port detection
  2013-02-11 19:52 ` Mugunthan V N
  (?)
@ 2013-02-11 19:52   ` Mugunthan V N
  -1 siblings, 0 replies; 48+ messages in thread
From: Mugunthan V N @ 2013-02-11 19:52 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-arm-kernel, linux-omap, Mugunthan V N

* Introduced parameter to add port number for directed packet in cpdma_chan_submit
* Source port detection macro with DMA descriptor status

Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
---
 drivers/net/ethernet/ti/cpsw.c          |    6 +++---
 drivers/net/ethernet/ti/davinci_cpdma.c |   17 +++++++++++++++--
 drivers/net/ethernet/ti/davinci_cpdma.h |    4 +++-
 drivers/net/ethernet/ti/davinci_emac.c  |    6 +++---
 4 files changed, 24 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 888708c..8ac60c7 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -424,7 +424,7 @@ void cpsw_rx_handler(void *token, int len, int status)
 			return;
 
 		ret = cpdma_chan_submit(priv->rxch, skb, skb->data,
-					skb_tailroom(skb), GFP_KERNEL);
+					skb_tailroom(skb), 0, GFP_KERNEL);
 	}
 	WARN_ON(ret < 0);
 }
@@ -705,7 +705,7 @@ static int cpsw_ndo_open(struct net_device *ndev)
 		if (!skb)
 			break;
 		ret = cpdma_chan_submit(priv->rxch, skb, skb->data,
-					skb_tailroom(skb), GFP_KERNEL);
+					skb_tailroom(skb), 0, GFP_KERNEL);
 		if (WARN_ON(ret < 0))
 			break;
 	}
@@ -766,7 +766,7 @@ static netdev_tx_t cpsw_ndo_start_xmit(struct sk_buff *skb,
 	skb_tx_timestamp(skb);
 
 	ret = cpdma_chan_submit(priv->txch, skb, skb->data,
-				skb->len, GFP_KERNEL);
+				skb->len, 0, GFP_KERNEL);
 	if (unlikely(ret != 0)) {
 		cpsw_err(priv, tx_err, "desc submit failed\n");
 		goto fail;
diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c b/drivers/net/ethernet/ti/davinci_cpdma.c
index afe14a6..ca25cc8 100644
--- a/drivers/net/ethernet/ti/davinci_cpdma.c
+++ b/drivers/net/ethernet/ti/davinci_cpdma.c
@@ -60,6 +60,9 @@
 #define CPDMA_DESC_EOQ		BIT(28)
 #define CPDMA_DESC_TD_COMPLETE	BIT(27)
 #define CPDMA_DESC_PASS_CRC	BIT(26)
+#define CPDMA_DESC_TO_PORT_EN	BIT(20)
+#define CPDMA_TO_PORT_SHIFT	16
+#define CPDMA_DESC_PORT_MASK	(BIT(18) | BIT(17) | BIT(16))
 
 #define CPDMA_TEARDOWN_VALUE	0xfffffffc
 
@@ -132,6 +135,14 @@ struct cpdma_chan {
 #define chan_write(chan, fld, v)	__raw_writel(v, (chan)->fld)
 #define desc_write(desc, fld, v)	__raw_writel((u32)(v), &(desc)->fld)
 
+#define cpdma_desc_to_port(chan, mode, directed)			\
+	do {								\
+		if (!is_rx_chan(chan) && ((directed == 1) ||		\
+					  (directed == 2)))		\
+			mode |= (CPDMA_DESC_TO_PORT_EN |		\
+				 (directed << CPDMA_TO_PORT_SHIFT));	\
+	} while (0)
+
 /*
  * Utility constructs for a cpdma descriptor pool.  Some devices (e.g. davinci
  * emac) have dedicated on-chip memory for these descriptors.  Some other
@@ -664,7 +675,7 @@ static void __cpdma_chan_submit(struct cpdma_chan *chan,
 }
 
 int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
-		      int len, gfp_t gfp_mask)
+		      int len, int directed, gfp_t gfp_mask)
 {
 	struct cpdma_ctlr		*ctlr = chan->ctlr;
 	struct cpdma_desc __iomem	*desc;
@@ -694,6 +705,7 @@ int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
 
 	buffer = dma_map_single(ctlr->dev, data, len, chan->dir);
 	mode = CPDMA_DESC_OWNER | CPDMA_DESC_SOP | CPDMA_DESC_EOP;
+	cpdma_desc_to_port(chan, mode, directed);
 
 	desc_write(desc, hw_next,   0);
 	desc_write(desc, hw_buffer, buffer);
@@ -784,7 +796,8 @@ static int __cpdma_chan_process(struct cpdma_chan *chan)
 		status = -EBUSY;
 		goto unlock_ret;
 	}
-	status	= status & (CPDMA_DESC_EOQ | CPDMA_DESC_TD_COMPLETE);
+	status	= status & (CPDMA_DESC_EOQ | CPDMA_DESC_TD_COMPLETE |
+			    CPDMA_DESC_PORT_MASK);
 
 	chan->head = desc_from_phys(pool, desc_read(desc, hw_next));
 	chan_write(chan, cp, desc_dma);
diff --git a/drivers/net/ethernet/ti/davinci_cpdma.h b/drivers/net/ethernet/ti/davinci_cpdma.h
index 8d2aeb2..a97d6ab 100644
--- a/drivers/net/ethernet/ti/davinci_cpdma.h
+++ b/drivers/net/ethernet/ti/davinci_cpdma.h
@@ -24,6 +24,8 @@
 #define __chan_linear(chan_num)	((chan_num) & (CPDMA_MAX_CHANNELS - 1))
 #define chan_linear(chan)	__chan_linear((chan)->chan_num)
 
+#define CPDMA_RX_SOURCE_PORT(__status__)	((__status__ >> 16) & 0x7)
+
 struct cpdma_params {
 	struct device		*dev;
 	void __iomem		*dmaregs;
@@ -82,7 +84,7 @@ int cpdma_chan_dump(struct cpdma_chan *chan);
 int cpdma_chan_get_stats(struct cpdma_chan *chan,
 			 struct cpdma_chan_stats *stats);
 int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
-		      int len, gfp_t gfp_mask);
+		      int len, int directed, gfp_t gfp_mask);
 int cpdma_chan_process(struct cpdma_chan *chan, int quota);
 
 int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable);
diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c
index 242ec55..52c0536 100644
--- a/drivers/net/ethernet/ti/davinci_emac.c
+++ b/drivers/net/ethernet/ti/davinci_emac.c
@@ -1037,7 +1037,7 @@ static void emac_rx_handler(void *token, int len, int status)
 
 recycle:
 	ret = cpdma_chan_submit(priv->rxchan, skb, skb->data,
-			skb_tailroom(skb), GFP_KERNEL);
+			skb_tailroom(skb), 0, GFP_KERNEL);
 
 	WARN_ON(ret == -ENOMEM);
 	if (unlikely(ret < 0))
@@ -1092,7 +1092,7 @@ static int emac_dev_xmit(struct sk_buff *skb, struct net_device *ndev)
 	skb_tx_timestamp(skb);
 
 	ret_code = cpdma_chan_submit(priv->txchan, skb, skb->data, skb->len,
-				     GFP_KERNEL);
+				     0, GFP_KERNEL);
 	if (unlikely(ret_code != 0)) {
 		if (netif_msg_tx_err(priv) && net_ratelimit())
 			dev_err(emac_dev, "DaVinci EMAC: desc submit failed");
@@ -1558,7 +1558,7 @@ static int emac_dev_open(struct net_device *ndev)
 			break;
 
 		ret = cpdma_chan_submit(priv->rxchan, skb, skb->data,
-					skb_tailroom(skb), GFP_KERNEL);
+					skb_tailroom(skb), 0, GFP_KERNEL);
 		if (WARN_ON(ret < 0))
 			break;
 	}
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 1/3] driver: net: ethernet: davinci_cpdma: add support for directed packet and source port detection
@ 2013-02-11 19:52   ` Mugunthan V N
  0 siblings, 0 replies; 48+ messages in thread
From: Mugunthan V N @ 2013-02-11 19:52 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-arm-kernel, linux-omap, Mugunthan V N

* Introduced parameter to add port number for directed packet in cpdma_chan_submit
* Source port detection macro with DMA descriptor status

Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
---
 drivers/net/ethernet/ti/cpsw.c          |    6 +++---
 drivers/net/ethernet/ti/davinci_cpdma.c |   17 +++++++++++++++--
 drivers/net/ethernet/ti/davinci_cpdma.h |    4 +++-
 drivers/net/ethernet/ti/davinci_emac.c  |    6 +++---
 4 files changed, 24 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 888708c..8ac60c7 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -424,7 +424,7 @@ void cpsw_rx_handler(void *token, int len, int status)
 			return;
 
 		ret = cpdma_chan_submit(priv->rxch, skb, skb->data,
-					skb_tailroom(skb), GFP_KERNEL);
+					skb_tailroom(skb), 0, GFP_KERNEL);
 	}
 	WARN_ON(ret < 0);
 }
@@ -705,7 +705,7 @@ static int cpsw_ndo_open(struct net_device *ndev)
 		if (!skb)
 			break;
 		ret = cpdma_chan_submit(priv->rxch, skb, skb->data,
-					skb_tailroom(skb), GFP_KERNEL);
+					skb_tailroom(skb), 0, GFP_KERNEL);
 		if (WARN_ON(ret < 0))
 			break;
 	}
@@ -766,7 +766,7 @@ static netdev_tx_t cpsw_ndo_start_xmit(struct sk_buff *skb,
 	skb_tx_timestamp(skb);
 
 	ret = cpdma_chan_submit(priv->txch, skb, skb->data,
-				skb->len, GFP_KERNEL);
+				skb->len, 0, GFP_KERNEL);
 	if (unlikely(ret != 0)) {
 		cpsw_err(priv, tx_err, "desc submit failed\n");
 		goto fail;
diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c b/drivers/net/ethernet/ti/davinci_cpdma.c
index afe14a6..ca25cc8 100644
--- a/drivers/net/ethernet/ti/davinci_cpdma.c
+++ b/drivers/net/ethernet/ti/davinci_cpdma.c
@@ -60,6 +60,9 @@
 #define CPDMA_DESC_EOQ		BIT(28)
 #define CPDMA_DESC_TD_COMPLETE	BIT(27)
 #define CPDMA_DESC_PASS_CRC	BIT(26)
+#define CPDMA_DESC_TO_PORT_EN	BIT(20)
+#define CPDMA_TO_PORT_SHIFT	16
+#define CPDMA_DESC_PORT_MASK	(BIT(18) | BIT(17) | BIT(16))
 
 #define CPDMA_TEARDOWN_VALUE	0xfffffffc
 
@@ -132,6 +135,14 @@ struct cpdma_chan {
 #define chan_write(chan, fld, v)	__raw_writel(v, (chan)->fld)
 #define desc_write(desc, fld, v)	__raw_writel((u32)(v), &(desc)->fld)
 
+#define cpdma_desc_to_port(chan, mode, directed)			\
+	do {								\
+		if (!is_rx_chan(chan) && ((directed == 1) ||		\
+					  (directed == 2)))		\
+			mode |= (CPDMA_DESC_TO_PORT_EN |		\
+				 (directed << CPDMA_TO_PORT_SHIFT));	\
+	} while (0)
+
 /*
  * Utility constructs for a cpdma descriptor pool.  Some devices (e.g. davinci
  * emac) have dedicated on-chip memory for these descriptors.  Some other
@@ -664,7 +675,7 @@ static void __cpdma_chan_submit(struct cpdma_chan *chan,
 }
 
 int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
-		      int len, gfp_t gfp_mask)
+		      int len, int directed, gfp_t gfp_mask)
 {
 	struct cpdma_ctlr		*ctlr = chan->ctlr;
 	struct cpdma_desc __iomem	*desc;
@@ -694,6 +705,7 @@ int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
 
 	buffer = dma_map_single(ctlr->dev, data, len, chan->dir);
 	mode = CPDMA_DESC_OWNER | CPDMA_DESC_SOP | CPDMA_DESC_EOP;
+	cpdma_desc_to_port(chan, mode, directed);
 
 	desc_write(desc, hw_next,   0);
 	desc_write(desc, hw_buffer, buffer);
@@ -784,7 +796,8 @@ static int __cpdma_chan_process(struct cpdma_chan *chan)
 		status = -EBUSY;
 		goto unlock_ret;
 	}
-	status	= status & (CPDMA_DESC_EOQ | CPDMA_DESC_TD_COMPLETE);
+	status	= status & (CPDMA_DESC_EOQ | CPDMA_DESC_TD_COMPLETE |
+			    CPDMA_DESC_PORT_MASK);
 
 	chan->head = desc_from_phys(pool, desc_read(desc, hw_next));
 	chan_write(chan, cp, desc_dma);
diff --git a/drivers/net/ethernet/ti/davinci_cpdma.h b/drivers/net/ethernet/ti/davinci_cpdma.h
index 8d2aeb2..a97d6ab 100644
--- a/drivers/net/ethernet/ti/davinci_cpdma.h
+++ b/drivers/net/ethernet/ti/davinci_cpdma.h
@@ -24,6 +24,8 @@
 #define __chan_linear(chan_num)	((chan_num) & (CPDMA_MAX_CHANNELS - 1))
 #define chan_linear(chan)	__chan_linear((chan)->chan_num)
 
+#define CPDMA_RX_SOURCE_PORT(__status__)	((__status__ >> 16) & 0x7)
+
 struct cpdma_params {
 	struct device		*dev;
 	void __iomem		*dmaregs;
@@ -82,7 +84,7 @@ int cpdma_chan_dump(struct cpdma_chan *chan);
 int cpdma_chan_get_stats(struct cpdma_chan *chan,
 			 struct cpdma_chan_stats *stats);
 int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
-		      int len, gfp_t gfp_mask);
+		      int len, int directed, gfp_t gfp_mask);
 int cpdma_chan_process(struct cpdma_chan *chan, int quota);
 
 int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable);
diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c
index 242ec55..52c0536 100644
--- a/drivers/net/ethernet/ti/davinci_emac.c
+++ b/drivers/net/ethernet/ti/davinci_emac.c
@@ -1037,7 +1037,7 @@ static void emac_rx_handler(void *token, int len, int status)
 
 recycle:
 	ret = cpdma_chan_submit(priv->rxchan, skb, skb->data,
-			skb_tailroom(skb), GFP_KERNEL);
+			skb_tailroom(skb), 0, GFP_KERNEL);
 
 	WARN_ON(ret == -ENOMEM);
 	if (unlikely(ret < 0))
@@ -1092,7 +1092,7 @@ static int emac_dev_xmit(struct sk_buff *skb, struct net_device *ndev)
 	skb_tx_timestamp(skb);
 
 	ret_code = cpdma_chan_submit(priv->txchan, skb, skb->data, skb->len,
-				     GFP_KERNEL);
+				     0, GFP_KERNEL);
 	if (unlikely(ret_code != 0)) {
 		if (netif_msg_tx_err(priv) && net_ratelimit())
 			dev_err(emac_dev, "DaVinci EMAC: desc submit failed");
@@ -1558,7 +1558,7 @@ static int emac_dev_open(struct net_device *ndev)
 			break;
 
 		ret = cpdma_chan_submit(priv->rxchan, skb, skb->data,
-					skb_tailroom(skb), GFP_KERNEL);
+					skb_tailroom(skb), 0, GFP_KERNEL);
 		if (WARN_ON(ret < 0))
 			break;
 	}
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 1/3] driver: net: ethernet: davinci_cpdma: add support for directed packet and source port detection
@ 2013-02-11 19:52   ` Mugunthan V N
  0 siblings, 0 replies; 48+ messages in thread
From: Mugunthan V N @ 2013-02-11 19:52 UTC (permalink / raw)
  To: linux-arm-kernel

* Introduced parameter to add port number for directed packet in cpdma_chan_submit
* Source port detection macro with DMA descriptor status

Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
---
 drivers/net/ethernet/ti/cpsw.c          |    6 +++---
 drivers/net/ethernet/ti/davinci_cpdma.c |   17 +++++++++++++++--
 drivers/net/ethernet/ti/davinci_cpdma.h |    4 +++-
 drivers/net/ethernet/ti/davinci_emac.c  |    6 +++---
 4 files changed, 24 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 888708c..8ac60c7 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -424,7 +424,7 @@ void cpsw_rx_handler(void *token, int len, int status)
 			return;
 
 		ret = cpdma_chan_submit(priv->rxch, skb, skb->data,
-					skb_tailroom(skb), GFP_KERNEL);
+					skb_tailroom(skb), 0, GFP_KERNEL);
 	}
 	WARN_ON(ret < 0);
 }
@@ -705,7 +705,7 @@ static int cpsw_ndo_open(struct net_device *ndev)
 		if (!skb)
 			break;
 		ret = cpdma_chan_submit(priv->rxch, skb, skb->data,
-					skb_tailroom(skb), GFP_KERNEL);
+					skb_tailroom(skb), 0, GFP_KERNEL);
 		if (WARN_ON(ret < 0))
 			break;
 	}
@@ -766,7 +766,7 @@ static netdev_tx_t cpsw_ndo_start_xmit(struct sk_buff *skb,
 	skb_tx_timestamp(skb);
 
 	ret = cpdma_chan_submit(priv->txch, skb, skb->data,
-				skb->len, GFP_KERNEL);
+				skb->len, 0, GFP_KERNEL);
 	if (unlikely(ret != 0)) {
 		cpsw_err(priv, tx_err, "desc submit failed\n");
 		goto fail;
diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c b/drivers/net/ethernet/ti/davinci_cpdma.c
index afe14a6..ca25cc8 100644
--- a/drivers/net/ethernet/ti/davinci_cpdma.c
+++ b/drivers/net/ethernet/ti/davinci_cpdma.c
@@ -60,6 +60,9 @@
 #define CPDMA_DESC_EOQ		BIT(28)
 #define CPDMA_DESC_TD_COMPLETE	BIT(27)
 #define CPDMA_DESC_PASS_CRC	BIT(26)
+#define CPDMA_DESC_TO_PORT_EN	BIT(20)
+#define CPDMA_TO_PORT_SHIFT	16
+#define CPDMA_DESC_PORT_MASK	(BIT(18) | BIT(17) | BIT(16))
 
 #define CPDMA_TEARDOWN_VALUE	0xfffffffc
 
@@ -132,6 +135,14 @@ struct cpdma_chan {
 #define chan_write(chan, fld, v)	__raw_writel(v, (chan)->fld)
 #define desc_write(desc, fld, v)	__raw_writel((u32)(v), &(desc)->fld)
 
+#define cpdma_desc_to_port(chan, mode, directed)			\
+	do {								\
+		if (!is_rx_chan(chan) && ((directed == 1) ||		\
+					  (directed == 2)))		\
+			mode |= (CPDMA_DESC_TO_PORT_EN |		\
+				 (directed << CPDMA_TO_PORT_SHIFT));	\
+	} while (0)
+
 /*
  * Utility constructs for a cpdma descriptor pool.  Some devices (e.g. davinci
  * emac) have dedicated on-chip memory for these descriptors.  Some other
@@ -664,7 +675,7 @@ static void __cpdma_chan_submit(struct cpdma_chan *chan,
 }
 
 int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
-		      int len, gfp_t gfp_mask)
+		      int len, int directed, gfp_t gfp_mask)
 {
 	struct cpdma_ctlr		*ctlr = chan->ctlr;
 	struct cpdma_desc __iomem	*desc;
@@ -694,6 +705,7 @@ int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
 
 	buffer = dma_map_single(ctlr->dev, data, len, chan->dir);
 	mode = CPDMA_DESC_OWNER | CPDMA_DESC_SOP | CPDMA_DESC_EOP;
+	cpdma_desc_to_port(chan, mode, directed);
 
 	desc_write(desc, hw_next,   0);
 	desc_write(desc, hw_buffer, buffer);
@@ -784,7 +796,8 @@ static int __cpdma_chan_process(struct cpdma_chan *chan)
 		status = -EBUSY;
 		goto unlock_ret;
 	}
-	status	= status & (CPDMA_DESC_EOQ | CPDMA_DESC_TD_COMPLETE);
+	status	= status & (CPDMA_DESC_EOQ | CPDMA_DESC_TD_COMPLETE |
+			    CPDMA_DESC_PORT_MASK);
 
 	chan->head = desc_from_phys(pool, desc_read(desc, hw_next));
 	chan_write(chan, cp, desc_dma);
diff --git a/drivers/net/ethernet/ti/davinci_cpdma.h b/drivers/net/ethernet/ti/davinci_cpdma.h
index 8d2aeb2..a97d6ab 100644
--- a/drivers/net/ethernet/ti/davinci_cpdma.h
+++ b/drivers/net/ethernet/ti/davinci_cpdma.h
@@ -24,6 +24,8 @@
 #define __chan_linear(chan_num)	((chan_num) & (CPDMA_MAX_CHANNELS - 1))
 #define chan_linear(chan)	__chan_linear((chan)->chan_num)
 
+#define CPDMA_RX_SOURCE_PORT(__status__)	((__status__ >> 16) & 0x7)
+
 struct cpdma_params {
 	struct device		*dev;
 	void __iomem		*dmaregs;
@@ -82,7 +84,7 @@ int cpdma_chan_dump(struct cpdma_chan *chan);
 int cpdma_chan_get_stats(struct cpdma_chan *chan,
 			 struct cpdma_chan_stats *stats);
 int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
-		      int len, gfp_t gfp_mask);
+		      int len, int directed, gfp_t gfp_mask);
 int cpdma_chan_process(struct cpdma_chan *chan, int quota);
 
 int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable);
diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c
index 242ec55..52c0536 100644
--- a/drivers/net/ethernet/ti/davinci_emac.c
+++ b/drivers/net/ethernet/ti/davinci_emac.c
@@ -1037,7 +1037,7 @@ static void emac_rx_handler(void *token, int len, int status)
 
 recycle:
 	ret = cpdma_chan_submit(priv->rxchan, skb, skb->data,
-			skb_tailroom(skb), GFP_KERNEL);
+			skb_tailroom(skb), 0, GFP_KERNEL);
 
 	WARN_ON(ret == -ENOMEM);
 	if (unlikely(ret < 0))
@@ -1092,7 +1092,7 @@ static int emac_dev_xmit(struct sk_buff *skb, struct net_device *ndev)
 	skb_tx_timestamp(skb);
 
 	ret_code = cpdma_chan_submit(priv->txchan, skb, skb->data, skb->len,
-				     GFP_KERNEL);
+				     0, GFP_KERNEL);
 	if (unlikely(ret_code != 0)) {
 		if (netif_msg_tx_err(priv) && net_ratelimit())
 			dev_err(emac_dev, "DaVinci EMAC: desc submit failed");
@@ -1558,7 +1558,7 @@ static int emac_dev_open(struct net_device *ndev)
 			break;
 
 		ret = cpdma_chan_submit(priv->rxchan, skb, skb->data,
-					skb_tailroom(skb), GFP_KERNEL);
+					skb_tailroom(skb), 0, GFP_KERNEL);
 		if (WARN_ON(ret < 0))
 			break;
 	}
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 2/3] driver: net: ethernet: cpsw: make cpts as pointer
  2013-02-11 19:52 ` Mugunthan V N
  (?)
@ 2013-02-11 19:52   ` Mugunthan V N
  -1 siblings, 0 replies; 48+ messages in thread
From: Mugunthan V N @ 2013-02-11 19:52 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-arm-kernel, linux-omap, Mugunthan V N

As CPTS is common module for both EMAC in Dual EMAC mode so making cpts as
pointer.

Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
---
 drivers/net/ethernet/ti/cpsw.c |   36 +++++++++++++++++++++---------------
 1 file changed, 21 insertions(+), 15 deletions(-)

diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 8ac60c7..4b964bb 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -319,7 +319,7 @@ struct cpsw_priv {
 	/* snapshot of IRQ numbers */
 	u32 irqs_table[4];
 	u32 num_irqs;
-	struct cpts cpts;
+	struct cpts *cpts;
 };
 
 #define napi_to_priv(napi)	container_of(napi, struct cpsw_priv, napi)
@@ -383,7 +383,7 @@ void cpsw_tx_handler(void *token, int len, int status)
 	 */
 	if (unlikely(netif_queue_stopped(ndev)))
 		netif_start_queue(ndev);
-	cpts_tx_timestamp(&priv->cpts, skb);
+	cpts_tx_timestamp(priv->cpts, skb);
 	priv->stats.tx_packets++;
 	priv->stats.tx_bytes += len;
 	dev_kfree_skb_any(skb);
@@ -404,7 +404,7 @@ void cpsw_rx_handler(void *token, int len, int status)
 	}
 	if (likely(status >= 0)) {
 		skb_put(skb, len);
-		cpts_rx_timestamp(&priv->cpts, skb);
+		cpts_rx_timestamp(priv->cpts, skb);
 		skb->protocol = eth_type_trans(skb, ndev);
 		netif_receive_skb(skb);
 		priv->stats.rx_bytes += len;
@@ -760,7 +760,8 @@ static netdev_tx_t cpsw_ndo_start_xmit(struct sk_buff *skb,
 		return NETDEV_TX_OK;
 	}
 
-	if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP && priv->cpts.tx_enable)
+	if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP &&
+				priv->cpts->tx_enable)
 		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
 
 	skb_tx_timestamp(skb);
@@ -815,7 +816,7 @@ static void cpsw_hwtstamp_v1(struct cpsw_priv *priv)
 	struct cpsw_slave *slave = &priv->slaves[priv->data.cpts_active_slave];
 	u32 ts_en, seq_id;
 
-	if (!priv->cpts.tx_enable && !priv->cpts.rx_enable) {
+	if (!priv->cpts->tx_enable && !priv->cpts->rx_enable) {
 		slave_write(slave, 0, CPSW1_TS_CTL);
 		return;
 	}
@@ -823,10 +824,10 @@ static void cpsw_hwtstamp_v1(struct cpsw_priv *priv)
 	seq_id = (30 << CPSW_V1_SEQ_ID_OFS_SHIFT) | ETH_P_1588;
 	ts_en = EVENT_MSG_BITS << CPSW_V1_MSG_TYPE_OFS;
 
-	if (priv->cpts.tx_enable)
+	if (priv->cpts->tx_enable)
 		ts_en |= CPSW_V1_TS_TX_EN;
 
-	if (priv->cpts.rx_enable)
+	if (priv->cpts->rx_enable)
 		ts_en |= CPSW_V1_TS_RX_EN;
 
 	slave_write(slave, ts_en, CPSW1_TS_CTL);
@@ -841,10 +842,10 @@ static void cpsw_hwtstamp_v2(struct cpsw_priv *priv)
 	ctrl = slave_read(slave, CPSW2_CONTROL);
 	ctrl &= ~CTRL_ALL_TS_MASK;
 
-	if (priv->cpts.tx_enable)
+	if (priv->cpts->tx_enable)
 		ctrl |= CTRL_TX_TS_BITS;
 
-	if (priv->cpts.rx_enable)
+	if (priv->cpts->rx_enable)
 		ctrl |= CTRL_RX_TS_BITS;
 
 	mtype = (30 << TS_SEQ_ID_OFFSET_SHIFT) | EVENT_MSG_BITS;
@@ -857,7 +858,7 @@ static void cpsw_hwtstamp_v2(struct cpsw_priv *priv)
 static int cpsw_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
 {
 	struct cpsw_priv *priv = netdev_priv(dev);
-	struct cpts *cpts = &priv->cpts;
+	struct cpts *cpts = priv->cpts;
 	struct hwtstamp_config cfg;
 
 	if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
@@ -1086,7 +1087,7 @@ static int cpsw_get_ts_info(struct net_device *ndev,
 		SOF_TIMESTAMPING_RX_SOFTWARE |
 		SOF_TIMESTAMPING_SOFTWARE |
 		SOF_TIMESTAMPING_RAW_HARDWARE;
-	info->phc_index = priv->cpts.phc_index;
+	info->phc_index = priv->cpts->phc_index;
 	info->tx_types =
 		(1 << HWTSTAMP_TX_OFF) |
 		(1 << HWTSTAMP_TX_ON);
@@ -1272,6 +1273,11 @@ static int cpsw_probe(struct platform_device *pdev)
 	priv->dev  = &ndev->dev;
 	priv->msg_enable = netif_msg_init(debug_level, CPSW_DEBUG);
 	priv->rx_packet_max = max(rx_packet_max, 128);
+	priv->cpts = devm_kzalloc(&pdev->dev, sizeof(struct cpts), GFP_KERNEL);
+	if (!ndev) {
+		pr_err("error allocating cpts\n");
+		goto clean_ndev_ret;
+	}
 
 	/*
 	 * This may be required here for child devices.
@@ -1358,7 +1364,7 @@ static int cpsw_probe(struct platform_device *pdev)
 	switch (priv->version) {
 	case CPSW_VERSION_1:
 		priv->host_port_regs = ss_regs + CPSW1_HOST_PORT_OFFSET;
-		priv->cpts.reg       = ss_regs + CPSW1_CPTS_OFFSET;
+		priv->cpts->reg       = ss_regs + CPSW1_CPTS_OFFSET;
 		dma_params.dmaregs   = ss_regs + CPSW1_CPDMA_OFFSET;
 		dma_params.txhdp     = ss_regs + CPSW1_STATERAM_OFFSET;
 		ale_params.ale_regs  = ss_regs + CPSW1_ALE_OFFSET;
@@ -1369,7 +1375,7 @@ static int cpsw_probe(struct platform_device *pdev)
 		break;
 	case CPSW_VERSION_2:
 		priv->host_port_regs = ss_regs + CPSW2_HOST_PORT_OFFSET;
-		priv->cpts.reg       = ss_regs + CPSW2_CPTS_OFFSET;
+		priv->cpts->reg       = ss_regs + CPSW2_CPTS_OFFSET;
 		dma_params.dmaregs   = ss_regs + CPSW2_CPDMA_OFFSET;
 		dma_params.txhdp     = ss_regs + CPSW2_STATERAM_OFFSET;
 		ale_params.ale_regs  = ss_regs + CPSW2_ALE_OFFSET;
@@ -1471,7 +1477,7 @@ static int cpsw_probe(struct platform_device *pdev)
 		goto clean_irq_ret;
 	}
 
-	if (cpts_register(&pdev->dev, &priv->cpts,
+	if (cpts_register(&pdev->dev, priv->cpts,
 			  data->cpts_clock_mult, data->cpts_clock_shift))
 		dev_err(priv->dev, "error registering cpts device\n");
 
@@ -1516,7 +1522,7 @@ static int cpsw_remove(struct platform_device *pdev)
 	pr_info("removing device");
 	platform_set_drvdata(pdev, NULL);
 
-	cpts_unregister(&priv->cpts);
+	cpts_unregister(priv->cpts);
 	free_irq(ndev->irq, priv);
 	cpsw_ale_destroy(priv->ale);
 	cpdma_chan_destroy(priv->txch);
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 2/3] driver: net: ethernet: cpsw: make cpts as pointer
@ 2013-02-11 19:52   ` Mugunthan V N
  0 siblings, 0 replies; 48+ messages in thread
From: Mugunthan V N @ 2013-02-11 19:52 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-arm-kernel, linux-omap, Mugunthan V N

As CPTS is common module for both EMAC in Dual EMAC mode so making cpts as
pointer.

Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
---
 drivers/net/ethernet/ti/cpsw.c |   36 +++++++++++++++++++++---------------
 1 file changed, 21 insertions(+), 15 deletions(-)

diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 8ac60c7..4b964bb 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -319,7 +319,7 @@ struct cpsw_priv {
 	/* snapshot of IRQ numbers */
 	u32 irqs_table[4];
 	u32 num_irqs;
-	struct cpts cpts;
+	struct cpts *cpts;
 };
 
 #define napi_to_priv(napi)	container_of(napi, struct cpsw_priv, napi)
@@ -383,7 +383,7 @@ void cpsw_tx_handler(void *token, int len, int status)
 	 */
 	if (unlikely(netif_queue_stopped(ndev)))
 		netif_start_queue(ndev);
-	cpts_tx_timestamp(&priv->cpts, skb);
+	cpts_tx_timestamp(priv->cpts, skb);
 	priv->stats.tx_packets++;
 	priv->stats.tx_bytes += len;
 	dev_kfree_skb_any(skb);
@@ -404,7 +404,7 @@ void cpsw_rx_handler(void *token, int len, int status)
 	}
 	if (likely(status >= 0)) {
 		skb_put(skb, len);
-		cpts_rx_timestamp(&priv->cpts, skb);
+		cpts_rx_timestamp(priv->cpts, skb);
 		skb->protocol = eth_type_trans(skb, ndev);
 		netif_receive_skb(skb);
 		priv->stats.rx_bytes += len;
@@ -760,7 +760,8 @@ static netdev_tx_t cpsw_ndo_start_xmit(struct sk_buff *skb,
 		return NETDEV_TX_OK;
 	}
 
-	if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP && priv->cpts.tx_enable)
+	if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP &&
+				priv->cpts->tx_enable)
 		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
 
 	skb_tx_timestamp(skb);
@@ -815,7 +816,7 @@ static void cpsw_hwtstamp_v1(struct cpsw_priv *priv)
 	struct cpsw_slave *slave = &priv->slaves[priv->data.cpts_active_slave];
 	u32 ts_en, seq_id;
 
-	if (!priv->cpts.tx_enable && !priv->cpts.rx_enable) {
+	if (!priv->cpts->tx_enable && !priv->cpts->rx_enable) {
 		slave_write(slave, 0, CPSW1_TS_CTL);
 		return;
 	}
@@ -823,10 +824,10 @@ static void cpsw_hwtstamp_v1(struct cpsw_priv *priv)
 	seq_id = (30 << CPSW_V1_SEQ_ID_OFS_SHIFT) | ETH_P_1588;
 	ts_en = EVENT_MSG_BITS << CPSW_V1_MSG_TYPE_OFS;
 
-	if (priv->cpts.tx_enable)
+	if (priv->cpts->tx_enable)
 		ts_en |= CPSW_V1_TS_TX_EN;
 
-	if (priv->cpts.rx_enable)
+	if (priv->cpts->rx_enable)
 		ts_en |= CPSW_V1_TS_RX_EN;
 
 	slave_write(slave, ts_en, CPSW1_TS_CTL);
@@ -841,10 +842,10 @@ static void cpsw_hwtstamp_v2(struct cpsw_priv *priv)
 	ctrl = slave_read(slave, CPSW2_CONTROL);
 	ctrl &= ~CTRL_ALL_TS_MASK;
 
-	if (priv->cpts.tx_enable)
+	if (priv->cpts->tx_enable)
 		ctrl |= CTRL_TX_TS_BITS;
 
-	if (priv->cpts.rx_enable)
+	if (priv->cpts->rx_enable)
 		ctrl |= CTRL_RX_TS_BITS;
 
 	mtype = (30 << TS_SEQ_ID_OFFSET_SHIFT) | EVENT_MSG_BITS;
@@ -857,7 +858,7 @@ static void cpsw_hwtstamp_v2(struct cpsw_priv *priv)
 static int cpsw_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
 {
 	struct cpsw_priv *priv = netdev_priv(dev);
-	struct cpts *cpts = &priv->cpts;
+	struct cpts *cpts = priv->cpts;
 	struct hwtstamp_config cfg;
 
 	if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
@@ -1086,7 +1087,7 @@ static int cpsw_get_ts_info(struct net_device *ndev,
 		SOF_TIMESTAMPING_RX_SOFTWARE |
 		SOF_TIMESTAMPING_SOFTWARE |
 		SOF_TIMESTAMPING_RAW_HARDWARE;
-	info->phc_index = priv->cpts.phc_index;
+	info->phc_index = priv->cpts->phc_index;
 	info->tx_types =
 		(1 << HWTSTAMP_TX_OFF) |
 		(1 << HWTSTAMP_TX_ON);
@@ -1272,6 +1273,11 @@ static int cpsw_probe(struct platform_device *pdev)
 	priv->dev  = &ndev->dev;
 	priv->msg_enable = netif_msg_init(debug_level, CPSW_DEBUG);
 	priv->rx_packet_max = max(rx_packet_max, 128);
+	priv->cpts = devm_kzalloc(&pdev->dev, sizeof(struct cpts), GFP_KERNEL);
+	if (!ndev) {
+		pr_err("error allocating cpts\n");
+		goto clean_ndev_ret;
+	}
 
 	/*
 	 * This may be required here for child devices.
@@ -1358,7 +1364,7 @@ static int cpsw_probe(struct platform_device *pdev)
 	switch (priv->version) {
 	case CPSW_VERSION_1:
 		priv->host_port_regs = ss_regs + CPSW1_HOST_PORT_OFFSET;
-		priv->cpts.reg       = ss_regs + CPSW1_CPTS_OFFSET;
+		priv->cpts->reg       = ss_regs + CPSW1_CPTS_OFFSET;
 		dma_params.dmaregs   = ss_regs + CPSW1_CPDMA_OFFSET;
 		dma_params.txhdp     = ss_regs + CPSW1_STATERAM_OFFSET;
 		ale_params.ale_regs  = ss_regs + CPSW1_ALE_OFFSET;
@@ -1369,7 +1375,7 @@ static int cpsw_probe(struct platform_device *pdev)
 		break;
 	case CPSW_VERSION_2:
 		priv->host_port_regs = ss_regs + CPSW2_HOST_PORT_OFFSET;
-		priv->cpts.reg       = ss_regs + CPSW2_CPTS_OFFSET;
+		priv->cpts->reg       = ss_regs + CPSW2_CPTS_OFFSET;
 		dma_params.dmaregs   = ss_regs + CPSW2_CPDMA_OFFSET;
 		dma_params.txhdp     = ss_regs + CPSW2_STATERAM_OFFSET;
 		ale_params.ale_regs  = ss_regs + CPSW2_ALE_OFFSET;
@@ -1471,7 +1477,7 @@ static int cpsw_probe(struct platform_device *pdev)
 		goto clean_irq_ret;
 	}
 
-	if (cpts_register(&pdev->dev, &priv->cpts,
+	if (cpts_register(&pdev->dev, priv->cpts,
 			  data->cpts_clock_mult, data->cpts_clock_shift))
 		dev_err(priv->dev, "error registering cpts device\n");
 
@@ -1516,7 +1522,7 @@ static int cpsw_remove(struct platform_device *pdev)
 	pr_info("removing device");
 	platform_set_drvdata(pdev, NULL);
 
-	cpts_unregister(&priv->cpts);
+	cpts_unregister(priv->cpts);
 	free_irq(ndev->irq, priv);
 	cpsw_ale_destroy(priv->ale);
 	cpdma_chan_destroy(priv->txch);
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 2/3] driver: net: ethernet: cpsw: make cpts as pointer
@ 2013-02-11 19:52   ` Mugunthan V N
  0 siblings, 0 replies; 48+ messages in thread
From: Mugunthan V N @ 2013-02-11 19:52 UTC (permalink / raw)
  To: linux-arm-kernel

As CPTS is common module for both EMAC in Dual EMAC mode so making cpts as
pointer.

Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
---
 drivers/net/ethernet/ti/cpsw.c |   36 +++++++++++++++++++++---------------
 1 file changed, 21 insertions(+), 15 deletions(-)

diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 8ac60c7..4b964bb 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -319,7 +319,7 @@ struct cpsw_priv {
 	/* snapshot of IRQ numbers */
 	u32 irqs_table[4];
 	u32 num_irqs;
-	struct cpts cpts;
+	struct cpts *cpts;
 };
 
 #define napi_to_priv(napi)	container_of(napi, struct cpsw_priv, napi)
@@ -383,7 +383,7 @@ void cpsw_tx_handler(void *token, int len, int status)
 	 */
 	if (unlikely(netif_queue_stopped(ndev)))
 		netif_start_queue(ndev);
-	cpts_tx_timestamp(&priv->cpts, skb);
+	cpts_tx_timestamp(priv->cpts, skb);
 	priv->stats.tx_packets++;
 	priv->stats.tx_bytes += len;
 	dev_kfree_skb_any(skb);
@@ -404,7 +404,7 @@ void cpsw_rx_handler(void *token, int len, int status)
 	}
 	if (likely(status >= 0)) {
 		skb_put(skb, len);
-		cpts_rx_timestamp(&priv->cpts, skb);
+		cpts_rx_timestamp(priv->cpts, skb);
 		skb->protocol = eth_type_trans(skb, ndev);
 		netif_receive_skb(skb);
 		priv->stats.rx_bytes += len;
@@ -760,7 +760,8 @@ static netdev_tx_t cpsw_ndo_start_xmit(struct sk_buff *skb,
 		return NETDEV_TX_OK;
 	}
 
-	if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP && priv->cpts.tx_enable)
+	if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP &&
+				priv->cpts->tx_enable)
 		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
 
 	skb_tx_timestamp(skb);
@@ -815,7 +816,7 @@ static void cpsw_hwtstamp_v1(struct cpsw_priv *priv)
 	struct cpsw_slave *slave = &priv->slaves[priv->data.cpts_active_slave];
 	u32 ts_en, seq_id;
 
-	if (!priv->cpts.tx_enable && !priv->cpts.rx_enable) {
+	if (!priv->cpts->tx_enable && !priv->cpts->rx_enable) {
 		slave_write(slave, 0, CPSW1_TS_CTL);
 		return;
 	}
@@ -823,10 +824,10 @@ static void cpsw_hwtstamp_v1(struct cpsw_priv *priv)
 	seq_id = (30 << CPSW_V1_SEQ_ID_OFS_SHIFT) | ETH_P_1588;
 	ts_en = EVENT_MSG_BITS << CPSW_V1_MSG_TYPE_OFS;
 
-	if (priv->cpts.tx_enable)
+	if (priv->cpts->tx_enable)
 		ts_en |= CPSW_V1_TS_TX_EN;
 
-	if (priv->cpts.rx_enable)
+	if (priv->cpts->rx_enable)
 		ts_en |= CPSW_V1_TS_RX_EN;
 
 	slave_write(slave, ts_en, CPSW1_TS_CTL);
@@ -841,10 +842,10 @@ static void cpsw_hwtstamp_v2(struct cpsw_priv *priv)
 	ctrl = slave_read(slave, CPSW2_CONTROL);
 	ctrl &= ~CTRL_ALL_TS_MASK;
 
-	if (priv->cpts.tx_enable)
+	if (priv->cpts->tx_enable)
 		ctrl |= CTRL_TX_TS_BITS;
 
-	if (priv->cpts.rx_enable)
+	if (priv->cpts->rx_enable)
 		ctrl |= CTRL_RX_TS_BITS;
 
 	mtype = (30 << TS_SEQ_ID_OFFSET_SHIFT) | EVENT_MSG_BITS;
@@ -857,7 +858,7 @@ static void cpsw_hwtstamp_v2(struct cpsw_priv *priv)
 static int cpsw_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
 {
 	struct cpsw_priv *priv = netdev_priv(dev);
-	struct cpts *cpts = &priv->cpts;
+	struct cpts *cpts = priv->cpts;
 	struct hwtstamp_config cfg;
 
 	if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
@@ -1086,7 +1087,7 @@ static int cpsw_get_ts_info(struct net_device *ndev,
 		SOF_TIMESTAMPING_RX_SOFTWARE |
 		SOF_TIMESTAMPING_SOFTWARE |
 		SOF_TIMESTAMPING_RAW_HARDWARE;
-	info->phc_index = priv->cpts.phc_index;
+	info->phc_index = priv->cpts->phc_index;
 	info->tx_types =
 		(1 << HWTSTAMP_TX_OFF) |
 		(1 << HWTSTAMP_TX_ON);
@@ -1272,6 +1273,11 @@ static int cpsw_probe(struct platform_device *pdev)
 	priv->dev  = &ndev->dev;
 	priv->msg_enable = netif_msg_init(debug_level, CPSW_DEBUG);
 	priv->rx_packet_max = max(rx_packet_max, 128);
+	priv->cpts = devm_kzalloc(&pdev->dev, sizeof(struct cpts), GFP_KERNEL);
+	if (!ndev) {
+		pr_err("error allocating cpts\n");
+		goto clean_ndev_ret;
+	}
 
 	/*
 	 * This may be required here for child devices.
@@ -1358,7 +1364,7 @@ static int cpsw_probe(struct platform_device *pdev)
 	switch (priv->version) {
 	case CPSW_VERSION_1:
 		priv->host_port_regs = ss_regs + CPSW1_HOST_PORT_OFFSET;
-		priv->cpts.reg       = ss_regs + CPSW1_CPTS_OFFSET;
+		priv->cpts->reg       = ss_regs + CPSW1_CPTS_OFFSET;
 		dma_params.dmaregs   = ss_regs + CPSW1_CPDMA_OFFSET;
 		dma_params.txhdp     = ss_regs + CPSW1_STATERAM_OFFSET;
 		ale_params.ale_regs  = ss_regs + CPSW1_ALE_OFFSET;
@@ -1369,7 +1375,7 @@ static int cpsw_probe(struct platform_device *pdev)
 		break;
 	case CPSW_VERSION_2:
 		priv->host_port_regs = ss_regs + CPSW2_HOST_PORT_OFFSET;
-		priv->cpts.reg       = ss_regs + CPSW2_CPTS_OFFSET;
+		priv->cpts->reg       = ss_regs + CPSW2_CPTS_OFFSET;
 		dma_params.dmaregs   = ss_regs + CPSW2_CPDMA_OFFSET;
 		dma_params.txhdp     = ss_regs + CPSW2_STATERAM_OFFSET;
 		ale_params.ale_regs  = ss_regs + CPSW2_ALE_OFFSET;
@@ -1471,7 +1477,7 @@ static int cpsw_probe(struct platform_device *pdev)
 		goto clean_irq_ret;
 	}
 
-	if (cpts_register(&pdev->dev, &priv->cpts,
+	if (cpts_register(&pdev->dev, priv->cpts,
 			  data->cpts_clock_mult, data->cpts_clock_shift))
 		dev_err(priv->dev, "error registering cpts device\n");
 
@@ -1516,7 +1522,7 @@ static int cpsw_remove(struct platform_device *pdev)
 	pr_info("removing device");
 	platform_set_drvdata(pdev, NULL);
 
-	cpts_unregister(&priv->cpts);
+	cpts_unregister(priv->cpts);
 	free_irq(ndev->irq, priv);
 	cpsw_ale_destroy(priv->ale);
 	cpdma_chan_destroy(priv->txch);
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 3/3] driver: net: ethernet: cpsw: dual emac interface implementation
  2013-02-11 19:52 ` Mugunthan V N
  (?)
@ 2013-02-11 19:52   ` Mugunthan V N
  -1 siblings, 0 replies; 48+ messages in thread
From: Mugunthan V N @ 2013-02-11 19:52 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-arm-kernel, linux-omap, Mugunthan V N

The CPSW switch can act as Dual EMAC by segregating the switch ports
using VLAN and port VLAN as per the TRM description in
14.3.2.10.2 Dual Mac Mode

Following CPSW components will be common for both the interfaces.
* Interrupt source is common for both eth interfaces
* Interrupt pacing is common for both interfaces
* Hardware statistics is common for all the ports
* CPDMA is common for both eth interface
* CPTS is common for both the interface and it should not be enabled on
  both the interface as timestamping information doesn't contain port
  information.

Constrains
* Reserved VID of One port should not be used in other interface which will
  enable switching functionality
* Same VID must not be used in both the interface which will enable switching
  functionality

Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
---
 Documentation/devicetree/bindings/net/cpsw.txt |    2 +
 drivers/net/ethernet/ti/cpsw.c                 |  335 ++++++++++++++++++++----
 include/linux/platform_data/cpsw.h             |    3 +
 3 files changed, 288 insertions(+), 52 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt
index 6ddd028..ecfdf75 100644
--- a/Documentation/devicetree/bindings/net/cpsw.txt
+++ b/Documentation/devicetree/bindings/net/cpsw.txt
@@ -24,6 +24,8 @@ Required properties:
 Optional properties:
 - ti,hwmods		: Must be "cpgmac0"
 - no_bd_ram		: Must be 0 or 1
+- dual_emac		: Specifies Switch to act as Dual EMAC
+- dual_emac_res_vlan	: Specifies VID to be used to segregate the ports
 
 Note: "ti,hwmods" field is used to fetch the base address and irq
 resources from TI, omap hwmod data base during device registration.
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 4b964bb..4ceed6e 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -122,6 +122,10 @@ do {								\
 #define CPSW_VLAN_AWARE		BIT(1)
 #define CPSW_ALE_VLAN_AWARE	1
 
+#define CPSW_FIFO_NORMAL_MODE		(0 << 15)
+#define CPSW_FIFO_DUAL_MAC_MODE		(1 << 15)
+#define CPSW_FIFO_RATE_LIMIT_MODE	(2 << 15)
+
 #define cpsw_enable_irq(priv)	\
 	do {			\
 		u32 i;		\
@@ -254,7 +258,7 @@ struct cpsw_ss_regs {
 struct cpsw_host_regs {
 	u32	max_blks;
 	u32	blk_cnt;
-	u32	flow_thresh;
+	u32	tx_in_ctl;
 	u32	port_vlan;
 	u32	tx_pri_map;
 	u32	cpdma_tx_pri_map;
@@ -281,6 +285,9 @@ struct cpsw_slave {
 	u32				mac_control;
 	struct cpsw_slave_data		*data;
 	struct phy_device		*phy;
+	struct net_device		*ndev;
+	u32				port_vlan;
+	u32				open_stat;
 };
 
 static inline u32 slave_read(struct cpsw_slave *slave, u32 offset)
@@ -320,15 +327,63 @@ struct cpsw_priv {
 	u32 irqs_table[4];
 	u32 num_irqs;
 	struct cpts *cpts;
+	u32 emac_port;
 };
 
 #define napi_to_priv(napi)	container_of(napi, struct cpsw_priv, napi)
-#define for_each_slave(priv, func, arg...)			\
-	do {							\
-		int idx;					\
-		for (idx = 0; idx < (priv)->data.slaves; idx++)	\
-			(func)((priv)->slaves + idx, ##arg);	\
+#define for_each_slave(priv, func, arg...)				\
+	do {								\
+		int idx;						\
+		if (priv->data.dual_emac)				\
+			(func)((priv)->slaves + priv->emac_port, ##arg);\
+		else							\
+			for (idx = 0; idx < (priv)->data.slaves; idx++)	\
+				(func)((priv)->slaves + idx, ##arg);	\
+	} while (0)
+#define cpsw_get_slave_ndev(priv, __slave_no__)				\
+	(priv->slaves[__slave_no__].ndev)
+#define cpsw_get_slave_priv(priv, __slave_no__)				\
+	((priv->slaves[__slave_no__].ndev) ?				\
+		netdev_priv(priv->slaves[__slave_no__].ndev) : NULL)	\
+
+#define cpsw_dual_emac_src_port_detect(status, priv, ndev, skb)		\
+	do {								\
+		if (!priv->data.dual_emac)				\
+			break;						\
+		if (CPDMA_RX_SOURCE_PORT(status) == 1) {		\
+			ndev = cpsw_get_slave_ndev(priv, 0);		\
+			priv = netdev_priv(ndev);			\
+			skb->dev = ndev;				\
+		} else if (CPDMA_RX_SOURCE_PORT(status) == 2) {		\
+			ndev = cpsw_get_slave_ndev(priv, 1);		\
+			priv = netdev_priv(ndev);			\
+			skb->dev = ndev;				\
+		}							\
 	} while (0)
+#define cpsw_add_mcast(priv, addr)					\
+	do {								\
+		if (priv->data.dual_emac) {				\
+			struct cpsw_slave *slave = priv->slaves +	\
+						priv->emac_port;	\
+			int slave_port = cpsw_get_slave_port(priv,	\
+						slave->slave_num);	\
+			cpsw_ale_add_mcast(priv->ale, addr,		\
+				1 << slave_port | 1 << priv->host_port,	\
+				ALE_VLAN, slave->port_vlan, 0);		\
+		} else {						\
+			cpsw_ale_add_mcast(priv->ale, addr,		\
+				ALE_ALL_PORTS << priv->host_port,	\
+				0, 0, 0);				\
+		}							\
+	} while (0)
+
+static inline int cpsw_get_slave_port(struct cpsw_priv *priv, u32 slave_num)
+{
+	if (priv->host_port == 0)
+		return slave_num + 1;
+	else
+		return slave_num;
+}
 
 static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
 {
@@ -348,8 +403,7 @@ static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
 
 		/* program multicast address list into ALE register */
 		netdev_for_each_mc_addr(ha, ndev) {
-			cpsw_ale_add_mcast(priv->ale, (u8 *)ha->addr,
-				ALE_ALL_PORTS << priv->host_port, 0, 0, 0);
+			cpsw_add_mcast(priv, (u8 *)ha->addr);
 		}
 	}
 }
@@ -396,6 +450,8 @@ void cpsw_rx_handler(void *token, int len, int status)
 	struct cpsw_priv	*priv = netdev_priv(ndev);
 	int			ret = 0;
 
+	cpsw_dual_emac_src_port_detect(status, priv, ndev, skb);
+
 	/* free and bail if we are shutting down */
 	if (unlikely(!netif_running(ndev)) ||
 			unlikely(!netif_carrier_ok(ndev))) {
@@ -437,18 +493,17 @@ static irqreturn_t cpsw_interrupt(int irq, void *dev_id)
 		cpsw_intr_disable(priv);
 		cpsw_disable_irq(priv);
 		napi_schedule(&priv->napi);
+	} else {
+		priv = cpsw_get_slave_priv(priv, 1);
+		if (likely(priv) && likely(netif_running(priv->ndev))) {
+			cpsw_intr_disable(priv);
+			cpsw_disable_irq(priv);
+			napi_schedule(&priv->napi);
+		}
 	}
 	return IRQ_HANDLED;
 }
 
-static inline int cpsw_get_slave_port(struct cpsw_priv *priv, u32 slave_num)
-{
-	if (priv->host_port == 0)
-		return slave_num + 1;
-	else
-		return slave_num;
-}
-
 static int cpsw_poll(struct napi_struct *napi, int budget)
 {
 	struct cpsw_priv	*priv = napi_to_priv(napi);
@@ -566,6 +621,54 @@ static inline int __show_stat(char *buf, int maxlen, const char *name, u32 val)
 				leader + strlen(name), val);
 }
 
+static int cpsw_common_res_usage_state(struct cpsw_priv *priv)
+{
+	u32 i;
+	u32 usage_count = 0;
+
+	if (!priv->data.dual_emac)
+		return 0;
+
+	for (i = 0; i < priv->data.slaves; i++)
+		if (priv->slaves[i].open_stat)
+			usage_count++;
+
+	return usage_count;
+}
+
+static inline int cpsw_tx_packet_submit(struct net_device *ndev,
+			struct cpsw_priv *priv, struct sk_buff *skb)
+{
+	if (!priv->data.dual_emac)
+		return cpdma_chan_submit(priv->txch, skb, skb->data,
+				  skb->len, 0, GFP_KERNEL);
+
+	if (ndev == cpsw_get_slave_ndev(priv, 0))
+		return cpdma_chan_submit(priv->txch, skb, skb->data,
+				  skb->len, 1, GFP_KERNEL);
+	else
+		return cpdma_chan_submit(priv->txch, skb, skb->data,
+				  skb->len, 2, GFP_KERNEL);
+}
+
+static inline void cpsw_add_dual_emac_def_ale_entries(
+		struct cpsw_priv *priv, struct cpsw_slave *slave,
+		u32 slave_port)
+{
+	u32 port_mask = 1 << slave_port | 1 << priv->host_port;
+
+	if (priv->version == CPSW_VERSION_1)
+		slave_write(slave, slave->port_vlan, CPSW1_PORT_VLAN);
+	else
+		slave_write(slave, slave->port_vlan, CPSW2_PORT_VLAN);
+	cpsw_ale_add_vlan(priv->ale, slave->port_vlan, port_mask,
+			  port_mask, port_mask, 0);
+	cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
+			   port_mask, ALE_VLAN, slave->port_vlan, 0);
+	cpsw_ale_add_ucast(priv->ale, priv->mac_addr,
+		priv->host_port, ALE_VLAN, slave->port_vlan);
+}
+
 static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
 {
 	char name[32];
@@ -595,8 +698,11 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
 
 	slave_port = cpsw_get_slave_port(priv, slave->slave_num);
 
-	cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
-			   1 << slave_port, 0, 0, ALE_MCAST_FWD_2);
+	if (priv->data.dual_emac)
+		cpsw_add_dual_emac_def_ale_entries(priv, slave, slave_port);
+	else
+		cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
+				   1 << slave_port, 0, 0, ALE_MCAST_FWD_2);
 
 	slave->phy = phy_connect(priv->ndev, slave->data->phy_id,
 				 &cpsw_adjust_link, slave->data->phy_if);
@@ -634,6 +740,7 @@ static inline void cpsw_add_default_vlan(struct cpsw_priv *priv)
 static void cpsw_init_host_port(struct cpsw_priv *priv)
 {
 	u32 control_reg;
+	u32 fifo_mode;
 
 	/* soft reset the controller and initialize ale */
 	soft_reset("cpsw", &priv->regs->soft_reset);
@@ -645,6 +752,9 @@ static void cpsw_init_host_port(struct cpsw_priv *priv)
 	control_reg = readl(&priv->regs->control);
 	control_reg |= CPSW_VLAN_AWARE;
 	writel(control_reg, &priv->regs->control);
+	fifo_mode = (priv->data.dual_emac) ? CPSW_FIFO_DUAL_MAC_MODE :
+		     CPSW_FIFO_NORMAL_MODE;
+	writel(fifo_mode, &priv->host_port_regs->tx_in_ctl);
 
 	/* setup host port priority mapping */
 	__raw_writel(CPDMA_TX_PRIORITY_MAP,
@@ -654,9 +764,12 @@ static void cpsw_init_host_port(struct cpsw_priv *priv)
 	cpsw_ale_control_set(priv->ale, priv->host_port,
 			     ALE_PORT_STATE, ALE_PORT_STATE_FORWARD);
 
-	cpsw_ale_add_ucast(priv->ale, priv->mac_addr, priv->host_port, 0, 0);
-	cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
-			   1 << priv->host_port, 0, 0, ALE_MCAST_FWD_2);
+	if (!priv->data.dual_emac) {
+		cpsw_ale_add_ucast(priv->ale, priv->mac_addr, priv->host_port,
+				   0, 0);
+		cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
+				   1 << priv->host_port, 0, 0, ALE_MCAST_FWD_2);
+	}
 }
 
 static int cpsw_ndo_open(struct net_device *ndev)
@@ -665,7 +778,8 @@ static int cpsw_ndo_open(struct net_device *ndev)
 	int i, ret;
 	u32 reg;
 
-	cpsw_intr_disable(priv);
+	if (!cpsw_common_res_usage_state(priv))
+		cpsw_intr_disable(priv);
 	netif_carrier_off(ndev);
 
 	pm_runtime_get_sync(&priv->pdev->dev);
@@ -677,46 +791,54 @@ static int cpsw_ndo_open(struct net_device *ndev)
 		 CPSW_RTL_VERSION(reg));
 
 	/* initialize host and slave ports */
-	cpsw_init_host_port(priv);
+	if (!cpsw_common_res_usage_state(priv))
+		cpsw_init_host_port(priv);
 	for_each_slave(priv, cpsw_slave_open, priv);
 
 	/* Add default VLAN */
-	cpsw_add_default_vlan(priv);
+	if (!priv->data.dual_emac)
+		cpsw_add_default_vlan(priv);
 
-	/* setup tx dma to fixed prio and zero offset */
-	cpdma_control_set(priv->dma, CPDMA_TX_PRIO_FIXED, 1);
-	cpdma_control_set(priv->dma, CPDMA_RX_BUFFER_OFFSET, 0);
+	if (!cpsw_common_res_usage_state(priv)) {
+		/* setup tx dma to fixed prio and zero offset */
+		cpdma_control_set(priv->dma, CPDMA_TX_PRIO_FIXED, 1);
+		cpdma_control_set(priv->dma, CPDMA_RX_BUFFER_OFFSET, 0);
 
-	/* disable priority elevation and enable statistics on all ports */
-	__raw_writel(0, &priv->regs->ptype);
+		/* disable priority elevation */
+		__raw_writel(0, &priv->regs->ptype);
 
-	/* enable statistics collection only on the host port */
-	__raw_writel(0x7, &priv->regs->stat_port_en);
+		/* enable statistics collection only on all ports */
+		__raw_writel(0x7, &priv->regs->stat_port_en);
 
-	if (WARN_ON(!priv->data.rx_descs))
-		priv->data.rx_descs = 128;
+		if (WARN_ON(!priv->data.rx_descs))
+			priv->data.rx_descs = 128;
 
-	for (i = 0; i < priv->data.rx_descs; i++) {
-		struct sk_buff *skb;
+		for (i = 0; i < priv->data.rx_descs; i++) {
+			struct sk_buff *skb;
 
-		ret = -ENOMEM;
-		skb = netdev_alloc_skb_ip_align(priv->ndev,
-						priv->rx_packet_max);
-		if (!skb)
-			break;
-		ret = cpdma_chan_submit(priv->rxch, skb, skb->data,
+			ret = -ENOMEM;
+			skb = netdev_alloc_skb_ip_align(priv->ndev,
+							priv->rx_packet_max);
+			if (!skb)
+				break;
+			ret = cpdma_chan_submit(priv->rxch, skb, skb->data,
 					skb_tailroom(skb), 0, GFP_KERNEL);
-		if (WARN_ON(ret < 0))
-			break;
+			if (WARN_ON(ret < 0))
+				break;
+		}
+		/* continue even if we didn't manage to submit all
+		 * receive descs
+		 */
+		cpsw_info(priv, ifup, "submitted %d rx descriptors\n", i);
 	}
-	/* continue even if we didn't manage to submit all receive descs */
-	cpsw_info(priv, ifup, "submitted %d rx descriptors\n", i);
 
 	cpdma_ctlr_start(priv->dma);
 	cpsw_intr_enable(priv);
 	napi_enable(&priv->napi);
 	cpdma_ctlr_eoi(priv->dma);
 
+	if (priv->data.dual_emac)
+		priv->slaves[priv->emac_port].open_stat = true;
 	return 0;
 }
 
@@ -737,12 +859,17 @@ static int cpsw_ndo_stop(struct net_device *ndev)
 	netif_stop_queue(priv->ndev);
 	napi_disable(&priv->napi);
 	netif_carrier_off(priv->ndev);
-	cpsw_intr_disable(priv);
-	cpdma_ctlr_int_ctrl(priv->dma, false);
-	cpdma_ctlr_stop(priv->dma);
-	cpsw_ale_stop(priv->ale);
+
+	if (cpsw_common_res_usage_state(priv) <= 1) {
+		cpsw_intr_disable(priv);
+		cpdma_ctlr_int_ctrl(priv->dma, false);
+		cpdma_ctlr_stop(priv->dma);
+		cpsw_ale_stop(priv->ale);
+	}
 	for_each_slave(priv, cpsw_slave_stop, priv);
 	pm_runtime_put_sync(&priv->pdev->dev);
+	if (priv->data.dual_emac)
+		priv->slaves[priv->emac_port].open_stat = false;
 	return 0;
 }
 
@@ -766,8 +893,7 @@ static netdev_tx_t cpsw_ndo_start_xmit(struct sk_buff *skb,
 
 	skb_tx_timestamp(skb);
 
-	ret = cpdma_chan_submit(priv->txch, skb, skb->data,
-				skb->len, 0, GFP_KERNEL);
+	ret = cpsw_tx_packet_submit(ndev, priv, skb);
 	if (unlikely(ret != 0)) {
 		cpsw_err(priv, tx_err, "desc submit failed\n");
 		goto fail;
@@ -836,9 +962,14 @@ static void cpsw_hwtstamp_v1(struct cpsw_priv *priv)
 
 static void cpsw_hwtstamp_v2(struct cpsw_priv *priv)
 {
-	struct cpsw_slave *slave = &priv->slaves[priv->data.cpts_active_slave];
+	struct cpsw_slave *slave;
 	u32 ctrl, mtype;
 
+	if (priv->data.dual_emac)
+		slave = &priv->slaves[priv->emac_port];
+	else
+		slave = &priv->slaves[priv->data.cpts_active_slave];
+
 	ctrl = slave_read(slave, CPSW2_CONTROL);
 	ctrl &= ~CTRL_ALL_TS_MASK;
 
@@ -1124,6 +1255,7 @@ static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv,
 	slave->data	= data;
 	slave->regs	= regs + slave_reg_ofs;
 	slave->sliver	= regs + sliver_reg_ofs;
+	slave->port_vlan = data->dual_emac_res_vlan;
 }
 
 static int cpsw_probe_dt(struct cpsw_platform_data *data,
@@ -1204,6 +1336,9 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
 	}
 	data->mac_control = prop;
 
+	if (!of_property_read_u32(node, "dual_emac", &prop))
+		data->dual_emac = prop;
+
 	/*
 	 * Populate all the child nodes here...
 	 */
@@ -1237,6 +1372,18 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
 		if (mac_addr)
 			memcpy(slave_data->mac_addr, mac_addr, ETH_ALEN);
 
+		if (data->dual_emac) {
+			if (of_property_read_u32(node, "dual_emac_res_vlan",
+						 &prop)) {
+				pr_err("Missing dual_emac_res_vlan in DT.\n");
+				slave_data->dual_emac_res_vlan = i+1;
+				pr_err("Using %d as Reserved VLAN for %d slave\n",
+				       slave_data->dual_emac_res_vlan, i);
+			} else {
+				slave_data->dual_emac_res_vlan = prop;
+			}
+		}
+
 		i++;
 	}
 
@@ -1247,6 +1394,79 @@ error_ret:
 	return ret;
 }
 
+static int cpsw_probe_dual_emac(struct platform_device *pdev,
+				struct cpsw_priv *priv)
+{
+	struct cpsw_platform_data	*data = &priv->data;
+	struct net_device		*ndev;
+	struct cpsw_priv		*priv_sl2;
+	int ret = 0, i;
+
+	ndev = alloc_etherdev(sizeof(struct cpsw_priv));
+	if (!ndev) {
+		pr_err("cpsw: error allocating net_device\n");
+		return -ENOMEM;
+	}
+
+	priv_sl2 = netdev_priv(ndev);
+	spin_lock_init(&priv_sl2->lock);
+	priv_sl2->data = *data;
+	priv_sl2->pdev = pdev;
+	priv_sl2->ndev = ndev;
+	priv_sl2->dev  = &ndev->dev;
+	priv_sl2->msg_enable = netif_msg_init(debug_level, CPSW_DEBUG);
+	priv_sl2->rx_packet_max = max(rx_packet_max, 128);
+
+	if (is_valid_ether_addr(data->slave_data[1].mac_addr)) {
+		memcpy(priv_sl2->mac_addr, data->slave_data[1].mac_addr,
+			ETH_ALEN);
+		pr_info("cpsw: Detected MACID = %pM\n", priv_sl2->mac_addr);
+	} else {
+		random_ether_addr(priv_sl2->mac_addr);
+		pr_info("cpsw: Random MACID = %pM\n", priv_sl2->mac_addr);
+	}
+	memcpy(ndev->dev_addr, priv_sl2->mac_addr, ETH_ALEN);
+
+	priv_sl2->slaves = priv->slaves;
+	priv_sl2->clk = priv->clk;
+
+	priv_sl2->cpsw_res = priv->cpsw_res;
+	priv_sl2->regs = priv->regs;
+	priv_sl2->host_port = priv->host_port;
+	priv_sl2->host_port_regs = priv->host_port_regs;
+	priv_sl2->wr_regs = priv->wr_regs;
+	priv_sl2->dma = priv->dma;
+	priv_sl2->txch = priv->txch;
+	priv_sl2->rxch = priv->rxch;
+	priv_sl2->ale = priv->ale;
+	priv_sl2->emac_port = 1;
+	priv->slaves[1].ndev = ndev;
+	priv_sl2->cpts = priv->cpts;
+	priv_sl2->version = priv->version;
+
+	for (i = 0; i < priv->num_irqs; i++) {
+		priv_sl2->irqs_table[i] = priv->irqs_table[i];
+		priv_sl2->num_irqs = priv->num_irqs;
+	}
+
+	ndev->features |= NETIF_F_HW_VLAN_FILTER;
+
+	ndev->netdev_ops = &cpsw_netdev_ops;
+	SET_ETHTOOL_OPS(ndev, &cpsw_ethtool_ops);
+	netif_napi_add(ndev, &priv_sl2->napi, cpsw_poll, CPSW_POLL_WEIGHT);
+
+	/* register the network device */
+	SET_NETDEV_DEV(ndev, &pdev->dev);
+	ret = register_netdev(ndev);
+	if (ret) {
+		pr_err("cpsw: error registering net device\n");
+		free_netdev(ndev);
+		ret = -ENODEV;
+	}
+
+	return ret;
+}
+
 static int cpsw_probe(struct platform_device *pdev)
 {
 	struct cpsw_platform_data	*data = pdev->dev.platform_data;
@@ -1310,6 +1530,9 @@ static int cpsw_probe(struct platform_device *pdev)
 	for (i = 0; i < data->slaves; i++)
 		priv->slaves[i].slave_num = i;
 
+	priv->slaves[0].ndev = ndev;
+	priv->emac_port = 0;
+
 	priv->clk = clk_get(&pdev->dev, "fck");
 	if (IS_ERR(priv->clk)) {
 		dev_err(&pdev->dev, "fck is not found\n");
@@ -1484,6 +1707,14 @@ static int cpsw_probe(struct platform_device *pdev)
 	cpsw_notice(priv, probe, "initialized device (regs %x, irq %d)\n",
 		  priv->cpsw_res->start, ndev->irq);
 
+	if (priv->data.dual_emac) {
+		ret = cpsw_probe_dual_emac(pdev, priv);
+		if (ret) {
+			cpsw_err(priv, probe, "error probe slave 2 emac interface\n");
+			goto clean_irq_ret;
+		}
+	}
+
 	return 0;
 
 clean_irq_ret:
diff --git a/include/linux/platform_data/cpsw.h b/include/linux/platform_data/cpsw.h
index e962cfd..798fb80 100644
--- a/include/linux/platform_data/cpsw.h
+++ b/include/linux/platform_data/cpsw.h
@@ -21,6 +21,8 @@ struct cpsw_slave_data {
 	char		phy_id[MII_BUS_ID_SIZE];
 	int		phy_if;
 	u8		mac_addr[ETH_ALEN];
+	u16		dual_emac_res_vlan;	/* Reserved VLAN for DualEMAC */
+
 };
 
 struct cpsw_platform_data {
@@ -36,6 +38,7 @@ struct cpsw_platform_data {
 	u32	rx_descs;	/* Number of Rx Descriptios */
 	u32	mac_control;	/* Mac control register */
 	u16	default_vlan;	/* Def VLAN for ALE lookup in VLAN aware mode*/
+	bool	dual_emac;	/* Enable Dual EMAC mode */
 };
 
 #endif /* __CPSW_H__ */
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 3/3] driver: net: ethernet: cpsw: dual emac interface implementation
@ 2013-02-11 19:52   ` Mugunthan V N
  0 siblings, 0 replies; 48+ messages in thread
From: Mugunthan V N @ 2013-02-11 19:52 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-arm-kernel, linux-omap, Mugunthan V N

The CPSW switch can act as Dual EMAC by segregating the switch ports
using VLAN and port VLAN as per the TRM description in
14.3.2.10.2 Dual Mac Mode

Following CPSW components will be common for both the interfaces.
* Interrupt source is common for both eth interfaces
* Interrupt pacing is common for both interfaces
* Hardware statistics is common for all the ports
* CPDMA is common for both eth interface
* CPTS is common for both the interface and it should not be enabled on
  both the interface as timestamping information doesn't contain port
  information.

Constrains
* Reserved VID of One port should not be used in other interface which will
  enable switching functionality
* Same VID must not be used in both the interface which will enable switching
  functionality

Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
---
 Documentation/devicetree/bindings/net/cpsw.txt |    2 +
 drivers/net/ethernet/ti/cpsw.c                 |  335 ++++++++++++++++++++----
 include/linux/platform_data/cpsw.h             |    3 +
 3 files changed, 288 insertions(+), 52 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt
index 6ddd028..ecfdf75 100644
--- a/Documentation/devicetree/bindings/net/cpsw.txt
+++ b/Documentation/devicetree/bindings/net/cpsw.txt
@@ -24,6 +24,8 @@ Required properties:
 Optional properties:
 - ti,hwmods		: Must be "cpgmac0"
 - no_bd_ram		: Must be 0 or 1
+- dual_emac		: Specifies Switch to act as Dual EMAC
+- dual_emac_res_vlan	: Specifies VID to be used to segregate the ports
 
 Note: "ti,hwmods" field is used to fetch the base address and irq
 resources from TI, omap hwmod data base during device registration.
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 4b964bb..4ceed6e 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -122,6 +122,10 @@ do {								\
 #define CPSW_VLAN_AWARE		BIT(1)
 #define CPSW_ALE_VLAN_AWARE	1
 
+#define CPSW_FIFO_NORMAL_MODE		(0 << 15)
+#define CPSW_FIFO_DUAL_MAC_MODE		(1 << 15)
+#define CPSW_FIFO_RATE_LIMIT_MODE	(2 << 15)
+
 #define cpsw_enable_irq(priv)	\
 	do {			\
 		u32 i;		\
@@ -254,7 +258,7 @@ struct cpsw_ss_regs {
 struct cpsw_host_regs {
 	u32	max_blks;
 	u32	blk_cnt;
-	u32	flow_thresh;
+	u32	tx_in_ctl;
 	u32	port_vlan;
 	u32	tx_pri_map;
 	u32	cpdma_tx_pri_map;
@@ -281,6 +285,9 @@ struct cpsw_slave {
 	u32				mac_control;
 	struct cpsw_slave_data		*data;
 	struct phy_device		*phy;
+	struct net_device		*ndev;
+	u32				port_vlan;
+	u32				open_stat;
 };
 
 static inline u32 slave_read(struct cpsw_slave *slave, u32 offset)
@@ -320,15 +327,63 @@ struct cpsw_priv {
 	u32 irqs_table[4];
 	u32 num_irqs;
 	struct cpts *cpts;
+	u32 emac_port;
 };
 
 #define napi_to_priv(napi)	container_of(napi, struct cpsw_priv, napi)
-#define for_each_slave(priv, func, arg...)			\
-	do {							\
-		int idx;					\
-		for (idx = 0; idx < (priv)->data.slaves; idx++)	\
-			(func)((priv)->slaves + idx, ##arg);	\
+#define for_each_slave(priv, func, arg...)				\
+	do {								\
+		int idx;						\
+		if (priv->data.dual_emac)				\
+			(func)((priv)->slaves + priv->emac_port, ##arg);\
+		else							\
+			for (idx = 0; idx < (priv)->data.slaves; idx++)	\
+				(func)((priv)->slaves + idx, ##arg);	\
+	} while (0)
+#define cpsw_get_slave_ndev(priv, __slave_no__)				\
+	(priv->slaves[__slave_no__].ndev)
+#define cpsw_get_slave_priv(priv, __slave_no__)				\
+	((priv->slaves[__slave_no__].ndev) ?				\
+		netdev_priv(priv->slaves[__slave_no__].ndev) : NULL)	\
+
+#define cpsw_dual_emac_src_port_detect(status, priv, ndev, skb)		\
+	do {								\
+		if (!priv->data.dual_emac)				\
+			break;						\
+		if (CPDMA_RX_SOURCE_PORT(status) == 1) {		\
+			ndev = cpsw_get_slave_ndev(priv, 0);		\
+			priv = netdev_priv(ndev);			\
+			skb->dev = ndev;				\
+		} else if (CPDMA_RX_SOURCE_PORT(status) == 2) {		\
+			ndev = cpsw_get_slave_ndev(priv, 1);		\
+			priv = netdev_priv(ndev);			\
+			skb->dev = ndev;				\
+		}							\
 	} while (0)
+#define cpsw_add_mcast(priv, addr)					\
+	do {								\
+		if (priv->data.dual_emac) {				\
+			struct cpsw_slave *slave = priv->slaves +	\
+						priv->emac_port;	\
+			int slave_port = cpsw_get_slave_port(priv,	\
+						slave->slave_num);	\
+			cpsw_ale_add_mcast(priv->ale, addr,		\
+				1 << slave_port | 1 << priv->host_port,	\
+				ALE_VLAN, slave->port_vlan, 0);		\
+		} else {						\
+			cpsw_ale_add_mcast(priv->ale, addr,		\
+				ALE_ALL_PORTS << priv->host_port,	\
+				0, 0, 0);				\
+		}							\
+	} while (0)
+
+static inline int cpsw_get_slave_port(struct cpsw_priv *priv, u32 slave_num)
+{
+	if (priv->host_port == 0)
+		return slave_num + 1;
+	else
+		return slave_num;
+}
 
 static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
 {
@@ -348,8 +403,7 @@ static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
 
 		/* program multicast address list into ALE register */
 		netdev_for_each_mc_addr(ha, ndev) {
-			cpsw_ale_add_mcast(priv->ale, (u8 *)ha->addr,
-				ALE_ALL_PORTS << priv->host_port, 0, 0, 0);
+			cpsw_add_mcast(priv, (u8 *)ha->addr);
 		}
 	}
 }
@@ -396,6 +450,8 @@ void cpsw_rx_handler(void *token, int len, int status)
 	struct cpsw_priv	*priv = netdev_priv(ndev);
 	int			ret = 0;
 
+	cpsw_dual_emac_src_port_detect(status, priv, ndev, skb);
+
 	/* free and bail if we are shutting down */
 	if (unlikely(!netif_running(ndev)) ||
 			unlikely(!netif_carrier_ok(ndev))) {
@@ -437,18 +493,17 @@ static irqreturn_t cpsw_interrupt(int irq, void *dev_id)
 		cpsw_intr_disable(priv);
 		cpsw_disable_irq(priv);
 		napi_schedule(&priv->napi);
+	} else {
+		priv = cpsw_get_slave_priv(priv, 1);
+		if (likely(priv) && likely(netif_running(priv->ndev))) {
+			cpsw_intr_disable(priv);
+			cpsw_disable_irq(priv);
+			napi_schedule(&priv->napi);
+		}
 	}
 	return IRQ_HANDLED;
 }
 
-static inline int cpsw_get_slave_port(struct cpsw_priv *priv, u32 slave_num)
-{
-	if (priv->host_port == 0)
-		return slave_num + 1;
-	else
-		return slave_num;
-}
-
 static int cpsw_poll(struct napi_struct *napi, int budget)
 {
 	struct cpsw_priv	*priv = napi_to_priv(napi);
@@ -566,6 +621,54 @@ static inline int __show_stat(char *buf, int maxlen, const char *name, u32 val)
 				leader + strlen(name), val);
 }
 
+static int cpsw_common_res_usage_state(struct cpsw_priv *priv)
+{
+	u32 i;
+	u32 usage_count = 0;
+
+	if (!priv->data.dual_emac)
+		return 0;
+
+	for (i = 0; i < priv->data.slaves; i++)
+		if (priv->slaves[i].open_stat)
+			usage_count++;
+
+	return usage_count;
+}
+
+static inline int cpsw_tx_packet_submit(struct net_device *ndev,
+			struct cpsw_priv *priv, struct sk_buff *skb)
+{
+	if (!priv->data.dual_emac)
+		return cpdma_chan_submit(priv->txch, skb, skb->data,
+				  skb->len, 0, GFP_KERNEL);
+
+	if (ndev == cpsw_get_slave_ndev(priv, 0))
+		return cpdma_chan_submit(priv->txch, skb, skb->data,
+				  skb->len, 1, GFP_KERNEL);
+	else
+		return cpdma_chan_submit(priv->txch, skb, skb->data,
+				  skb->len, 2, GFP_KERNEL);
+}
+
+static inline void cpsw_add_dual_emac_def_ale_entries(
+		struct cpsw_priv *priv, struct cpsw_slave *slave,
+		u32 slave_port)
+{
+	u32 port_mask = 1 << slave_port | 1 << priv->host_port;
+
+	if (priv->version == CPSW_VERSION_1)
+		slave_write(slave, slave->port_vlan, CPSW1_PORT_VLAN);
+	else
+		slave_write(slave, slave->port_vlan, CPSW2_PORT_VLAN);
+	cpsw_ale_add_vlan(priv->ale, slave->port_vlan, port_mask,
+			  port_mask, port_mask, 0);
+	cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
+			   port_mask, ALE_VLAN, slave->port_vlan, 0);
+	cpsw_ale_add_ucast(priv->ale, priv->mac_addr,
+		priv->host_port, ALE_VLAN, slave->port_vlan);
+}
+
 static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
 {
 	char name[32];
@@ -595,8 +698,11 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
 
 	slave_port = cpsw_get_slave_port(priv, slave->slave_num);
 
-	cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
-			   1 << slave_port, 0, 0, ALE_MCAST_FWD_2);
+	if (priv->data.dual_emac)
+		cpsw_add_dual_emac_def_ale_entries(priv, slave, slave_port);
+	else
+		cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
+				   1 << slave_port, 0, 0, ALE_MCAST_FWD_2);
 
 	slave->phy = phy_connect(priv->ndev, slave->data->phy_id,
 				 &cpsw_adjust_link, slave->data->phy_if);
@@ -634,6 +740,7 @@ static inline void cpsw_add_default_vlan(struct cpsw_priv *priv)
 static void cpsw_init_host_port(struct cpsw_priv *priv)
 {
 	u32 control_reg;
+	u32 fifo_mode;
 
 	/* soft reset the controller and initialize ale */
 	soft_reset("cpsw", &priv->regs->soft_reset);
@@ -645,6 +752,9 @@ static void cpsw_init_host_port(struct cpsw_priv *priv)
 	control_reg = readl(&priv->regs->control);
 	control_reg |= CPSW_VLAN_AWARE;
 	writel(control_reg, &priv->regs->control);
+	fifo_mode = (priv->data.dual_emac) ? CPSW_FIFO_DUAL_MAC_MODE :
+		     CPSW_FIFO_NORMAL_MODE;
+	writel(fifo_mode, &priv->host_port_regs->tx_in_ctl);
 
 	/* setup host port priority mapping */
 	__raw_writel(CPDMA_TX_PRIORITY_MAP,
@@ -654,9 +764,12 @@ static void cpsw_init_host_port(struct cpsw_priv *priv)
 	cpsw_ale_control_set(priv->ale, priv->host_port,
 			     ALE_PORT_STATE, ALE_PORT_STATE_FORWARD);
 
-	cpsw_ale_add_ucast(priv->ale, priv->mac_addr, priv->host_port, 0, 0);
-	cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
-			   1 << priv->host_port, 0, 0, ALE_MCAST_FWD_2);
+	if (!priv->data.dual_emac) {
+		cpsw_ale_add_ucast(priv->ale, priv->mac_addr, priv->host_port,
+				   0, 0);
+		cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
+				   1 << priv->host_port, 0, 0, ALE_MCAST_FWD_2);
+	}
 }
 
 static int cpsw_ndo_open(struct net_device *ndev)
@@ -665,7 +778,8 @@ static int cpsw_ndo_open(struct net_device *ndev)
 	int i, ret;
 	u32 reg;
 
-	cpsw_intr_disable(priv);
+	if (!cpsw_common_res_usage_state(priv))
+		cpsw_intr_disable(priv);
 	netif_carrier_off(ndev);
 
 	pm_runtime_get_sync(&priv->pdev->dev);
@@ -677,46 +791,54 @@ static int cpsw_ndo_open(struct net_device *ndev)
 		 CPSW_RTL_VERSION(reg));
 
 	/* initialize host and slave ports */
-	cpsw_init_host_port(priv);
+	if (!cpsw_common_res_usage_state(priv))
+		cpsw_init_host_port(priv);
 	for_each_slave(priv, cpsw_slave_open, priv);
 
 	/* Add default VLAN */
-	cpsw_add_default_vlan(priv);
+	if (!priv->data.dual_emac)
+		cpsw_add_default_vlan(priv);
 
-	/* setup tx dma to fixed prio and zero offset */
-	cpdma_control_set(priv->dma, CPDMA_TX_PRIO_FIXED, 1);
-	cpdma_control_set(priv->dma, CPDMA_RX_BUFFER_OFFSET, 0);
+	if (!cpsw_common_res_usage_state(priv)) {
+		/* setup tx dma to fixed prio and zero offset */
+		cpdma_control_set(priv->dma, CPDMA_TX_PRIO_FIXED, 1);
+		cpdma_control_set(priv->dma, CPDMA_RX_BUFFER_OFFSET, 0);
 
-	/* disable priority elevation and enable statistics on all ports */
-	__raw_writel(0, &priv->regs->ptype);
+		/* disable priority elevation */
+		__raw_writel(0, &priv->regs->ptype);
 
-	/* enable statistics collection only on the host port */
-	__raw_writel(0x7, &priv->regs->stat_port_en);
+		/* enable statistics collection only on all ports */
+		__raw_writel(0x7, &priv->regs->stat_port_en);
 
-	if (WARN_ON(!priv->data.rx_descs))
-		priv->data.rx_descs = 128;
+		if (WARN_ON(!priv->data.rx_descs))
+			priv->data.rx_descs = 128;
 
-	for (i = 0; i < priv->data.rx_descs; i++) {
-		struct sk_buff *skb;
+		for (i = 0; i < priv->data.rx_descs; i++) {
+			struct sk_buff *skb;
 
-		ret = -ENOMEM;
-		skb = netdev_alloc_skb_ip_align(priv->ndev,
-						priv->rx_packet_max);
-		if (!skb)
-			break;
-		ret = cpdma_chan_submit(priv->rxch, skb, skb->data,
+			ret = -ENOMEM;
+			skb = netdev_alloc_skb_ip_align(priv->ndev,
+							priv->rx_packet_max);
+			if (!skb)
+				break;
+			ret = cpdma_chan_submit(priv->rxch, skb, skb->data,
 					skb_tailroom(skb), 0, GFP_KERNEL);
-		if (WARN_ON(ret < 0))
-			break;
+			if (WARN_ON(ret < 0))
+				break;
+		}
+		/* continue even if we didn't manage to submit all
+		 * receive descs
+		 */
+		cpsw_info(priv, ifup, "submitted %d rx descriptors\n", i);
 	}
-	/* continue even if we didn't manage to submit all receive descs */
-	cpsw_info(priv, ifup, "submitted %d rx descriptors\n", i);
 
 	cpdma_ctlr_start(priv->dma);
 	cpsw_intr_enable(priv);
 	napi_enable(&priv->napi);
 	cpdma_ctlr_eoi(priv->dma);
 
+	if (priv->data.dual_emac)
+		priv->slaves[priv->emac_port].open_stat = true;
 	return 0;
 }
 
@@ -737,12 +859,17 @@ static int cpsw_ndo_stop(struct net_device *ndev)
 	netif_stop_queue(priv->ndev);
 	napi_disable(&priv->napi);
 	netif_carrier_off(priv->ndev);
-	cpsw_intr_disable(priv);
-	cpdma_ctlr_int_ctrl(priv->dma, false);
-	cpdma_ctlr_stop(priv->dma);
-	cpsw_ale_stop(priv->ale);
+
+	if (cpsw_common_res_usage_state(priv) <= 1) {
+		cpsw_intr_disable(priv);
+		cpdma_ctlr_int_ctrl(priv->dma, false);
+		cpdma_ctlr_stop(priv->dma);
+		cpsw_ale_stop(priv->ale);
+	}
 	for_each_slave(priv, cpsw_slave_stop, priv);
 	pm_runtime_put_sync(&priv->pdev->dev);
+	if (priv->data.dual_emac)
+		priv->slaves[priv->emac_port].open_stat = false;
 	return 0;
 }
 
@@ -766,8 +893,7 @@ static netdev_tx_t cpsw_ndo_start_xmit(struct sk_buff *skb,
 
 	skb_tx_timestamp(skb);
 
-	ret = cpdma_chan_submit(priv->txch, skb, skb->data,
-				skb->len, 0, GFP_KERNEL);
+	ret = cpsw_tx_packet_submit(ndev, priv, skb);
 	if (unlikely(ret != 0)) {
 		cpsw_err(priv, tx_err, "desc submit failed\n");
 		goto fail;
@@ -836,9 +962,14 @@ static void cpsw_hwtstamp_v1(struct cpsw_priv *priv)
 
 static void cpsw_hwtstamp_v2(struct cpsw_priv *priv)
 {
-	struct cpsw_slave *slave = &priv->slaves[priv->data.cpts_active_slave];
+	struct cpsw_slave *slave;
 	u32 ctrl, mtype;
 
+	if (priv->data.dual_emac)
+		slave = &priv->slaves[priv->emac_port];
+	else
+		slave = &priv->slaves[priv->data.cpts_active_slave];
+
 	ctrl = slave_read(slave, CPSW2_CONTROL);
 	ctrl &= ~CTRL_ALL_TS_MASK;
 
@@ -1124,6 +1255,7 @@ static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv,
 	slave->data	= data;
 	slave->regs	= regs + slave_reg_ofs;
 	slave->sliver	= regs + sliver_reg_ofs;
+	slave->port_vlan = data->dual_emac_res_vlan;
 }
 
 static int cpsw_probe_dt(struct cpsw_platform_data *data,
@@ -1204,6 +1336,9 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
 	}
 	data->mac_control = prop;
 
+	if (!of_property_read_u32(node, "dual_emac", &prop))
+		data->dual_emac = prop;
+
 	/*
 	 * Populate all the child nodes here...
 	 */
@@ -1237,6 +1372,18 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
 		if (mac_addr)
 			memcpy(slave_data->mac_addr, mac_addr, ETH_ALEN);
 
+		if (data->dual_emac) {
+			if (of_property_read_u32(node, "dual_emac_res_vlan",
+						 &prop)) {
+				pr_err("Missing dual_emac_res_vlan in DT.\n");
+				slave_data->dual_emac_res_vlan = i+1;
+				pr_err("Using %d as Reserved VLAN for %d slave\n",
+				       slave_data->dual_emac_res_vlan, i);
+			} else {
+				slave_data->dual_emac_res_vlan = prop;
+			}
+		}
+
 		i++;
 	}
 
@@ -1247,6 +1394,79 @@ error_ret:
 	return ret;
 }
 
+static int cpsw_probe_dual_emac(struct platform_device *pdev,
+				struct cpsw_priv *priv)
+{
+	struct cpsw_platform_data	*data = &priv->data;
+	struct net_device		*ndev;
+	struct cpsw_priv		*priv_sl2;
+	int ret = 0, i;
+
+	ndev = alloc_etherdev(sizeof(struct cpsw_priv));
+	if (!ndev) {
+		pr_err("cpsw: error allocating net_device\n");
+		return -ENOMEM;
+	}
+
+	priv_sl2 = netdev_priv(ndev);
+	spin_lock_init(&priv_sl2->lock);
+	priv_sl2->data = *data;
+	priv_sl2->pdev = pdev;
+	priv_sl2->ndev = ndev;
+	priv_sl2->dev  = &ndev->dev;
+	priv_sl2->msg_enable = netif_msg_init(debug_level, CPSW_DEBUG);
+	priv_sl2->rx_packet_max = max(rx_packet_max, 128);
+
+	if (is_valid_ether_addr(data->slave_data[1].mac_addr)) {
+		memcpy(priv_sl2->mac_addr, data->slave_data[1].mac_addr,
+			ETH_ALEN);
+		pr_info("cpsw: Detected MACID = %pM\n", priv_sl2->mac_addr);
+	} else {
+		random_ether_addr(priv_sl2->mac_addr);
+		pr_info("cpsw: Random MACID = %pM\n", priv_sl2->mac_addr);
+	}
+	memcpy(ndev->dev_addr, priv_sl2->mac_addr, ETH_ALEN);
+
+	priv_sl2->slaves = priv->slaves;
+	priv_sl2->clk = priv->clk;
+
+	priv_sl2->cpsw_res = priv->cpsw_res;
+	priv_sl2->regs = priv->regs;
+	priv_sl2->host_port = priv->host_port;
+	priv_sl2->host_port_regs = priv->host_port_regs;
+	priv_sl2->wr_regs = priv->wr_regs;
+	priv_sl2->dma = priv->dma;
+	priv_sl2->txch = priv->txch;
+	priv_sl2->rxch = priv->rxch;
+	priv_sl2->ale = priv->ale;
+	priv_sl2->emac_port = 1;
+	priv->slaves[1].ndev = ndev;
+	priv_sl2->cpts = priv->cpts;
+	priv_sl2->version = priv->version;
+
+	for (i = 0; i < priv->num_irqs; i++) {
+		priv_sl2->irqs_table[i] = priv->irqs_table[i];
+		priv_sl2->num_irqs = priv->num_irqs;
+	}
+
+	ndev->features |= NETIF_F_HW_VLAN_FILTER;
+
+	ndev->netdev_ops = &cpsw_netdev_ops;
+	SET_ETHTOOL_OPS(ndev, &cpsw_ethtool_ops);
+	netif_napi_add(ndev, &priv_sl2->napi, cpsw_poll, CPSW_POLL_WEIGHT);
+
+	/* register the network device */
+	SET_NETDEV_DEV(ndev, &pdev->dev);
+	ret = register_netdev(ndev);
+	if (ret) {
+		pr_err("cpsw: error registering net device\n");
+		free_netdev(ndev);
+		ret = -ENODEV;
+	}
+
+	return ret;
+}
+
 static int cpsw_probe(struct platform_device *pdev)
 {
 	struct cpsw_platform_data	*data = pdev->dev.platform_data;
@@ -1310,6 +1530,9 @@ static int cpsw_probe(struct platform_device *pdev)
 	for (i = 0; i < data->slaves; i++)
 		priv->slaves[i].slave_num = i;
 
+	priv->slaves[0].ndev = ndev;
+	priv->emac_port = 0;
+
 	priv->clk = clk_get(&pdev->dev, "fck");
 	if (IS_ERR(priv->clk)) {
 		dev_err(&pdev->dev, "fck is not found\n");
@@ -1484,6 +1707,14 @@ static int cpsw_probe(struct platform_device *pdev)
 	cpsw_notice(priv, probe, "initialized device (regs %x, irq %d)\n",
 		  priv->cpsw_res->start, ndev->irq);
 
+	if (priv->data.dual_emac) {
+		ret = cpsw_probe_dual_emac(pdev, priv);
+		if (ret) {
+			cpsw_err(priv, probe, "error probe slave 2 emac interface\n");
+			goto clean_irq_ret;
+		}
+	}
+
 	return 0;
 
 clean_irq_ret:
diff --git a/include/linux/platform_data/cpsw.h b/include/linux/platform_data/cpsw.h
index e962cfd..798fb80 100644
--- a/include/linux/platform_data/cpsw.h
+++ b/include/linux/platform_data/cpsw.h
@@ -21,6 +21,8 @@ struct cpsw_slave_data {
 	char		phy_id[MII_BUS_ID_SIZE];
 	int		phy_if;
 	u8		mac_addr[ETH_ALEN];
+	u16		dual_emac_res_vlan;	/* Reserved VLAN for DualEMAC */
+
 };
 
 struct cpsw_platform_data {
@@ -36,6 +38,7 @@ struct cpsw_platform_data {
 	u32	rx_descs;	/* Number of Rx Descriptios */
 	u32	mac_control;	/* Mac control register */
 	u16	default_vlan;	/* Def VLAN for ALE lookup in VLAN aware mode*/
+	bool	dual_emac;	/* Enable Dual EMAC mode */
 };
 
 #endif /* __CPSW_H__ */
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 3/3] driver: net: ethernet: cpsw: dual emac interface implementation
@ 2013-02-11 19:52   ` Mugunthan V N
  0 siblings, 0 replies; 48+ messages in thread
From: Mugunthan V N @ 2013-02-11 19:52 UTC (permalink / raw)
  To: linux-arm-kernel

The CPSW switch can act as Dual EMAC by segregating the switch ports
using VLAN and port VLAN as per the TRM description in
14.3.2.10.2 Dual Mac Mode

Following CPSW components will be common for both the interfaces.
* Interrupt source is common for both eth interfaces
* Interrupt pacing is common for both interfaces
* Hardware statistics is common for all the ports
* CPDMA is common for both eth interface
* CPTS is common for both the interface and it should not be enabled on
  both the interface as timestamping information doesn't contain port
  information.

Constrains
* Reserved VID of One port should not be used in other interface which will
  enable switching functionality
* Same VID must not be used in both the interface which will enable switching
  functionality

Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
---
 Documentation/devicetree/bindings/net/cpsw.txt |    2 +
 drivers/net/ethernet/ti/cpsw.c                 |  335 ++++++++++++++++++++----
 include/linux/platform_data/cpsw.h             |    3 +
 3 files changed, 288 insertions(+), 52 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt
index 6ddd028..ecfdf75 100644
--- a/Documentation/devicetree/bindings/net/cpsw.txt
+++ b/Documentation/devicetree/bindings/net/cpsw.txt
@@ -24,6 +24,8 @@ Required properties:
 Optional properties:
 - ti,hwmods		: Must be "cpgmac0"
 - no_bd_ram		: Must be 0 or 1
+- dual_emac		: Specifies Switch to act as Dual EMAC
+- dual_emac_res_vlan	: Specifies VID to be used to segregate the ports
 
 Note: "ti,hwmods" field is used to fetch the base address and irq
 resources from TI, omap hwmod data base during device registration.
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 4b964bb..4ceed6e 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -122,6 +122,10 @@ do {								\
 #define CPSW_VLAN_AWARE		BIT(1)
 #define CPSW_ALE_VLAN_AWARE	1
 
+#define CPSW_FIFO_NORMAL_MODE		(0 << 15)
+#define CPSW_FIFO_DUAL_MAC_MODE		(1 << 15)
+#define CPSW_FIFO_RATE_LIMIT_MODE	(2 << 15)
+
 #define cpsw_enable_irq(priv)	\
 	do {			\
 		u32 i;		\
@@ -254,7 +258,7 @@ struct cpsw_ss_regs {
 struct cpsw_host_regs {
 	u32	max_blks;
 	u32	blk_cnt;
-	u32	flow_thresh;
+	u32	tx_in_ctl;
 	u32	port_vlan;
 	u32	tx_pri_map;
 	u32	cpdma_tx_pri_map;
@@ -281,6 +285,9 @@ struct cpsw_slave {
 	u32				mac_control;
 	struct cpsw_slave_data		*data;
 	struct phy_device		*phy;
+	struct net_device		*ndev;
+	u32				port_vlan;
+	u32				open_stat;
 };
 
 static inline u32 slave_read(struct cpsw_slave *slave, u32 offset)
@@ -320,15 +327,63 @@ struct cpsw_priv {
 	u32 irqs_table[4];
 	u32 num_irqs;
 	struct cpts *cpts;
+	u32 emac_port;
 };
 
 #define napi_to_priv(napi)	container_of(napi, struct cpsw_priv, napi)
-#define for_each_slave(priv, func, arg...)			\
-	do {							\
-		int idx;					\
-		for (idx = 0; idx < (priv)->data.slaves; idx++)	\
-			(func)((priv)->slaves + idx, ##arg);	\
+#define for_each_slave(priv, func, arg...)				\
+	do {								\
+		int idx;						\
+		if (priv->data.dual_emac)				\
+			(func)((priv)->slaves + priv->emac_port, ##arg);\
+		else							\
+			for (idx = 0; idx < (priv)->data.slaves; idx++)	\
+				(func)((priv)->slaves + idx, ##arg);	\
+	} while (0)
+#define cpsw_get_slave_ndev(priv, __slave_no__)				\
+	(priv->slaves[__slave_no__].ndev)
+#define cpsw_get_slave_priv(priv, __slave_no__)				\
+	((priv->slaves[__slave_no__].ndev) ?				\
+		netdev_priv(priv->slaves[__slave_no__].ndev) : NULL)	\
+
+#define cpsw_dual_emac_src_port_detect(status, priv, ndev, skb)		\
+	do {								\
+		if (!priv->data.dual_emac)				\
+			break;						\
+		if (CPDMA_RX_SOURCE_PORT(status) == 1) {		\
+			ndev = cpsw_get_slave_ndev(priv, 0);		\
+			priv = netdev_priv(ndev);			\
+			skb->dev = ndev;				\
+		} else if (CPDMA_RX_SOURCE_PORT(status) == 2) {		\
+			ndev = cpsw_get_slave_ndev(priv, 1);		\
+			priv = netdev_priv(ndev);			\
+			skb->dev = ndev;				\
+		}							\
 	} while (0)
+#define cpsw_add_mcast(priv, addr)					\
+	do {								\
+		if (priv->data.dual_emac) {				\
+			struct cpsw_slave *slave = priv->slaves +	\
+						priv->emac_port;	\
+			int slave_port = cpsw_get_slave_port(priv,	\
+						slave->slave_num);	\
+			cpsw_ale_add_mcast(priv->ale, addr,		\
+				1 << slave_port | 1 << priv->host_port,	\
+				ALE_VLAN, slave->port_vlan, 0);		\
+		} else {						\
+			cpsw_ale_add_mcast(priv->ale, addr,		\
+				ALE_ALL_PORTS << priv->host_port,	\
+				0, 0, 0);				\
+		}							\
+	} while (0)
+
+static inline int cpsw_get_slave_port(struct cpsw_priv *priv, u32 slave_num)
+{
+	if (priv->host_port == 0)
+		return slave_num + 1;
+	else
+		return slave_num;
+}
 
 static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
 {
@@ -348,8 +403,7 @@ static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
 
 		/* program multicast address list into ALE register */
 		netdev_for_each_mc_addr(ha, ndev) {
-			cpsw_ale_add_mcast(priv->ale, (u8 *)ha->addr,
-				ALE_ALL_PORTS << priv->host_port, 0, 0, 0);
+			cpsw_add_mcast(priv, (u8 *)ha->addr);
 		}
 	}
 }
@@ -396,6 +450,8 @@ void cpsw_rx_handler(void *token, int len, int status)
 	struct cpsw_priv	*priv = netdev_priv(ndev);
 	int			ret = 0;
 
+	cpsw_dual_emac_src_port_detect(status, priv, ndev, skb);
+
 	/* free and bail if we are shutting down */
 	if (unlikely(!netif_running(ndev)) ||
 			unlikely(!netif_carrier_ok(ndev))) {
@@ -437,18 +493,17 @@ static irqreturn_t cpsw_interrupt(int irq, void *dev_id)
 		cpsw_intr_disable(priv);
 		cpsw_disable_irq(priv);
 		napi_schedule(&priv->napi);
+	} else {
+		priv = cpsw_get_slave_priv(priv, 1);
+		if (likely(priv) && likely(netif_running(priv->ndev))) {
+			cpsw_intr_disable(priv);
+			cpsw_disable_irq(priv);
+			napi_schedule(&priv->napi);
+		}
 	}
 	return IRQ_HANDLED;
 }
 
-static inline int cpsw_get_slave_port(struct cpsw_priv *priv, u32 slave_num)
-{
-	if (priv->host_port == 0)
-		return slave_num + 1;
-	else
-		return slave_num;
-}
-
 static int cpsw_poll(struct napi_struct *napi, int budget)
 {
 	struct cpsw_priv	*priv = napi_to_priv(napi);
@@ -566,6 +621,54 @@ static inline int __show_stat(char *buf, int maxlen, const char *name, u32 val)
 				leader + strlen(name), val);
 }
 
+static int cpsw_common_res_usage_state(struct cpsw_priv *priv)
+{
+	u32 i;
+	u32 usage_count = 0;
+
+	if (!priv->data.dual_emac)
+		return 0;
+
+	for (i = 0; i < priv->data.slaves; i++)
+		if (priv->slaves[i].open_stat)
+			usage_count++;
+
+	return usage_count;
+}
+
+static inline int cpsw_tx_packet_submit(struct net_device *ndev,
+			struct cpsw_priv *priv, struct sk_buff *skb)
+{
+	if (!priv->data.dual_emac)
+		return cpdma_chan_submit(priv->txch, skb, skb->data,
+				  skb->len, 0, GFP_KERNEL);
+
+	if (ndev == cpsw_get_slave_ndev(priv, 0))
+		return cpdma_chan_submit(priv->txch, skb, skb->data,
+				  skb->len, 1, GFP_KERNEL);
+	else
+		return cpdma_chan_submit(priv->txch, skb, skb->data,
+				  skb->len, 2, GFP_KERNEL);
+}
+
+static inline void cpsw_add_dual_emac_def_ale_entries(
+		struct cpsw_priv *priv, struct cpsw_slave *slave,
+		u32 slave_port)
+{
+	u32 port_mask = 1 << slave_port | 1 << priv->host_port;
+
+	if (priv->version == CPSW_VERSION_1)
+		slave_write(slave, slave->port_vlan, CPSW1_PORT_VLAN);
+	else
+		slave_write(slave, slave->port_vlan, CPSW2_PORT_VLAN);
+	cpsw_ale_add_vlan(priv->ale, slave->port_vlan, port_mask,
+			  port_mask, port_mask, 0);
+	cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
+			   port_mask, ALE_VLAN, slave->port_vlan, 0);
+	cpsw_ale_add_ucast(priv->ale, priv->mac_addr,
+		priv->host_port, ALE_VLAN, slave->port_vlan);
+}
+
 static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
 {
 	char name[32];
@@ -595,8 +698,11 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
 
 	slave_port = cpsw_get_slave_port(priv, slave->slave_num);
 
-	cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
-			   1 << slave_port, 0, 0, ALE_MCAST_FWD_2);
+	if (priv->data.dual_emac)
+		cpsw_add_dual_emac_def_ale_entries(priv, slave, slave_port);
+	else
+		cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
+				   1 << slave_port, 0, 0, ALE_MCAST_FWD_2);
 
 	slave->phy = phy_connect(priv->ndev, slave->data->phy_id,
 				 &cpsw_adjust_link, slave->data->phy_if);
@@ -634,6 +740,7 @@ static inline void cpsw_add_default_vlan(struct cpsw_priv *priv)
 static void cpsw_init_host_port(struct cpsw_priv *priv)
 {
 	u32 control_reg;
+	u32 fifo_mode;
 
 	/* soft reset the controller and initialize ale */
 	soft_reset("cpsw", &priv->regs->soft_reset);
@@ -645,6 +752,9 @@ static void cpsw_init_host_port(struct cpsw_priv *priv)
 	control_reg = readl(&priv->regs->control);
 	control_reg |= CPSW_VLAN_AWARE;
 	writel(control_reg, &priv->regs->control);
+	fifo_mode = (priv->data.dual_emac) ? CPSW_FIFO_DUAL_MAC_MODE :
+		     CPSW_FIFO_NORMAL_MODE;
+	writel(fifo_mode, &priv->host_port_regs->tx_in_ctl);
 
 	/* setup host port priority mapping */
 	__raw_writel(CPDMA_TX_PRIORITY_MAP,
@@ -654,9 +764,12 @@ static void cpsw_init_host_port(struct cpsw_priv *priv)
 	cpsw_ale_control_set(priv->ale, priv->host_port,
 			     ALE_PORT_STATE, ALE_PORT_STATE_FORWARD);
 
-	cpsw_ale_add_ucast(priv->ale, priv->mac_addr, priv->host_port, 0, 0);
-	cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
-			   1 << priv->host_port, 0, 0, ALE_MCAST_FWD_2);
+	if (!priv->data.dual_emac) {
+		cpsw_ale_add_ucast(priv->ale, priv->mac_addr, priv->host_port,
+				   0, 0);
+		cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
+				   1 << priv->host_port, 0, 0, ALE_MCAST_FWD_2);
+	}
 }
 
 static int cpsw_ndo_open(struct net_device *ndev)
@@ -665,7 +778,8 @@ static int cpsw_ndo_open(struct net_device *ndev)
 	int i, ret;
 	u32 reg;
 
-	cpsw_intr_disable(priv);
+	if (!cpsw_common_res_usage_state(priv))
+		cpsw_intr_disable(priv);
 	netif_carrier_off(ndev);
 
 	pm_runtime_get_sync(&priv->pdev->dev);
@@ -677,46 +791,54 @@ static int cpsw_ndo_open(struct net_device *ndev)
 		 CPSW_RTL_VERSION(reg));
 
 	/* initialize host and slave ports */
-	cpsw_init_host_port(priv);
+	if (!cpsw_common_res_usage_state(priv))
+		cpsw_init_host_port(priv);
 	for_each_slave(priv, cpsw_slave_open, priv);
 
 	/* Add default VLAN */
-	cpsw_add_default_vlan(priv);
+	if (!priv->data.dual_emac)
+		cpsw_add_default_vlan(priv);
 
-	/* setup tx dma to fixed prio and zero offset */
-	cpdma_control_set(priv->dma, CPDMA_TX_PRIO_FIXED, 1);
-	cpdma_control_set(priv->dma, CPDMA_RX_BUFFER_OFFSET, 0);
+	if (!cpsw_common_res_usage_state(priv)) {
+		/* setup tx dma to fixed prio and zero offset */
+		cpdma_control_set(priv->dma, CPDMA_TX_PRIO_FIXED, 1);
+		cpdma_control_set(priv->dma, CPDMA_RX_BUFFER_OFFSET, 0);
 
-	/* disable priority elevation and enable statistics on all ports */
-	__raw_writel(0, &priv->regs->ptype);
+		/* disable priority elevation */
+		__raw_writel(0, &priv->regs->ptype);
 
-	/* enable statistics collection only on the host port */
-	__raw_writel(0x7, &priv->regs->stat_port_en);
+		/* enable statistics collection only on all ports */
+		__raw_writel(0x7, &priv->regs->stat_port_en);
 
-	if (WARN_ON(!priv->data.rx_descs))
-		priv->data.rx_descs = 128;
+		if (WARN_ON(!priv->data.rx_descs))
+			priv->data.rx_descs = 128;
 
-	for (i = 0; i < priv->data.rx_descs; i++) {
-		struct sk_buff *skb;
+		for (i = 0; i < priv->data.rx_descs; i++) {
+			struct sk_buff *skb;
 
-		ret = -ENOMEM;
-		skb = netdev_alloc_skb_ip_align(priv->ndev,
-						priv->rx_packet_max);
-		if (!skb)
-			break;
-		ret = cpdma_chan_submit(priv->rxch, skb, skb->data,
+			ret = -ENOMEM;
+			skb = netdev_alloc_skb_ip_align(priv->ndev,
+							priv->rx_packet_max);
+			if (!skb)
+				break;
+			ret = cpdma_chan_submit(priv->rxch, skb, skb->data,
 					skb_tailroom(skb), 0, GFP_KERNEL);
-		if (WARN_ON(ret < 0))
-			break;
+			if (WARN_ON(ret < 0))
+				break;
+		}
+		/* continue even if we didn't manage to submit all
+		 * receive descs
+		 */
+		cpsw_info(priv, ifup, "submitted %d rx descriptors\n", i);
 	}
-	/* continue even if we didn't manage to submit all receive descs */
-	cpsw_info(priv, ifup, "submitted %d rx descriptors\n", i);
 
 	cpdma_ctlr_start(priv->dma);
 	cpsw_intr_enable(priv);
 	napi_enable(&priv->napi);
 	cpdma_ctlr_eoi(priv->dma);
 
+	if (priv->data.dual_emac)
+		priv->slaves[priv->emac_port].open_stat = true;
 	return 0;
 }
 
@@ -737,12 +859,17 @@ static int cpsw_ndo_stop(struct net_device *ndev)
 	netif_stop_queue(priv->ndev);
 	napi_disable(&priv->napi);
 	netif_carrier_off(priv->ndev);
-	cpsw_intr_disable(priv);
-	cpdma_ctlr_int_ctrl(priv->dma, false);
-	cpdma_ctlr_stop(priv->dma);
-	cpsw_ale_stop(priv->ale);
+
+	if (cpsw_common_res_usage_state(priv) <= 1) {
+		cpsw_intr_disable(priv);
+		cpdma_ctlr_int_ctrl(priv->dma, false);
+		cpdma_ctlr_stop(priv->dma);
+		cpsw_ale_stop(priv->ale);
+	}
 	for_each_slave(priv, cpsw_slave_stop, priv);
 	pm_runtime_put_sync(&priv->pdev->dev);
+	if (priv->data.dual_emac)
+		priv->slaves[priv->emac_port].open_stat = false;
 	return 0;
 }
 
@@ -766,8 +893,7 @@ static netdev_tx_t cpsw_ndo_start_xmit(struct sk_buff *skb,
 
 	skb_tx_timestamp(skb);
 
-	ret = cpdma_chan_submit(priv->txch, skb, skb->data,
-				skb->len, 0, GFP_KERNEL);
+	ret = cpsw_tx_packet_submit(ndev, priv, skb);
 	if (unlikely(ret != 0)) {
 		cpsw_err(priv, tx_err, "desc submit failed\n");
 		goto fail;
@@ -836,9 +962,14 @@ static void cpsw_hwtstamp_v1(struct cpsw_priv *priv)
 
 static void cpsw_hwtstamp_v2(struct cpsw_priv *priv)
 {
-	struct cpsw_slave *slave = &priv->slaves[priv->data.cpts_active_slave];
+	struct cpsw_slave *slave;
 	u32 ctrl, mtype;
 
+	if (priv->data.dual_emac)
+		slave = &priv->slaves[priv->emac_port];
+	else
+		slave = &priv->slaves[priv->data.cpts_active_slave];
+
 	ctrl = slave_read(slave, CPSW2_CONTROL);
 	ctrl &= ~CTRL_ALL_TS_MASK;
 
@@ -1124,6 +1255,7 @@ static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv,
 	slave->data	= data;
 	slave->regs	= regs + slave_reg_ofs;
 	slave->sliver	= regs + sliver_reg_ofs;
+	slave->port_vlan = data->dual_emac_res_vlan;
 }
 
 static int cpsw_probe_dt(struct cpsw_platform_data *data,
@@ -1204,6 +1336,9 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
 	}
 	data->mac_control = prop;
 
+	if (!of_property_read_u32(node, "dual_emac", &prop))
+		data->dual_emac = prop;
+
 	/*
 	 * Populate all the child nodes here...
 	 */
@@ -1237,6 +1372,18 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
 		if (mac_addr)
 			memcpy(slave_data->mac_addr, mac_addr, ETH_ALEN);
 
+		if (data->dual_emac) {
+			if (of_property_read_u32(node, "dual_emac_res_vlan",
+						 &prop)) {
+				pr_err("Missing dual_emac_res_vlan in DT.\n");
+				slave_data->dual_emac_res_vlan = i+1;
+				pr_err("Using %d as Reserved VLAN for %d slave\n",
+				       slave_data->dual_emac_res_vlan, i);
+			} else {
+				slave_data->dual_emac_res_vlan = prop;
+			}
+		}
+
 		i++;
 	}
 
@@ -1247,6 +1394,79 @@ error_ret:
 	return ret;
 }
 
+static int cpsw_probe_dual_emac(struct platform_device *pdev,
+				struct cpsw_priv *priv)
+{
+	struct cpsw_platform_data	*data = &priv->data;
+	struct net_device		*ndev;
+	struct cpsw_priv		*priv_sl2;
+	int ret = 0, i;
+
+	ndev = alloc_etherdev(sizeof(struct cpsw_priv));
+	if (!ndev) {
+		pr_err("cpsw: error allocating net_device\n");
+		return -ENOMEM;
+	}
+
+	priv_sl2 = netdev_priv(ndev);
+	spin_lock_init(&priv_sl2->lock);
+	priv_sl2->data = *data;
+	priv_sl2->pdev = pdev;
+	priv_sl2->ndev = ndev;
+	priv_sl2->dev  = &ndev->dev;
+	priv_sl2->msg_enable = netif_msg_init(debug_level, CPSW_DEBUG);
+	priv_sl2->rx_packet_max = max(rx_packet_max, 128);
+
+	if (is_valid_ether_addr(data->slave_data[1].mac_addr)) {
+		memcpy(priv_sl2->mac_addr, data->slave_data[1].mac_addr,
+			ETH_ALEN);
+		pr_info("cpsw: Detected MACID = %pM\n", priv_sl2->mac_addr);
+	} else {
+		random_ether_addr(priv_sl2->mac_addr);
+		pr_info("cpsw: Random MACID = %pM\n", priv_sl2->mac_addr);
+	}
+	memcpy(ndev->dev_addr, priv_sl2->mac_addr, ETH_ALEN);
+
+	priv_sl2->slaves = priv->slaves;
+	priv_sl2->clk = priv->clk;
+
+	priv_sl2->cpsw_res = priv->cpsw_res;
+	priv_sl2->regs = priv->regs;
+	priv_sl2->host_port = priv->host_port;
+	priv_sl2->host_port_regs = priv->host_port_regs;
+	priv_sl2->wr_regs = priv->wr_regs;
+	priv_sl2->dma = priv->dma;
+	priv_sl2->txch = priv->txch;
+	priv_sl2->rxch = priv->rxch;
+	priv_sl2->ale = priv->ale;
+	priv_sl2->emac_port = 1;
+	priv->slaves[1].ndev = ndev;
+	priv_sl2->cpts = priv->cpts;
+	priv_sl2->version = priv->version;
+
+	for (i = 0; i < priv->num_irqs; i++) {
+		priv_sl2->irqs_table[i] = priv->irqs_table[i];
+		priv_sl2->num_irqs = priv->num_irqs;
+	}
+
+	ndev->features |= NETIF_F_HW_VLAN_FILTER;
+
+	ndev->netdev_ops = &cpsw_netdev_ops;
+	SET_ETHTOOL_OPS(ndev, &cpsw_ethtool_ops);
+	netif_napi_add(ndev, &priv_sl2->napi, cpsw_poll, CPSW_POLL_WEIGHT);
+
+	/* register the network device */
+	SET_NETDEV_DEV(ndev, &pdev->dev);
+	ret = register_netdev(ndev);
+	if (ret) {
+		pr_err("cpsw: error registering net device\n");
+		free_netdev(ndev);
+		ret = -ENODEV;
+	}
+
+	return ret;
+}
+
 static int cpsw_probe(struct platform_device *pdev)
 {
 	struct cpsw_platform_data	*data = pdev->dev.platform_data;
@@ -1310,6 +1530,9 @@ static int cpsw_probe(struct platform_device *pdev)
 	for (i = 0; i < data->slaves; i++)
 		priv->slaves[i].slave_num = i;
 
+	priv->slaves[0].ndev = ndev;
+	priv->emac_port = 0;
+
 	priv->clk = clk_get(&pdev->dev, "fck");
 	if (IS_ERR(priv->clk)) {
 		dev_err(&pdev->dev, "fck is not found\n");
@@ -1484,6 +1707,14 @@ static int cpsw_probe(struct platform_device *pdev)
 	cpsw_notice(priv, probe, "initialized device (regs %x, irq %d)\n",
 		  priv->cpsw_res->start, ndev->irq);
 
+	if (priv->data.dual_emac) {
+		ret = cpsw_probe_dual_emac(pdev, priv);
+		if (ret) {
+			cpsw_err(priv, probe, "error probe slave 2 emac interface\n");
+			goto clean_irq_ret;
+		}
+	}
+
 	return 0;
 
 clean_irq_ret:
diff --git a/include/linux/platform_data/cpsw.h b/include/linux/platform_data/cpsw.h
index e962cfd..798fb80 100644
--- a/include/linux/platform_data/cpsw.h
+++ b/include/linux/platform_data/cpsw.h
@@ -21,6 +21,8 @@ struct cpsw_slave_data {
 	char		phy_id[MII_BUS_ID_SIZE];
 	int		phy_if;
 	u8		mac_addr[ETH_ALEN];
+	u16		dual_emac_res_vlan;	/* Reserved VLAN for DualEMAC */
+
 };
 
 struct cpsw_platform_data {
@@ -36,6 +38,7 @@ struct cpsw_platform_data {
 	u32	rx_descs;	/* Number of Rx Descriptios */
 	u32	mac_control;	/* Mac control register */
 	u16	default_vlan;	/* Def VLAN for ALE lookup in VLAN aware mode*/
+	bool	dual_emac;	/* Enable Dual EMAC mode */
 };
 
 #endif /* __CPSW_H__ */
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* Re: [PATCH 0/3] Dual EMAC mode implementation of CPSW
  2013-02-11 19:52 ` Mugunthan V N
@ 2013-02-12 21:15   ` David Miller
  -1 siblings, 0 replies; 48+ messages in thread
From: David Miller @ 2013-02-12 21:15 UTC (permalink / raw)
  To: mugunthanvnm; +Cc: netdev, linux-arm-kernel, linux-omap

From: Mugunthan V N <mugunthanvnm@ti.com>
Date: Tue, 12 Feb 2013 01:22:17 +0530

> This patch series implements Dual EMAC mode implementation of CPSW
> which acts as two standalone EMAC by segregating the switch using VIDs
> and port VLAN
> 
> Mugunthan V N (3):
>   driver: net: ethernet: davinci_cpdma: add support for directed packet
>     and source port detection
>   driver: net: ethernet: cpsw: make cpts as pointer
>   driver: net: ethernet: cpsw: dual emac interface implementation

Series applied.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH 0/3] Dual EMAC mode implementation of CPSW
@ 2013-02-12 21:15   ` David Miller
  0 siblings, 0 replies; 48+ messages in thread
From: David Miller @ 2013-02-12 21:15 UTC (permalink / raw)
  To: linux-arm-kernel

From: Mugunthan V N <mugunthanvnm@ti.com>
Date: Tue, 12 Feb 2013 01:22:17 +0530

> This patch series implements Dual EMAC mode implementation of CPSW
> which acts as two standalone EMAC by segregating the switch using VIDs
> and port VLAN
> 
> Mugunthan V N (3):
>   driver: net: ethernet: davinci_cpdma: add support for directed packet
>     and source port detection
>   driver: net: ethernet: cpsw: make cpts as pointer
>   driver: net: ethernet: cpsw: dual emac interface implementation

Series applied.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 3/3] driver: net: ethernet: cpsw: dual emac interface implementation
  2013-02-11 19:52   ` Mugunthan V N
@ 2013-02-18 13:36       ` Peter Korsgaard
  -1 siblings, 0 replies; 48+ messages in thread
From: Peter Korsgaard @ 2013-02-18 13:36 UTC (permalink / raw)
  To: Mugunthan V N
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-omap-u79uwXL29TY76Z2rM5mHXA, davem-fT/PcQaiUtIeIZ0/mPfg9Q,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

>>>>> "M" == Mugunthan V N <mugunthanvnm-l0cyMroinI0@public.gmane.org> writes:

 M> The CPSW switch can act as Dual EMAC by segregating the switch ports
 M> using VLAN and port VLAN as per the TRM description in
 M> 14.3.2.10.2 Dual Mac Mode

 M> Following CPSW components will be common for both the interfaces.
 M> * Interrupt source is common for both eth interfaces
 M> * Interrupt pacing is common for both interfaces
 M> * Hardware statistics is common for all the ports
 M> * CPDMA is common for both eth interface
 M> * CPTS is common for both the interface and it should not be enabled on
 M>   both the interface as timestamping information doesn't contain port
 M>   information.

 M> Constrains
 M> * Reserved VID of One port should not be used in other interface which will
 M>   enable switching functionality
 M> * Same VID must not be used in both the interface which will enable switching
 M>   functionality

 M> Signed-off-by: Mugunthan V N <mugunthanvnm-l0cyMroinI0@public.gmane.org>
 M> ---
 M>  Documentation/devicetree/bindings/net/cpsw.txt |    2 +
 M>  drivers/net/ethernet/ti/cpsw.c                 |  335 ++++++++++++++++++++----
 M>  include/linux/platform_data/cpsw.h             |    3 +
 M>  3 files changed, 288 insertions(+), 52 deletions(-)

 M> diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt
 M> index 6ddd028..ecfdf75 100644
 M> --- a/Documentation/devicetree/bindings/net/cpsw.txt
 M> +++ b/Documentation/devicetree/bindings/net/cpsw.txt
 M> @@ -24,6 +24,8 @@ Required properties:
 M>  Optional properties:
 M>  - ti,hwmods		: Must be "cpgmac0"
 M>  - no_bd_ram		: Must be 0 or 1
 M> +- dual_emac		: Specifies Switch to act as Dual EMAC
 M> +- dual_emac_res_vlan	: Specifies VID to be used to segregate the ports

You forgot to CC devicetree-discuss. Properties normally use dashes (-)
instead of underscores (_). These properties are more about
configuration and not hardware.

It is not clear to me from the description that dual_emac is a boolean
(0/1). Shouldn't dual_emacs_res_vlan be a property of the slave?

It would also be good to update the example below with this.




 M>  Note: "ti,hwmods" field is used to fetch base address and irq
 M>  resources from TI, omap hwmod data base during device registration.
 M> diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
 M> index 4b964bb..4ceed6e 100644
 M> --- a/drivers/net/ethernet/ti/cpsw.c
 M> +++ b/drivers/net/ethernet/ti/cpsw.c
 M> @@ -122,6 +122,10 @@ do {								\
 M>  #define CPSW_VLAN_AWARE		BIT(1)
 M>  #define CPSW_ALE_VLAN_AWARE	1
 
 M> +#define CPSW_FIFO_NORMAL_MODE		(0 << 15)
 M> +#define CPSW_FIFO_DUAL_MAC_MODE		(1 << 15)
 M> +#define CPSW_FIFO_RATE_LIMIT_MODE	(2 << 15)
 M> +
 M>  #define cpsw_enable_irq(priv)	\
 M>  	do {			\
 M>  		u32 i;		\
 M> @@ -254,7 +258,7 @@ struct cpsw_ss_regs {
 M>  struct cpsw_host_regs {
 M>  	u32	max_blks;
 M>  	u32	blk_cnt;
 M> -	u32	flow_thresh;
 M> +	u32	tx_in_ctl;
 M>  	u32	port_vlan;
 M>  	u32	tx_pri_map;
 M>  	u32	cpdma_tx_pri_map;
 M> @@ -281,6 +285,9 @@ struct cpsw_slave {
 M>  	u32				mac_control;
 M>  	struct cpsw_slave_data		*data;
 M>  	struct phy_device		*phy;
 M> +	struct net_device		*ndev;
 M> +	u32				port_vlan;
 M> +	u32				open_stat;
 M>  };
 
 M>  static inline u32 slave_read(struct cpsw_slave *slave, u32 offset)
 M> @@ -320,15 +327,63 @@ struct cpsw_priv {
 M>  	u32 irqs_table[4];
 M>  	u32 num_irqs;
 M>  	struct cpts *cpts;
 M> +	u32 emac_port;
 M>  };
 
 M>  #define napi_to_priv(napi)	container_of(napi, struct cpsw_priv, napi)
 M> -#define for_each_slave(priv, func, arg...)			\
 M> -	do {							\
 M> -		int idx;					\
 M> -		for (idx = 0; idx < (priv)->data.slaves; idx++)	\
 M> -			(func)((priv)->slaves + idx, ##arg);	\
 M> +#define for_each_slave(priv, func, arg...)				\
 M> +	do {								\
 M> +		int idx;						\
 M> +		if (priv->data.dual_emac)				\
 M> +			(func)((priv)->slaves + priv->emac_port, ##arg);\
 M> +		else							\
 M> +			for (idx = 0; idx < (priv)->data.slaves; idx++)	\
 M> +				(func)((priv)->slaves + idx, ##arg);	\
 M> +	} while (0)
 M> +#define cpsw_get_slave_ndev(priv, __slave_no__)				\
 M> +	(priv->slaves[__slave_no__].ndev)
 M> +#define cpsw_get_slave_priv(priv, __slave_no__)				\
 M> +	((priv->slaves[__slave_no__].ndev) ?				\
 M> +		netdev_priv(priv->slaves[__slave_no__].ndev) : NULL)	\
 M> +
 M> +#define cpsw_dual_emac_src_port_detect(status, priv, ndev, skb)		\
 M> +	do {								\
 M> +		if (!priv->data.dual_emac)				\
 M> +			break;						\
 M> +		if (CPDMA_RX_SOURCE_PORT(status) == 1) {		\
 M> +			ndev = cpsw_get_slave_ndev(priv, 0);		\
 M> +			priv = netdev_priv(ndev);			\
 M> +			skb->dev = ndev;				\
 M> +		} else if (CPDMA_RX_SOURCE_PORT(status) == 2) {		\
 M> +			ndev = cpsw_get_slave_ndev(priv, 1);		\
 M> +			priv = netdev_priv(ndev);			\
 M> +			skb->dev = ndev;				\
 M> +		}							\
 M>  	} while (0)
 M> +#define cpsw_add_mcast(priv, addr)					\
 M> +	do {								\
 M> +		if (priv->data.dual_emac) {				\
 M> +			struct cpsw_slave *slave = priv->slaves +	\
 M> +						priv->emac_port;	\
 M> +			int slave_port = cpsw_get_slave_port(priv,	\
 M> +						slave->slave_num);	\
 M> +			cpsw_ale_add_mcast(priv->ale, addr,		\
 M> +				1 << slave_port | 1 << priv->host_port,	\
 M> +				ALE_VLAN, slave->port_vlan, 0);		\
 M> +		} else {						\
 M> +			cpsw_ale_add_mcast(priv->ale, addr,		\
 M> +				ALE_ALL_PORTS << priv->host_port,	\
 M> +				0, 0, 0);				\
 M> +		}							\
 M> +	} while (0)
 M> +
 M> +static inline int cpsw_get_slave_port(struct cpsw_priv *priv, u32 slave_num)
 M> +{
 M> +	if (priv->host_port == 0)
 M> +		return slave_num + 1;
 M> +	else
 M> +		return slave_num;
 M> +}
 
 M>  static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
 M>  {
 M> @@ -348,8 +403,7 @@ static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
 
 M>  		/* program multicast address list into ALE register */
 M>  		netdev_for_each_mc_addr(ha, ndev) {
 M> -			cpsw_ale_add_mcast(priv->ale, (u8 *)ha->addr,
 M> -				ALE_ALL_PORTS << priv->host_port, 0, 0, 0);
 M> +			cpsw_add_mcast(priv, (u8 *)ha->addr);
 M>  		}
 M>  	}
 M>  }
 M> @@ -396,6 +450,8 @@ void cpsw_rx_handler(void *token, int len, int status)
 M>  	struct cpsw_priv	*priv = netdev_priv(ndev);
 M>  	int			ret = 0;
 
 M> +	cpsw_dual_emac_src_port_detect(status, priv, ndev, skb);
 M> +
 M>  	/* free and bail if we are shutting down */
 M>  	if (unlikely(!netif_running(ndev)) ||
 M>  			unlikely(!netif_carrier_ok(ndev))) {
 M> @@ -437,18 +493,17 @@ static irqreturn_t cpsw_interrupt(int irq, void *dev_id)
 M>  		cpsw_intr_disable(priv);
 M>  		cpsw_disable_irq(priv);
 M>  		napi_schedule(&priv->napi);
 M> +	} else {
 M> +		priv = cpsw_get_slave_priv(priv, 1);
 M> +		if (likely(priv) && likely(netif_running(priv->ndev))) {
 M> +			cpsw_intr_disable(priv);
 M> +			cpsw_disable_irq(priv);
 M> +			napi_schedule(&priv->napi);
 M> +		}
 M>  	}
 M>  	return IRQ_HANDLED;
 M>  }
 
 M> -static inline int cpsw_get_slave_port(struct cpsw_priv *priv, u32 slave_num)
 M> -{
 M> -	if (priv->host_port == 0)
 M> -		return slave_num + 1;
 M> -	else
 M> -		return slave_num;
 M> -}
 M> -
 M>  static int cpsw_poll(struct napi_struct *napi, int budget)
 M>  {
 M>  	struct cpsw_priv	*priv = napi_to_priv(napi);
 M> @@ -566,6 +621,54 @@ static inline int __show_stat(char *buf, int maxlen, const char *name, u32 val)
 M>  				leader + strlen(name), val);
 M>  }
 
 M> +static int cpsw_common_res_usage_state(struct cpsw_priv *priv)
 M> +{
 M> +	u32 i;
 M> +	u32 usage_count = 0;
 M> +
 M> +	if (!priv->data.dual_emac)
 M> +		return 0;
 M> +
 M> +	for (i = 0; i < priv->data.slaves; i++)
 M> +		if (priv->slaves[i].open_stat)
 M> +			usage_count++;
 M> +
 M> +	return usage_count;
 M> +}
 M> +
 M> +static inline int cpsw_tx_packet_submit(struct net_device *ndev,
 M> +			struct cpsw_priv *priv, struct sk_buff *skb)
 M> +{
 M> +	if (!priv->data.dual_emac)
 M> +		return cpdma_chan_submit(priv->txch, skb, skb->data,
 M> +				  skb->len, 0, GFP_KERNEL);
 M> +
 M> +	if (ndev == cpsw_get_slave_ndev(priv, 0))
 M> +		return cpdma_chan_submit(priv->txch, skb, skb->data,
 M> +				  skb->len, 1, GFP_KERNEL);
 M> +	else
 M> +		return cpdma_chan_submit(priv->txch, skb, skb->data,
 M> +				  skb->len, 2, GFP_KERNEL);
 M> +}
 M> +
 M> +static inline void cpsw_add_dual_emac_def_ale_entries(
 M> +		struct cpsw_priv *priv, struct cpsw_slave *slave,
 M> +		u32 slave_port)
 M> +{
 M> +	u32 port_mask = 1 << slave_port | 1 << priv->host_port;
 M> +
 M> +	if (priv->version == CPSW_VERSION_1)
 M> +		slave_write(slave, slave->port_vlan, CPSW1_PORT_VLAN);
 M> +	else
 M> +		slave_write(slave, slave->port_vlan, CPSW2_PORT_VLAN);
 M> +	cpsw_ale_add_vlan(priv->ale, slave->port_vlan, port_mask,
 M> +			  port_mask, port_mask, 0);
 M> +	cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
 M> +			   port_mask, ALE_VLAN, slave->port_vlan, 0);
 M> +	cpsw_ale_add_ucast(priv->ale, priv->mac_addr,
 M> +		priv->host_port, ALE_VLAN, slave->port_vlan);
 M> +}
 M> +
 M>  static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
 M>  {
 M>  	char name[32];
 M> @@ -595,8 +698,11 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
 
 M>  	slave_port = cpsw_get_slave_port(priv, slave->slave_num);
 
 M> -	cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
 M> -			   1 << slave_port, 0, 0, ALE_MCAST_FWD_2);
 M> +	if (priv->data.dual_emac)
 M> +		cpsw_add_dual_emac_def_ale_entries(priv, slave, slave_port);
 M> +	else
 M> +		cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
 M> +				   1 << slave_port, 0, 0, ALE_MCAST_FWD_2);
 
 slave-> phy = phy_connect(priv->ndev, slave->data->phy_id,
 M>  				 &cpsw_adjust_link, slave->data->phy_if);
 M> @@ -634,6 +740,7 @@ static inline void cpsw_add_default_vlan(struct cpsw_priv *priv)
 M>  static void cpsw_init_host_port(struct cpsw_priv *priv)
 M>  {
 M>  	u32 control_reg;
 M> +	u32 fifo_mode;
 
 M>  	/* soft reset the controller and initialize ale */
 M>  	soft_reset("cpsw", &priv->regs->soft_reset);
 M> @@ -645,6 +752,9 @@ static void cpsw_init_host_port(struct cpsw_priv *priv)
 M>  	control_reg = readl(&priv->regs->control);
 M>  	control_reg |= CPSW_VLAN_AWARE;
 M>  	writel(control_reg, &priv->regs->control);
 M> +	fifo_mode = (priv->data.dual_emac) ? CPSW_FIFO_DUAL_MAC_MODE :
 M> +		     CPSW_FIFO_NORMAL_MODE;
 M> +	writel(fifo_mode, &priv->host_port_regs->tx_in_ctl);
 
 M>  	/* setup host port priority mapping */
 M>  	__raw_writel(CPDMA_TX_PRIORITY_MAP,
 M> @@ -654,9 +764,12 @@ static void cpsw_init_host_port(struct cpsw_priv *priv)
 M>  	cpsw_ale_control_set(priv->ale, priv->host_port,
 M>  			     ALE_PORT_STATE, ALE_PORT_STATE_FORWARD);
 
 M> -	cpsw_ale_add_ucast(priv->ale, priv->mac_addr, priv->host_port, 0, 0);
 M> -	cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
 M> -			   1 << priv->host_port, 0, 0, ALE_MCAST_FWD_2);
 M> +	if (!priv->data.dual_emac) {
 M> +		cpsw_ale_add_ucast(priv->ale, priv->mac_addr, priv->host_port,
 M> +				   0, 0);
 M> +		cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
 M> +				   1 << priv->host_port, 0, 0, ALE_MCAST_FWD_2);
 M> +	}
 M>  }
 
 M>  static int cpsw_ndo_open(struct net_device *ndev)
 M> @@ -665,7 +778,8 @@ static int cpsw_ndo_open(struct net_device *ndev)
 M>  	int i, ret;
 M>  	u32 reg;
 
 M> -	cpsw_intr_disable(priv);
 M> +	if (!cpsw_common_res_usage_state(priv))
 M> +		cpsw_intr_disable(priv);
 M>  	netif_carrier_off(ndev);
 
 M>  	pm_runtime_get_sync(&priv->pdev->dev);
 M> @@ -677,46 +791,54 @@ static int cpsw_ndo_open(struct net_device *ndev)
 M>  		 CPSW_RTL_VERSION(reg));
 
 M>  	/* initialize host and slave ports */
 M> -	cpsw_init_host_port(priv);
 M> +	if (!cpsw_common_res_usage_state(priv))
 M> +		cpsw_init_host_port(priv);
 M>  	for_each_slave(priv, cpsw_slave_open, priv);
 
 M>  	/* Add default VLAN */
 M> -	cpsw_add_default_vlan(priv);
 M> +	if (!priv->data.dual_emac)
 M> +		cpsw_add_default_vlan(priv);
 
 M> -	/* setup tx dma to fixed prio and zero offset */
 M> -	cpdma_control_set(priv->dma, CPDMA_TX_PRIO_FIXED, 1);
 M> -	cpdma_control_set(priv->dma, CPDMA_RX_BUFFER_OFFSET, 0);
 M> +	if (!cpsw_common_res_usage_state(priv)) {
 M> +		/* setup tx dma to fixed prio and zero offset */
 M> +		cpdma_control_set(priv->dma, CPDMA_TX_PRIO_FIXED, 1);
 M> +		cpdma_control_set(priv->dma, CPDMA_RX_BUFFER_OFFSET, 0);
 
 M> -	/* disable priority elevation and enable statistics on all ports */
 M> -	__raw_writel(0, &priv->regs->ptype);
 M> +		/* disable priority elevation */
 M> +		__raw_writel(0, &priv->regs->ptype);
 
 M> -	/* enable statistics collection only on the host port */
 M> -	__raw_writel(0x7, &priv->regs->stat_port_en);
 M> +		/* enable statistics collection only on all ports */
 M> +		__raw_writel(0x7, &priv->regs->stat_port_en);
 
 M> -	if (WARN_ON(!priv->data.rx_descs))
 M> -		priv->data.rx_descs = 128;
 M> +		if (WARN_ON(!priv->data.rx_descs))
 M> +			priv->data.rx_descs = 128;
 
 M> -	for (i = 0; i < priv->data.rx_descs; i++) {
 M> -		struct sk_buff *skb;
 M> +		for (i = 0; i < priv->data.rx_descs; i++) {
 M> +			struct sk_buff *skb;
 
 M> -		ret = -ENOMEM;
 M> -		skb = netdev_alloc_skb_ip_align(priv->ndev,
 M> -						priv->rx_packet_max);
 M> -		if (!skb)
 M> -			break;
 M> -		ret = cpdma_chan_submit(priv->rxch, skb, skb->data,
 M> +			ret = -ENOMEM;
 M> +			skb = netdev_alloc_skb_ip_align(priv->ndev,
 M> +							priv->rx_packet_max);
 M> +			if (!skb)
 M> +				break;
 M> +			ret = cpdma_chan_submit(priv->rxch, skb, skb->data,
 M>  					skb_tailroom(skb), 0, GFP_KERNEL);
 M> -		if (WARN_ON(ret < 0))
 M> -			break;
 M> +			if (WARN_ON(ret < 0))
 M> +				break;
 M> +		}
 M> +		/* continue even if we didn't manage to submit all
 M> +		 * receive descs
 M> +		 */
 M> +		cpsw_info(priv, ifup, "submitted %d rx descriptors\n", i);
 M>  	}
 M> -	/* continue even if we didn't manage to submit all receive descs */
 M> -	cpsw_info(priv, ifup, "submitted %d rx descriptors\n", i);
 
 M>  	cpdma_ctlr_start(priv->dma);
 M>  	cpsw_intr_enable(priv);
 M>  	napi_enable(&priv->napi);
 M>  	cpdma_ctlr_eoi(priv->dma);
 
 M> +	if (priv->data.dual_emac)
 M> +		priv->slaves[priv->emac_port].open_stat = true;
 M>  	return 0;
 M>  }
 
 M> @@ -737,12 +859,17 @@ static int cpsw_ndo_stop(struct net_device *ndev)
 M>  	netif_stop_queue(priv->ndev);
 M>  	napi_disable(&priv->napi);
 M>  	netif_carrier_off(priv->ndev);
 M> -	cpsw_intr_disable(priv);
 M> -	cpdma_ctlr_int_ctrl(priv->dma, false);
 M> -	cpdma_ctlr_stop(priv->dma);
 M> -	cpsw_ale_stop(priv->ale);
 M> +
 M> +	if (cpsw_common_res_usage_state(priv) <= 1) {
 M> +		cpsw_intr_disable(priv);
 M> +		cpdma_ctlr_int_ctrl(priv->dma, false);
 M> +		cpdma_ctlr_stop(priv->dma);
 M> +		cpsw_ale_stop(priv->ale);
 M> +	}
 M>  	for_each_slave(priv, cpsw_slave_stop, priv);
 M>  	pm_runtime_put_sync(&priv->pdev->dev);
 M> +	if (priv->data.dual_emac)
 M> +		priv->slaves[priv->emac_port].open_stat = false;
 M>  	return 0;
 M>  }
 
 M> @@ -766,8 +893,7 @@ static netdev_tx_t cpsw_ndo_start_xmit(struct sk_buff *skb,
 
 M>  	skb_tx_timestamp(skb);
 
 M> -	ret = cpdma_chan_submit(priv->txch, skb, skb->data,
 M> -				skb->len, 0, GFP_KERNEL);
 M> +	ret = cpsw_tx_packet_submit(ndev, priv, skb);
 M>  	if (unlikely(ret != 0)) {
 M>  		cpsw_err(priv, tx_err, "desc submit failed\n");
 M>  		goto fail;
 M> @@ -836,9 +962,14 @@ static void cpsw_hwtstamp_v1(struct cpsw_priv *priv)
 
 M>  static void cpsw_hwtstamp_v2(struct cpsw_priv *priv)
 M>  {
 M> -	struct cpsw_slave *slave = &priv->slaves[priv->data.cpts_active_slave];
 M> +	struct cpsw_slave *slave;
 M>  	u32 ctrl, mtype;
 
 M> +	if (priv->data.dual_emac)
 M> +		slave = &priv->slaves[priv->emac_port];
 M> +	else
 M> +		slave = &priv->slaves[priv->data.cpts_active_slave];
 M> +
 M>  	ctrl = slave_read(slave, CPSW2_CONTROL);
 M>  	ctrl &= ~CTRL_ALL_TS_MASK;
 
 M> @@ -1124,6 +1255,7 @@ static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv,
 slave-> data	= data;
 slave-> regs	= regs + slave_reg_ofs;
 slave-> sliver	= regs + sliver_reg_ofs;
 M> +	slave->port_vlan = data->dual_emac_res_vlan;
 M>  }
 
 M>  static int cpsw_probe_dt(struct cpsw_platform_data *data,
 M> @@ -1204,6 +1336,9 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
 M>  	}
 data-> mac_control = prop;
 
 M> +	if (!of_property_read_u32(node, "dual_emac", &prop))
 M> +		data->dual_emac = prop;
 M> +
 M>  	/*
 M>  	 * Populate all the child nodes here...
 M>  	 */
 M> @@ -1237,6 +1372,18 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
 M>  		if (mac_addr)
 M>  			memcpy(slave_data->mac_addr, mac_addr, ETH_ALEN);
 
 M> +		if (data->dual_emac) {
 M> +			if (of_property_read_u32(node, "dual_emac_res_vlan",
 M> +						 &prop)) {
 M> +				pr_err("Missing dual_emac_res_vlan in DT.\n");
 M> +				slave_data->dual_emac_res_vlan = i+1;
 M> +				pr_err("Using %d as Reserved VLAN for %d slave\n",
 M> +				       slave_data->dual_emac_res_vlan, i);
 M> +			} else {
 M> +				slave_data->dual_emac_res_vlan = prop;
 M> +			}
 M> +		}
 M> +
 M>  		i++;
 M>  	}
 
 M> @@ -1247,6 +1394,79 @@ error_ret:
 M>  	return ret;
 M>  }
 
 M> +static int cpsw_probe_dual_emac(struct platform_device *pdev,
 M> +				struct cpsw_priv *priv)
 M> +{
 M> +	struct cpsw_platform_data	*data = &priv->data;
 M> +	struct net_device		*ndev;
 M> +	struct cpsw_priv		*priv_sl2;
 M> +	int ret = 0, i;
 M> +
 M> +	ndev = alloc_etherdev(sizeof(struct cpsw_priv));
 M> +	if (!ndev) {
 M> +		pr_err("cpsw: error allocating net_device\n");
 M> +		return -ENOMEM;
 M> +	}
 M> +
 M> +	priv_sl2 = netdev_priv(ndev);
 M> +	spin_lock_init(&priv_sl2->lock);
 M> +	priv_sl2->data = *data;
 M> +	priv_sl2->pdev = pdev;
 M> +	priv_sl2->ndev = ndev;
 M> +	priv_sl2->dev  = &ndev->dev;
 M> +	priv_sl2->msg_enable = netif_msg_init(debug_level, CPSW_DEBUG);
 M> +	priv_sl2->rx_packet_max = max(rx_packet_max, 128);
 M> +
 M> +	if (is_valid_ether_addr(data->slave_data[1].mac_addr)) {
 M> +		memcpy(priv_sl2->mac_addr, data->slave_data[1].mac_addr,
 M> +			ETH_ALEN);
 M> +		pr_info("cpsw: Detected MACID = %pM\n", priv_sl2->mac_addr);
 M> +	} else {
 M> +		random_ether_addr(priv_sl2->mac_addr);
 M> +		pr_info("cpsw: Random MACID = %pM\n", priv_sl2->mac_addr);
 M> +	}
 M> +	memcpy(ndev->dev_addr, priv_sl2->mac_addr, ETH_ALEN);
 M> +
 M> +	priv_sl2->slaves = priv->slaves;
 M> +	priv_sl2->clk = priv->clk;
 M> +
 M> +	priv_sl2->cpsw_res = priv->cpsw_res;
 M> +	priv_sl2->regs = priv->regs;
 M> +	priv_sl2->host_port = priv->host_port;
 M> +	priv_sl2->host_port_regs = priv->host_port_regs;
 M> +	priv_sl2->wr_regs = priv->wr_regs;
 M> +	priv_sl2->dma = priv->dma;
 M> +	priv_sl2->txch = priv->txch;
 M> +	priv_sl2->rxch = priv->rxch;
 M> +	priv_sl2->ale = priv->ale;
 M> +	priv_sl2->emac_port = 1;
 M> +	priv->slaves[1].ndev = ndev;
 M> +	priv_sl2->cpts = priv->cpts;
 M> +	priv_sl2->version = priv->version;
 M> +
 M> +	for (i = 0; i < priv->num_irqs; i++) {
 M> +		priv_sl2->irqs_table[i] = priv->irqs_table[i];
 M> +		priv_sl2->num_irqs = priv->num_irqs;
 M> +	}
 M> +
 M> +	ndev->features |= NETIF_F_HW_VLAN_FILTER;
 M> +
 M> +	ndev->netdev_ops = &cpsw_netdev_ops;
 M> +	SET_ETHTOOL_OPS(ndev, &cpsw_ethtool_ops);
 M> +	netif_napi_add(ndev, &priv_sl2->napi, cpsw_poll, CPSW_POLL_WEIGHT);
 M> +
 M> +	/* register the network device */
 M> +	SET_NETDEV_DEV(ndev, &pdev->dev);
 M> +	ret = register_netdev(ndev);
 M> +	if (ret) {
 M> +		pr_err("cpsw: error registering net device\n");
 M> +		free_netdev(ndev);
 M> +		ret = -ENODEV;
 M> +	}
 M> +
 M> +	return ret;
 M> +}
 M> +
 M>  static int cpsw_probe(struct platform_device *pdev)
 M>  {
 M>  	struct cpsw_platform_data	*data = pdev->dev.platform_data;
 M> @@ -1310,6 +1530,9 @@ static int cpsw_probe(struct platform_device *pdev)
 M>  	for (i = 0; i < data->slaves; i++)
 priv-> slaves[i].slave_num = i;
 
 M> +	priv->slaves[0].ndev = ndev;
 M> +	priv->emac_port = 0;
 M> +
 priv-> clk = clk_get(&pdev->dev, "fck");
 M>  	if (IS_ERR(priv->clk)) {
 M>  		dev_err(&pdev->dev, "fck is not found\n");
 M> @@ -1484,6 +1707,14 @@ static int cpsw_probe(struct platform_device *pdev)
 M>  	cpsw_notice(priv, probe, "initialized device (regs %x, irq %d)\n",
 priv-> cpsw_res->start, ndev->irq);
 
 M> +	if (priv->data.dual_emac) {
 M> +		ret = cpsw_probe_dual_emac(pdev, priv);
 M> +		if (ret) {
 M> +			cpsw_err(priv, probe, "error probe slave 2 emac interface\n");
 M> +			goto clean_irq_ret;
 M> +		}
 M> +	}
 M> +
 M>  	return 0;
 
 M>  clean_irq_ret:
 M> diff --git a/include/linux/platform_data/cpsw.h b/include/linux/platform_data/cpsw.h
 M> index e962cfd..798fb80 100644
 M> --- a/include/linux/platform_data/cpsw.h
 M> +++ b/include/linux/platform_data/cpsw.h
 M> @@ -21,6 +21,8 @@ struct cpsw_slave_data {
 M>  	char		phy_id[MII_BUS_ID_SIZE];
 M>  	int		phy_if;
 M>  	u8		mac_addr[ETH_ALEN];
 M> +	u16		dual_emac_res_vlan;	/* Reserved VLAN for DualEMAC */
 M> +
 M>  };
 
 M>  struct cpsw_platform_data {
 M> @@ -36,6 +38,7 @@ struct cpsw_platform_data {
 M>  	u32	rx_descs;	/* Number of Rx Descriptios */
 M>  	u32	mac_control;	/* Mac control register */
 M>  	u16	default_vlan;	/* Def VLAN for ALE lookup in VLAN aware mode*/
 M> +	bool	dual_emac;	/* Enable Dual EMAC mode */
 M>  };
 
 M>  #endif /* __CPSW_H__ */
 M> -- 
 M> 1.7.9.5

 M> --
 M> To unsubscribe from this list: send the line "unsubscribe netdev" in
 M> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
 M> More majordomo info at  http://vger.kernel.org/majordomo-info.html


-- 
Bye, Peter Korsgaard

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH 3/3] driver: net: ethernet: cpsw: dual emac interface implementation
@ 2013-02-18 13:36       ` Peter Korsgaard
  0 siblings, 0 replies; 48+ messages in thread
From: Peter Korsgaard @ 2013-02-18 13:36 UTC (permalink / raw)
  To: linux-arm-kernel

>>>>> "M" == Mugunthan V N <mugunthanvnm@ti.com> writes:

 M> The CPSW switch can act as Dual EMAC by segregating the switch ports
 M> using VLAN and port VLAN as per the TRM description in
 M> 14.3.2.10.2 Dual Mac Mode

 M> Following CPSW components will be common for both the interfaces.
 M> * Interrupt source is common for both eth interfaces
 M> * Interrupt pacing is common for both interfaces
 M> * Hardware statistics is common for all the ports
 M> * CPDMA is common for both eth interface
 M> * CPTS is common for both the interface and it should not be enabled on
 M>   both the interface as timestamping information doesn't contain port
 M>   information.

 M> Constrains
 M> * Reserved VID of One port should not be used in other interface which will
 M>   enable switching functionality
 M> * Same VID must not be used in both the interface which will enable switching
 M>   functionality

 M> Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
 M> ---
 M>  Documentation/devicetree/bindings/net/cpsw.txt |    2 +
 M>  drivers/net/ethernet/ti/cpsw.c                 |  335 ++++++++++++++++++++----
 M>  include/linux/platform_data/cpsw.h             |    3 +
 M>  3 files changed, 288 insertions(+), 52 deletions(-)

 M> diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt
 M> index 6ddd028..ecfdf75 100644
 M> --- a/Documentation/devicetree/bindings/net/cpsw.txt
 M> +++ b/Documentation/devicetree/bindings/net/cpsw.txt
 M> @@ -24,6 +24,8 @@ Required properties:
 M>  Optional properties:
 M>  - ti,hwmods		: Must be "cpgmac0"
 M>  - no_bd_ram		: Must be 0 or 1
 M> +- dual_emac		: Specifies Switch to act as Dual EMAC
 M> +- dual_emac_res_vlan	: Specifies VID to be used to segregate the ports

You forgot to CC devicetree-discuss. Properties normally use dashes (-)
instead of underscores (_). These properties are more about
configuration and not hardware.

It is not clear to me from the description that dual_emac is a boolean
(0/1). Shouldn't dual_emacs_res_vlan be a property of the slave?

It would also be good to update the example below with this.




 M>  Note: "ti,hwmods" field is used to fetch base address and irq
 M>  resources from TI, omap hwmod data base during device registration.
 M> diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
 M> index 4b964bb..4ceed6e 100644
 M> --- a/drivers/net/ethernet/ti/cpsw.c
 M> +++ b/drivers/net/ethernet/ti/cpsw.c
 M> @@ -122,6 +122,10 @@ do {								\
 M>  #define CPSW_VLAN_AWARE		BIT(1)
 M>  #define CPSW_ALE_VLAN_AWARE	1
 
 M> +#define CPSW_FIFO_NORMAL_MODE		(0 << 15)
 M> +#define CPSW_FIFO_DUAL_MAC_MODE		(1 << 15)
 M> +#define CPSW_FIFO_RATE_LIMIT_MODE	(2 << 15)
 M> +
 M>  #define cpsw_enable_irq(priv)	\
 M>  	do {			\
 M>  		u32 i;		\
 M> @@ -254,7 +258,7 @@ struct cpsw_ss_regs {
 M>  struct cpsw_host_regs {
 M>  	u32	max_blks;
 M>  	u32	blk_cnt;
 M> -	u32	flow_thresh;
 M> +	u32	tx_in_ctl;
 M>  	u32	port_vlan;
 M>  	u32	tx_pri_map;
 M>  	u32	cpdma_tx_pri_map;
 M> @@ -281,6 +285,9 @@ struct cpsw_slave {
 M>  	u32				mac_control;
 M>  	struct cpsw_slave_data		*data;
 M>  	struct phy_device		*phy;
 M> +	struct net_device		*ndev;
 M> +	u32				port_vlan;
 M> +	u32				open_stat;
 M>  };
 
 M>  static inline u32 slave_read(struct cpsw_slave *slave, u32 offset)
 M> @@ -320,15 +327,63 @@ struct cpsw_priv {
 M>  	u32 irqs_table[4];
 M>  	u32 num_irqs;
 M>  	struct cpts *cpts;
 M> +	u32 emac_port;
 M>  };
 
 M>  #define napi_to_priv(napi)	container_of(napi, struct cpsw_priv, napi)
 M> -#define for_each_slave(priv, func, arg...)			\
 M> -	do {							\
 M> -		int idx;					\
 M> -		for (idx = 0; idx < (priv)->data.slaves; idx++)	\
 M> -			(func)((priv)->slaves + idx, ##arg);	\
 M> +#define for_each_slave(priv, func, arg...)				\
 M> +	do {								\
 M> +		int idx;						\
 M> +		if (priv->data.dual_emac)				\
 M> +			(func)((priv)->slaves + priv->emac_port, ##arg);\
 M> +		else							\
 M> +			for (idx = 0; idx < (priv)->data.slaves; idx++)	\
 M> +				(func)((priv)->slaves + idx, ##arg);	\
 M> +	} while (0)
 M> +#define cpsw_get_slave_ndev(priv, __slave_no__)				\
 M> +	(priv->slaves[__slave_no__].ndev)
 M> +#define cpsw_get_slave_priv(priv, __slave_no__)				\
 M> +	((priv->slaves[__slave_no__].ndev) ?				\
 M> +		netdev_priv(priv->slaves[__slave_no__].ndev) : NULL)	\
 M> +
 M> +#define cpsw_dual_emac_src_port_detect(status, priv, ndev, skb)		\
 M> +	do {								\
 M> +		if (!priv->data.dual_emac)				\
 M> +			break;						\
 M> +		if (CPDMA_RX_SOURCE_PORT(status) == 1) {		\
 M> +			ndev = cpsw_get_slave_ndev(priv, 0);		\
 M> +			priv = netdev_priv(ndev);			\
 M> +			skb->dev = ndev;				\
 M> +		} else if (CPDMA_RX_SOURCE_PORT(status) == 2) {		\
 M> +			ndev = cpsw_get_slave_ndev(priv, 1);		\
 M> +			priv = netdev_priv(ndev);			\
 M> +			skb->dev = ndev;				\
 M> +		}							\
 M>  	} while (0)
 M> +#define cpsw_add_mcast(priv, addr)					\
 M> +	do {								\
 M> +		if (priv->data.dual_emac) {				\
 M> +			struct cpsw_slave *slave = priv->slaves +	\
 M> +						priv->emac_port;	\
 M> +			int slave_port = cpsw_get_slave_port(priv,	\
 M> +						slave->slave_num);	\
 M> +			cpsw_ale_add_mcast(priv->ale, addr,		\
 M> +				1 << slave_port | 1 << priv->host_port,	\
 M> +				ALE_VLAN, slave->port_vlan, 0);		\
 M> +		} else {						\
 M> +			cpsw_ale_add_mcast(priv->ale, addr,		\
 M> +				ALE_ALL_PORTS << priv->host_port,	\
 M> +				0, 0, 0);				\
 M> +		}							\
 M> +	} while (0)
 M> +
 M> +static inline int cpsw_get_slave_port(struct cpsw_priv *priv, u32 slave_num)
 M> +{
 M> +	if (priv->host_port == 0)
 M> +		return slave_num + 1;
 M> +	else
 M> +		return slave_num;
 M> +}
 
 M>  static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
 M>  {
 M> @@ -348,8 +403,7 @@ static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
 
 M>  		/* program multicast address list into ALE register */
 M>  		netdev_for_each_mc_addr(ha, ndev) {
 M> -			cpsw_ale_add_mcast(priv->ale, (u8 *)ha->addr,
 M> -				ALE_ALL_PORTS << priv->host_port, 0, 0, 0);
 M> +			cpsw_add_mcast(priv, (u8 *)ha->addr);
 M>  		}
 M>  	}
 M>  }
 M> @@ -396,6 +450,8 @@ void cpsw_rx_handler(void *token, int len, int status)
 M>  	struct cpsw_priv	*priv = netdev_priv(ndev);
 M>  	int			ret = 0;
 
 M> +	cpsw_dual_emac_src_port_detect(status, priv, ndev, skb);
 M> +
 M>  	/* free and bail if we are shutting down */
 M>  	if (unlikely(!netif_running(ndev)) ||
 M>  			unlikely(!netif_carrier_ok(ndev))) {
 M> @@ -437,18 +493,17 @@ static irqreturn_t cpsw_interrupt(int irq, void *dev_id)
 M>  		cpsw_intr_disable(priv);
 M>  		cpsw_disable_irq(priv);
 M>  		napi_schedule(&priv->napi);
 M> +	} else {
 M> +		priv = cpsw_get_slave_priv(priv, 1);
 M> +		if (likely(priv) && likely(netif_running(priv->ndev))) {
 M> +			cpsw_intr_disable(priv);
 M> +			cpsw_disable_irq(priv);
 M> +			napi_schedule(&priv->napi);
 M> +		}
 M>  	}
 M>  	return IRQ_HANDLED;
 M>  }
 
 M> -static inline int cpsw_get_slave_port(struct cpsw_priv *priv, u32 slave_num)
 M> -{
 M> -	if (priv->host_port == 0)
 M> -		return slave_num + 1;
 M> -	else
 M> -		return slave_num;
 M> -}
 M> -
 M>  static int cpsw_poll(struct napi_struct *napi, int budget)
 M>  {
 M>  	struct cpsw_priv	*priv = napi_to_priv(napi);
 M> @@ -566,6 +621,54 @@ static inline int __show_stat(char *buf, int maxlen, const char *name, u32 val)
 M>  				leader + strlen(name), val);
 M>  }
 
 M> +static int cpsw_common_res_usage_state(struct cpsw_priv *priv)
 M> +{
 M> +	u32 i;
 M> +	u32 usage_count = 0;
 M> +
 M> +	if (!priv->data.dual_emac)
 M> +		return 0;
 M> +
 M> +	for (i = 0; i < priv->data.slaves; i++)
 M> +		if (priv->slaves[i].open_stat)
 M> +			usage_count++;
 M> +
 M> +	return usage_count;
 M> +}
 M> +
 M> +static inline int cpsw_tx_packet_submit(struct net_device *ndev,
 M> +			struct cpsw_priv *priv, struct sk_buff *skb)
 M> +{
 M> +	if (!priv->data.dual_emac)
 M> +		return cpdma_chan_submit(priv->txch, skb, skb->data,
 M> +				  skb->len, 0, GFP_KERNEL);
 M> +
 M> +	if (ndev == cpsw_get_slave_ndev(priv, 0))
 M> +		return cpdma_chan_submit(priv->txch, skb, skb->data,
 M> +				  skb->len, 1, GFP_KERNEL);
 M> +	else
 M> +		return cpdma_chan_submit(priv->txch, skb, skb->data,
 M> +				  skb->len, 2, GFP_KERNEL);
 M> +}
 M> +
 M> +static inline void cpsw_add_dual_emac_def_ale_entries(
 M> +		struct cpsw_priv *priv, struct cpsw_slave *slave,
 M> +		u32 slave_port)
 M> +{
 M> +	u32 port_mask = 1 << slave_port | 1 << priv->host_port;
 M> +
 M> +	if (priv->version == CPSW_VERSION_1)
 M> +		slave_write(slave, slave->port_vlan, CPSW1_PORT_VLAN);
 M> +	else
 M> +		slave_write(slave, slave->port_vlan, CPSW2_PORT_VLAN);
 M> +	cpsw_ale_add_vlan(priv->ale, slave->port_vlan, port_mask,
 M> +			  port_mask, port_mask, 0);
 M> +	cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
 M> +			   port_mask, ALE_VLAN, slave->port_vlan, 0);
 M> +	cpsw_ale_add_ucast(priv->ale, priv->mac_addr,
 M> +		priv->host_port, ALE_VLAN, slave->port_vlan);
 M> +}
 M> +
 M>  static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
 M>  {
 M>  	char name[32];
 M> @@ -595,8 +698,11 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
 
 M>  	slave_port = cpsw_get_slave_port(priv, slave->slave_num);
 
 M> -	cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
 M> -			   1 << slave_port, 0, 0, ALE_MCAST_FWD_2);
 M> +	if (priv->data.dual_emac)
 M> +		cpsw_add_dual_emac_def_ale_entries(priv, slave, slave_port);
 M> +	else
 M> +		cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
 M> +				   1 << slave_port, 0, 0, ALE_MCAST_FWD_2);
 
 slave-> phy = phy_connect(priv->ndev, slave->data->phy_id,
 M>  				 &cpsw_adjust_link, slave->data->phy_if);
 M> @@ -634,6 +740,7 @@ static inline void cpsw_add_default_vlan(struct cpsw_priv *priv)
 M>  static void cpsw_init_host_port(struct cpsw_priv *priv)
 M>  {
 M>  	u32 control_reg;
 M> +	u32 fifo_mode;
 
 M>  	/* soft reset the controller and initialize ale */
 M>  	soft_reset("cpsw", &priv->regs->soft_reset);
 M> @@ -645,6 +752,9 @@ static void cpsw_init_host_port(struct cpsw_priv *priv)
 M>  	control_reg = readl(&priv->regs->control);
 M>  	control_reg |= CPSW_VLAN_AWARE;
 M>  	writel(control_reg, &priv->regs->control);
 M> +	fifo_mode = (priv->data.dual_emac) ? CPSW_FIFO_DUAL_MAC_MODE :
 M> +		     CPSW_FIFO_NORMAL_MODE;
 M> +	writel(fifo_mode, &priv->host_port_regs->tx_in_ctl);
 
 M>  	/* setup host port priority mapping */
 M>  	__raw_writel(CPDMA_TX_PRIORITY_MAP,
 M> @@ -654,9 +764,12 @@ static void cpsw_init_host_port(struct cpsw_priv *priv)
 M>  	cpsw_ale_control_set(priv->ale, priv->host_port,
 M>  			     ALE_PORT_STATE, ALE_PORT_STATE_FORWARD);
 
 M> -	cpsw_ale_add_ucast(priv->ale, priv->mac_addr, priv->host_port, 0, 0);
 M> -	cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
 M> -			   1 << priv->host_port, 0, 0, ALE_MCAST_FWD_2);
 M> +	if (!priv->data.dual_emac) {
 M> +		cpsw_ale_add_ucast(priv->ale, priv->mac_addr, priv->host_port,
 M> +				   0, 0);
 M> +		cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
 M> +				   1 << priv->host_port, 0, 0, ALE_MCAST_FWD_2);
 M> +	}
 M>  }
 
 M>  static int cpsw_ndo_open(struct net_device *ndev)
 M> @@ -665,7 +778,8 @@ static int cpsw_ndo_open(struct net_device *ndev)
 M>  	int i, ret;
 M>  	u32 reg;
 
 M> -	cpsw_intr_disable(priv);
 M> +	if (!cpsw_common_res_usage_state(priv))
 M> +		cpsw_intr_disable(priv);
 M>  	netif_carrier_off(ndev);
 
 M>  	pm_runtime_get_sync(&priv->pdev->dev);
 M> @@ -677,46 +791,54 @@ static int cpsw_ndo_open(struct net_device *ndev)
 M>  		 CPSW_RTL_VERSION(reg));
 
 M>  	/* initialize host and slave ports */
 M> -	cpsw_init_host_port(priv);
 M> +	if (!cpsw_common_res_usage_state(priv))
 M> +		cpsw_init_host_port(priv);
 M>  	for_each_slave(priv, cpsw_slave_open, priv);
 
 M>  	/* Add default VLAN */
 M> -	cpsw_add_default_vlan(priv);
 M> +	if (!priv->data.dual_emac)
 M> +		cpsw_add_default_vlan(priv);
 
 M> -	/* setup tx dma to fixed prio and zero offset */
 M> -	cpdma_control_set(priv->dma, CPDMA_TX_PRIO_FIXED, 1);
 M> -	cpdma_control_set(priv->dma, CPDMA_RX_BUFFER_OFFSET, 0);
 M> +	if (!cpsw_common_res_usage_state(priv)) {
 M> +		/* setup tx dma to fixed prio and zero offset */
 M> +		cpdma_control_set(priv->dma, CPDMA_TX_PRIO_FIXED, 1);
 M> +		cpdma_control_set(priv->dma, CPDMA_RX_BUFFER_OFFSET, 0);
 
 M> -	/* disable priority elevation and enable statistics on all ports */
 M> -	__raw_writel(0, &priv->regs->ptype);
 M> +		/* disable priority elevation */
 M> +		__raw_writel(0, &priv->regs->ptype);
 
 M> -	/* enable statistics collection only on the host port */
 M> -	__raw_writel(0x7, &priv->regs->stat_port_en);
 M> +		/* enable statistics collection only on all ports */
 M> +		__raw_writel(0x7, &priv->regs->stat_port_en);
 
 M> -	if (WARN_ON(!priv->data.rx_descs))
 M> -		priv->data.rx_descs = 128;
 M> +		if (WARN_ON(!priv->data.rx_descs))
 M> +			priv->data.rx_descs = 128;
 
 M> -	for (i = 0; i < priv->data.rx_descs; i++) {
 M> -		struct sk_buff *skb;
 M> +		for (i = 0; i < priv->data.rx_descs; i++) {
 M> +			struct sk_buff *skb;
 
 M> -		ret = -ENOMEM;
 M> -		skb = netdev_alloc_skb_ip_align(priv->ndev,
 M> -						priv->rx_packet_max);
 M> -		if (!skb)
 M> -			break;
 M> -		ret = cpdma_chan_submit(priv->rxch, skb, skb->data,
 M> +			ret = -ENOMEM;
 M> +			skb = netdev_alloc_skb_ip_align(priv->ndev,
 M> +							priv->rx_packet_max);
 M> +			if (!skb)
 M> +				break;
 M> +			ret = cpdma_chan_submit(priv->rxch, skb, skb->data,
 M>  					skb_tailroom(skb), 0, GFP_KERNEL);
 M> -		if (WARN_ON(ret < 0))
 M> -			break;
 M> +			if (WARN_ON(ret < 0))
 M> +				break;
 M> +		}
 M> +		/* continue even if we didn't manage to submit all
 M> +		 * receive descs
 M> +		 */
 M> +		cpsw_info(priv, ifup, "submitted %d rx descriptors\n", i);
 M>  	}
 M> -	/* continue even if we didn't manage to submit all receive descs */
 M> -	cpsw_info(priv, ifup, "submitted %d rx descriptors\n", i);
 
 M>  	cpdma_ctlr_start(priv->dma);
 M>  	cpsw_intr_enable(priv);
 M>  	napi_enable(&priv->napi);
 M>  	cpdma_ctlr_eoi(priv->dma);
 
 M> +	if (priv->data.dual_emac)
 M> +		priv->slaves[priv->emac_port].open_stat = true;
 M>  	return 0;
 M>  }
 
 M> @@ -737,12 +859,17 @@ static int cpsw_ndo_stop(struct net_device *ndev)
 M>  	netif_stop_queue(priv->ndev);
 M>  	napi_disable(&priv->napi);
 M>  	netif_carrier_off(priv->ndev);
 M> -	cpsw_intr_disable(priv);
 M> -	cpdma_ctlr_int_ctrl(priv->dma, false);
 M> -	cpdma_ctlr_stop(priv->dma);
 M> -	cpsw_ale_stop(priv->ale);
 M> +
 M> +	if (cpsw_common_res_usage_state(priv) <= 1) {
 M> +		cpsw_intr_disable(priv);
 M> +		cpdma_ctlr_int_ctrl(priv->dma, false);
 M> +		cpdma_ctlr_stop(priv->dma);
 M> +		cpsw_ale_stop(priv->ale);
 M> +	}
 M>  	for_each_slave(priv, cpsw_slave_stop, priv);
 M>  	pm_runtime_put_sync(&priv->pdev->dev);
 M> +	if (priv->data.dual_emac)
 M> +		priv->slaves[priv->emac_port].open_stat = false;
 M>  	return 0;
 M>  }
 
 M> @@ -766,8 +893,7 @@ static netdev_tx_t cpsw_ndo_start_xmit(struct sk_buff *skb,
 
 M>  	skb_tx_timestamp(skb);
 
 M> -	ret = cpdma_chan_submit(priv->txch, skb, skb->data,
 M> -				skb->len, 0, GFP_KERNEL);
 M> +	ret = cpsw_tx_packet_submit(ndev, priv, skb);
 M>  	if (unlikely(ret != 0)) {
 M>  		cpsw_err(priv, tx_err, "desc submit failed\n");
 M>  		goto fail;
 M> @@ -836,9 +962,14 @@ static void cpsw_hwtstamp_v1(struct cpsw_priv *priv)
 
 M>  static void cpsw_hwtstamp_v2(struct cpsw_priv *priv)
 M>  {
 M> -	struct cpsw_slave *slave = &priv->slaves[priv->data.cpts_active_slave];
 M> +	struct cpsw_slave *slave;
 M>  	u32 ctrl, mtype;
 
 M> +	if (priv->data.dual_emac)
 M> +		slave = &priv->slaves[priv->emac_port];
 M> +	else
 M> +		slave = &priv->slaves[priv->data.cpts_active_slave];
 M> +
 M>  	ctrl = slave_read(slave, CPSW2_CONTROL);
 M>  	ctrl &= ~CTRL_ALL_TS_MASK;
 
 M> @@ -1124,6 +1255,7 @@ static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv,
 slave-> data	= data;
 slave-> regs	= regs + slave_reg_ofs;
 slave-> sliver	= regs + sliver_reg_ofs;
 M> +	slave->port_vlan = data->dual_emac_res_vlan;
 M>  }
 
 M>  static int cpsw_probe_dt(struct cpsw_platform_data *data,
 M> @@ -1204,6 +1336,9 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
 M>  	}
 data-> mac_control = prop;
 
 M> +	if (!of_property_read_u32(node, "dual_emac", &prop))
 M> +		data->dual_emac = prop;
 M> +
 M>  	/*
 M>  	 * Populate all the child nodes here...
 M>  	 */
 M> @@ -1237,6 +1372,18 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
 M>  		if (mac_addr)
 M>  			memcpy(slave_data->mac_addr, mac_addr, ETH_ALEN);
 
 M> +		if (data->dual_emac) {
 M> +			if (of_property_read_u32(node, "dual_emac_res_vlan",
 M> +						 &prop)) {
 M> +				pr_err("Missing dual_emac_res_vlan in DT.\n");
 M> +				slave_data->dual_emac_res_vlan = i+1;
 M> +				pr_err("Using %d as Reserved VLAN for %d slave\n",
 M> +				       slave_data->dual_emac_res_vlan, i);
 M> +			} else {
 M> +				slave_data->dual_emac_res_vlan = prop;
 M> +			}
 M> +		}
 M> +
 M>  		i++;
 M>  	}
 
 M> @@ -1247,6 +1394,79 @@ error_ret:
 M>  	return ret;
 M>  }
 
 M> +static int cpsw_probe_dual_emac(struct platform_device *pdev,
 M> +				struct cpsw_priv *priv)
 M> +{
 M> +	struct cpsw_platform_data	*data = &priv->data;
 M> +	struct net_device		*ndev;
 M> +	struct cpsw_priv		*priv_sl2;
 M> +	int ret = 0, i;
 M> +
 M> +	ndev = alloc_etherdev(sizeof(struct cpsw_priv));
 M> +	if (!ndev) {
 M> +		pr_err("cpsw: error allocating net_device\n");
 M> +		return -ENOMEM;
 M> +	}
 M> +
 M> +	priv_sl2 = netdev_priv(ndev);
 M> +	spin_lock_init(&priv_sl2->lock);
 M> +	priv_sl2->data = *data;
 M> +	priv_sl2->pdev = pdev;
 M> +	priv_sl2->ndev = ndev;
 M> +	priv_sl2->dev  = &ndev->dev;
 M> +	priv_sl2->msg_enable = netif_msg_init(debug_level, CPSW_DEBUG);
 M> +	priv_sl2->rx_packet_max = max(rx_packet_max, 128);
 M> +
 M> +	if (is_valid_ether_addr(data->slave_data[1].mac_addr)) {
 M> +		memcpy(priv_sl2->mac_addr, data->slave_data[1].mac_addr,
 M> +			ETH_ALEN);
 M> +		pr_info("cpsw: Detected MACID = %pM\n", priv_sl2->mac_addr);
 M> +	} else {
 M> +		random_ether_addr(priv_sl2->mac_addr);
 M> +		pr_info("cpsw: Random MACID = %pM\n", priv_sl2->mac_addr);
 M> +	}
 M> +	memcpy(ndev->dev_addr, priv_sl2->mac_addr, ETH_ALEN);
 M> +
 M> +	priv_sl2->slaves = priv->slaves;
 M> +	priv_sl2->clk = priv->clk;
 M> +
 M> +	priv_sl2->cpsw_res = priv->cpsw_res;
 M> +	priv_sl2->regs = priv->regs;
 M> +	priv_sl2->host_port = priv->host_port;
 M> +	priv_sl2->host_port_regs = priv->host_port_regs;
 M> +	priv_sl2->wr_regs = priv->wr_regs;
 M> +	priv_sl2->dma = priv->dma;
 M> +	priv_sl2->txch = priv->txch;
 M> +	priv_sl2->rxch = priv->rxch;
 M> +	priv_sl2->ale = priv->ale;
 M> +	priv_sl2->emac_port = 1;
 M> +	priv->slaves[1].ndev = ndev;
 M> +	priv_sl2->cpts = priv->cpts;
 M> +	priv_sl2->version = priv->version;
 M> +
 M> +	for (i = 0; i < priv->num_irqs; i++) {
 M> +		priv_sl2->irqs_table[i] = priv->irqs_table[i];
 M> +		priv_sl2->num_irqs = priv->num_irqs;
 M> +	}
 M> +
 M> +	ndev->features |= NETIF_F_HW_VLAN_FILTER;
 M> +
 M> +	ndev->netdev_ops = &cpsw_netdev_ops;
 M> +	SET_ETHTOOL_OPS(ndev, &cpsw_ethtool_ops);
 M> +	netif_napi_add(ndev, &priv_sl2->napi, cpsw_poll, CPSW_POLL_WEIGHT);
 M> +
 M> +	/* register the network device */
 M> +	SET_NETDEV_DEV(ndev, &pdev->dev);
 M> +	ret = register_netdev(ndev);
 M> +	if (ret) {
 M> +		pr_err("cpsw: error registering net device\n");
 M> +		free_netdev(ndev);
 M> +		ret = -ENODEV;
 M> +	}
 M> +
 M> +	return ret;
 M> +}
 M> +
 M>  static int cpsw_probe(struct platform_device *pdev)
 M>  {
 M>  	struct cpsw_platform_data	*data = pdev->dev.platform_data;
 M> @@ -1310,6 +1530,9 @@ static int cpsw_probe(struct platform_device *pdev)
 M>  	for (i = 0; i < data->slaves; i++)
 priv-> slaves[i].slave_num = i;
 
 M> +	priv->slaves[0].ndev = ndev;
 M> +	priv->emac_port = 0;
 M> +
 priv-> clk = clk_get(&pdev->dev, "fck");
 M>  	if (IS_ERR(priv->clk)) {
 M>  		dev_err(&pdev->dev, "fck is not found\n");
 M> @@ -1484,6 +1707,14 @@ static int cpsw_probe(struct platform_device *pdev)
 M>  	cpsw_notice(priv, probe, "initialized device (regs %x, irq %d)\n",
 priv-> cpsw_res->start, ndev->irq);
 
 M> +	if (priv->data.dual_emac) {
 M> +		ret = cpsw_probe_dual_emac(pdev, priv);
 M> +		if (ret) {
 M> +			cpsw_err(priv, probe, "error probe slave 2 emac interface\n");
 M> +			goto clean_irq_ret;
 M> +		}
 M> +	}
 M> +
 M>  	return 0;
 
 M>  clean_irq_ret:
 M> diff --git a/include/linux/platform_data/cpsw.h b/include/linux/platform_data/cpsw.h
 M> index e962cfd..798fb80 100644
 M> --- a/include/linux/platform_data/cpsw.h
 M> +++ b/include/linux/platform_data/cpsw.h
 M> @@ -21,6 +21,8 @@ struct cpsw_slave_data {
 M>  	char		phy_id[MII_BUS_ID_SIZE];
 M>  	int		phy_if;
 M>  	u8		mac_addr[ETH_ALEN];
 M> +	u16		dual_emac_res_vlan;	/* Reserved VLAN for DualEMAC */
 M> +
 M>  };
 
 M>  struct cpsw_platform_data {
 M> @@ -36,6 +38,7 @@ struct cpsw_platform_data {
 M>  	u32	rx_descs;	/* Number of Rx Descriptios */
 M>  	u32	mac_control;	/* Mac control register */
 M>  	u16	default_vlan;	/* Def VLAN for ALE lookup in VLAN aware mode*/
 M> +	bool	dual_emac;	/* Enable Dual EMAC mode */
 M>  };
 
 M>  #endif /* __CPSW_H__ */
 M> -- 
 M> 1.7.9.5

 M> --
 M> To unsubscribe from this list: send the line "unsubscribe netdev" in
 M> the body of a message to majordomo at vger.kernel.org
 M> More majordomo info at  http://vger.kernel.org/majordomo-info.html


-- 
Bye, Peter Korsgaard

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 3/3] driver: net: ethernet: cpsw: dual emac interface implementation
  2013-02-18 13:36       ` Peter Korsgaard
@ 2013-02-18 15:10           ` Mugunthan V N
  -1 siblings, 0 replies; 48+ messages in thread
From: Mugunthan V N @ 2013-02-18 15:10 UTC (permalink / raw)
  To: Peter Korsgaard
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-omap-u79uwXL29TY76Z2rM5mHXA, davem-fT/PcQaiUtIeIZ0/mPfg9Q,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

On 2/18/2013 7:06 PM, Peter Korsgaard wrote:
>>>>>> "M" == Mugunthan V N <mugunthanvnm-l0cyMroinI0@public.gmane.org> writes:
>   M> The CPSW switch can act as Dual EMAC by segregating the switch ports
>   M> using VLAN and port VLAN as per the TRM description in
>   M> 14.3.2.10.2 Dual Mac Mode
>
>   M> Following CPSW components will be common for both the interfaces.
>   M> * Interrupt source is common for both eth interfaces
>   M> * Interrupt pacing is common for both interfaces
>   M> * Hardware statistics is common for all the ports
>   M> * CPDMA is common for both eth interface
>   M> * CPTS is common for both the interface and it should not be enabled on
>   M>   both the interface as timestamping information doesn't contain port
>   M>   information.
>
>   M> Constrains
>   M> * Reserved VID of One port should not be used in other interface which will
>   M>   enable switching functionality
>   M> * Same VID must not be used in both the interface which will enable switching
>   M>   functionality
>
>   M> Signed-off-by: Mugunthan V N <mugunthanvnm-l0cyMroinI0@public.gmane.org>
>   M> ---
>   M>  Documentation/devicetree/bindings/net/cpsw.txt |    2 +
>   M>  drivers/net/ethernet/ti/cpsw.c                 |  335 ++++++++++++++++++++----
>   M>  include/linux/platform_data/cpsw.h             |    3 +
>   M>  3 files changed, 288 insertions(+), 52 deletions(-)
>
>   M> diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt
>   M> index 6ddd028..ecfdf75 100644
>   M> --- a/Documentation/devicetree/bindings/net/cpsw.txt
>   M> +++ b/Documentation/devicetree/bindings/net/cpsw.txt
>   M> @@ -24,6 +24,8 @@ Required properties:
>   M>  Optional properties:
>   M>  - ti,hwmods		: Must be "cpgmac0"
>   M>  - no_bd_ram		: Must be 0 or 1
>   M> +- dual_emac		: Specifies Switch to act as Dual EMAC
>   M> +- dual_emac_res_vlan	: Specifies VID to be used to segregate the ports
>
> You forgot to CC devicetree-discuss. Properties normally use dashes (-)
> instead of underscores (_). These properties are more about
> configuration and not hardware.
>
> It is not clear to me from the description that dual_emac is a boolean
> (0/1). Shouldn't dual_emacs_res_vlan be a property of the slave?
>
> It would also be good to update the example below with this.
Since the series is already applied in net-next tree, i will submit a 
patch with incorporating
the above comments. Will add devicetree-discuss in my future patches.

Regards
Mugunthan V N

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH 3/3] driver: net: ethernet: cpsw: dual emac interface implementation
@ 2013-02-18 15:10           ` Mugunthan V N
  0 siblings, 0 replies; 48+ messages in thread
From: Mugunthan V N @ 2013-02-18 15:10 UTC (permalink / raw)
  To: linux-arm-kernel

On 2/18/2013 7:06 PM, Peter Korsgaard wrote:
>>>>>> "M" == Mugunthan V N <mugunthanvnm@ti.com> writes:
>   M> The CPSW switch can act as Dual EMAC by segregating the switch ports
>   M> using VLAN and port VLAN as per the TRM description in
>   M> 14.3.2.10.2 Dual Mac Mode
>
>   M> Following CPSW components will be common for both the interfaces.
>   M> * Interrupt source is common for both eth interfaces
>   M> * Interrupt pacing is common for both interfaces
>   M> * Hardware statistics is common for all the ports
>   M> * CPDMA is common for both eth interface
>   M> * CPTS is common for both the interface and it should not be enabled on
>   M>   both the interface as timestamping information doesn't contain port
>   M>   information.
>
>   M> Constrains
>   M> * Reserved VID of One port should not be used in other interface which will
>   M>   enable switching functionality
>   M> * Same VID must not be used in both the interface which will enable switching
>   M>   functionality
>
>   M> Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
>   M> ---
>   M>  Documentation/devicetree/bindings/net/cpsw.txt |    2 +
>   M>  drivers/net/ethernet/ti/cpsw.c                 |  335 ++++++++++++++++++++----
>   M>  include/linux/platform_data/cpsw.h             |    3 +
>   M>  3 files changed, 288 insertions(+), 52 deletions(-)
>
>   M> diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt
>   M> index 6ddd028..ecfdf75 100644
>   M> --- a/Documentation/devicetree/bindings/net/cpsw.txt
>   M> +++ b/Documentation/devicetree/bindings/net/cpsw.txt
>   M> @@ -24,6 +24,8 @@ Required properties:
>   M>  Optional properties:
>   M>  - ti,hwmods		: Must be "cpgmac0"
>   M>  - no_bd_ram		: Must be 0 or 1
>   M> +- dual_emac		: Specifies Switch to act as Dual EMAC
>   M> +- dual_emac_res_vlan	: Specifies VID to be used to segregate the ports
>
> You forgot to CC devicetree-discuss. Properties normally use dashes (-)
> instead of underscores (_). These properties are more about
> configuration and not hardware.
>
> It is not clear to me from the description that dual_emac is a boolean
> (0/1). Shouldn't dual_emacs_res_vlan be a property of the slave?
>
> It would also be good to update the example below with this.
Since the series is already applied in net-next tree, i will submit a 
patch with incorporating
the above comments. Will add devicetree-discuss in my future patches.

Regards
Mugunthan V N

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 0/3] Dual EMAC mode implementation of CPSW
  2013-02-12 21:15   ` David Miller
@ 2013-04-12  9:14     ` Mark Jackson
  -1 siblings, 0 replies; 48+ messages in thread
From: Mark Jackson @ 2013-04-12  9:14 UTC (permalink / raw)
  To: David Miller; +Cc: mugunthanvnm, netdev, linux-arm-kernel, linux-omap

On 12/02/13 21:15, David Miller wrote:
> From: Mugunthan V N <mugunthanvnm@ti.com>
> Date: Tue, 12 Feb 2013 01:22:17 +0530
> 
>> This patch series implements Dual EMAC mode implementation of CPSW
>> which acts as two standalone EMAC by segregating the switch using VIDs
>> and port VLAN
>>
>> Mugunthan V N (3):
>>   driver: net: ethernet: davinci_cpdma: add support for directed packet
>>     and source port detection
>>   driver: net: ethernet: cpsw: make cpts as pointer
>>   driver: net: ethernet: cpsw: dual emac interface implementation
> 
> Series applied.

I can see that this series is now in the mainline kernel, but can anyone
give me some pointers on how to use it ?

First, I'd like to check that it's achieving what I think it does ...
namely to be able to access both eth0 and eth1 as separate Ethernet ports ?

If this assumption is correct, can anyone guide me as to how to setup my
dts file to allow the kernel to see both ports ?

If have been trying to get it going (see my posting [1]), but to no avail.

Any help would be greatly appreciated !!

[1] http://www.spinics.net/lists/linux-omap/msg89920.html

Regards
Mark JACKSON

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH 0/3] Dual EMAC mode implementation of CPSW
@ 2013-04-12  9:14     ` Mark Jackson
  0 siblings, 0 replies; 48+ messages in thread
From: Mark Jackson @ 2013-04-12  9:14 UTC (permalink / raw)
  To: linux-arm-kernel

On 12/02/13 21:15, David Miller wrote:
> From: Mugunthan V N <mugunthanvnm@ti.com>
> Date: Tue, 12 Feb 2013 01:22:17 +0530
> 
>> This patch series implements Dual EMAC mode implementation of CPSW
>> which acts as two standalone EMAC by segregating the switch using VIDs
>> and port VLAN
>>
>> Mugunthan V N (3):
>>   driver: net: ethernet: davinci_cpdma: add support for directed packet
>>     and source port detection
>>   driver: net: ethernet: cpsw: make cpts as pointer
>>   driver: net: ethernet: cpsw: dual emac interface implementation
> 
> Series applied.

I can see that this series is now in the mainline kernel, but can anyone
give me some pointers on how to use it ?

First, I'd like to check that it's achieving what I think it does ...
namely to be able to access both eth0 and eth1 as separate Ethernet ports ?

If this assumption is correct, can anyone guide me as to how to setup my
dts file to allow the kernel to see both ports ?

If have been trying to get it going (see my posting [1]), but to no avail.

Any help would be greatly appreciated !!

[1] http://www.spinics.net/lists/linux-omap/msg89920.html

Regards
Mark JACKSON

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 0/3] Dual EMAC mode implementation of CPSW
  2013-02-11 19:52 ` Mugunthan V N
@ 2013-04-14 19:16   ` Mark Jackson
  -1 siblings, 0 replies; 48+ messages in thread
From: Mark Jackson @ 2013-04-14 19:16 UTC (permalink / raw)
  To: Mugunthan V N; +Cc: netdev, davem, linux-arm-kernel, linux-omap

On 11/02/13 19:52, Mugunthan V N wrote:
> This patch series implements Dual EMAC mode implementation of CPSW
> which acts as two standalone EMAC by segregating the switch using VIDs
> and port VLAN
>
> Mugunthan V N (3):
>    driver: net: ethernet: davinci_cpdma: add support for directed packet
>      and source port detection
>    driver: net: ethernet: cpsw: make cpts as pointer
>    driver: net: ethernet: cpsw: dual emac interface implementation
>
>   Documentation/devicetree/bindings/net/cpsw.txt |    2 +
>   drivers/net/ethernet/ti/cpsw.c                 |  387 +++++++++++++++++++-----
>   drivers/net/ethernet/ti/davinci_cpdma.c        |   17 +-
>   drivers/net/ethernet/ti/davinci_cpdma.h        |    4 +-
>   drivers/net/ethernet/ti/davinci_emac.c         |    6 +-
>   include/linux/platform_data/cpsw.h             |    3 +
>   6 files changed, 338 insertions(+), 81 deletions(-)

I'm trying to get dual emac mode working, but I'm only having partial 
success.  We have a custom AM335x board with dual LAN8710 PYHs, but the 
basic design is based on the BeagleBone board.

I have the following in my .dts file:-

mac: ethernet@4a100000 {
	dual_emac = <1>;
	cpsw_emac0: slave@4a100200 {
		dual_emac_res_vlan = <1>;
	};
	cpsw_emac1: slave@4a100300 {
		dual_emac_res_vlan = <2>;
	};
};

When I boot my board (across nfs via eth1):-

(a) the kernel is loaded (via tftp under U-Boot)
(b) the kernel mounts the nfsroot
(c) my init scripts are run (e.g. dropbear)
(d) the shell prompt appears

So far so good, but when I then try any shell command (e.g. "ps") the 
nfs link just hangs.

Below is an extract from the boot messages:-

[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Linux version 3.9.0-rc6-00186-g5b55d70-dirty 
(mpfj@mpfj-nanobone) (gcc version 4.7.2 (Buildroot 
2013.02-00154-g851ceaa) ) #19 Sun Apr 14 19:50:21 BST 2013
[    0.000000] CPU: ARMv7 Processor [413fc082] revision 2 (ARMv7), 
cr=10c53c7d
[    0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing 
instruction cache
[    0.000000] Machine: Generic AM33XX (Flattened Device Tree), model: 
Newflow AM335x NanoBone
[    0.000000] Memory policy: ECC disabled, Data cache writeback
[    0.000000] CPU: All CPU(s) started in SVC mode.
[    0.000000] AM335X ES1.0 (neon )
[    0.000000] Built 1 zonelists in Zone order, mobility grouping on. 
Total pages: 64768
[    0.000000] Kernel command line: root=/dev/nfs 
nfsroot=10.1.0.111:/tftpboot/nanobone/rootfs rw 
ip=10.1.0.199:10.1.0.111:10.1.0.1:255.255.0.0::eth1:off console=ttyO0,115200
...
[    1.424977] davinci_mdio 4a101000.mdio: davinci mdio revision 1.6
[    1.431443] davinci_mdio 4a101000.mdio: detected phy mask fffffffc
[    1.440939] libphy: 4a101000.mdio: probed
[    1.445266] davinci_mdio 4a101000.mdio: phy[0]: device 
4a101000.mdio:00, driver SMSC LAN8710/LAN8720
[    1.454962] davinci_mdio 4a101000.mdio: phy[1]: device 
4a101000.mdio:01, driver SMSC LAN8710/LAN8720
[    1.465059] Random MACID = a2:3f:fb:2c:47:d9
[    1.472276] cpsw: Random MACID = ae:d5:c0:c0:27:03
[    1.480588] rtc-ds1307 0-0068: setting system clock to 2013-04-14 
19:59:52 UTC (1365969592)
[    1.491543] net eth1: initializing cpsw version 1.12 (0)
[    1.516965] net eth1: phy found : id is : 0x7c0f1
[    4.595479] libphy: 4a101000.mdio:01 - Link is Up - 100/Full
[    4.625872] IP-Config: Complete:
[    4.629307]      device=eth1, hwaddr=ae:d5:c0:c0:27:03, 
ipaddr=10.1.0.199, mask=255.255.0.0, gw=10.1.0.1
[    4.639365]      host=10.1.0.199, domain=, nis-domain=(none)
[    4.645359]      bootserver=10.1.0.111, rootserver=10.1.0.111, rootpath=
[    4.674219] VFS: Mounted root (nfs filesystem) on device 0:12.
[    4.682438] devtmpfs: mounted
[    4.686042] Freeing init memory: 196K
Starting logging: OK
Initializing random number generator... done.
Starting network...
ip: RTNETLINK answers: File exists
[    5.340677] net eth0: initializing cpsw version 1.12 (0)
[    5.366463] net eth0: phy found : id is : 0x7c0f1
ip: RTNETLINK answers: File exists
ip: RTNETLINK answers: File exists
ip: RTNETLINK answers: File exists
Starting dropbear sshd: OK

Welcome to Buildroot
nanobone login: root
Password:
# ps
[   18.845266] nfs: server 10.1.0.111 not responding, still trying

At this point, I can disconnect my network cable from eth1 and connect 
to eth0, and back again which shows the PYHs appear to be detecting the 
link up/down status of each port.

[  562.675229] libphy: 4a101000.mdio:01 - Link is Down
[  567.885586] libphy: 4a101000.mdio:00 - Link is Up - 100/Full
[  571.965156] libphy: 4a101000.mdio:00 - Link is Down
[  575.014943] nfs: server 10.1.0.111 not responding, still trying
[  576.635412] libphy: 4a101000.mdio:01 - Link is Up - 100/Full
[  579.426051] nfs: server 10.1.0.111 OK

Notice that at the end, the nfs link appears to come back "ok", but the 
"ps" command never completes.

Any ideas of what's going on ?

Cheers
Mark J.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH 0/3] Dual EMAC mode implementation of CPSW
@ 2013-04-14 19:16   ` Mark Jackson
  0 siblings, 0 replies; 48+ messages in thread
From: Mark Jackson @ 2013-04-14 19:16 UTC (permalink / raw)
  To: linux-arm-kernel

On 11/02/13 19:52, Mugunthan V N wrote:
> This patch series implements Dual EMAC mode implementation of CPSW
> which acts as two standalone EMAC by segregating the switch using VIDs
> and port VLAN
>
> Mugunthan V N (3):
>    driver: net: ethernet: davinci_cpdma: add support for directed packet
>      and source port detection
>    driver: net: ethernet: cpsw: make cpts as pointer
>    driver: net: ethernet: cpsw: dual emac interface implementation
>
>   Documentation/devicetree/bindings/net/cpsw.txt |    2 +
>   drivers/net/ethernet/ti/cpsw.c                 |  387 +++++++++++++++++++-----
>   drivers/net/ethernet/ti/davinci_cpdma.c        |   17 +-
>   drivers/net/ethernet/ti/davinci_cpdma.h        |    4 +-
>   drivers/net/ethernet/ti/davinci_emac.c         |    6 +-
>   include/linux/platform_data/cpsw.h             |    3 +
>   6 files changed, 338 insertions(+), 81 deletions(-)

I'm trying to get dual emac mode working, but I'm only having partial 
success.  We have a custom AM335x board with dual LAN8710 PYHs, but the 
basic design is based on the BeagleBone board.

I have the following in my .dts file:-

mac: ethernet at 4a100000 {
	dual_emac = <1>;
	cpsw_emac0: slave at 4a100200 {
		dual_emac_res_vlan = <1>;
	};
	cpsw_emac1: slave at 4a100300 {
		dual_emac_res_vlan = <2>;
	};
};

When I boot my board (across nfs via eth1):-

(a) the kernel is loaded (via tftp under U-Boot)
(b) the kernel mounts the nfsroot
(c) my init scripts are run (e.g. dropbear)
(d) the shell prompt appears

So far so good, but when I then try any shell command (e.g. "ps") the 
nfs link just hangs.

Below is an extract from the boot messages:-

[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Linux version 3.9.0-rc6-00186-g5b55d70-dirty 
(mpfj at mpfj-nanobone) (gcc version 4.7.2 (Buildroot 
2013.02-00154-g851ceaa) ) #19 Sun Apr 14 19:50:21 BST 2013
[    0.000000] CPU: ARMv7 Processor [413fc082] revision 2 (ARMv7), 
cr=10c53c7d
[    0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing 
instruction cache
[    0.000000] Machine: Generic AM33XX (Flattened Device Tree), model: 
Newflow AM335x NanoBone
[    0.000000] Memory policy: ECC disabled, Data cache writeback
[    0.000000] CPU: All CPU(s) started in SVC mode.
[    0.000000] AM335X ES1.0 (neon )
[    0.000000] Built 1 zonelists in Zone order, mobility grouping on. 
Total pages: 64768
[    0.000000] Kernel command line: root=/dev/nfs 
nfsroot=10.1.0.111:/tftpboot/nanobone/rootfs rw 
ip=10.1.0.199:10.1.0.111:10.1.0.1:255.255.0.0::eth1:off console=ttyO0,115200
...
[    1.424977] davinci_mdio 4a101000.mdio: davinci mdio revision 1.6
[    1.431443] davinci_mdio 4a101000.mdio: detected phy mask fffffffc
[    1.440939] libphy: 4a101000.mdio: probed
[    1.445266] davinci_mdio 4a101000.mdio: phy[0]: device 
4a101000.mdio:00, driver SMSC LAN8710/LAN8720
[    1.454962] davinci_mdio 4a101000.mdio: phy[1]: device 
4a101000.mdio:01, driver SMSC LAN8710/LAN8720
[    1.465059] Random MACID = a2:3f:fb:2c:47:d9
[    1.472276] cpsw: Random MACID = ae:d5:c0:c0:27:03
[    1.480588] rtc-ds1307 0-0068: setting system clock to 2013-04-14 
19:59:52 UTC (1365969592)
[    1.491543] net eth1: initializing cpsw version 1.12 (0)
[    1.516965] net eth1: phy found : id is : 0x7c0f1
[    4.595479] libphy: 4a101000.mdio:01 - Link is Up - 100/Full
[    4.625872] IP-Config: Complete:
[    4.629307]      device=eth1, hwaddr=ae:d5:c0:c0:27:03, 
ipaddr=10.1.0.199, mask=255.255.0.0, gw=10.1.0.1
[    4.639365]      host=10.1.0.199, domain=, nis-domain=(none)
[    4.645359]      bootserver=10.1.0.111, rootserver=10.1.0.111, rootpath=
[    4.674219] VFS: Mounted root (nfs filesystem) on device 0:12.
[    4.682438] devtmpfs: mounted
[    4.686042] Freeing init memory: 196K
Starting logging: OK
Initializing random number generator... done.
Starting network...
ip: RTNETLINK answers: File exists
[    5.340677] net eth0: initializing cpsw version 1.12 (0)
[    5.366463] net eth0: phy found : id is : 0x7c0f1
ip: RTNETLINK answers: File exists
ip: RTNETLINK answers: File exists
ip: RTNETLINK answers: File exists
Starting dropbear sshd: OK

Welcome to Buildroot
nanobone login: root
Password:
# ps
[   18.845266] nfs: server 10.1.0.111 not responding, still trying

At this point, I can disconnect my network cable from eth1 and connect 
to eth0, and back again which shows the PYHs appear to be detecting the 
link up/down status of each port.

[  562.675229] libphy: 4a101000.mdio:01 - Link is Down
[  567.885586] libphy: 4a101000.mdio:00 - Link is Up - 100/Full
[  571.965156] libphy: 4a101000.mdio:00 - Link is Down
[  575.014943] nfs: server 10.1.0.111 not responding, still trying
[  576.635412] libphy: 4a101000.mdio:01 - Link is Up - 100/Full
[  579.426051] nfs: server 10.1.0.111 OK

Notice that at the end, the nfs link appears to come back "ok", but the 
"ps" command never completes.

Any ideas of what's going on ?

Cheers
Mark J.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 3/3] driver: net: ethernet: cpsw: dual emac interface implementation
  2013-02-11 19:52   ` Mugunthan V N
@ 2013-04-14 19:20     ` Mark Jackson
  -1 siblings, 0 replies; 48+ messages in thread
From: Mark Jackson @ 2013-04-14 19:20 UTC (permalink / raw)
  To: Mugunthan V N; +Cc: netdev, davem, linux-arm-kernel, linux-omap

On 11/02/13 19:52, Mugunthan V N wrote:
> The CPSW switch can act as Dual EMAC by segregating the switch ports
> using VLAN and port VLAN as per the TRM description in
> 14.3.2.10.2 Dual Mac Mode
>
> Following CPSW components will be common for both the interfaces.
> * Interrupt source is common for both eth interfaces
> * Interrupt pacing is common for both interfaces
> * Hardware statistics is common for all the ports
> * CPDMA is common for both eth interface
> * CPTS is common for both the interface and it should not be enabled on
>    both the interface as timestamping information doesn't contain port
>    information.
>
> Constrains
> * Reserved VID of One port should not be used in other interface which will
>    enable switching functionality
> * Same VID must not be used in both the interface which will enable switching
>    functionality
>
> Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
> ---
>   Documentation/devicetree/bindings/net/cpsw.txt |    2 +
>   drivers/net/ethernet/ti/cpsw.c                 |  335 ++++++++++++++++++++----
>   include/linux/platform_data/cpsw.h             |    3 +
>   3 files changed, 288 insertions(+), 52 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt
> index 6ddd028..ecfdf75 100644
> --- a/Documentation/devicetree/bindings/net/cpsw.txt
> +++ b/Documentation/devicetree/bindings/net/cpsw.txt
> @@ -24,6 +24,8 @@ Required properties:
>   Optional properties:
>   - ti,hwmods		: Must be "cpgmac0"
>   - no_bd_ram		: Must be 0 or 1
> +- dual_emac		: Specifies Switch to act as Dual EMAC
> +- dual_emac_res_vlan	: Specifies VID to be used to segregate the ports
>
>   Note: "ti,hwmods" field is used to fetch the base address and irq
>   resources from TI, omap hwmod data base during device registration.
> diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
> index 4b964bb..4ceed6e 100644
> --- a/drivers/net/ethernet/ti/cpsw.c
> +++ b/drivers/net/ethernet/ti/cpsw.c

<snip>

> @@ -1237,6 +1372,18 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
>   		if (mac_addr)
>   			memcpy(slave_data->mac_addr, mac_addr, ETH_ALEN);
>
> +		if (data->dual_emac) {
> +			if (of_property_read_u32(node, "dual_emac_res_vlan",
> +						 &prop)) {

Shouldn't this be:-

	if (of_property_read_u32(slave_node, "dual_emac_res_vlan",
                                  ^^^^^^^^^^

... so we pick each VLAN id from the individual slaves ?

Regards
Mark J.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH 3/3] driver: net: ethernet: cpsw: dual emac interface implementation
@ 2013-04-14 19:20     ` Mark Jackson
  0 siblings, 0 replies; 48+ messages in thread
From: Mark Jackson @ 2013-04-14 19:20 UTC (permalink / raw)
  To: linux-arm-kernel

On 11/02/13 19:52, Mugunthan V N wrote:
> The CPSW switch can act as Dual EMAC by segregating the switch ports
> using VLAN and port VLAN as per the TRM description in
> 14.3.2.10.2 Dual Mac Mode
>
> Following CPSW components will be common for both the interfaces.
> * Interrupt source is common for both eth interfaces
> * Interrupt pacing is common for both interfaces
> * Hardware statistics is common for all the ports
> * CPDMA is common for both eth interface
> * CPTS is common for both the interface and it should not be enabled on
>    both the interface as timestamping information doesn't contain port
>    information.
>
> Constrains
> * Reserved VID of One port should not be used in other interface which will
>    enable switching functionality
> * Same VID must not be used in both the interface which will enable switching
>    functionality
>
> Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
> ---
>   Documentation/devicetree/bindings/net/cpsw.txt |    2 +
>   drivers/net/ethernet/ti/cpsw.c                 |  335 ++++++++++++++++++++----
>   include/linux/platform_data/cpsw.h             |    3 +
>   3 files changed, 288 insertions(+), 52 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt
> index 6ddd028..ecfdf75 100644
> --- a/Documentation/devicetree/bindings/net/cpsw.txt
> +++ b/Documentation/devicetree/bindings/net/cpsw.txt
> @@ -24,6 +24,8 @@ Required properties:
>   Optional properties:
>   - ti,hwmods		: Must be "cpgmac0"
>   - no_bd_ram		: Must be 0 or 1
> +- dual_emac		: Specifies Switch to act as Dual EMAC
> +- dual_emac_res_vlan	: Specifies VID to be used to segregate the ports
>
>   Note: "ti,hwmods" field is used to fetch the base address and irq
>   resources from TI, omap hwmod data base during device registration.
> diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
> index 4b964bb..4ceed6e 100644
> --- a/drivers/net/ethernet/ti/cpsw.c
> +++ b/drivers/net/ethernet/ti/cpsw.c

<snip>

> @@ -1237,6 +1372,18 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
>   		if (mac_addr)
>   			memcpy(slave_data->mac_addr, mac_addr, ETH_ALEN);
>
> +		if (data->dual_emac) {
> +			if (of_property_read_u32(node, "dual_emac_res_vlan",
> +						 &prop)) {

Shouldn't this be:-

	if (of_property_read_u32(slave_node, "dual_emac_res_vlan",
                                  ^^^^^^^^^^

... so we pick each VLAN id from the individual slaves ?

Regards
Mark J.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 3/3] driver: net: ethernet: cpsw: dual emac interface implementation
  2013-04-14 19:20     ` Mark Jackson
  (?)
@ 2013-04-15 17:04       ` Mugunthan V N
  -1 siblings, 0 replies; 48+ messages in thread
From: Mugunthan V N @ 2013-04-15 17:04 UTC (permalink / raw)
  To: Mark Jackson; +Cc: netdev, davem, linux-arm-kernel, linux-omap

On 4/15/2013 12:50 AM, Mark Jackson wrote:
> On 11/02/13 19:52, Mugunthan V N wrote:
>> The CPSW switch can act as Dual EMAC by segregating the switch ports
>> using VLAN and port VLAN as per the TRM description in
>> 14.3.2.10.2 Dual Mac Mode
>>
>> Following CPSW components will be common for both the interfaces.
>> * Interrupt source is common for both eth interfaces
>> * Interrupt pacing is common for both interfaces
>> * Hardware statistics is common for all the ports
>> * CPDMA is common for both eth interface
>> * CPTS is common for both the interface and it should not be enabled on
>>    both the interface as timestamping information doesn't contain port
>>    information.
>>
>> Constrains
>> * Reserved VID of One port should not be used in other interface 
>> which will
>>    enable switching functionality
>> * Same VID must not be used in both the interface which will enable 
>> switching
>>    functionality
>>
>> Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
>> ---
>
>> @@ -1237,6 +1372,18 @@ static int cpsw_probe_dt(struct 
>> cpsw_platform_data *data,
>>           if (mac_addr)
>>               memcpy(slave_data->mac_addr, mac_addr, ETH_ALEN);
>>
>> +        if (data->dual_emac) {
>> +            if (of_property_read_u32(node, "dual_emac_res_vlan",
>> +                         &prop)) {
>
> Shouldn't this be:-
>
>     if (of_property_read_u32(slave_node, "dual_emac_res_vlan",
>                                  ^^^^^^^^^^
>
> ... so we pick each VLAN id from the individual slaves ?

Good catch, will send a fixup patch for this.

Regards
Mugunthan V N

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 3/3] driver: net: ethernet: cpsw: dual emac interface implementation
@ 2013-04-15 17:04       ` Mugunthan V N
  0 siblings, 0 replies; 48+ messages in thread
From: Mugunthan V N @ 2013-04-15 17:04 UTC (permalink / raw)
  To: Mark Jackson; +Cc: netdev, davem, linux-arm-kernel, linux-omap

On 4/15/2013 12:50 AM, Mark Jackson wrote:
> On 11/02/13 19:52, Mugunthan V N wrote:
>> The CPSW switch can act as Dual EMAC by segregating the switch ports
>> using VLAN and port VLAN as per the TRM description in
>> 14.3.2.10.2 Dual Mac Mode
>>
>> Following CPSW components will be common for both the interfaces.
>> * Interrupt source is common for both eth interfaces
>> * Interrupt pacing is common for both interfaces
>> * Hardware statistics is common for all the ports
>> * CPDMA is common for both eth interface
>> * CPTS is common for both the interface and it should not be enabled on
>>    both the interface as timestamping information doesn't contain port
>>    information.
>>
>> Constrains
>> * Reserved VID of One port should not be used in other interface 
>> which will
>>    enable switching functionality
>> * Same VID must not be used in both the interface which will enable 
>> switching
>>    functionality
>>
>> Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
>> ---
>
>> @@ -1237,6 +1372,18 @@ static int cpsw_probe_dt(struct 
>> cpsw_platform_data *data,
>>           if (mac_addr)
>>               memcpy(slave_data->mac_addr, mac_addr, ETH_ALEN);
>>
>> +        if (data->dual_emac) {
>> +            if (of_property_read_u32(node, "dual_emac_res_vlan",
>> +                         &prop)) {
>
> Shouldn't this be:-
>
>     if (of_property_read_u32(slave_node, "dual_emac_res_vlan",
>                                  ^^^^^^^^^^
>
> ... so we pick each VLAN id from the individual slaves ?

Good catch, will send a fixup patch for this.

Regards
Mugunthan V N

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH 3/3] driver: net: ethernet: cpsw: dual emac interface implementation
@ 2013-04-15 17:04       ` Mugunthan V N
  0 siblings, 0 replies; 48+ messages in thread
From: Mugunthan V N @ 2013-04-15 17:04 UTC (permalink / raw)
  To: linux-arm-kernel

On 4/15/2013 12:50 AM, Mark Jackson wrote:
> On 11/02/13 19:52, Mugunthan V N wrote:
>> The CPSW switch can act as Dual EMAC by segregating the switch ports
>> using VLAN and port VLAN as per the TRM description in
>> 14.3.2.10.2 Dual Mac Mode
>>
>> Following CPSW components will be common for both the interfaces.
>> * Interrupt source is common for both eth interfaces
>> * Interrupt pacing is common for both interfaces
>> * Hardware statistics is common for all the ports
>> * CPDMA is common for both eth interface
>> * CPTS is common for both the interface and it should not be enabled on
>>    both the interface as timestamping information doesn't contain port
>>    information.
>>
>> Constrains
>> * Reserved VID of One port should not be used in other interface 
>> which will
>>    enable switching functionality
>> * Same VID must not be used in both the interface which will enable 
>> switching
>>    functionality
>>
>> Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
>> ---
>
>> @@ -1237,6 +1372,18 @@ static int cpsw_probe_dt(struct 
>> cpsw_platform_data *data,
>>           if (mac_addr)
>>               memcpy(slave_data->mac_addr, mac_addr, ETH_ALEN);
>>
>> +        if (data->dual_emac) {
>> +            if (of_property_read_u32(node, "dual_emac_res_vlan",
>> +                         &prop)) {
>
> Shouldn't this be:-
>
>     if (of_property_read_u32(slave_node, "dual_emac_res_vlan",
>                                  ^^^^^^^^^^
>
> ... so we pick each VLAN id from the individual slaves ?

Good catch, will send a fixup patch for this.

Regards
Mugunthan V N

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 0/3] Dual EMAC mode implementation of CPSW
  2013-04-14 19:16   ` Mark Jackson
  (?)
@ 2013-04-15 17:07     ` Mugunthan V N
  -1 siblings, 0 replies; 48+ messages in thread
From: Mugunthan V N @ 2013-04-15 17:07 UTC (permalink / raw)
  To: Mark Jackson; +Cc: netdev, davem, linux-arm-kernel, linux-omap

On 4/15/2013 12:46 AM, Mark Jackson wrote:
> On 11/02/13 19:52, Mugunthan V N wrote:
>> This patch series implements Dual EMAC mode implementation of CPSW
>> which acts as two standalone EMAC by segregating the switch using VIDs
>> and port VLAN
>>
>> Mugunthan V N (3):
>>    driver: net: ethernet: davinci_cpdma: add support for directed packet
>>      and source port detection
>>    driver: net: ethernet: cpsw: make cpts as pointer
>>    driver: net: ethernet: cpsw: dual emac interface implementation
>>
>>   Documentation/devicetree/bindings/net/cpsw.txt |    2 +
>>   drivers/net/ethernet/ti/cpsw.c                 |  387 
>> +++++++++++++++++++-----
>>   drivers/net/ethernet/ti/davinci_cpdma.c        |   17 +-
>>   drivers/net/ethernet/ti/davinci_cpdma.h        |    4 +-
>>   drivers/net/ethernet/ti/davinci_emac.c         |    6 +-
>>   include/linux/platform_data/cpsw.h             |    3 +
>>   6 files changed, 338 insertions(+), 81 deletions(-)
>
> I'm trying to get dual emac mode working, but I'm only having partial 
> success.  We have a custom AM335x board with dual LAN8710 PYHs, but 
> the basic design is based on the BeagleBone board.
>
> I have the following in my .dts file:-
>
> mac: ethernet@4a100000 {
>     dual_emac = <1>;
>     cpsw_emac0: slave@4a100200 {
>         dual_emac_res_vlan = <1>;
>     };
>     cpsw_emac1: slave@4a100300 {
>         dual_emac_res_vlan = <2>;
>     };
> };
>
> When I boot my board (across nfs via eth1):-
>
> (a) the kernel is loaded (via tftp under U-Boot)
> (b) the kernel mounts the nfsroot
> (c) my init scripts are run (e.g. dropbear)
> (d) the shell prompt appears
>
> So far so good, but when I then try any shell command (e.g. "ps") the 
> nfs link just hangs.
>
> Below is an extract from the boot messages:-
>
> [    0.000000] Booting Linux on physical CPU 0x0
> [    0.000000] Linux version 3.9.0-rc6-00186-g5b55d70-dirty 
> (mpfj@mpfj-nanobone) (gcc version 4.7.2 (Buildroot 
> 2013.02-00154-g851ceaa) ) #19 Sun Apr 14 19:50:21 BST 2013
> [    0.000000] CPU: ARMv7 Processor [413fc082] revision 2 (ARMv7), 
> cr=10c53c7d
> [    0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing 
> instruction cache
> [    0.000000] Machine: Generic AM33XX (Flattened Device Tree), model: 
> Newflow AM335x NanoBone
> [    0.000000] Memory policy: ECC disabled, Data cache writeback
> [    0.000000] CPU: All CPU(s) started in SVC mode.
> [    0.000000] AM335X ES1.0 (neon )
> [    0.000000] Built 1 zonelists in Zone order, mobility grouping on. 
> Total pages: 64768
> [    0.000000] Kernel command line: root=/dev/nfs 
> nfsroot=10.1.0.111:/tftpboot/nanobone/rootfs rw 
> ip=10.1.0.199:10.1.0.111:10.1.0.1:255.255.0.0::eth1:off 
> console=ttyO0,115200
> ...
> [    1.424977] davinci_mdio 4a101000.mdio: davinci mdio revision 1.6
> [    1.431443] davinci_mdio 4a101000.mdio: detected phy mask fffffffc
> [    1.440939] libphy: 4a101000.mdio: probed
> [    1.445266] davinci_mdio 4a101000.mdio: phy[0]: device 
> 4a101000.mdio:00, driver SMSC LAN8710/LAN8720
> [    1.454962] davinci_mdio 4a101000.mdio: phy[1]: device 
> 4a101000.mdio:01, driver SMSC LAN8710/LAN8720
> [    1.465059] Random MACID = a2:3f:fb:2c:47:d9
> [    1.472276] cpsw: Random MACID = ae:d5:c0:c0:27:03
> [    1.480588] rtc-ds1307 0-0068: setting system clock to 2013-04-14 
> 19:59:52 UTC (1365969592)
> [    1.491543] net eth1: initializing cpsw version 1.12 (0)
> [    1.516965] net eth1: phy found : id is : 0x7c0f1
> [    4.595479] libphy: 4a101000.mdio:01 - Link is Up - 100/Full
> [    4.625872] IP-Config: Complete:
> [    4.629307]      device=eth1, hwaddr=ae:d5:c0:c0:27:03, 
> ipaddr=10.1.0.199, mask=255.255.0.0, gw=10.1.0.1
> [    4.639365]      host=10.1.0.199, domain=, nis-domain=(none)
> [    4.645359]      bootserver=10.1.0.111, rootserver=10.1.0.111, 
> rootpath=
> [    4.674219] VFS: Mounted root (nfs filesystem) on device 0:12.
> [    4.682438] devtmpfs: mounted
> [    4.686042] Freeing init memory: 196K
> Starting logging: OK
> Initializing random number generator... done.
> Starting network...
> ip: RTNETLINK answers: File exists
> [    5.340677] net eth0: initializing cpsw version 1.12 (0)
> [    5.366463] net eth0: phy found : id is : 0x7c0f1
> ip: RTNETLINK answers: File exists
> ip: RTNETLINK answers: File exists
> ip: RTNETLINK answers: File exists
> Starting dropbear sshd: OK
>
> Welcome to Buildroot
> nanobone login: root
> Password:
> # ps
> [   18.845266] nfs: server 10.1.0.111 not responding, still trying
>
> At this point, I can disconnect my network cable from eth1 and connect 
> to eth0, and back again which shows the PYHs appear to be detecting 
> the link up/down status of each port.
>
> [  562.675229] libphy: 4a101000.mdio:01 - Link is Down
> [  567.885586] libphy: 4a101000.mdio:00 - Link is Up - 100/Full
> [  571.965156] libphy: 4a101000.mdio:00 - Link is Down
> [  575.014943] nfs: server 10.1.0.111 not responding, still trying
> [  576.635412] libphy: 4a101000.mdio:01 - Link is Up - 100/Full
> [  579.426051] nfs: server 10.1.0.111 OK
>
> Notice that at the end, the nfs link appears to come back "ok", but 
> the "ps" command never completes.
>
> Any ideas of what's going on ?

I have tried ping on both the interface fine. Will verify with ps again 
later in this week.
Can you provide below details details
- Are you using EVMsk or custom build EVM?

Regards
Mugunthan V N

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 0/3] Dual EMAC mode implementation of CPSW
@ 2013-04-15 17:07     ` Mugunthan V N
  0 siblings, 0 replies; 48+ messages in thread
From: Mugunthan V N @ 2013-04-15 17:07 UTC (permalink / raw)
  To: Mark Jackson; +Cc: netdev, davem, linux-arm-kernel, linux-omap

On 4/15/2013 12:46 AM, Mark Jackson wrote:
> On 11/02/13 19:52, Mugunthan V N wrote:
>> This patch series implements Dual EMAC mode implementation of CPSW
>> which acts as two standalone EMAC by segregating the switch using VIDs
>> and port VLAN
>>
>> Mugunthan V N (3):
>>    driver: net: ethernet: davinci_cpdma: add support for directed packet
>>      and source port detection
>>    driver: net: ethernet: cpsw: make cpts as pointer
>>    driver: net: ethernet: cpsw: dual emac interface implementation
>>
>>   Documentation/devicetree/bindings/net/cpsw.txt |    2 +
>>   drivers/net/ethernet/ti/cpsw.c                 |  387 
>> +++++++++++++++++++-----
>>   drivers/net/ethernet/ti/davinci_cpdma.c        |   17 +-
>>   drivers/net/ethernet/ti/davinci_cpdma.h        |    4 +-
>>   drivers/net/ethernet/ti/davinci_emac.c         |    6 +-
>>   include/linux/platform_data/cpsw.h             |    3 +
>>   6 files changed, 338 insertions(+), 81 deletions(-)
>
> I'm trying to get dual emac mode working, but I'm only having partial 
> success.  We have a custom AM335x board with dual LAN8710 PYHs, but 
> the basic design is based on the BeagleBone board.
>
> I have the following in my .dts file:-
>
> mac: ethernet@4a100000 {
>     dual_emac = <1>;
>     cpsw_emac0: slave@4a100200 {
>         dual_emac_res_vlan = <1>;
>     };
>     cpsw_emac1: slave@4a100300 {
>         dual_emac_res_vlan = <2>;
>     };
> };
>
> When I boot my board (across nfs via eth1):-
>
> (a) the kernel is loaded (via tftp under U-Boot)
> (b) the kernel mounts the nfsroot
> (c) my init scripts are run (e.g. dropbear)
> (d) the shell prompt appears
>
> So far so good, but when I then try any shell command (e.g. "ps") the 
> nfs link just hangs.
>
> Below is an extract from the boot messages:-
>
> [    0.000000] Booting Linux on physical CPU 0x0
> [    0.000000] Linux version 3.9.0-rc6-00186-g5b55d70-dirty 
> (mpfj@mpfj-nanobone) (gcc version 4.7.2 (Buildroot 
> 2013.02-00154-g851ceaa) ) #19 Sun Apr 14 19:50:21 BST 2013
> [    0.000000] CPU: ARMv7 Processor [413fc082] revision 2 (ARMv7), 
> cr=10c53c7d
> [    0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing 
> instruction cache
> [    0.000000] Machine: Generic AM33XX (Flattened Device Tree), model: 
> Newflow AM335x NanoBone
> [    0.000000] Memory policy: ECC disabled, Data cache writeback
> [    0.000000] CPU: All CPU(s) started in SVC mode.
> [    0.000000] AM335X ES1.0 (neon )
> [    0.000000] Built 1 zonelists in Zone order, mobility grouping on. 
> Total pages: 64768
> [    0.000000] Kernel command line: root=/dev/nfs 
> nfsroot=10.1.0.111:/tftpboot/nanobone/rootfs rw 
> ip=10.1.0.199:10.1.0.111:10.1.0.1:255.255.0.0::eth1:off 
> console=ttyO0,115200
> ...
> [    1.424977] davinci_mdio 4a101000.mdio: davinci mdio revision 1.6
> [    1.431443] davinci_mdio 4a101000.mdio: detected phy mask fffffffc
> [    1.440939] libphy: 4a101000.mdio: probed
> [    1.445266] davinci_mdio 4a101000.mdio: phy[0]: device 
> 4a101000.mdio:00, driver SMSC LAN8710/LAN8720
> [    1.454962] davinci_mdio 4a101000.mdio: phy[1]: device 
> 4a101000.mdio:01, driver SMSC LAN8710/LAN8720
> [    1.465059] Random MACID = a2:3f:fb:2c:47:d9
> [    1.472276] cpsw: Random MACID = ae:d5:c0:c0:27:03
> [    1.480588] rtc-ds1307 0-0068: setting system clock to 2013-04-14 
> 19:59:52 UTC (1365969592)
> [    1.491543] net eth1: initializing cpsw version 1.12 (0)
> [    1.516965] net eth1: phy found : id is : 0x7c0f1
> [    4.595479] libphy: 4a101000.mdio:01 - Link is Up - 100/Full
> [    4.625872] IP-Config: Complete:
> [    4.629307]      device=eth1, hwaddr=ae:d5:c0:c0:27:03, 
> ipaddr=10.1.0.199, mask=255.255.0.0, gw=10.1.0.1
> [    4.639365]      host=10.1.0.199, domain=, nis-domain=(none)
> [    4.645359]      bootserver=10.1.0.111, rootserver=10.1.0.111, 
> rootpath=
> [    4.674219] VFS: Mounted root (nfs filesystem) on device 0:12.
> [    4.682438] devtmpfs: mounted
> [    4.686042] Freeing init memory: 196K
> Starting logging: OK
> Initializing random number generator... done.
> Starting network...
> ip: RTNETLINK answers: File exists
> [    5.340677] net eth0: initializing cpsw version 1.12 (0)
> [    5.366463] net eth0: phy found : id is : 0x7c0f1
> ip: RTNETLINK answers: File exists
> ip: RTNETLINK answers: File exists
> ip: RTNETLINK answers: File exists
> Starting dropbear sshd: OK
>
> Welcome to Buildroot
> nanobone login: root
> Password:
> # ps
> [   18.845266] nfs: server 10.1.0.111 not responding, still trying
>
> At this point, I can disconnect my network cable from eth1 and connect 
> to eth0, and back again which shows the PYHs appear to be detecting 
> the link up/down status of each port.
>
> [  562.675229] libphy: 4a101000.mdio:01 - Link is Down
> [  567.885586] libphy: 4a101000.mdio:00 - Link is Up - 100/Full
> [  571.965156] libphy: 4a101000.mdio:00 - Link is Down
> [  575.014943] nfs: server 10.1.0.111 not responding, still trying
> [  576.635412] libphy: 4a101000.mdio:01 - Link is Up - 100/Full
> [  579.426051] nfs: server 10.1.0.111 OK
>
> Notice that at the end, the nfs link appears to come back "ok", but 
> the "ps" command never completes.
>
> Any ideas of what's going on ?

I have tried ping on both the interface fine. Will verify with ps again 
later in this week.
Can you provide below details details
- Are you using EVMsk or custom build EVM?

Regards
Mugunthan V N

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH 0/3] Dual EMAC mode implementation of CPSW
@ 2013-04-15 17:07     ` Mugunthan V N
  0 siblings, 0 replies; 48+ messages in thread
From: Mugunthan V N @ 2013-04-15 17:07 UTC (permalink / raw)
  To: linux-arm-kernel

On 4/15/2013 12:46 AM, Mark Jackson wrote:
> On 11/02/13 19:52, Mugunthan V N wrote:
>> This patch series implements Dual EMAC mode implementation of CPSW
>> which acts as two standalone EMAC by segregating the switch using VIDs
>> and port VLAN
>>
>> Mugunthan V N (3):
>>    driver: net: ethernet: davinci_cpdma: add support for directed packet
>>      and source port detection
>>    driver: net: ethernet: cpsw: make cpts as pointer
>>    driver: net: ethernet: cpsw: dual emac interface implementation
>>
>>   Documentation/devicetree/bindings/net/cpsw.txt |    2 +
>>   drivers/net/ethernet/ti/cpsw.c                 |  387 
>> +++++++++++++++++++-----
>>   drivers/net/ethernet/ti/davinci_cpdma.c        |   17 +-
>>   drivers/net/ethernet/ti/davinci_cpdma.h        |    4 +-
>>   drivers/net/ethernet/ti/davinci_emac.c         |    6 +-
>>   include/linux/platform_data/cpsw.h             |    3 +
>>   6 files changed, 338 insertions(+), 81 deletions(-)
>
> I'm trying to get dual emac mode working, but I'm only having partial 
> success.  We have a custom AM335x board with dual LAN8710 PYHs, but 
> the basic design is based on the BeagleBone board.
>
> I have the following in my .dts file:-
>
> mac: ethernet at 4a100000 {
>     dual_emac = <1>;
>     cpsw_emac0: slave at 4a100200 {
>         dual_emac_res_vlan = <1>;
>     };
>     cpsw_emac1: slave at 4a100300 {
>         dual_emac_res_vlan = <2>;
>     };
> };
>
> When I boot my board (across nfs via eth1):-
>
> (a) the kernel is loaded (via tftp under U-Boot)
> (b) the kernel mounts the nfsroot
> (c) my init scripts are run (e.g. dropbear)
> (d) the shell prompt appears
>
> So far so good, but when I then try any shell command (e.g. "ps") the 
> nfs link just hangs.
>
> Below is an extract from the boot messages:-
>
> [    0.000000] Booting Linux on physical CPU 0x0
> [    0.000000] Linux version 3.9.0-rc6-00186-g5b55d70-dirty 
> (mpfj at mpfj-nanobone) (gcc version 4.7.2 (Buildroot 
> 2013.02-00154-g851ceaa) ) #19 Sun Apr 14 19:50:21 BST 2013
> [    0.000000] CPU: ARMv7 Processor [413fc082] revision 2 (ARMv7), 
> cr=10c53c7d
> [    0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing 
> instruction cache
> [    0.000000] Machine: Generic AM33XX (Flattened Device Tree), model: 
> Newflow AM335x NanoBone
> [    0.000000] Memory policy: ECC disabled, Data cache writeback
> [    0.000000] CPU: All CPU(s) started in SVC mode.
> [    0.000000] AM335X ES1.0 (neon )
> [    0.000000] Built 1 zonelists in Zone order, mobility grouping on. 
> Total pages: 64768
> [    0.000000] Kernel command line: root=/dev/nfs 
> nfsroot=10.1.0.111:/tftpboot/nanobone/rootfs rw 
> ip=10.1.0.199:10.1.0.111:10.1.0.1:255.255.0.0::eth1:off 
> console=ttyO0,115200
> ...
> [    1.424977] davinci_mdio 4a101000.mdio: davinci mdio revision 1.6
> [    1.431443] davinci_mdio 4a101000.mdio: detected phy mask fffffffc
> [    1.440939] libphy: 4a101000.mdio: probed
> [    1.445266] davinci_mdio 4a101000.mdio: phy[0]: device 
> 4a101000.mdio:00, driver SMSC LAN8710/LAN8720
> [    1.454962] davinci_mdio 4a101000.mdio: phy[1]: device 
> 4a101000.mdio:01, driver SMSC LAN8710/LAN8720
> [    1.465059] Random MACID = a2:3f:fb:2c:47:d9
> [    1.472276] cpsw: Random MACID = ae:d5:c0:c0:27:03
> [    1.480588] rtc-ds1307 0-0068: setting system clock to 2013-04-14 
> 19:59:52 UTC (1365969592)
> [    1.491543] net eth1: initializing cpsw version 1.12 (0)
> [    1.516965] net eth1: phy found : id is : 0x7c0f1
> [    4.595479] libphy: 4a101000.mdio:01 - Link is Up - 100/Full
> [    4.625872] IP-Config: Complete:
> [    4.629307]      device=eth1, hwaddr=ae:d5:c0:c0:27:03, 
> ipaddr=10.1.0.199, mask=255.255.0.0, gw=10.1.0.1
> [    4.639365]      host=10.1.0.199, domain=, nis-domain=(none)
> [    4.645359]      bootserver=10.1.0.111, rootserver=10.1.0.111, 
> rootpath=
> [    4.674219] VFS: Mounted root (nfs filesystem) on device 0:12.
> [    4.682438] devtmpfs: mounted
> [    4.686042] Freeing init memory: 196K
> Starting logging: OK
> Initializing random number generator... done.
> Starting network...
> ip: RTNETLINK answers: File exists
> [    5.340677] net eth0: initializing cpsw version 1.12 (0)
> [    5.366463] net eth0: phy found : id is : 0x7c0f1
> ip: RTNETLINK answers: File exists
> ip: RTNETLINK answers: File exists
> ip: RTNETLINK answers: File exists
> Starting dropbear sshd: OK
>
> Welcome to Buildroot
> nanobone login: root
> Password:
> # ps
> [   18.845266] nfs: server 10.1.0.111 not responding, still trying
>
> At this point, I can disconnect my network cable from eth1 and connect 
> to eth0, and back again which shows the PYHs appear to be detecting 
> the link up/down status of each port.
>
> [  562.675229] libphy: 4a101000.mdio:01 - Link is Down
> [  567.885586] libphy: 4a101000.mdio:00 - Link is Up - 100/Full
> [  571.965156] libphy: 4a101000.mdio:00 - Link is Down
> [  575.014943] nfs: server 10.1.0.111 not responding, still trying
> [  576.635412] libphy: 4a101000.mdio:01 - Link is Up - 100/Full
> [  579.426051] nfs: server 10.1.0.111 OK
>
> Notice that at the end, the nfs link appears to come back "ok", but 
> the "ps" command never completes.
>
> Any ideas of what's going on ?

I have tried ping on both the interface fine. Will verify with ps again 
later in this week.
Can you provide below details details
- Are you using EVMsk or custom build EVM?

Regards
Mugunthan V N

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 0/3] Dual EMAC mode implementation of CPSW
  2013-04-15 17:07     ` Mugunthan V N
@ 2013-04-15 17:28       ` Mark Jackson
  -1 siblings, 0 replies; 48+ messages in thread
From: Mark Jackson @ 2013-04-15 17:28 UTC (permalink / raw)
  To: Mugunthan V N; +Cc: netdev, davem, linux-arm-kernel, linux-omap

On 15/04/13 18:07, Mugunthan V N wrote:
> On 4/15/2013 12:46 AM, Mark Jackson wrote:

<snip>

>>
>> Notice that at the end, the nfs link appears to come back "ok", but
>> the "ps" command never completes.
>>
>> Any ideas of what's going on ?
>
> I have tried ping on both the interface fine. Will verify with ps again
> later in this week.
> Can you provide below details details
> - Are you using EVMsk or custom build EVM?

This is a custom board (based on the BeagleBone design) with dual 
Ethernet, NAND, NOR and FRAM.

The dual emac thing is (one of) the last things to get signed off, so 
I'm willing to assist in tracking this down.

Regards
Mark J.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH 0/3] Dual EMAC mode implementation of CPSW
@ 2013-04-15 17:28       ` Mark Jackson
  0 siblings, 0 replies; 48+ messages in thread
From: Mark Jackson @ 2013-04-15 17:28 UTC (permalink / raw)
  To: linux-arm-kernel

On 15/04/13 18:07, Mugunthan V N wrote:
> On 4/15/2013 12:46 AM, Mark Jackson wrote:

<snip>

>>
>> Notice that at the end, the nfs link appears to come back "ok", but
>> the "ps" command never completes.
>>
>> Any ideas of what's going on ?
>
> I have tried ping on both the interface fine. Will verify with ps again
> later in this week.
> Can you provide below details details
> - Are you using EVMsk or custom build EVM?

This is a custom board (based on the BeagleBone design) with dual 
Ethernet, NAND, NOR and FRAM.

The dual emac thing is (one of) the last things to get signed off, so 
I'm willing to assist in tracking this down.

Regards
Mark J.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 0/3] Dual EMAC mode implementation of CPSW
  2013-04-15 17:28       ` Mark Jackson
  (?)
@ 2013-04-15 17:34         ` Mugunthan V N
  -1 siblings, 0 replies; 48+ messages in thread
From: Mugunthan V N @ 2013-04-15 17:34 UTC (permalink / raw)
  To: Mark Jackson; +Cc: netdev, davem, linux-arm-kernel, linux-omap

On 4/15/2013 10:58 PM, Mark Jackson wrote:
> On 15/04/13 18:07, Mugunthan V N wrote:
>> On 4/15/2013 12:46 AM, Mark Jackson wrote:
>
> <snip>
>
>>>
>>> Notice that at the end, the nfs link appears to come back "ok", but
>>> the "ps" command never completes.
>>>
>>> Any ideas of what's going on ?
>>
>> I have tried ping on both the interface fine. Will verify with ps again
>> later in this week.
>> Can you provide below details details
>> - Are you using EVMsk or custom build EVM?
>
> This is a custom board (based on the BeagleBone design) with dual 
> Ethernet, NAND, NOR and FRAM.
>
> The dual emac thing is (one of) the last things to get signed off, so 
> I'm willing to assist in tracking this down.

After testing the scenario i may be able to send you an update later in 
this week.

Regards
Mugunthan V N

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 0/3] Dual EMAC mode implementation of CPSW
@ 2013-04-15 17:34         ` Mugunthan V N
  0 siblings, 0 replies; 48+ messages in thread
From: Mugunthan V N @ 2013-04-15 17:34 UTC (permalink / raw)
  To: Mark Jackson; +Cc: netdev, davem, linux-arm-kernel, linux-omap

On 4/15/2013 10:58 PM, Mark Jackson wrote:
> On 15/04/13 18:07, Mugunthan V N wrote:
>> On 4/15/2013 12:46 AM, Mark Jackson wrote:
>
> <snip>
>
>>>
>>> Notice that at the end, the nfs link appears to come back "ok", but
>>> the "ps" command never completes.
>>>
>>> Any ideas of what's going on ?
>>
>> I have tried ping on both the interface fine. Will verify with ps again
>> later in this week.
>> Can you provide below details details
>> - Are you using EVMsk or custom build EVM?
>
> This is a custom board (based on the BeagleBone design) with dual 
> Ethernet, NAND, NOR and FRAM.
>
> The dual emac thing is (one of) the last things to get signed off, so 
> I'm willing to assist in tracking this down.

After testing the scenario i may be able to send you an update later in 
this week.

Regards
Mugunthan V N

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH 0/3] Dual EMAC mode implementation of CPSW
@ 2013-04-15 17:34         ` Mugunthan V N
  0 siblings, 0 replies; 48+ messages in thread
From: Mugunthan V N @ 2013-04-15 17:34 UTC (permalink / raw)
  To: linux-arm-kernel

On 4/15/2013 10:58 PM, Mark Jackson wrote:
> On 15/04/13 18:07, Mugunthan V N wrote:
>> On 4/15/2013 12:46 AM, Mark Jackson wrote:
>
> <snip>
>
>>>
>>> Notice that at the end, the nfs link appears to come back "ok", but
>>> the "ps" command never completes.
>>>
>>> Any ideas of what's going on ?
>>
>> I have tried ping on both the interface fine. Will verify with ps again
>> later in this week.
>> Can you provide below details details
>> - Are you using EVMsk or custom build EVM?
>
> This is a custom board (based on the BeagleBone design) with dual 
> Ethernet, NAND, NOR and FRAM.
>
> The dual emac thing is (one of) the last things to get signed off, so 
> I'm willing to assist in tracking this down.

After testing the scenario i may be able to send you an update later in 
this week.

Regards
Mugunthan V N

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 0/3] Dual EMAC mode implementation of CPSW
  2013-04-15 17:34         ` Mugunthan V N
@ 2013-04-15 18:00           ` Mark Jackson
  -1 siblings, 0 replies; 48+ messages in thread
From: Mark Jackson @ 2013-04-15 18:00 UTC (permalink / raw)
  To: Mugunthan V N; +Cc: netdev, davem, linux-arm-kernel, linux-omap

On 15/04/13 18:34, Mugunthan V N wrote:
> On 4/15/2013 10:58 PM, Mark Jackson wrote:
>> On 15/04/13 18:07, Mugunthan V N wrote:
>>> On 4/15/2013 12:46 AM, Mark Jackson wrote:
>>
>> <snip>
>>
>>>>
>>>> Notice that at the end, the nfs link appears to come back "ok", but
>>>> the "ps" command never completes.
>>>>
>>>> Any ideas of what's going on ?
>>>
>>> I have tried ping on both the interface fine. Will verify with ps again
>>> later in this week.
>>> Can you provide below details details
>>> - Are you using EVMsk or custom build EVM?
>>
>> This is a custom board (based on the BeagleBone design) with dual
>> Ethernet, NAND, NOR and FRAM.
>>
>> The dual emac thing is (one of) the last things to get signed off, so
>> I'm willing to assist in tracking this down.
>
> After testing the scenario i may be able to send you an update later in
> this week.

Excellent ... if you've anything I can test now, I'd be happy to try.

Cheers
Mark J.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH 0/3] Dual EMAC mode implementation of CPSW
@ 2013-04-15 18:00           ` Mark Jackson
  0 siblings, 0 replies; 48+ messages in thread
From: Mark Jackson @ 2013-04-15 18:00 UTC (permalink / raw)
  To: linux-arm-kernel

On 15/04/13 18:34, Mugunthan V N wrote:
> On 4/15/2013 10:58 PM, Mark Jackson wrote:
>> On 15/04/13 18:07, Mugunthan V N wrote:
>>> On 4/15/2013 12:46 AM, Mark Jackson wrote:
>>
>> <snip>
>>
>>>>
>>>> Notice that at the end, the nfs link appears to come back "ok", but
>>>> the "ps" command never completes.
>>>>
>>>> Any ideas of what's going on ?
>>>
>>> I have tried ping on both the interface fine. Will verify with ps again
>>> later in this week.
>>> Can you provide below details details
>>> - Are you using EVMsk or custom build EVM?
>>
>> This is a custom board (based on the BeagleBone design) with dual
>> Ethernet, NAND, NOR and FRAM.
>>
>> The dual emac thing is (one of) the last things to get signed off, so
>> I'm willing to assist in tracking this down.
>
> After testing the scenario i may be able to send you an update later in
> this week.

Excellent ... if you've anything I can test now, I'd be happy to try.

Cheers
Mark J.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 0/3] Dual EMAC mode implementation of CPSW
  2013-04-15 17:34         ` Mugunthan V N
@ 2013-04-16 11:09           ` Mark Jackson
  -1 siblings, 0 replies; 48+ messages in thread
From: Mark Jackson @ 2013-04-16 11:09 UTC (permalink / raw)
  To: Mugunthan V N; +Cc: netdev, davem, linux-arm-kernel, linux-omap

On 15/04/13 18:34, Mugunthan V N wrote:
> On 4/15/2013 10:58 PM, Mark Jackson wrote:
>> On 15/04/13 18:07, Mugunthan V N wrote:
>>> On 4/15/2013 12:46 AM, Mark Jackson wrote:
>>
>> <snip>
>>
>>>>
>>>> Notice that at the end, the nfs link appears to come back "ok", but
>>>> the "ps" command never completes.
>>>>
>>>> Any ideas of what's going on ?
>>>
>>> I have tried ping on both the interface fine. Will verify with ps again
>>> later in this week.
>>> Can you provide below details details
>>> - Are you using EVMsk or custom build EVM?
>>
>> This is a custom board (based on the BeagleBone design) with dual Ethernet, NAND, NOR and FRAM.
>>
>> The dual emac thing is (one of) the last things to get signed off, so I'm willing to assist in tracking this down.
> 
> After testing the scenario i may be able to send you an update later in this week.

Just a quick update ...

I've now setup our board to boot entirely from NAND (UBoot -> Kernel -> UBIFS) so
that I'm no longer using NFS (just to isolate any issues there).

I am still *unable* to get a connection on either Ethernet port.

*HOWEVER* ... I *can* ping my board from another PC on the network:-

mpfj@mpfj-nanobone:~/uboot/u-boot$ ping 10.0.101.111 -c 5
PING 10.0.101.111 (10.0.101.111) 56(84) bytes of data.
64 bytes from 10.0.101.111: icmp_req=1 ttl=64 time=0.692 ms
64 bytes from 10.0.101.111: icmp_req=2 ttl=64 time=0.551 ms
64 bytes from 10.0.101.111: icmp_req=3 ttl=64 time=0.462 ms
64 bytes from 10.0.101.111: icmp_req=4 ttl=64 time=0.409 ms
64 bytes from 10.0.101.111: icmp_req=5 ttl=64 time=0.344 ms

--- 10.0.101.111 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 3998ms
rtt min/avg/max/mdev = 0.344/0.491/0.692/0.123 ms

So I can't ping *out*, but I can ping *in* !!

Note that I've only tried this ping test to/from eth0 ... I'll
setup another box on the correct IP range so I can also test eth1.

I've added my boot log below.

Cheers
Mark J.
---
U-Boot SPL 2013.04-rc2-00065-g7450e4d-dirty (Apr 16 2013 - 11:36:17)


U-Boot 2013.04-rc2-00065-g7450e4d-dirty (Apr 16 2013 - 11:36:17)

I2C:   ready
DRAM:  256 MiB
WARNING: Caches not enabled
NAND:  256 MiB
MMC:   OMAP SD/MMC: 0, OMAP SD/MMC: 1
Net:   cpsw:0 is connected to cpsw.  Reconnecting to cpsw
cpsw
Hit any key to stop autoboot:  0

NAND read: device 0 offset 0x200000, size 0x400000
 4194304 bytes read: OK
## Booting kernel from Legacy Image at 80200000 ...
   Image Name:   Linux 3.9.0-rc7-00023-gfcc38a5
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    2997518 Bytes = 2.9 MiB
   Load Address: 80008000
   Entry Point:  80008000
   Verifying Checksum ... OK
   Loading Kernel Image ... OK
OK

Starting kernel ...

[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Linux version 3.9.0-rc7-00023-gfcc38a5 (mpfj@mpfj-nanobone) (gcc version 4.5.4 (Buildroot 2012.11) ) #156 Tue Apr 16 08:55:28 BST 2013
[    0.000000] CPU: ARMv7 Processor [413fc082] revision 2 (ARMv7), cr=10c53c7d
[    0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
[    0.000000] Machine: Generic AM33XX (Flattened Device Tree), model: Newflow AM335x NanoBone
[    0.000000] debug: ignoring loglevel setting.
[    0.000000] Memory policy: ECC disabled, Data cache writeback
[    0.000000] On node 0 totalpages: 65280
[    0.000000] free_area_init_node: node 0, pgdat c059a858, node_mem_map c0ac4000
[    0.000000]   Normal zone: 512 pages used for memmap
[    0.000000]   Normal zone: 0 pages reserved
[    0.000000]   Normal zone: 65280 pages, LIFO batch:15
[    0.000000] CPU: All CPU(s) started in SVC mode.
[    0.000000] AM335X ES1.0 (neon )
[    0.000000] pcpu-alloc: s0 r0 d32768 u32768 alloc=1*32768
[    0.000000] pcpu-alloc: [0] 0
[    0.000000] Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 64768
[    0.000000] Kernel command line: console=ttyO0,115200n8 noinitrd ip=off mem=256M rootwait=1 ubi.mtd=4,2048 rootfstype=ubifs root=ubi0:rootfs ignore_loglevel
[    0.000000] PID hash table entries: 1024 (order: 0, 4096 bytes)
[    0.000000] Dentry cache hash table entries: 32768 (order: 5, 131072 bytes)
[    0.000000] Inode-cache hash table entries: 16384 (order: 4, 65536 bytes)
[    0.000000] __ex_table already sorted, skipping sort
[    0.000000] Memory: 255MB = 255MB total
[    0.000000] Memory: 247776k/247776k available, 14368k reserved, 0K highmem
[    0.000000] Virtual kernel memory layout:
[    0.000000]     vector  : 0xffff0000 - 0xffff1000   (   4 kB)
[    0.000000]     fixmap  : 0xfff00000 - 0xfffe0000   ( 896 kB)
[    0.000000]     vmalloc : 0xd0800000 - 0xff000000   ( 744 MB)
[    0.000000]     lowmem  : 0xc0000000 - 0xd0000000   ( 256 MB)
[    0.000000]     pkmap   : 0xbfe00000 - 0xc0000000   (   2 MB)
[    0.000000]       .text : 0xc0008000 - 0xc0517550   (5182 kB)
[    0.000000]       .init : 0xc0518000 - 0xc0549fdc   ( 200 kB)
[    0.000000]       .data : 0xc054a000 - 0xc059b420   ( 326 kB)
[    0.000000]        .bss : 0xc059b420 - 0xc0ac0210   (5268 kB)
[    0.000000] NR_IRQS:16 nr_irqs:16 16
[    0.000000] IRQ: Found an INTC at 0xfa200000 (revision 5.0) with 128 interrupts
[    0.000000] Total of 128 interrupts on 1 active controller
[    0.000000] OMAP clockevent source: GPTIMER1 at 26000000 Hz
[    0.000000] sched_clock: 32 bits at 26MHz, resolution 38ns, wraps every 165191ms
[    0.000000] OMAP clocksource: GPTIMER2 at 26000000 Hz
[    0.000000] Console: colour dummy device 80x30
[    0.000000] Lock dependency validator: Copyright (c) 2006 Red Hat, Inc., Ingo Molnar
[    0.000000] ... MAX_LOCKDEP_SUBCLASSES:  8
[    0.000000] ... MAX_LOCK_DEPTH:          48
[    0.000000] ... MAX_LOCKDEP_KEYS:        8191
[    0.000000] ... CLASSHASH_SIZE:          4096
[    0.000000] ... MAX_LOCKDEP_ENTRIES:     16384
[    0.000000] ... MAX_LOCKDEP_CHAINS:      32768
[    0.000000] ... CHAINHASH_SIZE:          16384
[    0.000000]  memory used by lock dependency info: 3695 kB
[    0.000000]  per task-struct memory footprint: 1152 bytes
[    0.000847] Calibrating delay loop... 479.23 BogoMIPS (lpj=2396160)
[    0.109871] pid_max: default: 32768 minimum: 301
[    0.110137] Security Framework initialized
[    0.110240] Mount-cache hash table entries: 512
[    0.120776] CPU: Testing write buffer coherency: ok
[    0.122005] Setting up static identity map for 0xc0401520 - 0xc0401578
[    0.125334] devtmpfs: initialized
[    0.187056] pinctrl core: initialized pinctrl subsystem
[    0.192364] regulator-dummy: no parameters
[    0.194592] NET: Registered protocol family 16
[    0.195373] DMA: preallocated 256 KiB pool for atomic coherent allocations
[    0.213975] gpiochip_add: registered GPIOs 0 to 31 on device: gpio
[    0.214363] OMAP GPIO hardware version 0.1
[    0.217164] gpiochip_add: registered GPIOs 32 to 63 on device: gpio
[    0.219783] gpiochip_add: registered GPIOs 64 to 95 on device: gpio
[    0.222396] gpiochip_add: registered GPIOs 96 to 127 on device: gpio
[    0.237302] omap-gpmc 50000000.gpmc: could not find pctldev for node /pinmux@44e10800/gpmc_pins, deferring probe
[    0.237355] platform 50000000.gpmc: Driver omap-gpmc requests probe deferral
[    0.237973] No ATAGs?
[    0.237993] hw-breakpoint: debug architecture 0x4 unsupported.
[    0.276361] bio: create slab <bio-0> at 0
[    0.342986] omap-dma-engine omap-dma-engine: OMAP DMA engine driver
[    0.349442] usbcore: registered new interface driver usbfs
[    0.350031] usbcore: registered new interface driver hub
[    0.350724] usbcore: registered new device driver usb
[    0.351718] omap_i2c 44e0b000.i2c: could not find pctldev for node /pinmux@44e10800/i2c1_pins, deferring probe
[    0.351765] platform 44e0b000.i2c: Driver omap_i2c requests probe deferral
[    0.358976] cfg80211: Calling CRDA to update world regulatory domain
[    0.360721] Switching to clocksource gp_timer
[    0.410493] NET: Registered protocol family 2
[    0.412172] TCP established hash table entries: 2048 (order: 2, 16384 bytes)
[    0.412382] TCP bind hash table entries: 2048 (order: 4, 73728 bytes)
[    0.413327] TCP: Hash tables configured (established 2048 bind 2048)
[    0.413543] TCP: reno registered
[    0.413576] UDP hash table entries: 256 (order: 2, 20480 bytes)
[    0.413836] UDP-Lite hash table entries: 256 (order: 2, 20480 bytes)
[    0.414647] NET: Registered protocol family 1
[    0.416021] RPC: Registered named UNIX socket transport module.
[    0.416048] RPC: Registered udp transport module.
[    0.416062] RPC: Registered tcp transport module.
[    0.416076] RPC: Registered tcp NFSv4.1 backchannel transport module.
[    0.416981] NetWinder Floating Point Emulator V0.97 (double precision)
[    0.417431] CPU PMU: probing PMU on CPU 0
[    0.417461] hw perfevents: enabled with ARMv7 Cortex-A8 PMU driver, 5 counters available
[    0.429858] msgmni has been set to 483
[    0.434203] io scheduler noop registered
[    0.434229] io scheduler deadline registered
[    0.434299] io scheduler cfq registered (default)
[    0.435365] pinctrl-single 44e10800.pinmux: 142 pins at pa f9e10800 size 568
[    0.436997] Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled
[    0.444362] 44e09000.serial: ttyO0 at MMIO 0x44e09000 (irq = 88) is a OMAP UART0
[    1.057074] console [ttyO0] enabled
[    1.063340] 48022000.serial: ttyO1 at MMIO 0x48022000 (irq = 89) is a OMAP UART1
[    1.072890] 48024000.serial: ttyO2 at MMIO 0x48024000 (irq = 90) is a OMAP UART2
[    1.082323] 481a6000.serial: ttyO3 at MMIO 0x481a6000 (irq = 60) is a OMAP UART3
[    1.091771] 481a8000.serial: ttyO4 at MMIO 0x481a8000 (irq = 61) is a OMAP UART4
[    1.101172] 481aa000.serial: ttyO5 at MMIO 0x481aa000 (irq = 62) is a OMAP UART5
[    1.135992] brd: module loaded
[    1.155121] loop: module loaded
[    1.161971] Generic platform RAM MTD, (c) 2004 Simtec Electronics
[    1.173565] usbcore: registered new interface driver rt2800usb
[    1.180130] usbcore: registered new interface driver asix
[    1.186291] usbcore: registered new interface driver cdc_ether
[    1.192897] usbcore: registered new interface driver smsc95xx
[    1.199347] usbcore: registered new interface driver net1080
[    1.205770] usbcore: registered new interface driver cdc_subset
[    1.212450] usbcore: registered new interface driver zaurus
[    1.218778] usbcore: registered new interface driver cdc_ncm
[    1.226712] usbcore: registered new interface driver cdc_wdm
[    1.233200] usbcore: registered new interface driver usbtest
[    1.239574] i2c /dev entries driver
[    1.246666] omap_wdt: OMAP Watchdog Timer Rev 0x01: initial timeout 60 sec
[    1.255267] omap_cpufreq_init: unable to get MPU regulator
[    1.263425] leds-gpio leds.3: pins are not configured from the driver
[    1.270281] of_get_named_gpio_flags exited with status 5
[    1.275978] of_get_named_gpio_flags exited with status 5
[    1.284737] usbcore: registered new interface driver usbhid
[    1.290643] usbhid: USB HID core driver
[    1.295943] oprofile: using arm/armv7
[    1.300536] TCP: cubic registered
[    1.304134] Initializing XFRM netlink socket
[    1.308766] NET: Registered protocol family 17
[    1.313610] NET: Registered protocol family 15
[    1.318770] Key type dns_resolver registered
[    1.323453] VFP support v0.3: implementor 41 architecture 3 part 30 variant c rev 3
[    1.331650] ThumbEE CPU extension supported.
[    1.340254] omap-gpmc 50000000.gpmc: GPMC revision 6.0
[    1.347867] enabling NAND BCH ecc with 8-bit correction
[    1.353814] ONFI param page 0 valid
[    1.357509] ONFI flash detected
[    1.360873] NAND device: Manufacturer ID: 0x2c, Chip ID: 0xda (Micron MT29F2G08ABAEAWP), 256MiB, page size: 2048, OOB size: 64
[    1.373151] 6 ofpart partitions found on MTD device omap2-nand.0
[    1.379506] Creating 6 MTD partitions on "omap2-nand.0":
[    1.385173] 0x000000000000-0x000000020000 : "spl"
[    1.392610] 0x000000020000-0x0000001e0000 : "boot"
[    1.399934] 0x0000001e0000-0x000000200000 : "env"
[    1.405820] 0x000000200000-0x000000600000 : "kernel"
[    1.415189] 0x000000600000-0x000004600000 : "rootfs"
[    1.476147] 0x000004600000-0x000010000000 : "data"
[    1.645387] omap_i2c 44e0b000.i2c: bus 0 rev0.11 at 400 kHz
[    1.652197] mcp230xx 0-0020: invalid or missing platform data
[    1.658321] mcp230xx: probe of 0-0020 failed with error -22
[    1.669107] DCDC1: at 1800 mV
[    1.674476] vdd_mpu: 925 <--> 1325 mV at 3300 mV
[    1.681644] vdd_core: 925 <--> 1150 mV at 1100 mV
[    1.688614] LDO1: at 1800 mV
[    1.693751] LDO2: at 3300 mV
[    1.698747] LDO3: at 1800 mV
[    1.703850] LDO4: at 2800 mV
[    1.708625] tps65217 0-0024: TPS65217 ID 0x7 version 1.1
[    1.715197] at24 0-0053: 256 byte 24c02 EEPROM, writable, 8 bytes/write
[    1.725928] rtc-ds1307 0-0068: rtc core: registered ds1307 as rtc0
[    1.732584] rtc-ds1307 0-0068: 56 bytes nvram
[    1.739183] UBI: attaching mtd4 to ubi0
[    2.062968] UBI: scanning is finished
[    2.074398] UBI warning: print_rsvd_warning: cannot reserve enough PEBs for bad PEB handling, reserved 4, need 40
[    2.089143] UBI: attached mtd4 (name "rootfs", size 64 MiB) to ubi0
[    2.095874] UBI: PEB size: 131072 bytes (128 KiB), LEB size: 126976 bytes
[    2.103085] UBI: min./max. I/O unit sizes: 2048/2048, sub-page size 512
[    2.110079] UBI: VID header offset: 2048 (aligned 2048), data offset: 4096
[    2.117376] UBI: good PEBs: 512, bad PEBs: 0, corrupted PEBs: 0
[    2.123661] UBI: user volume: 1, internal volumes: 1, max. volumes count: 128
[    2.131233] UBI: max/mean erase counter: 2/1, WL threshold: 4096, image sequence number: 1434266085
[    2.140824] UBI: available PEBs: 0, total reserved PEBs: 512, PEBs reserved for bad PEB handling: 4
[    2.151800] UBI: background thread "ubi_bgt0d" started, PID 591
[    2.220904] davinci_mdio 4a101000.mdio: davinci mdio revision 1.6
[    2.227366] davinci_mdio 4a101000.mdio: detected phy mask fffffffc
[    2.236894] libphy: 4a101000.mdio: probed
[    2.241232] davinci_mdio 4a101000.mdio: phy[0]: device 4a101000.mdio:00, driver SMSC LAN8710/LAN8720
[    2.250932] davinci_mdio 4a101000.mdio: phy[1]: device 4a101000.mdio:01, driver SMSC LAN8710/LAN8720
[    2.260831] Missing dual_emac_res_vlan in DT.
[    2.265440] Using 1 as Reserved VLAN for 0 slave
[    2.270383] Missing dual_emac_res_vlan in DT.
[    2.275018] Using 2 as Reserved VLAN for 1 slave
[    2.280057] Random MACID = 7a:9d:bf:22:b3:c7
[    2.287417] cpsw: Random MACID = 1a:48:dc:88:09:4d
[    2.295871] rtc-ds1307 0-0068: setting system clock to 2013-04-16 11:38:41 UTC (1366112321)
[    2.373950] UBIFS: mounted UBI device 0, volume 0, name "rootfs", R/O mode
[    2.381327] UBIFS: LEB size: 126976 bytes (124 KiB), min./max. I/O unit sizes: 2048 bytes/2048 bytes
[    2.391019] UBIFS: FS size: 60059648 bytes (57 MiB, 473 LEBs), journal size 7999488 bytes (7 MiB, 63 LEBs)
[    2.401254] UBIFS: reserved for root: 0 bytes (0 KiB)
[    2.406601] UBIFS: media format: w4/r0 (latest is w4/r0), UUID 93286679-C044-4BC4-8FCB-6E5055E65825, small LPT model
[    2.419981] VFS: Mounted root (ubifs filesystem) readonly on device 0:12.
[    2.429644] devtmpfs: mounted
[    2.433300] Freeing init memory: 196K
[    2.558990] UBIFS: background thread "ubifs_bgt0_0" started, PID 604
Starting logging: OK
Initializing random number generator... done.
Starting network...
[    2.870749] net eth0: initializing cpsw version 1.12 (0)
[    2.879972] net eth0: phy found : id is : 0x7c0f1
[    2.943874] net eth1: initializing cpsw version 1.12 (0)
[    2.952704] net eth1: phy found : id is : 0x7c0f1
ip: RTNETLINK answers: File exists
Starting dropbear sshd: OK
Starting lighttpd: OK

Welcome to Buildroot
nanobone login: root
Password: 
[    5.951540] libphy: 4a101000.mdio:00 - Link is Up - 100/Full

# cat /etc/network/interfaces
# Configure Loopback
auto lo eth0 eth1
iface lo inet loopback
iface eth0 inet static
address 10.0.101.111
netmask 255.255.0.0
gateway 10.0.0.1
iface eth1 inet static
address 10.1.101.111
netmask 255.255.0.0
gateway 10.1.0.1

# ifconfig
eth0      Link encap:Ethernet  HWaddr 7A:9D:BF:22:B3:C7
          inet addr:10.0.101.111  Bcast:0.0.0.0  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:11 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:704 (704.0 B)  TX bytes:0 (0.0 B)
          Interrupt:56

eth1      Link encap:Ethernet  HWaddr 1A:48:DC:88:09:4D
          inet addr:10.1.101.111  Bcast:0.0.0.0  Mask:255.255.0.0
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

#
[   20.031081] libphy: 4a101000.mdio:00 - Link is Down
[   24.391357] libphy: 4a101000.mdio:01 - Link is Up - 100/Full
[   30.471110] libphy: 4a101000.mdio:01 - Link is Down
[   33.991395] libphy: 4a101000.mdio:00 - Link is Up - 100/Full
#
#
# ping 10.0.0.1
PING 10.0.0.1 (10.0.0.1): 56 data bytes

--- 10.0.0.1 ping statistics ---
46 packets transmitted, 0 packets received, 100% packet loss
# 
# ping 10.0.101.111
PING 10.0.101.111 (10.0.101.111): 56 data bytes
64 bytes from 10.0.101.111: seq=0 ttl=64 time=0.364 ms
64 bytes from 10.0.101.111: seq=1 ttl=64 time=0.252 ms

--- 10.0.101.111 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.252/0.308/0.364 ms
# ping 127.0.0.1
PING 127.0.0.1 (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: seq=0 ttl=64 time=0.751 ms
64 bytes from 127.0.0.1: seq=1 ttl=64 time=0.303 ms
#


^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH 0/3] Dual EMAC mode implementation of CPSW
@ 2013-04-16 11:09           ` Mark Jackson
  0 siblings, 0 replies; 48+ messages in thread
From: Mark Jackson @ 2013-04-16 11:09 UTC (permalink / raw)
  To: linux-arm-kernel

On 15/04/13 18:34, Mugunthan V N wrote:
> On 4/15/2013 10:58 PM, Mark Jackson wrote:
>> On 15/04/13 18:07, Mugunthan V N wrote:
>>> On 4/15/2013 12:46 AM, Mark Jackson wrote:
>>
>> <snip>
>>
>>>>
>>>> Notice that at the end, the nfs link appears to come back "ok", but
>>>> the "ps" command never completes.
>>>>
>>>> Any ideas of what's going on ?
>>>
>>> I have tried ping on both the interface fine. Will verify with ps again
>>> later in this week.
>>> Can you provide below details details
>>> - Are you using EVMsk or custom build EVM?
>>
>> This is a custom board (based on the BeagleBone design) with dual Ethernet, NAND, NOR and FRAM.
>>
>> The dual emac thing is (one of) the last things to get signed off, so I'm willing to assist in tracking this down.
> 
> After testing the scenario i may be able to send you an update later in this week.

Just a quick update ...

I've now setup our board to boot entirely from NAND (UBoot -> Kernel -> UBIFS) so
that I'm no longer using NFS (just to isolate any issues there).

I am still *unable* to get a connection on either Ethernet port.

*HOWEVER* ... I *can* ping my board from another PC on the network:-

mpfj at mpfj-nanobone:~/uboot/u-boot$ ping 10.0.101.111 -c 5
PING 10.0.101.111 (10.0.101.111) 56(84) bytes of data.
64 bytes from 10.0.101.111: icmp_req=1 ttl=64 time=0.692 ms
64 bytes from 10.0.101.111: icmp_req=2 ttl=64 time=0.551 ms
64 bytes from 10.0.101.111: icmp_req=3 ttl=64 time=0.462 ms
64 bytes from 10.0.101.111: icmp_req=4 ttl=64 time=0.409 ms
64 bytes from 10.0.101.111: icmp_req=5 ttl=64 time=0.344 ms

--- 10.0.101.111 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 3998ms
rtt min/avg/max/mdev = 0.344/0.491/0.692/0.123 ms

So I can't ping *out*, but I can ping *in* !!

Note that I've only tried this ping test to/from eth0 ... I'll
setup another box on the correct IP range so I can also test eth1.

I've added my boot log below.

Cheers
Mark J.
---
U-Boot SPL 2013.04-rc2-00065-g7450e4d-dirty (Apr 16 2013 - 11:36:17)


U-Boot 2013.04-rc2-00065-g7450e4d-dirty (Apr 16 2013 - 11:36:17)

I2C:   ready
DRAM:  256 MiB
WARNING: Caches not enabled
NAND:  256 MiB
MMC:   OMAP SD/MMC: 0, OMAP SD/MMC: 1
Net:   cpsw:0 is connected to cpsw.  Reconnecting to cpsw
cpsw
Hit any key to stop autoboot:  0

NAND read: device 0 offset 0x200000, size 0x400000
 4194304 bytes read: OK
## Booting kernel from Legacy Image at 80200000 ...
   Image Name:   Linux 3.9.0-rc7-00023-gfcc38a5
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    2997518 Bytes = 2.9 MiB
   Load Address: 80008000
   Entry Point:  80008000
   Verifying Checksum ... OK
   Loading Kernel Image ... OK
OK

Starting kernel ...

[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Linux version 3.9.0-rc7-00023-gfcc38a5 (mpfj at mpfj-nanobone) (gcc version 4.5.4 (Buildroot 2012.11) ) #156 Tue Apr 16 08:55:28 BST 2013
[    0.000000] CPU: ARMv7 Processor [413fc082] revision 2 (ARMv7), cr=10c53c7d
[    0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
[    0.000000] Machine: Generic AM33XX (Flattened Device Tree), model: Newflow AM335x NanoBone
[    0.000000] debug: ignoring loglevel setting.
[    0.000000] Memory policy: ECC disabled, Data cache writeback
[    0.000000] On node 0 totalpages: 65280
[    0.000000] free_area_init_node: node 0, pgdat c059a858, node_mem_map c0ac4000
[    0.000000]   Normal zone: 512 pages used for memmap
[    0.000000]   Normal zone: 0 pages reserved
[    0.000000]   Normal zone: 65280 pages, LIFO batch:15
[    0.000000] CPU: All CPU(s) started in SVC mode.
[    0.000000] AM335X ES1.0 (neon )
[    0.000000] pcpu-alloc: s0 r0 d32768 u32768 alloc=1*32768
[    0.000000] pcpu-alloc: [0] 0
[    0.000000] Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 64768
[    0.000000] Kernel command line: console=ttyO0,115200n8 noinitrd ip=off mem=256M rootwait=1 ubi.mtd=4,2048 rootfstype=ubifs root=ubi0:rootfs ignore_loglevel
[    0.000000] PID hash table entries: 1024 (order: 0, 4096 bytes)
[    0.000000] Dentry cache hash table entries: 32768 (order: 5, 131072 bytes)
[    0.000000] Inode-cache hash table entries: 16384 (order: 4, 65536 bytes)
[    0.000000] __ex_table already sorted, skipping sort
[    0.000000] Memory: 255MB = 255MB total
[    0.000000] Memory: 247776k/247776k available, 14368k reserved, 0K highmem
[    0.000000] Virtual kernel memory layout:
[    0.000000]     vector  : 0xffff0000 - 0xffff1000   (   4 kB)
[    0.000000]     fixmap  : 0xfff00000 - 0xfffe0000   ( 896 kB)
[    0.000000]     vmalloc : 0xd0800000 - 0xff000000   ( 744 MB)
[    0.000000]     lowmem  : 0xc0000000 - 0xd0000000   ( 256 MB)
[    0.000000]     pkmap   : 0xbfe00000 - 0xc0000000   (   2 MB)
[    0.000000]       .text : 0xc0008000 - 0xc0517550   (5182 kB)
[    0.000000]       .init : 0xc0518000 - 0xc0549fdc   ( 200 kB)
[    0.000000]       .data : 0xc054a000 - 0xc059b420   ( 326 kB)
[    0.000000]        .bss : 0xc059b420 - 0xc0ac0210   (5268 kB)
[    0.000000] NR_IRQS:16 nr_irqs:16 16
[    0.000000] IRQ: Found an INTC at 0xfa200000 (revision 5.0) with 128 interrupts
[    0.000000] Total of 128 interrupts on 1 active controller
[    0.000000] OMAP clockevent source: GPTIMER1 at 26000000 Hz
[    0.000000] sched_clock: 32 bits at 26MHz, resolution 38ns, wraps every 165191ms
[    0.000000] OMAP clocksource: GPTIMER2 at 26000000 Hz
[    0.000000] Console: colour dummy device 80x30
[    0.000000] Lock dependency validator: Copyright (c) 2006 Red Hat, Inc., Ingo Molnar
[    0.000000] ... MAX_LOCKDEP_SUBCLASSES:  8
[    0.000000] ... MAX_LOCK_DEPTH:          48
[    0.000000] ... MAX_LOCKDEP_KEYS:        8191
[    0.000000] ... CLASSHASH_SIZE:          4096
[    0.000000] ... MAX_LOCKDEP_ENTRIES:     16384
[    0.000000] ... MAX_LOCKDEP_CHAINS:      32768
[    0.000000] ... CHAINHASH_SIZE:          16384
[    0.000000]  memory used by lock dependency info: 3695 kB
[    0.000000]  per task-struct memory footprint: 1152 bytes
[    0.000847] Calibrating delay loop... 479.23 BogoMIPS (lpj=2396160)
[    0.109871] pid_max: default: 32768 minimum: 301
[    0.110137] Security Framework initialized
[    0.110240] Mount-cache hash table entries: 512
[    0.120776] CPU: Testing write buffer coherency: ok
[    0.122005] Setting up static identity map for 0xc0401520 - 0xc0401578
[    0.125334] devtmpfs: initialized
[    0.187056] pinctrl core: initialized pinctrl subsystem
[    0.192364] regulator-dummy: no parameters
[    0.194592] NET: Registered protocol family 16
[    0.195373] DMA: preallocated 256 KiB pool for atomic coherent allocations
[    0.213975] gpiochip_add: registered GPIOs 0 to 31 on device: gpio
[    0.214363] OMAP GPIO hardware version 0.1
[    0.217164] gpiochip_add: registered GPIOs 32 to 63 on device: gpio
[    0.219783] gpiochip_add: registered GPIOs 64 to 95 on device: gpio
[    0.222396] gpiochip_add: registered GPIOs 96 to 127 on device: gpio
[    0.237302] omap-gpmc 50000000.gpmc: could not find pctldev for node /pinmux at 44e10800/gpmc_pins, deferring probe
[    0.237355] platform 50000000.gpmc: Driver omap-gpmc requests probe deferral
[    0.237973] No ATAGs?
[    0.237993] hw-breakpoint: debug architecture 0x4 unsupported.
[    0.276361] bio: create slab <bio-0> at 0
[    0.342986] omap-dma-engine omap-dma-engine: OMAP DMA engine driver
[    0.349442] usbcore: registered new interface driver usbfs
[    0.350031] usbcore: registered new interface driver hub
[    0.350724] usbcore: registered new device driver usb
[    0.351718] omap_i2c 44e0b000.i2c: could not find pctldev for node /pinmux at 44e10800/i2c1_pins, deferring probe
[    0.351765] platform 44e0b000.i2c: Driver omap_i2c requests probe deferral
[    0.358976] cfg80211: Calling CRDA to update world regulatory domain
[    0.360721] Switching to clocksource gp_timer
[    0.410493] NET: Registered protocol family 2
[    0.412172] TCP established hash table entries: 2048 (order: 2, 16384 bytes)
[    0.412382] TCP bind hash table entries: 2048 (order: 4, 73728 bytes)
[    0.413327] TCP: Hash tables configured (established 2048 bind 2048)
[    0.413543] TCP: reno registered
[    0.413576] UDP hash table entries: 256 (order: 2, 20480 bytes)
[    0.413836] UDP-Lite hash table entries: 256 (order: 2, 20480 bytes)
[    0.414647] NET: Registered protocol family 1
[    0.416021] RPC: Registered named UNIX socket transport module.
[    0.416048] RPC: Registered udp transport module.
[    0.416062] RPC: Registered tcp transport module.
[    0.416076] RPC: Registered tcp NFSv4.1 backchannel transport module.
[    0.416981] NetWinder Floating Point Emulator V0.97 (double precision)
[    0.417431] CPU PMU: probing PMU on CPU 0
[    0.417461] hw perfevents: enabled with ARMv7 Cortex-A8 PMU driver, 5 counters available
[    0.429858] msgmni has been set to 483
[    0.434203] io scheduler noop registered
[    0.434229] io scheduler deadline registered
[    0.434299] io scheduler cfq registered (default)
[    0.435365] pinctrl-single 44e10800.pinmux: 142 pins at pa f9e10800 size 568
[    0.436997] Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled
[    0.444362] 44e09000.serial: ttyO0 at MMIO 0x44e09000 (irq = 88) is a OMAP UART0
[    1.057074] console [ttyO0] enabled
[    1.063340] 48022000.serial: ttyO1 at MMIO 0x48022000 (irq = 89) is a OMAP UART1
[    1.072890] 48024000.serial: ttyO2 at MMIO 0x48024000 (irq = 90) is a OMAP UART2
[    1.082323] 481a6000.serial: ttyO3 at MMIO 0x481a6000 (irq = 60) is a OMAP UART3
[    1.091771] 481a8000.serial: ttyO4 at MMIO 0x481a8000 (irq = 61) is a OMAP UART4
[    1.101172] 481aa000.serial: ttyO5 at MMIO 0x481aa000 (irq = 62) is a OMAP UART5
[    1.135992] brd: module loaded
[    1.155121] loop: module loaded
[    1.161971] Generic platform RAM MTD, (c) 2004 Simtec Electronics
[    1.173565] usbcore: registered new interface driver rt2800usb
[    1.180130] usbcore: registered new interface driver asix
[    1.186291] usbcore: registered new interface driver cdc_ether
[    1.192897] usbcore: registered new interface driver smsc95xx
[    1.199347] usbcore: registered new interface driver net1080
[    1.205770] usbcore: registered new interface driver cdc_subset
[    1.212450] usbcore: registered new interface driver zaurus
[    1.218778] usbcore: registered new interface driver cdc_ncm
[    1.226712] usbcore: registered new interface driver cdc_wdm
[    1.233200] usbcore: registered new interface driver usbtest
[    1.239574] i2c /dev entries driver
[    1.246666] omap_wdt: OMAP Watchdog Timer Rev 0x01: initial timeout 60 sec
[    1.255267] omap_cpufreq_init: unable to get MPU regulator
[    1.263425] leds-gpio leds.3: pins are not configured from the driver
[    1.270281] of_get_named_gpio_flags exited with status 5
[    1.275978] of_get_named_gpio_flags exited with status 5
[    1.284737] usbcore: registered new interface driver usbhid
[    1.290643] usbhid: USB HID core driver
[    1.295943] oprofile: using arm/armv7
[    1.300536] TCP: cubic registered
[    1.304134] Initializing XFRM netlink socket
[    1.308766] NET: Registered protocol family 17
[    1.313610] NET: Registered protocol family 15
[    1.318770] Key type dns_resolver registered
[    1.323453] VFP support v0.3: implementor 41 architecture 3 part 30 variant c rev 3
[    1.331650] ThumbEE CPU extension supported.
[    1.340254] omap-gpmc 50000000.gpmc: GPMC revision 6.0
[    1.347867] enabling NAND BCH ecc with 8-bit correction
[    1.353814] ONFI param page 0 valid
[    1.357509] ONFI flash detected
[    1.360873] NAND device: Manufacturer ID: 0x2c, Chip ID: 0xda (Micron MT29F2G08ABAEAWP), 256MiB, page size: 2048, OOB size: 64
[    1.373151] 6 ofpart partitions found on MTD device omap2-nand.0
[    1.379506] Creating 6 MTD partitions on "omap2-nand.0":
[    1.385173] 0x000000000000-0x000000020000 : "spl"
[    1.392610] 0x000000020000-0x0000001e0000 : "boot"
[    1.399934] 0x0000001e0000-0x000000200000 : "env"
[    1.405820] 0x000000200000-0x000000600000 : "kernel"
[    1.415189] 0x000000600000-0x000004600000 : "rootfs"
[    1.476147] 0x000004600000-0x000010000000 : "data"
[    1.645387] omap_i2c 44e0b000.i2c: bus 0 rev0.11 at 400 kHz
[    1.652197] mcp230xx 0-0020: invalid or missing platform data
[    1.658321] mcp230xx: probe of 0-0020 failed with error -22
[    1.669107] DCDC1: at 1800 mV
[    1.674476] vdd_mpu: 925 <--> 1325 mV at 3300 mV
[    1.681644] vdd_core: 925 <--> 1150 mV at 1100 mV
[    1.688614] LDO1: at 1800 mV
[    1.693751] LDO2: at 3300 mV
[    1.698747] LDO3: at 1800 mV
[    1.703850] LDO4: at 2800 mV
[    1.708625] tps65217 0-0024: TPS65217 ID 0x7 version 1.1
[    1.715197] at24 0-0053: 256 byte 24c02 EEPROM, writable, 8 bytes/write
[    1.725928] rtc-ds1307 0-0068: rtc core: registered ds1307 as rtc0
[    1.732584] rtc-ds1307 0-0068: 56 bytes nvram
[    1.739183] UBI: attaching mtd4 to ubi0
[    2.062968] UBI: scanning is finished
[    2.074398] UBI warning: print_rsvd_warning: cannot reserve enough PEBs for bad PEB handling, reserved 4, need 40
[    2.089143] UBI: attached mtd4 (name "rootfs", size 64 MiB) to ubi0
[    2.095874] UBI: PEB size: 131072 bytes (128 KiB), LEB size: 126976 bytes
[    2.103085] UBI: min./max. I/O unit sizes: 2048/2048, sub-page size 512
[    2.110079] UBI: VID header offset: 2048 (aligned 2048), data offset: 4096
[    2.117376] UBI: good PEBs: 512, bad PEBs: 0, corrupted PEBs: 0
[    2.123661] UBI: user volume: 1, internal volumes: 1, max. volumes count: 128
[    2.131233] UBI: max/mean erase counter: 2/1, WL threshold: 4096, image sequence number: 1434266085
[    2.140824] UBI: available PEBs: 0, total reserved PEBs: 512, PEBs reserved for bad PEB handling: 4
[    2.151800] UBI: background thread "ubi_bgt0d" started, PID 591
[    2.220904] davinci_mdio 4a101000.mdio: davinci mdio revision 1.6
[    2.227366] davinci_mdio 4a101000.mdio: detected phy mask fffffffc
[    2.236894] libphy: 4a101000.mdio: probed
[    2.241232] davinci_mdio 4a101000.mdio: phy[0]: device 4a101000.mdio:00, driver SMSC LAN8710/LAN8720
[    2.250932] davinci_mdio 4a101000.mdio: phy[1]: device 4a101000.mdio:01, driver SMSC LAN8710/LAN8720
[    2.260831] Missing dual_emac_res_vlan in DT.
[    2.265440] Using 1 as Reserved VLAN for 0 slave
[    2.270383] Missing dual_emac_res_vlan in DT.
[    2.275018] Using 2 as Reserved VLAN for 1 slave
[    2.280057] Random MACID = 7a:9d:bf:22:b3:c7
[    2.287417] cpsw: Random MACID = 1a:48:dc:88:09:4d
[    2.295871] rtc-ds1307 0-0068: setting system clock to 2013-04-16 11:38:41 UTC (1366112321)
[    2.373950] UBIFS: mounted UBI device 0, volume 0, name "rootfs", R/O mode
[    2.381327] UBIFS: LEB size: 126976 bytes (124 KiB), min./max. I/O unit sizes: 2048 bytes/2048 bytes
[    2.391019] UBIFS: FS size: 60059648 bytes (57 MiB, 473 LEBs), journal size 7999488 bytes (7 MiB, 63 LEBs)
[    2.401254] UBIFS: reserved for root: 0 bytes (0 KiB)
[    2.406601] UBIFS: media format: w4/r0 (latest is w4/r0), UUID 93286679-C044-4BC4-8FCB-6E5055E65825, small LPT model
[    2.419981] VFS: Mounted root (ubifs filesystem) readonly on device 0:12.
[    2.429644] devtmpfs: mounted
[    2.433300] Freeing init memory: 196K
[    2.558990] UBIFS: background thread "ubifs_bgt0_0" started, PID 604
Starting logging: OK
Initializing random number generator... done.
Starting network...
[    2.870749] net eth0: initializing cpsw version 1.12 (0)
[    2.879972] net eth0: phy found : id is : 0x7c0f1
[    2.943874] net eth1: initializing cpsw version 1.12 (0)
[    2.952704] net eth1: phy found : id is : 0x7c0f1
ip: RTNETLINK answers: File exists
Starting dropbear sshd: OK
Starting lighttpd: OK

Welcome to Buildroot
nanobone login: root
Password: 
[    5.951540] libphy: 4a101000.mdio:00 - Link is Up - 100/Full

# cat /etc/network/interfaces
# Configure Loopback
auto lo eth0 eth1
iface lo inet loopback
iface eth0 inet static
address 10.0.101.111
netmask 255.255.0.0
gateway 10.0.0.1
iface eth1 inet static
address 10.1.101.111
netmask 255.255.0.0
gateway 10.1.0.1

# ifconfig
eth0      Link encap:Ethernet  HWaddr 7A:9D:BF:22:B3:C7
          inet addr:10.0.101.111  Bcast:0.0.0.0  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:11 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:704 (704.0 B)  TX bytes:0 (0.0 B)
          Interrupt:56

eth1      Link encap:Ethernet  HWaddr 1A:48:DC:88:09:4D
          inet addr:10.1.101.111  Bcast:0.0.0.0  Mask:255.255.0.0
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

#
[   20.031081] libphy: 4a101000.mdio:00 - Link is Down
[   24.391357] libphy: 4a101000.mdio:01 - Link is Up - 100/Full
[   30.471110] libphy: 4a101000.mdio:01 - Link is Down
[   33.991395] libphy: 4a101000.mdio:00 - Link is Up - 100/Full
#
#
# ping 10.0.0.1
PING 10.0.0.1 (10.0.0.1): 56 data bytes

--- 10.0.0.1 ping statistics ---
46 packets transmitted, 0 packets received, 100% packet loss
# 
# ping 10.0.101.111
PING 10.0.101.111 (10.0.101.111): 56 data bytes
64 bytes from 10.0.101.111: seq=0 ttl=64 time=0.364 ms
64 bytes from 10.0.101.111: seq=1 ttl=64 time=0.252 ms

--- 10.0.101.111 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.252/0.308/0.364 ms
# ping 127.0.0.1
PING 127.0.0.1 (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: seq=0 ttl=64 time=0.751 ms
64 bytes from 127.0.0.1: seq=1 ttl=64 time=0.303 ms
#

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 0/3] Dual EMAC mode implementation of CPSW
  2013-04-15 17:34         ` Mugunthan V N
@ 2013-04-18 16:01           ` Mark Jackson
  -1 siblings, 0 replies; 48+ messages in thread
From: Mark Jackson @ 2013-04-18 16:01 UTC (permalink / raw)
  To: Mugunthan V N; +Cc: netdev, davem, linux-arm-kernel, linux-omap

On 15/04/13 18:34, Mugunthan V N wrote:
> On 4/15/2013 10:58 PM, Mark Jackson wrote:
>> On 15/04/13 18:07, Mugunthan V N wrote:
>>> On 4/15/2013 12:46 AM, Mark Jackson wrote:
>>
>> <snip>
>>
>>>>
>>>> Notice that at the end, the nfs link appears to come back "ok", but
>>>> the "ps" command never completes.
>>>>
>>>> Any ideas of what's going on ?
>>>
>>> I have tried ping on both the interface fine. Will verify with ps again
>>> later in this week.
>>> Can you provide below details details
>>> - Are you using EVMsk or custom build EVM?
>>
>> This is a custom board (based on the BeagleBone design) with dual
>> Ethernet, NAND, NOR and FRAM.
>>
>> The dual emac thing is (one of) the last things to get signed off, so
>> I'm willing to assist in tracking this down.
> 
> After testing the scenario i may be able to send you an update later in
> this week.

I have made some progress ... I realised I was missing a (clearly rather
important !!) item in my .config file, namely CONFIG_TI_DAVINCI_EMAC.

I am now able to ping from our board to other systems on the network
(again, I've only tested eth0 at the moment).

However, I am unable to ping everything I should be able to !!

Here's my setup ...

# cat /etc/network/interfaces
# Configure Loopback
auto lo eth0 eth1
iface lo inet loopback
iface eth1 inet static
address 10.1.101.111
netmask 255.255.0.0
gateway 10.1.0.1
iface eth0 inet static
address 10.0.101.111
netmask 255.255.0.0
gateway 10.0.0.1

# ifconfig
eth0      Link encap:Ethernet  HWaddr C2:21:5E:B4:06:5E
          inet addr:10.0.101.111  Bcast:0.0.0.0  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:67 errors:0 dropped:0 overruns:0 frame:0
          TX packets:62 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:8848 (8.6 KiB)  TX bytes:4290 (4.1 KiB)
          Interrupt:56

eth1      Link encap:Ethernet  HWaddr D6:2F:CF:39:22:4E
          inet addr:10.1.101.111  Bcast:0.0.0.0  Mask:255.255.0.0
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:38 errors:0 dropped:0 overruns:0 frame:0
          TX packets:38 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:4022 (3.9 KiB)  TX bytes:4022 (3.9 KiB)

# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use
Iface
0.0.0.0         10.0.0.1        0.0.0.0         UG    0      0        0 eth0
10.0.0.0        0.0.0.0         255.255.0.0     U     0      0        0 eth0
10.1.0.0        0.0.0.0         255.255.0.0     U     0      0        0 eth1

I can ping a couple of units on 10.0.0.x ...

# ping 10.0.0.120
PING 10.0.0.120 (10.0.0.120): 56 data bytes
64 bytes from 10.0.0.120: seq=0 ttl=64 time=0.955 ms
64 bytes from 10.0.0.120: seq=1 ttl=64 time=0.676 ms
64 bytes from 10.0.0.120: seq=2 ttl=64 time=0.732 ms
64 bytes from 10.0.0.120: seq=3 ttl=64 time=0.762 ms

--- 10.0.0.120 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.676/0.781/0.955 ms
# ping 10.0.0.5
PING 10.0.0.5 (10.0.0.5): 56 data bytes
64 bytes from 10.0.0.5: seq=0 ttl=64 time=1.815 ms
64 bytes from 10.0.0.5: seq=1 ttl=64 time=0.458 ms
64 bytes from 10.0.0.5: seq=2 ttl=64 time=0.474 ms
64 bytes from 10.0.0.5: seq=3 ttl=64 time=0.345 ms
64 bytes from 10.0.0.5: seq=4 ttl=64 time=0.329 ms

--- 10.0.0.5 ping statistics ---
5 packets transmitted, 5 packets received, 0% packet loss
round-trip min/avg/max = 0.329/0.684/1.815 ms

But *not* my router on the same subnet ...

# ping 10.0.0.1
PING 10.0.0.1 (10.0.0.1): 56 data bytes

--- 10.0.0.1 ping statistics ---
15 packets transmitted, 0 packets received, 100% packet loss

I am also unable to ping other equipment that exists:-

# ping 10.0.101.2
PING 10.0.101.2 (10.0.101.2): 56 data bytes

--- 10.0.101.2 ping statistics ---
6 packets transmitted, 0 packets received, 100% packet loss

# ping 10.0.200.2
PING 10.0.200.2 (10.0.200.2): 56 data bytes

--- 10.0.200.2 ping statistics ---
5 packets transmitted, 0 packets received, 100% packet loss

Just to prove these other item do exist, here's me pinging them from
another Linux VM (working off the same physical switch):-

mpfj@mpfj-nanobone:~/linux/linux-2.6$ ifconfig
eth0      Link encap:Ethernet  HWaddr 08:00:27:1e:0d:f5
          inet addr:10.0.0.120  Bcast:10.0.255.255  Mask:255.255.0.0
          inet6 addr: fe80::a00:27ff:fe1e:df5/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:135935 errors:0 dropped:0 overruns:0 frame:0
          TX packets:172692 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:109340858 (109.3 MB)  TX bytes:177519151 (177.5 MB)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:3771 errors:0 dropped:0 overruns:0 frame:0
          TX packets:3771 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:294818 (294.8 KB)  TX bytes:294818 (294.8 KB)

mpfj@mpfj-nanobone:~/linux/linux-2.6$ ping 10.0.0.1
PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
64 bytes from 10.0.0.1: icmp_req=1 ttl=255 time=0.453 ms
64 bytes from 10.0.0.1: icmp_req=2 ttl=255 time=0.445 ms
64 bytes from 10.0.0.1: icmp_req=3 ttl=255 time=0.488 ms
64 bytes from 10.0.0.1: icmp_req=4 ttl=255 time=0.471 ms
64 bytes from 10.0.0.1: icmp_req=5 ttl=255 time=0.460 ms
^C
--- 10.0.0.1 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 3998ms
rtt min/avg/max/mdev = 0.445/0.463/0.488/0.024 ms
mpfj@mpfj-nanobone:~/linux/linux-2.6$ ping 10.0.200.2
PING 10.0.200.2 (10.0.200.2) 56(84) bytes of data.
64 bytes from 10.0.200.2: icmp_req=1 ttl=64 time=2.09 ms
64 bytes from 10.0.200.2: icmp_req=2 ttl=64 time=1.17 ms
64 bytes from 10.0.200.2: icmp_req=3 ttl=64 time=0.994 ms
64 bytes from 10.0.200.2: icmp_req=4 ttl=64 time=0.920 ms
^C
--- 10.0.200.2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 0.920/1.296/2.095/0.471 ms
mpfj@mpfj-nanobone:~/linux/linux-2.6$ ping 10.0.101.2
PING 10.0.101.2 (10.0.101.2) 56(84) bytes of data.
64 bytes from 10.0.101.2: icmp_req=1 ttl=64 time=1.48 ms
64 bytes from 10.0.101.2: icmp_req=2 ttl=64 time=0.939 ms
64 bytes from 10.0.101.2: icmp_req=3 ttl=64 time=0.946 ms
64 bytes from 10.0.101.2: icmp_req=4 ttl=64 time=1.04 ms
^C
--- 10.0.101.2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 0.939/1.104/1.483/0.223 ms

When the pings fail, I am unable to see *any* activity on the network
(using wireshark).

Is there anything else I should try ?

Cheers
Mark J.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH 0/3] Dual EMAC mode implementation of CPSW
@ 2013-04-18 16:01           ` Mark Jackson
  0 siblings, 0 replies; 48+ messages in thread
From: Mark Jackson @ 2013-04-18 16:01 UTC (permalink / raw)
  To: linux-arm-kernel

On 15/04/13 18:34, Mugunthan V N wrote:
> On 4/15/2013 10:58 PM, Mark Jackson wrote:
>> On 15/04/13 18:07, Mugunthan V N wrote:
>>> On 4/15/2013 12:46 AM, Mark Jackson wrote:
>>
>> <snip>
>>
>>>>
>>>> Notice that at the end, the nfs link appears to come back "ok", but
>>>> the "ps" command never completes.
>>>>
>>>> Any ideas of what's going on ?
>>>
>>> I have tried ping on both the interface fine. Will verify with ps again
>>> later in this week.
>>> Can you provide below details details
>>> - Are you using EVMsk or custom build EVM?
>>
>> This is a custom board (based on the BeagleBone design) with dual
>> Ethernet, NAND, NOR and FRAM.
>>
>> The dual emac thing is (one of) the last things to get signed off, so
>> I'm willing to assist in tracking this down.
> 
> After testing the scenario i may be able to send you an update later in
> this week.

I have made some progress ... I realised I was missing a (clearly rather
important !!) item in my .config file, namely CONFIG_TI_DAVINCI_EMAC.

I am now able to ping from our board to other systems on the network
(again, I've only tested eth0 at the moment).

However, I am unable to ping everything I should be able to !!

Here's my setup ...

# cat /etc/network/interfaces
# Configure Loopback
auto lo eth0 eth1
iface lo inet loopback
iface eth1 inet static
address 10.1.101.111
netmask 255.255.0.0
gateway 10.1.0.1
iface eth0 inet static
address 10.0.101.111
netmask 255.255.0.0
gateway 10.0.0.1

# ifconfig
eth0      Link encap:Ethernet  HWaddr C2:21:5E:B4:06:5E
          inet addr:10.0.101.111  Bcast:0.0.0.0  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:67 errors:0 dropped:0 overruns:0 frame:0
          TX packets:62 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:8848 (8.6 KiB)  TX bytes:4290 (4.1 KiB)
          Interrupt:56

eth1      Link encap:Ethernet  HWaddr D6:2F:CF:39:22:4E
          inet addr:10.1.101.111  Bcast:0.0.0.0  Mask:255.255.0.0
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:38 errors:0 dropped:0 overruns:0 frame:0
          TX packets:38 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:4022 (3.9 KiB)  TX bytes:4022 (3.9 KiB)

# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use
Iface
0.0.0.0         10.0.0.1        0.0.0.0         UG    0      0        0 eth0
10.0.0.0        0.0.0.0         255.255.0.0     U     0      0        0 eth0
10.1.0.0        0.0.0.0         255.255.0.0     U     0      0        0 eth1

I can ping a couple of units on 10.0.0.x ...

# ping 10.0.0.120
PING 10.0.0.120 (10.0.0.120): 56 data bytes
64 bytes from 10.0.0.120: seq=0 ttl=64 time=0.955 ms
64 bytes from 10.0.0.120: seq=1 ttl=64 time=0.676 ms
64 bytes from 10.0.0.120: seq=2 ttl=64 time=0.732 ms
64 bytes from 10.0.0.120: seq=3 ttl=64 time=0.762 ms

--- 10.0.0.120 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.676/0.781/0.955 ms
# ping 10.0.0.5
PING 10.0.0.5 (10.0.0.5): 56 data bytes
64 bytes from 10.0.0.5: seq=0 ttl=64 time=1.815 ms
64 bytes from 10.0.0.5: seq=1 ttl=64 time=0.458 ms
64 bytes from 10.0.0.5: seq=2 ttl=64 time=0.474 ms
64 bytes from 10.0.0.5: seq=3 ttl=64 time=0.345 ms
64 bytes from 10.0.0.5: seq=4 ttl=64 time=0.329 ms

--- 10.0.0.5 ping statistics ---
5 packets transmitted, 5 packets received, 0% packet loss
round-trip min/avg/max = 0.329/0.684/1.815 ms

But *not* my router on the same subnet ...

# ping 10.0.0.1
PING 10.0.0.1 (10.0.0.1): 56 data bytes

--- 10.0.0.1 ping statistics ---
15 packets transmitted, 0 packets received, 100% packet loss

I am also unable to ping other equipment that exists:-

# ping 10.0.101.2
PING 10.0.101.2 (10.0.101.2): 56 data bytes

--- 10.0.101.2 ping statistics ---
6 packets transmitted, 0 packets received, 100% packet loss

# ping 10.0.200.2
PING 10.0.200.2 (10.0.200.2): 56 data bytes

--- 10.0.200.2 ping statistics ---
5 packets transmitted, 0 packets received, 100% packet loss

Just to prove these other item do exist, here's me pinging them from
another Linux VM (working off the same physical switch):-

mpfj at mpfj-nanobone:~/linux/linux-2.6$ ifconfig
eth0      Link encap:Ethernet  HWaddr 08:00:27:1e:0d:f5
          inet addr:10.0.0.120  Bcast:10.0.255.255  Mask:255.255.0.0
          inet6 addr: fe80::a00:27ff:fe1e:df5/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:135935 errors:0 dropped:0 overruns:0 frame:0
          TX packets:172692 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:109340858 (109.3 MB)  TX bytes:177519151 (177.5 MB)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:3771 errors:0 dropped:0 overruns:0 frame:0
          TX packets:3771 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:294818 (294.8 KB)  TX bytes:294818 (294.8 KB)

mpfj at mpfj-nanobone:~/linux/linux-2.6$ ping 10.0.0.1
PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
64 bytes from 10.0.0.1: icmp_req=1 ttl=255 time=0.453 ms
64 bytes from 10.0.0.1: icmp_req=2 ttl=255 time=0.445 ms
64 bytes from 10.0.0.1: icmp_req=3 ttl=255 time=0.488 ms
64 bytes from 10.0.0.1: icmp_req=4 ttl=255 time=0.471 ms
64 bytes from 10.0.0.1: icmp_req=5 ttl=255 time=0.460 ms
^C
--- 10.0.0.1 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 3998ms
rtt min/avg/max/mdev = 0.445/0.463/0.488/0.024 ms
mpfj at mpfj-nanobone:~/linux/linux-2.6$ ping 10.0.200.2
PING 10.0.200.2 (10.0.200.2) 56(84) bytes of data.
64 bytes from 10.0.200.2: icmp_req=1 ttl=64 time=2.09 ms
64 bytes from 10.0.200.2: icmp_req=2 ttl=64 time=1.17 ms
64 bytes from 10.0.200.2: icmp_req=3 ttl=64 time=0.994 ms
64 bytes from 10.0.200.2: icmp_req=4 ttl=64 time=0.920 ms
^C
--- 10.0.200.2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 0.920/1.296/2.095/0.471 ms
mpfj at mpfj-nanobone:~/linux/linux-2.6$ ping 10.0.101.2
PING 10.0.101.2 (10.0.101.2) 56(84) bytes of data.
64 bytes from 10.0.101.2: icmp_req=1 ttl=64 time=1.48 ms
64 bytes from 10.0.101.2: icmp_req=2 ttl=64 time=0.939 ms
64 bytes from 10.0.101.2: icmp_req=3 ttl=64 time=0.946 ms
64 bytes from 10.0.101.2: icmp_req=4 ttl=64 time=1.04 ms
^C
--- 10.0.101.2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 0.939/1.104/1.483/0.223 ms

When the pings fail, I am unable to see *any* activity on the network
(using wireshark).

Is there anything else I should try ?

Cheers
Mark J.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 0/3] Dual EMAC mode implementation of CPSW
  2013-04-18 16:01           ` Mark Jackson
@ 2013-04-22 14:07             ` Mark Jackson
  -1 siblings, 0 replies; 48+ messages in thread
From: Mark Jackson @ 2013-04-22 14:07 UTC (permalink / raw)
  To: Mugunthan V N; +Cc: netdev, davem, linux-arm-kernel, linux-omap

On 18/04/13 17:01, Mark Jackson wrote:
> On 15/04/13 18:34, Mugunthan V N wrote:
>> On 4/15/2013 10:58 PM, Mark Jackson wrote:
>>> On 15/04/13 18:07, Mugunthan V N wrote:
>>>> On 4/15/2013 12:46 AM, Mark Jackson wrote:
>>>
>>> <snip>
>>>
>>>>>
>>>>> Notice that at the end, the nfs link appears to come back "ok", but
>>>>> the "ps" command never completes.
>>>>>
>>>>> Any ideas of what's going on ?
>>>>
>>>> I have tried ping on both the interface fine. Will verify with ps again
>>>> later in this week.
>>>> Can you provide below details details
>>>> - Are you using EVMsk or custom build EVM?
>>>
>>> This is a custom board (based on the BeagleBone design) with dual
>>> Ethernet, NAND, NOR and FRAM.
>>>
>>> The dual emac thing is (one of) the last things to get signed off, so
>>> I'm willing to assist in tracking this down.
>>
>> After testing the scenario i may be able to send you an update later in
>> this week.
> 
> I have made some progress ... I realised I was missing a (clearly rather
> important !!) item in my .config file, namely CONFIG_TI_DAVINCI_EMAC.
> 
> I am now able to ping from our board to other systems on the network
> (again, I've only tested eth0 at the moment).
> 
> However, I am unable to ping everything I should be able to !!

<snip>

> When the pings fail, I am unable to see *any* activity on the network
> (using wireshark).
> 
> Is there anything else I should try ?

Mugunthan

Can you confirm that I'm actually trying to achieve the right thing ?

I have all along assumed that Dual EMAC mode would simply provide the
kernel will a pair of independent Ethernet ports.

All I am trying to do is to get both Ethernet ports working so I can
have one port on (say) 10.0.x.x and the other on (say) 10.1.x.x

But there is all this reference to VLANs(in the source code and the TRM)
... I have not setup any VLANs.  Do I need to ?  If so, how ?

Cheers
Mark J.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH 0/3] Dual EMAC mode implementation of CPSW
@ 2013-04-22 14:07             ` Mark Jackson
  0 siblings, 0 replies; 48+ messages in thread
From: Mark Jackson @ 2013-04-22 14:07 UTC (permalink / raw)
  To: linux-arm-kernel

On 18/04/13 17:01, Mark Jackson wrote:
> On 15/04/13 18:34, Mugunthan V N wrote:
>> On 4/15/2013 10:58 PM, Mark Jackson wrote:
>>> On 15/04/13 18:07, Mugunthan V N wrote:
>>>> On 4/15/2013 12:46 AM, Mark Jackson wrote:
>>>
>>> <snip>
>>>
>>>>>
>>>>> Notice that at the end, the nfs link appears to come back "ok", but
>>>>> the "ps" command never completes.
>>>>>
>>>>> Any ideas of what's going on ?
>>>>
>>>> I have tried ping on both the interface fine. Will verify with ps again
>>>> later in this week.
>>>> Can you provide below details details
>>>> - Are you using EVMsk or custom build EVM?
>>>
>>> This is a custom board (based on the BeagleBone design) with dual
>>> Ethernet, NAND, NOR and FRAM.
>>>
>>> The dual emac thing is (one of) the last things to get signed off, so
>>> I'm willing to assist in tracking this down.
>>
>> After testing the scenario i may be able to send you an update later in
>> this week.
> 
> I have made some progress ... I realised I was missing a (clearly rather
> important !!) item in my .config file, namely CONFIG_TI_DAVINCI_EMAC.
> 
> I am now able to ping from our board to other systems on the network
> (again, I've only tested eth0 at the moment).
> 
> However, I am unable to ping everything I should be able to !!

<snip>

> When the pings fail, I am unable to see *any* activity on the network
> (using wireshark).
> 
> Is there anything else I should try ?

Mugunthan

Can you confirm that I'm actually trying to achieve the right thing ?

I have all along assumed that Dual EMAC mode would simply provide the
kernel will a pair of independent Ethernet ports.

All I am trying to do is to get both Ethernet ports working so I can
have one port on (say) 10.0.x.x and the other on (say) 10.1.x.x

But there is all this reference to VLANs(in the source code and the TRM)
... I have not setup any VLANs.  Do I need to ?  If so, how ?

Cheers
Mark J.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 0/3] Dual EMAC mode implementation of CPSW
  2013-04-22 14:07             ` Mark Jackson
  (?)
@ 2013-04-22 17:01               ` Mugunthan V N
  -1 siblings, 0 replies; 48+ messages in thread
From: Mugunthan V N @ 2013-04-22 17:01 UTC (permalink / raw)
  To: Mark Jackson; +Cc: netdev, davem, linux-arm-kernel, linux-omap

On 4/22/2013 7:37 PM, Mark Jackson wrote:
> Mugunthan
>
> Can you confirm that I'm actually trying to achieve the right thing ?
>
> I have all along assumed that Dual EMAC mode would simply provide the
> kernel will a pair of independent Ethernet ports.
Yes, it will provide two network interfaces for ex eth0 and eth1
> All I am trying to do is to get both Ethernet ports working so I can
> have one port on (say) 10.0.x.x and the other on (say) 10.1.x.x
This is perfectly correct
> But there is all this reference to VLANs(in the source code and the TRM)
> ... I have not setup any VLANs.  Do I need to ?  If so, how ?
No need to setup any VLAN. VLAN are used to segregate the
two down stream ports and it will be taken care by the driver

Regards
Mugunthan V N

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 0/3] Dual EMAC mode implementation of CPSW
@ 2013-04-22 17:01               ` Mugunthan V N
  0 siblings, 0 replies; 48+ messages in thread
From: Mugunthan V N @ 2013-04-22 17:01 UTC (permalink / raw)
  To: Mark Jackson; +Cc: netdev, davem, linux-arm-kernel, linux-omap

On 4/22/2013 7:37 PM, Mark Jackson wrote:
> Mugunthan
>
> Can you confirm that I'm actually trying to achieve the right thing ?
>
> I have all along assumed that Dual EMAC mode would simply provide the
> kernel will a pair of independent Ethernet ports.
Yes, it will provide two network interfaces for ex eth0 and eth1
> All I am trying to do is to get both Ethernet ports working so I can
> have one port on (say) 10.0.x.x and the other on (say) 10.1.x.x
This is perfectly correct
> But there is all this reference to VLANs(in the source code and the TRM)
> ... I have not setup any VLANs.  Do I need to ?  If so, how ?
No need to setup any VLAN. VLAN are used to segregate the
two down stream ports and it will be taken care by the driver

Regards
Mugunthan V N

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH 0/3] Dual EMAC mode implementation of CPSW
@ 2013-04-22 17:01               ` Mugunthan V N
  0 siblings, 0 replies; 48+ messages in thread
From: Mugunthan V N @ 2013-04-22 17:01 UTC (permalink / raw)
  To: linux-arm-kernel

On 4/22/2013 7:37 PM, Mark Jackson wrote:
> Mugunthan
>
> Can you confirm that I'm actually trying to achieve the right thing ?
>
> I have all along assumed that Dual EMAC mode would simply provide the
> kernel will a pair of independent Ethernet ports.
Yes, it will provide two network interfaces for ex eth0 and eth1
> All I am trying to do is to get both Ethernet ports working so I can
> have one port on (say) 10.0.x.x and the other on (say) 10.1.x.x
This is perfectly correct
> But there is all this reference to VLANs(in the source code and the TRM)
> ... I have not setup any VLANs.  Do I need to ?  If so, how ?
No need to setup any VLAN. VLAN are used to segregate the
two down stream ports and it will be taken care by the driver

Regards
Mugunthan V N

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 0/3] Dual EMAC mode implementation of CPSW
  2013-04-22 17:01               ` Mugunthan V N
@ 2013-04-23  5:11                 ` Mark Jackson
  -1 siblings, 0 replies; 48+ messages in thread
From: Mark Jackson @ 2013-04-23  5:11 UTC (permalink / raw)
  To: Mugunthan V N, systemprogrammierung.brunner
  Cc: netdev, davem, linux-arm-kernel, linux-omap

On 22/04/13 18:01, Mugunthan V N wrote:
> On 4/22/2013 7:37 PM, Mark Jackson wrote:
>> Mugunthan
>>
>> Can you confirm that I'm actually trying to achieve the right thing ?
>>
>> I have all along assumed that Dual EMAC mode would simply provide the
>> kernel will a pair of independent Ethernet ports.
> Yes, it will provide two network interfaces for ex eth0 and eth1
>> All I am trying to do is to get both Ethernet ports working so I can
>> have one port on (say) 10.0.x.x and the other on (say) 10.1.x.x
> This is perfectly correct
>> But there is all this reference to VLANs(in the source code and the TRM)
>> ... I have not setup any VLANs.  Do I need to ?  If so, how ?
> No need to setup any VLAN. VLAN are used to segregate the
> two down stream ports and it will be taken care by the driver

Mugunthan

I now have this all working, thanks to Markus Brunner who spotted that
the CPSW_VLAN_AWARE bit is being incorrectly set rather than cleared in
cpsw_init_host_port().

I think he will be posting a patch soon.

Regards
Mark J.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH 0/3] Dual EMAC mode implementation of CPSW
@ 2013-04-23  5:11                 ` Mark Jackson
  0 siblings, 0 replies; 48+ messages in thread
From: Mark Jackson @ 2013-04-23  5:11 UTC (permalink / raw)
  To: linux-arm-kernel

On 22/04/13 18:01, Mugunthan V N wrote:
> On 4/22/2013 7:37 PM, Mark Jackson wrote:
>> Mugunthan
>>
>> Can you confirm that I'm actually trying to achieve the right thing ?
>>
>> I have all along assumed that Dual EMAC mode would simply provide the
>> kernel will a pair of independent Ethernet ports.
> Yes, it will provide two network interfaces for ex eth0 and eth1
>> All I am trying to do is to get both Ethernet ports working so I can
>> have one port on (say) 10.0.x.x and the other on (say) 10.1.x.x
> This is perfectly correct
>> But there is all this reference to VLANs(in the source code and the TRM)
>> ... I have not setup any VLANs.  Do I need to ?  If so, how ?
> No need to setup any VLAN. VLAN are used to segregate the
> two down stream ports and it will be taken care by the driver

Mugunthan

I now have this all working, thanks to Markus Brunner who spotted that
the CPSW_VLAN_AWARE bit is being incorrectly set rather than cleared in
cpsw_init_host_port().

I think he will be posting a patch soon.

Regards
Mark J.

^ permalink raw reply	[flat|nested] 48+ messages in thread

end of thread, other threads:[~2013-04-23  5:11 UTC | newest]

Thread overview: 48+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-02-11 19:52 [PATCH 0/3] Dual EMAC mode implementation of CPSW Mugunthan V N
2013-02-11 19:52 ` Mugunthan V N
2013-02-11 19:52 ` Mugunthan V N
2013-02-11 19:52 ` [PATCH 1/3] driver: net: ethernet: davinci_cpdma: add support for directed packet and source port detection Mugunthan V N
2013-02-11 19:52   ` Mugunthan V N
2013-02-11 19:52   ` Mugunthan V N
2013-02-11 19:52 ` [PATCH 2/3] driver: net: ethernet: cpsw: make cpts as pointer Mugunthan V N
2013-02-11 19:52   ` Mugunthan V N
2013-02-11 19:52   ` Mugunthan V N
2013-02-11 19:52 ` [PATCH 3/3] driver: net: ethernet: cpsw: dual emac interface implementation Mugunthan V N
2013-02-11 19:52   ` Mugunthan V N
2013-02-11 19:52   ` Mugunthan V N
     [not found]   ` <1360612340-9266-4-git-send-email-mugunthanvnm-l0cyMroinI0@public.gmane.org>
2013-02-18 13:36     ` Peter Korsgaard
2013-02-18 13:36       ` Peter Korsgaard
     [not found]       ` <87mwv1kaln.fsf-D6SC8u56vOOJDPpyT6T3/w@public.gmane.org>
2013-02-18 15:10         ` Mugunthan V N
2013-02-18 15:10           ` Mugunthan V N
2013-04-14 19:20   ` Mark Jackson
2013-04-14 19:20     ` Mark Jackson
2013-04-15 17:04     ` Mugunthan V N
2013-04-15 17:04       ` Mugunthan V N
2013-04-15 17:04       ` Mugunthan V N
2013-02-12 21:15 ` [PATCH 0/3] Dual EMAC mode implementation of CPSW David Miller
2013-02-12 21:15   ` David Miller
2013-04-12  9:14   ` Mark Jackson
2013-04-12  9:14     ` Mark Jackson
2013-04-14 19:16 ` Mark Jackson
2013-04-14 19:16   ` Mark Jackson
2013-04-15 17:07   ` Mugunthan V N
2013-04-15 17:07     ` Mugunthan V N
2013-04-15 17:07     ` Mugunthan V N
2013-04-15 17:28     ` Mark Jackson
2013-04-15 17:28       ` Mark Jackson
2013-04-15 17:34       ` Mugunthan V N
2013-04-15 17:34         ` Mugunthan V N
2013-04-15 17:34         ` Mugunthan V N
2013-04-15 18:00         ` Mark Jackson
2013-04-15 18:00           ` Mark Jackson
2013-04-16 11:09         ` Mark Jackson
2013-04-16 11:09           ` Mark Jackson
2013-04-18 16:01         ` Mark Jackson
2013-04-18 16:01           ` Mark Jackson
2013-04-22 14:07           ` Mark Jackson
2013-04-22 14:07             ` Mark Jackson
2013-04-22 17:01             ` Mugunthan V N
2013-04-22 17:01               ` Mugunthan V N
2013-04-22 17:01               ` Mugunthan V N
2013-04-23  5:11               ` Mark Jackson
2013-04-23  5:11                 ` Mark Jackson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.