[PORT FROM R2] intel_mid_hsi: Cleaned-up reset sequence for avoiding RX errors.
authorOlivier Stoltz Douchet <olivierx.stoltz-douchet@intel.com>
Mon, 28 Nov 2011 09:38:53 +0000 (10:38 +0100)
committerbuildbot <buildbot@intel.com>
Wed, 18 Jan 2012 18:55:14 +0000 (10:55 -0800)
BZ: 15516

This patch is cleaning up the reset sequence of Intel HSI controller by:
- disabling the tasklet prior to resetting the hardware to prevent those
  tasklets to run after the transfer contexts have been freed thus protecting
  against a potential kernel panic;
- not disabling the IP clock generation and PLL, as this causes RX errors when
  the device is re-enabled without going into suspend mode. This error is not
  happening when the device is going through a suspend / resume cycle as it is
  un-powered and restarts in a safe state.

Change-Id: I404feb0c96840e9eeec4e78336b42a1254c4acff
Orig-Change-Id: I092434a4dfeb5dd2c6a31bc887e9115eff23fba4
Signed-off-by: Olivier Stoltz Douchet <olivierx.stoltz-douchet@intel.com>
Reviewed-on: http://android.intel.com:8080/31423
Reviewed-by: Robert, Denis <denis.robert@intel.com>
Reviewed-by: Akue, LoicX <loicx.akue@intel.com>
Reviewed-by: Pillet, VincentX <vincentx.pillet@intel.com>
Reviewed-by: Predon, Frederic <frederic.predon@intel.com>
Reviewed-by: Lebsir, SamiX <samix.lebsir@intel.com>
Tested-by: Lebsir, SamiX <samix.lebsir@intel.com>
Reviewed-by: buildbot <buildbot@intel.com>
Tested-by: buildbot <buildbot@intel.com>
drivers/hsi/controllers/intel_mid_hsi.c

index c07655b..fe14e69 100644 (file)
@@ -1037,9 +1037,8 @@ static int hsi_ctrl_suspend(struct intel_controller *intel_hsi)
                hsi_enable_interrupt(ctrl, 0);
                hsi_enable_error_interrupt(ctrl, 0);
 
-               /* Cut the clock and set the device as being suspended */
+               /* Disable everyting and set the device as being suspended */
                iowrite32(0, ARASAN_HSI_PROGRAM(ctrl));
-               iowrite32(0, ARASAN_HSI_CLOCK_CONTROL(ctrl));
                intel_hsi->suspend_state = DEVICE_SUSPENDED;
 
 #ifdef CONFIG_HAS_WAKELOCK
@@ -1262,6 +1261,10 @@ static void hsi_ctrl_clean_reset(struct intel_controller *intel_hsi)
        /* Disable the interrupt line */
        disable_irq(intel_hsi->irq);
 
+       /* Disable (and flush) all tasklets */
+       tasklet_disable(&intel_hsi->isr_tasklet);
+       tasklet_disable(&intel_hsi->fwd_tasklet);
+
        spin_lock_irqsave(&intel_hsi->hw_lock, flags);
 
        /* Remove the CAWAKE poll timer */
@@ -1283,9 +1286,6 @@ static void hsi_ctrl_clean_reset(struct intel_controller *intel_hsi)
        /* Kill RX and TX wake sources and disable all channels */
        iowrite32(0, ARASAN_HSI_PROGRAM(ctrl));
 
-       /* Cut the clock and set the device as being not configured */
-       iowrite32(0, ARASAN_HSI_CLOCK_CONTROL(ctrl));
-
 exit_clean_reset:
        if (intel_hsi->rx_state == RX_READY)
                intel_hsi->rx_state = RX_CAN_SLEEP;
@@ -1299,6 +1299,10 @@ exit_clean_reset:
                ;
        (void) has_disabled_acready(intel_hsi);
 
+       /* Re-enable all tasklets */
+       tasklet_enable(&intel_hsi->fwd_tasklet);
+       tasklet_enable(&intel_hsi->isr_tasklet);
+
        /* Do not forget to re-enable the interrupt */
        enable_irq(intel_hsi->irq);
 
@@ -1858,6 +1862,7 @@ static void hsi_rx_error(struct intel_controller *intel_hsi)
        unsigned long                    flags;
 
        pr_err("hsi: rx error\n");
+
        for (i = 0; i < hsi_rx_channel_count(intel_hsi); i++) {
                queue = &intel_hsi->rx_queue[i];
                spin_lock_irqsave(&intel_hsi->sw_lock, flags);
@@ -2381,7 +2386,7 @@ static int hsi_mid_flush(struct hsi_client *cl)
        struct hsi_port *port = hsi_get_port(cl);
        struct intel_controller *intel_hsi = hsi_port_drvdata(port);
        void __iomem *ctrl = intel_hsi->ctrl_io;
-       unsigned int i, unforce;
+       unsigned int i, unforce = 0;
        unsigned long flags;
 
        /* Prevent any new message in the software queues */