All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/9] post cpdma/mdio refactoring fixes
@ 2010-09-13 18:07 Cyril Chemparathy
       [not found] ` <1284401251-8846-1-git-send-email-cyril-l0cyMroinI0@public.gmane.org>
                   ` (9 more replies)
  0 siblings, 10 replies; 11+ messages in thread
From: Cyril Chemparathy @ 2010-09-13 18:07 UTC (permalink / raw)
  To: netdev, davinci-linux-open-source, linux-omap
  Cc: michael.williamson, caglarakyuz, bparrot, Cyril Chemparathy

This series consists of fixes for issues found during broader testing of the
davinci cpdma/mdio separation series.

The fixes included here are:

  1. Ability to force 100/full rather than auto-detect phy.  This is necessary
     for the external switch on the da830 evm platform

  2. Fix end-of-queue requeue to include checks at submission time (in
     addition to pre-existing completion time checks).

  3. Cleanups to rx path error handling.  This prevents unnecessary stack
     dumps for perfectly legal situations.

  4. Work around for emac-soft-reset tie-up to mdio controller.  This affects
     all da8xx family devices (and possibly am35xx as well).

  5. Reworked hard-coded scan-time estimate to use a more accurate calculated
     number instead.

  6. Code to generate cpdma register dumps, useful during debug.


Many thanks to Mike and Caglar for patiently working with me through these
issues, I've taken the liberty of adding their sign offs.

Cyril Chemparathy (9):
  net: davinci_emac: allow forced 100/full via phy_id
  davinci: specify phy_id rather than auto-detect
  net: davinci_cpdma: requeue on early end-of-queue
  net: davinci_emac: fix rx error handling
  net: davinci_mdio: separate out controller reset
  net: davinci_mdio: use calculated bus access times
  net: davinci_mdio: work around emac soft-reset during i/o
  net: davinci_cpdma: add register dump routines
  net: davinci_emac: extended register dumps on tx timeout

 arch/arm/mach-davinci/board-da830-evm.c    |    2 +
 arch/arm/mach-davinci/board-da850-evm.c    |    3 +
 arch/arm/mach-davinci/board-dm365-evm.c    |    4 +
 arch/arm/mach-davinci/board-dm644x-evm.c   |    3 +
 arch/arm/mach-davinci/board-dm646x-evm.c   |    5 +
 arch/arm/mach-davinci/board-mityomapl138.c |    3 +
 arch/arm/mach-davinci/board-neuros-osd2.c  |    4 +
 arch/arm/mach-davinci/board-sffsdr.c       |    4 +
 drivers/net/davinci_cpdma.c                |  132 ++++++++++++++++++-
 drivers/net/davinci_cpdma.h                |    3 +
 drivers/net/davinci_emac.c                 |   31 ++++-
 drivers/net/davinci_mdio.c                 |  195 ++++++++++++++++++++--------
 include/linux/davinci_emac.h               |    7 +
 13 files changed, 334 insertions(+), 62 deletions(-)


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

* [PATCH 1/9] net: davinci_emac: allow forced 100/full via phy_id
       [not found] ` <1284401251-8846-1-git-send-email-cyril-l0cyMroinI0@public.gmane.org>
@ 2010-09-13 18:07   ` Cyril Chemparathy
  0 siblings, 0 replies; 11+ messages in thread
From: Cyril Chemparathy @ 2010-09-13 18:07 UTC (permalink / raw)
  To: netdev-u79uwXL29TY76Z2rM5mHXA,
	davinci-linux-open-source-VycZQUHpC/PFrsHnngEfi1aTQe2KTcn/,
	linux-omap-u79uwXL29TY76Z2rM5mHXA

With this patch, phy_id can be one of the following:
  1) NULL		: use the first phy on the bus,
  2) ""			: force to 100/full, no mdio control
  3) "<bus>:<addr>"	: use the specified bus and phy

The ability to force 100/full is necessary on some platforms (e.g. da830 evm),
where an on-board switch may be connected on the emac mii.

Signed-off-by: Cyril Chemparathy <cyril-l0cyMroinI0@public.gmane.org>
Signed-off-by: Michael Williamson <michael.williamson-wZX4cNJlHJ2sVWG7oymsAA@public.gmane.org>
Signed-off-by: Caglar Akyuz <caglarakyuz-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
 drivers/net/davinci_emac.c   |    2 +-
 include/linux/davinci_emac.h |    7 +++++++
 2 files changed, 8 insertions(+), 1 deletions(-)

diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c
index 525b84c..363c970 100644
--- a/drivers/net/davinci_emac.c
+++ b/drivers/net/davinci_emac.c
@@ -1566,7 +1566,7 @@ static int emac_dev_open(struct net_device *ndev)
 			priv->phy_id = dev_name(phy);
 	}
 
-	if (priv->phy_id) {
+	if (priv->phy_id && *priv->phy_id) {
 		priv->phydev = phy_connect(ndev, priv->phy_id,
 					   &emac_adjust_link, 0,
 					   PHY_INTERFACE_MODE_MII);
diff --git a/include/linux/davinci_emac.h b/include/linux/davinci_emac.h
index 7508e49..9ae9ff0 100644
--- a/include/linux/davinci_emac.h
+++ b/include/linux/davinci_emac.h
@@ -25,6 +25,13 @@ struct emac_platform_data {
 	u32 ctrl_ram_offset;
 	u32 hw_ram_addr;
 	u32 ctrl_ram_size;
+
+	/*
+	 * phy_id can be one of the following:
+	 *   - NULL		: use the first phy on the bus,
+	 *   - ""		: force to 100/full, no mdio control
+	 *   - "<bus>:<addr>"	: use the specified bus and phy
+	 */
 	const char *phy_id;
 	u8 rmii_en;
 	u8 version;
-- 
1.7.0.4

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

* [PATCH 2/9] davinci: specify phy_id rather than auto-detect
  2010-09-13 18:07 [PATCH 0/9] post cpdma/mdio refactoring fixes Cyril Chemparathy
       [not found] ` <1284401251-8846-1-git-send-email-cyril-l0cyMroinI0@public.gmane.org>
@ 2010-09-13 18:07 ` Cyril Chemparathy
  2010-09-13 18:07 ` [PATCH 3/9] net: davinci_cpdma: requeue on early end-of-queue Cyril Chemparathy
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Cyril Chemparathy @ 2010-09-13 18:07 UTC (permalink / raw)
  To: netdev, davinci-linux-open-source, linux-omap
  Cc: michael.williamson, caglarakyuz, bparrot, Cyril Chemparathy

The cpdma/mdio refactoring incorrectly defaulted to using the first phy
detected on the platform.  Although auto detection works on most sane
platforms, it can prove to be problematic on some.

For example, the da830/omap-l137 evm has an on-board switch that always
connects 100/full.  Consequently, normal phy auto-detection does not work
on this platform.

Rather than risk breaking other boards, this patch reverts to using hard-coded
phy ids on platforms that did so earlier.

Signed-off-by: Cyril Chemparathy <cyril@ti.com>
Signed-off-by: Michael Williamson <michael.williamson@criticallink.com>
Signed-off-by: Caglar Akyuz <caglarakyuz@gmail.com>
---
 arch/arm/mach-davinci/board-da830-evm.c    |    2 ++
 arch/arm/mach-davinci/board-da850-evm.c    |    3 +++
 arch/arm/mach-davinci/board-dm365-evm.c    |    4 ++++
 arch/arm/mach-davinci/board-dm644x-evm.c   |    3 +++
 arch/arm/mach-davinci/board-dm646x-evm.c   |    5 +++++
 arch/arm/mach-davinci/board-mityomapl138.c |    3 +++
 arch/arm/mach-davinci/board-neuros-osd2.c  |    4 ++++
 arch/arm/mach-davinci/board-sffsdr.c       |    4 ++++
 8 files changed, 28 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c
index 2613324..1bb89d3 100644
--- a/arch/arm/mach-davinci/board-da830-evm.c
+++ b/arch/arm/mach-davinci/board-da830-evm.c
@@ -31,6 +31,7 @@
 #include <mach/usb.h>
 #include <mach/aemif.h>
 
+#define DA830_EVM_PHY_ID		""
 /*
  * USB1 VBUS is controlled by GPIO1[15], over-current is reported on GPIO2[4].
  */
@@ -556,6 +557,7 @@ static __init void da830_evm_init(void)
 	da830_evm_usb_init();
 
 	soc_info->emac_pdata->rmii_en = 1;
+	soc_info->emac_pdata->phy_id = DA830_EVM_PHY_ID;
 
 	ret = davinci_cfg_reg_list(da830_cpgmac_pins);
 	if (ret)
diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index 9d4dfcb..5e435b0 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -38,6 +38,7 @@
 #include <mach/mux.h>
 #include <mach/aemif.h>
 
+#define DA850_EVM_PHY_ID		"0:00"
 #define DA850_LCD_PWR_PIN		GPIO_TO_PIN(2, 8)
 #define DA850_LCD_BL_PIN		GPIO_TO_PIN(2, 15)
 
@@ -675,6 +676,8 @@ static int __init da850_evm_config_emac(void)
 	/* Enable/Disable MII MDIO clock */
 	gpio_direction_output(DA850_MII_MDIO_CLKEN_PIN, rmii_en);
 
+	soc_info->emac_pdata->phy_id = DA850_EVM_PHY_ID;
+
 	ret = da8xx_register_emac();
 	if (ret)
 		pr_warning("da850_evm_init: emac registration failed: %d\n",
diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c
index f697914..86d9abc 100644
--- a/arch/arm/mach-davinci/board-dm365-evm.c
+++ b/arch/arm/mach-davinci/board-dm365-evm.c
@@ -54,6 +54,7 @@ static inline int have_tvp7002(void)
 	return 0;
 }
 
+#define DM365_EVM_PHY_ID		"0:01"
 /*
  * A MAX-II CPLD is used for various board control functions.
  */
@@ -527,12 +528,15 @@ fail:
 		/* externally mux MMC1/ENET/AIC33 to imager */
 		mux |= BIT(6) | BIT(5) | BIT(3);
 	} else {
+		struct davinci_soc_info *soc_info = &davinci_soc_info;
+
 		/* we can use MMC1 ... */
 		dm365evm_mmc_configure();
 		davinci_setup_mmc(1, &dm365evm_mmc_config);
 
 		/* ... and ENET ... */
 		dm365evm_emac_configure();
+		soc_info->emac_pdata->phy_id = DM365_EVM_PHY_ID;
 		resets &= ~BIT(3);
 
 		/* ... and AIC33 */
diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c
index c86bf23..44a2f0a 100644
--- a/arch/arm/mach-davinci/board-dm644x-evm.c
+++ b/arch/arm/mach-davinci/board-dm644x-evm.c
@@ -39,6 +39,7 @@
 #include <mach/usb.h>
 #include <mach/aemif.h>
 
+#define DM644X_EVM_PHY_ID		"0:01"
 #define LXT971_PHY_ID	(0x001378e2)
 #define LXT971_PHY_MASK	(0xfffffff0)
 
@@ -669,6 +670,7 @@ static int davinci_phy_fixup(struct phy_device *phydev)
 static __init void davinci_evm_init(void)
 {
 	struct clk *aemif_clk;
+	struct davinci_soc_info *soc_info = &davinci_soc_info;
 
 	aemif_clk = clk_get(NULL, "aemif");
 	clk_enable(aemif_clk);
@@ -703,6 +705,7 @@ static __init void davinci_evm_init(void)
 	davinci_serial_init(&uart_config);
 	dm644x_init_asp(&dm644x_evm_snd_data);
 
+	soc_info->emac_pdata->phy_id = DM644X_EVM_PHY_ID;
 	/* Register the fixup for PHY on DaVinci */
 	phy_register_fixup_for_uid(LXT971_PHY_ID, LXT971_PHY_MASK,
 					davinci_phy_fixup);
diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c
index 3f34221..67669bb 100644
--- a/arch/arm/mach-davinci/board-dm646x-evm.c
+++ b/arch/arm/mach-davinci/board-dm646x-evm.c
@@ -729,6 +729,7 @@ static struct davinci_uart_config uart_config __initdata = {
 	.enabled_uarts = (1 << 0),
 };
 
+#define DM646X_EVM_PHY_ID		"0:01"
 /*
  * The following EDMA channels/slots are not being used by drivers (for
  * example: Timer, GPIO, UART events etc) on dm646x, hence they are being
@@ -764,6 +765,8 @@ static struct edma_rsv_info dm646x_edma_rsv[] = {
 
 static __init void evm_init(void)
 {
+	struct davinci_soc_info *soc_info = &davinci_soc_info;
+
 	evm_init_i2c();
 	davinci_serial_init(&uart_config);
 	dm646x_init_mcasp0(&dm646x_evm_snd_data[0]);
@@ -778,6 +781,8 @@ static __init void evm_init(void)
 
 	if (HAS_ATA)
 		davinci_init_ide();
+
+	soc_info->emac_pdata->phy_id = DM646X_EVM_PHY_ID;
 }
 
 #define DM646X_EVM_REF_FREQ		27000000
diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c
index e872fcc..6f12a18 100644
--- a/arch/arm/mach-davinci/board-mityomapl138.c
+++ b/arch/arm/mach-davinci/board-mityomapl138.c
@@ -24,6 +24,7 @@
 #include <mach/nand.h>
 #include <mach/mux.h>
 
+#define MITYOMAPL138_PHY_ID		"0:03"
 static struct davinci_i2c_platform_data mityomap_i2c_0_pdata = {
 	.bus_freq	= 100,	/* kHz */
 	.bus_delay	= 0,	/* usec */
@@ -270,6 +271,8 @@ static void __init mityomapl138_config_emac(void)
 	/* configure the CFGCHIP3 register for RMII or MII */
 	__raw_writel(val, cfg_chip3_base);
 
+	soc_info->emac_pdata->phy_id = MITYOMAPL138_PHY_ID;
+
 	ret = da8xx_register_emac();
 	if (ret)
 		pr_warning("emac registration failed: %d\n", ret);
diff --git a/arch/arm/mach-davinci/board-neuros-osd2.c b/arch/arm/mach-davinci/board-neuros-osd2.c
index 4b32f0a..04a8d16 100644
--- a/arch/arm/mach-davinci/board-neuros-osd2.c
+++ b/arch/arm/mach-davinci/board-neuros-osd2.c
@@ -39,6 +39,7 @@
 #include <mach/mmc.h>
 #include <mach/usb.h>
 
+#define NEUROS_OSD2_PHY_ID		"0:01"
 #define LXT971_PHY_ID			0x001378e2
 #define LXT971_PHY_MASK			0xfffffff0
 
@@ -215,6 +216,7 @@ static struct davinci_mmc_config davinci_ntosd2_mmc_config = {
 static __init void davinci_ntosd2_init(void)
 {
 	struct clk *aemif_clk;
+	struct davinci_soc_info *soc_info = &davinci_soc_info;
 	int	status;
 
 	aemif_clk = clk_get(NULL, "aemif");
@@ -248,6 +250,8 @@ static __init void davinci_ntosd2_init(void)
 	davinci_serial_init(&uart_config);
 	dm644x_init_asp(&dm644x_ntosd2_snd_data);
 
+	soc_info->emac_pdata->phy_id = NEUROS_OSD2_PHY_ID;
+
 	davinci_setup_usb(1000, 8);
 	/*
 	 * Mux the pins to be GPIOs, VLYNQEN is already done at startup.
diff --git a/arch/arm/mach-davinci/board-sffsdr.c b/arch/arm/mach-davinci/board-sffsdr.c
index b372d7f..ab4292d 100644
--- a/arch/arm/mach-davinci/board-sffsdr.c
+++ b/arch/arm/mach-davinci/board-sffsdr.c
@@ -42,6 +42,7 @@
 #include <mach/mux.h>
 #include <mach/usb.h>
 
+#define SFFSDR_PHY_ID		"0:01"
 static struct mtd_partition davinci_sffsdr_nandflash_partition[] = {
 	/* U-Boot Environment: Block 0
 	 * UBL:                Block 1
@@ -134,10 +135,13 @@ static void __init davinci_sffsdr_map_io(void)
 
 static __init void davinci_sffsdr_init(void)
 {
+	struct davinci_soc_info *soc_info = &davinci_soc_info;
+
 	platform_add_devices(davinci_sffsdr_devices,
 			     ARRAY_SIZE(davinci_sffsdr_devices));
 	sffsdr_init_i2c();
 	davinci_serial_init(&uart_config);
+	soc_info->emac_pdata->phy_id = SFFSDR_PHY_ID;
 	davinci_setup_usb(0, 0); /* We support only peripheral mode. */
 
 	/* mux VLYNQ pins */
-- 
1.7.0.4


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

* [PATCH 3/9] net: davinci_cpdma: requeue on early end-of-queue
  2010-09-13 18:07 [PATCH 0/9] post cpdma/mdio refactoring fixes Cyril Chemparathy
       [not found] ` <1284401251-8846-1-git-send-email-cyril-l0cyMroinI0@public.gmane.org>
  2010-09-13 18:07 ` [PATCH 2/9] davinci: specify phy_id rather than auto-detect Cyril Chemparathy
@ 2010-09-13 18:07 ` Cyril Chemparathy
  2010-09-13 18:07 ` [PATCH 4/9] net: davinci_emac: fix rx error handling Cyril Chemparathy
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Cyril Chemparathy @ 2010-09-13 18:07 UTC (permalink / raw)
  To: netdev, davinci-linux-open-source, linux-omap
  Cc: michael.williamson, caglarakyuz, bparrot, Cyril Chemparathy

When chaining descriptors to the end of a cpdma queue, there is a chance that
the cpdma engine has already traversed the last descriptor and signalled an
end-of-queue.  The original cpdma code detected this condition and requeued
descriptors on submission.

With this patch, an early end-of-queue condition is detected on descriptor
submission as well.  This is necessary on davinci style emac controllers, and
prevents transmit timeouts when sending out a burst of packets.

Signed-off-by: Cyril Chemparathy <cyril@ti.com>
Signed-off-by: Michael Williamson <michael.williamson@criticallink.com>
Signed-off-by: Caglar Akyuz <caglarakyuz@gmail.com>
---
 drivers/net/davinci_cpdma.c |   12 ++++++++++--
 drivers/net/davinci_cpdma.h |    1 +
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/drivers/net/davinci_cpdma.c b/drivers/net/davinci_cpdma.c
index ab7ecd7..abc2b14 100644
--- a/drivers/net/davinci_cpdma.c
+++ b/drivers/net/davinci_cpdma.c
@@ -488,6 +488,7 @@ static void __cpdma_chan_submit(struct cpdma_chan *chan,
 	struct cpdma_desc __iomem	*prev = chan->tail;
 	struct cpdma_desc_pool		*pool = ctlr->pool;
 	dma_addr_t			desc_dma;
+	u32				mode;
 
 	desc_dma = desc_phys(pool, desc);
 
@@ -507,8 +508,10 @@ static void __cpdma_chan_submit(struct cpdma_chan *chan,
 	chan->stats.tail_enqueue++;
 
 	/* next check if EOQ has been triggered already */
-	if (desc_read(prev, hw_mode) & CPDMA_DESC_EOQ &&
-	    chan->state == CPDMA_STATE_ACTIVE) {
+	mode = desc_read(prev, hw_mode);
+	if (((mode & (CPDMA_DESC_EOQ | CPDMA_DESC_OWNER)) == CPDMA_DESC_EOQ) &&
+	    (chan->state == CPDMA_STATE_ACTIVE)) {
+		desc_write(prev, hw_mode, mode & ~CPDMA_DESC_EOQ);
 		chan_write(chan, hdp, desc_dma);
 		chan->stats.misqueued++;
 	}
@@ -618,6 +621,11 @@ static int __cpdma_chan_process(struct cpdma_chan *chan)
 	chan->count--;
 	chan->stats.good_dequeue++;
 
+	if (status & CPDMA_DESC_EOQ) {
+		chan->stats.requeue++;
+		chan_write(chan, hdp, desc_phys(pool, chan->head));
+	}
+
 	spin_unlock_irqrestore(&chan->lock, flags);
 
 	__cpdma_chan_free(chan, desc, outlen, status);
diff --git a/drivers/net/davinci_cpdma.h b/drivers/net/davinci_cpdma.h
index d50ee35..9baacca 100644
--- a/drivers/net/davinci_cpdma.h
+++ b/drivers/net/davinci_cpdma.h
@@ -56,6 +56,7 @@ struct cpdma_chan_stats {
 	u32			empty_dequeue;
 	u32			busy_dequeue;
 	u32			good_dequeue;
+	u32			requeue;
 	u32			teardown_dequeue;
 };
 
-- 
1.7.0.4


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

* [PATCH 4/9] net: davinci_emac: fix rx error handling
  2010-09-13 18:07 [PATCH 0/9] post cpdma/mdio refactoring fixes Cyril Chemparathy
                   ` (2 preceding siblings ...)
  2010-09-13 18:07 ` [PATCH 3/9] net: davinci_cpdma: requeue on early end-of-queue Cyril Chemparathy
@ 2010-09-13 18:07 ` Cyril Chemparathy
  2010-09-13 18:07 ` [PATCH 5/9] net: davinci_mdio: separate out controller reset Cyril Chemparathy
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Cyril Chemparathy @ 2010-09-13 18:07 UTC (permalink / raw)
  To: netdev, davinci-linux-open-source, linux-omap
  Cc: michael.williamson, caglarakyuz, bparrot, Cyril Chemparathy

This patch adds the following fixes to the emac receive handler:

1. WARN_ON during interface shutdown.
   Although harmless, these complaints were quite disconcerting.  With this
   patch, the receive handler explicitly checks for the shutdown condition, in
   which case is bails quietly.

2. Update rx_error stats on dma receive error

3. Rate limit error messages on buffer allocation failures

Signed-off-by: Cyril Chemparathy <cyril@ti.com>
Signed-off-by: Michael Williamson <michael.williamson@criticallink.com>
Signed-off-by: Caglar Akyuz <caglarakyuz@gmail.com>
---
 drivers/net/davinci_emac.c |   25 +++++++++++++++++++------
 1 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c
index 363c970..9e866ae 100644
--- a/drivers/net/davinci_emac.c
+++ b/drivers/net/davinci_emac.c
@@ -1002,13 +1002,22 @@ static void emac_rx_handler(void *token, int len, int status)
 	struct sk_buff		*skb = token;
 	struct net_device	*ndev = skb->dev;
 	struct emac_priv	*priv = netdev_priv(ndev);
+	struct device		*emac_dev = &ndev->dev;
 	int			ret;
 
+	/* free and bail if we are shutting down */
+	if (unlikely(!netif_running(ndev))) {
+		dev_kfree_skb_any(skb);
+		return;
+	}
+
+	/* recycle on recieve error */
 	if (status < 0) {
-		/* error */
+		ndev->stats.rx_errors++;
 		goto recycle;
 	}
 
+	/* feed received packet up the stack */
 	skb_put(skb, len);
 	skb->protocol = eth_type_trans(skb, ndev);
 	netif_receive_skb(skb);
@@ -1017,13 +1026,17 @@ static void emac_rx_handler(void *token, int len, int status)
 
 	/* alloc a new packet for receive */
 	skb = emac_rx_alloc(priv);
+	if (!skb) {
+		if (netif_msg_rx_err(priv) && net_ratelimit())
+			dev_err(emac_dev, "failed rx buffer alloc\n");
+		return;
+	}
 
 recycle:
-	if (skb) {
-		ret = cpdma_chan_submit(priv->rxchan, skb, skb->data,
-					skb_tailroom(skb), GFP_KERNEL);
-		WARN_ON(ret < 0);
-	}
+	ret = cpdma_chan_submit(priv->rxchan, skb, skb->data,
+			skb_tailroom(skb), GFP_KERNEL);
+	if (WARN_ON(ret < 0))
+		dev_kfree_skb_any(skb);
 }
 
 static void emac_tx_handler(void *token, int len, int status)
-- 
1.7.0.4


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

* [PATCH 5/9] net: davinci_mdio: separate out controller reset
  2010-09-13 18:07 [PATCH 0/9] post cpdma/mdio refactoring fixes Cyril Chemparathy
                   ` (3 preceding siblings ...)
  2010-09-13 18:07 ` [PATCH 4/9] net: davinci_emac: fix rx error handling Cyril Chemparathy
@ 2010-09-13 18:07 ` Cyril Chemparathy
  2010-09-13 18:07 ` [PATCH 6/9] net: davinci_mdio: use calculated bus access times Cyril Chemparathy
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Cyril Chemparathy @ 2010-09-13 18:07 UTC (permalink / raw)
  To: netdev, davinci-linux-open-source, linux-omap
  Cc: michael.williamson, caglarakyuz, bparrot, Cyril Chemparathy

This patch separates out the controller reset logic, and makes this available
via mii_bus->reset.

Signed-off-by: Cyril Chemparathy <cyril@ti.com>
Signed-off-by: Michael Williamson <michael.williamson@criticallink.com>
Signed-off-by: Caglar Akyuz <caglarakyuz@gmail.com>
---
 drivers/net/davinci_mdio.c |   90 +++++++++++++++++++++++++------------------
 1 files changed, 52 insertions(+), 38 deletions(-)

diff --git a/drivers/net/davinci_mdio.c b/drivers/net/davinci_mdio.c
index d34a53a..a9fbc26 100644
--- a/drivers/net/davinci_mdio.c
+++ b/drivers/net/davinci_mdio.c
@@ -85,6 +85,57 @@ struct davinci_mdio_data {
 	bool		suspended;
 };
 
+static void __davinci_mdio_reset(struct davinci_mdio_data *data)
+{
+	u32 mdio_in, div;
+
+	mdio_in = clk_get_rate(data->clk);
+	div = (mdio_in / data->pdata.bus_freq) - 1;
+	if (div > CONTROL_MAX_DIV)
+		div = CONTROL_MAX_DIV;
+
+	/* set enable and clock divider */
+	__raw_writel(div | CONTROL_ENABLE, &data->regs->control);
+}
+
+static int davinci_mdio_reset(struct mii_bus *bus)
+{
+	struct davinci_mdio_data *data = bus->priv;
+	u32 phy_mask, ver;
+
+	__davinci_mdio_reset(data);
+
+	/*
+	 * wait for scan logic to settle:
+	 * the scan time consists of (a) a large fixed component, and (b) a
+	 * small component that varies with the mii bus frequency.  These
+	 * were estimated using measurements at 1.1 and 2.2 MHz on tnetv107x
+	 * silicon.  Since the effect of (b) was found to be largely
+	 * negligible, we keep things simple here.
+	 */
+	mdelay(1);
+
+	/* dump hardware version info */
+	ver = __raw_readl(&data->regs->version);
+	dev_info(data->dev, "davinci mdio revision %d.%d\n",
+		 (ver >> 8) & 0xff, ver & 0xff);
+
+	/* get phy mask from the alive register */
+	phy_mask = __raw_readl(&data->regs->alive);
+	if (phy_mask) {
+		/* restrict mdio bus to live phys only */
+		dev_info(data->dev, "detected phy mask %x\n", ~phy_mask);
+		phy_mask = ~phy_mask;
+	} else {
+		/* desperately scan all phys */
+		dev_warn(data->dev, "no live phy, scanning all\n");
+		phy_mask = 0;
+	}
+	data->bus->phy_mask = phy_mask;
+
+	return 0;
+}
+
 /* wait until hardware is ready for another user access */
 static inline u32 wait_for_user_access(struct davinci_mdio_data *data)
 {
@@ -163,7 +214,6 @@ static int __devinit davinci_mdio_probe(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	struct davinci_mdio_data *data;
 	struct resource *res;
-	u32 mdio_in_freq, mdio_out_freq, div, phy_mask, ver;
 	struct phy_device *phy;
 	int ret, addr;
 
@@ -185,6 +235,7 @@ static int __devinit davinci_mdio_probe(struct platform_device *pdev)
 	data->bus->name		= dev_name(dev);
 	data->bus->read		= davinci_mdio_read,
 	data->bus->write	= davinci_mdio_write,
+	data->bus->reset	= davinci_mdio_reset,
 	data->bus->parent	= dev;
 	data->bus->priv		= data;
 	snprintf(data->bus->id, MII_BUS_ID_SIZE, "%x", pdev->id);
@@ -225,43 +276,6 @@ static int __devinit davinci_mdio_probe(struct platform_device *pdev)
 		goto bail_out;
 	}
 
-	mdio_in_freq = clk_get_rate(data->clk);
-	div = (mdio_in_freq / data->pdata.bus_freq) - 1;
-	if (div > CONTROL_MAX_DIV)
-		div = CONTROL_MAX_DIV;
-	mdio_out_freq = mdio_in_freq / (div + 1);
-
-	/* set enable and clock divider */
-	__raw_writel(div | CONTROL_ENABLE, &data->regs->control);
-
-	/*
-	 * wait for scan logic to settle:
-	 * the scan time consists of (a) a large fixed component, and (b) a
-	 * small component that varies with the mii bus frequency.  These
-	 * were estimated using measurements at 1.1 and 2.2 MHz on tnetv107x
-	 * silicon.  Since the effect of (b) was found to be largely
-	 * negligible, we keep things simple here.
-	 */
-	mdelay(1);
-
-	/* dump hardware version info */
-	ver = __raw_readl(&data->regs->version);
-	dev_info(dev, "davinci mdio revision %d.%d\n",
-			(ver >> 8) & 0xff, ver & 0xff);
-
-	/* get phy mask from the alive register */
-	phy_mask = __raw_readl(&data->regs->alive);
-	if (phy_mask) {
-		/* restrict mdio bus to live phys only */
-		dev_info(dev, "detected phy mask %x\n", ~phy_mask);
-		phy_mask = ~phy_mask;
-	} else {
-		/* desperately scan all phys */
-		dev_warn(dev, "failed to detect live phys, scanning all\n");
-		phy_mask = 0;
-	}
-	data->bus->phy_mask = phy_mask;
-
 	/* register the mii bus */
 	ret = mdiobus_register(data->bus);
 	if (ret)
-- 
1.7.0.4


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

* [PATCH 6/9] net: davinci_mdio: use calculated bus access times
  2010-09-13 18:07 [PATCH 0/9] post cpdma/mdio refactoring fixes Cyril Chemparathy
                   ` (4 preceding siblings ...)
  2010-09-13 18:07 ` [PATCH 5/9] net: davinci_mdio: separate out controller reset Cyril Chemparathy
@ 2010-09-13 18:07 ` Cyril Chemparathy
  2010-09-13 18:07 ` [PATCH 7/9] net: davinci_mdio: work around emac soft-reset during i/o Cyril Chemparathy
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Cyril Chemparathy @ 2010-09-13 18:07 UTC (permalink / raw)
  To: netdev, davinci-linux-open-source, linux-omap
  Cc: michael.williamson, caglarakyuz, bparrot, Cyril Chemparathy

This patch replaces the hardcoded scan delay with a calculated delay that
adjusts to clock rates.  This delay is calculated on the basis of a worst case
bus transaction time, with generous built-in margins of error.

Signed-off-by: Cyril Chemparathy <cyril@ti.com>
Signed-off-by: Michael Williamson <michael.williamson@criticallink.com>
Signed-off-by: Caglar Akyuz <caglarakyuz@gmail.com>
---
 drivers/net/davinci_mdio.c |   33 +++++++++++++++++++++++----------
 1 files changed, 23 insertions(+), 10 deletions(-)

diff --git a/drivers/net/davinci_mdio.c b/drivers/net/davinci_mdio.c
index a9fbc26..f2d7639 100644
--- a/drivers/net/davinci_mdio.c
+++ b/drivers/net/davinci_mdio.c
@@ -83,11 +83,12 @@ struct davinci_mdio_data {
 	struct device	*dev;
 	struct mii_bus	*bus;
 	bool		suspended;
+	unsigned long	access_time; /* jiffies */
 };
 
 static void __davinci_mdio_reset(struct davinci_mdio_data *data)
 {
-	u32 mdio_in, div;
+	u32 mdio_in, div, mdio_out_khz, access_time;
 
 	mdio_in = clk_get_rate(data->clk);
 	div = (mdio_in / data->pdata.bus_freq) - 1;
@@ -96,6 +97,25 @@ static void __davinci_mdio_reset(struct davinci_mdio_data *data)
 
 	/* set enable and clock divider */
 	__raw_writel(div | CONTROL_ENABLE, &data->regs->control);
+
+	/*
+	 * One mdio transaction consists of:
+	 *	32 bits of preamble
+	 *	32 bits of transferred data
+	 *	24 bits of bus yield (not needed unless shared?)
+	 */
+	mdio_out_khz = mdio_in / (1000 * (div + 1));
+	access_time  = (88 * 1000) / mdio_out_khz;
+
+	/*
+	 * In the worst case, we could be kicking off a user-access immediately
+	 * after the mdio bus scan state-machine triggered its own read.  If
+	 * so, our request could get deferred by one access cycle.  We
+	 * defensively allow for 4 access cycles.
+	 */
+	data->access_time = usecs_to_jiffies(access_time * 4);
+	if (!data->access_time)
+		data->access_time = 1;
 }
 
 static int davinci_mdio_reset(struct mii_bus *bus)
@@ -105,15 +125,8 @@ static int davinci_mdio_reset(struct mii_bus *bus)
 
 	__davinci_mdio_reset(data);
 
-	/*
-	 * wait for scan logic to settle:
-	 * the scan time consists of (a) a large fixed component, and (b) a
-	 * small component that varies with the mii bus frequency.  These
-	 * were estimated using measurements at 1.1 and 2.2 MHz on tnetv107x
-	 * silicon.  Since the effect of (b) was found to be largely
-	 * negligible, we keep things simple here.
-	 */
-	mdelay(1);
+	/* wait for scan logic to settle */
+	msleep(PHY_MAX_ADDR * data->access_time);
 
 	/* dump hardware version info */
 	ver = __raw_readl(&data->regs->version);
-- 
1.7.0.4


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

* [PATCH 7/9] net: davinci_mdio: work around emac soft-reset during i/o
  2010-09-13 18:07 [PATCH 0/9] post cpdma/mdio refactoring fixes Cyril Chemparathy
                   ` (5 preceding siblings ...)
  2010-09-13 18:07 ` [PATCH 6/9] net: davinci_mdio: use calculated bus access times Cyril Chemparathy
@ 2010-09-13 18:07 ` Cyril Chemparathy
  2010-09-13 18:07 ` [PATCH 8/9] net: davinci_cpdma: add register dump routines Cyril Chemparathy
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Cyril Chemparathy @ 2010-09-13 18:07 UTC (permalink / raw)
  To: netdev, davinci-linux-open-source, linux-omap
  Cc: michael.williamson, caglarakyuz, bparrot, Cyril Chemparathy

On certain devices (e.g. da8xx), the hardware design ties emac soft-reset to
the mdio module.  In these cases, when the emac device is opened, an in-flight
mdio transaction could fail by returning the controller to idle state.  This
patch detects this condition and works around it by retrying the failed
transaction.

In addition, defensive timeouts have been added to prevent an indefinite
lockup in case of an unexpected hardware error.

Signed-off-by: Cyril Chemparathy <cyril@ti.com>
Signed-off-by: Michael Williamson <michael.williamson@criticallink.com>
Signed-off-by: Caglar Akyuz <caglarakyuz@gmail.com>
---
 drivers/net/davinci_mdio.c |   92 ++++++++++++++++++++++++++++++++++++-------
 1 files changed, 77 insertions(+), 15 deletions(-)

diff --git a/drivers/net/davinci_mdio.c b/drivers/net/davinci_mdio.c
index f2d7639..7615040 100644
--- a/drivers/net/davinci_mdio.c
+++ b/drivers/net/davinci_mdio.c
@@ -36,6 +36,13 @@
 #include <linux/io.h>
 #include <linux/davinci_emac.h>
 
+/*
+ * This timeout definition is a worst-case ultra defensive measure against
+ * unexpected controller lock ups.  Ideally, we should never ever hit this
+ * scenario in practice.
+ */
+#define MDIO_TIMEOUT		100 /* msecs */
+
 #define PHY_REG_MASK		0x1f
 #define PHY_ID_MASK		0x1f
 
@@ -150,30 +157,53 @@ static int davinci_mdio_reset(struct mii_bus *bus)
 }
 
 /* wait until hardware is ready for another user access */
-static inline u32 wait_for_user_access(struct davinci_mdio_data *data)
+static inline int wait_for_user_access(struct davinci_mdio_data *data)
 {
 	struct davinci_mdio_regs __iomem *regs = data->regs;
+	unsigned long timeout = jiffies + msecs_to_jiffies(MDIO_TIMEOUT);
 	u32 reg;
 
-	while ((reg = __raw_readl(&regs->user[0].access)) & USERACCESS_GO)
-		;
-
-	return reg;
+	while (time_after(timeout, jiffies)) {
+		reg = __raw_readl(&regs->user[0].access);
+		if ((reg & USERACCESS_GO) == 0)
+			return 0;
+
+		reg = __raw_readl(&regs->control);
+		if ((reg & CONTROL_IDLE) == 0)
+			continue;
+
+		/*
+		 * An emac soft_reset may have clobbered the mdio controller's
+		 * state machine.  We need to reset and retry the current
+		 * operation
+		 */
+		dev_warn(data->dev, "resetting idled controller\n");
+		__davinci_mdio_reset(data);
+		return -EAGAIN;
+	}
+	dev_err(data->dev, "timed out waiting for user access\n");
+	return -ETIMEDOUT;
 }
 
 /* wait until hardware state machine is idle */
-static inline void wait_for_idle(struct davinci_mdio_data *data)
+static inline int wait_for_idle(struct davinci_mdio_data *data)
 {
 	struct davinci_mdio_regs __iomem *regs = data->regs;
+	unsigned long timeout = jiffies + msecs_to_jiffies(MDIO_TIMEOUT);
 
-	while ((__raw_readl(&regs->control) & CONTROL_IDLE) == 0)
-		;
+	while (time_after(timeout, jiffies)) {
+		if (__raw_readl(&regs->control) & CONTROL_IDLE)
+			return 0;
+	}
+	dev_err(data->dev, "timed out waiting for idle\n");
+	return -ETIMEDOUT;
 }
 
 static int davinci_mdio_read(struct mii_bus *bus, int phy_id, int phy_reg)
 {
 	struct davinci_mdio_data *data = bus->priv;
 	u32 reg;
+	int ret;
 
 	if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
 		return -EINVAL;
@@ -185,14 +215,32 @@ static int davinci_mdio_read(struct mii_bus *bus, int phy_id, int phy_reg)
 		return -ENODEV;
 	}
 
-	wait_for_user_access(data);
 	reg = (USERACCESS_GO | USERACCESS_READ | (phy_reg << 21) |
 	       (phy_id << 16));
-	__raw_writel(reg, &data->regs->user[0].access);
-	reg = wait_for_user_access(data);
+
+	while (1) {
+		ret = wait_for_user_access(data);
+		if (ret == -EAGAIN)
+			continue;
+		if (ret < 0)
+			break;
+
+		__raw_writel(reg, &data->regs->user[0].access);
+
+		ret = wait_for_user_access(data);
+		if (ret == -EAGAIN)
+			continue;
+		if (ret < 0)
+			break;
+
+		reg = __raw_readl(&data->regs->user[0].access);
+		ret = (reg & USERACCESS_ACK) ? (reg & USERACCESS_DATA) : -EIO;
+		break;
+	}
+
 	spin_unlock(&data->lock);
 
-	return (reg & USERACCESS_ACK) ? (reg & USERACCESS_DATA) : -EIO;
+	return ret;
 }
 
 static int davinci_mdio_write(struct mii_bus *bus, int phy_id,
@@ -200,6 +248,7 @@ static int davinci_mdio_write(struct mii_bus *bus, int phy_id,
 {
 	struct davinci_mdio_data *data = bus->priv;
 	u32 reg;
+	int ret;
 
 	if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
 		return -EINVAL;
@@ -211,11 +260,24 @@ static int davinci_mdio_write(struct mii_bus *bus, int phy_id,
 		return -ENODEV;
 	}
 
-	wait_for_user_access(data);
 	reg = (USERACCESS_GO | USERACCESS_WRITE | (phy_reg << 21) |
 		   (phy_id << 16) | (phy_data & USERACCESS_DATA));
-	__raw_writel(reg, &data->regs->user[0].access);
-	wait_for_user_access(data);
+
+	while (1) {
+		ret = wait_for_user_access(data);
+		if (ret == -EAGAIN)
+			continue;
+		if (ret < 0)
+			break;
+
+		__raw_writel(reg, &data->regs->user[0].access);
+
+		ret = wait_for_user_access(data);
+		if (ret == -EAGAIN)
+			continue;
+		break;
+	}
+
 	spin_unlock(&data->lock);
 
 	return 0;
-- 
1.7.0.4


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

* [PATCH 8/9] net: davinci_cpdma: add register dump routines
  2010-09-13 18:07 [PATCH 0/9] post cpdma/mdio refactoring fixes Cyril Chemparathy
                   ` (6 preceding siblings ...)
  2010-09-13 18:07 ` [PATCH 7/9] net: davinci_mdio: work around emac soft-reset during i/o Cyril Chemparathy
@ 2010-09-13 18:07 ` Cyril Chemparathy
  2010-09-13 18:07 ` [PATCH 9/9] net: davinci_emac: extended register dumps on tx timeout Cyril Chemparathy
  2010-09-14 18:50 ` [PATCH 0/9] post cpdma/mdio refactoring fixes Kevin Hilman
  9 siblings, 0 replies; 11+ messages in thread
From: Cyril Chemparathy @ 2010-09-13 18:07 UTC (permalink / raw)
  To: netdev, davinci-linux-open-source, linux-omap
  Cc: michael.williamson, caglarakyuz, bparrot, Cyril Chemparathy

This patch adds register dump routines at both controller and channel levels.
These are intended to be used in higher level driver debug dumps, e.g.
emac_dump_regs().

Signed-off-by: Cyril Chemparathy <cyril@ti.com>
Signed-off-by: Michael Williamson <michael.williamson@criticallink.com>
Signed-off-by: Caglar Akyuz <caglarakyuz@gmail.com>
---
 drivers/net/davinci_cpdma.c |  120 +++++++++++++++++++++++++++++++++++++++++++
 drivers/net/davinci_cpdma.h |    2 +
 2 files changed, 122 insertions(+), 0 deletions(-)

diff --git a/drivers/net/davinci_cpdma.c b/drivers/net/davinci_cpdma.c
index abc2b14..e92b2b6 100644
--- a/drivers/net/davinci_cpdma.c
+++ b/drivers/net/davinci_cpdma.c
@@ -91,6 +91,8 @@ enum cpdma_state {
 	CPDMA_STATE_TEARDOWN,
 };
 
+const char *cpdma_state_str[] = { "idle", "active", "teardown" };
+
 struct cpdma_ctlr {
 	enum cpdma_state	state;
 	struct cpdma_params	params;
@@ -345,6 +347,76 @@ int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr)
 	return 0;
 }
 
+int cpdma_ctlr_dump(struct cpdma_ctlr *ctlr)
+{
+	struct device *dev = ctlr->dev;
+	unsigned long flags;
+	int i;
+
+	spin_lock_irqsave(&ctlr->lock, flags);
+
+	dev_info(dev, "CPDMA: state: %s", cpdma_state_str[ctlr->state]);
+
+	dev_info(dev, "CPDMA: txidver: %x",
+		 dma_reg_read(ctlr, CPDMA_TXIDVER));
+	dev_info(dev, "CPDMA: txcontrol: %x",
+		 dma_reg_read(ctlr, CPDMA_TXCONTROL));
+	dev_info(dev, "CPDMA: txteardown: %x",
+		 dma_reg_read(ctlr, CPDMA_TXTEARDOWN));
+	dev_info(dev, "CPDMA: rxidver: %x",
+		 dma_reg_read(ctlr, CPDMA_RXIDVER));
+	dev_info(dev, "CPDMA: rxcontrol: %x",
+		 dma_reg_read(ctlr, CPDMA_RXCONTROL));
+	dev_info(dev, "CPDMA: softreset: %x",
+		 dma_reg_read(ctlr, CPDMA_SOFTRESET));
+	dev_info(dev, "CPDMA: rxteardown: %x",
+		 dma_reg_read(ctlr, CPDMA_RXTEARDOWN));
+	dev_info(dev, "CPDMA: txintstatraw: %x",
+		 dma_reg_read(ctlr, CPDMA_TXINTSTATRAW));
+	dev_info(dev, "CPDMA: txintstatmasked: %x",
+		 dma_reg_read(ctlr, CPDMA_TXINTSTATMASKED));
+	dev_info(dev, "CPDMA: txintmaskset: %x",
+		 dma_reg_read(ctlr, CPDMA_TXINTMASKSET));
+	dev_info(dev, "CPDMA: txintmaskclear: %x",
+		 dma_reg_read(ctlr, CPDMA_TXINTMASKCLEAR));
+	dev_info(dev, "CPDMA: macinvector: %x",
+		 dma_reg_read(ctlr, CPDMA_MACINVECTOR));
+	dev_info(dev, "CPDMA: maceoivector: %x",
+		 dma_reg_read(ctlr, CPDMA_MACEOIVECTOR));
+	dev_info(dev, "CPDMA: rxintstatraw: %x",
+		 dma_reg_read(ctlr, CPDMA_RXINTSTATRAW));
+	dev_info(dev, "CPDMA: rxintstatmasked: %x",
+		 dma_reg_read(ctlr, CPDMA_RXINTSTATMASKED));
+	dev_info(dev, "CPDMA: rxintmaskset: %x",
+		 dma_reg_read(ctlr, CPDMA_RXINTMASKSET));
+	dev_info(dev, "CPDMA: rxintmaskclear: %x",
+		 dma_reg_read(ctlr, CPDMA_RXINTMASKCLEAR));
+	dev_info(dev, "CPDMA: dmaintstatraw: %x",
+		 dma_reg_read(ctlr, CPDMA_DMAINTSTATRAW));
+	dev_info(dev, "CPDMA: dmaintstatmasked: %x",
+		 dma_reg_read(ctlr, CPDMA_DMAINTSTATMASKED));
+	dev_info(dev, "CPDMA: dmaintmaskset: %x",
+		 dma_reg_read(ctlr, CPDMA_DMAINTMASKSET));
+	dev_info(dev, "CPDMA: dmaintmaskclear: %x",
+		 dma_reg_read(ctlr, CPDMA_DMAINTMASKCLEAR));
+
+	if (!ctlr->params.has_ext_regs) {
+		dev_info(dev, "CPDMA: dmacontrol: %x",
+			 dma_reg_read(ctlr, CPDMA_DMACONTROL));
+		dev_info(dev, "CPDMA: dmastatus: %x",
+			 dma_reg_read(ctlr, CPDMA_DMASTATUS));
+		dev_info(dev, "CPDMA: rxbuffofs: %x",
+			 dma_reg_read(ctlr, CPDMA_RXBUFFOFS));
+	}
+
+	for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++)
+		if (ctlr->channels[i])
+			cpdma_chan_dump(ctlr->channels[i]);
+
+	spin_unlock_irqrestore(&ctlr->lock, flags);
+	return 0;
+}
+
 int cpdma_ctlr_destroy(struct cpdma_ctlr *ctlr)
 {
 	unsigned long flags;
@@ -481,6 +553,54 @@ int cpdma_chan_get_stats(struct cpdma_chan *chan,
 	return 0;
 }
 
+int cpdma_chan_dump(struct cpdma_chan *chan)
+{
+	unsigned long flags;
+	struct device *dev = chan->ctlr->dev;
+
+	spin_lock_irqsave(&chan->lock, flags);
+
+	dev_info(dev, "channel %d (%s %d) state %s",
+		 chan->chan_num, is_rx_chan(chan) ? "rx" : "tx",
+		 chan_linear(chan), cpdma_state_str[chan->state]);
+	dev_info(dev, "\thdp: %x\n", chan_read(chan, hdp));
+	dev_info(dev, "\tcp: %x\n", chan_read(chan, cp));
+	if (chan->rxfree) {
+		dev_info(dev, "\trxfree: %x\n",
+			 chan_read(chan, rxfree));
+	}
+
+	dev_info(dev, "\tstats head_enqueue: %d\n",
+		 chan->stats.head_enqueue);
+	dev_info(dev, "\tstats tail_enqueue: %d\n",
+		 chan->stats.tail_enqueue);
+	dev_info(dev, "\tstats pad_enqueue: %d\n",
+		 chan->stats.pad_enqueue);
+	dev_info(dev, "\tstats misqueued: %d\n",
+		 chan->stats.misqueued);
+	dev_info(dev, "\tstats desc_alloc_fail: %d\n",
+		 chan->stats.desc_alloc_fail);
+	dev_info(dev, "\tstats pad_alloc_fail: %d\n",
+		 chan->stats.pad_alloc_fail);
+	dev_info(dev, "\tstats runt_receive_buff: %d\n",
+		 chan->stats.runt_receive_buff);
+	dev_info(dev, "\tstats runt_transmit_buff: %d\n",
+		 chan->stats.runt_transmit_buff);
+	dev_info(dev, "\tstats empty_dequeue: %d\n",
+		 chan->stats.empty_dequeue);
+	dev_info(dev, "\tstats busy_dequeue: %d\n",
+		 chan->stats.busy_dequeue);
+	dev_info(dev, "\tstats good_dequeue: %d\n",
+		 chan->stats.good_dequeue);
+	dev_info(dev, "\tstats requeue: %d\n",
+		 chan->stats.requeue);
+	dev_info(dev, "\tstats teardown_dequeue: %d\n",
+		 chan->stats.teardown_dequeue);
+
+	spin_unlock_irqrestore(&chan->lock, flags);
+	return 0;
+}
+
 static void __cpdma_chan_submit(struct cpdma_chan *chan,
 				struct cpdma_desc __iomem *desc)
 {
diff --git a/drivers/net/davinci_cpdma.h b/drivers/net/davinci_cpdma.h
index 9baacca..868e50e 100644
--- a/drivers/net/davinci_cpdma.h
+++ b/drivers/net/davinci_cpdma.h
@@ -69,12 +69,14 @@ struct cpdma_ctlr *cpdma_ctlr_create(struct cpdma_params *params);
 int cpdma_ctlr_destroy(struct cpdma_ctlr *ctlr);
 int cpdma_ctlr_start(struct cpdma_ctlr *ctlr);
 int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr);
+int cpdma_ctlr_dump(struct cpdma_ctlr *ctlr);
 
 struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num,
 				     cpdma_handler_fn handler);
 int cpdma_chan_destroy(struct cpdma_chan *chan);
 int cpdma_chan_start(struct cpdma_chan *chan);
 int cpdma_chan_stop(struct cpdma_chan *chan);
+int cpdma_chan_dump(struct cpdma_chan *chan);
 
 int cpdma_chan_get_stats(struct cpdma_chan *chan,
 			 struct cpdma_chan_stats *stats);
-- 
1.7.0.4


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

* [PATCH 9/9] net: davinci_emac: extended register dumps on tx timeout
  2010-09-13 18:07 [PATCH 0/9] post cpdma/mdio refactoring fixes Cyril Chemparathy
                   ` (7 preceding siblings ...)
  2010-09-13 18:07 ` [PATCH 8/9] net: davinci_cpdma: add register dump routines Cyril Chemparathy
@ 2010-09-13 18:07 ` Cyril Chemparathy
  2010-09-14 18:50 ` [PATCH 0/9] post cpdma/mdio refactoring fixes Kevin Hilman
  9 siblings, 0 replies; 11+ messages in thread
From: Cyril Chemparathy @ 2010-09-13 18:07 UTC (permalink / raw)
  To: netdev, davinci-linux-open-source, linux-omap
  Cc: michael.williamson, caglarakyuz, bparrot, Cyril Chemparathy

This patch hooks up the emac_dump_regs() function to use cpdma dump routines.
Further, we dump registers on transmit timeout, to make such timeouts
debuggable.

Signed-off-by: Cyril Chemparathy <cyril@ti.com>
Signed-off-by: Michael Williamson <michael.williamson@criticallink.com>
Signed-off-by: Caglar Akyuz <caglarakyuz@gmail.com>
---
 drivers/net/davinci_emac.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c
index 9e866ae..2a628d1 100644
--- a/drivers/net/davinci_emac.c
+++ b/drivers/net/davinci_emac.c
@@ -460,6 +460,8 @@ static void emac_dump_regs(struct emac_priv *priv)
 		emac_read(EMAC_RXMOFOVERRUNS));
 	dev_info(emac_dev, "EMAC: rx_dma_overruns:%d\n",
 		emac_read(EMAC_RXDMAOVERRUNS));
+
+	cpdma_ctlr_dump(priv->dma);
 }
 
 /**
@@ -1115,6 +1117,8 @@ static void emac_dev_tx_timeout(struct net_device *ndev)
 	if (netif_msg_tx_err(priv))
 		dev_err(emac_dev, "DaVinci EMAC: xmit timeout, restarting TX");
 
+	emac_dump_regs(priv);
+
 	ndev->stats.tx_errors++;
 	emac_int_disable(priv);
 	cpdma_chan_stop(priv->txchan);
-- 
1.7.0.4


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

* Re: [PATCH 0/9] post cpdma/mdio refactoring fixes
  2010-09-13 18:07 [PATCH 0/9] post cpdma/mdio refactoring fixes Cyril Chemparathy
                   ` (8 preceding siblings ...)
  2010-09-13 18:07 ` [PATCH 9/9] net: davinci_emac: extended register dumps on tx timeout Cyril Chemparathy
@ 2010-09-14 18:50 ` Kevin Hilman
  9 siblings, 0 replies; 11+ messages in thread
From: Kevin Hilman @ 2010-09-14 18:50 UTC (permalink / raw)
  To: Cyril Chemparathy
  Cc: netdev, davinci-linux-open-source, linux-omap,
	michael.williamson, caglarakyuz, bparrot

Cyril Chemparathy <cyril@ti.com> writes:

> This series consists of fixes for issues found during broader testing of the
> davinci cpdma/mdio separation series.
>
> The fixes included here are:
>
>   1. Ability to force 100/full rather than auto-detect phy.  This is necessary
>      for the external switch on the da830 evm platform
>
>   2. Fix end-of-queue requeue to include checks at submission time (in
>      addition to pre-existing completion time checks).
>
>   3. Cleanups to rx path error handling.  This prevents unnecessary stack
>      dumps for perfectly legal situations.
>
>   4. Work around for emac-soft-reset tie-up to mdio controller.  This affects
>      all da8xx family devices (and possibly am35xx as well).
>
>   5. Reworked hard-coded scan-time estimate to use a more accurate calculated
>      number instead.
>
>   6. Code to generate cpdma register dumps, useful during debug.
>
>
> Many thanks to Mike and Caglar for patiently working with me through these
> issues

Thanks for working with them to resolve these issues.

> I've taken the liberty of adding their sign offs.

A sign-off is only for those on the delivery path of the patch.  Can you
update changing those to Tested-By  tags?

If you prefer, you can respin the original series with these fixes
included instead of creating a separate series.  I will then just drop
the original, and queue the new one.

Thanks,

Kevin

> Cyril Chemparathy (9):
>   net: davinci_emac: allow forced 100/full via phy_id
>   davinci: specify phy_id rather than auto-detect
>   net: davinci_cpdma: requeue on early end-of-queue
>   net: davinci_emac: fix rx error handling
>   net: davinci_mdio: separate out controller reset
>   net: davinci_mdio: use calculated bus access times
>   net: davinci_mdio: work around emac soft-reset during i/o
>   net: davinci_cpdma: add register dump routines
>   net: davinci_emac: extended register dumps on tx timeout
>
>  arch/arm/mach-davinci/board-da830-evm.c    |    2 +
>  arch/arm/mach-davinci/board-da850-evm.c    |    3 +
>  arch/arm/mach-davinci/board-dm365-evm.c    |    4 +
>  arch/arm/mach-davinci/board-dm644x-evm.c   |    3 +
>  arch/arm/mach-davinci/board-dm646x-evm.c   |    5 +
>  arch/arm/mach-davinci/board-mityomapl138.c |    3 +
>  arch/arm/mach-davinci/board-neuros-osd2.c  |    4 +
>  arch/arm/mach-davinci/board-sffsdr.c       |    4 +
>  drivers/net/davinci_cpdma.c                |  132 ++++++++++++++++++-
>  drivers/net/davinci_cpdma.h                |    3 +
>  drivers/net/davinci_emac.c                 |   31 ++++-
>  drivers/net/davinci_mdio.c                 |  195 ++++++++++++++++++++--------
>  include/linux/davinci_emac.h               |    7 +
>  13 files changed, 334 insertions(+), 62 deletions(-)
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

end of thread, other threads:[~2010-09-14 18:50 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-09-13 18:07 [PATCH 0/9] post cpdma/mdio refactoring fixes Cyril Chemparathy
     [not found] ` <1284401251-8846-1-git-send-email-cyril-l0cyMroinI0@public.gmane.org>
2010-09-13 18:07   ` [PATCH 1/9] net: davinci_emac: allow forced 100/full via phy_id Cyril Chemparathy
2010-09-13 18:07 ` [PATCH 2/9] davinci: specify phy_id rather than auto-detect Cyril Chemparathy
2010-09-13 18:07 ` [PATCH 3/9] net: davinci_cpdma: requeue on early end-of-queue Cyril Chemparathy
2010-09-13 18:07 ` [PATCH 4/9] net: davinci_emac: fix rx error handling Cyril Chemparathy
2010-09-13 18:07 ` [PATCH 5/9] net: davinci_mdio: separate out controller reset Cyril Chemparathy
2010-09-13 18:07 ` [PATCH 6/9] net: davinci_mdio: use calculated bus access times Cyril Chemparathy
2010-09-13 18:07 ` [PATCH 7/9] net: davinci_mdio: work around emac soft-reset during i/o Cyril Chemparathy
2010-09-13 18:07 ` [PATCH 8/9] net: davinci_cpdma: add register dump routines Cyril Chemparathy
2010-09-13 18:07 ` [PATCH 9/9] net: davinci_emac: extended register dumps on tx timeout Cyril Chemparathy
2010-09-14 18:50 ` [PATCH 0/9] post cpdma/mdio refactoring fixes Kevin Hilman

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.