From patchwork Wed May 2 23:47:18 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Greer X-Patchwork-Id: 156579 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 36AD5B6FB7 for ; Thu, 3 May 2012 09:54:03 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752266Ab2EBXyA (ORCPT ); Wed, 2 May 2012 19:54:00 -0400 Received: from mail20.dotsterhost.com ([66.11.232.73]:40891 "EHLO mail20.dotsterhost.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750893Ab2EBXyA (ORCPT ); Wed, 2 May 2012 19:54:00 -0400 X-Greylist: delayed 396 seconds by postgrey-1.27 at vger.kernel.org; Wed, 02 May 2012 19:54:00 EDT Received: (qmail 26579 invoked from network); 2 May 2012 23:47:19 -0000 Received: from unknown (HELO blue.animalcreek.com) (mgreer@animalcreek.com@[68.2.83.159]) by 66.11.232.73 with SMTP; 2 May 2012 23:47:19 -0000 Received: by blue.animalcreek.com (Postfix, from userid 1001) id D5C8A65C15; Wed, 2 May 2012 16:47:18 -0700 (MST) Date: Wed, 2 May 2012 16:47:18 -0700 From: "Mark A. Greer" To: netdev@vger.kernel.org Cc: linux-omap@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH] net: davinci_emac: Add pre_open, post_stop platform callbacks Message-ID: <20120502234718.GA5432@animalcreek.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.20 (2009-06-14) Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: "Mark A. Greer" The davinci EMAC driver has been incorporated into the am35x family of SoC's which is OMAP-based. The incorporation is incomplete in that the EMAC cannot unblock the [ARM] core if its blocked on a 'wfi' instruction. This is an issue with the cpu_idle code because it has the core execute a 'wfi' instruction. To work around this issue, add platform data callbacks which are called at the beginning of the open routine and at the end of the stop routine of the davinci_emac driver. The callbacks allow the platform code to issue disable_hlt() and enable_hlt() calls appropriately. Calling disable_hlt() prevents cpu_idle from issuing the 'wfi' instruction. It is not sufficient to simply call disable_hlt() when there is an EMAC present because it could be present but not actually used in which case, we do want the 'wfi' to be executed. Signed-off-by: Mark A. Greer --- I know adding platform_data callbacks are frowned upon and I really don't want to add them but I don't see any other way to accomplish what needs to be accomplished. Any suggestions? Thanks, Mark. drivers/net/ethernet/ti/davinci_emac.c | 14 ++++++++++++++ include/linux/davinci_emac.h | 2 ++ 2 files changed, 16 insertions(+) diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c index 174a334..141a888 100644 --- a/drivers/net/ethernet/ti/davinci_emac.c +++ b/drivers/net/ethernet/ti/davinci_emac.c @@ -344,6 +344,8 @@ struct emac_priv { /*platform specific members*/ void (*int_enable) (void); void (*int_disable) (void); + void (*pre_open) (struct net_device *ndev); + void (*post_stop) (struct net_device *ndev); }; /* clock frequency for EMAC */ @@ -1534,6 +1536,9 @@ static int emac_dev_open(struct net_device *ndev) int k = 0; struct emac_priv *priv = netdev_priv(ndev); + if (priv->pre_open) + priv->pre_open(ndev); + netif_carrier_off(ndev); for (cnt = 0; cnt < ETH_ALEN; cnt++) ndev->dev_addr[cnt] = priv->mac_addr[cnt]; @@ -1644,6 +1649,10 @@ rollback: res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, k-1); m = res->end; } + + if (priv->post_stop) + priv->post_stop(ndev); + return -EBUSY; } @@ -1686,6 +1695,9 @@ static int emac_dev_stop(struct net_device *ndev) if (netif_msg_drv(priv)) dev_notice(emac_dev, "DaVinci EMAC: %s stopped\n", ndev->name); + if (priv->post_stop) + priv->post_stop(ndev); + return 0; } @@ -1817,6 +1829,8 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) priv->version = pdata->version; priv->int_enable = pdata->interrupt_enable; priv->int_disable = pdata->interrupt_disable; + priv->pre_open = pdata->pre_open; + priv->post_stop = pdata->post_stop; priv->coal_intvl = 0; priv->bus_freq_mhz = (u32)(emac_bus_frequency / 1000000); diff --git a/include/linux/davinci_emac.h b/include/linux/davinci_emac.h index 5428885..b61e6de 100644 --- a/include/linux/davinci_emac.h +++ b/include/linux/davinci_emac.h @@ -39,6 +39,8 @@ struct emac_platform_data { bool no_bd_ram; void (*interrupt_enable) (void); void (*interrupt_disable) (void); + void (*pre_open) (struct net_device *ndev); + void (*post_stop) (struct net_device *ndev); }; enum {