aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnssi Hannula <anssi.hannula@bitwise.fi>2018-05-17 08:41:19 -0400
committerMarc Kleine-Budde <mkl@pengutronix.de>2018-07-23 08:34:46 -0400
commit8ebd83bdb027f29870d96649dba18b91581ea829 (patch)
tree82032da918b1f9d0a3cce4cc50da1aa99aef13e7
parent2f4f0f338cf453bfcdbcf089e177c16f35f023c8 (diff)
can: xilinx_can: fix power management handling
There are several issues with the suspend/resume handling code of the driver: - The device is attached and detached in the runtime_suspend() and runtime_resume() callbacks if the interface is running. However, during xcan_chip_start() the interface is considered running, causing the resume handler to incorrectly call netif_start_queue() at the beginning of xcan_chip_start(), and on xcan_chip_start() error return the suspend handler detaches the device leaving the user unable to bring-up the device anymore. - The device is not brought properly up on system resume. A reset is done and the code tries to determine the bus state after that. However, after reset the device is always in Configuration mode (down), so the state checking code does not make sense and communication will also not work. - The suspend callback tries to set the device to sleep mode (low-power mode which monitors the bus and brings the device back to normal mode on activity), but then immediately disables the clocks (possibly before the device reaches the sleep mode), which does not make sense to me. If a clean shutdown is wanted before disabling clocks, we can just bring it down completely instead of only sleep mode. Reorganize the PM code so that only the clock logic remains in the runtime PM callbacks and the system PM callbacks contain the device bring-up/down logic. This makes calling the runtime PM callbacks during e.g. xcan_chip_start() safe. The system PM callbacks now simply call common code to start/stop the HW if the interface was running, replacing the broken code from before. xcan_chip_stop() is updated to use the common reset code so that it will wait for the reset to complete. Reset also disables all interrupts so do not do that separately. Also, the device_may_wakeup() checks are removed as the driver does not have wakeup support. Tested on Zynq-7000 integrated CAN. Signed-off-by: Anssi Hannula <anssi.hannula@bitwise.fi> Cc: Michal Simek <michal.simek@xilinx.com> Cc: <stable@vger.kernel.org> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
-rw-r--r--drivers/net/can/xilinx_can.c69
1 files changed, 28 insertions, 41 deletions
diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c
index cb80a9aa7281..5a24039733ef 100644
--- a/drivers/net/can/xilinx_can.c
+++ b/drivers/net/can/xilinx_can.c
@@ -984,13 +984,9 @@ static irqreturn_t xcan_interrupt(int irq, void *dev_id)
984static void xcan_chip_stop(struct net_device *ndev) 984static void xcan_chip_stop(struct net_device *ndev)
985{ 985{
986 struct xcan_priv *priv = netdev_priv(ndev); 986 struct xcan_priv *priv = netdev_priv(ndev);
987 u32 ier;
988 987
989 /* Disable interrupts and leave the can in configuration mode */ 988 /* Disable interrupts and leave the can in configuration mode */
990 ier = priv->read_reg(priv, XCAN_IER_OFFSET); 989 set_reset_mode(ndev);
991 ier &= ~XCAN_INTR_ALL;
992 priv->write_reg(priv, XCAN_IER_OFFSET, ier);
993 priv->write_reg(priv, XCAN_SRR_OFFSET, XCAN_SRR_RESET_MASK);
994 priv->can.state = CAN_STATE_STOPPED; 990 priv->can.state = CAN_STATE_STOPPED;
995} 991}
996 992
@@ -1123,10 +1119,15 @@ static const struct net_device_ops xcan_netdev_ops = {
1123 */ 1119 */
1124static int __maybe_unused xcan_suspend(struct device *dev) 1120static int __maybe_unused xcan_suspend(struct device *dev)
1125{ 1121{
1126 if (!device_may_wakeup(dev)) 1122 struct net_device *ndev = dev_get_drvdata(dev);
1127 return pm_runtime_force_suspend(dev);
1128 1123
1129 return 0; 1124 if (netif_running(ndev)) {
1125 netif_stop_queue(ndev);
1126 netif_device_detach(ndev);
1127 xcan_chip_stop(ndev);
1128 }
1129
1130 return pm_runtime_force_suspend(dev);
1130} 1131}
1131 1132
1132/** 1133/**
@@ -1138,11 +1139,27 @@ static int __maybe_unused xcan_suspend(struct device *dev)
1138 */ 1139 */
1139static int __maybe_unused xcan_resume(struct device *dev) 1140static int __maybe_unused xcan_resume(struct device *dev)
1140{ 1141{
1141 if (!device_may_wakeup(dev)) 1142 struct net_device *ndev = dev_get_drvdata(dev);
1142 return pm_runtime_force_resume(dev); 1143 int ret;
1143 1144
1144 return 0; 1145 ret = pm_runtime_force_resume(dev);
1146 if (ret) {
1147 dev_err(dev, "pm_runtime_force_resume failed on resume\n");
1148 return ret;
1149 }
1150
1151 if (netif_running(ndev)) {
1152 ret = xcan_chip_start(ndev);
1153 if (ret) {
1154 dev_err(dev, "xcan_chip_start failed on resume\n");
1155 return ret;
1156 }
1145 1157
1158 netif_device_attach(ndev);
1159 netif_start_queue(ndev);
1160 }
1161
1162 return 0;
1146} 1163}
1147 1164
1148/** 1165/**
@@ -1157,14 +1174,6 @@ static int __maybe_unused xcan_runtime_suspend(struct device *dev)
1157 struct net_device *ndev = dev_get_drvdata(dev); 1174 struct net_device *ndev = dev_get_drvdata(dev);
1158 struct xcan_priv *priv = netdev_priv(ndev); 1175 struct xcan_priv *priv = netdev_priv(ndev);
1159 1176
1160 if (netif_running(ndev)) {
1161 netif_stop_queue(ndev);
1162 netif_device_detach(ndev);
1163 }
1164
1165 priv->write_reg(priv, XCAN_MSR_OFFSET, XCAN_MSR_SLEEP_MASK);
1166 priv->can.state = CAN_STATE_SLEEPING;
1167
1168 clk_disable_unprepare(priv->bus_clk); 1177 clk_disable_unprepare(priv->bus_clk);
1169 clk_disable_unprepare(priv->can_clk); 1178 clk_disable_unprepare(priv->can_clk);
1170 1179
@@ -1183,7 +1192,6 @@ static int __maybe_unused xcan_runtime_resume(struct device *dev)
1183 struct net_device *ndev = dev_get_drvdata(dev); 1192 struct net_device *ndev = dev_get_drvdata(dev);
1184 struct xcan_priv *priv = netdev_priv(ndev); 1193 struct xcan_priv *priv = netdev_priv(ndev);
1185 int ret; 1194 int ret;
1186 u32 isr, status;
1187 1195
1188 ret = clk_prepare_enable(priv->bus_clk); 1196 ret = clk_prepare_enable(priv->bus_clk);
1189 if (ret) { 1197 if (ret) {
@@ -1197,27 +1205,6 @@ static int __maybe_unused xcan_runtime_resume(struct device *dev)
1197 return ret; 1205 return ret;
1198 } 1206 }
1199 1207
1200 priv->write_reg(priv, XCAN_SRR_OFFSET, XCAN_SRR_RESET_MASK);
1201 isr = priv->read_reg(priv, XCAN_ISR_OFFSET);
1202 status = priv->read_reg(priv, XCAN_SR_OFFSET);
1203
1204 if (netif_running(ndev)) {
1205 if (isr & XCAN_IXR_BSOFF_MASK) {
1206 priv->can.state = CAN_STATE_BUS_OFF;
1207 priv->write_reg(priv, XCAN_SRR_OFFSET,
1208 XCAN_SRR_RESET_MASK);
1209 } else if ((status & XCAN_SR_ESTAT_MASK) ==
1210 XCAN_SR_ESTAT_MASK) {
1211 priv->can.state = CAN_STATE_ERROR_PASSIVE;
1212 } else if (status & XCAN_SR_ERRWRN_MASK) {
1213 priv->can.state = CAN_STATE_ERROR_WARNING;
1214 } else {
1215 priv->can.state = CAN_STATE_ERROR_ACTIVE;
1216 }
1217 netif_device_attach(ndev);
1218 netif_start_queue(ndev);
1219 }
1220
1221 return 0; 1208 return 0;
1222} 1209}
1223 1210