Skip to contentSkip to conversation

cell: cpufreq and pmi patches

PATCH In review Christian Krafft 2 participants 10 messages Jun 21, 2007 – Jun 25, 2007

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover cell: cpufreq and pmi patches

Hi,

The following patches contain fixes in the cbe_cpufreq driver and the pmi driver.
There are some minor bugfixes, but most of it is cleanup stuff.

Signature · 13 lines
Mit freundlichen Gruessen,
kind regards,

Christian Krafft
IBM Systems & Technology Group,
Linux Kernel Development
IT Specialist


Vorsitzender des Aufsichtsrats:	Martin Jetter
Geschaeftsfuehrung:		Herbert Kircher
Sitz der Gesellschaft:		Boeblingen
Registriergericht:		Amtsgericht Stuttgart, HRB 243294
#1 lore raw

PATCH 1/5 cell: pmi remove support for mutiple devices.

From: Christian Krafft <[email protected]>

The pmi driver got simplified by removing support for multiple devices. As there is no more than one pmi device per maschine, there is no need to specify the device for listening and sending messages.

This way the caller (cbe_cpufreq) doesn't need to scan the device tree. When registering the handler on a board without a pmi interface, pmi.c will just return -ENODEV.

arch/powerpc/platforms/cell/cbe_cpufreq.c +18 -21
Index: linux/arch/powerpc/platforms/cell/cbe_cpufreq.c
===================================================================
@@ -68,12 +68,14 @@ static u64 MIC_Slow_Next_Timer_table[] =
 };
 
 static unsigned int pmi_frequency_limit = 0;
+
 /*
  * hardware specific functions
  */
 
-static struct of_device *pmi_dev;
+static bool cbe_cpufreq_has_pmi;
 
+#ifdef CONFIG_PPC_PMI
 static int set_pmode_pmi(int cpu, unsigned int pmode)
 {
 	int ret;
@@ -90,7 +92,7 @@ static int set_pmode_pmi(int cpu, unsign
 	time = (u64) get_cycles();
 #endif
 
-	pmi_send_message(pmi_dev, pmi_msg);
+	pmi_send_message(pmi_msg);
 	ret = pmi_msg.data2;
 
 	pr_debug("PMI returned slow mode %d\n", ret);
@@ -102,7 +104,7 @@ static int set_pmode_pmi(int cpu, unsign
 #endif
 	return ret;
 }
-
+#endif
 
 static int get_pmode(int cpu)
 {
@@ -156,14 +158,16 @@ static int set_pmode_reg(int cpu, unsign
 	return 0;
 }
 
-static int set_pmode(int cpu, unsigned int slow_mode) {
-	if (pmi_dev)
+static int set_pmode(int cpu, unsigned int slow_mode)
+{
+#ifdef CONFIG_PPC_PMI
+	if (cbe_cpufreq_has_pmi)
 		return set_pmode_pmi(cpu, slow_mode);
-	else
-		return set_pmode_reg(cpu, slow_mode);
+#endif
+	return set_pmode_reg(cpu, slow_mode);
 }
 
-static void cbe_cpufreq_handle_pmi(struct of_device *dev, pmi_message_t pmi_msg)
+static void cbe_cpufreq_handle_pmi(pmi_message_t pmi_msg)
 {
 	u8 cpu;
 	u8 cbe_pmode_new;
@@ -250,7 +254,7 @@ static int cbe_cpufreq_cpu_init(struct c
 
 	cpufreq_frequency_table_get_attr(cbe_freqs, policy->cpu);
 
-	if (pmi_dev) {
+	if (cbe_cpufreq_has_pmi) {
 		/* frequency might get limited later, initialize limit with max_freq */
 		pmi_frequency_limit = max_freq;
 		cpufreq_register_notifier(&pmi_notifier_block, CPUFREQ_POLICY_NOTIFIER);
@@ -262,7 +266,7 @@ static int cbe_cpufreq_cpu_init(struct c
 
 static int cbe_cpufreq_cpu_exit(struct cpufreq_policy *policy)
 {
-	if (pmi_dev)
+	if (cbe_cpufreq_has_pmi)
 		cpufreq_unregister_notifier(&pmi_notifier_block, CPUFREQ_POLICY_NOTIFIER);
 
 	cpufreq_frequency_table_put_attr(policy->cpu);
@@ -323,27 +327,20 @@ static struct cpufreq_driver cbe_cpufreq
 
 static int __init cbe_cpufreq_init(void)
 {
-	struct device_node *np;
-
 	if (!machine_is(cell))
 		return -ENODEV;
 
-	np = of_find_node_by_type(NULL, "ibm,pmi");
-
-	pmi_dev = of_find_device_by_node(np);
-
-	if (pmi_dev)
-		pmi_register_handler(pmi_dev, &cbe_pmi_handler);
+	cbe_cpufreq_has_pmi = pmi_register_handler(&cbe_pmi_handler) == 0;
 
 	return cpufreq_register_driver(&cbe_cpufreq_driver);
 }
 
 static void __exit cbe_cpufreq_exit(void)
 {
-	if (pmi_dev)
-		pmi_unregister_handler(pmi_dev, &cbe_pmi_handler);
-
 	cpufreq_unregister_driver(&cbe_cpufreq_driver);
+
+	if (cbe_cpufreq_has_pmi)
+		pmi_unregister_handler(&cbe_pmi_handler);
 }
 
 module_init(cbe_cpufreq_init);
arch/powerpc/sysdev/pmi.c +20 -28

135 lines not on this page · raw message

include/asm-powerpc/pmi.h +4 -4
Index: linux/include/asm-powerpc/pmi.h
===================================================================
@@ -55,13 +55,13 @@ typedef struct {
 struct pmi_handler {
 	struct list_head node;
 	u8 type;
-	void (*handle_pmi_message) (struct of_device *, pmi_message_t);
+	void (*handle_pmi_message) (pmi_message_t);
 };
 
-void pmi_register_handler(struct of_device *, struct pmi_handler *);
-void pmi_unregister_handler(struct of_device *, struct pmi_handler *);
+int pmi_register_handler(struct pmi_handler *);
+void pmi_unregister_handler(struct pmi_handler *);
 
-void pmi_send_message(struct of_device *, pmi_message_t);
+int pmi_send_message(pmi_message_t);
 
 #endif /* __KERNEL__ */
 #endif /* _POWERPC_PMI_H */
Signature · 13 lines
Mit freundlichen Gruessen,
kind regards,

Christian Krafft
IBM Systems & Technology Group,
Linux Kernel Development
IT Specialist


Vorsitzender des Aufsichtsrats:	Martin Jetter
Geschaeftsfuehrung:		Herbert Kircher
Sitz der Gesellschaft:		Boeblingen
Registriergericht:		Amtsgericht Stuttgart, HRB 243294
#2 lore raw

Re: [Cbe-oss-dev] [patch 1/5] cell: pmi remove support for mutiple devices.

Quoted 10 lines

Index: linux/arch/powerpc/sysdev/pmi.c
===================================================================

arch/powerpc/sysdev/pmi.c +1 -0
@@ -48,15 +48,13 @@ struct pmi_data {
 	struct work_struct	work;
 };
 
+static struct pmi_data *data;
 

[...]

Quoted 46 lines
arch/powerpc/sysdev/pmi.c +7 -6
@@ -129,9 +124,14 @@ static int pmi_of_probe(struct of_device
 			const struct of_device_id *match)
 {
 	struct device_node *np = dev->node;
-	struct pmi_data *data;
 	int rc;
 
+	if (data) {
+		printk(KERN_ERR "pmi: driver has already been initialized.\n");
+		rc = -EBUSY;
+		goto out;
+	}
+
 	data = kzalloc(sizeof(struct pmi_data), GFP_KERNEL);
 	if (!data) {
 		printk(KERN_ERR "pmi: could not allocate memory.\n");
@@ -154,7 +154,6 @@ static int pmi_of_probe(struct of_device
 
 	INIT_WORK(&data->work, pmi_notify_handlers);
 
-	dev->dev.driver_data = data;
 	data->dev = dev;
 
 	data->irq = irq_of_parse_and_map(np, 0);
@@ -164,7 +163,7 @@ static int pmi_of_probe(struct of_device
 		goto error_cleanup_iomap;
 	}
 
-	rc = request_irq(data->irq, pmi_irq_handler, 0, "pmi", data);
+	rc = request_irq(data->irq, pmi_irq_handler, 0, "pmi", NULL);
 	if (rc) {
 		printk(KERN_ERR "pmi: can't request IRQ %d: returned %d\n",
 				data->irq, rc);
@@ -187,11 +186,8 @@ out:
 
 static int pmi_of_remove(struct of_device *dev)
 {
-	struct pmi_data *data;
 	struct pmi_handler *handler, *tmp;
 
-	data = dev->dev.driver_data;
-
 	free_irq(data->irq, data);
 	iounmap(data->pmi_reg);
 

arch/powerpc/sysdev/pmi.c static int pmi_of_remove(struct of_devic · line 201

Quoted 5 lines
arch/powerpc/sysdev/pmi.c +1 -1
@@ -202,7 +198,7 @@ static int pmi_of_remove(struct of_devic
 
 	spin_unlock(&data->handler_spinlock);
 
-	kfree(dev->dev.driver_data);
+	kfree(data);

Shouldn't it set data = NULL here?

I guess we will get "pmi: driver has already been initialized" message and -EBUSY on reloading pmi driver.

Quoted 3 lines
arch/powerpc/sysdev/pmi.c +0 -0
 	return 0;
 }
#3 lore raw

Re: [Cbe-oss-dev] [patch 1/5] cell: pmi remove support for mutiple devices.

Hi,

Quoted 12 lines · On Thu, 21 Jun 2007 23:07:31 +0900 Akinobu Mita <[email protected]> wrote:

arch/powerpc/sysdev/pmi.c static int pmi_of_remove(struct of_devic · line 201

Quoted 3 lines
arch/powerpc/sysdev/pmi.c +1 -1
-	kfree(dev->dev.driver_data);
+	kfree(data);

Shouldn't it set data = NULL here?

I guess we will get "pmi: driver has already been initialized" message and -EBUSY on reloading pmi driver.

Quoted 3 lines

return 0;
}

That problem did actually not occur.
Anyway, I added the line for completeness and consistency.

But while testing I found another bug that occurred when freeing the irq. The dev_id when requesting the irq was NULL, but not when freeing the irq. I'm resending the patch as a reply to the first version.

Signature · 13 lines
Mit freundlichen Gruessen,
kind regards,

Christian Krafft
IBM Systems & Technology Group,
Linux Kernel Development
IT Specialist


Vorsitzender des Aufsichtsrats:	Martin Jetter
Geschaeftsfuehrung:		Herbert Kircher
Sitz der Gesellschaft:		Boeblingen
Registriergericht:		Amtsgericht Stuttgart, HRB 243294
#4 lore raw

Re: [Cbe-oss-dev] [patch 1/5] cell: pmi remove support for mutiple devices.

Quoted 10 lines
Quoted 10 lines

arch/powerpc/sysdev/pmi.c static int pmi_of_remove(struct of_devic · line 201

Quoted 3 lines
arch/powerpc/sysdev/pmi.c +1 -1
-kfree(dev->dev.driver_data);
+kfree(data);

Shouldn't it set data = NULL here?

I guess we will get "pmi: driver has already been initialized" message and -EBUSY on reloading pmi driver.

Quoted 1 line
Quoted 5 lines
Quoted 2 lines
Quoted 2 lines

return 0;
}

That problem did actually not occur.
Anyway, I added the line for completeness and consistency.

The data is located in module data. So unloading module clean up the data, too. I missed it.

In order to test the problem I said, we need to re-probe pmi driver without unloading pmi driver. (http://lwn.net/Articles/143397/)

I hope your updated version of patch fixes the problem.

#5 lore raw

Resend: [patch 1/5] cell: pmi remove support for mutiple devices.

In reply to Christian Krafft

Subject: cell: pmi remove support for mutiple devices.

From: Christian Krafft <[email protected]>

The pmi driver got simplified by removing support for multiple devices. As there is no more than one pmi device per maschine, there is no need to specify the device for listening and sending messages.

This way the caller (cbe_cpufreq) doesn't need to scan the device tree. When registering the handler on a board without a pmi interface, pmi.c will just return -ENODEV.

arch/powerpc/platforms/cell/cbe_cpufreq.c +18 -21
Index: linux-2.6.22-rc5/arch/powerpc/platforms/cell/cbe_cpufreq.c
===================================================================
@@ -68,12 +68,14 @@ static u64 MIC_Slow_Next_Timer_table[] =
 };
 
 static unsigned int pmi_frequency_limit = 0;
+
 /*
  * hardware specific functions
  */
 
-static struct of_device *pmi_dev;
+static bool cbe_cpufreq_has_pmi;
 
+#ifdef CONFIG_PPC_PMI
 static int set_pmode_pmi(int cpu, unsigned int pmode)
 {
 	int ret;
@@ -90,7 +92,7 @@ static int set_pmode_pmi(int cpu, unsign
 	time = (u64) get_cycles();
 #endif
 
-	pmi_send_message(pmi_dev, pmi_msg);
+	pmi_send_message(pmi_msg);
 	ret = pmi_msg.data2;
 
 	pr_debug("PMI returned slow mode %d\n", ret);
@@ -102,7 +104,7 @@ static int set_pmode_pmi(int cpu, unsign
 #endif
 	return ret;
 }
-
+#endif
 
 static int get_pmode(int cpu)
 {
@@ -156,14 +158,16 @@ static int set_pmode_reg(int cpu, unsign
 	return 0;
 }
 
-static int set_pmode(int cpu, unsigned int slow_mode) {
-	if (pmi_dev)
+static int set_pmode(int cpu, unsigned int slow_mode)
+{
+#ifdef CONFIG_PPC_PMI
+	if (cbe_cpufreq_has_pmi)
 		return set_pmode_pmi(cpu, slow_mode);
-	else
-		return set_pmode_reg(cpu, slow_mode);
+#endif
+	return set_pmode_reg(cpu, slow_mode);
 }
 
-static void cbe_cpufreq_handle_pmi(struct of_device *dev, pmi_message_t pmi_msg)
+static void cbe_cpufreq_handle_pmi(pmi_message_t pmi_msg)
 {
 	u8 cpu;
 	u8 cbe_pmode_new;
@@ -250,7 +254,7 @@ static int cbe_cpufreq_cpu_init(struct c
 
 	cpufreq_frequency_table_get_attr(cbe_freqs, policy->cpu);
 
-	if (pmi_dev) {
+	if (cbe_cpufreq_has_pmi) {
 		/* frequency might get limited later, initialize limit with max_freq */
 		pmi_frequency_limit = max_freq;
 		cpufreq_register_notifier(&pmi_notifier_block, CPUFREQ_POLICY_NOTIFIER);
@@ -262,7 +266,7 @@ static int cbe_cpufreq_cpu_init(struct c
 
 static int cbe_cpufreq_cpu_exit(struct cpufreq_policy *policy)
 {
-	if (pmi_dev)
+	if (cbe_cpufreq_has_pmi)
 		cpufreq_unregister_notifier(&pmi_notifier_block, CPUFREQ_POLICY_NOTIFIER);
 
 	cpufreq_frequency_table_put_attr(policy->cpu);
@@ -323,27 +327,20 @@ static struct cpufreq_driver cbe_cpufreq
 
 static int __init cbe_cpufreq_init(void)
 {
-	struct device_node *np;
-
 	if (!machine_is(cell))
 		return -ENODEV;
 
-	np = of_find_node_by_type(NULL, "ibm,pmi");
-
-	pmi_dev = of_find_device_by_node(np);
-
-	if (pmi_dev)
-		pmi_register_handler(pmi_dev, &cbe_pmi_handler);
+	cbe_cpufreq_has_pmi = pmi_register_handler(&cbe_pmi_handler) == 0;
 
 	return cpufreq_register_driver(&cbe_cpufreq_driver);
 }
 
 static void __exit cbe_cpufreq_exit(void)
 {
-	if (pmi_dev)
-		pmi_unregister_handler(pmi_dev, &cbe_pmi_handler);
-
 	cpufreq_unregister_driver(&cbe_cpufreq_driver);
+
+	if (cbe_cpufreq_has_pmi)
+		pmi_unregister_handler(&cbe_pmi_handler);
 }
 
 module_init(cbe_cpufreq_init);
arch/powerpc/sysdev/pmi.c +22 -29

138 lines not on this page · raw message

include/asm-powerpc/pmi.h +4 -4
Index: linux-2.6.22-rc5/include/asm-powerpc/pmi.h
===================================================================
@@ -55,13 +55,13 @@ typedef struct {
 struct pmi_handler {
 	struct list_head node;
 	u8 type;
-	void (*handle_pmi_message) (struct of_device *, pmi_message_t);
+	void (*handle_pmi_message) (pmi_message_t);
 };
 
-void pmi_register_handler(struct of_device *, struct pmi_handler *);
-void pmi_unregister_handler(struct of_device *, struct pmi_handler *);
+int pmi_register_handler(struct pmi_handler *);
+void pmi_unregister_handler(struct pmi_handler *);
 
-void pmi_send_message(struct of_device *, pmi_message_t);
+int pmi_send_message(pmi_message_t);
 
 #endif /* __KERNEL__ */
 #endif /* _POWERPC_PMI_H */
Signature · 13 lines
Mit freundlichen Gruessen,
kind regards,

Christian Krafft
IBM Systems & Technology Group,
Linux Kernel Development
IT Specialist


Vorsitzender des Aufsichtsrats:	Martin Jetter
Geschaeftsfuehrung:		Herbert Kircher
Sitz der Gesellschaft:		Boeblingen
Registriergericht:		Amtsgericht Stuttgart, HRB 243294
#6 lore raw

PATCH 2/5 cell: cbe_cpufreq fix latency measurement

In reply to Christian Krafft

From: Christian Krafft <[email protected]>

This patch fixes the debug code that calculates the transition time when changing the slow modes on a Cell BE cpu.

arch/powerpc/platforms/cell/cbe_cpufreq.c +17 -8
Index: linux/arch/powerpc/platforms/cell/cbe_cpufreq.c
===================================================================
@@ -81,7 +81,7 @@ static int set_pmode_pmi(int cpu, unsign
 	int ret;
 	pmi_message_t pmi_msg;
 #ifdef DEBUG
-	u64 time;
+	long time;
 #endif
 
 	pmi_msg.type = PMI_TYPE_FREQ_CHANGE;
@@ -89,7 +89,7 @@ static int set_pmode_pmi(int cpu, unsign
 	pmi_msg.data2 = pmode;
 
 #ifdef DEBUG
-	time = (u64) get_cycles();
+	time = jiffies;
 #endif
 
 	pmi_send_message(pmi_msg);
@@ -98,9 +98,9 @@ static int set_pmode_pmi(int cpu, unsign
 	pr_debug("PMI returned slow mode %d\n", ret);
 
 #ifdef DEBUG
-	time = (u64) get_cycles() - time; /* actual cycles (not cpu cycles!) */
-	time = 1000000000 * time / CLOCK_TICK_RATE; /* time in ns (10^-9) */
-	pr_debug("had to wait %lu ns for a transition\n", time);
+	time = jiffies - time; /* actual cycles (not cpu cycles!) */
+	time = jiffies_to_msecs(time);
+	pr_debug("had to wait %lu ms for a transition using PMI.\n", time);
 #endif
 	return ret;
 }
@@ -123,15 +123,18 @@ static int set_pmode_reg(int cpu, unsign
 	struct cbe_mic_tm_regs __iomem *mic_tm_regs;
 	u64 flags;
 	u64 value;
+#ifdef DEBUG
+	long time;
+#endif
 
 	local_irq_save(flags);
 
 	mic_tm_regs = cbe_get_cpu_mic_tm_regs(cpu);
 	pmd_regs = cbe_get_cpu_pmd_regs(cpu);
 
-	pr_debug("pm register is mapped at %p\n", &pmd_regs->pmcr);
-	pr_debug("mic register is mapped at %p\n", &mic_tm_regs->slow_fast_timer_0);
-
+#ifdef DEBUG
+	time = jiffies;
+#endif
 	out_be64(&mic_tm_regs->slow_fast_timer_0, MIC_Slow_Fast_Timer_table[pmode]);
 	out_be64(&mic_tm_regs->slow_fast_timer_1, MIC_Slow_Fast_Timer_table[pmode]);
 
@@ -146,6 +149,7 @@ static int set_pmode_reg(int cpu, unsign
 
 	out_be64(&pmd_regs->pmcr, value);
 
+#ifdef DEBUG
 	/* wait until new pmode appears in status register */
 	value = in_be64(&pmd_regs->pmsr) & 0x07;
 	while(value != pmode) {
@@ -153,6 +157,11 @@ static int set_pmode_reg(int cpu, unsign
 		value = in_be64(&pmd_regs->pmsr) & 0x07;
 	}
 
+	time = jiffies - time;
+	time = jiffies_to_msecs(time);
+	pr_debug("had to wait %lu ms for a transition using " \
+		 "the pervasive unit.\n", time);
+#endif
 	local_irq_restore(flags);
 
 	return 0;
Signature · 13 lines
Mit freundlichen Gruessen,
kind regards,

Christian Krafft
IBM Systems & Technology Group,
Linux Kernel Development
IT Specialist


Vorsitzender des Aufsichtsrats:	Martin Jetter
Geschaeftsfuehrung:		Herbert Kircher
Sitz der Gesellschaft:		Boeblingen
Registriergericht:		Amtsgericht Stuttgart, HRB 243294

Subject: cell: cbe_cpufreq fix latency measurement

From: Christian Krafft <[email protected]>

This patch fixes the debug code that calculates the transition time when changing the slow modes on a Cell BE cpu.

arch/powerpc/platforms/cell/cbe_cpufreq.c +17 -8
Index: linux/arch/powerpc/platforms/cell/cbe_cpufreq.c
===================================================================
@@ -81,7 +81,7 @@ static int set_pmode_pmi(int cpu, unsign
 	int ret;
 	pmi_message_t pmi_msg;
 #ifdef DEBUG
-	u64 time;
+	long time;
 #endif
 
 	pmi_msg.type = PMI_TYPE_FREQ_CHANGE;
@@ -89,7 +89,7 @@ static int set_pmode_pmi(int cpu, unsign
 	pmi_msg.data2 = pmode;
 
 #ifdef DEBUG
-	time = (u64) get_cycles();
+	time = jiffies;
 #endif
 
 	pmi_send_message(pmi_msg);
@@ -98,9 +98,9 @@ static int set_pmode_pmi(int cpu, unsign
 	pr_debug("PMI returned slow mode %d\n", ret);
 
 #ifdef DEBUG
-	time = (u64) get_cycles() - time; /* actual cycles (not cpu cycles!) */
-	time = 1000000000 * time / CLOCK_TICK_RATE; /* time in ns (10^-9) */
-	pr_debug("had to wait %lu ns for a transition\n", time);
+	time = jiffies - time; /* actual cycles (not cpu cycles!) */
+	time = jiffies_to_msecs(time);
+	pr_debug("had to wait %lu ms for a transition using PMI.\n", time);
 #endif
 	return ret;
 }
@@ -123,15 +123,18 @@ static int set_pmode_reg(int cpu, unsign
 	struct cbe_mic_tm_regs __iomem *mic_tm_regs;
 	u64 flags;
 	u64 value;
+#ifdef DEBUG
+	long time;
+#endif
 
 	local_irq_save(flags);
 
 	mic_tm_regs = cbe_get_cpu_mic_tm_regs(cpu);
 	pmd_regs = cbe_get_cpu_pmd_regs(cpu);
 
-	pr_debug("pm register is mapped at %p\n", &pmd_regs->pmcr);
-	pr_debug("mic register is mapped at %p\n", &mic_tm_regs->slow_fast_timer_0);
-
+#ifdef DEBUG
+	time = jiffies;
+#endif
 	out_be64(&mic_tm_regs->slow_fast_timer_0, MIC_Slow_Fast_Timer_table[pmode]);
 	out_be64(&mic_tm_regs->slow_fast_timer_1, MIC_Slow_Fast_Timer_table[pmode]);
 
@@ -146,6 +149,7 @@ static int set_pmode_reg(int cpu, unsign
 
 	out_be64(&pmd_regs->pmcr, value);
 
+#ifdef DEBUG
 	/* wait until new pmode appears in status register */
 	value = in_be64(&pmd_regs->pmsr) & 0x07;
 	while(value != pmode) {
@@ -153,6 +157,11 @@ static int set_pmode_reg(int cpu, unsign
 		value = in_be64(&pmd_regs->pmsr) & 0x07;
 	}
 
+	time = jiffies - time;
+	time = jiffies_to_msecs(time);
+	pr_debug("had to wait %lu ms for a transition using " \
+		 "the pervasive unit.\n", time);
+#endif
 	local_irq_restore(flags);
 
 	return 0;
#7 lore raw

PATCH 3/5 cell: cbe_cpufreq: fix initialization

In reply to Christian Krafft

From: Christian Krafft <[email protected]>

This patch fixes the initialization of the cbe_cpufreq driver. The code that initializes the PMI related functions was called per cpu:
* registering cpufreq notifier block
* registering a pmi handler

This ends in a bug that the notifier block gets called in an endless loop. The initialization code is being put to the
module init code path by this patch. This way it only gets called once.

arch/powerpc/platforms/cell/cbe_cpufreq.c +8 -12
Index: linux/arch/powerpc/platforms/cell/cbe_cpufreq.c
===================================================================
@@ -196,10 +196,9 @@ static int pmi_notifier(struct notifier_
 {
 	struct cpufreq_policy *policy = data;
 
-	if (event != CPUFREQ_INCOMPATIBLE)
-		return 0;
+	if (pmi_frequency_limit)
+		cpufreq_verify_within_limits(policy, 0, pmi_frequency_limit);
 
-	cpufreq_verify_within_limits(policy, 0, pmi_frequency_limit);
 	return 0;
 }
 
@@ -263,11 +262,6 @@ static int cbe_cpufreq_cpu_init(struct c
 
 	cpufreq_frequency_table_get_attr(cbe_freqs, policy->cpu);
 
-	if (cbe_cpufreq_has_pmi) {
-		/* frequency might get limited later, initialize limit with max_freq */
-		pmi_frequency_limit = max_freq;
-		cpufreq_register_notifier(&pmi_notifier_block, CPUFREQ_POLICY_NOTIFIER);
-	}
 
 	/* this ensures that policy->cpuinfo_min and policy->cpuinfo_max are set correctly */
 	return cpufreq_frequency_table_cpuinfo(policy, cbe_freqs);
@@ -275,9 +269,6 @@ static int cbe_cpufreq_cpu_init(struct c
 
 static int cbe_cpufreq_cpu_exit(struct cpufreq_policy *policy)
 {
-	if (cbe_cpufreq_has_pmi)
-		cpufreq_unregister_notifier(&pmi_notifier_block, CPUFREQ_POLICY_NOTIFIER);
-
 	cpufreq_frequency_table_put_attr(policy->cpu);
 	return 0;
 }
@@ -341,6 +332,9 @@ static int __init cbe_cpufreq_init(void)
 
 	cbe_cpufreq_has_pmi = pmi_register_handler(&cbe_pmi_handler) == 0;
 
+	if (cbe_cpufreq_has_pmi)
+		cpufreq_register_notifier(&pmi_notifier_block, CPUFREQ_POLICY_NOTIFIER);
+
 	return cpufreq_register_driver(&cbe_cpufreq_driver);
 }
 
@@ -348,8 +342,10 @@ static void __exit cbe_cpufreq_exit(void
 {
 	cpufreq_unregister_driver(&cbe_cpufreq_driver);
 
-	if (cbe_cpufreq_has_pmi)
+	if (cbe_cpufreq_has_pmi) {
+		cpufreq_unregister_notifier(&pmi_notifier_block, CPUFREQ_POLICY_NOTIFIER);
 		pmi_unregister_handler(&cbe_pmi_handler);
+	}
 }
 
 module_init(cbe_cpufreq_init);
Signature · 13 lines
Mit freundlichen Gruessen,
kind regards,

Christian Krafft
IBM Systems & Technology Group,
Linux Kernel Development
IT Specialist


Vorsitzender des Aufsichtsrats:	Martin Jetter
Geschaeftsfuehrung:		Herbert Kircher
Sitz der Gesellschaft:		Boeblingen
Registriergericht:		Amtsgericht Stuttgart, HRB 243294
#8 lore raw

PATCH 4/5 cell: cpufreq and pmi patches

In reply to Christian Krafft

Subject: cbe_cpufreq: fix minor issues

From: Christian Krafft <[email protected]>

Minor issues have been fixed:
* added a missing call to of_node_put()
* signedness of a function parameter
* added some line breaks
* changed global pmi_frequency_limit to a
per node pmi_slow_mode_limit array

arch/powerpc/platforms/cell/cbe_cpufreq.c +40 -18
Index: linux-2.6.22-rc5/arch/powerpc/platforms/cell/cbe_cpufreq.c
===================================================================
@@ -67,7 +67,7 @@ static u64 MIC_Slow_Next_Timer_table[] =
 	0x00003FC000000000ull,
 };
 
-static unsigned int pmi_frequency_limit = 0;
+static u8 pmi_slow_mode_limit[MAX_BE];
 
 /*
  * hardware specific functions
@@ -169,35 +169,50 @@ static int set_pmode_reg(int cpu, unsign
 
 static int set_pmode(int cpu, unsigned int slow_mode)
 {
+	int rc;
 #ifdef CONFIG_PPC_PMI
 	if (cbe_cpufreq_has_pmi)
-		return set_pmode_pmi(cpu, slow_mode);
+		rc = set_pmode_pmi(cpu, slow_mode);
+	else
 #endif
-	return set_pmode_reg(cpu, slow_mode);
+		rc = set_pmode_reg(cpu, slow_mode);
+
+	pr_debug("register contains slow mode %d\n", get_pmode(cpu));
+
+	return rc;
 }
 
 static void cbe_cpufreq_handle_pmi(pmi_message_t pmi_msg)
 {
-	u8 cpu;
-	u8 cbe_pmode_new;
+	u8 node; slow_mode;
 
 	BUG_ON(pmi_msg.type != PMI_TYPE_FREQ_CHANGE);
 
-	cpu = cbe_node_to_cpu(pmi_msg.data1);
-	cbe_pmode_new = pmi_msg.data2;
+	node = pmi_msg.data1;
+	slow_mode = pmi_msg.data2;
 
-	pmi_frequency_limit = cbe_freqs[cbe_pmode_new].frequency;
+	pmi_slow_mode_limit[node] = slow_mode;
 
-	pr_debug("cbe_handle_pmi: max freq=%d\n", pmi_frequency_limit);
+	pr_debug("cbe_handle_pmi: node: %d, max slow_mode=%d\n", slow_mode);
 }
 
 static int pmi_notifier(struct notifier_block *nb,
 				       unsigned long event, void *data)
 {
 	struct cpufreq_policy *policy = data;
+	u8 node;
+
+	node = cbe_cpu_to_node(policy->cpu);
+
+	pr_debug("got notified, event=%lu, node=%u\n", event, node);
 
-	if (pmi_frequency_limit)
-		cpufreq_verify_within_limits(policy, 0, pmi_frequency_limit);
+	if (pmi_slow_mode_limit[node] != 0) {
+		pr_debug("limiting node %d to slow mode %d\n",
+			 node, pmi_slow_mode_limit[node]);
+
+		cpufreq_verify_within_limits(policy, 0,
+			 cbe_freqs[pmi_slow_mode_limit[node]].frequency);
+	}
 
 	return 0;
 }
@@ -232,6 +247,8 @@ static int cbe_cpufreq_cpu_init(struct c
 
 	max_freqp = of_get_property(cpu, "clock-frequency", NULL);
 
+	of_node_put(cpu);
+
 	if (!max_freqp)
 		return -EINVAL;
 
@@ -248,7 +265,9 @@ static int cbe_cpufreq_cpu_init(struct c
 	}
 
 	policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
-	/* if DEBUG is enabled set_pmode() measures the correct latency of a transition */
+
+	/* if DEBUG is enabled set_pmode() measures the latency
+	 * of a transition */
 	policy->cpuinfo.transition_latency = 25000;
 
 	cur_pmode = get_pmode(policy->cpu);
@@ -262,8 +281,8 @@ static int cbe_cpufreq_cpu_init(struct c
 
 	cpufreq_frequency_table_get_attr(cbe_freqs, policy->cpu);
 
-
-	/* this ensures that policy->cpuinfo_min and policy->cpuinfo_max are set correctly */
+	/* this ensures that policy->cpuinfo_min
+	 * and policy->cpuinfo_max are set correctly */
 	return cpufreq_frequency_table_cpuinfo(policy, cbe_freqs);
 }
 
@@ -279,12 +298,13 @@ static int cbe_cpufreq_verify(struct cpu
 }
 
 
-static int cbe_cpufreq_target(struct cpufreq_policy *policy, unsigned int target_freq,
-			    unsigned int relation)
+static int cbe_cpufreq_target(struct cpufreq_policy *policy,
+			      unsigned int target_freq,
+			      unsigned int relation)
 {
 	int rc;
 	struct cpufreq_freqs freqs;
-	int cbe_pmode_new;
+	unsigned int cbe_pmode_new;
 
 	cpufreq_frequency_table_target(policy,
 				       cbe_freqs,
@@ -299,12 +319,14 @@ static int cbe_cpufreq_target(struct cpu
 	mutex_lock(&cbe_switch_mutex);
 	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 
-	pr_debug("setting frequency for cpu %d to %d kHz, 1/%d of max frequency\n",
+	pr_debug("setting frequency for cpu %d to %d kHz, " \
+		 "1/%d of max frequency\n",
 		 policy->cpu,
 		 cbe_freqs[cbe_pmode_new].frequency,
 		 cbe_freqs[cbe_pmode_new].index);
 
 	rc = set_pmode(policy->cpu, cbe_pmode_new);
+
 	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 	mutex_unlock(&cbe_switch_mutex);
 
Signature · 13 lines
Mit freundlichen Gruessen,
kind regards,

Christian Krafft
IBM Systems & Technology Group,
Linux Kernel Development
IT Specialist


Vorsitzender des Aufsichtsrats:	Martin Jetter
Geschaeftsfuehrung:		Herbert Kircher
Sitz der Gesellschaft:		Boeblingen
Registriergericht:		Amtsgericht Stuttgart, HRB 243294
#9 lore raw

PATCH 5/5 cell: cbe_cpufreq: reorganize code

In reply to Christian Krafft

Subject: cbe_cpufreq: reorganize code and fix some bugs

From: Christian Krafft <[email protected]>

This patch reorganizes the code of the driver into three files. Two cbe_cpufreq_pmi.c and cbe_cpufreq_pervasive.c care about hardware. cbe_cpufreq.c contains the logic.
There is no changed behaviour, except that the PMI related function is now located in a seperate module cbe_cpufreq_pmi. This module will be required by cbe_cpufreq, if CONFIG_CBE_CPUFREQ_PMI has been set.

arch/powerpc/platforms/cell/Kconfig +10 -0
Index: linux-2.6.22-rc5/arch/powerpc/platforms/cell/Kconfig
===================================================================
@@ -73,4 +73,14 @@ config CBE_CPUFREQ
 	  For details, take a look at <file:Documentation/cpu-freq/>.
 	  If you don't have such processor, say N
 
+config CBE_CPUFREQ_PMI
+	tristate "CBE frequency scaling using PMI interface"
+	depends on CBE_CPUFREQ && PPC_PMI && EXPERIMENTAL
+	default n
+	help
+	  Select this, if you want to use the PMI interface
+	  to switch frequencies. Using PMI, the
+	  processor will not only be able to run at lower speed,
+	  but also at lower core voltage.
+
 endmenu
arch/powerpc/platforms/cell/Makefile +3 -1
Index: linux-2.6.22-rc5/arch/powerpc/platforms/cell/Makefile
===================================================================
@@ -4,7 +4,9 @@ obj-$(CONFIG_PPC_CELL_NATIVE)		+= interr
 obj-$(CONFIG_CBE_RAS)			+= ras.o
 
 obj-$(CONFIG_CBE_THERM)			+= cbe_thermal.o
-obj-$(CONFIG_CBE_CPUFREQ)		+= cbe_cpufreq.o
+obj-$(CONFIG_CBE_CPUFREQ_PMI)		+= cbe_cpufreq_pmi.o
+obj-$(CONFIG_CBE_CPUFREQ)		+= cbe-cpufreq.o
+cbe-cpufreq-y				+= cbe_cpufreq_pervasive.o cbe_cpufreq.o
 
 ifeq ($(CONFIG_SMP),y)
 obj-$(CONFIG_PPC_CELL_NATIVE)		+= smp.o
arch/powerpc/platforms/cell/cbe_cpufreq.c +9 -187

253 lines not on this page · raw message

arch/powerpc/platforms/cell/cbe_cpufreq.h new file +24 -0
Index: linux-2.6.22-rc5/arch/powerpc/platforms/cell/cbe_cpufreq.h
===================================================================
@@ -0,0 +1,24 @@
+/*
+ * cbe_cpufreq.h
+ *
+ * This file contains the definitions used by the cbe_cpufreq driver.
+ *
+ * (C) Copyright IBM Deutschland Entwicklung GmbH 2005-2007
+ *
+ * Author: Christian Krafft <[email protected]>
+ *
+ */
+
+#include <linux/cpufreq.h>
+#include <linux/types.h>
+
+int cbe_cpufreq_set_pmode(int cpu, unsigned int pmode);
+int cbe_cpufreq_get_pmode(int cpu);
+
+int cbe_cpufreq_set_pmode_pmi(int cpu, unsigned int pmode);
+
+#if defined(CONFIG_CBE_CPUFREQ_PMI) || defined(CONFIG_CBE_CPUFREQ_PMI_MODULE)
+extern bool cbe_cpufreq_has_pmi;
+#else
+#define cbe_cpufreq_has_pmi (0)
+#endif
arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c new file +118 -0

118 lines not on this page · raw message

arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c new file +148 -0

148 lines not on this page · raw message

Signature · 13 lines
Mit freundlichen Gruessen,
kind regards,

Christian Krafft
IBM Systems & Technology Group,
Linux Kernel Development
IT Specialist


Vorsitzender des Aufsichtsrats:	Martin Jetter
Geschaeftsfuehrung:		Herbert Kircher
Sitz der Gesellschaft:		Boeblingen
Registriergericht:		Amtsgericht Stuttgart, HRB 243294