From 48bb574f70dd89c417a0a01cbd58e4797a8d7b9b Mon Sep 17 00:00:00 2001 From: Olivier Stoltz Douchet Date: Mon, 28 Nov 2011 10:38:53 +0100 Subject: [PATCH] [PORT FROM R2] intel_mid_hsi: Cleaned-up reset sequence for avoiding RX errors. 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 Reviewed-on: http://android.intel.com:8080/31423 Reviewed-by: Robert, Denis Reviewed-by: Akue, LoicX Reviewed-by: Pillet, VincentX Reviewed-by: Predon, Frederic Reviewed-by: Lebsir, SamiX Tested-by: Lebsir, SamiX Reviewed-by: buildbot Tested-by: buildbot --- drivers/hsi/controllers/intel_mid_hsi.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/hsi/controllers/intel_mid_hsi.c b/drivers/hsi/controllers/intel_mid_hsi.c index c07655b..fe14e69 100644 --- a/drivers/hsi/controllers/intel_mid_hsi.c +++ b/drivers/hsi/controllers/intel_mid_hsi.c @@ -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 */ -- 2.7.4