LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 4/9] ACPI / cpuidle: fix max idle state handling with hotplug CPU support
From: Bartlomiej Zolnierkiewicz @ 2013-12-20 18:47 UTC (permalink / raw)
  To: rjw
  Cc: linux-samsung-soc, linux-pm, b.zolnierkie, daniel.lezcano,
	linux-kernel, kyungmin.park, linuxppc-dev, lenb
In-Reply-To: <1387565251-7051-1-git-send-email-b.zolnierkie@samsung.com>

acpi_processor_hotplug() calls acpi_processor_setup_cpuidle_cx()
without calling acpi_processor_setup_cpuidle_states() first so it
is possible that dev->state_count becomes different from
drv->state_count (in case of SMP system with unsupported C2/C3
states + enabled CPU hotplug and num_online_cpus() becoming > 1).

The driver code assumes that cpuidle core will handle such cases
but currently this is untrue (dev->state_count is used only for
handling cpuidle state sysfs entries and drv->state_count is used
for all other cases) and will not be fixed in the future as
dev->state_count is planned to be removed.

Fix the issue by checking for the max supported idle state in
C2/C3 state's ->enter handler (acpi_idle_enter_simple() for C2/C3
and acpi_idle_enter_bm() for C3 + bm_check flag set) and setting
the C1 state (instead of higher states) when needed.

Also remove no longer needed max idle state checks from
acpi_processor_setup_cpuidle_[states,cx]().

Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Len Brown <lenb@kernel.org>
---
 drivers/acpi/processor_idle.c | 27 ++++++++++++++-------------
 1 file changed, 14 insertions(+), 13 deletions(-)

diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index a0cc5ef4f..c080c99 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -783,6 +783,13 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
 	if (unlikely(!pr))
 		return -EINVAL;
 
+#ifdef CONFIG_HOTPLUG_CPU
+	if ((cx->type != ACPI_STATE_C1) && (num_online_cpus() > 1) &&
+	    !pr->flags.has_cst &&
+	    !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED))
+		return acpi_idle_enter_c1(dev, drv, CPUIDLE_DRIVER_STATE_START);
+#endif
+
 	if (cx->entry_method == ACPI_CSTATE_FFH) {
 		if (current_set_polling_and_test())
 			return -EINVAL;
@@ -829,6 +836,13 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
 	if (unlikely(!pr))
 		return -EINVAL;
 
+#ifdef CONFIG_HOTPLUG_CPU
+	if ((cx->type != ACPI_STATE_C1) && (num_online_cpus() > 1) &&
+	    !pr->flags.has_cst &&
+	    !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED))
+		return acpi_idle_enter_c1(dev, drv, CPUIDLE_DRIVER_STATE_START);
+#endif
+
 	if (!cx->bm_sts_skip && acpi_idle_bm_check()) {
 		if (drv->safe_state_index >= 0) {
 			return drv->states[drv->safe_state_index].enter(dev,
@@ -930,12 +944,6 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr,
 		if (!cx->valid)
 			continue;
 
-#ifdef CONFIG_HOTPLUG_CPU
-		if ((cx->type != ACPI_STATE_C1) && (num_online_cpus() > 1) &&
-		    !pr->flags.has_cst &&
-		    !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED))
-			continue;
-#endif
 		per_cpu(acpi_cstate[count], dev->cpu) = cx;
 
 		count++;
@@ -985,13 +993,6 @@ static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr)
 		if (!cx->valid)
 			continue;
 
-#ifdef CONFIG_HOTPLUG_CPU
-		if ((cx->type != ACPI_STATE_C1) && (num_online_cpus() > 1) &&
-		    !pr->flags.has_cst &&
-		    !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED))
-			continue;
-#endif
-
 		state = &drv->states[count];
 		snprintf(state->name, CPUIDLE_NAME_LEN, "C%d", i);
 		strncpy(state->desc, cx->desc, CPUIDLE_DESC_LEN);
-- 
1.8.2.3

^ permalink raw reply related

* [PATCH v2 5/9] ACPI / cpuidle: remove dev->state_count setting
From: Bartlomiej Zolnierkiewicz @ 2013-12-20 18:47 UTC (permalink / raw)
  To: rjw
  Cc: linux-samsung-soc, linux-pm, b.zolnierkie, daniel.lezcano,
	linux-kernel, kyungmin.park, linuxppc-dev, lenb
In-Reply-To: <1387565251-7051-1-git-send-email-b.zolnierkie@samsung.com>

dev->state_count is now always equal to drv->state_count and
drv->state_count no longer can change during driver's lifetime so
the default dev->state_count initialization in cpuidle_enable_device()
(called from cpuidle_register_device()) can be used instead.

Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Len Brown <lenb@kernel.org>
---
 drivers/acpi/processor_idle.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index c080c99..da8ce91 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -951,8 +951,6 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr,
 			break;
 	}
 
-	dev->state_count = count;
-
 	if (!count)
 		return -EINVAL;
 
-- 
1.8.2.3

^ permalink raw reply related

* [PATCH v2 6/9] intel_idle: do C1E promotion disable quirk for hotplugged CPUs
From: Bartlomiej Zolnierkiewicz @ 2013-12-20 18:47 UTC (permalink / raw)
  To: rjw
  Cc: linux-samsung-soc, linux-pm, b.zolnierkie, daniel.lezcano,
	linux-kernel, kyungmin.park, linuxppc-dev, lenb
In-Reply-To: <1387565251-7051-1-git-send-email-b.zolnierkie@samsung.com>

If the system is booted with some CPUs offline C1E promotion disable quirk
won't be applied because on_each_cpu() in intel_idle_cpuidle_driver_init()
operates only on online CPUs. Fix it by adding the C1E promotion disable
handling to intel_idle_cpu_init() (which is also called during CPU_ONLINE
operation).

Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Len Brown <lenb@kernel.org>
---
 drivers/idle/intel_idle.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 92d1206..38da3fb 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -683,6 +683,9 @@ static int intel_idle_cpu_init(int cpu)
 	if (icpu->auto_demotion_disable_flags)
 		smp_call_function_single(cpu, auto_demotion_disable, NULL, 1);
 
+	if (icpu->disable_promotion_to_c1e)
+		smp_call_function_single(cpu, c1e_promotion_disable, NULL, 1);
+
 	return 0;
 }
 
-- 
1.8.2.3

^ permalink raw reply related

* [PATCH v2 7/9] intel_idle: remove superfluous dev->state_count initialization
From: Bartlomiej Zolnierkiewicz @ 2013-12-20 18:47 UTC (permalink / raw)
  To: rjw
  Cc: linux-samsung-soc, linux-pm, b.zolnierkie, daniel.lezcano,
	linux-kernel, kyungmin.park, linuxppc-dev, lenb
In-Reply-To: <1387565251-7051-1-git-send-email-b.zolnierkie@samsung.com>

intel_idle driver sets dev->state_count to drv->state_count so
the default dev->state_count initialization in cpuidle_enable_device()
(called from cpuidle_register_device()) can be used instead.

Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Len Brown <lenb@kernel.org>
---
 drivers/idle/intel_idle.c | 29 -----------------------------
 1 file changed, 29 deletions(-)

diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 38da3fb..524d07b 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -639,39 +639,10 @@ static int __init intel_idle_cpuidle_driver_init(void)
  */
 static int intel_idle_cpu_init(int cpu)
 {
-	int cstate;
 	struct cpuidle_device *dev;
 
 	dev = per_cpu_ptr(intel_idle_cpuidle_devices, cpu);
 
-	dev->state_count = 1;
-
-	for (cstate = 0; cstate < CPUIDLE_STATE_MAX; ++cstate) {
-		int num_substates, mwait_hint, mwait_cstate, mwait_substate;
-
-		if (cpuidle_state_table[cstate].enter == NULL)
-			break;
-
-		if (cstate + 1 > max_cstate) {
-			printk(PREFIX "max_cstate %d reached\n", max_cstate);
-			break;
-		}
-
-		mwait_hint = flg2MWAIT(cpuidle_state_table[cstate].flags);
-		mwait_cstate = MWAIT_HINT2CSTATE(mwait_hint);
-		mwait_substate = MWAIT_HINT2SUBSTATE(mwait_hint);
-
-		/* does the state exist in CPUID.MWAIT? */
-		num_substates = (mwait_substates >> ((mwait_cstate + 1) * 4))
-					& MWAIT_SUBSTATE_MASK;
-
-		/* if sub-state in table is not enumerated by CPUID */
-		if ((mwait_substate + 1) > num_substates)
-			continue;
-
-		dev->state_count += 1;
-	}
-
 	dev->cpu = cpu;
 
 	if (cpuidle_register_device(dev)) {
-- 
1.8.2.3

^ permalink raw reply related

* [PATCH v2 8/9] intel_idle: use the common cpuidle_[un]register() routines
From: Bartlomiej Zolnierkiewicz @ 2013-12-20 18:47 UTC (permalink / raw)
  To: rjw
  Cc: linux-samsung-soc, linux-pm, b.zolnierkie, daniel.lezcano,
	linux-kernel, kyungmin.park, linuxppc-dev, lenb
In-Reply-To: <1387565251-7051-1-git-send-email-b.zolnierkie@samsung.com>

It is now possible to use the common cpuidle_[un]register() routines
(instead of open-coding them) so do it.

Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Len Brown <lenb@kernel.org>
---
 drivers/idle/intel_idle.c | 114 ++++++++++++----------------------------------
 1 file changed, 29 insertions(+), 85 deletions(-)

diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 524d07b..a1a4dbd 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -93,10 +93,8 @@ struct idle_cpu {
 };
 
 static const struct idle_cpu *icpu;
-static struct cpuidle_device __percpu *intel_idle_cpuidle_devices;
 static int intel_idle(struct cpuidle_device *dev,
 			struct cpuidle_driver *drv, int index);
-static int intel_idle_cpu_init(int cpu);
 
 static struct cpuidle_state *cpuidle_state_table;
 
@@ -400,11 +398,27 @@ static void __setup_broadcast_timer(void *arg)
 	clockevents_notify(reason, &cpu);
 }
 
+static void auto_demotion_disable(void *dummy)
+{
+	unsigned long long msr_bits;
+
+	rdmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits);
+	msr_bits &= ~(icpu->auto_demotion_disable_flags);
+	wrmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits);
+}
+static void c1e_promotion_disable(void *dummy)
+{
+	unsigned long long msr_bits;
+
+	rdmsrl(MSR_IA32_POWER_CTL, msr_bits);
+	msr_bits &= ~0x2;
+	wrmsrl(MSR_IA32_POWER_CTL, msr_bits);
+}
+
 static int cpu_hotplug_notify(struct notifier_block *n,
 			      unsigned long action, void *hcpu)
 {
 	int hotcpu = (unsigned long)hcpu;
-	struct cpuidle_device *dev;
 
 	switch (action & ~CPU_TASKS_FROZEN) {
 	case CPU_ONLINE:
@@ -416,11 +430,15 @@ static int cpu_hotplug_notify(struct notifier_block *n,
 		/*
 		 * Some systems can hotplug a cpu at runtime after
 		 * the kernel has booted, we have to initialize the
-		 * driver in this case
+		 * hardware in this case.
 		 */
-		dev = per_cpu_ptr(intel_idle_cpuidle_devices, hotcpu);
-		if (!dev->registered)
-			intel_idle_cpu_init(hotcpu);
+		if (icpu->auto_demotion_disable_flags)
+			smp_call_function_single(hotcpu, auto_demotion_disable,
+						NULL, 1);
+
+		if (icpu->disable_promotion_to_c1e)
+			smp_call_function_single(hotcpu, c1e_promotion_disable,
+						NULL, 1);
 
 		break;
 	}
@@ -431,23 +449,6 @@ static struct notifier_block cpu_hotplug_notifier = {
 	.notifier_call = cpu_hotplug_notify,
 };
 
-static void auto_demotion_disable(void *dummy)
-{
-	unsigned long long msr_bits;
-
-	rdmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits);
-	msr_bits &= ~(icpu->auto_demotion_disable_flags);
-	wrmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits);
-}
-static void c1e_promotion_disable(void *dummy)
-{
-	unsigned long long msr_bits;
-
-	rdmsrl(MSR_IA32_POWER_CTL, msr_bits);
-	msr_bits &= ~0x2;
-	wrmsrl(MSR_IA32_POWER_CTL, msr_bits);
-}
-
 static const struct idle_cpu idle_cpu_nehalem = {
 	.state_table = nehalem_cstates,
 	.auto_demotion_disable_flags = NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE,
@@ -560,23 +561,6 @@ static int __init intel_idle_probe(void)
 }
 
 /*
- * intel_idle_cpuidle_devices_uninit()
- * unregister, free cpuidle_devices
- */
-static void intel_idle_cpuidle_devices_uninit(void)
-{
-	int i;
-	struct cpuidle_device *dev;
-
-	for_each_online_cpu(i) {
-		dev = per_cpu_ptr(intel_idle_cpuidle_devices, i);
-		cpuidle_unregister_device(dev);
-	}
-
-	free_percpu(intel_idle_cpuidle_devices);
-	return;
-}
-/*
  * intel_idle_cpuidle_driver_init()
  * allocate, initialize cpuidle_states
  */
@@ -632,37 +616,9 @@ static int __init intel_idle_cpuidle_driver_init(void)
 }
 
 
-/*
- * intel_idle_cpu_init()
- * allocate, initialize, register cpuidle_devices
- * @cpu: cpu/core to initialize
- */
-static int intel_idle_cpu_init(int cpu)
-{
-	struct cpuidle_device *dev;
-
-	dev = per_cpu_ptr(intel_idle_cpuidle_devices, cpu);
-
-	dev->cpu = cpu;
-
-	if (cpuidle_register_device(dev)) {
-		pr_debug(PREFIX "cpuidle_register_device %d failed!\n", cpu);
-		intel_idle_cpuidle_devices_uninit();
-		return -EIO;
-	}
-
-	if (icpu->auto_demotion_disable_flags)
-		smp_call_function_single(cpu, auto_demotion_disable, NULL, 1);
-
-	if (icpu->disable_promotion_to_c1e)
-		smp_call_function_single(cpu, c1e_promotion_disable, NULL, 1);
-
-	return 0;
-}
-
 static int __init intel_idle_init(void)
 {
-	int retval, i;
+	int retval;
 
 	/* Do not load intel_idle at all for now if idle= is passed */
 	if (boot_option_idle_override != IDLE_NO_OVERRIDE)
@@ -673,7 +629,8 @@ static int __init intel_idle_init(void)
 		return retval;
 
 	intel_idle_cpuidle_driver_init();
-	retval = cpuidle_register_driver(&intel_idle_driver);
+
+	retval = cpuidle_register(&intel_idle_driver, NULL);
 	if (retval) {
 		struct cpuidle_driver *drv = cpuidle_get_driver();
 		printk(KERN_DEBUG PREFIX "intel_idle yielding to %s",
@@ -681,17 +638,6 @@ static int __init intel_idle_init(void)
 		return retval;
 	}
 
-	intel_idle_cpuidle_devices = alloc_percpu(struct cpuidle_device);
-	if (intel_idle_cpuidle_devices == NULL)
-		return -ENOMEM;
-
-	for_each_online_cpu(i) {
-		retval = intel_idle_cpu_init(i);
-		if (retval) {
-			cpuidle_unregister_driver(&intel_idle_driver);
-			return retval;
-		}
-	}
 	register_cpu_notifier(&cpu_hotplug_notifier);
 
 	return 0;
@@ -699,9 +645,7 @@ static int __init intel_idle_init(void)
 
 static void __exit intel_idle_exit(void)
 {
-	intel_idle_cpuidle_devices_uninit();
-	cpuidle_unregister_driver(&intel_idle_driver);
-
+	cpuidle_unregister(&intel_idle_driver);
 
 	if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE)
 		on_each_cpu(__setup_broadcast_timer, (void *)false, 1);
-- 
1.8.2.3

^ permalink raw reply related

* [PATCH v2 9/9] cpuidle: remove state_count field from struct cpuidle_device
From: Bartlomiej Zolnierkiewicz @ 2013-12-20 18:47 UTC (permalink / raw)
  To: rjw
  Cc: linux-samsung-soc, linux-pm, b.zolnierkie, daniel.lezcano,
	linux-kernel, kyungmin.park, linuxppc-dev, lenb
In-Reply-To: <1387565251-7051-1-git-send-email-b.zolnierkie@samsung.com>

dev->state_count is now always equal to drv->state_count so
it can be removed.

Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 drivers/cpuidle/cpuidle.c | 3 ---
 drivers/cpuidle/sysfs.c   | 5 +++--
 include/linux/cpuidle.h   | 1 -
 3 files changed, 3 insertions(+), 6 deletions(-)

diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index a55e68f..e3d2052 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -252,9 +252,6 @@ int cpuidle_enable_device(struct cpuidle_device *dev)
 	if (!dev->registered)
 		return -EINVAL;
 
-	if (!dev->state_count)
-		dev->state_count = drv->state_count;
-
 	ret = cpuidle_add_device_sysfs(dev);
 	if (ret)
 		return ret;
diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c
index e918b6d..dcaae4c 100644
--- a/drivers/cpuidle/sysfs.c
+++ b/drivers/cpuidle/sysfs.c
@@ -398,7 +398,7 @@ static int cpuidle_add_state_sysfs(struct cpuidle_device *device)
 	struct cpuidle_driver *drv = cpuidle_get_cpu_driver(device);
 
 	/* state statistics */
-	for (i = 0; i < device->state_count; i++) {
+	for (i = 0; i < drv->state_count; i++) {
 		kobj = kzalloc(sizeof(struct cpuidle_state_kobj), GFP_KERNEL);
 		if (!kobj)
 			goto error_state;
@@ -430,9 +430,10 @@ error_state:
  */
 static void cpuidle_remove_state_sysfs(struct cpuidle_device *device)
 {
+	struct cpuidle_driver *drv = cpuidle_get_cpu_driver(device);
 	int i;
 
-	for (i = 0; i < device->state_count; i++)
+	for (i = 0; i < drv->state_count; i++)
 		cpuidle_free_state_kobj(device, i);
 }
 
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
index 50fcbb0..d133817 100644
--- a/include/linux/cpuidle.h
+++ b/include/linux/cpuidle.h
@@ -69,7 +69,6 @@ struct cpuidle_device {
 	unsigned int		cpu;
 
 	int			last_residency;
-	int			state_count;
 	struct cpuidle_state_usage	states_usage[CPUIDLE_STATE_MAX];
 	struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX];
 	struct cpuidle_driver_kobj *kobj_driver;
-- 
1.8.2.3

^ permalink raw reply related

* [PATCH v2] powernv: eeh: add buffer for P7IOC hub error data
From: Brian W Hart @ 2013-12-20 19:06 UTC (permalink / raw)
  To: linuxppc-dev

V2: Replace driver-global 'hub_diag' with a per-PHB hub diag structure.

Prevent ioda_eeh_hub_diag() from clobbering itself when called by supplying
a per-PHB buffer for P7IOC hub diagnostic data.  Take care to inform OPAL of
the correct size for the buffer.

Signed-off-by: Brian W Hart <hartb@linux.vnet.ibm.com>
---
 arch/powerpc/platforms/powernv/eeh-ioda.c | 15 ++-------------
 arch/powerpc/platforms/powernv/pci.h      |  4 +++-
 2 files changed, 5 insertions(+), 14 deletions(-)

diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c b/arch/powerpc/platforms/powernv/eeh-ioda.c
index 8184ef5..4790275 100644
--- a/arch/powerpc/platforms/powernv/eeh-ioda.c
+++ b/arch/powerpc/platforms/powernv/eeh-ioda.c
@@ -36,7 +36,6 @@
 #include "powernv.h"
 #include "pci.h"
 
-static char *hub_diag = NULL;
 static int ioda_eeh_nb_init = 0;
 
 static int ioda_eeh_event(struct notifier_block *nb,
@@ -140,15 +139,6 @@ static int ioda_eeh_post_init(struct pci_controller *hose)
 		ioda_eeh_nb_init = 1;
 	}
 
-	/* We needn't HUB diag-data on PHB3 */
-	if (phb->type == PNV_PHB_IODA1 && !hub_diag) {
-		hub_diag = (char *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
-		if (!hub_diag) {
-			pr_err("%s: Out of memory !\n", __func__);
-			return -ENOMEM;
-		}
-	}
-
 #ifdef CONFIG_DEBUG_FS
 	if (phb->dbgfs) {
 		debugfs_create_file("err_injct_outbound", 0600,
@@ -633,11 +623,10 @@ static void ioda_eeh_hub_diag_common(struct OpalIoP7IOCErrorData *data)
 static void ioda_eeh_hub_diag(struct pci_controller *hose)
 {
 	struct pnv_phb *phb = hose->private_data;
-	struct OpalIoP7IOCErrorData *data;
+	struct OpalIoP7IOCErrorData *data = &phb->diag.hub_diag;
 	long rc;
 
-	data = (struct OpalIoP7IOCErrorData *)ioda_eeh_hub_diag;
-	rc = opal_pci_get_hub_diag_data(phb->hub_id, data, PAGE_SIZE);
+	rc = opal_pci_get_hub_diag_data(phb->hub_id, data, sizeof *data);
 	if (rc != OPAL_SUCCESS) {
 		pr_warning("%s: Failed to get HUB#%llx diag-data (%ld)\n",
 			   __func__, phb->hub_id, rc);
diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h
index 911c24e..1ed8d5f 100644
--- a/arch/powerpc/platforms/powernv/pci.h
+++ b/arch/powerpc/platforms/powernv/pci.h
@@ -172,11 +172,13 @@ struct pnv_phb {
 		} ioda;
 	};
 
-	/* PHB status structure */
+	/* PHB and hub status structure */
 	union {
 		unsigned char			blob[PNV_PCI_DIAG_BUF_SIZE];
 		struct OpalIoP7IOCPhbErrorData	p7ioc;
+		struct OpalIoP7IOCErrorData 	hub_diag;
 	} diag;
+
 };
 
 extern struct pci_ops pnv_pci_ops;
-- 
1.8.3.1

^ permalink raw reply related

* Re: [PATCH v2 1/9] ARM: EXYNOS: cpuidle: fix AFTR mode check
From: Kukjin Kim @ 2013-12-20 20:47 UTC (permalink / raw)
  To: Bartlomiej Zolnierkiewicz
  Cc: linux-samsung-soc, linux-pm, daniel.lezcano, rjw, linux-kernel,
	kyungmin.park, Kukjin Kim, linuxppc-dev, lenb
In-Reply-To: <1387565251-7051-2-git-send-email-b.zolnierkie@samsung.com>

On 12/21/13 03:47, Bartlomiej Zolnierkiewicz wrote:
> The EXYNOS cpuidle driver code assumes that cpuidle core will handle
> dev->state_count smaller than drv->state_count but currently this is
> untrue (dev->state_count is used only for handling cpuidle state sysfs
> entries and drv->state_count is used for all other cases) and will not
> be fixed in the future as dev->state_count is planned to be removed.
>
> Fix the issue by checking for the max supported idle state in AFTR
> state's ->enter handler (exynos4_enter_lowpower()) and entering AFTR
> mode only when cores other than CPU0 are offline.
>
> Signed-off-by: Bartlomiej Zolnierkiewicz<b.zolnierkie@samsung.com>
> Signed-off-by: Kyungmin Park<kyungmin.park@samsung.com>
> Acked-by: Daniel Lezcano<daniel.lezcano@linaro.org>
> Cc: Kukjin Kim<kgene.kim@samsung.com>

Acked-by: Kukjin Kim <kgene.kim@samsung.com>

Thanks,
Kukjin

> ---
>   arch/arm/mach-exynos/cpuidle.c | 8 ++------
>   1 file changed, 2 insertions(+), 6 deletions(-)
>
> diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c
> index da65b03..f57cb91 100644
> --- a/arch/arm/mach-exynos/cpuidle.c
> +++ b/arch/arm/mach-exynos/cpuidle.c
> @@ -172,8 +172,8 @@ static int exynos4_enter_lowpower(struct cpuidle_device *dev,
>   {
>   	int new_index = index;
>
> -	/* This mode only can be entered when other core's are offline */
> -	if (num_online_cpus()>  1)
> +	/* AFTR can only be entered when cores other than CPU0 are offline */
> +	if (num_online_cpus()>  1 || dev->cpu != 0)
>   		new_index = drv->safe_state_index;
>
>   	if (new_index == 0)
> @@ -235,10 +235,6 @@ static int exynos_cpuidle_probe(struct platform_device *pdev)
>   		device =&per_cpu(exynos4_cpuidle_device, cpu_id);
>   		device->cpu = cpu_id;
>
> -		/* Support IDLE only */
> -		if (cpu_id != 0)
> -			device->state_count = 1;
> -
>   		ret = cpuidle_register_device(device);
>   		if (ret) {
>   			dev_err(&pdev->dev, "failed to register cpuidle device\n");

^ permalink raw reply

* Re: [PATCH v2 1/9] ARM: EXYNOS: cpuidle: fix AFTR mode check
From: Daniel Lezcano @ 2013-12-20 21:16 UTC (permalink / raw)
  To: Bartlomiej Zolnierkiewicz, rjw
  Cc: linux-samsung-soc, linux-pm, linux-kernel, kyungmin.park,
	Kukjin Kim, linuxppc-dev, lenb
In-Reply-To: <1387565251-7051-2-git-send-email-b.zolnierkie@samsung.com>

On 12/20/2013 07:47 PM, Bartlomiej Zolnierkiewicz wrote:
> The EXYNOS cpuidle driver code assumes that cpuidle core will handle
> dev->state_count smaller than drv->state_count but currently this is
> untrue (dev->state_count is used only for handling cpuidle state sysfs
> entries and drv->state_count is used for all other cases) and will not
> be fixed in the future as dev->state_count is planned to be removed.
>
> Fix the issue by checking for the max supported idle state in AFTR
> state's ->enter handler (exynos4_enter_lowpower()) and entering AFTR
> mode only when cores other than CPU0 are offline.
>
> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org>
> Cc: Kukjin Kim <kgene.kim@samsung.com>
> ---
>   arch/arm/mach-exynos/cpuidle.c | 8 ++------
>   1 file changed, 2 insertions(+), 6 deletions(-)
>
> diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c
> index da65b03..f57cb91 100644
> --- a/arch/arm/mach-exynos/cpuidle.c
> +++ b/arch/arm/mach-exynos/cpuidle.c
> @@ -172,8 +172,8 @@ static int exynos4_enter_lowpower(struct cpuidle_device *dev,
>   {
>   	int new_index = index;
>
> -	/* This mode only can be entered when other core's are offline */
> -	if (num_online_cpus() > 1)
> +	/* AFTR can only be entered when cores other than CPU0 are offline */
> +	if (num_online_cpus() > 1 || dev->cpu != 0)
>   		new_index = drv->safe_state_index;
>
>   	if (new_index == 0)
> @@ -235,10 +235,6 @@ static int exynos_cpuidle_probe(struct platform_device *pdev)
>   		device = &per_cpu(exynos4_cpuidle_device, cpu_id);
>   		device->cpu = cpu_id;
>
> -		/* Support IDLE only */
> -		if (cpu_id != 0)
> -			device->state_count = 1;
> -
>   		ret = cpuidle_register_device(device);
>   		if (ret) {
>   			dev_err(&pdev->dev, "failed to register cpuidle device\n");
>

Hi Bartlomiej,

thanks for this cleanup. May be you can also add another patch to switch 
to the generic cpuidle_register function ?

Thanks
   -- Daniel

-- 
  <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog

^ permalink raw reply

* Re: [PATCH v2] powerpc/512x: dts: disable MPC5125 usb module
From: Anatolij Gustschin @ 2013-12-20 21:16 UTC (permalink / raw)
  To: Matteo Facchinetti; +Cc: gsi, linuxppc-dev
In-Reply-To: <1387530982-6115-1-git-send-email-matteo.facchinetti@sirius-es.it>

On Fri, 20 Dec 2013 10:16:22 +0100
Matteo Facchinetti <matteo.facchinetti@sirius-es.it> wrote:

> At the moment the USB controller's pin muxing is not setup
> correctly and causes a kernel panic upon system startup, so
> disable the USB1 device tree node in the MPC5125 tower board
> dts file.
> 
> The USB controller is connected to an USB3320 ULPI transceiver
> and the device tree should receive an update to reflect correct
> dependencies and required initialization data before the USB1
> node can get re-enabled.
> 
> Signed-off-by: Matteo Facchinetti <matteo.facchinetti@sirius-es.it>
> ---
> v2:
> * improve the text of the commit as suggested by Gerhard Sittig <gsi@denx.de>
> * put the 'status = "disabled"' to the last line in the list of properties
> * rewiew the comment related to USB1 device tree node
> ---
>  arch/powerpc/boot/dts/mpc5125twr.dts | 5 +++++
>  1 file changed, 5 insertions(+)

Applied to merge branch. Thanks!

Anatolij

^ permalink raw reply

* Re: [PATCH v2 9/9] cpuidle: remove state_count field from struct cpuidle_device
From: Daniel Lezcano @ 2013-12-20 21:27 UTC (permalink / raw)
  To: Bartlomiej Zolnierkiewicz, rjw
  Cc: linux-samsung-soc, linux-pm, linux-kernel, kyungmin.park,
	linuxppc-dev, lenb
In-Reply-To: <1387565251-7051-10-git-send-email-b.zolnierkie@samsung.com>

On 12/20/2013 07:47 PM, Bartlomiej Zolnierkiewicz wrote:
> dev->state_count is now always equal to drv->state_count so
> it can be removed.
>
> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>

Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org>

> ---
>   drivers/cpuidle/cpuidle.c | 3 ---
>   drivers/cpuidle/sysfs.c   | 5 +++--
>   include/linux/cpuidle.h   | 1 -
>   3 files changed, 3 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
> index a55e68f..e3d2052 100644
> --- a/drivers/cpuidle/cpuidle.c
> +++ b/drivers/cpuidle/cpuidle.c
> @@ -252,9 +252,6 @@ int cpuidle_enable_device(struct cpuidle_device *dev)
>   	if (!dev->registered)
>   		return -EINVAL;
>
> -	if (!dev->state_count)
> -		dev->state_count = drv->state_count;
> -
>   	ret = cpuidle_add_device_sysfs(dev);
>   	if (ret)
>   		return ret;
> diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c
> index e918b6d..dcaae4c 100644
> --- a/drivers/cpuidle/sysfs.c
> +++ b/drivers/cpuidle/sysfs.c
> @@ -398,7 +398,7 @@ static int cpuidle_add_state_sysfs(struct cpuidle_device *device)
>   	struct cpuidle_driver *drv = cpuidle_get_cpu_driver(device);
>
>   	/* state statistics */
> -	for (i = 0; i < device->state_count; i++) {
> +	for (i = 0; i < drv->state_count; i++) {
>   		kobj = kzalloc(sizeof(struct cpuidle_state_kobj), GFP_KERNEL);
>   		if (!kobj)
>   			goto error_state;
> @@ -430,9 +430,10 @@ error_state:
>    */
>   static void cpuidle_remove_state_sysfs(struct cpuidle_device *device)
>   {
> +	struct cpuidle_driver *drv = cpuidle_get_cpu_driver(device);
>   	int i;
>
> -	for (i = 0; i < device->state_count; i++)
> +	for (i = 0; i < drv->state_count; i++)
>   		cpuidle_free_state_kobj(device, i);
>   }
>
> diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
> index 50fcbb0..d133817 100644
> --- a/include/linux/cpuidle.h
> +++ b/include/linux/cpuidle.h
> @@ -69,7 +69,6 @@ struct cpuidle_device {
>   	unsigned int		cpu;
>
>   	int			last_residency;
> -	int			state_count;
>   	struct cpuidle_state_usage	states_usage[CPUIDLE_STATE_MAX];
>   	struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX];
>   	struct cpuidle_driver_kobj *kobj_driver;
>


-- 
  <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog

^ permalink raw reply

* Re: [PATCH v2 8/9] intel_idle: use the common cpuidle_[un]register() routines
From: Daniel Lezcano @ 2013-12-20 21:42 UTC (permalink / raw)
  To: Bartlomiej Zolnierkiewicz, rjw
  Cc: linux-samsung-soc, linux-pm, linux-kernel, kyungmin.park,
	linuxppc-dev, lenb
In-Reply-To: <1387565251-7051-9-git-send-email-b.zolnierkie@samsung.com>

On 12/20/2013 07:47 PM, Bartlomiej Zolnierkiewicz wrote:
> It is now possible to use the common cpuidle_[un]register() routines
> (instead of open-coding them) so do it.

Just an addition:

The cpuidle_register common routine calls cpuidle_register_driver which 
initialize the driver's cpumask to cpu_possible_mask if not set (which 
is the default on most platform) and right after it uses this mask to 
register the cpuidle devices. That's why the cpu hotplug does not need 
to register the device unlike before this patch where the cpumask was 
cpu_online_mask. So we can't fall in the "Some systems can hotplug a cpu 
at runtime after the kernel has booted" case.

Reviewed-by: Daniel Lezcano <daniel.lezcano@linaro.org>

> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> Cc: Len Brown <lenb@kernel.org>
> ---
>   drivers/idle/intel_idle.c | 114 ++++++++++++----------------------------------
>   1 file changed, 29 insertions(+), 85 deletions(-)
>
> diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
> index 524d07b..a1a4dbd 100644
> --- a/drivers/idle/intel_idle.c
> +++ b/drivers/idle/intel_idle.c
> @@ -93,10 +93,8 @@ struct idle_cpu {
>   };
>
>   static const struct idle_cpu *icpu;
> -static struct cpuidle_device __percpu *intel_idle_cpuidle_devices;
>   static int intel_idle(struct cpuidle_device *dev,
>   			struct cpuidle_driver *drv, int index);
> -static int intel_idle_cpu_init(int cpu);
>
>   static struct cpuidle_state *cpuidle_state_table;
>
> @@ -400,11 +398,27 @@ static void __setup_broadcast_timer(void *arg)
>   	clockevents_notify(reason, &cpu);
>   }
>
> +static void auto_demotion_disable(void *dummy)
> +{
> +	unsigned long long msr_bits;
> +
> +	rdmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits);
> +	msr_bits &= ~(icpu->auto_demotion_disable_flags);
> +	wrmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits);
> +}
> +static void c1e_promotion_disable(void *dummy)
> +{
> +	unsigned long long msr_bits;
> +
> +	rdmsrl(MSR_IA32_POWER_CTL, msr_bits);
> +	msr_bits &= ~0x2;
> +	wrmsrl(MSR_IA32_POWER_CTL, msr_bits);
> +}
> +
>   static int cpu_hotplug_notify(struct notifier_block *n,
>   			      unsigned long action, void *hcpu)
>   {
>   	int hotcpu = (unsigned long)hcpu;
> -	struct cpuidle_device *dev;
>
>   	switch (action & ~CPU_TASKS_FROZEN) {
>   	case CPU_ONLINE:
> @@ -416,11 +430,15 @@ static int cpu_hotplug_notify(struct notifier_block *n,
>   		/*
>   		 * Some systems can hotplug a cpu at runtime after
>   		 * the kernel has booted, we have to initialize the
> -		 * driver in this case
> +		 * hardware in this case.
>   		 */
> -		dev = per_cpu_ptr(intel_idle_cpuidle_devices, hotcpu);
> -		if (!dev->registered)
> -			intel_idle_cpu_init(hotcpu);
> +		if (icpu->auto_demotion_disable_flags)
> +			smp_call_function_single(hotcpu, auto_demotion_disable,
> +						NULL, 1);
> +
> +		if (icpu->disable_promotion_to_c1e)
> +			smp_call_function_single(hotcpu, c1e_promotion_disable,
> +						NULL, 1);
>
>   		break;
>   	}
> @@ -431,23 +449,6 @@ static struct notifier_block cpu_hotplug_notifier = {
>   	.notifier_call = cpu_hotplug_notify,
>   };
>
> -static void auto_demotion_disable(void *dummy)
> -{
> -	unsigned long long msr_bits;
> -
> -	rdmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits);
> -	msr_bits &= ~(icpu->auto_demotion_disable_flags);
> -	wrmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits);
> -}
> -static void c1e_promotion_disable(void *dummy)
> -{
> -	unsigned long long msr_bits;
> -
> -	rdmsrl(MSR_IA32_POWER_CTL, msr_bits);
> -	msr_bits &= ~0x2;
> -	wrmsrl(MSR_IA32_POWER_CTL, msr_bits);
> -}
> -
>   static const struct idle_cpu idle_cpu_nehalem = {
>   	.state_table = nehalem_cstates,
>   	.auto_demotion_disable_flags = NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE,
> @@ -560,23 +561,6 @@ static int __init intel_idle_probe(void)
>   }
>
>   /*
> - * intel_idle_cpuidle_devices_uninit()
> - * unregister, free cpuidle_devices
> - */
> -static void intel_idle_cpuidle_devices_uninit(void)
> -{
> -	int i;
> -	struct cpuidle_device *dev;
> -
> -	for_each_online_cpu(i) {
> -		dev = per_cpu_ptr(intel_idle_cpuidle_devices, i);
> -		cpuidle_unregister_device(dev);
> -	}
> -
> -	free_percpu(intel_idle_cpuidle_devices);
> -	return;
> -}
> -/*
>    * intel_idle_cpuidle_driver_init()
>    * allocate, initialize cpuidle_states
>    */
> @@ -632,37 +616,9 @@ static int __init intel_idle_cpuidle_driver_init(void)
>   }
>
>
> -/*
> - * intel_idle_cpu_init()
> - * allocate, initialize, register cpuidle_devices
> - * @cpu: cpu/core to initialize
> - */
> -static int intel_idle_cpu_init(int cpu)
> -{
> -	struct cpuidle_device *dev;
> -
> -	dev = per_cpu_ptr(intel_idle_cpuidle_devices, cpu);
> -
> -	dev->cpu = cpu;
> -
> -	if (cpuidle_register_device(dev)) {
> -		pr_debug(PREFIX "cpuidle_register_device %d failed!\n", cpu);
> -		intel_idle_cpuidle_devices_uninit();
> -		return -EIO;
> -	}
> -
> -	if (icpu->auto_demotion_disable_flags)
> -		smp_call_function_single(cpu, auto_demotion_disable, NULL, 1);
> -
> -	if (icpu->disable_promotion_to_c1e)
> -		smp_call_function_single(cpu, c1e_promotion_disable, NULL, 1);
> -
> -	return 0;
> -}
> -
>   static int __init intel_idle_init(void)
>   {
> -	int retval, i;
> +	int retval;
>
>   	/* Do not load intel_idle at all for now if idle= is passed */
>   	if (boot_option_idle_override != IDLE_NO_OVERRIDE)
> @@ -673,7 +629,8 @@ static int __init intel_idle_init(void)
>   		return retval;
>
>   	intel_idle_cpuidle_driver_init();
> -	retval = cpuidle_register_driver(&intel_idle_driver);
> +
> +	retval = cpuidle_register(&intel_idle_driver, NULL);
>   	if (retval) {
>   		struct cpuidle_driver *drv = cpuidle_get_driver();
>   		printk(KERN_DEBUG PREFIX "intel_idle yielding to %s",
> @@ -681,17 +638,6 @@ static int __init intel_idle_init(void)
>   		return retval;
>   	}
>
> -	intel_idle_cpuidle_devices = alloc_percpu(struct cpuidle_device);
> -	if (intel_idle_cpuidle_devices == NULL)
> -		return -ENOMEM;
> -
> -	for_each_online_cpu(i) {
> -		retval = intel_idle_cpu_init(i);
> -		if (retval) {
> -			cpuidle_unregister_driver(&intel_idle_driver);
> -			return retval;
> -		}
> -	}
>   	register_cpu_notifier(&cpu_hotplug_notifier);
>
>   	return 0;
> @@ -699,9 +645,7 @@ static int __init intel_idle_init(void)
>
>   static void __exit intel_idle_exit(void)
>   {
> -	intel_idle_cpuidle_devices_uninit();
> -	cpuidle_unregister_driver(&intel_idle_driver);
> -
> +	cpuidle_unregister(&intel_idle_driver);
>
>   	if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE)
>   		on_each_cpu(__setup_broadcast_timer, (void *)false, 1);
>


-- 
  <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog

^ permalink raw reply

* Re: [PATCH v2 7/9] intel_idle: remove superfluous dev->state_count initialization
From: Daniel Lezcano @ 2013-12-20 21:48 UTC (permalink / raw)
  To: Bartlomiej Zolnierkiewicz, rjw
  Cc: linux-samsung-soc, linux-pm, linux-kernel, kyungmin.park,
	linuxppc-dev, lenb
In-Reply-To: <1387565251-7051-8-git-send-email-b.zolnierkie@samsung.com>

On 12/20/2013 07:47 PM, Bartlomiej Zolnierkiewicz wrote:
> intel_idle driver sets dev->state_count to drv->state_count so
> the default dev->state_count initialization in cpuidle_enable_device()
> (called from cpuidle_register_device()) can be used instead.
>
> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> Cc: Len Brown <lenb@kernel.org>

Reviewed-by: Daniel Lezcano <daniel.lezcano@linaro.org>

> ---
>   drivers/idle/intel_idle.c | 29 -----------------------------
>   1 file changed, 29 deletions(-)
>
> diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
> index 38da3fb..524d07b 100644
> --- a/drivers/idle/intel_idle.c
> +++ b/drivers/idle/intel_idle.c
> @@ -639,39 +639,10 @@ static int __init intel_idle_cpuidle_driver_init(void)
>    */
>   static int intel_idle_cpu_init(int cpu)
>   {
> -	int cstate;
>   	struct cpuidle_device *dev;
>
>   	dev = per_cpu_ptr(intel_idle_cpuidle_devices, cpu);
>
> -	dev->state_count = 1;
> -
> -	for (cstate = 0; cstate < CPUIDLE_STATE_MAX; ++cstate) {
> -		int num_substates, mwait_hint, mwait_cstate, mwait_substate;
> -
> -		if (cpuidle_state_table[cstate].enter == NULL)
> -			break;
> -
> -		if (cstate + 1 > max_cstate) {
> -			printk(PREFIX "max_cstate %d reached\n", max_cstate);
> -			break;
> -		}
> -
> -		mwait_hint = flg2MWAIT(cpuidle_state_table[cstate].flags);
> -		mwait_cstate = MWAIT_HINT2CSTATE(mwait_hint);
> -		mwait_substate = MWAIT_HINT2SUBSTATE(mwait_hint);
> -
> -		/* does the state exist in CPUID.MWAIT? */
> -		num_substates = (mwait_substates >> ((mwait_cstate + 1) * 4))
> -					& MWAIT_SUBSTATE_MASK;
> -
> -		/* if sub-state in table is not enumerated by CPUID */
> -		if ((mwait_substate + 1) > num_substates)
> -			continue;
> -
> -		dev->state_count += 1;
> -	}
> -
>   	dev->cpu = cpu;
>
>   	if (cpuidle_register_device(dev)) {
>


-- 
  <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog

^ permalink raw reply

* Re: [PATCH v2 6/9] intel_idle: do C1E promotion disable quirk for hotplugged CPUs
From: Daniel Lezcano @ 2013-12-20 21:52 UTC (permalink / raw)
  To: Bartlomiej Zolnierkiewicz, rjw
  Cc: linux-samsung-soc, linux-pm, linux-kernel, kyungmin.park,
	linuxppc-dev, lenb
In-Reply-To: <1387565251-7051-7-git-send-email-b.zolnierkie@samsung.com>

On 12/20/2013 07:47 PM, Bartlomiej Zolnierkiewicz wrote:
> If the system is booted with some CPUs offline C1E promotion disable quirk
> won't be applied because on_each_cpu() in intel_idle_cpuidle_driver_init()
> operates only on online CPUs. Fix it by adding the C1E promotion disable
> handling to intel_idle_cpu_init() (which is also called during CPU_ONLINE
> operation).
>
> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> Cc: Len Brown <lenb@kernel.org>

Reviewed-by: Daniel Lezcano <daniel.lezcano@linaro.org>

> ---
>   drivers/idle/intel_idle.c | 3 +++
>   1 file changed, 3 insertions(+)
>
> diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
> index 92d1206..38da3fb 100644
> --- a/drivers/idle/intel_idle.c
> +++ b/drivers/idle/intel_idle.c
> @@ -683,6 +683,9 @@ static int intel_idle_cpu_init(int cpu)
>   	if (icpu->auto_demotion_disable_flags)
>   		smp_call_function_single(cpu, auto_demotion_disable, NULL, 1);
>
> +	if (icpu->disable_promotion_to_c1e)
> +		smp_call_function_single(cpu, c1e_promotion_disable, NULL, 1);
> +
>   	return 0;
>   }

-- 
  <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog

^ permalink raw reply

* AUTO: Michael Barry is out of the office (returning 06/01/2014)
From: Michael Barry @ 2013-12-20 23:22 UTC (permalink / raw)
  To: linuxppc-dev


I am out of the office until 06/01/2014.




Note: This is an automated response to your message  "Linuxppc-dev Digest,
Vol 112, Issue 84" sent on 20/12/2013 18:58:14.

This is the only notification you will receive while this person is away.

^ permalink raw reply

* [PATCH] powerpc: Align p_end
From: Anton Blanchard @ 2013-12-23  1:19 UTC (permalink / raw)
  To: benh, paulus; +Cc: linuxppc-dev


p_end is an 8 byte value embedded in the text section. This means it
is only 4 byte aligned when it should be 8 byte aligned. Fix this
by adding an explicit alignment.

This fixes an issue where POWER7 little endian builds with 
CONFIG_RELOCATABLE=y fail to boot.

Signed-off-by: Anton Blanchard <anton@samba.org>
---

diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 2ae41ab..fad2abd 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -470,6 +470,7 @@ _STATIC(__after_prom_start)
 	mtctr	r8
 	bctr
 
+.balign 8
 p_end:	.llong	_end - _stext
 
 4:	/* Now copy the rest of the kernel up to _end */

^ permalink raw reply related

* [PATCH 4/4] powerpc: Don't return to BE mode when we are already there
From: Alexander Graf @ 2013-12-23  1:24 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Dinar Valeev, Anton Blanchard
In-Reply-To: <1387761885-39599-1-git-send-email-agraf@suse.de>

Our Little Endian kernels can now live in a world where they are
running with Big Endian interrupts enabled. That is great for kexec,
because now we don't have to switch back to Big Endian mode.

Indicate this in the code. Only try to go into Big Endian mode when
we're not already there yet.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 arch/powerpc/platforms/pseries/setup.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index fb5d98c..7db1cf1 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -446,10 +446,15 @@ static void pSeries_machine_kexec(struct kimage *image)
 #endif
 
 #ifdef __LITTLE_ENDIAN__
+static bool ile_enabled;
+
 long pseries_big_endian_exceptions(void)
 {
 	long rc;
 
+	if (!ile_enabled)
+		return H_SUCCESS;
+
 	while (1) {
 		rc = enable_big_endian_exceptions();
 		if (!H_IS_LONG_BUSY(rc))
@@ -498,8 +503,12 @@ static long pseries_little_endian_exceptions(void)
 
 	while (1) {
 		rc = enable_little_endian_exceptions();
-		if (!H_IS_LONG_BUSY(rc))
+
+		if (!H_IS_LONG_BUSY(rc)) {
+			ile_enabled = true;
 			return rc;
+		}
+
 		mdelay(get_longbusy_msecs(rc));
 	}
 }
-- 
1.8.1.4

^ permalink raw reply related

* [PATCH 2/4] powerpc: Add relocation code for fixups
From: Alexander Graf @ 2013-12-23  1:24 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Dinar Valeev, Anton Blanchard
In-Reply-To: <1387761885-39599-1-git-send-email-agraf@suse.de>

We need to patch an instruction that is covered by the fixup
framework. If we don't do anything about it we end up getting
our own patched instruction unpatched by nops by the fixups.

So add an export to the fixup code that allows us to tell it
that an instruction moved location in memory. This works because
we move the instruction into a different location, but still
execute it.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 arch/powerpc/include/asm/cputable.h |  2 ++
 arch/powerpc/lib/feature-fixups.c   | 22 ++++++++++++++++++++++
 2 files changed, 24 insertions(+)

diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h
index 0d4939b..c981f99 100644
--- a/arch/powerpc/include/asm/cputable.h
+++ b/arch/powerpc/include/asm/cputable.h
@@ -99,6 +99,8 @@ extern unsigned int __start___ftr_fixup, __stop___ftr_fixup;
 extern struct cpu_spec *identify_cpu(unsigned long offset, unsigned int pvr);
 extern void do_feature_fixups(unsigned long value, void *fixup_start,
 			      void *fixup_end);
+extern void relocate_fixup_entry(void *fixup_start, void *fixup_end,
+				 void *old_addr, void *new_addr);
 
 extern const char *powerpc_base_platform;
 
diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c
index 7a8a748..33996a4 100644
--- a/arch/powerpc/lib/feature-fixups.c
+++ b/arch/powerpc/lib/feature-fixups.c
@@ -151,6 +151,28 @@ void do_final_fixups(void)
 #endif
 }
 
+/*
+ * This changes the internal fixup location of a code block from
+ * old_addr to new_addr.
+ */
+void relocate_fixup_entry(void *fixup_start, void *fixup_end,
+			  void *old_addr, void *new_addr)
+{
+	struct fixup_entry *fcur, *fend;
+
+	fcur = fixup_start;
+	fend = fixup_end;
+
+	for (; fcur < fend; fcur++) {
+		long diff = (long)new_addr -
+			    (long)calc_addr(fcur, fcur->start_off);
+		if (calc_addr(fcur, fcur->start_off) == old_addr) {
+			fcur->start_off += diff;
+			fcur->end_off += diff;
+		}
+	}
+}
+
 #ifdef CONFIG_FTR_FIXUP_SELFTEST
 
 #define check(x)	\
-- 
1.8.1.4

^ permalink raw reply related

* [PATCH 0/4] powerpc: Enable ILE on pSeries without H_MODE_SET
From: Alexander Graf @ 2013-12-23  1:24 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Dinar Valeev, Anton Blanchard

Howdy,

There are a few machines out there that would be pretty ppc64le capable
if only it wasn't for the hypervisor that's running on them.

The problem is that we need to run in ILE (interrupts delivered in little
endian) mode to run our normal interrupt vectors. The hypercall to enable
this mode is not available on PowerVM.

However, we can try to be smart here. Instead of configuring the hypervisor
to run interrupts in little endian mode, we can just bring ourselves back
to little endian on every interrupt.

We do this by patching every interrupt handler with a "branch" instruction
at the beginning which jumps into a tiny helper that turns on MSR.LE and
resumes the interrupt handler.

This is not the most smart thing to do performance wise, but it does have
a really nice side effect: We do not impact hypervisors that do support
H_SET_MODE. This is important, as we want to be as fast as possible on machines
that are supposed to run Little Endian guests.

As a tiny side effect we also clobber CFAR in every interrupt, rendering
the whole thing pretty useless. So we don't get nice and shiny perf and
debugging helps. Oh well.

Given that the alternatives to all of this would either be

  a) Not run at all or
  b) Incur performance penalties for "good" systems or
  c) Add significant maintenance burden on us

I'm quite convinced this is the way we want to go.


Enjoy,

Alex

Alexander Graf (4):
  powerpc: Add global exports for all interrupt vectors
  powerpc: Add relocation code for fixups
  powerpc: Add hack to make ppc64le work on hosts without ILE
  powerpc: Don't return to BE mode when we are already there

 arch/powerpc/include/asm/cputable.h    |   2 +
 arch/powerpc/kernel/Makefile           |   3 +
 arch/powerpc/kernel/exceptions-64s.S   |   5 ++
 arch/powerpc/kernel/fake_ile.S         | 101 +++++++++++++++++++++++++++++++++
 arch/powerpc/kernel/vmlinux.lds.S      |  14 +++++
 arch/powerpc/lib/feature-fixups.c      |  22 +++++++
 arch/powerpc/platforms/pseries/setup.c |  61 +++++++++++++++++++-
 7 files changed, 207 insertions(+), 1 deletion(-)
 create mode 100644 arch/powerpc/kernel/fake_ile.S

-- 
1.8.1.4

^ permalink raw reply

* [PATCH 1/4] powerpc: Add global exports for all interrupt vectors
From: Alexander Graf @ 2013-12-23  1:24 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Dinar Valeev, Anton Blanchard
In-Reply-To: <1387761885-39599-1-git-send-email-agraf@suse.de>

We need to access every interrupt vector we can find soon, so let's
make them all visible through names to outside code.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 arch/powerpc/kernel/exceptions-64s.S | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 9f905e4..fcd039f 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -148,6 +148,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
 				 NOTEST, 0x100)
 
 	. = 0x200
+	.globl machine_check_pSeries_1
 machine_check_pSeries_1:
 	/* This is moved out of line as it can be patched by FW, but
 	 * some code path might still want to branch into the original
@@ -328,24 +329,28 @@ hv_doorbell_trampoline:
 	 * trickery is thus necessary
 	 */
 	. = 0xf00
+	.global performance_monitor_pseries_trampoline
 performance_monitor_pseries_trampoline:
 	SET_SCRATCH0(r13)
 	EXCEPTION_PROLOG_0(PACA_EXGEN)
 	b	performance_monitor_pSeries
 
 	. = 0xf20
+	.global altivec_unavailable_pseries_trampoline
 altivec_unavailable_pseries_trampoline:
 	SET_SCRATCH0(r13)
 	EXCEPTION_PROLOG_0(PACA_EXGEN)
 	b	altivec_unavailable_pSeries
 
 	. = 0xf40
+	.global vsx_unavailable_pseries_trampoline
 vsx_unavailable_pseries_trampoline:
 	SET_SCRATCH0(r13)
 	EXCEPTION_PROLOG_0(PACA_EXGEN)
 	b	vsx_unavailable_pSeries
 
 	. = 0xf60
+	.global facility_unavailable_trampoline
 facility_unavailable_trampoline:
 	SET_SCRATCH0(r13)
 	EXCEPTION_PROLOG_0(PACA_EXGEN)
-- 
1.8.1.4

^ permalink raw reply related

* [PATCH 3/4] powerpc: Add hack to make ppc64le work on hosts without ILE
From: Alexander Graf @ 2013-12-23  1:24 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Dinar Valeev, Anton Blanchard
In-Reply-To: <1387761885-39599-1-git-send-email-agraf@suse.de>

Some hypervisors don't implement the H_SET_MODE hypercall that we
need to set the ILE bit in LPCR which allows us to execute interrupts
in little endian mode.

However otherwise we would be able to run on those hypervisors just
fine.

So let's be creative. This patch creates a few small helpers that
work without register clobbering that execute in big endian mode.

Every interrupt gets patched with a branch instruction as the first
instruction which jumps into their respective helper. That helper
enables MSR.LE and returns back to the original interrupt.

That way we can keep our interrupt handlers in little endian code
while the hypervisor is unaware that we need them to be in little
endian.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 arch/powerpc/kernel/Makefile           |   3 +
 arch/powerpc/kernel/fake_ile.S         | 101 +++++++++++++++++++++++++++++++++
 arch/powerpc/kernel/vmlinux.lds.S      |  14 +++++
 arch/powerpc/platforms/pseries/setup.c |  50 ++++++++++++++++
 4 files changed, 168 insertions(+)
 create mode 100644 arch/powerpc/kernel/fake_ile.S

diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 445cb6e..31842e6 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -131,6 +131,9 @@ endif
 
 obj-$(CONFIG_EPAPR_PARAVIRT)	+= epapr_paravirt.o epapr_hcalls.o
 obj-$(CONFIG_KVM_GUEST)		+= kvm.o kvm_emul.o
+ifeq ($(CONFIG_CPU_LITTLE_ENDIAN),y)
+obj-$(CONFIG_PPC_BOOK3S_64)	+= fake_ile.o
+endif
 
 # Disable GCOV in odd or sensitive code
 GCOV_PROFILE_prom_init.o := n
diff --git a/arch/powerpc/kernel/fake_ile.S b/arch/powerpc/kernel/fake_ile.S
new file mode 100644
index 0000000..21e9bd7
--- /dev/null
+++ b/arch/powerpc/kernel/fake_ile.S
@@ -0,0 +1,101 @@
+/*
+ * PowerPC helpers for hypervisors without ILE implementation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright SUSE Linux Products GmbH 2013
+ *
+ * Authors: Alexander Graf <agraf@suse.de>
+ */
+
+#include <asm/reg.h>
+#include <asm/ppc_asm.h>
+#include <asm/asm-offsets.h>
+#include <asm/exception-64s.h>
+
+/* Little Endian fixups for hosts that don't support Little Endian */
+
+#define FAKE_ILE_HANDLER(handler, area) 			 \
+								 \
+/* This runs in BE mode */					 \
+fake_ile_##handler:						 \
+	.section __be_patch,"a"					;\
+	.llong fake_ile_##handler				;\
+	.previous						;\
+	SET_SCRATCH0(r13)					;\
+	GET_PACA(r13)						;\
+	std     r9, area + EX_R9(r13)				;\
+	std     r10, area + EX_R10(r13)				;\
+	mfsrr0	r9						;\
+	mfsrr1	r10						;\
+	std	r9, area + EX_SRR0(r13)				;\
+	std	r10, area + EX_R11(r13)				;\
+	mflr	r9						;\
+	bl	1f						;\
+	1:							;\
+	mflr	r10						;\
+	mtlr	r9						;\
+	addi	r9, r10, back_to_interrupt_##handler - 1b	;\
+	mfmsr	r10						;\
+	ori	r10, r10, MSR_LE				;\
+	mtsrr0	r9						;\
+	mtsrr1	r10						;\
+	ld	r9, area + EX_SRR0(r13)				;\
+	ld	r10, area + EX_R11(r13)				;\
+	RFI							;\
+	end_fake_ile_##handler:					;\
+	.section __be_patch,"a"					;\
+	.llong end_fake_ile_##handler				;\
+	.previous						;\
+								;\
+/* This runs in LE mode */					 \
+back_to_interrupt_##handler:					;\
+	mtsrr0	r9						;\
+	mtsrr1	r10						;\
+	li	r9, area + EX_R9				;\
+	li	r10, area + EX_R10				;\
+	ldbrx	r9, r13, r9					;\
+	ldbrx	r10, r13, r10					;\
+	GET_SCRATCH0(r13)					;\
+	/* This becomes the instruction we patched away */	 \
+	patched_insn_##handler:					;\
+	.long 0							;\
+	b 	handler + 4					;\
+								 \
+	.section __fake_ile,"a"					;\
+	.llong handler						;\
+	.llong patched_insn_##handler				;\
+	.llong fake_ile_##handler				;\
+	.previous						;\
+
+FAKE_ILE_HANDLER(system_reset_pSeries, PACA_EXMC)
+FAKE_ILE_HANDLER(machine_check_pSeries_1, PACA_EXMC)
+FAKE_ILE_HANDLER(data_access_pSeries, PACA_EXGEN)
+FAKE_ILE_HANDLER(data_access_slb_pSeries, PACA_EXSLB)
+FAKE_ILE_HANDLER(instruction_access_pSeries, PACA_EXGEN)
+FAKE_ILE_HANDLER(instruction_access_slb_pSeries, PACA_EXSLB)
+FAKE_ILE_HANDLER(hardware_interrupt_pSeries, PACA_EXGEN)
+FAKE_ILE_HANDLER(alignment_pSeries, PACA_EXGEN)
+FAKE_ILE_HANDLER(program_check_pSeries, PACA_EXGEN)
+FAKE_ILE_HANDLER(fp_unavailable_pSeries, PACA_EXGEN)
+FAKE_ILE_HANDLER(decrementer_pSeries, PACA_EXGEN)
+FAKE_ILE_HANDLER(doorbell_super_pSeries, PACA_EXGEN)
+FAKE_ILE_HANDLER(trap_0b_pSeries, PACA_EXGEN)
+FAKE_ILE_HANDLER(system_call_pSeries, PACA_EXGEN)
+FAKE_ILE_HANDLER(performance_monitor_pseries_trampoline, PACA_EXGEN)
+FAKE_ILE_HANDLER(altivec_unavailable_pseries_trampoline, PACA_EXGEN)
+FAKE_ILE_HANDLER(vsx_unavailable_pseries_trampoline, PACA_EXGEN)
+FAKE_ILE_HANDLER(facility_unavailable_trampoline, PACA_EXGEN)
+FAKE_ILE_HANDLER(instruction_breakpoint_pSeries, PACA_EXGEN)
+FAKE_ILE_HANDLER(altivec_assist_pSeries, PACA_EXGEN)
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index f096e72..7fdb7c9 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -147,6 +147,20 @@ SECTIONS
 		*(__fw_ftr_fixup)
 		__stop___fw_ftr_fixup = .;
 	}
+
+	. = ALIGN(8);
+	__fake_ile : AT(ADDR(__fake_ile) - LOAD_OFFSET) {
+		__start___fake_ile = .;
+		*(__fake_ile)
+		__stop___fake_ile = .;
+	}
+
+	. = ALIGN(8);
+	__be_patch : AT(ADDR(__be_patch) - LOAD_OFFSET) {
+		__start___be_patch = .;
+		*(__be_patch)
+		__stop___be_patch = .;
+	}
 #endif
 	.init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) {
 		INIT_RAM_FS
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index c1f1908..fb5d98c 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -67,6 +67,9 @@
 #include <asm/eeh.h>
 #include <asm/reg.h>
 #include <asm/plpar_wrappers.h>
+#include <asm/cacheflush.h>
+#include <asm/cputable.h>
+#include <asm/code-patching.h>
 
 #include "pseries.h"
 
@@ -455,6 +458,40 @@ long pseries_big_endian_exceptions(void)
 	}
 }
 
+static void swizzle_endian(u32 *start, u32 *end)
+{
+	for (; (long)start < (long)end; start++)
+		patch_instruction(start, swab32(*start));
+}
+
+static void fixup_missing_little_endian_exceptions(void)
+{
+	extern u32 *__start___fake_ile, *__stop___fake_ile;
+	extern u32 *__start___be_patch, *__stop___be_patch;
+	u32 **be_table = &__start___be_patch;
+	u32 **fake_table = &__start___fake_ile;
+
+	/* Make our big endian code look like big endian code */
+	for (; (long)be_table < (long)&__stop___be_patch; be_table += 2)
+		swizzle_endian(be_table[0], be_table[1]);
+
+	/* Now patch the interrupt handlers to branch to our BE code */
+	for (; (long)fake_table < (long)&__stop___fake_ile; fake_table += 3) {
+		u32 *le_handler = fake_table[0];
+		u32 *patched_insn = fake_table[1];
+		u32 *be_handler = fake_table[2];
+		u32 le_be_diff = (long)be_handler - (long)le_handler;
+		patch_instruction(patched_insn, *le_handler);
+		/* This patches the interrupt handler's first instruction into
+		   a branch that jumps to our BE handler that enables MSR_LE */
+		patch_instruction(le_handler, swab32(0x48000000 | le_be_diff));
+		/* Make sure that feature fixups use the new address for its
+		   code patching */
+		relocate_fixup_entry(&__start___ftr_fixup, &__stop___ftr_fixup,
+				     le_handler, patched_insn);
+	}
+}
+
 static long pseries_little_endian_exceptions(void)
 {
 	long rc;
@@ -737,6 +774,19 @@ static int __init pSeries_probe(void)
 			ppc_md.progress("H_SET_MODE LE exception fail", 0);
 			panic("Could not enable little endian exceptions");
 		}
+	} else {
+		/*
+		 * The hypervisor we're running on does not know how to
+		 * configure us to run interrupts in little endian mode,
+		 * so we have to cheat a bit.
+		 *
+		 * This call reprograms all interrupt handlers' first
+		 * instruction into a branch to a big endian fixup section
+		 * which only transitions us into little endian mode, then
+		 * returns back to the normal little endian interrupt
+		 * handler.
+		 */
+		fixup_missing_little_endian_exceptions();
 	}
 #endif
 
-- 
1.8.1.4

^ permalink raw reply related

* [PATCH] ibmveth: Fix more little endian issues
From: Alexander Graf @ 2013-12-23  1:29 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Santiago Leon, Dinar Valeev, Anton Blanchard, netdev

The ibmveth driver is memcpy()'ing the mac address between a variable
(register) and memory. This assumes a certain endianness of the
system, so let's make that implicit assumption work again.

This patch adds be64_to_cpu() calls to all places where the mac address
gets memcpy()'ed into a local variable.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 drivers/net/ethernet/ibm/ibmveth.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c
index 952d795..97f4ee96 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -581,7 +581,7 @@ static int ibmveth_open(struct net_device *netdev)
 	adapter->rx_queue.toggle = 1;
 
 	memcpy(&mac_address, netdev->dev_addr, netdev->addr_len);
-	mac_address = mac_address >> 16;
+	mac_address = be64_to_cpu(mac_address) >> 16;
 
 	rxq_desc.fields.flags_len = IBMVETH_BUF_VALID |
 					adapter->rx_queue.queue_len;
@@ -1186,6 +1186,7 @@ static void ibmveth_set_multicast_list(struct net_device *netdev)
 			/* add the multicast address to the filter table */
 			unsigned long mcast_addr = 0;
 			memcpy(((char *)&mcast_addr)+2, ha->addr, ETH_ALEN);
+			mcast_addr = cpu_to_be64(mcast_addr);
 			lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address,
 						   IbmVethMcastAddFilter,
 						   mcast_addr);
-- 
1.8.1.4

^ permalink raw reply related

* Re: [PATCH v2] powernv: eeh: add buffer for P7IOC hub error data
From: Gavin Shan @ 2013-12-23  1:33 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <20131220190601.GC5480@oc3347516403.ibm.com>

On Fri, Dec 20, 2013 at 01:06:01PM -0600, Brian W Hart wrote:
>V2: Replace driver-global 'hub_diag' with a per-PHB hub diag structure.
>
>Prevent ioda_eeh_hub_diag() from clobbering itself when called by supplying
>a per-PHB buffer for P7IOC hub diagnostic data.  Take care to inform OPAL of
>the correct size for the buffer.
>
>Signed-off-by: Brian W Hart <hartb@linux.vnet.ibm.com>

Acked-by: Gavin Shan <shangw@linux.vnet.ibm.com>

We also need backport it to stable kernel 3.11+

>---
> arch/powerpc/platforms/powernv/eeh-ioda.c | 15 ++-------------
> arch/powerpc/platforms/powernv/pci.h      |  4 +++-
> 2 files changed, 5 insertions(+), 14 deletions(-)
>
>diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c b/arch/powerpc/platforms/powernv/eeh-ioda.c
>index 8184ef5..4790275 100644
>--- a/arch/powerpc/platforms/powernv/eeh-ioda.c
>+++ b/arch/powerpc/platforms/powernv/eeh-ioda.c
>@@ -36,7 +36,6 @@
> #include "powernv.h"
> #include "pci.h"
>
>-static char *hub_diag = NULL;
> static int ioda_eeh_nb_init = 0;
>
> static int ioda_eeh_event(struct notifier_block *nb,
>@@ -140,15 +139,6 @@ static int ioda_eeh_post_init(struct pci_controller *hose)
> 		ioda_eeh_nb_init = 1;
> 	}
>
>-	/* We needn't HUB diag-data on PHB3 */
>-	if (phb->type == PNV_PHB_IODA1 && !hub_diag) {
>-		hub_diag = (char *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
>-		if (!hub_diag) {
>-			pr_err("%s: Out of memory !\n", __func__);
>-			return -ENOMEM;
>-		}
>-	}
>-
> #ifdef CONFIG_DEBUG_FS
> 	if (phb->dbgfs) {
> 		debugfs_create_file("err_injct_outbound", 0600,
>@@ -633,11 +623,10 @@ static void ioda_eeh_hub_diag_common(struct OpalIoP7IOCErrorData *data)
> static void ioda_eeh_hub_diag(struct pci_controller *hose)
> {
> 	struct pnv_phb *phb = hose->private_data;
>-	struct OpalIoP7IOCErrorData *data;
>+	struct OpalIoP7IOCErrorData *data = &phb->diag.hub_diag;
> 	long rc;
>
>-	data = (struct OpalIoP7IOCErrorData *)ioda_eeh_hub_diag;
>-	rc = opal_pci_get_hub_diag_data(phb->hub_id, data, PAGE_SIZE);
>+	rc = opal_pci_get_hub_diag_data(phb->hub_id, data, sizeof *data);
> 	if (rc != OPAL_SUCCESS) {
> 		pr_warning("%s: Failed to get HUB#%llx diag-data (%ld)\n",
> 			   __func__, phb->hub_id, rc);
>diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h
>index 911c24e..1ed8d5f 100644
>--- a/arch/powerpc/platforms/powernv/pci.h
>+++ b/arch/powerpc/platforms/powernv/pci.h
>@@ -172,11 +172,13 @@ struct pnv_phb {
> 		} ioda;
> 	};
>
>-	/* PHB status structure */
>+	/* PHB and hub status structure */
> 	union {
> 		unsigned char			blob[PNV_PCI_DIAG_BUF_SIZE];
> 		struct OpalIoP7IOCPhbErrorData	p7ioc;
>+		struct OpalIoP7IOCErrorData 	hub_diag;
> 	} diag;
>+
> };
>
> extern struct pci_ops pnv_pci_ops;

Thanks,
Gavin

^ permalink raw reply

* [PATCH] powerpc/mpic_timer: fix the time calculation is not accurate
From: Dongsheng Wang @ 2013-12-23  2:33 UTC (permalink / raw)
  To: scottwood, galak; +Cc: linuxppc-dev, Wang Dongsheng

From: Wang Dongsheng <dongsheng.wang@freescale.com>

When the timer GTCCR toggle bit is inverted, we calculated the rest
of the time is not accurate. So we need to ignore this bit.

Signed-off-by: Wang Dongsheng <dongsheng.wang@freescale.com>

diff --git a/arch/powerpc/sysdev/mpic_timer.c b/arch/powerpc/sysdev/mpic_timer.c
index 22d7d57..0fb70c9 100644
--- a/arch/powerpc/sysdev/mpic_timer.c
+++ b/arch/powerpc/sysdev/mpic_timer.c
@@ -41,6 +41,7 @@
 #define MPIC_TIMER_TCR_ROVR_OFFSET	24
 
 #define TIMER_STOP			0x80000000
+#define GTCCR_TOG			0x80000000
 #define TIMERS_PER_GROUP		4
 #define MAX_TICKS			(~0U >> 1)
 #define MAX_TICKS_CASCADE		(~0U)
@@ -96,8 +97,15 @@ static void convert_ticks_to_time(struct timer_group_priv *priv,
 	time->tv_sec = (__kernel_time_t)div_u64(ticks, priv->timerfreq);
 	tmp_sec = (u64)time->tv_sec * (u64)priv->timerfreq;
 
-	time->tv_usec = (__kernel_suseconds_t)
-		div_u64((ticks - tmp_sec) * 1000000, priv->timerfreq);
+	time->tv_usec = 0;
+
+	/*
+	 * In some cases tmp_sec may be greater than ticks, because in the
+	 * process of calculation ticks and tmp_sec will be rounded.
+	 */
+	if (tmp_sec <= ticks)
+		time->tv_usec = (__kernel_suseconds_t)
+			div_u64((ticks - tmp_sec) * 1000000, priv->timerfreq);
 
 	return;
 }
@@ -327,11 +335,13 @@ void mpic_get_remain_time(struct mpic_timer *handle, struct timeval *time)
 	casc_priv = priv->timer[handle->num].cascade_handle;
 	if (casc_priv) {
 		tmp_ticks = in_be32(&priv->regs[handle->num].gtccr);
+		tmp_ticks &= ~GTCCR_TOG;
 		ticks = ((u64)tmp_ticks & UINT_MAX) * (u64)MAX_TICKS_CASCADE;
 		tmp_ticks = in_be32(&priv->regs[handle->num - 1].gtccr);
 		ticks += tmp_ticks;
 	} else {
 		ticks = in_be32(&priv->regs[handle->num].gtccr);
+		ticks &= ~GTCCR_TOG;
 	}
 
 	convert_ticks_to_time(priv, ticks, time);
-- 
1.8.5

^ permalink raw reply related

* [PATCH 02/21] net: freescale: slight optimization of addr compare
From: Ding Tianhong @ 2013-12-23  5:09 UTC (permalink / raw)
  To: Li Yang, Netdev, linux-kernel@vger.kernel.org, linuxppc-dev

Use the recently added and possibly more efficient
ether_addr_equal_unaligned to instead of memcmp.

Cc: Li Yang <leoli@freescale.com>
Cc: netdev@vger.kernel.org
Cc: linuxppc-dev@lists.ozlabs.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Ding Tianhong <dingtianhong@huawei.com>
---
 drivers/net/ethernet/freescale/ucc_geth.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/ucc_geth.c b/drivers/net/ethernet/freescale/ucc_geth.c
index 5548b6d..88a1525 100644
--- a/drivers/net/ethernet/freescale/ucc_geth.c
+++ b/drivers/net/ethernet/freescale/ucc_geth.c
@@ -437,7 +437,7 @@ static void hw_add_addr_in_hash(struct ucc_geth_private *ugeth,
 
 static inline int compare_addr(u8 **addr1, u8 **addr2)
 {
-	return memcmp(addr1, addr2, ETH_ALEN);
+	return !ether_addr_equal_unaligned(addr1, addr2);
 }
 
 #ifdef DEBUG
-- 
1.8.0

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox