#include <linux/suspend.h>
#include <linux/wakelock.h>
#include <asm/mrst.h>
+#include <asm/apic.h>
+
#include <linux/intel_mid_pm.h>
#include "pmu.h"
} else {
s0ix_sram_restore(mid_pmu_cxt->s0ix_entered);
+ /* Wakeup allother CPU's */
+ if (mid_pmu_cxt->s0ix_entered == MID_S0I3_STATE)
+ apic->send_IPI_allbutself(RESCHEDULE_VECTOR);
+
mid_pmu_cxt->s0ix_entered = 0;
/* S0ix case release it */
}
EXPORT_SYMBOL(pmu_set_s0ix_complete);
+bool pmu_is_s0i3_in_progress(void)
+{
+ bool state = false;
+
+ if (pmu_initialized && mid_pmu_cxt->s0ix_entered == MID_S0I3_STATE)
+ state = true;
+
+ return state;
+}
+EXPORT_SYMBOL(pmu_is_s0i3_in_progress);
+
static inline u32 find_index_in_hash(struct pci_dev *pdev, int *found)
{
u32 h_index;
eax = C6_HINT;
}
+ /* Check if s0i3 is already in progress,
+ * This is required to demote C6 while S0ix
+ * is in progress
+ */
+ if (unlikely(pmu_is_s0i3_in_progress())) {
+ dev->last_state = &dev->states[C4_STATE_IDX];
+ return intel_idle(dev, &dev->states[C4_STATE_IDX]);
+ }
+
local_irq_disable();
/*
num_online_cpus() && s0ix_state) {
s0ix_entered = mfld_s0ix_enter(s0ix_state);
if (!s0ix_entered) {
- eax = C4_HINT;
+ if (pmu_is_s0i3_in_progress()) {
+ atomic_dec(&nr_cpus_in_c6);
+ eax = C4_HINT;
+ }
pmu_set_s0ix_complete();
}
}
if (!need_resched())
__mwait(eax, ecx);
- atomic_dec(&nr_cpus_in_c6);
+ if (likely(eax == C6_HINT))
+ atomic_dec(&nr_cpus_in_c6);
+
/* During s0ix exit inform scu that OS
* has exited. In case scu is still waiting
* for ack c6 trigger, it would exit out
extern int mfld_s0ix_enter(int);
extern int get_target_platform_state(void);
extern void pmu_set_s0ix_complete(void);
-extern unsigned long pmu_get_cstate(unsigned long eax);
+extern bool pmu_is_s0i3_in_progress(void);
extern int pmu_nc_set_power_state
(int islands, int state_type, int reg_type);
extern void mfld_shutdown(void);
static inline void pmu_set_s0ix_complete(void) { return; }
static inline void mfld_shutdown(void) { return; }
-#endif /* #ifdef CONFIG_X86_MDFLD */
+static inline bool pmu_is_s0ix_in_progress(void) { return false; };
+#endif /* #ifdef CONFIG_INTEL_MID_POWER */
+
#endif /* #ifndef INTEL_MID_PM_H */