Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751687AbbKJIdX (ORCPT ); Tue, 10 Nov 2015 03:33:23 -0500 Received: from mail-bl2on0066.outbound.protection.outlook.com ([65.55.169.66]:33248 "EHLO na01-bl2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751113AbbKJIdT convert rfc822-to-8bit (ORCPT ); Tue, 10 Nov 2015 03:33:19 -0500 Authentication-Results: spf=pass (sender IP is 149.199.60.83) smtp.mailfrom=xilinx.com; grandegger.com; dkim=none (message not signed) header.d=none;grandegger.com; dmarc=bestguesspass action=none header.from=xilinx.com; From: Appana Durga Kedareswara Rao To: Appana Durga Kedareswara Rao , Anirudha Sarangi , "wg@grandegger.com" , "mkl@pengutronix.de" , Michal Simek , Soren Brinkmann CC: "linux-can@vger.kernel.org" , "netdev@vger.kernel.org" , "linux-arm-kernel@lists.infradead.org" , "linux-kernel@vger.kernel.org" Subject: RE: [PATCH v8] can: xilinx: Convert to runtime_pm Thread-Topic: [PATCH v8] can: xilinx: Convert to runtime_pm Thread-Index: AQHRD7U/uZgfzds3j0imccSPpng1GZ6VBU+A Date: Tue, 10 Nov 2015 08:33:12 +0000 Message-ID: References: <1445839914-26249-1-git-send-email-appanad@xilinx.com> In-Reply-To: <1445839914-26249-1-git-send-email-appanad@xilinx.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [172.23.95.58] Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 8BIT MIME-Version: 1.0 X-TM-AS-Product-Ver: IMSS-7.1.0.1224-8.0.0.1202-21932.005 X-TM-AS-User-Approved-Sender: Yes;Yes X-EOPAttributedMessage: 0 X-Microsoft-Exchange-Diagnostics: 1;BL2FFO11OLC006;1:ZrGiqh4rESHoUCctSJvGo6W4XJI3abAFXFYaCOi3ja1GOfqtyOvM34cWw/TFqJlN2N9aYJVAic/1snwwrurwzLZbJIAqXe83aSirSK6VncrtoMg4tgzKpH2OUWA0dvvk2TZmmaIKZJ5ROWrPcIvT/fW0Zm0gJHA2gsX8SG9FltMqOCzReDPmtaP51Of/OhgrXzKFNcyYITLfLRXFq1W+yk5NiMH4OlLnz+9nlwYmeeyzwacUETlcMetyS8x6Jthw/oXgnKnytEkQA4jS9TSE2OUmAkH4WKfdPXfUSTv4P7A/oHqJN++IUwbmh0qQGc/jMKB+R4S3lbMKgo3hrnh0eplQNT7epCtSpMLr7ViaAzpG+E7YZ8YWbVSxfEvU+PyZHR6IKxucb2ccTDQCDPzGPg== X-Forefront-Antispam-Report: CIP:149.199.60.83;CTRY:US;IPV:NLI;EFV:NLI;SFV:NSPM;SFS:(10009020)(6009001)(2980300002)(438002)(199003)(189002)(13464003)(377454003)(55846006)(5004730100002)(86362001)(92566002)(76176999)(4001450100002)(63266004)(2201001)(50466002)(189998001)(5008740100001)(11100500001)(5890100001)(87936001)(2501003)(6806005)(5250100002)(46406003)(50986999)(19580405001)(47776003)(5003600100002)(5007970100001)(54356999)(2920100001)(19580395003)(33656002)(106116001)(5001770100001)(81156007)(5001960100002)(102836002)(106466001)(2950100001)(2900100001)(23726002)(97756001)(107986001);DIR:OUT;SFP:1101;SCL:1;SRVR:BL2FFO11HUB045;H:xsj-pvapsmtpgw01;FPR:;SPF:Pass;PTR:unknown-60-83.xilinx.com;A:1;MX:1;LANG:en; X-Microsoft-Exchange-Diagnostics: 1;BL2FFO11HUB045;2:BSw6B6+u07kgMiHGF8sKqPhNHLbCyuqPcm5uXOVlk/DB1Ysgevqwm/C8zkKv+e2vLy/cqMJflFJbEJaJ6tmRs1sI03GE6o+y4FdWF49vRwHyQNOelHpmHRvpdwRROI7jA0u7yWlpKkJ05lsCa+jkZeDazwLsPBRwpffZuK4yJNg=;3:KUK+hNubAKPJ8bXA0GVUWZNM/NcH5yt6/p+oA/BCFl+nJTX98Tu5QBAm/yEejKmDjDk/riX9wqLoTvakrFMcJsI+K1xhgozMMeo9g1n+uLxQVbhOeoMdiLPApvrU7VUfKsT1sHvKb79TfCYVU+aA4D2vi0f4DGeEZQRc5Ag3YGmOytmkY3ctpgJjfXX0eOsEec6kg2nnLYAUIR/y/vwu/iYURHdlmrYMC0bMxni+iBJVPBfI2bsDEdI2wiFuqXATWueZHdUTHe/SSDCge73gJQ==;25:hTMSauquy1yaJl4tvkl67MlKQ7oXkxGO/X5Wagx6e5PwveWdRLw5yj/0ljFJvwU7ejOhbi5AZ1Y1toB0E+IyWyF12/FoolSxipqWgeNEezcz23H0Xd/KLIv5E9KoLYSBZRl2KUemz2JcZd/Q/7RPJjtsnUeSRFViyRT7n9HYTcKbRtBQLUAXNbtUUDuTCEZsfzKa4ZlpqGbgNtRpA2oj15Keo0OSVBKag68LsPepRP2NCMQYbywXS4W/q7Ne2GGa8YIc9BSatv8lH813usZXvg== X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(8251501001);SRVR:BL2FFO11HUB045; X-Microsoft-Exchange-Diagnostics: 1;BL2FFO11HUB045;20:3ojJNeKjDQfDLNngQ5khIgfsQ5DFa/1R2zcfFPTk2fJHyMF7tn+NXAPuQKI9yYtS52pBd918/Ivi4ylZ82+NklWe4D0ReF3AoedVTarqwYPaQapaZ6c7lzbr7l0WLUoIHVRbonvxMSH0wKyL0EPB4SPIQizjoGD3ljpeEudU0pGs8RlR8U6S0EsJEpoPKz/tEYJkRLlau4M4uNB83ohq714oEFNOUhu9GcoiUQ+ArbsC+48cGFsDjyYnvlwp+eAt204LyS8XO6s2MaDmy+Oi1TbjI/1LTbmvvqeAkzmmRfdHdCfb+T+9YRH8wHctnC+8HqHix31tkZRTwwDmy3nKvJK8Y3C4rCG+yWrneyKwwz2ngiBkYTtOwcVnWalguSXUcNxheC/1nst3RcLIlZ5yAffBbMRjTsAHJbFkSHSttoeMze39+PPTHiXHExfedHcw/sfGVOgT8U5cTSLA37zFgif4VTyyLox86CeiO42y/dIt4Mu1sskTsPlr05JnxOkp;4:6FEaQWT49l801oLpGsjEquVK4OObMJfh4Zb7Rl7ynVn+rOsVDYNOj1zR7Ul76RGV0+5tQS4GTrrdroEpWZK7wI95lW+BqhMXcmuo63GZaaKhYeMuyE7KHngtT1Ikj6p4M2Iw5JN3smXV6D2Ink6Ai9KwT3BVWJO9WnUVzEHTWfAU3HUto9F+qwY/XQDw2HZ3I/gn/C5753wYnaNPgeVaag00Ddq8XkbVgyuzFbGLHY8vMJLKnl5hy1l0sVlEJcQKNlqNQ3CeGmYJXZ+56SJ6h2Eg3CMneypMuNgRMb0xrnQfxugtxhzo7r9H9pUw1qI6YoKrJiITztdOwZ6oLdfMsyjT0y2mDWO0t+ad5OY7twWkWsl4/ENfh4C4hfeir5CE 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)(8121501046)(5005006)(3002001)(10201501046);SRVR:BL2FFO11HUB045;BCL:0;PCL:0;RULEID:;SRVR:BL2FFO11HUB045; X-Forefront-PRVS: 07562C22DA X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;BL2FFO11HUB045;23:EJvIuSNUfaxHGIHIzPX+twcxBBijI/5mnDXNDP8A?= =?us-ascii?Q?f0LOYHKzfvmG6ctTnjzkwXgakIbrix73fa8Nnrh8+c1AFtoHkGgS1Uz85ACm?= =?us-ascii?Q?vKDOvdIlzby5gLsSF0mTdnoSAY2OtYoCtZjurPR9U1xLiq01E2A4m5611TNR?= =?us-ascii?Q?PrCjZchTnOdFxmGUcUGfz3SRzLPMj1cWLii13Zp3fsjRBPaCkk1ho4r9P2qS?= =?us-ascii?Q?hMvsUpMF91bV5/5iKQhYedOI1OL6BWXc3yS1+4n5nCULMi6hI/CMP6Y1sCQj?= =?us-ascii?Q?8eeNtrcasFal1cBnP1sm9vve3U1dpa5/vuAdSFYzUf1OPS0O42/qnihLoKuL?= =?us-ascii?Q?Yown/e1vHKM5Kvt/WizelpPei404E5YlYNPBdDTvyL13SwI3gxQmJylOB+Q8?= =?us-ascii?Q?3LYyVSnK79KAdlJLBykzNS94li599CDwXQ0UiDQLF28WNv836gQZxOUSZ2G4?= =?us-ascii?Q?HY5BUCCwS/Ag4VEqak7c6fnJA5iFkLcldxt/Dqj09pF9CjisvmTZYJioUkVo?= =?us-ascii?Q?JfQc867ZmFH5QF/4hvILXvZwi5sqporxyW64DUMi6YNMD3Q9ZTODcfSWCWC0?= =?us-ascii?Q?rNDToLZY0BFRHJiyCFpbfAcZE6z6J0v0eFYndXzN0J4/JEgTxY7Pz/D9pC/m?= =?us-ascii?Q?Sry4r1q9RRhLgPiClUpfVlcWPPgmDOYpB83t6cM/8LpJ/AwqQI1jnAMBi1YV?= =?us-ascii?Q?52xPBvZyQON9EBxsUBADTKgfLoBtBID1WrXC2dkbm7JNrabhUEJA3bfckpvZ?= =?us-ascii?Q?vrbB/jLp1qJv9q5JyaJqPxMM0FEwZkIrZ1PUUURzAyW+IpuioeqIEQ7TwDIE?= =?us-ascii?Q?bHzEqh4uTLxMhlquwrYLvBDDzWoj5hFiIvB42i66RNd3wQNWTMEyQknRw8hp?= =?us-ascii?Q?FmiqxuorCx72Ae/JHwi9PsO5cSX86PC+mXD1geOW1RZXguUfHRBsEUldxeCl?= =?us-ascii?Q?2AHwfnbFhI4wlYzyG21L/nWNE6ZcRZU0S9CbyCAxdStsUC269gIOrPM1BwZQ?= =?us-ascii?Q?qL1y4JurjaavTfOAq5LijONj1MRbTiDAoV2e1rdqibYM7rmL5npiDDM3z0zk?= =?us-ascii?Q?uOlYzq+vM+4uJ8Hwki/DOGwfwboNIT/Q5xbDv0R29MhanLlgTJdNDJe1W+xl?= =?us-ascii?Q?06arSNHpAF5uoMqm8J14oJC7oIKmyw9kay02gmFxC2WNbEP+CFc7pU50GDo9?= =?us-ascii?Q?6h0AEUONgK9ziwv+AUoPjB4IabPBzXtgc/ghwGJW+9Ix3L+9LzlzjBGgZg?= =?us-ascii?Q?=3D=3D?= X-Microsoft-Exchange-Diagnostics: 1;BL2FFO11HUB045;5:6WBaER9hK/IcvDprR6VPrSnNsp8FJh94GoS+UoB7BMKqWgzNrgMTMfXoWIXiUKCi+SvbrmOZXGJnb/oVFph7zTqlynDHCnLZjZsxu7cIJg+Ob64wclc3VshEnRFhOxuIxo0vSIuJNEUUtVVelC57Ew==;24:fmynZgDMSfmZFDGidtu7hq1PH8x97/PmTHgrDELpkht3a0AtXlT9/RyOCtguq8PF9bUGU5kdHcJ5xzLQ5YzAOZR5OLxS8SBDQBq+vIs3Asw= SpamDiagnosticOutput: 1:23 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: xilinx.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 10 Nov 2015 08:33:16.2187 (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: BL2FFO11HUB045 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 12030 Lines: 405 Ping!! > -----Original Message----- > From: Kedareswara rao Appana [mailto:appana.durga.rao@xilinx.com] > Sent: Monday, October 26, 2015 11:42 AM > To: Anirudha Sarangi; wg@grandegger.com; mkl@pengutronix.de; Michal > Simek; Soren Brinkmann > Cc: linux-can@vger.kernel.org; netdev@vger.kernel.org; linux-arm- > kernel@lists.infradead.org; linux-kernel@vger.kernel.org; Appana Durga > Kedareswara Rao > Subject: [PATCH v8] can: xilinx: Convert to runtime_pm > > 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 v8: > - Remove pm_runtime_irq_safe() API call from the probe as > clk_prepare_enable > Call canbe called from the atomic context as suggested by Marc. > 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 | 176 +++++++++++++++++++++++++----------------- > - > 1 file changed, 101 insertions(+), 75 deletions(-) > > diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c > index fc55e8e..ad38065 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,17 @@ 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_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 +1168,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 +1203,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 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/