LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH] powerpc: Xserve G5 thermal control fixes
From: Benjamin Herrenschmidt @ 2006-07-06  9:09 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: linuxppc-dev list, Paul Mackerras, Linux Kernel list
In-Reply-To: <CCA3F98E-8F8F-4003-87BA-8091F8AB668F@kernel.crashing.org>

On Thu, 2006-07-06 at 07:37 +0200, Segher Boessenkool wrote:
> > This patch also changes the fixed value of the slots fan for
> > desktop G5s to 40% instead of 50%. It seems to still have a pretty  
> > good
> > airflow that way and is much less noisy.
> 
> Is this save when people have one of the ridiculously expensive
> (and hot) video cards installed?  And perhaps even a few other
> cards, too?

Those cards are nvidia and they only get hot if you use the 3d which you
can't do in linux/ppc (beside they have their own fan on the card
anyway).

Ben.

^ permalink raw reply

* Re: [PATCH] powerpc: Xserve G5 thermal control fixes (#2)
From: Benjamin Herrenschmidt @ 2006-07-06  8:03 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev list, Linux Kernel list
In-Reply-To: <1152162394.24632.58.camel@localhost.localdomain>

The thermal control for the Xserve G5s had a few issues. For one, the
way to program the RPM fans speeds into the FCU is different between it
and the desktop models, which I didn't figure out until recently, and it
was missing a control loop for the slots fan, running it too fast. Both
of those problems were causing the machine to be much more noisy than
necessary. This patch also changes the fixed value of the slots fan for
desktop G5s to 40% instead of 50%. It seems to still have a pretty good
airflow that way and is much less noisy.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
----

This version adds code to tickle the FCU regulary so it doesn't timeout
if we decide not to change the fan speed for a while.

Index: linux-irq-work/drivers/macintosh/therm_pm72.c
===================================================================
--- linux-irq-work.orig/drivers/macintosh/therm_pm72.c	2006-07-06 16:43:34.000000000 +1000
+++ linux-irq-work/drivers/macintosh/therm_pm72.c	2006-07-06 16:52:43.000000000 +1000
@@ -95,6 +95,17 @@
  *	- Use min/max macros here or there
  *	- Latest darwin updated U3H min fan speed to 20% PWM
  *
+ *  July. 06, 2006 : 1.3
+ *	- Fix setting of RPM fans on Xserve G5 (they were going too fast)
+ *      - Add missing slots fan control loop for Xserve G5
+ *	- Lower fixed slots fan speed from 50% to 40% on desktop G5s. We
+ *        still can't properly implement the control loop for these, so let's
+ *        reduce the noise a little bit, it appears that 40% still gives us
+ *        a pretty good air flow
+ *	- Add code to "tickle" the FCU regulary so it doesn't think that
+ *        we are gone while in fact, the machine just didn't need any fan
+ *        speed change lately
+ *
  */
 
 #include <linux/types.h>
@@ -121,7 +132,7 @@
 
 #include "therm_pm72.h"
 
-#define VERSION "1.2b2"
+#define VERSION "1.3"
 
 #undef DEBUG
 
@@ -146,6 +157,7 @@
 static struct backside_pid_state	backside_state;
 static struct drives_pid_state		drives_state;
 static struct dimm_pid_state		dimms_state;
+static struct slots_pid_state		slots_state;
 static int				state;
 static int				cpu_count;
 static int				cpu_pid_type;
@@ -154,7 +166,8 @@
 static int				critical_state;
 static int				rackmac;
 static s32				dimm_output_clamp;
-
+static int 				fcu_rpm_shift;
+static int				fcu_tickle_ticks;
 static DECLARE_MUTEX(driver_lock);
 
 /*
@@ -495,13 +508,20 @@
 	rc = fan_write_reg(0x2e, &buf, 1);
 	if (rc < 0)
 		return -EIO;
+	rc = fan_read_reg(0, &buf, 1);
+	if (rc < 0)
+		return -EIO;
+	fcu_rpm_shift = (buf == 1) ? 2 : 3;
+	printk(KERN_DEBUG "FCU Initialized, RPM fan shift is %d\n",
+	       fcu_rpm_shift);
+
 	return 0;
 }
 
 static int set_rpm_fan(int fan_index, int rpm)
 {
 	unsigned char buf[2];
-	int rc, id;
+	int rc, id, min, max;
 
 	if (fcu_fans[fan_index].type != FCU_FAN_RPM)
 		return -EINVAL;
@@ -509,12 +529,15 @@
 	if (id == FCU_FAN_ABSENT_ID)
 		return -EINVAL;
 
-	if (rpm < 300)
-		rpm = 300;
-	else if (rpm > 8191)
-		rpm = 8191;
-	buf[0] = rpm >> 5;
-	buf[1] = rpm << 3;
+	min = 2400 >> fcu_rpm_shift;
+	max = 56000 >> fcu_rpm_shift;
+
+	if (rpm < min)
+		rpm = min;
+	else if (rpm > max)
+		rpm = max;
+	buf[0] = rpm >> (8 - fcu_rpm_shift);
+	buf[1] = rpm << fcu_rpm_shift;
 	rc = fan_write_reg(0x10 + (id * 2), buf, 2);
 	if (rc < 0)
 		return -EIO;
@@ -551,7 +574,7 @@
 	if (rc != 2)
 		return -EIO;
 
-	return (buf[0] << 5) | buf[1] >> 3;
+	return (buf[0] << (8 - fcu_rpm_shift)) | buf[1] >> fcu_rpm_shift;
 }
 
 static int set_pwm_fan(int fan_index, int pwm)
@@ -609,6 +632,26 @@
 	return (buf[0] * 1000) / 2559;
 }
 
+static void tickle_fcu(void)
+{
+	int pwm;
+
+	pwm = get_pwm_fan(SLOTS_FAN_PWM_INDEX);
+
+	DBG("FCU Tickle, slots fan is: %d\n", pwm);
+	if (pwm < 0)
+		pwm = 100;
+
+	if (!rackmac) {
+		pwm = SLOTS_FAN_DEFAULT_PWM;
+	} else if (pwm < SLOTS_PID_OUTPUT_MIN)
+		pwm = SLOTS_PID_OUTPUT_MIN;
+
+	/* That is hopefully enough to make the FCU happy */
+	set_pwm_fan(SLOTS_FAN_PWM_INDEX, pwm);
+}
+
+
 /*
  * Utility routine to read the CPU calibration EEPROM data
  * from the device-tree
@@ -715,6 +758,9 @@
 BUILD_SHOW_FUNC_FIX(drives_temperature, drives_state.last_temp)
 BUILD_SHOW_FUNC_INT(drives_fan_rpm, drives_state.rpm)
 
+BUILD_SHOW_FUNC_FIX(slots_temperature, slots_state.last_temp)
+BUILD_SHOW_FUNC_INT(slots_fan_pwm, slots_state.pwm)
+
 BUILD_SHOW_FUNC_FIX(dimms_temperature, dimms_state.last_temp)
 
 static DEVICE_ATTR(cpu0_temperature,S_IRUGO,show_cpu0_temperature,NULL);
@@ -735,6 +781,9 @@
 static DEVICE_ATTR(drives_temperature,S_IRUGO,show_drives_temperature,NULL);
 static DEVICE_ATTR(drives_fan_rpm,S_IRUGO,show_drives_fan_rpm,NULL);
 
+static DEVICE_ATTR(slots_temperature,S_IRUGO,show_slots_temperature,NULL);
+static DEVICE_ATTR(slots_fan_pwm,S_IRUGO,show_slots_fan_pwm,NULL);
+
 static DEVICE_ATTR(dimms_temperature,S_IRUGO,show_dimms_temperature,NULL);
 
 /*
@@ -1076,6 +1125,9 @@
 	fan_min = dimm_output_clamp;
 	fan_min = max(fan_min, (int)state->mpu.rminn_intake_fan);
 
+	DBG(" CPU min mpu = %d, min dimm = %d\n",
+	    state->mpu.rminn_intake_fan, dimm_output_clamp);
+
 	state->rpm = max(state->rpm, (int)fan_min);
 	state->rpm = min(state->rpm, (int)state->mpu.rmaxn_intake_fan);
 	state->intake_rpm = state->rpm;
@@ -1374,7 +1426,8 @@
 	DBG("  current rpm: %d\n", state->rpm);
 
 	/* Get some sensor readings */
-	temp = le16_to_cpu(i2c_smbus_read_word_data(state->monitor, DS1775_TEMP)) << 8;
+	temp = le16_to_cpu(i2c_smbus_read_word_data(state->monitor,
+						    DS1775_TEMP)) << 8;
 	state->last_temp = temp;
 	DBG("  temp: %d.%03d, target: %d.%03d\n", FIX32TOPRINT(temp),
 	    FIX32TOPRINT(DRIVES_PID_INPUT_TARGET));
@@ -1575,7 +1628,7 @@
 }
 
 /*
- * Dispose of the state data for the drives control loop
+ * Dispose of the state data for the DIMM control loop
  */
 static void dispose_dimms_state(struct dimm_pid_state *state)
 {
@@ -1588,6 +1641,127 @@
 	state->monitor = NULL;
 }
 
+/*
+ * Slots fan control loop
+ */
+static void do_monitor_slots(struct slots_pid_state *state)
+{
+	s32 temp, integral, derivative;
+	s64 integ_p, deriv_p, prop_p, sum;
+	int i, rc;
+
+	if (--state->ticks != 0)
+		return;
+	state->ticks = SLOTS_PID_INTERVAL;
+
+	DBG("slots:\n");
+
+	/* Check fan status */
+	rc = get_pwm_fan(SLOTS_FAN_PWM_INDEX);
+	if (rc < 0) {
+		printk(KERN_WARNING "Error %d reading slots fan !\n", rc);
+		/* XXX What do we do now ? */
+	} else
+		state->pwm = rc;
+	DBG("  current pwm: %d\n", state->pwm);
+
+	/* Get some sensor readings */
+	temp = le16_to_cpu(i2c_smbus_read_word_data(state->monitor,
+						    DS1775_TEMP)) << 8;
+	state->last_temp = temp;
+	DBG("  temp: %d.%03d, target: %d.%03d\n", FIX32TOPRINT(temp),
+	    FIX32TOPRINT(SLOTS_PID_INPUT_TARGET));
+
+	/* Store temperature and error in history array */
+	state->cur_sample = (state->cur_sample + 1) % SLOTS_PID_HISTORY_SIZE;
+	state->sample_history[state->cur_sample] = temp;
+	state->error_history[state->cur_sample] = temp - SLOTS_PID_INPUT_TARGET;
+
+	/* If first loop, fill the history table */
+	if (state->first) {
+		for (i = 0; i < (SLOTS_PID_HISTORY_SIZE - 1); i++) {
+			state->cur_sample = (state->cur_sample + 1) %
+				SLOTS_PID_HISTORY_SIZE;
+			state->sample_history[state->cur_sample] = temp;
+			state->error_history[state->cur_sample] =
+				temp - SLOTS_PID_INPUT_TARGET;
+		}
+		state->first = 0;
+	}
+
+	/* Calculate the integral term */
+	sum = 0;
+	integral = 0;
+	for (i = 0; i < SLOTS_PID_HISTORY_SIZE; i++)
+		integral += state->error_history[i];
+	integral *= SLOTS_PID_INTERVAL;
+	DBG("  integral: %08x\n", integral);
+	integ_p = ((s64)SLOTS_PID_G_r) * (s64)integral;
+	DBG("   integ_p: %d\n", (int)(integ_p >> 36));
+	sum += integ_p;
+
+	/* Calculate the derivative term */
+	derivative = state->error_history[state->cur_sample] -
+		state->error_history[(state->cur_sample + SLOTS_PID_HISTORY_SIZE - 1)
+				    % SLOTS_PID_HISTORY_SIZE];
+	derivative /= SLOTS_PID_INTERVAL;
+	deriv_p = ((s64)SLOTS_PID_G_d) * (s64)derivative;
+	DBG("   deriv_p: %d\n", (int)(deriv_p >> 36));
+	sum += deriv_p;
+
+	/* Calculate the proportional term */
+	prop_p = ((s64)SLOTS_PID_G_p) * (s64)(state->error_history[state->cur_sample]);
+	DBG("   prop_p: %d\n", (int)(prop_p >> 36));
+	sum += prop_p;
+
+	/* Scale sum */
+	sum >>= 36;
+
+	DBG("   sum: %d\n", (int)sum);
+	state->pwm = (s32)sum;
+
+	state->pwm = max(state->pwm, SLOTS_PID_OUTPUT_MIN);
+	state->pwm = min(state->pwm, SLOTS_PID_OUTPUT_MAX);
+
+	DBG("** DRIVES PWM: %d\n", (int)state->pwm);
+	set_pwm_fan(SLOTS_FAN_PWM_INDEX, state->pwm);
+}
+
+/*
+ * Initialize the state structure for the slots bay fan control loop
+ */
+static int init_slots_state(struct slots_pid_state *state)
+{
+	state->ticks = 1;
+	state->first = 1;
+	state->pwm = 50;
+
+	state->monitor = attach_i2c_chip(XSERVE_SLOTS_LM75, "slots_temp");
+	if (state->monitor == NULL)
+		return -ENODEV;
+
+	device_create_file(&of_dev->dev, &dev_attr_slots_temperature);
+	device_create_file(&of_dev->dev, &dev_attr_slots_fan_pwm);
+
+	return 0;
+}
+
+/*
+ * Dispose of the state data for the slots control loop
+ */
+static void dispose_slots_state(struct slots_pid_state *state)
+{
+	if (state->monitor == NULL)
+		return;
+
+	device_remove_file(&of_dev->dev, &dev_attr_slots_temperature);
+	device_remove_file(&of_dev->dev, &dev_attr_slots_fan_pwm);
+
+	detach_i2c_chip(state->monitor);
+	state->monitor = NULL;
+}
+
+
 static int call_critical_overtemp(void)
 {
 	char *argv[] = { critical_overtemp_path, NULL };
@@ -1617,14 +1791,17 @@
 		goto out;
 	}
 
-	/* Set the PCI fan once for now */
-	set_pwm_fan(SLOTS_FAN_PWM_INDEX, SLOTS_FAN_DEFAULT_PWM);
+	/* Set the PCI fan once for now on non-RackMac */
+	if (!rackmac)
+		set_pwm_fan(SLOTS_FAN_PWM_INDEX, SLOTS_FAN_DEFAULT_PWM);
 
 	/* Initialize ADCs */
 	initialize_adc(&cpu_state[0]);
 	if (cpu_state[1].monitor != NULL)
 		initialize_adc(&cpu_state[1]);
 
+	fcu_tickle_ticks = FCU_TICKLE_TICKS;
+
 	up(&driver_lock);
 
 	while (state == state_attached) {
@@ -1634,6 +1811,12 @@
 
 		down(&driver_lock);
 
+		/* Tickle the FCU just in case */
+		if (--fcu_tickle_ticks < 0) {
+			fcu_tickle_ticks = FCU_TICKLE_TICKS;
+			tickle_fcu();
+		}
+
 		/* First, we always calculate the new DIMMs state on an Xserve */
 		if (rackmac)
 			do_monitor_dimms(&dimms_state);
@@ -1654,7 +1837,9 @@
 		}
 		/* Then, the rest */
 		do_monitor_backside(&backside_state);
-		if (!rackmac)
+		if (rackmac)
+			do_monitor_slots(&slots_state);
+		else
 			do_monitor_drives(&drives_state);
 		up(&driver_lock);
 
@@ -1696,6 +1881,7 @@
 	dispose_cpu_state(&cpu_state[1]);
 	dispose_backside_state(&backside_state);
 	dispose_drives_state(&drives_state);
+	dispose_slots_state(&slots_state);
 	dispose_dimms_state(&dimms_state);
 }
 
@@ -1745,6 +1931,8 @@
 		goto fail;
 	if (rackmac && init_dimms_state(&dimms_state))
 		goto fail;
+	if (rackmac && init_slots_state(&slots_state))
+		goto fail;
 	if (!rackmac && init_drives_state(&drives_state))
 		goto fail;
 
Index: linux-irq-work/drivers/macintosh/therm_pm72.h
===================================================================
--- linux-irq-work.orig/drivers/macintosh/therm_pm72.h	2006-07-06 16:43:34.000000000 +1000
+++ linux-irq-work/drivers/macintosh/therm_pm72.h	2006-07-06 16:43:36.000000000 +1000
@@ -105,6 +105,7 @@
 #define DRIVES_DALLAS_ID	0x94
 #define BACKSIDE_MAX_ID		0x98
 #define XSERVE_DIMMS_LM87	0x25a
+#define XSERVE_SLOTS_LM75	0x290
 
 /*
  * Some MAX6690, DS1775, LM87 register definitions
@@ -198,7 +199,7 @@
 
 #define SLOTS_FAN_PWM_DEFAULT_ID	2
 #define SLOTS_FAN_PWM_INDEX		2
-#define	SLOTS_FAN_DEFAULT_PWM		50 /* Do better here ! */
+#define	SLOTS_FAN_DEFAULT_PWM		40 /* Do better here ! */
 
 
 /*
@@ -206,7 +207,7 @@
  */
 #define DIMM_PID_G_d			0
 #define DIMM_PID_G_p			0
-#define DIMM_PID_G_r			0x6553600
+#define DIMM_PID_G_r			0x06553600
 #define DIMM_PID_INPUT_TARGET		3276800
 #define DIMM_PID_INTERVAL    		1
 #define DIMM_PID_OUTPUT_MAX		14000
@@ -226,6 +227,31 @@
 };
 
 
+/*
+ * PID factors for the Xserve Slots control loop
+ */
+#define SLOTS_PID_G_d			0
+#define SLOTS_PID_G_p			0
+#define SLOTS_PID_G_r			0x00100000
+#define SLOTS_PID_INPUT_TARGET		3200000
+#define SLOTS_PID_INTERVAL    		1
+#define SLOTS_PID_OUTPUT_MAX		100
+#define SLOTS_PID_OUTPUT_MIN		20
+#define SLOTS_PID_HISTORY_SIZE		20
+
+struct slots_pid_state
+{
+	int			ticks;
+	struct i2c_client *	monitor;
+	s32	       		sample_history[SLOTS_PID_HISTORY_SIZE];
+	s32			error_history[SLOTS_PID_HISTORY_SIZE];
+	int			cur_sample;
+	s32			last_temp;
+	int			first;
+	int			pwm;
+};
+
+
 
 /* Desktops */
 
@@ -283,6 +309,9 @@
 	s32			pump_max;
 };
 
+/* Tickle FCU every 10 seconds */
+#define FCU_TICKLE_TICKS	10
+
 /*
  * Driver state
  */

^ permalink raw reply

* MPC5200 PCI resource allocation problem
From: robinpv @ 2006-07-06  7:17 UTC (permalink / raw)
  To: linuxppc-dev

Hi,
I am using the MPC5200 based board. I have a PCI 2250 bridge, with 2 
RTL8110S ethernet chips on the bridge.
I am using the lite5200 as reference code.
When i run the linux(2.6.16.1), during bootup the following messages are 
displayed,

PCI: Probing PCI hardware
PCI: Cannot allocate resource region 0 of PCI bridge 1
PCI: bridge 1 resource 0 moved to b0fff000..b0ffffff
PCI: Cannot allocate resource region 1 of PCI bridge 1
PCI: bridge 1 resource 1 moved to aff00000..afffffff
PCI: Cannot allocate resource region 2 of PCI bridge 1
PCI: bridge 1 resource 2 moved to 9ff00000..9fffffff

Looking at the iomem and ioports dump, shows that MMIO region has been 
allocated.
But in the ethernet driver when i try to access the ethernet registers. 
all the register content are shown as FFFF.
Also in the mpc52xx_pci.h, the default value for these macros are...
#define MPC52xx_PCI_IO_BASE       0xb0000000
#define MPC52xx_PCI_IO_START    0x00000000
For this setting, IO resource allocation fails
changing to
#define MPC52xx_PCI_IO_START    0xB0000000
passes through.

Can some suggest what could be the problem and how to go about.??

-------------------------------------------------------------------
the iomem dump is as follows
80000000-9fffffff : PCI prefetchable memory
  9ff00000-9fffffff : PCI Bus #01
a0000000-afffffff : PCI memory
  a0000000-a07fffff : 0000:00:10.0
  a0800000-a09fffff : 0000:00:10.0
    a0840000-a0840057 : ohci_hcd
  a0a00000-a0a000ff : 0000:00:11.0
    a0a00000-a0a000ff : SiI680
  a0a40000-a0a7ffff : 0000:00:1a.0
  aff00000-afffffff : PCI Bus #01
    aff00000-aff000ff : 0000:01:02.0
      aff00000-aff000ff : r8169 <= Ethernet 1
    aff00100-aff001ff : 0000:01:03.0
      aff00100-aff001ff : r8169 <=Ethernet 2
f0000900-f000097f : mpc52xx-mscan.0
f0000980-f00009ff : mpc52xx-mscan.1
f0000f00-f0000f1f : mpc52xx-spi
f0001000-f00010ff : ppc-soc-ohci
f0001300-f000130f : mpc52xx-bdlc
f0002000-f000209f : mpc52xx-psc.0
  f0002000-f000209f : mpc52xx_psc_uart
f0002200-f000229f : mpc52xx-psc.1
f0002400-f000249f : mpc52xx-psc.2
f0002600-f000269f : mpc52xx-psc.3
f0002800-f000289f : mpc52xx-psc.4
f0002c00-f0002c9f : mpc52xx-psc.5
f0003000-f00033ff : mpc52xx-fec
f0003a00-f0003aff : mpc52xx-ata
f0003d00-f0003d1f : fsl-i2c.0
f0003d40-f0003d5f : fsl-i2c.1
-------------------------------------------------------
the ioports dump is
  b0000000-b0000007 : 0000:00:11.0
  b0000008-b000000b : 0000:00:11.0
  b000000c-b000000f : 0000:00:11.0
  b0000010-b0000017 : 0000:00:11.0
  b0000020-b000002f : 0000:00:11.0
  b0fff000-b0ffffff : PCI Bus #01
    b0fff000-b0fff0ff : 0000:01:02.0
      b0fff000-b0fff0ff : r8169 <=Ethernet 1
    b0fff400-b0fff4ff : 0000:01:03.0
      b0fff400-b0fff4ff : r8169 <=Ethernet 2
----------------------------------------------------------

With Regards,
Robin

^ permalink raw reply

* Re: Problem in PCI with MPC5200B
From: Heiko Schocher @ 2006-07-06  7:08 UTC (permalink / raw)
  To: linuxppc-embedded; +Cc: hlrprasad
In-Reply-To: <mailman.656.1149719253.11183.linuxppc-embedded@ozlabs.org>

Hello Ram,

On Wed, 7 Jun 2006 11:05:16 +0530 Ram Prasad H L wrote
> hi all,
> 	We are using a customised board which is based on
> 	the reference design of lite5200B. But our board is customised by adding
> 	a PCI-PCI Bridge on the primary bus. On the secondary bus we have added
> 	a DSP(DM642) along with 2 PCI slots, which are routed through
> 	bridge (PCI2250) to MPC5200B.
> 
> 	As far as software is concerned we are using "mpc5200_lite_K26-BSP-b30"
> 	BSP downloaded from freescale's website for lite5200B. This BSP has a
> 	u-boot-1.1.3 and linux kernel-2.6.11.7. As far as u-boot is concerned
> 	the PCI devices are allocated and assigned with proper resources (BAR's)
> 	which come under the range for Mem region(40000000 - 4fffffff) and I/O
> 	region (50000000 - 50ffffff). But during the boot process of linux we
> 	are getting the following errors:
> 
> 
> ****************************************************************************
> ***
> 	PCI: Probing PCI hardware
> 	PCI: Cannot allocate resource region 1 of PCI bridge 1
> 	PCI: bridge 1 resource 1 moved to 4ff00000..4fffffff
> 	PCI: Cannot allocate resource region 2 of PCI bridge 1
> 	PCI: bridge 1 resource 2 moved to 4fe00000..4fefffff
> 	PCI: Failed to allocate mem resource #0: 400000 @ 50000000 for 0000:01:08.0
> 	PCI: Failed to allocate mem resource #1: 800000 @ 50000000 for 0000:01:08.0
> 	PCI: Failed to allocate I/O resource #2: 10 @ 1000 for 0000:01:08.0
> 
> ****************************************************************************
> ****

I had a similar problem with a 2.4.25 Kernel. I get the following
errors:

PCI: Cannot allocate resource region 0 of device 00:1b.0
PCI: moved device 00:1b.0 resource 0 (200) to e0000000

I solved the problem by adding

hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);

at the end of the function mpc5xxx_find_bridges() in
arch/ppc/kernel/mpc5xxx_pci.c

I didnt looked in the 2.6.11.7 Kernel, but maybe this helps you!

Best regards
Heiko

^ permalink raw reply

* Re: [PATCH] powerpc: Xserve G5 thermal control fixes
From: Olof Johansson @ 2006-07-06  5:46 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: linuxppc-dev list, Paul Mackerras, Linux Kernel list
In-Reply-To: <1152162394.24632.58.camel@localhost.localdomain>

On Thu, Jul 06, 2006 at 03:06:34PM +1000, Benjamin Herrenschmidt wrote:
> The thermal control for the Xserve G5s had a few issues. For one, the
> way to program the RPM fans speeds into the FCU is different between it
> and the desktop models, which I didn't figure out until recently, and it
> was missing a control loop for the slots fan, running it too fast. Both
> of those problems were causing the machine to be much more noisy than
> necessary. This patch also changes the fixed value of the slots fan for
> desktop G5s to 40% instead of 50%. It seems to still have a pretty good
> airflow that way and is much less noisy.
> 
> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> 
> Index: linux-irq-work/drivers/macintosh/therm_pm72.c
> ===================================================================
> --- linux-irq-work.orig/drivers/macintosh/therm_pm72.c	2006-07-05 14:46:11.000000000 +1000
> +++ linux-irq-work/drivers/macintosh/therm_pm72.c	2006-07-06 14:42:31.000000000 +1000
> @@ -95,6 +95,14 @@
>   *	- Use min/max macros here or there
>   *	- Latest darwin updated U3H min fan speed to 20% PWM
>   *
> + *  July. 06, 2006 : 1.3
> + *	- Fix setting of RPM fans on Xserve G5 (they were going too fast)
> + *      - Add missing slots fan control loop for Xserve G5
> + *	- Lower fixed slots fan speed from 50% to 40% on desktop G5s. We
> + *        still can't properly implement the control loop for these, so let's
> + *        reduce the noise a little bit, it appears that 40% still gives us
> + *        a pretty good air flow
> + *

Doesn't it make more sense to keep this in the GIT log instead of in
the file? (I seem to remember Freescale getting similar comments on some
posted code just a few days ago :-)

Keeping version numbers for in-tree-only drivers isn't all that useful
either.


-Olof

^ permalink raw reply

* Re: [PATCH] powerpc: Xserve G5 thermal control fixes
From: Segher Boessenkool @ 2006-07-06  5:37 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: linuxppc-dev list, Paul Mackerras, Linux Kernel list
In-Reply-To: <1152162394.24632.58.camel@localhost.localdomain>

> This patch also changes the fixed value of the slots fan for
> desktop G5s to 40% instead of 50%. It seems to still have a pretty  
> good
> airflow that way and is much less noisy.

Is this save when people have one of the ridiculously expensive
(and hot) video cards installed?  And perhaps even a few other
cards, too?


Segher

^ permalink raw reply

* [PATCH] powerpc: Add cpufreq support for Xserve G5
From: Benjamin Herrenschmidt @ 2006-07-06  5:09 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev list, Linux Kernel list

The Xserve G5 are capable of frequency switching like other desktop G5s.
This enables it. It also fix a Kconfig issue which prevented from
building the G5 cpufreq support if CONFIG_PMAC_SMU was not set (the
first version of that driver only worked with SMU based macs, but this
isn't the case anymore).

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

Index: linux-irq-work/arch/powerpc/Kconfig
===================================================================
--- linux-irq-work.orig/arch/powerpc/Kconfig	2006-07-01 13:51:11.000000000 +1000
+++ linux-irq-work/arch/powerpc/Kconfig	2006-07-06 12:16:11.000000000 +1000
@@ -504,7 +504,7 @@
 
 config CPU_FREQ_PMAC64
 	bool "Support for some Apple G5s"
-	depends on CPU_FREQ && PMAC_SMU && PPC64
+	depends on CPU_FREQ && PPC64
 	select CPU_FREQ_TABLE
 	help
 	  This adds support for frequency switching on Apple iMac G5,
Index: linux-irq-work/arch/powerpc/platforms/powermac/cpufreq_64.c
===================================================================
--- linux-irq-work.orig/arch/powerpc/platforms/powermac/cpufreq_64.c	2006-07-01 13:51:11.000000000 +1000
+++ linux-irq-work/arch/powerpc/platforms/powermac/cpufreq_64.c	2006-07-06 14:58:31.000000000 +1000
@@ -10,6 +10,8 @@
  * that is iMac G5 and latest single CPU desktop.
  */
 
+#undef DEBUG
+
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/errno.h>
@@ -30,13 +32,7 @@
 #include <asm/smu.h>
 #include <asm/pmac_pfunc.h>
 
-#undef DEBUG
-
-#ifdef DEBUG
-#define DBG(fmt...) printk(fmt)
-#else
-#define DBG(fmt...)
-#endif
+#define DBG(fmt...) pr_debug(fmt)
 
 /* see 970FX user manual */
 
@@ -82,8 +78,6 @@
 /* Power mode data is an array of the 32 bits PCR values to use for
  * the various frequencies, retrieved from the device-tree
  */
-static u32 *g5_pmode_data;
-static int g5_pmode_max;
 static int g5_pmode_cur;
 
 static void (*g5_switch_volt)(int speed_mode);
@@ -93,6 +87,11 @@
 static DEFINE_MUTEX(g5_switch_mutex);
 
 
+#ifdef CONFIG_PPC_SMU
+
+static u32 *g5_pmode_data;
+static int g5_pmode_max;
+
 static struct smu_sdbp_fvt *g5_fvt_table;	/* table of op. points */
 static int g5_fvt_count;			/* number of op. points */
 static int g5_fvt_cur;				/* current op. point */
@@ -210,6 +209,16 @@
 }
 
 /*
+ * Fake voltage switching for platforms with missing support
+ */
+
+static void g5_dummy_switch_volt(int speed_mode)
+{
+}
+
+#endif /* CONFIG_PPC_SMU */
+
+/*
  * Platform function based voltage switching for PowerMac7,2 & 7,3
  */
 
@@ -248,6 +257,9 @@
 	struct pmf_args args;
 	u32 done = 0;
 	unsigned long timeout;
+	int rc;
+
+	DBG("g5_pfunc_switch_freq(%d)\n", speed_mode);
 
 	/* If frequency is going up, first ramp up the voltage */
 	if (speed_mode < g5_pmode_cur)
@@ -255,9 +267,12 @@
 
 	/* Do it */
 	if (speed_mode == CPUFREQ_HIGH)
-		pmf_call_one(pfunc_cpu_setfreq_high, NULL);
+		rc = pmf_call_one(pfunc_cpu_setfreq_high, NULL);
 	else
-		pmf_call_one(pfunc_cpu_setfreq_low, NULL);
+		rc = pmf_call_one(pfunc_cpu_setfreq_low, NULL);
+
+	if (rc)
+		printk(KERN_WARNING "cpufreq: pfunc switch error %d\n", rc);
 
 	/* It's an irq GPIO so we should be able to just block here,
 	 * I'll do that later after I've properly tested the IRQ code for
@@ -296,13 +311,6 @@
 	return val ? CPUFREQ_HIGH : CPUFREQ_LOW;
 }
 
-/*
- * Fake voltage switching for platforms with missing support
- */
-
-static void g5_dummy_switch_volt(int speed_mode)
-{
-}
 
 /*
  * Common interface to the cpufreq core
@@ -375,6 +383,8 @@
 };
 
 
+#ifdef CONFIG_PPC_SMU
+
 static int __init g5_neo2_cpufreq_init(struct device_node *cpus)
 {
 	struct device_node *cpunode;
@@ -525,6 +535,9 @@
 	return rc;
 }
 
+#endif /* CONFIG_PPC_SMU */
+
+
 static int __init g5_pm72_cpufreq_init(struct device_node *cpus)
 {
 	struct device_node *cpuid = NULL, *hwclock = NULL, *cpunode = NULL;
@@ -533,6 +546,9 @@
 	u64 max_freq, min_freq, ih, il;
 	int has_volt = 1, rc = 0;
 
+	DBG("cpufreq: Initializing for PowerMac7,2, PowerMac7,3 and"
+	    " RackMac3,1...\n");
+
 	/* Get first CPU node */
 	for (cpunode = NULL;
 	     (cpunode = of_get_next_child(cpus, cpunode)) != NULL;) {
@@ -636,6 +652,15 @@
 	 */
 	ih = *((u32 *)(eeprom + 0x10));
 	il = *((u32 *)(eeprom + 0x20));
+
+	/* Check for machines with no useful settings */
+	if (il == ih) {
+		printk(KERN_WARNING "cpufreq: No low frequency mode available"
+		       " on this model !\n");
+		rc = -ENODEV;
+		goto bail;
+	}
+
 	min_freq = 0;
 	if (ih != 0 && il != 0)
 		min_freq = (max_freq * il) / ih;
@@ -643,7 +668,7 @@
 	/* Sanity check */
 	if (min_freq >= max_freq || min_freq < 1000) {
 		printk(KERN_ERR "cpufreq: Can't calculate low frequency !\n");
-		rc = -ENODEV;
+		rc = -ENXIO;
 		goto bail;
 	}
 	g5_cpu_freqs[0].frequency = max_freq;
@@ -690,16 +715,10 @@
 	return rc;
 }
 
-static int __init g5_rm31_cpufreq_init(struct device_node *cpus)
-{
-	/* NYI */
-	return 0;
-}
-
 static int __init g5_cpufreq_init(void)
 {
 	struct device_node *cpus;
-	int rc;
+	int rc = 0;
 
 	cpus = of_find_node_by_path("/cpus");
 	if (cpus == NULL) {
@@ -708,12 +727,13 @@
 	}
 
 	if (machine_is_compatible("PowerMac7,2") ||
-	    machine_is_compatible("PowerMac7,3"))
+	    machine_is_compatible("PowerMac7,3") ||
+	    machine_is_compatible("RackMac3,1"))
 		rc = g5_pm72_cpufreq_init(cpus);
-	else if (machine_is_compatible("RackMac3,1"))
-		rc = g5_rm31_cpufreq_init(cpus);
+#ifdef CONFIG_PPC_SMU
 	else
 		rc = g5_neo2_cpufreq_init(cpus);
+#endif /* CONFIG_PPC_SMU */
 
 	of_node_put(cpus);
 	return rc;

^ permalink raw reply

* [PATCH] powerpc: Xserve G5 thermal control fixes
From: Benjamin Herrenschmidt @ 2006-07-06  5:06 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev list, Linux Kernel list

The thermal control for the Xserve G5s had a few issues. For one, the
way to program the RPM fans speeds into the FCU is different between it
and the desktop models, which I didn't figure out until recently, and it
was missing a control loop for the slots fan, running it too fast. Both
of those problems were causing the machine to be much more noisy than
necessary. This patch also changes the fixed value of the slots fan for
desktop G5s to 40% instead of 50%. It seems to still have a pretty good
airflow that way and is much less noisy.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

Index: linux-irq-work/drivers/macintosh/therm_pm72.c
===================================================================
--- linux-irq-work.orig/drivers/macintosh/therm_pm72.c	2006-07-05 14:46:11.000000000 +1000
+++ linux-irq-work/drivers/macintosh/therm_pm72.c	2006-07-06 14:42:31.000000000 +1000
@@ -95,6 +95,14 @@
  *	- Use min/max macros here or there
  *	- Latest darwin updated U3H min fan speed to 20% PWM
  *
+ *  July. 06, 2006 : 1.3
+ *	- Fix setting of RPM fans on Xserve G5 (they were going too fast)
+ *      - Add missing slots fan control loop for Xserve G5
+ *	- Lower fixed slots fan speed from 50% to 40% on desktop G5s. We
+ *        still can't properly implement the control loop for these, so let's
+ *        reduce the noise a little bit, it appears that 40% still gives us
+ *        a pretty good air flow
+ *
  */
 
 #include <linux/types.h>
@@ -121,7 +129,7 @@
 
 #include "therm_pm72.h"
 
-#define VERSION "1.2b2"
+#define VERSION "1.3"
 
 #undef DEBUG
 
@@ -146,6 +154,7 @@
 static struct backside_pid_state	backside_state;
 static struct drives_pid_state		drives_state;
 static struct dimm_pid_state		dimms_state;
+static struct slots_pid_state		slots_state;
 static int				state;
 static int				cpu_count;
 static int				cpu_pid_type;
@@ -154,7 +163,7 @@
 static int				critical_state;
 static int				rackmac;
 static s32				dimm_output_clamp;
-
+static int 				fcu_rpm_shift;
 static DECLARE_MUTEX(driver_lock);
 
 /*
@@ -495,13 +504,20 @@
 	rc = fan_write_reg(0x2e, &buf, 1);
 	if (rc < 0)
 		return -EIO;
+	rc = fan_read_reg(0, &buf, 1);
+	if (rc < 0)
+		return -EIO;
+	fcu_rpm_shift = (buf == 1) ? 2 : 3;
+	printk(KERN_DEBUG "FCU Initialized, RPM fan shift is %d\n",
+	       fcu_rpm_shift);
+
 	return 0;
 }
 
 static int set_rpm_fan(int fan_index, int rpm)
 {
 	unsigned char buf[2];
-	int rc, id;
+	int rc, id, min, max;
 
 	if (fcu_fans[fan_index].type != FCU_FAN_RPM)
 		return -EINVAL;
@@ -509,12 +525,15 @@
 	if (id == FCU_FAN_ABSENT_ID)
 		return -EINVAL;
 
-	if (rpm < 300)
-		rpm = 300;
-	else if (rpm > 8191)
-		rpm = 8191;
-	buf[0] = rpm >> 5;
-	buf[1] = rpm << 3;
+	min = 2400 >> fcu_rpm_shift;
+	max = 56000 >> fcu_rpm_shift;
+
+	if (rpm < min)
+		rpm = min;
+	else if (rpm > max)
+		rpm = max;
+	buf[0] = rpm >> (8 - fcu_rpm_shift);
+	buf[1] = rpm << fcu_rpm_shift;
 	rc = fan_write_reg(0x10 + (id * 2), buf, 2);
 	if (rc < 0)
 		return -EIO;
@@ -551,7 +570,7 @@
 	if (rc != 2)
 		return -EIO;
 
-	return (buf[0] << 5) | buf[1] >> 3;
+	return (buf[0] << (8 - fcu_rpm_shift)) | buf[1] >> fcu_rpm_shift;
 }
 
 static int set_pwm_fan(int fan_index, int pwm)
@@ -715,6 +734,9 @@
 BUILD_SHOW_FUNC_FIX(drives_temperature, drives_state.last_temp)
 BUILD_SHOW_FUNC_INT(drives_fan_rpm, drives_state.rpm)
 
+BUILD_SHOW_FUNC_FIX(slots_temperature, slots_state.last_temp)
+BUILD_SHOW_FUNC_INT(slots_fan_pwm, slots_state.pwm)
+
 BUILD_SHOW_FUNC_FIX(dimms_temperature, dimms_state.last_temp)
 
 static DEVICE_ATTR(cpu0_temperature,S_IRUGO,show_cpu0_temperature,NULL);
@@ -735,6 +757,9 @@
 static DEVICE_ATTR(drives_temperature,S_IRUGO,show_drives_temperature,NULL);
 static DEVICE_ATTR(drives_fan_rpm,S_IRUGO,show_drives_fan_rpm,NULL);
 
+static DEVICE_ATTR(slots_temperature,S_IRUGO,show_slots_temperature,NULL);
+static DEVICE_ATTR(slots_fan_pwm,S_IRUGO,show_slots_fan_pwm,NULL);
+
 static DEVICE_ATTR(dimms_temperature,S_IRUGO,show_dimms_temperature,NULL);
 
 /*
@@ -1076,6 +1101,9 @@
 	fan_min = dimm_output_clamp;
 	fan_min = max(fan_min, (int)state->mpu.rminn_intake_fan);
 
+	DBG(" CPU min mpu = %d, min dimm = %d\n",
+	    state->mpu.rminn_intake_fan, dimm_output_clamp);
+
 	state->rpm = max(state->rpm, (int)fan_min);
 	state->rpm = min(state->rpm, (int)state->mpu.rmaxn_intake_fan);
 	state->intake_rpm = state->rpm;
@@ -1374,7 +1402,8 @@
 	DBG("  current rpm: %d\n", state->rpm);
 
 	/* Get some sensor readings */
-	temp = le16_to_cpu(i2c_smbus_read_word_data(state->monitor, DS1775_TEMP)) << 8;
+	temp = le16_to_cpu(i2c_smbus_read_word_data(state->monitor,
+						    DS1775_TEMP)) << 8;
 	state->last_temp = temp;
 	DBG("  temp: %d.%03d, target: %d.%03d\n", FIX32TOPRINT(temp),
 	    FIX32TOPRINT(DRIVES_PID_INPUT_TARGET));
@@ -1575,7 +1604,7 @@
 }
 
 /*
- * Dispose of the state data for the drives control loop
+ * Dispose of the state data for the DIMM control loop
  */
 static void dispose_dimms_state(struct dimm_pid_state *state)
 {
@@ -1588,6 +1617,127 @@
 	state->monitor = NULL;
 }
 
+/*
+ * Slots fan control loop
+ */
+static void do_monitor_slots(struct slots_pid_state *state)
+{
+	s32 temp, integral, derivative;
+	s64 integ_p, deriv_p, prop_p, sum;
+	int i, rc;
+
+	if (--state->ticks != 0)
+		return;
+	state->ticks = SLOTS_PID_INTERVAL;
+
+	DBG("slots:\n");
+
+	/* Check fan status */
+	rc = get_pwm_fan(SLOTS_FAN_PWM_INDEX);
+	if (rc < 0) {
+		printk(KERN_WARNING "Error %d reading slots fan !\n", rc);
+		/* XXX What do we do now ? */
+	} else
+		state->pwm = rc;
+	DBG("  current pwm: %d\n", state->pwm);
+
+	/* Get some sensor readings */
+	temp = le16_to_cpu(i2c_smbus_read_word_data(state->monitor,
+						    DS1775_TEMP)) << 8;
+	state->last_temp = temp;
+	DBG("  temp: %d.%03d, target: %d.%03d\n", FIX32TOPRINT(temp),
+	    FIX32TOPRINT(SLOTS_PID_INPUT_TARGET));
+
+	/* Store temperature and error in history array */
+	state->cur_sample = (state->cur_sample + 1) % SLOTS_PID_HISTORY_SIZE;
+	state->sample_history[state->cur_sample] = temp;
+	state->error_history[state->cur_sample] = temp - SLOTS_PID_INPUT_TARGET;
+
+	/* If first loop, fill the history table */
+	if (state->first) {
+		for (i = 0; i < (SLOTS_PID_HISTORY_SIZE - 1); i++) {
+			state->cur_sample = (state->cur_sample + 1) %
+				SLOTS_PID_HISTORY_SIZE;
+			state->sample_history[state->cur_sample] = temp;
+			state->error_history[state->cur_sample] =
+				temp - SLOTS_PID_INPUT_TARGET;
+		}
+		state->first = 0;
+	}
+
+	/* Calculate the integral term */
+	sum = 0;
+	integral = 0;
+	for (i = 0; i < SLOTS_PID_HISTORY_SIZE; i++)
+		integral += state->error_history[i];
+	integral *= SLOTS_PID_INTERVAL;
+	DBG("  integral: %08x\n", integral);
+	integ_p = ((s64)SLOTS_PID_G_r) * (s64)integral;
+	DBG("   integ_p: %d\n", (int)(integ_p >> 36));
+	sum += integ_p;
+
+	/* Calculate the derivative term */
+	derivative = state->error_history[state->cur_sample] -
+		state->error_history[(state->cur_sample + SLOTS_PID_HISTORY_SIZE - 1)
+				    % SLOTS_PID_HISTORY_SIZE];
+	derivative /= SLOTS_PID_INTERVAL;
+	deriv_p = ((s64)SLOTS_PID_G_d) * (s64)derivative;
+	DBG("   deriv_p: %d\n", (int)(deriv_p >> 36));
+	sum += deriv_p;
+
+	/* Calculate the proportional term */
+	prop_p = ((s64)SLOTS_PID_G_p) * (s64)(state->error_history[state->cur_sample]);
+	DBG("   prop_p: %d\n", (int)(prop_p >> 36));
+	sum += prop_p;
+
+	/* Scale sum */
+	sum >>= 36;
+
+	DBG("   sum: %d\n", (int)sum);
+	state->pwm = (s32)sum;
+
+	state->pwm = max(state->pwm, SLOTS_PID_OUTPUT_MIN);
+	state->pwm = min(state->pwm, SLOTS_PID_OUTPUT_MAX);
+
+	DBG("** DRIVES PWM: %d\n", (int)state->pwm);
+	set_pwm_fan(SLOTS_FAN_PWM_INDEX, state->pwm);
+}
+
+/*
+ * Initialize the state structure for the slots bay fan control loop
+ */
+static int init_slots_state(struct slots_pid_state *state)
+{
+	state->ticks = 1;
+	state->first = 1;
+	state->pwm = 50;
+
+	state->monitor = attach_i2c_chip(XSERVE_SLOTS_LM75, "slots_temp");
+	if (state->monitor == NULL)
+		return -ENODEV;
+
+	device_create_file(&of_dev->dev, &dev_attr_slots_temperature);
+	device_create_file(&of_dev->dev, &dev_attr_slots_fan_pwm);
+
+	return 0;
+}
+
+/*
+ * Dispose of the state data for the slots control loop
+ */
+static void dispose_slots_state(struct slots_pid_state *state)
+{
+	if (state->monitor == NULL)
+		return;
+
+	device_remove_file(&of_dev->dev, &dev_attr_slots_temperature);
+	device_remove_file(&of_dev->dev, &dev_attr_slots_fan_pwm);
+
+	detach_i2c_chip(state->monitor);
+	state->monitor = NULL;
+}
+
+
 static int call_critical_overtemp(void)
 {
 	char *argv[] = { critical_overtemp_path, NULL };
@@ -1617,8 +1767,9 @@
 		goto out;
 	}
 
-	/* Set the PCI fan once for now */
-	set_pwm_fan(SLOTS_FAN_PWM_INDEX, SLOTS_FAN_DEFAULT_PWM);
+	/* Set the PCI fan once for now on non-RackMac */
+	if (!rackmac)
+		set_pwm_fan(SLOTS_FAN_PWM_INDEX, SLOTS_FAN_DEFAULT_PWM);
 
 	/* Initialize ADCs */
 	initialize_adc(&cpu_state[0]);
@@ -1654,7 +1805,9 @@
 		}
 		/* Then, the rest */
 		do_monitor_backside(&backside_state);
-		if (!rackmac)
+		if (rackmac)
+			do_monitor_slots(&slots_state);
+		else
 			do_monitor_drives(&drives_state);
 		up(&driver_lock);
 
@@ -1696,6 +1849,7 @@
 	dispose_cpu_state(&cpu_state[1]);
 	dispose_backside_state(&backside_state);
 	dispose_drives_state(&drives_state);
+	dispose_slots_state(&slots_state);
 	dispose_dimms_state(&dimms_state);
 }
 
@@ -1745,6 +1899,8 @@
 		goto fail;
 	if (rackmac && init_dimms_state(&dimms_state))
 		goto fail;
+	if (rackmac && init_slots_state(&slots_state))
+		goto fail;
 	if (!rackmac && init_drives_state(&drives_state))
 		goto fail;
 
Index: linux-irq-work/drivers/macintosh/therm_pm72.h
===================================================================
--- linux-irq-work.orig/drivers/macintosh/therm_pm72.h	2006-07-01 13:51:20.000000000 +1000
+++ linux-irq-work/drivers/macintosh/therm_pm72.h	2006-07-06 14:03:16.000000000 +1000
@@ -105,6 +105,7 @@
 #define DRIVES_DALLAS_ID	0x94
 #define BACKSIDE_MAX_ID		0x98
 #define XSERVE_DIMMS_LM87	0x25a
+#define XSERVE_SLOTS_LM75	0x290
 
 /*
  * Some MAX6690, DS1775, LM87 register definitions
@@ -198,7 +199,7 @@
 
 #define SLOTS_FAN_PWM_DEFAULT_ID	2
 #define SLOTS_FAN_PWM_INDEX		2
-#define	SLOTS_FAN_DEFAULT_PWM		50 /* Do better here ! */
+#define	SLOTS_FAN_DEFAULT_PWM		40 /* Do better here ! */
 
 
 /*
@@ -206,7 +207,7 @@
  */
 #define DIMM_PID_G_d			0
 #define DIMM_PID_G_p			0
-#define DIMM_PID_G_r			0x6553600
+#define DIMM_PID_G_r			0x06553600
 #define DIMM_PID_INPUT_TARGET		3276800
 #define DIMM_PID_INTERVAL    		1
 #define DIMM_PID_OUTPUT_MAX		14000
@@ -226,6 +227,31 @@
 };
 
 
+/*
+ * PID factors for the Xserve Slots control loop
+ */
+#define SLOTS_PID_G_d			0
+#define SLOTS_PID_G_p			0
+#define SLOTS_PID_G_r			0x00100000
+#define SLOTS_PID_INPUT_TARGET		3200000
+#define SLOTS_PID_INTERVAL    		1
+#define SLOTS_PID_OUTPUT_MAX		100
+#define SLOTS_PID_OUTPUT_MIN		20
+#define SLOTS_PID_HISTORY_SIZE		20
+
+struct slots_pid_state
+{
+	int			ticks;
+	struct i2c_client *	monitor;
+	s32	       		sample_history[SLOTS_PID_HISTORY_SIZE];
+	s32			error_history[SLOTS_PID_HISTORY_SIZE];
+	int			cur_sample;
+	s32			last_temp;
+	int			first;
+	int			pwm;
+};
+
+
 
 /* Desktops */
 

^ permalink raw reply

* Re: [PATCH] Fix snd-aoa irq conversion
From: Benjamin Herrenschmidt @ 2006-07-05 23:16 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: linuxppc-dev
In-Reply-To: <jeirmbn76v.fsf@sykes.suse.de>

On Wed, 2006-07-05 at 22:11 +0200, Andreas Schwab wrote:
> Use proper irq mapping interface for snd-aoa-i2sbus.
> 
> Signed-off-by: Andreas Schwab <schwab@suse.de>

Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

One could argue that the "proper" fix is to update macio_asic.c to
register the sub-nodes i2s-X as individual devices. That would also
allow to move the various resource workarounds there along with others
and simplify the code in snd-aoa.

Ben.

^ permalink raw reply

* problem with kernel debug using BDI2000
From: hb fei @ 2006-07-05 20:11 UTC (permalink / raw)
  To: linuxppc-embedded

[-- Attachment #1: Type: text/plain, Size: 3724 bytes --]

Hi there,

  I met some problems when I tried to debug the 2.5.16 kernel with BDI2000
for a customerized MPC8xx.
I listed my two trials, can any one tell me what is wrong with my approachs,


[Try 1] =============================================>

(1) Build the kernel image, the map file -- System.map file

.....

c0000000 T _start

c0000000 T __start

c0000000 T _stext

c0000018 t turn_on_mmu

c0000100 t Reset

.....

(2) Copy the vmlinux into /tftpboot for load the iamge

(3) I mapped the logic address 0xc0000000 into physical address 0x00100000
in target

by loading the file through BDI telnet console, the telnet screen shows

BDI>load 0x40100000 vmlinux elf

Loading vmlinux , please wait ....

- File offset 0x00010000 to address 0x00100000 size 1728646

Loading program file passed



(4) Start the GDB command, and single step from address 0x00100000.

I tried two version of ppc gdb, both have the same result. The location of
one of

the gdb (through DENX) is,

$ which ppc_8xx-gdb

/opt/eldk/usr/bin/ppc_8xx-gdb



(5) And start the gdb through the following command,

$ ppc_8xx-gdb vmlinux (under kernel top directory)

(gdb) target remote 10.199.5.234:2001

Remote debugging using 10.199.5.234:2001

(gdb) si

0x0010000c in ?? ()

(gdb)

0x00100010 in ?? ()

(gdb)

0x00100014 in ?? ()

....

Things go well till I reach the

(gdb)

0x00100030 in ?? ()

(gdb)

Program received signal SIGSTOP, Stopped (signal).

0x00100030 in ?? ()

(gdb)

Program received signal SIGSTOP, Stopped (signal).

0x00100030 in ?? ()

(gdb)



If I check the code carefully in /arch/ppc/kernel_8xx.S, 0x00100030 address

matches the rfi comamnd in

turn_on_mmu:

mfmsr r0

ori r0,r0,MSR_DR|MSR_IR

mtspr SPRN_SRR1,r0

lis r0,start_here@h

ori r0,r0,start_here@l

mtspr SPRN_SRR0,r0

SYNC

rfi /* enables MMU */



(6) I check the BDI configuration (8xx.cfg) file, seems I had enabled the
MMI



[TARGET]

CPUCLOCK 32000000 ;the CPU clock rate after processing the init list

BDIMODE AGENT ;the BDI working mode (LOADONLY | AGENT)

BREAKMODE SOFT ;SOFT or HARD, HARD uses PPC hardware breakpoints

;STEPMODE HWBP ;TRACE or HWBP, HWPB uses one or two hardware breakpoints

;STARTUP STOP 5000 ;let the monitor initialize the system

;DCACHE FLUSH ;flush data cache, needs a workspace of 32 bytes

;WORKSPACE 0x00000040 ;workspace in target RAM for data cache flush

MMU XLAT ;translate effective to physical address

;PTBASE 0x00000f0 ;????

;REGLIST SPR ;select register to transfer to GDB

REGLIST ALL ;select register to transfer to GDB

I assume I do not need set PTBASE, since I am working on the very new
version of kernel

(2.6.15).



Question, seems to me the MMU in BDI does still map the logic address into
physical

address correctly, what did I miss here?

[Try 2 ]  ===================================================>

Exactly follow the BDI user manual,

(1) load image, BDI telnet screen shows

BDI>load 0x40100000 vmlinux elf

Loading vmlinux , please wait ....

- File offset 0x00010000 to address 0x00100000 size 1728646

Loading program file passed



(2) set hardware break point

BDI>bi 0xc0000000 0xc00fffff

Breakpoint identification is 0

(3) issue go comamnd from telnet screen

BDI>go

- TARGET: stopped

(4) Disable hardware break point

BDI> ci

(5) Start gdb from another terminal,

$ ppc_8xx-gdb vmlinux

(6) Attached target,

(gdb) target remote 10.199.5.234:2001

Remote debugging using 10.199.5.234:2001

0x00001100 in ?? ()

(7) Set software break point,

(gdb) b start_kernel

(8) let go

(gdb) c

Continuing.

Program received signal SIGTRAP, Trace/breakpoint trap.

0x00001100 in ?? ()

Seems to me the MMU still not work with BDI.

Can any one one point out what is the problem?

Thanks!

[-- Attachment #2: Type: text/html, Size: 4809 bytes --]

^ permalink raw reply

* [PATCH] Fix snd-aoa irq conversion
From: Andreas Schwab @ 2006-07-05 20:11 UTC (permalink / raw)
  To: linuxppc-dev

Use proper irq mapping interface for snd-aoa-i2sbus.

Signed-off-by: Andreas Schwab <schwab@suse.de>

---
 sound/aoa/soundbus/i2sbus/i2sbus-core.c |    9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

Index: linux-2.6.17-git24/sound/aoa/soundbus/i2sbus/i2sbus-core.c
===================================================================
--- linux-2.6.17-git24.orig/sound/aoa/soundbus/i2sbus/i2sbus-core.c	2006-07-05 20:50:07.000000000 +0200
+++ linux-2.6.17-git24/sound/aoa/soundbus/i2sbus/i2sbus-core.c	2006-07-05 22:02:47.000000000 +0200
@@ -129,9 +129,6 @@ static int i2sbus_add_dev(struct macio_d
 	if (strncmp(np->name, "i2s-", 4))
 		return 0;
 
-	if (macio_irq_count(macio) != 3)
-		return 0;
-
 	dev = kzalloc(sizeof(struct i2sbus_dev), GFP_KERNEL);
 	if (!dev)
 		return 0;
@@ -183,10 +180,10 @@ static int i2sbus_add_dev(struct macio_d
 		snprintf(dev->rnames[i], sizeof(dev->rnames[i]), rnames[i], np->name);
 	}
 	for (i=0;i<3;i++) {
-		if (request_irq(macio_irq(macio, i), ints[i], 0,
-				dev->rnames[i], dev))
+		int irq = irq_of_parse_and_map(np, i);
+		if (request_irq(irq, ints[i], 0, dev->rnames[i], dev))
 			goto err;
-		dev->interrupts[i] = macio_irq(macio, i);
+		dev->interrupts[i] = irq;
 	}
 
 	for (i=0;i<3;i++) {


Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux Products GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany
PGP key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ permalink raw reply

* append a correct "root= boot option"
From: Gabriele @ 2006-07-05 16:12 UTC (permalink / raw)
  To: linuxppc-embedded

help me

I upgrade  the linux Kernel from 2.4 to 2.6, but i don't succeed  to Configurate the mtd.

Creating 4 MTD partitions on "EVBOARD875-0":
0x00000000-0x00060000 : "u-boot"
0x00060000-0x00160000 : "kernel"
0x00160000-0x004fa000 : "cramfs"
mtd: partition "cramfs" doesn't end on an erase block -- force read-only
0x00500000-0x00806000 : "jffs2"

obtain the follw message:

"Please append a correct "root= boot option"

from what can to depend? 

thanks to all 

 Gabriele
morelli.gab@virgilio.it
2006-07-05

^ permalink raw reply

* RE: Linux 2.6.x : cpm_dpalloc alignment bug perhaps not fully resolved
From: Laurent Lagrange @ 2006-07-05 10:03 UTC (permalink / raw)
  To: 'Pantelis Antoniou'; +Cc: linuxppc-embedded
In-Reply-To: <200607051238.18237.pantelis@embeddedalley.com>



> -----Message d'origine-----
> De : Pantelis Antoniou [mailto:pantelis@embeddedalley.com]
> Envoyé : mer. 5 juillet 2006 10:38
> À : Laurent Lagrange
> Cc : 'Li Yang-r58472'; linuxppc-embedded@ozlabs.org
> Objet : Re: Linux 2.6.x : cpm_dpalloc alignment bug perhaps not fully
> resolved
>
> Should be a bug at the free. I'll take a look at it when I have a few
> spare cycles.
>
> Pantelis
>
Yes, I think so.
I'll try to get more details if I can help you.
Best regards
Laurent

^ permalink raw reply

* Re: Linux 2.6.x : cpm_dpalloc alignment bug perhaps not fully resolved
From: Pantelis Antoniou @ 2006-07-05  9:38 UTC (permalink / raw)
  To: Laurent Lagrange; +Cc: linuxppc-embedded
In-Reply-To: <000001c6a013$0f321100$5201a8c0@GEG2400>

On Wednesday 05 July 2006 12:11, Laurent Lagrange wrote:
>=20
> > -----Message d'origine-----
> > De : Li Yang-r58472 [mailto:LeoLi@freescale.com]
> > Envoy=E9 : mer. 5 juillet 2006 09:36
> > =C0 : Laurent Lagrange; pantelis@embeddedalley.com
> > >
> > > The patch, I already applied, comes directly from Pantelis
> > > and is the same code as found at
> > > http://patchwork.ozlabs.org/linuxppc/patch?id=3D3484
> >
> > Sure, it is the patch I mentioned.  Also be noted that the
> > patch only fixes rheap in arch/ppc/.  If you are using latest
> > 2.6 source, you are most probably using code under arch/powerpc/.
> > >
> I use a Linux 2.6.9 for MPC8260 and the arch/ppc/lib/rheap.c file.
> I have no arch/powerpc tree in this kernel.
>=20
> Before applying the patch, I was not able to get a right aligned area
> with cpm_dpalloc. After applying it, cpm_dpalloc seems to be right
> until I use cpm_dpfree and then cpm_dpalloc on the same area.
>=20
> Another idea ?
> Thanks
> Laurent
>=20
>=20
>=20

Should be a bug at the free. I'll take a look at it when I have a few
spare cycles.

Pantelis

^ permalink raw reply

* RE: Linux 2.6.x : cpm_dpalloc alignment bug perhaps not fully resolved
From: Laurent Lagrange @ 2006-07-05  9:11 UTC (permalink / raw)
  To: 'Li Yang-r58472', pantelis; +Cc: linuxppc-embedded
In-Reply-To: <9FCDBA58F226D911B202000BDBAD467306FFBEDC@zch01exm40.ap.freescale.net>



> -----Message d'origine-----
> De : Li Yang-r58472 [mailto:LeoLi@freescale.com]
> Envoyé : mer. 5 juillet 2006 09:36
> À : Laurent Lagrange; pantelis@embeddedalley.com
> >
> > The patch, I already applied, comes directly from Pantelis
> > and is the same code as found at
> > http://patchwork.ozlabs.org/linuxppc/patch?id=3484
>
> Sure, it is the patch I mentioned.  Also be noted that the
> patch only fixes rheap in arch/ppc/.  If you are using latest
> 2.6 source, you are most probably using code under arch/powerpc/.
> >
I use a Linux 2.6.9 for MPC8260 and the arch/ppc/lib/rheap.c file.
I have no arch/powerpc tree in this kernel.

Before applying the patch, I was not able to get a right aligned area
with cpm_dpalloc. After applying it, cpm_dpalloc seems to be right
until I use cpm_dpfree and then cpm_dpalloc on the same area.

Another idea ?
Thanks
Laurent

^ permalink raw reply

* RE: Linux 2.6.x  :  cpm_dpalloc alignment bug perhaps not fully r esolved
From: Li Yang-r58472 @ 2006-07-05  8:35 UTC (permalink / raw)
  To: Laurent Lagrange, pantelis; +Cc: linuxppc-embedded

> -----Original Message-----
> From: Laurent Lagrange [mailto:lagrange@fr.oleane.com]
> Sent: Wednesday, July 05, 2006 4:26 PM
> To: Li Yang-r58472; pantelis@embeddedalley.com
> Cc: linuxppc-embedded@ozlabs.org
> Subject: RE: Linux 2.6.x : cpm_dpalloc alignment bug perhaps not =
fully resolved
>=20
> Hi Leo,
>=20
> Thanks for the reply.
>=20
> The patch, I already applied, comes directly from Pantelis
> and is the same code as found at
> http://patchwork.ozlabs.org/linuxppc/patch?id=3D3484

Sure, it is the patch I mentioned.  Also be noted that the patch only =
fixes rheap in arch/ppc/.  If you are using latest 2.6 source, you are =
most probably using code under arch/powerpc/.
>=20
> What do you mean by the alignment patch ?
>=20
> I suspect a problem in the cpm_dpfree function,
> not in the cpm_dpalloc function.
>=20
> I'll try to give more details.
>=20
> Best regards
> Laurent
>=20
>=20
>=20
> > -----Message d'origine-----
> > De : Li Yang-r58472 [mailto:LeoLi@freescale.com]
> > Envoy=E9 : mer. 5 juillet 2006 03:32
> > =C0 : Laurent Lagrange; pantelis@embeddedalley.com
> > Cc : linuxppc-embedded@ozlabs.org
> > Objet : RE: Linux 2.6.x : cpm_dpalloc alignment bug perhaps not =
fully
> > resolved
> >
> >
> > Did you apply the alignment patch too?  AFAIK, the problem is
> > never fixed in
> > mainstream trees.
> >
> > Best Regards,
> > Leo
> >

^ permalink raw reply

* RE: Linux 2.6.x : cpm_dpalloc alignment bug perhaps not fully resolved
From: Laurent Lagrange @ 2006-07-05  8:25 UTC (permalink / raw)
  To: 'Li Yang-r58472', pantelis; +Cc: linuxppc-embedded
In-Reply-To: <9FCDBA58F226D911B202000BDBAD467306FA6F52@zch01exm40.ap.freescale.net>

Hi Leo,

Thanks for the reply.

The patch, I already applied, comes directly from Pantelis
and is the same code as found at
http://patchwork.ozlabs.org/linuxppc/patch?id=3484

What do you mean by the alignment patch ?

I suspect a problem in the cpm_dpfree function,
not in the cpm_dpalloc function.

I'll try to give more details.

Best regards
Laurent



> -----Message d'origine-----
> De : Li Yang-r58472 [mailto:LeoLi@freescale.com]
> Envoyé : mer. 5 juillet 2006 03:32
> À : Laurent Lagrange; pantelis@embeddedalley.com
> Cc : linuxppc-embedded@ozlabs.org
> Objet : RE: Linux 2.6.x : cpm_dpalloc alignment bug perhaps not fully
> resolved
>
>
> Did you apply the alignment patch too?  AFAIK, the problem is
> never fixed in
> mainstream trees.
>
> Best Regards,
> Leo
>

^ permalink raw reply

* Re: [PATCH 13/20] [powerpc, video & agp] Constify & voidify get_property()
From: Dave Jones @ 2006-07-05  5:43 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev, davej
In-Reply-To: <17579.18070.211297.508029@cargo.ozlabs.ibm.com>

On Wed, Jul 05, 2006 at 02:56:54PM +1000, Paul Mackerras wrote:
 > Dave Jones writes:
 > 
 > > I assume this stuff is going in through the ppc tree?
 > 
 > Yes, I'll take care of it.  Once Linus releases -rc1 I'll start
 > pushing the for-2.6.19 patches (including these) to the master branch
 > of the powerpc.git tree.

Sounds good, thanks Paul.

		Dave

-- 
http://www.codemonkey.org.uk

^ permalink raw reply

* Re: [PATCH] powerpc: Fix loss of interrupts with MPIC (#2)
From: Benjamin Herrenschmidt @ 2006-07-05  5:36 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev list, Linus Torvalds, Linux Kernel list
In-Reply-To: <1152076021.17790.10.camel@localhost.localdomain>

And here's the right version of the patch, pls drop the other one,
sorry....

With the new interrupt rework, an interrupt "host" map() callback can be
called after the interrupt is already active (it's called again for an
already mapped interrupt to allow changing the trigger
setup, and currently this is not guarded with a test of wether the
interrupt is requested or not, I plan to change some of this logic to be
a bit less lenient against random reconfiguring of live
interrupts but just not yet). The ported MPIC driver has a bug where
when that happens, it will mask the interrupt. This changes it to
preserve the previous masking of the interrupt instead.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
Linus: It would be nice if that could still sneak into -rc1 as it causes
hangs and other bad issues on PowerMac.

Index: linux-irq-work/arch/powerpc/sysdev/mpic.c
===================================================================
--- linux-irq-work.orig/arch/powerpc/sysdev/mpic.c	2006-07-05 14:46:11.000000000 +1000
+++ linux-irq-work/arch/powerpc/sysdev/mpic.c	2006-07-05 15:34:50.000000000 +1000
@@ -405,20 +405,22 @@
 	unsigned int loops = 100000;
 	struct mpic *mpic = mpic_from_irq(irq);
 	unsigned int src = mpic_irq_to_hw(irq);
+	unsigned long flags;
 
 	DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, irq, src);
 
+	spin_lock_irqsave(&mpic_lock, flags);
 	mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
 		       mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) &
 		       ~MPIC_VECPRI_MASK);
-
 	/* make sure mask gets to controller before we return to user */
 	do {
 		if (!loops--) {
 			printk(KERN_ERR "mpic_enable_irq timeout\n");
 			break;
 		}
-	} while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK);	
+	} while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK);
+	spin_unlock_irqrestore(&mpic_lock, flags);
 }
 
 static void mpic_mask_irq(unsigned int irq)
@@ -426,9 +428,11 @@
 	unsigned int loops = 100000;
 	struct mpic *mpic = mpic_from_irq(irq);
 	unsigned int src = mpic_irq_to_hw(irq);
+	unsigned long flags;
 
 	DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src);
 
+	spin_lock_irqsave(&mpic_lock, flags);
 	mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
 		       mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) |
 		       MPIC_VECPRI_MASK);
@@ -440,6 +444,7 @@
 			break;
 		}
 	} while(!(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK));
+	spin_unlock_irqrestore(&mpic_lock, flags);
 }
 
 static void mpic_end_irq(unsigned int irq)
@@ -624,9 +629,10 @@
 	struct irq_desc *desc = get_irq_desc(virq);
 	struct irq_chip *chip;
 	struct mpic *mpic = h->host_data;
-	unsigned int vecpri = MPIC_VECPRI_SENSE_LEVEL |
+	u32 v, vecpri = MPIC_VECPRI_SENSE_LEVEL |
 		MPIC_VECPRI_POLARITY_NEGATIVE;
 	int level;
+	unsigned long iflags;
 
 	pr_debug("mpic: map virq %d, hwirq 0x%lx, flags: 0x%x\n",
 		 virq, hw, flags);
@@ -668,11 +674,21 @@
 	}
 #endif
 
-	/* Reconfigure irq */
-	vecpri |= MPIC_VECPRI_MASK | hw | (8 << MPIC_VECPRI_PRIORITY_SHIFT);
-	mpic_irq_write(hw, MPIC_IRQ_VECTOR_PRI, vecpri);
+	/* Reconfigure irq. We must preserve the mask bit as we can be called
+	 * while the interrupt is still active (This may change in the future
+	 * but for now, it is the case).
+	 */
+	spin_lock_irqsave(&mpic_lock, iflags);
+	v = mpic_irq_read(hw, MPIC_IRQ_VECTOR_PRI);
+	vecpri = (v &
+		~(MPIC_VECPRI_POLARITY_MASK | MPIC_VECPRI_SENSE_MASK)) |
+		vecpri;
+	if (vecpri != v)
+		mpic_irq_write(hw, MPIC_IRQ_VECTOR_PRI, vecpri);
+	spin_unlock_irqrestore(&mpic_lock, iflags);
 
-	pr_debug("mpic: mapping as IRQ\n");
+	pr_debug("mpic: mapping as IRQ, vecpri = 0x%08x (was 0x%08x)\n",
+		 vecpri, v);
 
 	set_irq_chip_data(virq, mpic);
 	set_irq_chip_and_handler(virq, chip, handle_fasteoi_irq);
@@ -904,8 +920,8 @@
 		
 		/* do senses munging */
 		if (mpic->senses && i < mpic->senses_count)
-			vecpri = mpic_flags_to_vecpri(mpic->senses[i],
-						      &level);
+			vecpri |= mpic_flags_to_vecpri(mpic->senses[i],
+						       &level);
 		else
 			vecpri |= MPIC_VECPRI_SENSE_LEVEL;
 
@@ -955,14 +971,17 @@
 
 void __init mpic_set_serial_int(struct mpic *mpic, int enable)
 {
+	unsigned long flags;
 	u32 v;
 
+	spin_lock_irqsave(&mpic_lock, flags);
 	v = mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1);
 	if (enable)
 		v |= MPIC_GREG_GLOBAL_CONF_1_SIE;
 	else
 		v &= ~MPIC_GREG_GLOBAL_CONF_1_SIE;
 	mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1, v);
+	spin_unlock_irqrestore(&mpic_lock, flags);
 }
 
 void mpic_irq_set_priority(unsigned int irq, unsigned int pri)

^ permalink raw reply

* [PATCH] powerpc: Fix loss of interrupts with MPIC
From: Benjamin Herrenschmidt @ 2006-07-05  5:07 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev list, Linus Torvalds, Linux Kernel list

With the new interrupt rework, an interrupt "host" map() callback can be
called after the interrupt is already active (it's called again for an
already mapped interrupt to allow changing the trigger
setup, and currently this is not guarded with a test of wether the
interrupt is requested or not, I plan to change some of this logic to be
a bit less lenient against random reconfiguring of live
interrupts but just not yet). The ported MPIC driver has a bug where
when that happens, it will mask the interrupt. This changes it to
preserve the previous masking of the interrupt instead.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
Linus: It would be nice if that could still sneak into -rc1 as it causes
hangs and other bad issues on PowerMac.

Index: linux-irq-work/arch/powerpc/sysdev/mpic.c
===================================================================
--- linux-irq-work.orig/arch/powerpc/sysdev/mpic.c	2006-07-05 14:46:11.000000000 +1000
+++ linux-irq-work/arch/powerpc/sysdev/mpic.c	2006-07-05 15:00:48.000000000 +1000
@@ -405,20 +405,22 @@
 	unsigned int loops = 100000;
 	struct mpic *mpic = mpic_from_irq(irq);
 	unsigned int src = mpic_irq_to_hw(irq);
+	unsigned long flags;
 
 	DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, irq, src);
 
+	spin_lock_irqsave(&mpic_lock, flags);
 	mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
 		       mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) &
 		       ~MPIC_VECPRI_MASK);
-
 	/* make sure mask gets to controller before we return to user */
 	do {
 		if (!loops--) {
 			printk(KERN_ERR "mpic_enable_irq timeout\n");
 			break;
 		}
-	} while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK);	
+	} while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK);
+	spin_unlock_irqrestore(&mpic_lock, flags);
 }
 
 static void mpic_mask_irq(unsigned int irq)
@@ -426,9 +428,11 @@
 	unsigned int loops = 100000;
 	struct mpic *mpic = mpic_from_irq(irq);
 	unsigned int src = mpic_irq_to_hw(irq);
+	unsigned long flags;
 
 	DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src);
 
+	spin_lock_irqsave(&mpic_lock, flags);
 	mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
 		       mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) |
 		       MPIC_VECPRI_MASK);
@@ -440,6 +444,7 @@
 			break;
 		}
 	} while(!(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK));
+	spin_unlock_irqrestore(&mpic_lock, flags);
 }
 
 static void mpic_end_irq(unsigned int irq)
@@ -624,7 +629,7 @@
 	struct irq_desc *desc = get_irq_desc(virq);
 	struct irq_chip *chip;
 	struct mpic *mpic = h->host_data;
-	unsigned int vecpri = MPIC_VECPRI_SENSE_LEVEL |
+	u32 v, vecpri = MPIC_VECPRI_SENSE_LEVEL |
 		MPIC_VECPRI_POLARITY_NEGATIVE;
 	int level;
 
@@ -668,11 +673,21 @@
 	}
 #endif
 
-	/* Reconfigure irq */
-	vecpri |= MPIC_VECPRI_MASK | hw | (8 << MPIC_VECPRI_PRIORITY_SHIFT);
-	mpic_irq_write(hw, MPIC_IRQ_VECTOR_PRI, vecpri);
+	/* Reconfigure irq. We must preserve the mask bit as we can be called
+	 * while the interrupt is still active (This may change in the future
+	 * but for now, it is the case).
+	 */
+	spin_lock_irqsave(&mpic_lock, flags);
+	v = mpic_irq_read(hw, MPIC_IRQ_VECTOR_PRI);
+	vecpri = (v &
+		~(MPIC_VECPRI_POLARITY_MASK | MPIC_VECPRI_SENSE_MASK)) |
+		vecpri;
+	if (vecpri != v)
+		mpic_irq_write(hw, MPIC_IRQ_VECTOR_PRI, vecpri);
+	spin_unlock_irqrestore(&mpic_lock, flags);
 
-	pr_debug("mpic: mapping as IRQ\n");
+	pr_debug("mpic: mapping as IRQ, vecpri = 0x%08x (was 0x%08x)\n",
+		 vecpri, v);
 
 	set_irq_chip_data(virq, mpic);
 	set_irq_chip_and_handler(virq, chip, handle_fasteoi_irq);
@@ -904,8 +919,8 @@
 		
 		/* do senses munging */
 		if (mpic->senses && i < mpic->senses_count)
-			vecpri = mpic_flags_to_vecpri(mpic->senses[i],
-						      &level);
+			vecpri |= mpic_flags_to_vecpri(mpic->senses[i],
+						       &level);
 		else
 			vecpri |= MPIC_VECPRI_SENSE_LEVEL;
 
@@ -955,14 +970,17 @@
 
 void __init mpic_set_serial_int(struct mpic *mpic, int enable)
 {
+	unsigned long flags;
 	u32 v;
 
+	spin_lock_irqsave(&mpic_lock, flags);
 	v = mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1);
 	if (enable)
 		v |= MPIC_GREG_GLOBAL_CONF_1_SIE;
 	else
 		v &= ~MPIC_GREG_GLOBAL_CONF_1_SIE;
 	mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1, v);
+	spin_unlock_irqrestore(&mpic_lock, flags);
 }
 
 void mpic_irq_set_priority(unsigned int irq, unsigned int pri)
  

^ permalink raw reply

* Re: [PATCH 13/20] [powerpc, video & agp] Constify & voidify get_property()
From: Paul Mackerras @ 2006-07-05  4:56 UTC (permalink / raw)
  To: Dave Jones; +Cc: linuxppc-dev, davej
In-Reply-To: <20060704190054.GA20952@redhat.com>

Dave Jones writes:

> I assume this stuff is going in through the ppc tree?

Yes, I'll take care of it.  Once Linus releases -rc1 I'll start
pushing the for-2.6.19 patches (including these) to the master branch
of the powerpc.git tree.

Paul.

^ permalink raw reply

* [RFC/PATCH 2/2] Make crash.c work on 32-bit and 64-bit
From: Michael Ellerman @ 2006-07-05  4:39 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <1152074382.592260.383409859049.qpush@concordia>

To compile kexec on 32-bit we need a few more bits and pieces. Rather
than add empty definitions, we can make crash.c work on 32-bit, with
only a couple of kludges.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---

 arch/powerpc/kernel/Makefile           |    4 ++--
 arch/powerpc/kernel/crash.c            |   11 +++++++++++
 arch/powerpc/kernel/machine_kexec_64.c |    1 -
 arch/powerpc/kernel/traps.c            |    3 ---
 include/asm-powerpc/kexec.h            |    3 +--
 5 files changed, 14 insertions(+), 8 deletions(-)

Index: to-merge/arch/powerpc/kernel/Makefile
===================================================================
--- to-merge.orig/arch/powerpc/kernel/Makefile
+++ to-merge/arch/powerpc/kernel/Makefile
@@ -67,9 +67,9 @@ pci64-$(CONFIG_PPC64)		+= pci_64.o pci_d
 				   pci_direct_iommu.o iomap.o
 pci32-$(CONFIG_PPC32)		:= pci_32.o
 obj-$(CONFIG_PCI)		+= $(pci64-y) $(pci32-y)
-kexec-$(CONFIG_PPC64)		:= machine_kexec_64.o crash.o
+kexec-$(CONFIG_PPC64)		:= machine_kexec_64.o
 kexec-$(CONFIG_PPC32)		:= machine_kexec_32.o
-obj-$(CONFIG_KEXEC)		+= machine_kexec.o $(kexec-y)
+obj-$(CONFIG_KEXEC)		+= machine_kexec.o crash.o $(kexec-y)
 
 ifeq ($(CONFIG_PPC_ISERIES),y)
 $(obj)/head_64.o: $(obj)/lparmap.s
Index: to-merge/arch/powerpc/kernel/crash.c
===================================================================
--- to-merge.orig/arch/powerpc/kernel/crash.c
+++ to-merge/arch/powerpc/kernel/crash.c
@@ -44,6 +44,7 @@
 /* This keeps a track of which one is crashing cpu. */
 int crashing_cpu = -1;
 static cpumask_t cpus_in_crash = CPU_MASK_NONE;
+cpumask_t cpus_in_sr = CPU_MASK_NONE;
 
 static u32 *append_elf_note(u32 *buf, char *name, unsigned type, void *data,
 							       size_t data_len)
@@ -139,7 +140,13 @@ void crash_ipi_callback(struct pt_regs *
 
 	if (ppc_md.kexec_cpu_down)
 		ppc_md.kexec_cpu_down(1, 1);
+
+#ifdef CONFIG_PPC64
 	kexec_smp_wait();
+#else
+	for (;;);	/* FIXME */
+#endif
+
 	/* NOTREACHED */
 }
 
@@ -255,7 +262,11 @@ static void crash_kexec_prepare_cpus(int
 	 *
 	 * do this if kexec in setup.c ?
 	 */
+#ifdef CONFIG_PPC64
 	smp_release_cpus();
+#else
+	/* FIXME */
+#endif
 }
 
 void crash_kexec_secondary(struct pt_regs *regs)
Index: to-merge/arch/powerpc/kernel/machine_kexec_64.c
===================================================================
--- to-merge.orig/arch/powerpc/kernel/machine_kexec_64.c
+++ to-merge/arch/powerpc/kernel/machine_kexec_64.c
@@ -10,7 +10,6 @@
  */
 
 
-#include <linux/cpumask.h>
 #include <linux/kexec.h>
 #include <linux/smp.h>
 #include <linux/thread_info.h>
Index: to-merge/arch/powerpc/kernel/traps.c
===================================================================
--- to-merge.orig/arch/powerpc/kernel/traps.c
+++ to-merge/arch/powerpc/kernel/traps.c
@@ -55,9 +55,6 @@
 
 #ifdef CONFIG_PPC64	/* XXX */
 #define _IO_BASE	pci_io_base
-#ifdef CONFIG_KEXEC
-cpumask_t cpus_in_sr = CPU_MASK_NONE;
-#endif
 #endif
 
 #ifdef CONFIG_DEBUGGER
Index: to-merge/include/asm-powerpc/kexec.h
===================================================================
--- to-merge.orig/include/asm-powerpc/kexec.h
+++ to-merge/include/asm-powerpc/kexec.h
@@ -32,6 +32,7 @@
 #endif
 
 #ifndef __ASSEMBLY__
+#include <linux/cpumask.h>
 
 #ifdef CONFIG_KEXEC
 
@@ -109,7 +110,6 @@ static inline void crash_setup_regs(stru
 
 #define MAX_NOTE_BYTES 1024
 
-#ifdef __powerpc64__
 extern void kexec_smp_wait(void);	/* get and clear naca physid, wait for
 					  master to copy new code to 0 */
 extern int crashing_cpu;
@@ -119,7 +119,6 @@ static inline int kexec_sr_activated(int
 {
 	return cpu_isset(cpu,cpus_in_sr);
 }
-#endif /* __powerpc64 __ */
 
 struct kimage;
 struct pt_regs;

^ permalink raw reply

* [RFC/PATCH 1/2] Move some kexec logic into machine_kexec.c
From: Michael Ellerman @ 2006-07-05  4:39 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev

We're missing a few functions for kexec to compile on 32-bit. There's
nothing really 64-bit specific about the 64-bit versions, so make them
generic rather than adding empty definitions for 32-bit.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---

 arch/powerpc/kernel/machine_kexec.c    |   56 +++++++++++++++++++++++++++++++++
 arch/powerpc/kernel/machine_kexec_64.c |   56 ---------------------------------
 2 files changed, 56 insertions(+), 56 deletions(-)

Index: to-merge/arch/powerpc/kernel/machine_kexec.c
===================================================================
--- to-merge.orig/arch/powerpc/kernel/machine_kexec.c
+++ to-merge/arch/powerpc/kernel/machine_kexec.c
@@ -13,6 +13,7 @@
 #include <linux/reboot.h>
 #include <linux/threads.h>
 #include <asm/machdep.h>
+#include <asm/lmb.h>
 
 void machine_crash_shutdown(struct pt_regs *regs)
 {
@@ -59,3 +60,58 @@ NORET_TYPE void machine_kexec(struct kim
 	}
 	for(;;);
 }
+
+static int __init early_parse_crashk(char *p)
+{
+	unsigned long size;
+
+	if (!p)
+		return 1;
+
+	size = memparse(p, &p);
+
+	if (*p == '@')
+		crashk_res.start = memparse(p + 1, &p);
+	else
+		crashk_res.start = KDUMP_KERNELBASE;
+
+	crashk_res.end = crashk_res.start + size - 1;
+
+	return 0;
+}
+early_param("crashkernel", early_parse_crashk);
+
+void __init reserve_crashkernel(void)
+{
+	unsigned long size;
+
+	if (crashk_res.start == 0)
+		return;
+
+	/* We might have got these values via the command line or the
+	 * device tree, either way sanitise them now. */
+
+	size = crashk_res.end - crashk_res.start + 1;
+
+	if (crashk_res.start != KDUMP_KERNELBASE)
+		printk("Crash kernel location must be 0x%x\n",
+				KDUMP_KERNELBASE);
+
+	crashk_res.start = KDUMP_KERNELBASE;
+	size = PAGE_ALIGN(size);
+	crashk_res.end = crashk_res.start + size - 1;
+
+	/* Crash kernel trumps memory limit */
+	if (memory_limit && memory_limit <= crashk_res.end) {
+		memory_limit = crashk_res.end + 1;
+		printk("Adjusted memory limit for crashkernel, now 0x%lx\n",
+				memory_limit);
+	}
+
+	lmb_reserve(crashk_res.start, size);
+}
+
+int overlaps_crashkernel(unsigned long start, unsigned long size)
+{
+	return (start + size) > crashk_res.start && start <= crashk_res.end;
+}
Index: to-merge/arch/powerpc/kernel/machine_kexec_64.c
===================================================================
--- to-merge.orig/arch/powerpc/kernel/machine_kexec_64.c
+++ to-merge/arch/powerpc/kernel/machine_kexec_64.c
@@ -21,7 +21,6 @@
 #include <asm/machdep.h>
 #include <asm/cacheflush.h>
 #include <asm/paca.h>
-#include <asm/lmb.h>
 #include <asm/mmu.h>
 #include <asm/sections.h>	/* _end */
 #include <asm/prom.h>
@@ -385,58 +384,3 @@ static int __init kexec_setup(void)
 	return 0;
 }
 __initcall(kexec_setup);
-
-static int __init early_parse_crashk(char *p)
-{
-	unsigned long size;
-
-	if (!p)
-		return 1;
-
-	size = memparse(p, &p);
-
-	if (*p == '@')
-		crashk_res.start = memparse(p + 1, &p);
-	else
-		crashk_res.start = KDUMP_KERNELBASE;
-
-	crashk_res.end = crashk_res.start + size - 1;
-
-	return 0;
-}
-early_param("crashkernel", early_parse_crashk);
-
-void __init reserve_crashkernel(void)
-{
-	unsigned long size;
-
-	if (crashk_res.start == 0)
-		return;
-
-	/* We might have got these values via the command line or the
-	 * device tree, either way sanitise them now. */
-
-	size = crashk_res.end - crashk_res.start + 1;
-
-	if (crashk_res.start != KDUMP_KERNELBASE)
-		printk("Crash kernel location must be 0x%x\n",
-				KDUMP_KERNELBASE);
-
-	crashk_res.start = KDUMP_KERNELBASE;
-	size = PAGE_ALIGN(size);
-	crashk_res.end = crashk_res.start + size - 1;
-
-	/* Crash kernel trumps memory limit */
-	if (memory_limit && memory_limit <= crashk_res.end) {
-		memory_limit = crashk_res.end + 1;
-		printk("Adjusted memory limit for crashkernel, now 0x%lx\n",
-				memory_limit);
-	}
-
-	lmb_reserve(crashk_res.start, size);
-}
-
-int overlaps_crashkernel(unsigned long start, unsigned long size)
-{
-	return (start + size) > crashk_res.start && start <= crashk_res.end;
-}

^ permalink raw reply

* RE: Linux 2.6.x  :  cpm_dpalloc alignment bug perhaps not fully r esolved
From: Li Yang-r58472 @ 2006-07-05  2:32 UTC (permalink / raw)
  To: Laurent Lagrange, pantelis; +Cc: linuxppc-embedded

Did you apply the alignment patch too?  AFAIK, the problem is never fixed in 
mainstream trees.

Best Regards,
Leo
> -----Original Message-----
> From: linuxppc-embedded-bounces+leoli=freescale.com@ozlabs.org
> [mailto:linuxppc-embedded-bounces+leoli=freescale.com@ozlabs.org] On Behalf
> Of Laurent Lagrange
> Sent: Tuesday, July 04, 2006 11:37 PM
> To: pantelis@embeddedalley.com
> Cc: linuxppc-embedded@ozlabs.org
> Subject: Linux 2.6.x : cpm_dpalloc alignment bug perhaps not fully resolved
> 
> 
> Hello Pantelis,
> 
> Few months ago (25 January 2006), I sent a mail about an alignment bug in
> cpm_dpalloc.
> I applied and verified the provided patch. I was very satisfied with the
> result.
> 
> Today I port a driver from Linux 2.4 to Linux 2.6 and I have strange
> results.
> 
> The driver allocates rx and tx bds (8 bytes aligned) in the module_init for
> 4 SCC ports.
> That is always right. Then one port is opened by an application and a user
> configuration
> is set via an ioctl (set_conf).
> 
> This ioctl first frees the old bds :
> 	cpm_dpfree(chan->rx_bd_offset);
> 	cpm_dpfree(chan->tx_bd_offset);
> then allocates the new ones :
> 	chan->rx_bd_offset = cpm_dpalloc(sizeof(cbd_t) * chan->conf.rx_bufnbr,
> 8);
> 	chan->tx_bd_offset = cpm_dpalloc(sizeof(cbd_t) * chan->conf.tx_bufnbr,
> 8);
> with rx_bufnbr == 8 and tx_bufnbr == 2
> 
> module_init
> SCC1 rx_bd_offset=160
> SCC1 tx_bd_offset=1a8
> SCC2 rx_bd_offset=1c0
> SCC2 tx_bd_offset=208
> SCC3 rx_bd_offset=220
> SCC3 tx_bd_offset=260
> SCC4 rx_bd_offset=278
> SCC4 tx_bd_offset=2c0
> set_conf
> SCC1 rx_bd_offset=160
> SCC1 tx_bd_offset=1a4	-> ???
> 
> module_init
> SCC1 rx_bd_offset=160
> SCC1 tx_bd_offset=1a8
> SCC2 rx_bd_offset=1c0
> SCC2 tx_bd_offset=208
> SCC3 rx_bd_offset=220
> SCC3 tx_bd_offset=260
> SCC4 rx_bd_offset=278
> SCC4 tx_bd_offset=2c0
> set_conf
> SCC2 rx_bd_offset=1c0
> SCC2 tx_bd_offset=202	-> ???
> 
> module_init
> SCC1 rx_bd_offset=160
> SCC1 tx_bd_offset=1a8
> SCC2 rx_bd_offset=1c0
> SCC2 tx_bd_offset=208
> SCC3 rx_bd_offset=220
> SCC3 tx_bd_offset=260
> SCC4 rx_bd_offset=278
> SCC4 tx_bd_offset=2c0
> set_conf
> SCC3 rx_bd_offset=220
> SCC3 tx_bd_offset=260	-> ok
> 
> module_init
> SCC1 rx_bd_offset=160
> SCC1 tx_bd_offset=1a8
> SCC2 rx_bd_offset=1c0
> SCC2 tx_bd_offset=208
> SCC3 rx_bd_offset=220
> SCC3 tx_bd_offset=260
> SCC4 rx_bd_offset=278
> SCC4 tx_bd_offset=2c0
> set_conf
> SCC4 rx_bd_offset=278
> SCC4 tx_bd_offset=2c0	-> ok
> 
> WARNING : if I only uses the SCC1 port without allocating bds for the other
> ports,
> I can free and reallocate the bds for the SCC1 port as many times I want.
> 
> module_init
> SCC1 rx_bd_offset=160
> SCC1 tx_bd_offset=1a8
> set_conf
> SCC1 rx_bd_offset=160
> SCC1 tx_bd_offset=1a8	-> ok
> 
> Really, I don't understand how this can arise.
> Any idea ?
> 
> Thanks
> Laurent
> 
> 
> 
> 
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded

^ permalink raw reply

* Re: [PATCH 3/20] [powerpc] Remove linux,pci-domain properties
From: Jeremy Kerr @ 2006-07-04 23:22 UTC (permalink / raw)
  To: Milton Miller; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <e53c7a64d7260d56983e22360cb5dd5a@bga.com>

Milton,

> Without looking at the mentioned utilities, DLPAR and PCI Hotplug get
> a location code, so I'm hoping that the pci slot name is identified
> by that.  Is lsvpd scanning?  Or does it scan sysfs first and
> /proc/device-tree secondarly?

Yes, lsvpd scans sysfs first, then uses devspec to refer to the device 
tree. and AFAICT, the slot id can't be extracted from the location 
code.

So you're saying that the linux,pci-domain property is still in use, 
right? If so, I'll do up a patch to fix add_linux_pci_domain rather 
than removing it.

Cheers,


Jeremy

^ permalink raw reply


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