From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751289AbbJWFi0 (ORCPT ); Fri, 23 Oct 2015 01:38:26 -0400 Received: from mail-bl2on0084.outbound.protection.outlook.com ([65.55.169.84]:51968 "EHLO na01-bl2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1750743AbbJWFiW (ORCPT ); Fri, 23 Oct 2015 01:38:22 -0400 Authentication-Results: spf=pass (sender IP is 149.199.60.83) smtp.mailfrom=xilinx.com; vger.kernel.org; dkim=none (message not signed) header.d=none;vger.kernel.org; dmarc=bestguesspass action=none header.from=xilinx.com; From: Kedareswara rao Appana To: , , , , CC: , , , , Kedareswara rao Appana Subject: [PATCH v7] can: xilinx: Convert to runtime_pm Date: Fri, 23 Oct 2015 10:53:38 +0530 Message-ID: <1445577818-26165-1-git-send-email-appanad@xilinx.com> X-Mailer: git-send-email 2.1.2 X-RCIS-Action: ALLOW X-TM-AS-Product-Ver: IMSS-7.1.0.1224-8.0.0.1202-21894.005 X-TM-AS-User-Approved-Sender: Yes;Yes X-EOPAttributedMessage: 0 X-Microsoft-Exchange-Diagnostics: 1;BN1BFFO11OLC001;1:C76t4icURIFG+f/dzpjncdFub8yBadiaaM/+OgpsyWqRdn6QKIvztGc+kT8cM7QA6t0jf7DFH/cras78s2x3jae5aeUthVe1lLscewzFXzItOvRcH0LkIhxATnUU9CH2ruKWUv6XRkB/nZtwfLBEVHSi+tR73CHOl+C7nF3CzzLYjlzSzo0uBJpujdl4xuf8+rdN494yciYAp92Ba8esBzQYjBs7N8IMndisxz3Avs0ooPAr9H4SU1cZLEXLTXgLh/9LX0ROIhQl/RAP8NyhIf+MEl6wr/TUMFvYSPPIrfjdIObxrs8F+tScC/swY+9phbGDgxf/BFDFeCCxPSb/8kAOjwiEY3yT2B2B7K3OR/HQfaLsHTZtijJXeUPbMbKLeRLuAVNoDLPpv6BQqbGBMA== X-Forefront-Antispam-Report: CIP:149.199.60.83;CTRY:US;IPV:NLI;EFV:NLI;SFV:NSPM;SFS:(10009020)(6009001)(2980300002)(438002)(189002)(199003)(5007970100001)(90966002)(2201001)(52956003)(19580395003)(50466002)(86362001)(19580405001)(11100500001)(6806005)(5890100001)(47776003)(48376002)(5008740100001)(103686003)(50226001)(33646002)(42186005)(4001450100002)(45336002)(36386004)(5001920100001)(81156007)(229853001)(189998001)(5001770100001)(5001960100002)(50986999)(107886002)(63266004)(5003940100001)(106466001)(36756003)(87936001)(92566002)(46386002)(107986001)(4001430100001)(2101003);DIR:OUT;SFP:1101;SCL:1;SRVR:BN1BFFO11HUB044;H:xsj-pvapsmtpgw01;FPR:;SPF:Pass;PTR:unknown-60-83.xilinx.com;MX:1;A:1;LANG:en; MIME-Version: 1.0 Content-Type: text/plain X-Microsoft-Exchange-Diagnostics: 1;BN1BFFO11HUB044;2:6VMpbOZP2lf10ybTbEc83Oxbx90lwf4d6yeJko4+ayZO44k6QcOpJNYoYoQqdC3fMhoBsJmyLwuFpnoDEgKRyIurpTreu2NOv3gwK+iacXDRtiCSvu+XHSvEWVrf0zme48qccZNbnUaZrHaA9I+9UDn7K9OToaH8kg2gxX14z48=;3:Yw+9KtHIrnifgZnnajGtmKG2fw6vbKSxpR4U4OLytJnhEK4BBFj3Ynb9k1r56Zrf6eIZuB8at58bt1c+gQFG1o9+CadLuoGm1XvT1r94RMR6eHutACL6aGOl5Jo26Z/4+fJkV4YOQL/qpTKj5RhyC6nesVtHJiQ9/JRYG7nzYuoE7fElKNUIBii1FF5Wjwz8cFwE2zycCSv9XXeq68/9/SI/ae4m8QEZepPrPsFANgz4bfXxEKp5zkLwJvBBDTfywl3FAIv1wlnk6Q8n9MjwZQ==;25:z3VBh/yr8sTFJFiiWJzFlC41td/iS48s33WNzGywdJH/mn3JMVtBfjnyy/vf9GZcO9b6yqfBKKolySTie2OstTfP2x4l27EC1t0GOQqh2SvnL44Obw//alsA1EPOreUohvnDz/meOe48bgJ6AGlQinJKrDuUoXlSeJHk27Kk8ja++dhqN+r2J3bEHMh2E4ZFX+LSubluXT9gZcugCuOEeW38paMfi/48SD0uMttKGKOevEhleZYEHpnraRda+cshVirtoe3oHtPplyOWdlwrgw== X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(8251501001);SRVR:BN1BFFO11HUB044; X-Microsoft-Exchange-Diagnostics: 1;BN1BFFO11HUB044;20:t/HMekON+3DKmiBQGC9VYZA4z8h1dNyK/hJDmP9AWRqoVUkqBYQ458ZVnJQj0w4jxf/cG56N1lizMa2ySN+kdgXNeMU9L7s+xVYMTy/P6tqxON+9UwGhY/WC0/Qx8XTqvB7foAyJVkJ6eQEHHMUJ3ov2MiG7ECKm+dMTcHm9Hi+CyKjlekPhvon5r+7IM4Z4OFcaUej+gIP5JElMTHLwolGsQWJc/+Qj8Fh15KqJgjgQQC3LLPMoWXaYUjgQCauoge7CA/YMYQrbdfYgajkY+wkdyPAqi6yHE76DAM1BWOYEPMiU95Q9cczSNAvcZTYCFJhrLaT70m6p3bZxA4SBbRC3RoMX35o0UvoTpmx/y0RigpU+bkGKTFuR+bSr/V6HRcYtfmEkGMPnRcQAtNHc1soPA2Q0/eq9oJT/i4jy1Een1HaD92EJo8G/dvgE9Ed4qvHd1Ax0SbwDlovMZBWg6DNuXQwS4GauXNcW2n2+khybVSQrPmASOharEXhy7VGD;4:JhTy+nkFkNKidsW37GJ1FBKIXaUsglfirEZDisrXbJDuNBaxBLN/bZ9LxiLtnIWW1KdCh+p6lGHO/rlR/brH+10SxUrTU20zLEBb8Ydfk4qVxiPJclw9cYOQ231ORXYGM5eU79w+qOYDf4VplS4qvQYpgZ/PadfgZeOyCNuxJdWqGDLgnf3V920AvM1zPyogaOv6lcsY+laT74X847DDEOSYiVUG58D6TWvNsvrJilOKMc0qDagqJOgLL/rJdG/TDqb1A8QMSeoaspP70vVJRdArzo2ts/YA2GelHEBtXTdtdGQ5F3n38MOxZVOE8vz0nz+GbKy9eAx0D9iSMa7nk3k55wimEhowZVq2tNkYAjIeLpzL0lEtxvax2MUmtfSe X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(192813158149592); X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(601004)(2401047)(520078)(5005006)(8121501046)(3002001)(102215026);SRVR:BN1BFFO11HUB044;BCL:0;PCL:0;RULEID:;SRVR:BN1BFFO11HUB044; X-Forefront-PRVS: 0738AF4208 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;BN1BFFO11HUB044;23:iAksYyPX+44GVD1z9ZovTftFQ4nC0FzP3sM0FFs?= =?us-ascii?Q?Ii7VHJhelM4RHUJ+ZCaBTZ7BxZ8bVaCkRBAJ+9e/7NqxRIcX36LcHeVVBAPs?= =?us-ascii?Q?1Qvj7X62c1RTpe58C6HytKthiSUVUB0pn3Z7sIA9us0wqGk070otJ6h0DvOw?= =?us-ascii?Q?jVzd79CNE1Afbw5jzQysYKxj1OfRxcdyTjOdvfV1xfmUdRYqrZcO+nNaH+nV?= =?us-ascii?Q?PRgREoGAn6/o7Df7zOW/ulb+272cOW99V6lctvd2Dssc31EpoxJCyy5DZSai?= =?us-ascii?Q?KbjUG1OAUYtSDT6p68eZyNjnG0xiam9MRnWF1ZebqFpurxs+9eeOiicb6yAg?= =?us-ascii?Q?PHu+N+MklpMLnLiplZuUuAJfDAh408HV4STJWN26dkcql66q5dyYgPF29d3m?= =?us-ascii?Q?9FTRswJvyJYvD3bEYNSy2x8qy6zpByqx2zYVrzpokmNlxp5GAnNDFtRpKagN?= =?us-ascii?Q?u0oi0XRTGgZW6qlj5ek2nVRdtLdhbhZ/XHUZWaf+y/x0CHYqTAaHrrdSCSAX?= =?us-ascii?Q?Rfo/HVbNwH4F43NHWQHPC6KuspcsCgWm6MxOg8DDyNL4Tt8uruJhDJUsYWXl?= =?us-ascii?Q?L7JKZ/kmeN5QHEryyuFMh4jKbnBGIWGpWwWBzXFtyd/PuB3QE+A9O+cY94cw?= =?us-ascii?Q?j+B3AMtdc5N6C0eUxs+ip/5RpVqiAj+bw/t0p3hBGm03/L5GERiXUkffbMC8?= =?us-ascii?Q?13u+Bnqjgm7akMbd0G1KYi/X3hN6cIz4B9hUjsPw05LiSFBU8YlJcZCoRP1C?= =?us-ascii?Q?VtO7lau1LOOqVTT+JuqzJaedaaJKEA09P1LIoz+zVqBYKk9fVqT/MOuKnJ0P?= =?us-ascii?Q?9nJZ+edNCwt8d+15NSLL0szEJHxCFDDbXktjBlrrLaoIADP896rH/AqCw4iX?= =?us-ascii?Q?e7TfvYEHAF7LrkUHD0NJ7+gf4DhfBvLUDQJfC/n/WwoZealLiXrTzCPZKqkH?= =?us-ascii?Q?H9qjZavVMJk1ewwEJprazXywwCyWy2uM0K5lSkuLqE4/1rjjFOEUTRPTzJOj?= =?us-ascii?Q?oznFcHrPfQ37U/oRm/ocJYf14ubAp0jpiHMAZaH7hg/5f3lxfMx+PHyDssiu?= =?us-ascii?Q?pCT1Vb3mM64Wk18L5Va5/75n6lCr4Afb/TCI7Q8dNXMB32L7toFnO96FXR/q?= =?us-ascii?Q?S7p1/uzMtwN4/EJNcN97o8J+HRsQHV3TS7ES7BADoNHbJid5vu9FzVMHeceR?= =?us-ascii?Q?SQMj4j8DS70W8ub5QxyL+WANZyZQ69oEZEgsE?= X-Microsoft-Exchange-Diagnostics: 1;BN1BFFO11HUB044;5:XtE61W22uuTuQq5A2KyxdjQ8Bdoa5H/xuHSQf003PGdIWjEVTE/MhwZndKoHjZvECfutbFGrdLIWnPMSZcotdMaVdPAmkXGR9vp+TgwwdyVENZoScEB/9n76dkE8C1LcDeDGL9ASwLgj+wAYbCIZHg==;24:GRCzPMNYK2Fdte1sMA67VdRFrDIk0MiMRE/eTQdml+Rjt/7y4/W2Cr++dN4bQ/0GajkJHUffYA5b3JxaL66Fr80c+4wX/wehImEegfanvBU= SpamDiagnosticOutput: 1:23 SpamDiagnosticMetadata: NSPM X-MS-Exchange-CrossTenant-OriginalArrivalTime: 23 Oct 2015 05:23:52.4830 (UTC) X-MS-Exchange-CrossTenant-Id: 657af505-d5df-48d0-8300-c31994686c5c X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=657af505-d5df-48d0-8300-c31994686c5c;Ip=[149.199.60.83];Helo=[xsj-pvapsmtpgw01] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN1BFFO11HUB044 X-Microsoft-Exchange-Diagnostics: 1;BN1AFFO11HUB040;2:98YLkBu9o77/XhgfFTYzmRbiirW4koau1yuWwkEXvmaspfpjlBFfRp1kKL3SvA6PzeyllhVZN7tUEs9CDYT2EpBWcBpiB1a89/Wm3wLvVfimCTZXLtU8UhazIUOZ9h2Fs7y7tyL0sgywG7IYx3mI+ZcZiDkzukrEtzsSnKlZEKo=;23:V7UE+eFdihTss+KzJ7+rKRNlLc9N5CVgcv47Rr4PcT1Q1qCAo485oTer5AVzv7pUUm8PVB5KP6Mu00lyImnSq5ai7kf2gv9GrpHaOZCeAX0xVITW2P8iXZGBwYYStuk7tNHmg3BsF6z2vihGuhx81+czLicYlwrjVVXFVk9H1dzj9LVCF0Ya10xWrKyT/k7A X-OriginatorOrg: xilinx.com Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Instead of enabling/disabling clocks at several locations in the driver, Use the runtime_pm framework. This consolidates the actions for runtime PM In the appropriate callbacks and makes the driver more readable and mantainable. Signed-off-by: Kedareswara rao Appana --- Changes for v7: - Removed the unnecessary clk_prepare/clk_unprepare calls From the probe and remove as suggested by Soren. Changes for v6: - Updated the driver with review comments as suggested by Marc. Changes for v5: - Updated with the review comments. Updated the remove fuction to use runtime_pm. Chnages for v4: - Updated with the review comments. Changes for v3: - Converted the driver to use runtime_pm. Changes for v2: - Removed the struct platform_device* from suspend/resume as suggest by Lothar. drivers/net/can/xilinx_can.c | 177 +++++++++++++++++++++++++------------------ 1 file changed, 102 insertions(+), 75 deletions(-) diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c index fc55e8e..fcb584f 100644 --- a/drivers/net/can/xilinx_can.c +++ b/drivers/net/can/xilinx_can.c @@ -32,6 +32,7 @@ #include #include #include +#include #define DRIVER_NAME "xilinx_can" @@ -138,7 +139,7 @@ struct xcan_priv { u32 (*read_reg)(const struct xcan_priv *priv, enum xcan_reg reg); void (*write_reg)(const struct xcan_priv *priv, enum xcan_reg reg, u32 val); - struct net_device *dev; + struct device *dev; void __iomem *reg_base; unsigned long irq_flags; struct clk *bus_clk; @@ -843,6 +844,13 @@ static int xcan_open(struct net_device *ndev) struct xcan_priv *priv = netdev_priv(ndev); int ret; + ret = pm_runtime_get_sync(priv->dev); + if (ret < 0) { + netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n", + __func__, ret); + return ret; + } + ret = request_irq(ndev->irq, xcan_interrupt, priv->irq_flags, ndev->name, ndev); if (ret < 0) { @@ -850,29 +858,17 @@ static int xcan_open(struct net_device *ndev) goto err; } - ret = clk_prepare_enable(priv->can_clk); - if (ret) { - netdev_err(ndev, "unable to enable device clock\n"); - goto err_irq; - } - - ret = clk_prepare_enable(priv->bus_clk); - if (ret) { - netdev_err(ndev, "unable to enable bus clock\n"); - goto err_can_clk; - } - /* Set chip into reset mode */ ret = set_reset_mode(ndev); if (ret < 0) { netdev_err(ndev, "mode resetting failed!\n"); - goto err_bus_clk; + goto err_irq; } /* Common open */ ret = open_candev(ndev); if (ret) - goto err_bus_clk; + goto err_irq; ret = xcan_chip_start(ndev); if (ret < 0) { @@ -888,13 +884,11 @@ static int xcan_open(struct net_device *ndev) err_candev: close_candev(ndev); -err_bus_clk: - clk_disable_unprepare(priv->bus_clk); -err_can_clk: - clk_disable_unprepare(priv->can_clk); err_irq: free_irq(ndev->irq, ndev); err: + pm_runtime_put(priv->dev); + return ret; } @@ -911,12 +905,11 @@ static int xcan_close(struct net_device *ndev) netif_stop_queue(ndev); napi_disable(&priv->napi); xcan_chip_stop(ndev); - clk_disable_unprepare(priv->bus_clk); - clk_disable_unprepare(priv->can_clk); free_irq(ndev->irq, ndev); close_candev(ndev); can_led_event(ndev, CAN_LED_EVENT_STOP); + pm_runtime_put(priv->dev); return 0; } @@ -935,27 +928,20 @@ static int xcan_get_berr_counter(const struct net_device *ndev, struct xcan_priv *priv = netdev_priv(ndev); int ret; - ret = clk_prepare_enable(priv->can_clk); - if (ret) - goto err; - - ret = clk_prepare_enable(priv->bus_clk); - if (ret) - goto err_clk; + ret = pm_runtime_get_sync(priv->dev); + if (ret < 0) { + netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n", + __func__, ret); + return ret; + } bec->txerr = priv->read_reg(priv, XCAN_ECR_OFFSET) & XCAN_ECR_TEC_MASK; bec->rxerr = ((priv->read_reg(priv, XCAN_ECR_OFFSET) & XCAN_ECR_REC_MASK) >> XCAN_ESR_REC_SHIFT); - clk_disable_unprepare(priv->bus_clk); - clk_disable_unprepare(priv->can_clk); + pm_runtime_put(priv->dev); return 0; - -err_clk: - clk_disable_unprepare(priv->can_clk); -err: - return ret; } @@ -968,15 +954,45 @@ static const struct net_device_ops xcan_netdev_ops = { /** * xcan_suspend - Suspend method for the driver - * @dev: Address of the platform_device structure + * @dev: Address of the device structure * * Put the driver into low power mode. - * Return: 0 always + * Return: 0 on success and failure value on error */ static int __maybe_unused xcan_suspend(struct device *dev) { - struct platform_device *pdev = dev_get_drvdata(dev); - struct net_device *ndev = platform_get_drvdata(pdev); + if (!device_may_wakeup(dev)) + return pm_runtime_force_suspend(dev); + + return 0; +} + +/** + * xcan_resume - Resume from suspend + * @dev: Address of the device structure + * + * Resume operation after suspend. + * Return: 0 on success and failure value on error + */ +static int __maybe_unused xcan_resume(struct device *dev) +{ + if (!device_may_wakeup(dev)) + return pm_runtime_force_resume(dev); + + return 0; + +} + +/** + * xcan_runtime_suspend - Runtime suspend method for the driver + * @dev: Address of the device structure + * + * Put the driver into low power mode. + * Return: 0 always + */ +static int __maybe_unused xcan_runtime_suspend(struct device *dev) +{ + struct net_device *ndev = dev_get_drvdata(dev); struct xcan_priv *priv = netdev_priv(ndev); if (netif_running(ndev)) { @@ -987,43 +1003,55 @@ static int __maybe_unused xcan_suspend(struct device *dev) priv->write_reg(priv, XCAN_MSR_OFFSET, XCAN_MSR_SLEEP_MASK); priv->can.state = CAN_STATE_SLEEPING; - clk_disable(priv->bus_clk); - clk_disable(priv->can_clk); + clk_disable_unprepare(priv->bus_clk); + clk_disable_unprepare(priv->can_clk); return 0; } /** - * xcan_resume - Resume from suspend - * @dev: Address of the platformdevice structure + * xcan_runtime_resume - Runtime resume from suspend + * @dev: Address of the device structure * * Resume operation after suspend. * Return: 0 on success and failure value on error */ -static int __maybe_unused xcan_resume(struct device *dev) +static int __maybe_unused xcan_runtime_resume(struct device *dev) { - struct platform_device *pdev = dev_get_drvdata(dev); - struct net_device *ndev = platform_get_drvdata(pdev); + struct net_device *ndev = dev_get_drvdata(dev); struct xcan_priv *priv = netdev_priv(ndev); int ret; + u32 isr, status; - ret = clk_enable(priv->bus_clk); + ret = clk_prepare_enable(priv->bus_clk); if (ret) { dev_err(dev, "Cannot enable clock.\n"); return ret; } - ret = clk_enable(priv->can_clk); + ret = clk_prepare_enable(priv->can_clk); if (ret) { dev_err(dev, "Cannot enable clock.\n"); clk_disable_unprepare(priv->bus_clk); return ret; } - priv->write_reg(priv, XCAN_MSR_OFFSET, 0); - priv->write_reg(priv, XCAN_SRR_OFFSET, XCAN_SRR_CEN_MASK); - priv->can.state = CAN_STATE_ERROR_ACTIVE; + priv->write_reg(priv, XCAN_SRR_OFFSET, XCAN_SRR_RESET_MASK); + isr = priv->read_reg(priv, XCAN_ISR_OFFSET); + status = priv->read_reg(priv, XCAN_SR_OFFSET); if (netif_running(ndev)) { + if (isr & XCAN_IXR_BSOFF_MASK) { + priv->can.state = CAN_STATE_BUS_OFF; + priv->write_reg(priv, XCAN_SRR_OFFSET, + XCAN_SRR_RESET_MASK); + } else if ((status & XCAN_SR_ESTAT_MASK) == + XCAN_SR_ESTAT_MASK) { + priv->can.state = CAN_STATE_ERROR_PASSIVE; + } else if (status & XCAN_SR_ERRWRN_MASK) { + priv->can.state = CAN_STATE_ERROR_WARNING; + } else { + priv->can.state = CAN_STATE_ERROR_ACTIVE; + } netif_device_attach(ndev); netif_start_queue(ndev); } @@ -1031,7 +1059,10 @@ static int __maybe_unused xcan_resume(struct device *dev) return 0; } -static SIMPLE_DEV_PM_OPS(xcan_dev_pm_ops, xcan_suspend, xcan_resume); +static const struct dev_pm_ops xcan_dev_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(xcan_suspend, xcan_resume) + SET_RUNTIME_PM_OPS(xcan_runtime_suspend, xcan_runtime_resume, NULL) +}; /** * xcan_probe - Platform registration call @@ -1072,7 +1103,7 @@ static int xcan_probe(struct platform_device *pdev) return -ENOMEM; priv = netdev_priv(ndev); - priv->dev = ndev; + priv->dev = &pdev->dev; priv->can.bittiming_const = &xcan_bittiming_const; priv->can.do_set_mode = xcan_do_set_mode; priv->can.do_get_berr_counter = xcan_get_berr_counter; @@ -1114,21 +1145,18 @@ static int xcan_probe(struct platform_device *pdev) } } - ret = clk_prepare_enable(priv->can_clk); - if (ret) { - dev_err(&pdev->dev, "unable to enable device clock\n"); - goto err_free; - } - - ret = clk_prepare_enable(priv->bus_clk); - if (ret) { - dev_err(&pdev->dev, "unable to enable bus clock\n"); - goto err_unprepare_disable_dev; - } - priv->write_reg = xcan_write_reg_le; priv->read_reg = xcan_read_reg_le; + pm_runtime_irq_safe(&pdev->dev); + pm_runtime_enable(&pdev->dev); + ret = pm_runtime_get_sync(&pdev->dev); + if (ret < 0) { + netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n", + __func__, ret); + goto err_pmdisable; + } + if (priv->read_reg(priv, XCAN_SR_OFFSET) != XCAN_SR_CONFIG_MASK) { priv->write_reg = xcan_write_reg_be; priv->read_reg = xcan_read_reg_be; @@ -1141,22 +1169,23 @@ static int xcan_probe(struct platform_device *pdev) ret = register_candev(ndev); if (ret) { dev_err(&pdev->dev, "fail to register failed (err=%d)\n", ret); - goto err_unprepare_disable_busclk; + goto err_disableclks; } devm_can_led_init(ndev); - clk_disable_unprepare(priv->bus_clk); - clk_disable_unprepare(priv->can_clk); + + pm_runtime_put(&pdev->dev); + netdev_dbg(ndev, "reg_base=0x%p irq=%d clock=%d, tx fifo depth:%d\n", priv->reg_base, ndev->irq, priv->can.clock.freq, priv->tx_max); return 0; -err_unprepare_disable_busclk: - clk_disable_unprepare(priv->bus_clk); -err_unprepare_disable_dev: - clk_disable_unprepare(priv->can_clk); +err_disableclks: + pm_runtime_put(priv->dev); +err_pmdisable: + pm_runtime_disable(&pdev->dev); err_free: free_candev(ndev); err: @@ -1175,10 +1204,8 @@ static int xcan_remove(struct platform_device *pdev) struct net_device *ndev = platform_get_drvdata(pdev); struct xcan_priv *priv = netdev_priv(ndev); - if (set_reset_mode(ndev) < 0) - netdev_err(ndev, "mode resetting failed!\n"); - unregister_candev(ndev); + pm_runtime_disable(&pdev->dev); netif_napi_del(&priv->napi); free_candev(ndev); -- 2.1.2