• Anssi Hannula's avatar
    can: xilinx_can: fix power management handling · 8ebd83bd
    Anssi Hannula authored
    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: default avatarAnssi Hannula <anssi.hannula@bitwise.fi>
    Cc: Michal Simek <michal.simek@xilinx.com>
    Cc: <stable@vger.kernel.org>
    Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
    8ebd83bd
xilinx_can.c 38.9 KB