From: Dong Yang Date: Sun, 17 Jun 2012 04:12:17 +0000 (+0800) Subject: intel_soc_pmu: optimize retry logic and dump more information X-Git-Tag: 2.1b_release~553 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=058eeec7131967ffabe57ac51a1524eed426f40b;p=kernel%2Fkernel-mfld-blackbay.git intel_soc_pmu: optimize retry logic and dump more information BZ: 42229 the pmu_pci_set_power_state() will try 3 times to wait the pmu2 get ready, but every time issue a command to pmu2, since pmu2 is busy, this is the wrong behavior, it should issue the interactive command only for 1 time and wait the pmu2 to get ready for 3 times. or else it won't trigger panic and will returned in case pmu2 busy forever. Optimize retry logic and add longer delay in _pmu2_wait_not_busy_yield(), use endless loop if PMU is alwasy busy, dump all CPU call trace. Change-Id: I4355706f95c87872e961f106ee1059eaee1590e1 Signed-off-by: Dong Yang Signed-off-by: Illyas Mansoor Signed-off-by: Yanmin Zhang Signed-off-by: He, Bo --- diff --git a/arch/x86/platform/intel-mid/intel_soc_pmu.c b/arch/x86/platform/intel-mid/intel_soc_pmu.c index 101c74e..231c7f4 100644 --- a/arch/x86/platform/intel-mid/intel_soc_pmu.c +++ b/arch/x86/platform/intel-mid/intel_soc_pmu.c @@ -353,9 +353,9 @@ int _pmu2_wait_not_busy(void) static int _pmu2_wait_not_busy_yield(void) { - int pmu_busy_retry = 20; + int pmu_busy_retry = 50000; /* 500msec minimum */ - /* wait 10ms that the latest pmu command finished */ + /* wait for the latest pmu command finished */ do { usleep_range(10, 500); @@ -1248,7 +1248,8 @@ int __ref pmu_pci_set_power_state(struct pci_dev *pdev, pci_power_t state) int pmu_num; struct pmu_ss_states cur_pmssc; int status = 0; - int retry_count = 3; + int retry_times = 0; + ktime_t calltime, delta, rettime; /* Ignore callback from devices until we have initialized */ if (unlikely((!pmu_initialized))) @@ -1317,90 +1318,67 @@ int __ref pmu_pci_set_power_state(struct pci_dev *pdev, pci_power_t state) cur_pmssc.pmu2_states[2] &= ~IGNORE_SSS2; cur_pmssc.pmu2_states[3] &= ~IGNORE_SSS3; - do { - /* Issue the pmu command to PMU 2 - * flag is needed to distinguish between - * S0ix vs interactive command in pmu_sc_irq() - */ - status = pmu_issue_interactive_command(&cur_pmssc, false); - - if (unlikely(status != PMU_SUCCESS)) { - dev_dbg(&mid_pmu_cxt->pmu_dev->dev, - "Failed to Issue a PM command to PMU2\n"); - goto unlock; - } + /* Issue the pmu command to PMU 2 + * flag is needed to distinguish between + * S0ix vs interactive command in pmu_sc_irq() + */ + status = pmu_issue_interactive_command(&cur_pmssc, false); - /* - * Wait for interactive command to complete. - * If we dont wait, there is a possibility that - * the driver may access the device before its - * powered on in SCU. - * - */ - status = _pmu2_wait_not_busy_yield(); + if (unlikely(status != PMU_SUCCESS)) { + dev_dbg(&mid_pmu_cxt->pmu_dev->dev, + "Failed to Issue a PM command to PMU2\n"); + goto unlock; + } - if (likely(!status)) - break; + calltime = ktime_get(); +retry: + /* + * Wait for interactive command to complete. + * If we dont wait, there is a possibility that + * the driver may access the device before its + * powered on in SCU. + * + */ + status = _pmu2_wait_not_busy_yield(); + if (unlikely(status)) { + rettime = ktime_get(); + delta = ktime_sub(rettime, calltime); + retry_times++; printk(KERN_CRIT "%s: D0ix transition failure:" " %04x %04X %s %20s:\n", __func__, pdev->vendor, pdev->device, dev_name(&pdev->dev), dev_driver_string(&pdev->dev)); + printk(KERN_CRIT "interrupt pending = %d\n", + pmu_interrupt_pending()); printk(KERN_CRIT "pmu_busy_status = %d\n", - _pmu_read_status(PMU_BUSY_STATUS)); + _pmu_read_status(PMU_BUSY_STATUS)); printk(KERN_CRIT "suspend_started = %d\n", mid_pmu_cxt->suspend_started); printk(KERN_CRIT "shutdown_started = %d\n", mid_pmu_cxt->shutdown_started); - printk(KERN_CRIT "Retrying... attempt(%d):\n", - retry_count); - } while (--retry_count); - - if (unlikely(status)) { - struct pmu_ss_states new_pmsss; - u32 post_transition_val; - - /* - * Check if the power transition - * indeed happend, if yes continue, else BUG - */ - new_value &= - (D0I3_MASK << (sub_sys_pos * BITS_PER_LSS)); - pmu_read_sss(&new_pmsss); - post_transition_val = - (new_pmsss.pmu2_states[sub_sys_index] & - (D0I3_MASK << (sub_sys_pos * BITS_PER_LSS))); - - if (new_value != post_transition_val) { - printk(KERN_CRIT "%s: D0ix transition failure:" - " %04x %04X %s %20s:\n", __func__, - pdev->vendor, pdev->device, - dev_name(&pdev->dev), - dev_driver_string(&pdev->dev)); - printk(KERN_CRIT "interrupt pending = %d\n", - pmu_interrupt_pending()); - printk(KERN_CRIT "pmu_busy_status = %d\n", - _pmu_read_status(PMU_BUSY_STATUS)); - printk(KERN_CRIT "suspend_started = %d\n", - mid_pmu_cxt->suspend_started); - printk(KERN_CRIT "shutdown_started = %d\n", - mid_pmu_cxt->shutdown_started); - printk(KERN_CRIT "interactive_cmd_sent = %d\n", + printk(KERN_CRIT "interactive_cmd_sent = %d\n", (int)mid_pmu_cxt->interactive_cmd_sent); - printk(KERN_CRIT "camera_off = %d" - " display_off = %d\n", mid_pmu_cxt->camera_off, - mid_pmu_cxt->display_off); - printk(KERN_CRIT "s0ix_possible = 0x%x\n", - mid_pmu_cxt->s0ix_possible); - printk(KERN_CRIT "s0ix_entered = 0x%x\n", - mid_pmu_cxt->s0ix_entered); - printk(KERN_CRIT "pmu_current_state = %d\n", - mid_pmu_cxt->pmu_current_state); - pmu_dump_logs(); + printk(KERN_CRIT "camera_off = %d" + " display_off = %d\n", mid_pmu_cxt->camera_off, + mid_pmu_cxt->display_off); + printk(KERN_CRIT "s0ix_possible = 0x%x\n", + mid_pmu_cxt->s0ix_possible); + printk(KERN_CRIT "s0ix_entered = 0x%x\n", + mid_pmu_cxt->s0ix_entered); + printk(KERN_CRIT "pmu_current_state = %d\n", + mid_pmu_cxt->pmu_current_state); + printk(KERN_CRIT "PMU is BUSY! retry_times[%d] " + "total_delay[%lli]ms. Retry ...\n", + retry_times, (long long) ktime_to_ms(delta)); + pmu_dump_logs(); + trigger_all_cpu_backtrace(); + if (retry_times < 60) + goto retry; + else BUG(); - } } pmu_set_s0ix_possible(state); diff --git a/arch/x86/platform/intel-mid/intel_soc_pmu.h b/arch/x86/platform/intel-mid/intel_soc_pmu.h index f6342b0..db0c530 100644 --- a/arch/x86/platform/intel-mid/intel_soc_pmu.h +++ b/arch/x86/platform/intel-mid/intel_soc_pmu.h @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include