Skip to contentSkip to conversation

PS3: Rename IPI symbols

PATCH In review Geoff Levand 13 participants 59 messages Jun 6, 2007 – Jun 25, 2007 1 message not in the archive

Subsystems (7)
lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): [email protected]

#1 lore raw

PATCH 1/18 Cell: Add spu shutdown method

Add a shutdown method to spu_sysdev_class to allow proper spu resource cleanup on system shutdown. This is needed to support kexec on the PS3 platform.

---
 arch/powerpc/platforms/cell/spu_base.c |   12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)
arch/powerpc/platforms/cell/spu_base.c +11 -1
@@ -462,8 +462,18 @@ void spu_free(struct spu *spu)
 }
 EXPORT_SYMBOL_GPL(spu_free);
 
+static int spu_shutdown(struct sys_device *sysdev)
+{
+	struct spu *spu = container_of(sysdev, struct spu, sysdev);
+
+	spu_free_irqs(spu);
+	spu_destroy_spu(spu);
+	return 0;
+}
+
 struct sysdev_class spu_sysdev_class = {
-	set_kset_name("spu")
+	set_kset_name("spu"),
+	.shutdown = spu_shutdown,
 };
 
 int spu_add_sysdev_attr(struct sysdev_attribute *attr)
#2 lore raw

Re: [patch 01/18] Cell: Add spu shutdown method

Quoted 9 lines · Geoff Levand

Add a shutdown method to spu_sysdev_class to allow proper spu resource cleanup on system shutdown. This is needed to support kexec on the PS3 platform.

---
 arch/powerpc/platforms/cell/spu_base.c |   12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

André, does this interact with your kexec work at all?

cheers

Quoted 23 lines
arch/powerpc/platforms/cell/spu_base.c +11 -1
@@ -462,8 +462,18 @@ void spu_free(struct spu *spu)
 }
 EXPORT_SYMBOL_GPL(spu_free);
 
+static int spu_shutdown(struct sys_device *sysdev)
+{
+	struct spu *spu = container_of(sysdev, struct spu, sysdev);
+
+	spu_free_irqs(spu);
+	spu_destroy_spu(spu);
+	return 0;
+}
+
 struct sysdev_class spu_sysdev_class = {
-	set_kset_name("spu")
+	set_kset_name("spu"),
+	.shutdown = spu_shutdown,
 };
 
 int spu_add_sysdev_attr(struct sysdev_attribute *attr)
Signature · 8 lines
Michael Ellerman
OzLabs, IBM Australia Development Lab

wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)

We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person
#3 lore raw

Re: [patch 01/18] Cell: Add spu shutdown method

Quoted 5 lines · Michael Ellerman
Quoted 4 lines · Geoff Levand

Add a shutdown method to spu_sysdev_class to allow proper spu resource cleanup on system shutdown. This is needed to support kexec on the PS3 platform.

Quoted 7 lines
Quoted 5 lines
---
 arch/powerpc/platforms/cell/spu_base.c |   12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

André, does this interact with your kexec work at all?

No. My cell kexec patch is actually crash-specific, activated under default_machine_crash_shutdown. Geoff's ps3 kexec patches do not seem to affect this code path.

--
Andre Detsch

#4 lore raw

PATCH 2/18 PS3: Rename IPI symbols

In reply to a message not in the archive

Rename the PS3 static symbol virqs to ps3_ipi_virqs to aid in debugging.

---
 arch/powerpc/platforms/ps3/smp.c |   14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)
arch/powerpc/platforms/ps3/smp.c +7 -7
@@ -39,11 +39,11 @@ static irqreturn_t ipi_function_handler(
 }
 
 /**
-  * virqs - a per cpu array of virqs for ipi use
+  * ps3_ipi_virqs - a per cpu array of virqs for ipi use
   */
 
 #define MSG_COUNT 4
-static DEFINE_PER_CPU(unsigned int, virqs[MSG_COUNT]);
+static DEFINE_PER_CPU(unsigned int, ps3_ipi_virqs[MSG_COUNT]);
 
 static const char *names[MSG_COUNT] = {
 	"ipi call",
@@ -62,7 +62,7 @@ static void do_message_pass(int target, 
 		return;
 	}
 
-	virq = per_cpu(virqs, target)[msg];
+	virq = per_cpu(ps3_ipi_virqs, target)[msg];
 	result = ps3_send_event_locally(virq);
 
 	if (result)
@@ -94,13 +94,13 @@ static int ps3_smp_probe(void)
 static void __init ps3_smp_setup_cpu(int cpu)
 {
 	int result;
-	unsigned int *virqs = per_cpu(virqs, cpu);
+	unsigned int *virqs = per_cpu(ps3_ipi_virqs, cpu);
 	int i;
 
 	DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu);
 
 	/*
-	 * Check assumptions on virqs[] indexing. If this
+	 * Check assumptions on ps3_ipi_virqs[] indexing. If this
 	 * check fails, then a different mapping of PPC_MSG_
 	 * to index needs to be setup.
 	 */
@@ -132,13 +132,13 @@ static void __init ps3_smp_setup_cpu(int
 
 void ps3_smp_cleanup_cpu(int cpu)
 {
-	unsigned int *virqs = per_cpu(virqs, cpu);
+	unsigned int *virqs = per_cpu(ps3_ipi_virqs, cpu);
 	int i;
 
 	DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu);
 
 	for (i = 0; i < MSG_COUNT; i++) {
-		free_irq(virqs[i], (void*)(long)i);
+		/* Can't call free_irq from interrupt context. */
 		ps3_event_receive_port_destroy(virqs[i]);
 		virqs[i] = NO_IRQ;
 	}
#5 lore raw

arch/powerpc/platforms/ps3/smp.c static void __init ps3_smp_setup_cpu(int · line 141

Quoted 9 lines · On Tue, 05 Jun 2007 19:59:25 -0700 Geoff Levand <[email protected]>…

Rename the PS3 static symbol virqs to ps3_ipi_virqs to aid in debugging.

arch/powerpc/platforms/ps3/smp.c +1 -1
 	for (i = 0; i < MSG_COUNT; i++) {
-		free_irq(virqs[i], (void*)(long)i);
+		/* Can't call free_irq from interrupt context. */

This change is probably worth a mention in the change log - it looks like a bug fix.

Signature · 3 lines
Cheers,
Stephen Rothwell                    [email protected]
http://www.canb.auug.org.au/~sfr/
#6 lore raw
Quoted 5 lines · Stephen Rothwell
Quoted 4 lines · On Tue, 05 Jun 2007 19:59:25 -0700 Geoff Levand <[email protected]>…

Rename the PS3 static symbol virqs to ps3_ipi_virqs to aid in debugging.

Quoted 8 lines

arch/powerpc/platforms/ps3/smp.c static void __init ps3_smp_setup_cpu(int · line 141

Quoted 5 lines
arch/powerpc/platforms/ps3/smp.c +1 -1
 	for (i = 0; i < MSG_COUNT; i++) {
-		free_irq(virqs[i], (void*)(long)i);
+		/* Can't call free_irq from interrupt context. */

This change is probably worth a mention in the change log - it looks like a bug fix.

Does the free_irq call (being removed here) need to be added back in somewhere else?

-Will

Quoted 4 lines

_______________________________________________
Linuxppc-dev mailing list
[email protected]
https://ozlabs.org/mailman/listinfo/linuxppc-dev

#7 lore raw
Quoted 16 lines · Will Schmidt
Quoted 5 lines · Stephen Rothwell
Quoted 4 lines · On Tue, 05 Jun 2007 19:59:25 -0700 Geoff Levand <[email protected]>…

Rename the PS3 static symbol virqs to ps3_ipi_virqs to aid in debugging.

Quoted 8 lines

arch/powerpc/platforms/ps3/smp.c static void __init ps3_smp_setup_cpu(int · line 141

Quoted 5 lines
arch/powerpc/platforms/ps3/smp.c +1 -1
 	for (i = 0; i < MSG_COUNT; i++) {
-		free_irq(virqs[i], (void*)(long)i);
+		/* Can't call free_irq from interrupt context. */

This change is probably worth a mention in the change log - it looks like a bug fix.

Quoted 2 lines

Does the free_irq call (being removed here) need to be added back in somewhere else?

No, the kernel is kexecing, so it is not needed.

-Geoff

#8 lore raw
In reply to Stephen Rothwell
Quoted 5 lines · Stephen Rothwell
Quoted 4 lines · On Tue, 05 Jun 2007 19:59:25 -0700 Geoff Levand <[email protected]>…

Rename the PS3 static symbol virqs to ps3_ipi_virqs to aid in debugging.

Quoted 8 lines

arch/powerpc/platforms/ps3/smp.c static void __init ps3_smp_setup_cpu(int · line 141

Quoted 5 lines
arch/powerpc/platforms/ps3/smp.c +1 -1
 	for (i = 0; i < MSG_COUNT; i++) {
-		free_irq(virqs[i], (void*)(long)i);
+		/* Can't call free_irq from interrupt context. */

This change is probably worth a mention in the change log - it looks like a bug fix.

That leaked into this patch from my kexec cleanups. I'll move it out to where it belongs.

-Geoff

#9 lore raw

PATCH 3/18 PS3: Use __maybe_unused

In reply to a message not in the archive

Change the PS3 debug routines from using the GCC specific '__attribute__ ((unused))' to the preprocessor macro __maybe_unused.

---
 arch/powerpc/platforms/ps3/interrupt.c |    4 ++--
 arch/powerpc/platforms/ps3/time.c      |    2 +-
 drivers/ps3/vuart.c                    |    4 ++--
 3 files changed, 5 insertions(+), 5 deletions(-)
arch/powerpc/platforms/ps3/interrupt.c +2 -2
@@ -533,7 +533,7 @@ static void _dump_64_bmp(const char *hea
 		*p & 0xffff);
 }
 
-static void __attribute__ ((unused)) _dump_256_bmp(const char *header,
+static void __maybe_unused _dump_256_bmp(const char *header,
 	const u64 *p, unsigned cpu, const char* func, int line)
 {
 	pr_debug("%s:%d: %s %u {%016lx:%016lx:%016lx:%016lx}\n",
@@ -552,7 +552,7 @@ static void _dump_bmp(struct ps3_private
 }
 
 #define dump_mask(_x) _dump_mask(_x, __func__, __LINE__)
-static void __attribute__ ((unused)) _dump_mask(struct ps3_private* pd,
+static void __maybe_unused _dump_mask(struct ps3_private* pd,
 	const char* func, int line)
 {
 	unsigned long flags;
arch/powerpc/platforms/ps3/time.c +1 -1
@@ -39,7 +39,7 @@ static void _dump_tm(const struct rtc_ti
 }
 
 #define dump_time(_a) _dump_time(_a, __func__, __LINE__)
-static void __attribute__ ((unused)) _dump_time(int time, const char* func,
+static void __maybe_unused _dump_time(int time, const char* func,
 	int line)
 {
 	struct rtc_time tm;
drivers/ps3/vuart.c +2 -2
@@ -83,7 +83,7 @@ struct ports_bmp {
 } __attribute__ ((aligned (32)));
 
 #define dump_ports_bmp(_b) _dump_ports_bmp(_b, __func__, __LINE__)
-static void __attribute__ ((unused)) _dump_ports_bmp(
+static void __maybe_unused _dump_ports_bmp(
 	const struct ports_bmp* bmp, const char* func, int line)
 {
 	pr_debug("%s:%d: ports_bmp: %016lxh\n", func, line, bmp->status);
@@ -107,7 +107,7 @@ static int ps3_vuart_match_id_to_port(en
 }
 
 #define dump_port_params(_b) _dump_port_params(_b, __func__, __LINE__)
-static void __attribute__ ((unused)) _dump_port_params(unsigned int port_number,
+static void __maybe_unused _dump_port_params(unsigned int port_number,
 	const char* func, int line)
 {
 #if defined(DEBUG)
#10 lore raw

Re: [patch 03/18] PS3: Use __maybe_unused

Quoted 3 lines · Geoff Levand

Change the PS3 debug routines from using the GCC specific '__attribute__ ((unused))' to the preprocessor macro __maybe_unused.

I'm confused. If DEBUG is defined then they're used, if it's not then they're not built.

cheers

Signature · 8 lines
Michael Ellerman
OzLabs, IBM Australia Development Lab

wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)

We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person
#11 lore raw

Re: [patch 03/18] PS3: Use __maybe_unused

Quoted 7 lines · Michael Ellerman
Quoted 3 lines · Geoff Levand

Change the PS3 debug routines from using the GCC specific '__attribute__ ((unused))' to the preprocessor macro __maybe_unused.

I'm confused. If DEBUG is defined then they're used, if it's not then they're not built.

Some are for actual 'debugging' use, calls to be added later, not just for verbose output. Others are for verbose output when DEBUG is defined. I have it setup so they are always built to do the syntax check, but removed by the optimizer when not used. I was planning to remove these routines sometime in the future, but want to keep them in until the code gets stable.

-Geoff

#12 lore raw

PATCH 4/18 PS3: Compare firmware version

In reply to a message not in the archive

Add a utiltiy routine ps3_compare_firmware_version() to compare system firmware versions. Uses the existing ps3_get_firmware_version() routine.

---
 arch/powerpc/platforms/ps3/setup.c |   32 ++++++++++++++++++++------------
 include/asm-powerpc/ps3.h          |    3 ++-
 2 files changed, 22 insertions(+), 13 deletions(-)
arch/powerpc/platforms/ps3/setup.c +20 -12
@@ -46,18 +46,26 @@
 static void smp_send_stop(void) {}
 #endif
 
-int ps3_get_firmware_version(union ps3_firmware_version *v)
+static union ps3_firmware_version ps3_firmware_version;
+
+void ps3_get_firmware_version(union ps3_firmware_version *v)
 {
-	int result = lv1_get_version_info(&v->raw);
+	*v = ps3_firmware_version;
+}
+EXPORT_SYMBOL_GPL(ps3_get_firmware_version);
 
-	if (result) {
-		v->raw = 0;
-		return -1;
-	}
+int ps3_compare_firmware_version(u16 major, u16 minor, u16 rev)
+{
+	union ps3_firmware_version x;
+
+	x.pad = 0;
+	x.major = major;
+	x.minor = minor;
+	x.rev = rev;
 
-	return result;
+	return (ps3_firmware_version.raw - x.raw);
 }
-EXPORT_SYMBOL_GPL(ps3_get_firmware_version);
+EXPORT_SYMBOL_GPL(ps3_compare_firmware_version);
 
 static void ps3_power_save(void)
 {
@@ -146,13 +154,13 @@ static int ps3_set_dabr(u64 dabr)
 
 static void __init ps3_setup_arch(void)
 {
-	union ps3_firmware_version v;
 
 	DBG(" -> %s:%d\n", __func__, __LINE__);
 
-	ps3_get_firmware_version(&v);
-	printk(KERN_INFO "PS3 firmware version %u.%u.%u\n", v.major, v.minor,
-		v.rev);
+	lv1_get_version_info(&ps3_firmware_version.raw);
+	printk(KERN_INFO "PS3 firmware version %u.%u.%u\n",
+	       ps3_firmware_version.major, ps3_firmware_version.minor,
+	       ps3_firmware_version.rev);
 
 	ps3_spu_set_platform();
 	ps3_map_htab();
include/asm-powerpc/ps3.h +2 -1
@@ -35,7 +35,8 @@ union ps3_firmware_version {
 	};
 };
 
-int ps3_get_firmware_version(union ps3_firmware_version *v);
+void ps3_get_firmware_version(union ps3_firmware_version *v);
+int ps3_compare_firmware_version(u16 major, u16 minor, u16 rev);
 
 /* 'Other OS' area */
 
#13 lore raw

PATCH 5/18 PS3: Fix sparse warnings

In reply to a message not in the archive

Fix some PS3 build warnings reported by `make C=1'. You need to install sparse:
git://git.kernel.org/pub/scm/devel/sparse/sparse.git

---
 arch/powerpc/platforms/ps3/os-area.c |    4 ++--
 arch/powerpc/platforms/ps3/spu.c     |    3 ++-
 2 files changed, 4 insertions(+), 3 deletions(-)
arch/powerpc/platforms/ps3/os-area.c +2 -2
@@ -133,7 +133,7 @@ struct saved_params {
 } static saved_params;
 
 #define dump_header(_a) _dump_header(_a, __func__, __LINE__)
-static void _dump_header(const struct os_area_header __iomem *h, const char* func,
+static void _dump_header(const struct os_area_header *h, const char* func,
 	int line)
 {
 	pr_debug("%s:%d: h.magic_num:         '%s'\n", func, line,
@@ -151,7 +151,7 @@ static void _dump_header(const struct os
 }
 
 #define dump_params(_a) _dump_params(_a, __func__, __LINE__)
-static void _dump_params(const struct os_area_params __iomem *p, const char* func,
+static void _dump_params(const struct os_area_params *p, const char* func,
 	int line)
 {
 	pr_debug("%s:%d: p.boot_flag:       %u\n", func, line, p->boot_flag);
arch/powerpc/platforms/ps3/spu.c +2 -1
@@ -190,7 +190,8 @@ static int __init setup_areas(struct spu
 		goto fail_ioremap;
 	}
 
-	spu->local_store = ioremap(spu->local_store_phys, LS_SIZE);
+	spu->local_store = (__force void *)ioremap(spu->local_store_phys,
+						   LS_SIZE);
 	if (!spu->local_store) {
 		pr_debug("%s:%d: ioremap local_store failed\n",
 			__func__, __LINE__);
#14 lore raw

Re: [patch 05/18] PS3: Fix sparse warnings

Quoted 1 line · Geoff Levand

-=A0=A0=A0=A0=A0=A0=A0spu->local_store =3D ioremap(spu->local_store_phys,=

LS_SIZE);

Quoted 1 line

+=A0=A0=A0=A0=A0=A0=A0spu->local_store =3D (__force void *)ioremap(spu->l=

ocal_store_phys,

Quoted 1 line

+=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=

=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 =A0 L= S_SIZE);

I haven't noticed this before, but it seems to be a preexisting bug:
You map the local_store as with the guarded page table bit set, which causes a performance degradation when accessing the memory from kernel space.

If you're lucky, your hypervisor knows this and will fix it up for you, but I would replace the ioremap call with an ioremap_flags(..., _PAGE_NO_CACHE); to be on the safe side.

If you want to measure the impact, I'd suggest timing a user space read() on the mem file of a running SPU context.

	Arnd <><
#15 lore raw

Re: [patch 05/18] PS3: Fix sparse warnings

Quoted 2 lines · Arnd Bergmann
Quoted 1 line · Geoff Levand

-=EF=BF=BD=EF=BF=BD=EF=BF=BD=EF=BF=BD=EF=BF=BD=EF=BF=BD=EF=BF=BDspu->l=

ocal_store =3D ioremap(spu->local_store_phys, LS_SIZE);

Quoted 1 line
Quoted 1 line

+=EF=BF=BD=EF=BF=BD=EF=BF=BD=EF=BF=BD=EF=BF=BD=EF=BF=BD=EF=BF=BDspu->l=

ocal_store =3D (__force void *)ioremap(spu->local_store_phys,

Quoted 1 line
Quoted 1 line

+=EF=BF=BD=EF=BF=BD=EF=BF=BD=EF=BF=BD=EF=BF=BD=EF=BF=BD=EF=BF=BD=EF=BF=

=BD=EF=BF=BD=EF=BF=BD=EF=BF=BD=EF=BF=BD=EF=BF=BD=EF=BF=BD=EF=BF=BD=EF=BF=BD= =EF=BF=BD=EF=BF=BD=EF=BF=BD=EF=BF=BD=EF=BF=BD=EF=BF=BD=EF=BF=BD=EF=BF=BD=EF= =BF=BD=EF=BF=BD=EF=BF=BD=EF=BF=BD=EF=BF=BD=EF=BF=BD=EF=BF=BD=EF=BF=BD=EF=BF= =BD=EF=BF=BD=EF=BF=BD=EF=BF=BD=EF=BF=BD=EF=BF=BD=EF=BF=BD=EF=BF=BD=EF=BF=BD= =EF=BF=BD=EF=BF=BD=EF=BF=BD=EF=BF=BD=EF=BF=BD=EF=BF=BD =EF=BF=BD LS_SIZE)= ;

Quoted 4 lines

=20
I haven't noticed this before, but it seems to be a preexisting bug:
You map the local_store as with the guarded page table bit set, which causes a performance degradation when accessing the memory from kernel

Quoted 8 lines

space.
=20
If you're lucky, your hypervisor knows this and will fix it up for you, but I would replace the ioremap call with an ioremap_flags(..., _PAGE_NO_CACHE); to be on the safe side. =20
If you want to measure the impact, I'd suggest timing a user space read() on the mem file of a running SPU context.

Hi Arnd,

I asked Noguchi-san to check the performance and below is his report and test program. I'll add the change into my patch set.

-Geoff

-------- Original Message --------
Subject: RE: [patch 05/18] PS3: Fix sparse warnings
Date: Thu, 7 Jun 2007 05:39:43 -0700
From: Noguchi, Masato <[email protected]>
To: Levand, Geoff <[email protected]>

<< A time to read a whole of LS by read system call >>

not patched: avg. 21053.7800 tick ( 263.831830 microseconds )
patched:     avg. 20809.2412 tick ( 260.767434 microseconds )

about 1% faster.=20
I think it's a valid difference. (not a measurement error.)

FYI,=20
The attached file is source code to measure it.
I run it 10000 times and calc an average.

#include <sys/types.h>

#include <sys/stat.h>

#include <sys/syscall.h>

#include <sys/mman.h>

#include <sys/wait.h>

#include <fcntl.h>

#include <unistd.h>

#include <stdio.h>

#include <signal.h>

#include <string.h>

#include <stdint.h>

#include <stdlib.h>

#include <pthread.h>

#define __NR_spe_run 278

#define __NR_spe_create 279

#define LS_SIZE 0x40000

#define SPENODE "/spu/stoplooptest"

#define MFTB(RA) __asm__ volatile("mftb %0":"=3Dr"(RA))

long long do_test(void)

{

	int spefd =3D -1, lsfd =3D -1;

	int npc, status;

	long long ret =3D -1;



	char buf[LS_SIZE];

	int n;

	uint32_t t1, t2;



	/* create context */

	spefd =3D syscall(__NR_spe_create, SPENODE, 0,

			S_IRUSR | S_IWUSR | S_IXUSR);

	if (spefd < 0) goto out;



	/* run once to assign physical spe */

	npc =3D 0;

	syscall(__NR_spe_run, spefd, &npc, &status);



	/* get /mem file descriptor */

	lsfd =3D open(SPENODE "/mem", O_RDWR,

		    S_IRUSR | S_IWUSR);

	if (lsfd < 0) goto out;



	/* read mem */

	MFTB(t1);

	if (read(lsfd, buf, LS_SIZE) !=3D LS_SIZE) {

		goto out;

	}

	MFTB(t2);



	ret =3D t2 - t1;

out:

	if ( lsfd >=3D 0 ) close(lsfd);

	if ( spefd >=3D 0 ) close(spefd);



	return ret;

}

int main(int argc, char *argv[])

{

	long long r;

	r =3D do_test();

	printf("%lld\n", r);



	return 0;

}

#16 lore raw

Re: [patch 05/18] PS3: Fix sparse warnings

Quoted 32 lines · Geoff Levand
Quoted 11 lines · Arnd Bergmann
Quoted 4 lines · Geoff Levand
-╴╴╴╴╴╴╴spu->local_store = ioremap(spu->local_store_phys, LS_SIZE);
+╴╴╴╴╴╴╴spu->local_store = (__force void 

*)ioremap(spu->local_store_phys, +╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴ ╴ LS_SIZE);

I haven't noticed this before, but it seems to be a preexisting bug:
You map the local_store as with the guarded page table bit set, which causes a performance degradation when accessing the memory from kernel space.

Quoted 6 lines

If you're lucky, your hypervisor knows this and will fix it up for you, but I would replace the ioremap call with an ioremap_flags(..., _PAGE_NO_CACHE); to be on the safe side.

If you want to measure the impact, I'd suggest timing a user space read() on the mem file of a running SPU context.

Hi Arnd,

I asked Noguchi-san to check the performance and below is his report and test program. I'll add the change into my patch set.

-Geoff

-------- Original Message --------
Subject: RE: [patch 05/18] PS3: Fix sparse warnings
Date: Thu, 7 Jun 2007 05:39:43 -0700
From: Noguchi, Masato <[email protected]>
To: Levand, Geoff <[email protected]>

Quoted 6 lines

<< A time to read a whole of LS by read system call >>

not patched: avg. 21053.7800 tick ( 263.831830 microseconds )
patched:     avg. 20809.2412 tick ( 260.767434 microseconds )

about 1% faster.
I think it's a valid difference. (not a measurement error.)

Let me correct above measurements and analysis.

My understanding is:

1) caching-inhibited loads are usually implemented as guarded. Thus, guarded property will not affect load performance.

2) caching-inhibited and non-guarded sequential stores are usually gathered (merged) in store buffer. Thus, guarded property will affect store performance much.

Therefor, we should measure write(2) performance to evaluate the impact of the patch.

Attached is a little modified test program based on Noguchi-san's one. It measures write(2) performance. Buffer area is 'pre-touched' to avoid VM overhead.

***** test results *****

before: 103903 [TB cycles] (best value out of 100 tries.)
after: 14277 [TB cycles] (best value out of 100 tries.)

-- Takao Shinohara

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>

#include <pthread.h>

#define __NR_spe_run 278
#define __NR_spe_create 279

#define LS_SIZE 0x40000

#define SPENODE "/spu/stoplooptest"

#define MFTB(RA) __asm__ volatile("mftb %0":"=r"(RA))

long long do_test(void)

{
	int spefd = -1, lsfd = -1;
	int npc, status;
	long long ret = -1;

	char buf[LS_SIZE];
	int n;
	uint32_t t1, t2;

	/* create context */
	spefd = syscall(__NR_spe_create, SPENODE, 0,
			S_IRUSR | S_IWUSR | S_IXUSR);
	if (spefd < 0) goto out;

	/* run once to assign physical spe */
	npc = 0;
	syscall(__NR_spe_run, spefd, &npc, &status);

	/* get /mem file descriptor */
	lsfd = open(SPENODE "/mem", O_RDWR,
		    S_IRUSR | S_IWUSR);
	if (lsfd < 0) goto out;

	/* make sure main memory is allocated and writable for 'buf' */
	memset(buf, 0, sizeof buf);

	/* write mem */
	MFTB(t1);
	if (write(lsfd, buf, LS_SIZE) != LS_SIZE) {
		goto out;
	}
	MFTB(t2);

	ret = t2 - t1;
 out:
	if ( lsfd >= 0 ) close(lsfd);
	if ( spefd >= 0 ) close(spefd);

	return ret;
}

int main(int argc, char *argv[])

{
	long long r;
	r = do_test();
	printf("%lld\n", r);

	return 0;
}
#17 lore raw

PATCH 6/18 PS3: Add support for HDMI RGB Full Range mode

In reply to a message not in the archive

Add support for HDMI RGB Full Range mode, which is available on system software 1.80 or newer.

---
 drivers/ps3/ps3av_cmd.c     |   16 ++++++++++++++++
 include/asm-powerpc/ps3av.h |   12 +++++++++---
 2 files changed, 25 insertions(+), 3 deletions(-)
drivers/ps3/ps3av_cmd.c +16 -0
@@ -143,6 +143,14 @@ static u32 ps3av_vid_video2av(int vid)
 	return PS3AV_CMD_AV_VID_480P;
 }
 
+static int ps3av_hdmi_range(void)
+{
+	if (ps3_compare_firmware_version(1, 8, 0) < 0)
+		return 0;
+	else
+		return 1; /* supported */
+}
+
 int ps3av_cmd_init(void)
 {
 	int res;
@@ -350,6 +358,10 @@ u32 ps3av_cmd_set_av_video_cs(void *p, u
 	/* should be same as video_mode.video_cs_out */
 	av_video_cs->av_cs_in = ps3av_cs_video2av(PS3AV_CMD_VIDEO_CS_RGB_8);
 	av_video_cs->bitlen_out = ps3av_cs_video2av_bitlen(cs_out);
+	if ((id & PS3AV_MODE_WHITE) && ps3av_hdmi_range())
+		av_video_cs->super_white = PS3AV_CMD_AV_SUPER_WHITE_ON;
+	else /* default off */
+		av_video_cs->super_white = PS3AV_CMD_AV_SUPER_WHITE_OFF;
 	av_video_cs->aspect = aspect;
 	if (id & PS3AV_MODE_DITHER) {
 		av_video_cs->dither = PS3AV_CMD_AV_DITHER_ON
@@ -392,6 +404,10 @@ u32 ps3av_cmd_set_video_mode(void *p, u3
 	video_mode->pitch = video_mode->width * 4;	/* line_length */
 	video_mode->video_out_format = PS3AV_CMD_VIDEO_OUT_FORMAT_RGB_12BIT;
 	video_mode->video_format = ps3av_video_fmt_table[video_fmt].format;
+	if ((id & PS3AV_MODE_COLOR) && ps3av_hdmi_range())
+		video_mode->video_cl_cnv = PS3AV_CMD_VIDEO_CL_CNV_DISABLE_LUT;
+	else /* default enable */
+		video_mode->video_cl_cnv = PS3AV_CMD_VIDEO_CL_CNV_ENABLE_LUT;
 	video_mode->video_order = ps3av_video_fmt_table[video_fmt].order;
 
 	pr_debug("%s: video_mode:vid:%x width:%d height:%d pitch:%d out_format:%d format:%x order:%x\n",
include/asm-powerpc/ps3av.h +9 -3
@@ -159,6 +159,9 @@
 #define PS3AV_CMD_VIDEO_FMT_X8R8G8B8			0x0000
 /* video_out_format */
 #define PS3AV_CMD_VIDEO_OUT_FORMAT_RGB_12BIT		0x0000
+/* video_cl_cnv */
+#define PS3AV_CMD_VIDEO_CL_CNV_ENABLE_LUT		0x0000
+#define PS3AV_CMD_VIDEO_CL_CNV_DISABLE_LUT		0x0010
 /* video_sync */
 #define PS3AV_CMD_VIDEO_SYNC_VSYNC			0x0001
 #define PS3AV_CMD_VIDEO_SYNC_CSYNC			0x0004
@@ -311,6 +314,8 @@
 #define PS3AV_MODE_MASK				0x000F
 #define PS3AV_MODE_HDCP_OFF			0x1000	/* Retail PS3 product doesn't support this */
 #define PS3AV_MODE_DITHER			0x0800
+#define PS3AV_MODE_COLOR			0x0400
+#define PS3AV_MODE_WHITE			0x0200
 #define PS3AV_MODE_FULL				0x0080
 #define PS3AV_MODE_DVI				0x0040
 #define PS3AV_MODE_RGB				0x0020
@@ -529,9 +534,9 @@ struct ps3av_pkt_video_mode {
 	u32 video_out_format;	/* in: out format */
 	u32 video_format;	/* in: input frame buffer format */
 	u8 reserved3;
-	u8 reserved4;
+	u8 video_cl_cnv;	/* in: color conversion */
 	u16 video_order;	/* in: input RGB order */
-	u32 reserved5;
+	u32 reserved4;
 };
 
 /* video: format */
@@ -539,7 +544,8 @@ struct ps3av_pkt_video_format {
 	struct ps3av_send_hdr send_hdr;
 	u32 video_head;		/* in: head */
 	u32 video_format;	/* in: frame buffer format */
-	u16 reserved;
+	u8 reserved;
+	u8 video_cl_cnv;	/* in: color conversion */
 	u16 video_order;	/* in: input RGB order */
 };
 
#18 lore raw

PATCH 7/18 PS3: Make ps3av.h usable from user space

In reply to a message not in the archive

The user applications to manage the PS3 AV modes can use values defined in this header.

---
 include/asm-powerpc/Kbuild  |    1 +
 include/asm-powerpc/ps3av.h |    2 ++
 2 files changed, 3 insertions(+)
include/asm-powerpc/Kbuild +1 -0
@@ -34,6 +34,7 @@ unifdef-y += elf.h
 unifdef-y += nvram.h
 unifdef-y += param.h
 unifdef-y += posix_types.h
+unifdef-y += ps3av.h
 unifdef-y += ptrace.h
 unifdef-y += seccomp.h
 unifdef-y += signal.h
include/asm-powerpc/ps3av.h +2 -0
@@ -321,6 +321,7 @@
 #define PS3AV_MODE_RGB				0x0020
 
 
+#ifdef __KERNEL__
 /** command packet structure **/
 struct ps3av_send_hdr {
 	u16 version;
@@ -723,4 +724,5 @@ extern int ps3av_audio_mute(int);
 extern int ps3av_dev_open(void);
 extern int ps3av_dev_close(void);
 
+#endif /* __KERNEL__ */
 #endif	/* _ASM_POWERPC_PS3AV_H_ */
#19 lore raw

Re: [patch 07/18] PS3: Make ps3av.h usable from user space

Quoted 2 lines · Geoff Levand

The user applications to manage the PS3 AV modes can use values defined in this header.

NACK. First please don't introduce new unifdef-y headers but always separated them. Second I don't see any of the values actually used in a user<->kerne interface. If the application only happens to use the same values it should ship a copy of the header intead.

#20 lore raw

Re: [patch 07/18] PS3: Make ps3av.h usable from user space

Quoted 8 lines · Christoph Hellwig
Quoted 2 lines · Geoff Levand

The user applications to manage the PS3 AV modes can use values defined in this header.

NACK. First please don't introduce new unifdef-y headers but always separated them. Second I don't see any of the values actually used in a user<->kerne interface. If the application only happens to use the same values it should ship a copy of the header intead.

ps3videomode (from ps3-utils,
git://git.kernel.org/pub/scm/linux/kernel/git/geoff/ps3-utils.git) uses the PS3AV_MODE_* definitions for the PS3FB_IOCTL_[SG]ETMODE ioctls on /dev/fb0.

But it indeed just uses a few values, and ps3videomode.c already handles the case were <asm/ps3av.h> is not available, so I guess we can drop the export.

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE) [email protected] ------- The Corporate Village, Da Vincilaan 7-D1 Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

#21 lore raw

Re: [patch 07/18] PS3: Make ps3av.h usable from user space

In reply to Christoph Hellwig
Quoted 8 lines · Christoph Hellwig
Quoted 2 lines · Geoff Levand

The user applications to manage the PS3 AV modes can use values defined in this header.

NACK. First please don't introduce new unifdef-y headers but always separated them. Second I don't see any of the values actually used in a user<->kerne interface. If the application only happens to use the same values it should ship a copy of the header intead.

Yes, they are currently used with ioctl for video mode selection by the ps3videomode utility.

OK, you recommend having two headers one for the kernel and one for the application or library, then keeping them in sync. I think in some ways that is easier for the package user also, since there is no dependency on kernel headers. It does mean that the package definitions need to be kept up to date.

-Geoff

#22 lore raw

Re: [patch 07/18] PS3: Make ps3av.h usable from user space

Quoted 10 lines · Geoff Levand
Quoted 8 lines · Christoph Hellwig
Quoted 2 lines · Geoff Levand

The user applications to manage the PS3 AV modes can use values defined in this header.

NACK. First please don't introduce new unifdef-y headers but always separated them. Second I don't see any of the values actually used in a user<->kerne interface. If the application only happens to use the same values it should ship a copy of the header intead.

Quoted 8 lines

Yes, they are currently used with ioctl for video mode selection by the ps3videomode utility.

OK, you recommend having two headers one for the kernel and one for the application or library, then keeping them in sync. I think in some ways that is easier for the package user also, since there is no dependency on kernel headers. It does mean that the package definitions need to be kept up to date.

Now that we're actually using it for the ioctls it's fine to export it. But please use a separate header that contains just these bits instead of introducing more headers that need unifdefing.

#23 lore raw

PATCH 8/18 PS3: Kexec support

In reply to a message not in the archive

Fixup the core platform parts needed for kexec to work on the PS3.
- Setup ps3_hpte_clear correctly.
- Mask interrupts on irq removal.
- Release all hypervisor resources.

---
 arch/powerpc/platforms/ps3/htab.c      |   14 +-
 arch/powerpc/platforms/ps3/interrupt.c |  199 ++++++++++++++++++++-------------
 arch/powerpc/platforms/ps3/setup.c     |   29 ++--
 3 files changed, 147 insertions(+), 95 deletions(-)
arch/powerpc/platforms/ps3/htab.c +11 -3
@@ -234,10 +234,18 @@ static void ps3_hpte_invalidate(unsigned
 
 static void ps3_hpte_clear(void)
 {
-	/* Make sure to clean up the frame buffer device first */
-	ps3fb_cleanup();
+	int result;
 
-	lv1_unmap_htab(htab_addr);
+	DBG(" -> %s:%d\n", __func__, __LINE__);
+
+	result = lv1_unmap_htab(htab_addr);
+	BUG_ON(result);
+
+	ps3_mm_shutdown();
+
+	ps3_mm_vas_destroy();
+
+	DBG(" <- %s:%d\n", __func__, __LINE__);
 }
 
 void __init ps3_hpte_init(unsigned long htab_size)
arch/powerpc/platforms/ps3/interrupt.c +123 -76

283 lines not on this page · raw message

arch/powerpc/platforms/ps3/setup.c +13 -16
@@ -209,31 +209,28 @@ static int __init ps3_probe(void)
 #if defined(CONFIG_KEXEC)
 static void ps3_kexec_cpu_down(int crash_shutdown, int secondary)
 {
-	DBG(" -> %s:%d\n", __func__, __LINE__);
+	int result;
+	u64 ppe_id;
+	u64 thread_id = secondary ? 1 : 0;
+
+	DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, secondary);
+	ps3_smp_cleanup_cpu(thread_id);
+
+	lv1_get_logical_ppe_id(&ppe_id);
+	result = lv1_configure_irq_state_bitmap(ppe_id, secondary ? 0 : 1, 0);
 
-	if (secondary) {
-		int cpu;
-		for_each_online_cpu(cpu)
-			if (cpu)
-				ps3_smp_cleanup_cpu(cpu);
-	} else
-		ps3_smp_cleanup_cpu(0);
+	/* seems to fail on second call */
+	DBG("%s:%d: lv1_configure_irq_state_bitmap (%d) %s\n", __func__,
+		__LINE__, secondary, ps3_result(result));
 
 	DBG(" <- %s:%d\n", __func__, __LINE__);
 }
 
 static void ps3_machine_kexec(struct kimage *image)
 {
-	unsigned long ppe_id;
-
 	DBG(" -> %s:%d\n", __func__, __LINE__);
 
-	lv1_get_logical_ppe_id(&ppe_id);
-	lv1_configure_irq_state_bitmap(ppe_id, 0, 0);
-	ps3_mm_shutdown();
-	ps3_mm_vas_destroy();
-
-	default_machine_kexec(image);
+	default_machine_kexec(image); // needs ipi, never returns.
 
 	DBG(" <- %s:%d\n", __func__, __LINE__);
 }
#24 lore raw

Re: [patch 08/18] PS3: Kexec support

Quoted 4 lines · Geoff Levand

Fixup the core platform parts needed for kexec to work on the PS3.
- Setup ps3_hpte_clear correctly.
- Mask interrupts on irq removal.
- Release all hypervisor resources.

The irq changes might be kexec related, but it's a mess to review. You seem to moving a bunch of code around in the patch as well.

Quoted 19 lines
---
 arch/powerpc/platforms/ps3/htab.c      |   14 +-
 arch/powerpc/platforms/ps3/interrupt.c |  199 ++++++++++++++++++++-------------
 arch/powerpc/platforms/ps3/setup.c     |   29 ++--
 3 files changed, 147 insertions(+), 95 deletions(-)
arch/powerpc/platforms/ps3/htab.c +2 -3
@@ -234,10 +234,18 @@ static void ps3_hpte_invalidate(unsigned
 
 static void ps3_hpte_clear(void)
 {
-	/* Make sure to clean up the frame buffer device first */
-	ps3fb_cleanup();
+	int result;
 
-	lv1_unmap_htab(htab_addr);
+	DBG(" -> %s:%d\n", __func__, __LINE__);

arch/powerpc/platforms/ps3/htab.c static void ps3_hpte_invalidate(unsigned · line 249

Quoted 10 lines
arch/powerpc/platforms/ps3/htab.c +9 -0
+
+	result = lv1_unmap_htab(htab_addr);
+	BUG_ON(result);
+
+	ps3_mm_shutdown();
+
+	ps3_mm_vas_destroy();
+
+	DBG(" <- %s:%d\n", __func__, __LINE__);
 }

Do you really want to be calling DBG() here? Hmm, it looks like it doesn't actually do anything?

Quoted 26 lines
arch/powerpc/platforms/ps3/htab.c +0 -0
 void __init ps3_hpte_init(unsigned long htab_size)
arch/powerpc/platforms/ps3/interrupt.c +18 -0
@@ -91,6 +91,92 @@ struct ps3_private {
 static DEFINE_PER_CPU(struct ps3_private, ps3_private);
 
 /**
+ * ps3_chip_mask - Set an interrupt mask bit in ps3_bmp.
+ * @virq: The assigned Linux virq.
+ *
+ * Sets ps3_bmp.mask and calls lv1_did_update_interrupt_mask().
+ */
+
+static void ps3_chip_mask(unsigned int virq)
+{
+	struct ps3_private *pd = get_irq_chip_data(virq);
+	u64 bit = 0x8000000000000000UL >> virq;
+	u64 *p = &pd->bmp.mask;
+	u64 old;
+	unsigned long flags;
+
+	pr_debug("%s:%d: cpu %u, virq %d\n", __func__, __LINE__, pd->cpu, virq);
+
+	local_irq_save(flags);
+	asm volatile(

arch/powerpc/platforms/ps3/interrupt.c struct ps3_private { · line 121

Quoted 10 lines
arch/powerpc/platforms/ps3/interrupt.c +10 -0
+		     "1:	ldarx %0,0,%3\n"
+		     "andc	%0,%0,%2\n"
+		     "stdcx.	%0,0,%3\n"
+		     "bne-	1b"
+		     : "=&r" (old), "+m" (*p)
+		     : "r" (bit), "r" (p)
+		     : "cc" );
+
+	lv1_did_update_interrupt_mask(pd->node, pd->cpu);
+	local_irq_restore(flags);

How is this different from set_bit() ? (asm-powerpc/bitops.h)

ps. now that I see you're just moving this code around someone's probably already asked that question.

Quoted 295 lines
arch/powerpc/platforms/ps3/interrupt.c +93 -76
+/**
+ * ps3_chip_unmask - Clear an interrupt mask bit in ps3_bmp.
+ * @virq: The assigned Linux virq.
+ *
+ * Clears ps3_bmp.mask and calls lv1_did_update_interrupt_mask().
+ */
+
+static void ps3_chip_unmask(unsigned int virq)
+{
+	struct ps3_private *pd = get_irq_chip_data(virq);
+	u64 bit = 0x8000000000000000UL >> virq;
+	u64 *p = &pd->bmp.mask;
+	u64 old;
+	unsigned long flags;
+
+	pr_debug("%s:%d: cpu %u, virq %d\n", __func__, __LINE__, pd->cpu, virq);
+
+	local_irq_save(flags);
+	asm volatile(
+		     "1:	ldarx %0,0,%3\n"
+		     "or	%0,%0,%2\n"
+		     "stdcx.	%0,0,%3\n"
+		     "bne-	1b"
+		     : "=&r" (old), "+m" (*p)
+		     : "r" (bit), "r" (p)
+		     : "cc" );
+
+	lv1_did_update_interrupt_mask(pd->node, pd->cpu);
+	local_irq_restore(flags);
+}
+
+/**
+ * ps3_chip_eoi - HV end-of-interrupt.
+ * @virq: The assigned Linux virq.
+ *
+ * Calls lv1_end_of_interrupt_ext().
+ */
+
+static void ps3_chip_eoi(unsigned int virq)
+{
+	const struct ps3_private *pd = get_irq_chip_data(virq);
+	lv1_end_of_interrupt_ext(pd->node, pd->cpu, virq);
+}
+
+/**
+ * ps3_irq_chip - Represents the ps3_bmp as a Linux struct irq_chip.
+ */
+
+static struct irq_chip ps3_irq_chip = {
+	.typename = "ps3",
+	.mask = ps3_chip_mask,
+	.unmask = ps3_chip_unmask,
+	.eoi = ps3_chip_eoi,
+};
+
+/**
  * ps3_virq_setup - virq related setup.
  * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
  * serviced on.
@@ -134,6 +220,8 @@ int ps3_virq_setup(enum ps3_cpu_binding 
 		goto fail_set;
 	}
 
+	ps3_chip_mask(*virq);
+
 	return result;
 
 fail_set:
@@ -225,6 +313,8 @@ int ps3_irq_plug_destroy(unsigned int vi
 	pr_debug("%s:%d: node %lu, cpu %d, virq %u\n", __func__, __LINE__,
 		pd->node, pd->cpu, virq);
 
+	ps3_chip_mask(virq);
+
 	result = lv1_disconnect_irq_plug_ext(pd->node, pd->cpu, virq);
 
 	if (result)
@@ -282,7 +372,9 @@ int ps3_event_receive_port_destroy(unsig
 {
 	int result;
 
-	pr_debug(" -> %s:%d virq: %u\n", __func__, __LINE__, virq);
+	pr_debug(" -> %s:%d virq %u\n", __func__, __LINE__, virq);
+
+	ps3_chip_mask(virq);
 
 	result = lv1_destruct_event_receive_port(virq_to_hw(virq));
 
@@ -290,17 +382,13 @@ int ps3_event_receive_port_destroy(unsig
 		pr_debug("%s:%d: lv1_destruct_event_receive_port failed: %s\n",
 			__func__, __LINE__, ps3_result(result));
 
-	/* lv1_destruct_event_receive_port() destroys the IRQ plug,
-	 * so don't call ps3_irq_plug_destroy() here.
+	/* Can't call ps3_virq_destroy() here since ps3_smp_cleanup_cpu()
+	 * calls from interrupt context (smp_call_function).
 	 */
 
-	result = ps3_virq_destroy(virq);
-	BUG_ON(result);
-
 	pr_debug(" <- %s:%d\n", __func__, __LINE__);
 	return result;
 }
-EXPORT_SYMBOL_GPL(ps3_event_receive_port_destroy);
 
 int ps3_send_event_locally(unsigned int virq)
 {
@@ -372,6 +460,13 @@ int ps3_sb_event_receive_port_destroy(co
 	result = ps3_event_receive_port_destroy(virq);
 	BUG_ON(result);
 
+	/* ps3_event_receive_port_destroy() destroys the IRQ plug,
+	 * so don't call ps3_irq_plug_destroy() here.
+	 */
+
+	result = ps3_virq_destroy(virq);
+	BUG_ON(result);
+
 	pr_debug(" <- %s:%d\n", __func__, __LINE__);
 	return result;
 }
@@ -412,16 +507,23 @@ EXPORT_SYMBOL_GPL(ps3_io_irq_setup);
 int ps3_io_irq_destroy(unsigned int virq)
 {
 	int result;
+	unsigned long outlet = virq_to_hw(virq);
 
-	result = lv1_destruct_io_irq_outlet(virq_to_hw(virq));
+	ps3_chip_mask(virq);
 
-	if (result)
-		pr_debug("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n",
-			__func__, __LINE__, ps3_result(result));
+	/* lv1_destruct_io_irq_outlet() will destroy the IRQ plug,
+	 * so call ps3_irq_plug_destroy() first.
+	 */
 
 	result = ps3_irq_plug_destroy(virq);
 	BUG_ON(result);
 
+	result = lv1_destruct_io_irq_outlet(outlet);
+
+	if (result)
+		pr_debug("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n",
+			__func__, __LINE__, ps3_result(result));
+
 	return result;
 }
 EXPORT_SYMBOL_GPL(ps3_io_irq_destroy);
@@ -466,6 +568,7 @@ int ps3_vuart_irq_destroy(unsigned int v
 {
 	int result;
 
+	ps3_chip_mask(virq);
 	result = lv1_deconfigure_virtual_uart_irq();
 
 	if (result) {
@@ -514,9 +617,14 @@ int ps3_spe_irq_setup(enum ps3_cpu_bindi
 
 int ps3_spe_irq_destroy(unsigned int virq)
 {
-	int result = ps3_irq_plug_destroy(virq);
+	int result;
+
+	ps3_chip_mask(virq);
+
+	result = ps3_irq_plug_destroy(virq);
 	BUG_ON(result);
-	return 0;
+
+	return result;
 }
 
 
@@ -565,67 +673,6 @@ static void __maybe_unused _dump_mask(st
 static void dump_bmp(struct ps3_private* pd) {};
 #endif /* defined(DEBUG) */
 
-static void ps3_chip_mask(unsigned int virq)
-{
-	struct ps3_private *pd = get_irq_chip_data(virq);
-	u64 bit = 0x8000000000000000UL >> virq;
-	u64 *p = &pd->bmp.mask;
-	u64 old;
-	unsigned long flags;
-
-	pr_debug("%s:%d: cpu %u, virq %d\n", __func__, __LINE__, pd->cpu, virq);
-
-	local_irq_save(flags);
-	asm volatile(
-		     "1:	ldarx %0,0,%3\n"
-		     "andc	%0,%0,%2\n"
-		     "stdcx.	%0,0,%3\n"
-		     "bne-	1b"
-		     : "=&r" (old), "+m" (*p)
-		     : "r" (bit), "r" (p)
-		     : "cc" );
-
-	lv1_did_update_interrupt_mask(pd->node, pd->cpu);
-	local_irq_restore(flags);
-}
-
-static void ps3_chip_unmask(unsigned int virq)
-{
-	struct ps3_private *pd = get_irq_chip_data(virq);
-	u64 bit = 0x8000000000000000UL >> virq;
-	u64 *p = &pd->bmp.mask;
-	u64 old;
-	unsigned long flags;
-
-	pr_debug("%s:%d: cpu %u, virq %d\n", __func__, __LINE__, pd->cpu, virq);
-
-	local_irq_save(flags);
-	asm volatile(
-		     "1:	ldarx %0,0,%3\n"
-		     "or	%0,%0,%2\n"
-		     "stdcx.	%0,0,%3\n"
-		     "bne-	1b"
-		     : "=&r" (old), "+m" (*p)
-		     : "r" (bit), "r" (p)
-		     : "cc" );
-
-	lv1_did_update_interrupt_mask(pd->node, pd->cpu);
-	local_irq_restore(flags);
-}
-
-static void ps3_chip_eoi(unsigned int virq)
-{
-	const struct ps3_private *pd = get_irq_chip_data(virq);
-	lv1_end_of_interrupt_ext(pd->node, pd->cpu, virq);
-}
-
-static struct irq_chip irq_chip = {
-	.typename = "ps3",
-	.mask = ps3_chip_mask,
-	.unmask = ps3_chip_unmask,
-	.eoi = ps3_chip_eoi,
-};
-
 static void ps3_host_unmap(struct irq_host *h, unsigned int virq)
 {
 	set_irq_chip_data(virq, NULL);
@@ -637,7 +684,7 @@ static int ps3_host_map(struct irq_host 
 	pr_debug("%s:%d: hwirq %lu, virq %u\n", __func__, __LINE__, hwirq,
 		virq);
 
-	set_irq_chip_and_handler(virq, &irq_chip, handle_fasteoi_irq);
+	set_irq_chip_and_handler(virq, &ps3_irq_chip, handle_fasteoi_irq);
 
 	return 0;
 }
@@ -657,7 +704,7 @@ void __init ps3_register_ipi_debug_brk(u
 		cpu, virq, pd->bmp.ipi_debug_brk_mask);
 }
 
-unsigned int ps3_get_irq(void)
+static unsigned int ps3_get_irq(void)
 {
 	struct ps3_private *pd = &__get_cpu_var(ps3_private);
 	u64 x = (pd->bmp.status & pd->bmp.mask);
arch/powerpc/platforms/ps3/setup.c +12 -9
@@ -209,31 +209,28 @@ static int __init ps3_probe(void)
 #if defined(CONFIG_KEXEC)
 static void ps3_kexec_cpu_down(int crash_shutdown, int secondary)
 {
-	DBG(" -> %s:%d\n", __func__, __LINE__);
+	int result;
+	u64 ppe_id;
+	u64 thread_id = secondary ? 1 : 0;
+
+	DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, secondary);
+	ps3_smp_cleanup_cpu(thread_id);
+
+	lv1_get_logical_ppe_id(&ppe_id);
+	result = lv1_configure_irq_state_bitmap(ppe_id, secondary ? 0 : 1, 0);
 
-	if (secondary) {
-		int cpu;
-		for_each_online_cpu(cpu)
-			if (cpu)
-				ps3_smp_cleanup_cpu(cpu);
-	} else
-		ps3_smp_cleanup_cpu(0);
+	/* seems to fail on second call */
+	DBG("%s:%d: lv1_configure_irq_state_bitmap (%d) %s\n", __func__,
+		__LINE__, secondary, ps3_result(result));
 
 	DBG(" <- %s:%d\n", __func__, __LINE__);
 }
 
 static void ps3_machine_kexec(struct kimage *image)
 {
-	unsigned long ppe_id;

arch/powerpc/platforms/ps3/setup.c static int __init ps3_probe(void) · line 233

Quoted 10 lines
arch/powerpc/platforms/ps3/setup.c +1 -7
-
 	DBG(" -> %s:%d\n", __func__, __LINE__);
 
-	lv1_get_logical_ppe_id(&ppe_id);
-	lv1_configure_irq_state_bitmap(ppe_id, 0, 0);
-	ps3_mm_shutdown();
-	ps3_mm_vas_destroy();
-
-	default_machine_kexec(image);
+	default_machine_kexec(image); // needs ipi, never returns.

Just get rid of ps3_machine_kexec() and hook default_machine_kexec() directly into your ppc_md.

cheers

Signature · 8 lines
Michael Ellerman
OzLabs, IBM Australia Development Lab

wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)

We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person
#25 lore raw

Re: [patch 08/18] PS3: Kexec support

Quoted 8 lines · Michael Ellerman
Quoted 4 lines · Geoff Levand

Fixup the core platform parts needed for kexec to work on the PS3.
- Setup ps3_hpte_clear correctly.
- Mask interrupts on irq removal.
- Release all hypervisor resources.

The irq changes might be kexec related, but it's a mess to review. You seem to moving a bunch of code around in the patch as well.

Yes, I need to move the static chip_mask routines up so they would be defined before the irq setup/destroy routines.

Quoted 17 lines
Quoted 17 lines
---
 arch/powerpc/platforms/ps3/htab.c      |   14 +-
 arch/powerpc/platforms/ps3/interrupt.c |  199 ++++++++++++++++++++-------------
 arch/powerpc/platforms/ps3/setup.c     |   29 ++--
 3 files changed, 147 insertions(+), 95 deletions(-)
arch/powerpc/platforms/ps3/htab.c +1 -2
@@ -234,10 +234,18 @@ static void ps3_hpte_invalidate(unsigned
 
 static void ps3_hpte_clear(void)
 {
-	/* Make sure to clean up the frame buffer device first */
-	ps3fb_cleanup();
+	int result;
 
Quoted 15 lines

arch/powerpc/platforms/ps3/htab.c static void ps3_hpte_invalidate(unsigned · line 249

Quoted 12 lines
arch/powerpc/platforms/ps3/htab.c +10 -1
-	lv1_unmap_htab(htab_addr);
+	DBG(" -> %s:%d\n", __func__, __LINE__);
+
+	result = lv1_unmap_htab(htab_addr);
+	BUG_ON(result);
+
+	ps3_mm_shutdown();
+
+	ps3_mm_vas_destroy();
+
+	DBG(" <- %s:%d\n", __func__, __LINE__);
 }

Do you really want to be calling DBG() here? Hmm, it looks like it doesn't actually do anything?

Sure, it uses udbg_printf, and works OK.

Quoted 25 lines
Quoted 12 lines
arch/powerpc/platforms/ps3/htab.c +12 -0
+static void ps3_chip_mask(unsigned int virq)
+{
+	struct ps3_private *pd = get_irq_chip_data(virq);
+	u64 bit = 0x8000000000000000UL >> virq;
+	u64 *p = &pd->bmp.mask;
+	u64 old;
+	unsigned long flags;
+
+	pr_debug("%s:%d: cpu %u, virq %d\n", __func__, __LINE__, pd->cpu, virq);
+
+	local_irq_save(flags);
+	asm volatile(

arch/powerpc/platforms/ps3/htab.c static void ps3_hpte_invalidate(unsigned

Quoted 10 lines
arch/powerpc/platforms/ps3/htab.c +10 -0
+		     "1:	ldarx %0,0,%3\n"
+		     "andc	%0,%0,%2\n"
+		     "stdcx.	%0,0,%3\n"
+		     "bne-	1b"
+		     : "=&r" (old), "+m" (*p)
+		     : "r" (bit), "r" (p)
+		     : "cc" );
+
+	lv1_did_update_interrupt_mask(pd->node, pd->cpu);
+	local_irq_restore(flags);

How is this different from set_bit() ? (asm-powerpc/bitops.h)

Quoted 2 lines

ps. now that I see you're just moving this code around someone's probably already asked that question.

This was contributed by Ben H as the fastest way. I think the reason was that we could minimize the time between local_irq_save and local_irq_restore?

Quoted 6 lines
Quoted 6 lines

static void ps3_machine_kexec(struct kimage *image) {

arch/powerpc/platforms/ps3/htab.c +0 -2
-	unsigned long ppe_id;
-
 	DBG(" -> %s:%d\n", __func__, __LINE__);
Quoted 10 lines

arch/powerpc/platforms/ps3/htab.c

Quoted 7 lines
arch/powerpc/platforms/ps3/htab.c +1 -6
-	lv1_get_logical_ppe_id(&ppe_id);
-	lv1_configure_irq_state_bitmap(ppe_id, 0, 0);
-	ps3_mm_shutdown();
-	ps3_mm_vas_destroy();
-
-	default_machine_kexec(image);
+	default_machine_kexec(image); // needs ipi, never returns.

Just get rid of ps3_machine_kexec() and hook default_machine_kexec() directly into your ppc_md.

Right, just a debugging leftover...

-Geoff

#26 lore raw

Re: [patch 08/18] PS3: Kexec support

Hi Geoff,

Quoted 8 lines · On Wed, 06 Jun 2007 14:55:00 -0700 Geoff Levand <[email protected]>…
Quoted 6 lines · Michael Ellerman
Quoted 4 lines · Geoff Levand

Fixup the core platform parts needed for kexec to work on the PS3.
- Setup ps3_hpte_clear correctly.
- Mask interrupts on irq removal.
- Release all hypervisor resources.

Quoted 5 lines
Quoted 2 lines

The irq changes might be kexec related, but it's a mess to review. You seem to moving a bunch of code around in the patch as well.

Yes, I need to move the static chip_mask routines up so they would be defined before the irq setup/destroy routines.

I think Michael's point then is that if you submitted a separate preceding patch that just moves stuff around without any other changes (if at all possible) then reviewing the changes in this would be much easier (and our confidence would be higher).

Signature · 3 lines
Cheers,
Stephen Rothwell                    [email protected]
http://www.canb.auug.org.au/~sfr/
#27 lore raw

Re: [patch 08/18] PS3: Kexec support

Quoted 14 lines · Stephen Rothwell

Hi Geoff,

Quoted 11 lines · On Wed, 06 Jun 2007 14:55:00 -0700 Geoff Levand <[email protected]>…
Quoted 8 lines · Michael Ellerman
Quoted 4 lines · Geoff Levand

Fixup the core platform parts needed for kexec to work on the PS3.
- Setup ps3_hpte_clear correctly.
- Mask interrupts on irq removal.
- Release all hypervisor resources.

The irq changes might be kexec related, but it's a mess to review. You seem to moving a bunch of code around in the patch as well.

Quoted 7 lines
Quoted 2 lines

Yes, I need to move the static chip_mask routines up so they would be defined before the irq setup/destroy routines.

I think Michael's point then is that if you submitted a separate preceding patch that just moves stuff around without any other changes (if at all possible) then reviewing the changes in this would be much easier (and our confidence would be higher).

Yes, sorry, I understood. I've already split it up for the next round.

-Geoff

#28 lore raw

Re: [patch 08/18] PS3: Kexec support

Quoted 2 lines · On Wed, 06 Jun 2007 18:33:05 -0700 Geoff Levand <[email protected]>…

Yes, sorry, I understood. I've already split it up for the next round.

Excellent, thanks.

Signature · 3 lines
Cheers,
Stephen Rothwell                    [email protected]
http://www.canb.auug.org.au/~sfr/
#29 lore raw

Re: [patch 08/18] PS3: Kexec support

In reply to Geoff Levand
Quoted 28 lines · Geoff Levand
Quoted 10 lines · Michael Ellerman
Quoted 10 lines
arch/powerpc/platforms/ps3/htab.c +1 -2
@@ -234,10 +234,18 @@ static void ps3_hpte_invalidate(unsigned
 
 static void ps3_hpte_clear(void)
 {
-	/* Make sure to clean up the frame buffer device first */
-	ps3fb_cleanup();
+	int result;
 
Quoted 15 lines

arch/powerpc/platforms/ps3/htab.c static void ps3_hpte_invalidate(unsigned · line 249

Quoted 12 lines
arch/powerpc/platforms/ps3/htab.c +10 -1
-	lv1_unmap_htab(htab_addr);
+	DBG(" -> %s:%d\n", __func__, __LINE__);
+
+	result = lv1_unmap_htab(htab_addr);
+	BUG_ON(result);
+
+	ps3_mm_shutdown();
+
+	ps3_mm_vas_destroy();
+
+	DBG(" <- %s:%d\n", __func__, __LINE__);
 }

Do you really want to be calling DBG() here? Hmm, it looks like it doesn't actually do anything?

Quoted 1 line

Sure, it uses udbg_printf, and works OK.

Which is hooked up to what?

Quoted 25 lines
Quoted 25 lines
Quoted 12 lines
arch/powerpc/platforms/ps3/htab.c +12 -0
+static void ps3_chip_mask(unsigned int virq)
+{
+	struct ps3_private *pd = get_irq_chip_data(virq);
+	u64 bit = 0x8000000000000000UL >> virq;
+	u64 *p = &pd->bmp.mask;
+	u64 old;
+	unsigned long flags;
+
+	pr_debug("%s:%d: cpu %u, virq %d\n", __func__, __LINE__, pd->cpu, virq);
+
+	local_irq_save(flags);
+	asm volatile(

arch/powerpc/platforms/ps3/htab.c static void ps3_hpte_invalidate(unsigned

Quoted 10 lines
arch/powerpc/platforms/ps3/htab.c +10 -0
+		     "1:	ldarx %0,0,%3\n"
+		     "andc	%0,%0,%2\n"
+		     "stdcx.	%0,0,%3\n"
+		     "bne-	1b"
+		     : "=&r" (old), "+m" (*p)
+		     : "r" (bit), "r" (p)
+		     : "cc" );
+
+	lv1_did_update_interrupt_mask(pd->node, pd->cpu);
+	local_irq_restore(flags);

How is this different from set_bit() ? (asm-powerpc/bitops.h)

Quoted 7 lines
Quoted 2 lines

ps. now that I see you're just moving this code around someone's probably already asked that question.

This was contributed by Ben H as the fastest way. I think the reason was that we could minimize the time between local_irq_save and local_irq_restore?

To save ~10 instructions? Followed by a HV call? I guess Ben has some really good benchmark data to support it ;)

cheers

Signature · 8 lines
Michael Ellerman
OzLabs, IBM Australia Development Lab

wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)

We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person
#30 lore raw

Re: [patch 08/18] PS3: Kexec support

Quoted 20 lines · Michael Ellerman
Quoted 1 line
Quoted 1 line
Quoted 1 line

+ pr_debug("%s:%d: cpu %u, virq %d\n", __func__, __LINE__,

pd->cpu, virq);

Quoted 18 lines
Quoted 18 lines

arch/powerpc/platforms/ps3/interrupt.c struct ps3_private { · line 121

Quoted 13 lines
arch/powerpc/platforms/ps3/interrupt.c +13 -0
+
+  local_irq_save(flags);
+  asm volatile(
+               "1:        ldarx %0,0,%3\n"
+               "andc      %0,%0,%2\n"
+               "stdcx.    %0,0,%3\n"
+               "bne-      1b"
+               : "=&r" (old), "+m" (*p)
+               : "r" (bit), "r" (p)
+               : "cc" );
+
+  lv1_did_update_interrupt_mask(pd->node, pd->cpu);
+  local_irq_restore(flags);

How is this different from set_bit() ? (asm-powerpc/bitops.h)

ps. now that I see you're just moving this code around someone's probably already asked that question.

Actually the above is clear_bit :-)

That would thus be something around the lines of:

clear_bit(&pd->bmp.mask, 63 - virq);

Geoff, feel free to replace it with the clear_bit if you think it's nicer that way :-) (and double check I didn't smoke crack when doing the above conversion).

The other one in unmask would be set_bit() of course.

Ben.

#31 lore raw

Re: [patch 08/18] PS3: Kexec support

Quoted 26 lines · Benjamin Herrenschmidt
Quoted 20 lines · Michael Ellerman
Quoted 1 line
Quoted 1 line
Quoted 1 line

+ pr_debug("%s:%d: cpu %u, virq %d\n", __func__, __LINE__,

pd->cpu, virq);

Quoted 18 lines
Quoted 18 lines

arch/powerpc/platforms/ps3/interrupt.c struct ps3_private { · line 121

Quoted 13 lines
arch/powerpc/platforms/ps3/interrupt.c +13 -0
+
+  local_irq_save(flags);
+  asm volatile(
+               "1:        ldarx %0,0,%3\n"
+               "andc      %0,%0,%2\n"
+               "stdcx.    %0,0,%3\n"
+               "bne-      1b"
+               : "=&r" (old), "+m" (*p)
+               : "r" (bit), "r" (p)
+               : "cc" );
+
+  lv1_did_update_interrupt_mask(pd->node, pd->cpu);
+  local_irq_restore(flags);

How is this different from set_bit() ? (asm-powerpc/bitops.h)

ps. now that I see you're just moving this code around someone's probably already asked that question.

Actually the above is clear_bit :-)

That would thus be something around the lines of:

Quoted 7 lines

clear_bit(&pd->bmp.mask, 63 - virq);

Geoff, feel free to replace it with the clear_bit if you think it's nicer that way :-) (and double check I didn't smoke crack when doing the above conversion).

The other one in unmask would be set_bit() of course.

Almost right. Needed clear_bit(63 - virq, &pd->bmp.mask). I added it in.

-Geoff

#32 lore raw

Re: [patch 08/18] PS3: Kexec support (and a tutoral on the kexec flow for 64 bit powerpc)

In reply to Geoff Levand
Quoted 16 lines · Geoff Levand

Fixup the core platform parts needed for kexec to work on the PS3.
- Setup ps3_hpte_clear correctly.
- Mask interrupts on irq removal.
- Release all hypervisor resources.

Signed-off-by Geoff Levand <geoffrey.levand at am.sony.com>
---
 arch/powerpc/platforms/ps3/htab.c      |   14 +-
 arch/powerpc/platforms/ps3/interrupt.c |  199 
++++++++++++++++++++-------------
 arch/powerpc/platforms/ps3/setup.c     |   29 ++--
 3 files changed, 147 insertions(+), 95 deletions(-)

arch/powerpc/platforms/ps3/htab.c static void ps3_hpte_invalidate(unsigned · line 238

Quoted 5 lines
arch/powerpc/platforms/ps3/htab.c +0 -2
@@ -234,10 +234,18 @@ static void ps3_hpte_invalidate(unsigned
 
 static void ps3_hpte_clear(void)
 {
-       /* Make sure to clean up the frame buffer device first */
-       ps3fb_cleanup();

I'm glad to see this go. Which patch added the call to the driver?

arch/powerpc/platforms/ps3/htab.c static void ps3_hpte_invalidate(unsigned · line 250

Quoted 12 lines
arch/powerpc/platforms/ps3/htab.c +9 -1
+       int result;
 
-       lv1_unmap_htab(htab_addr);
+       DBG(" -> %s:%d\n", __func__, __LINE__);
+
+       result = lv1_unmap_htab(htab_addr);
+       BUG_ON(result);
+
+       ps3_mm_shutdown();
+
+       ps3_mm_vas_destroy();
 

I tried to look at these to check that nothing dynamically allocated was being touched. I didn't find anything if the memory had been hot-unplugged, but it also looked like they skipped the last one.

Quoted 6 lines
arch/powerpc/platforms/ps3/htab.c +2 -0
+
+       DBG(" <- %s:%d\n", __func__, __LINE__);
 }
 

void __init ps3_hpte_init(unsigned long htab_size)

[skipped interrupt.c changes]

arch/powerpc/platforms/ps3/setup.c static int __init ps3_probe(void) · line 214

Quoted 10 lines
arch/powerpc/platforms/ps3/setup.c +3 -1
@@ -209,31 +209,28 @@ static int __init ps3_probe(void)
 #if defined(CONFIG_KEXEC)
 static void ps3_kexec_cpu_down(int crash_shutdown, int secondary)
 {
-       DBG(" -> %s:%d\n", __func__, __LINE__);
+       int result;
+       u64 ppe_id;
+       u64 thread_id = secondary ? 1 : 0;

This is wrong. This is not what secondary means. To get the thread_id you must use smp_processor_id for logical or hard_smp_processor_id() for the hardware thread id.

arch/powerpc/platforms/ps3/setup.c static int __init ps3_probe(void)

Quoted 7 lines
arch/powerpc/platforms/ps3/setup.c +6 -0
+
+       DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, secondary);
+       ps3_smp_cleanup_cpu(thread_id);
+
+       lv1_get_logical_ppe_id(&ppe_id);
+       result = lv1_configure_irq_state_bitmap(ppe_id, secondary ? 0 
 : 1, 0);

As the second argument is thread id, again this is wrong.

Quoted 5 lines
arch/powerpc/platforms/ps3/setup.c +0 -4
-       if (secondary) {
-               int cpu;
-               for_each_online_cpu(cpu)
-                       if (cpu)

arch/powerpc/platforms/ps3/setup.c static int __init ps3_probe(void) · line 227

Quoted 10 lines
arch/powerpc/platforms/ps3/setup.c +3 -3
-                               ps3_smp_cleanup_cpu(cpu);
-       } else
-               ps3_smp_cleanup_cpu(0);
+       /* seems to fail on second call */
+       DBG("%s:%d: lv1_configure_irq_state_bitmap (%d) %s\n", 
 __func__,
+               __LINE__, secondary, ps3_result(result));
 
        DBG(" <- %s:%d\n", __func__, __LINE__);
 }

Once linux is running, all processors are identical. That is the S in SMP. However, during kernel boot, we need one cpu to be running and the others to wait until the path is prepared. Since kexec effectively leads to a boot, one cpu becomes known as the boot cpu and the rest become secondary cpus.

There are two paths to enter the kexec code: the panic code, and the shutdown/reboot syscall. For normal kexec, whatever cpu thread is running the user process when it makes the reboot system call will be the master. For crash kexec, its whichever thread called panic.

The secondary flag to cpu_down exists because the secondary cpus will call it in ipi context but will not return to the irq layer to eoi the ipi. The call to cpu_down is made from kexec_smp_down initiated via the smp_call_function ipi context but instead of returning, kexec_smp_down calls kexec_smp_wait which will mark the paca, switch to real mode and spin with the hardware thread in r3 until the master tells them its done copying the kernel, when it will jump to address 0x60.

The code in default_machine_kexec calls kexec_prepare_cpus which uses smp_call_function to ipi the other cpus and have them call kexec_cpu_down. After the secondaries have marked their paca, cpu_down will be called on the master with the secondary arg 0. During this call all other cpus are spinning. After this call, the cpu will switch to a statically allocated stack and copy the new image pages into place, destroying any dynamically allocated and per-cpu data. It then calls switches to real mode and calls the htab_clear hook to tear down the page tables, leaving a clean state for the new kernel. When finished it copies 256 bytes from the entry point to address 0 and tells any slaves to branch to 0x60. It then branches to the entry point (not address 0) with r3 containing its hardware cpu id, r4 containing the entry address, and r5 containing 0.

When using kexec-tools, the entry point in v2wrap.S stores the master cpu id, calls the generic C code to checksum the image, then stores the master cpu id as the boot cpu in the device tree header, loads r3 with the device tree, and enters the new kernel. (This adjusts for the difference between leaving the kernel, where cpu id is in r3, and entering the kernel, which expects a pointer to the device tree. The kexec_load syscall just supplies memory contents and the entry point; the design is that any registers needed by the new code are to be set by a trampoline added to the list of image segments by user space. The master cpu is not known until kexec is initiated and therefore is passed in the r3 (the very existence of the device-tree structure is only known to user space, not passed to the system call); the specification of r4 and r5 for the master thread is for convenience)

Since there is no handoff to say the slave noticed that the master was done copying the image, I have submitted a kernel patch to release the slaves to the new kernel's wait code entry point at 0x60 before calling the htab_clear routine, giving them the time that the htab_clear function executes in addition to the time for the code in purgatory. The patch \to copy the payload kernel's spin loop instead of creating another loop and sync gate is in kexec-testing.

Note that the order describe above is for the 64 bit PowerPC port; most architectures switch to real mode, flash invalidate the mmu and copy the new kernel in real mode using an relocatable assembly routine running at a location chosen by the kernel (a page that is neither an image source or destination page). The LPAR real mode limitations deem this impractical; instead we reserve the kernel text, data, and bss space, the mmu hash table (in non-lpar mode), and any tce tables. If the execed image was a kernel, it will copy itself to its linked location as it must when started from open firmware.

Quoted 8 lines
arch/powerpc/platforms/ps3/setup.c +0 -2
 static void ps3_machine_kexec(struct kimage *image)
 {
-       unsigned long ppe_id;
-
        DBG(" -> %s:%d\n", __func__, __LINE__);
 

arch/powerpc/platforms/ps3/setup.c static int __init ps3_probe(void) · line 236

Quoted 10 lines
arch/powerpc/platforms/ps3/setup.c +1 -6
-       lv1_get_logical_ppe_id(&ppe_id);
-       lv1_configure_irq_state_bitmap(ppe_id, 0, 0);
-       ps3_mm_shutdown();
-       ps3_mm_vas_destroy();
-
-       default_machine_kexec(image);
+       default_machine_kexec(image); // needs ipi, never returns.
 
        DBG(" <- %s:%d\n", __func__, __LINE__);
 }

Others noted this now passthough function can be eliminated.

milton

#33 lore raw

Re: [patch 08/18] PS3: Kexec support (and a tutoral on the kexec flow for 64 bit powerpc)

Hi Milton.

Quoted 7 lines · Milton Miller
Quoted 4 lines · Geoff Levand

Fixup the core platform parts needed for kexec to work on the PS3.
- Setup ps3_hpte_clear correctly.
- Mask interrupts on irq removal.
- Release all hypervisor resources.

Quoted 6 lines

arch/powerpc/platforms/ps3/htab.c static void ps3_hpte_invalidate(unsigned · line 238

Quoted 4 lines

static void ps3_hpte_clear(void)
{

arch/powerpc/platforms/ps3/htab.c +0 -2
-       /* Make sure to clean up the frame buffer device first */
-       ps3fb_cleanup();

I'm glad to see this go. Which patch added the call to the driver?

I don't know the exact history, but I am pretty sure that is a left over from before the framebuffer driver used the dma support now provided by the ps3_system_bus. The old fb code managed its own IOPTE's, and I think this call cleaned those. But as Geert was re-writing the fb driver ps3fb_cleanup became a place to put general fb shutdown code. At the time we were working to just get it to boot and run, and had no concern what happened at shutdown let alone kexec. It wasn't like someone consciously made a single change to do driver shutdown here, it just was a result of the churn.

Quoted 15 lines

arch/powerpc/platforms/ps3/htab.c static void ps3_hpte_invalidate(unsigned · line 246

Quoted 12 lines
arch/powerpc/platforms/ps3/htab.c +9 -1
+       int result;
 
-       lv1_unmap_htab(htab_addr);
+       DBG(" -> %s:%d\n", __func__, __LINE__);
+
+       result = lv1_unmap_htab(htab_addr);
+       BUG_ON(result);
+
+       ps3_mm_shutdown();
+
+       ps3_mm_vas_destroy();

I tried to look at these to check that nothing dynamically allocated
was being touched. I didn't find anything if the memory had been
hot-unplugged, but it also looked like they skipped the last one.

By 'last one' I guess you mean the rm region (map.rm). That is the 'real mode' boot mem region. It is allocated by the hypervisor for the life of the lpar. It's not hot-pluggable.

Quoted 22 lines

arch/powerpc/platforms/ps3/setup.c static int __init ps3_probe(void) · line 214

Quoted 8 lines
arch/powerpc/platforms/ps3/setup.c +3 -1
@@ -209,31 +209,28 @@ static int __init ps3_probe(void)
 #if defined(CONFIG_KEXEC)
 static void ps3_kexec_cpu_down(int crash_shutdown, int secondary)
 {
-       DBG(" -> %s:%d\n", __func__, __LINE__);
+       int result;
+       u64 ppe_id;
+       u64 thread_id = secondary ? 1 : 0;

This is wrong. This is not what secondary means. To get the
thread_id you must use smp_processor_id for logical or hard_smp_processor_id() for the hardware thread id.

arch/powerpc/platforms/ps3/setup.c static int __init ps3_probe(void)

Quoted 8 lines
arch/powerpc/platforms/ps3/setup.c +7 -0
+       DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, secondary);
+       ps3_smp_cleanup_cpu(thread_id);
+
+       lv1_get_logical_ppe_id(&ppe_id);
+       result = lv1_configure_irq_state_bitmap(ppe_id, secondary ? 0 
 : 1, 0);
+       /* seems to fail on second call */
+       DBG("%s:%d: lv1_configure_irq_state_bitmap (%d) %s\n", 
Quoted 1 line

As the second argument is thread id, again this is wrong.

OK, I setup a new routine ps3_shutdown_IRQ() to mirror ps3_init_IRQ(). ps3_shutdown_IRQ() uses the hard processor id.

Quoted 1 line

Once linux is running, all processors are identical. That is the S in

...

Quoted 1 line

location as it must when started from open firmware.

Thanks for the explanation. I wish I had that before starting this work, but it still explained a few points I still wasn't clear on. I think we should put it somewhere formal like the kernel source Documentntation directory. What do you think?

-Geoff

#34 lore raw

PATCH 9/18 PS3: System-bus rework

In reply to a message not in the archive

Rework the PS3 system bus to unify device support.
- DMA region sizes must be a power of two
- storage bus DMA updates:
- Small fixes for the PS3 DMA core:
o fix alignment bug
o kill superfluous test
o indentation
o spelling
o export ps3_dma_region_{create,free}()
- ps3_dma_region_init():
o Add addr' and len' parameters, so you can create a DMA region that does not cover all memory (use NULL' and 0' to cover all memory). This is needed because there are not sufficient IOMMU resources to have all DMA regions cover all memory.
o Uninline
- Added remove and shutdown routines to all to all drivers.
- Added loadable module support to all drivers.
- Added HV calls for iopte management (needed by sound driver).

---
 arch/powerpc/platforms/ps3/interrupt.c  |   24 -
 arch/powerpc/platforms/ps3/mm.c         |  621 ++++++++++++++++++++++++++------
 arch/powerpc/platforms/ps3/platform.h   |   11 
 arch/powerpc/platforms/ps3/system-bus.c |  525 ++++++++++++++++++++++-----
 include/asm-powerpc/lv1call.h           |    3 
 include/asm-powerpc/ps3.h               |  150 +++++--
 6 files changed, 1081 insertions(+), 253 deletions(-)
arch/powerpc/platforms/ps3/interrupt.c +11 -13
@@ -399,17 +399,15 @@ int ps3_send_event_locally(unsigned int 
  * ps3_sb_event_receive_port_setup - Setup a system bus event receive port.
  * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
  * serviced on.
- * @did: The HV device identifier read from the system repository.
- * @interrupt_id: The device interrupt id read from the system repository.
+ * @dev: The system bus device instance.
  * @virq: The assigned Linux virq.
  *
  * An event irq represents a virtual device interrupt.  The interrupt_id
  * coresponds to the software interrupt number.
  */
 
-int ps3_sb_event_receive_port_setup(enum ps3_cpu_binding cpu,
-	const struct ps3_device_id *did, unsigned int interrupt_id,
-	unsigned int *virq)
+int ps3_sb_event_receive_port_setup(struct ps3_system_bus_device *dev,
+	enum ps3_cpu_binding cpu, unsigned int *virq)
 {
 	/* this should go in system-bus.c */
 
@@ -420,8 +418,8 @@ int ps3_sb_event_receive_port_setup(enum
 	if (result)
 		return result;
 
-	result = lv1_connect_interrupt_event_receive_port(did->bus_id,
-		did->dev_id, virq_to_hw(*virq), interrupt_id);
+	result = lv1_connect_interrupt_event_receive_port(dev->bus_id,
+		dev->dev_id, virq_to_hw(*virq), dev->interrupt_id);
 
 	if (result) {
 		pr_debug("%s:%d: lv1_connect_interrupt_event_receive_port"
@@ -433,24 +431,24 @@ int ps3_sb_event_receive_port_setup(enum
 	}
 
 	pr_debug("%s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__,
-		interrupt_id, *virq);
+		dev->interrupt_id, *virq);
 
 	return 0;
 }
 EXPORT_SYMBOL(ps3_sb_event_receive_port_setup);
 
-int ps3_sb_event_receive_port_destroy(const struct ps3_device_id *did,
-	unsigned int interrupt_id, unsigned int virq)
+int ps3_sb_event_receive_port_destroy(struct ps3_system_bus_device *dev,
+	unsigned int virq)
 {
 	/* this should go in system-bus.c */
 
 	int result;
 
 	pr_debug(" -> %s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__,
-		interrupt_id, virq);
+		dev->interrupt_id, virq);
 
-	result = lv1_disconnect_interrupt_event_receive_port(did->bus_id,
-		did->dev_id, virq_to_hw(virq), interrupt_id);
+	result = lv1_disconnect_interrupt_event_receive_port(dev->bus_id,
+		dev->dev_id, virq_to_hw(virq), dev->interrupt_id);
 
 	if (result)
 		pr_debug("%s:%d: lv1_disconnect_interrupt_event_receive_port"
arch/powerpc/platforms/ps3/mm.c +513 -108

919 lines not on this page · raw message

arch/powerpc/platforms/ps3/platform.h +11 -0
@@ -82,6 +82,7 @@ enum ps3_dev_type {
 	PS3_DEV_TYPE_STOR_ROM = TYPE_ROM,	/* 5 */
 	PS3_DEV_TYPE_SB_GPIO = 6,
 	PS3_DEV_TYPE_STOR_FLASH = TYPE_RBC,	/* 14 */
+	PS3_DEV_TYPE_NOACCESS = 255,
 };
 
 int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str,
@@ -216,4 +217,14 @@ int ps3_repository_read_num_spu_resource
 int ps3_repository_read_spu_resource_id(unsigned int res_index,
 	enum ps3_spu_resource_type* resource_type, unsigned int *resource_id);
 
+/* Page table entries */
+#define IOPTE_PP_W		0x8000000000000000ul /* protection: write */
+#define IOPTE_PP_R		0x4000000000000000ul /* protection: read */
+#define IOPTE_M			0x2000000000000000ul /* coherency required */
+#define IOPTE_SO_R		0x1000000000000000ul /* ordering: writes */
+#define IOPTE_SO_RW             0x1800000000000000ul /* ordering: r & w */
+#define IOPTE_RPN_Mask		0x07fffffffffff000ul /* RPN */
+#define IOPTE_H			0x0000000000000800ul /* cache hint */
+#define IOPTE_IOID_Mask		0x00000000000007fful /* ioid */
+
 #endif
arch/powerpc/platforms/ps3/system-bus.c +443 -82

729 lines not on this page · raw message

include/asm-powerpc/lv1call.h +3 -0
@@ -238,6 +238,7 @@ LV1_CALL(destruct_virtual_address_space,
 LV1_CALL(configure_irq_state_bitmap,                    3, 0,  11 )
 LV1_CALL(connect_irq_plug_ext,                          5, 0,  12 )
 LV1_CALL(release_memory,                                1, 0,  13 )
+LV1_CALL(put_iopte,                                     5, 0,  15 )
 LV1_CALL(disconnect_irq_plug_ext,                       3, 0,  17 )
 LV1_CALL(construct_event_receive_port,                  0, 1,  18 )
 LV1_CALL(destruct_event_receive_port,                   1, 0,  19 )
@@ -268,6 +269,8 @@ LV1_CALL(remove_repository_node,        
 LV1_CALL(read_htab_entries,                             2, 5,  95 )
 LV1_CALL(set_dabr,                                      2, 0,  96 )
 LV1_CALL(get_total_execution_time,                      2, 1, 103 )
+LV1_CALL(allocate_io_segment,                           3, 1, 116 )
+LV1_CALL(release_io_segment,                            2, 0, 117 )
 LV1_CALL(construct_io_irq_outlet,                       1, 1, 120 )
 LV1_CALL(destruct_io_irq_outlet,                        1, 0, 121 )
 LV1_CALL(map_htab,                                      1, 1, 122 )
include/asm-powerpc/ps3.h +99 -50

254 lines not on this page · raw message

#35 lore raw

Re: [patch 09/18] PS3: System-bus rework

Quoted 14 lines · Geoff Levand
arch/powerpc/platforms/ps3/mm.c +1 -0
@@ -17,6 +17,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
+#define DEBUG
 
 #include <linux/kernel.h>
 #include <linux/module.h>

arch/powerpc/platforms/ps3/system-bus.c line 25

Quoted 8 lines
arch/powerpc/platforms/ps3/system-bus.c +2 -0
@@ -18,6 +18,8 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#define DEBUG
+
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>

You forgot to remove these before release.

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE) [email protected] ------- The Corporate Village, Da Vincilaan 7-D1 Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

#36 lore raw

Re: [patch 09/18] PS3: System-bus rework

In reply to Geoff Levand
Quoted 11 lines · Geoff Levand

Rework the PS3 system bus to unify device support.
- DMA region sizes must be a power of two
- storage bus DMA updates:
- Small fixes for the PS3 DMA core:
o fix alignment bug
o kill superfluous test
o indentation
o spelling
o export ps3_dma_region_{create,free}()
- ps3_dma_region_init():
o Add addr' and len' parameters, so you can create a DMA

Quoted 8 lines

region that
does not cover all memory (use NULL' and 0' to cover all
memory).
This is needed because there are not sufficient IOMMU
resources to have
all DMA regions cover all memory.
o Uninline
- Added remove and shutdown routines to all to all drivers.

That'd be all y'all .

Oh, wait, changelogs are not ususally in Texan. :-)

Quoted 3 lines

- Added loadable module support to all drivers.
- Added HV calls for iopte management (needed by sound driver).

Just a quick scan through :

arch/powerpc/platforms/ps3/mm.c line 36

Quoted 4 lines
arch/powerpc/platforms/ps3/mm.c +1 -1
-#define DBG(fmt...) do{if(0)printk(fmt);}while(0)
+#define DBG(fmt...) do { if (0) printk(fmt);} while (0)

While there isn't a style guide for one line defines, while you're adding spaces add one more after the ; before the } where a new line would normally appear.

arch/powerpc/platforms/ps3/mm.c

Quoted 5 lines
arch/powerpc/platforms/ps3/mm.c +5 -0
+       BUG_ON(!dev->bus_id);
+       mutex_lock(&usage_hack.mutex);
+
+       if(dev->bus_id == 1 && dev->dev_id == 1) {
+               usage_hack.sb_11++;

If you expect to leave this hack in for a while, how about adding a DEVICE_IS(dev, bus, device) macro?

milton

#37 lore raw

Re: [patch 09/18] PS3: System-bus rework

Quoted 8 lines · Milton Miller

arch/powerpc/platforms/ps3/mm.c line 36

Quoted 4 lines
arch/powerpc/platforms/ps3/mm.c +1 -1
-#define DBG(fmt...) do{if(0)printk(fmt);}while(0)
+#define DBG(fmt...) do { if (0) printk(fmt);} while (0)

While there isn't a style guide for one line defines, while you're adding spaces add one more after the ; before the } where a new line would normally appear.

I don't even like the original. I planned to replace it with the following, and will do so now.

static inline int __attribute__ ((format (printf, 1, 2))) DBG(

	const char *fmt, ...) {return 0;}
Quoted 8 lines

arch/powerpc/platforms/ps3/mm.c

Quoted 5 lines
arch/powerpc/platforms/ps3/mm.c +5 -0
+       BUG_ON(!dev->bus_id);
+       mutex_lock(&usage_hack.mutex);
+
+       if(dev->bus_id == 1 && dev->dev_id == 1) {
+               usage_hack.sb_11++;

If you expect to leave this hack in for a while, how about adding a DEVICE_IS(dev, bus, device) macro?

A good idea!

-Geoff

#38 lore raw

Re: [patch 09/18] PS3: System-bus rework

Quoted 11 lines · Geoff Levand
Quoted 8 lines · Milton Miller

arch/powerpc/platforms/ps3/mm.c line 36

Quoted 4 lines
arch/powerpc/platforms/ps3/mm.c +1 -1
-#define DBG(fmt...) do{if(0)printk(fmt);}while(0)
+#define DBG(fmt...) do { if (0) printk(fmt);} while (0)

While there isn't a style guide for one line defines, while you're adding spaces add one more after the ; before the } where a new line would normally appear.

Quoted 5 lines

I don't even like the original. I planned to replace it with the following, and will do so now.

static inline int __attribute__ ((format (printf, 1, 2))) DBG(

	const char *fmt, ...) {return 0;}

We have the exact same definition (albeit with a different name, `pr_debug'), in include/linux/kernel.h...

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE) [email protected] ------- The Corporate Village, Da Vincilaan 7-D1 Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

#39 lore raw

PATCH 10/18 PS3: System-bus uevent

In reply to a message not in the archive

To allow userspace to automatically load modules, we need to hook up uevent for ps3_system_bus devices. I've used the form 'ps3:%d' with the ps3_match_id, since that's what we use for matching drivers.

---
 arch/powerpc/platforms/ps3/system-bus.c |   16 ++++++++++++++++
 1 file changed, 16 insertions(+)
arch/powerpc/platforms/ps3/system-bus.c +16 -0
@@ -433,9 +433,25 @@ static void ps3_system_bus_shutdown(stru
 	dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
 }
 
+static int ps3_system_bus_uevent(struct device *_dev, char **envp,
+				 int num_envp, char *buffer, int buffer_size)
+{
+	struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
+	int i=0, length = 0;
+
+	if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
+			   &length, "MODALIAS=ps3:%d",
+			   dev->match_id))
+		return -ENOMEM;
+
+	envp[i] = NULL;
+	return 0;
+}
+
 struct bus_type ps3_system_bus_type = {
 	.name = "ps3_system_bus",
 	.match = ps3_system_bus_match,
+	.uevent = ps3_system_bus_uevent,
 	.probe = ps3_system_bus_probe,
 	.remove = ps3_system_bus_remove,
 	.shutdown = ps3_system_bus_shutdown,
#40 lore raw

PATCH 11/18 PS3: System-bus modinfo attribute

In reply to a message not in the archive

Add modinfo attribute to ps3_system_bus devices. Also make them all children of the same ps3_system_bus 'device' so they appear in a corresponding subdirectory under /sys/devices

---
 arch/powerpc/platforms/ps3/system-bus.c |   15 +++++++++++++++
 1 file changed, 15 insertions(+)
arch/powerpc/platforms/ps3/system-bus.c +15 -0
@@ -448,6 +448,20 @@ static int ps3_system_bus_uevent(struct 
 	return 0;
 }
 
+static ssize_t modalias_show(struct device *_dev, struct device_attribute *a,
+			     char *buf)
+{
+	struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
+        int len = snprintf(buf, PAGE_SIZE, "ps3:%d\n", dev->match_id);
+
+        return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
+}
+
+static struct device_attribute ps3_system_bus_dev_attrs[] = {
+        __ATTR_RO(modalias),
+        __ATTR_NULL,
+};
+
 struct bus_type ps3_system_bus_type = {
 	.name = "ps3_system_bus",
 	.match = ps3_system_bus_match,
@@ -455,6 +469,7 @@ struct bus_type ps3_system_bus_type = {
 	.probe = ps3_system_bus_probe,
 	.remove = ps3_system_bus_remove,
 	.shutdown = ps3_system_bus_shutdown,
+	.dev_attrs = ps3_system_bus_dev_attrs,
 };
 
 static int __init ps3_system_bus_init(void)
#41 lore raw

Re: [patch 11/18] PS3: System-bus modinfo attribute

arch/powerpc/platforms/ps3/system-bus.c static int ps3_system_bus_uevent(struct · line 455

Quoted 6 lines · On Tue, 05 Jun 2007 20:00:44 -0700 Geoff Levand <[email protected]>…
arch/powerpc/platforms/ps3/system-bus.c +5 -0
+static ssize_t modalias_show(struct device *_dev, struct device_attribute *a,
+			     char *buf)
+{
+	struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
+        int len = snprintf(buf, PAGE_SIZE, "ps3:%d\n", dev->match_id);

Broken whitespace ...

arch/powerpc/platforms/ps3/system-bus.c static int ps3_system_bus_uevent(struct · line 457

Quoted 2 lines
arch/powerpc/platforms/ps3/system-bus.c +2 -0
+
+        return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;

And here.

Signature · 3 lines
Cheers,
Stephen Rothwell                    [email protected]
http://www.canb.auug.org.au/~sfr/
#42 lore raw

PATCH 12/18 PS3: Repository probe cleanups

In reply to a message not in the archive

Repository updates:
- Extract ps3_repository_find_bus() from ps3_repository_find_device(), as the storage driver needs it.
- Make ps3_repository_find_device() return -ENODEV if a device is not found, just like if a bus is not found.
- Add ps3_repository_read_vuart_sysmgr_port() and ps3_repository_read_vuart_av_port() to get vuart port info.
- Add device enumeration routines ps3_repository_find_device() and ps3_repository_find_devices().
- Cleanup debug routines.

---
 arch/powerpc/platforms/ps3/platform.h   |   31 +
 arch/powerpc/platforms/ps3/repository.c |  592 +++++++++++++++++---------------
 2 files changed, 340 insertions(+), 283 deletions(-)
arch/powerpc/platforms/ps3/platform.h +20 -11
@@ -130,24 +130,28 @@ int ps3_repository_read_dev_reg(unsigned
 /* repository bus enumerators */
 
 struct ps3_repository_device {
+	enum ps3_bus_type bus_type;
 	unsigned int bus_index;
+	unsigned int bus_id;
+	enum ps3_dev_type dev_type;
 	unsigned int dev_index;
-	struct ps3_device_id did;
+	unsigned int dev_id;
 };
 
-int ps3_repository_find_device(enum ps3_bus_type bus_type,
-	enum ps3_dev_type dev_type,
-	const struct ps3_repository_device *start_dev,
-	struct ps3_repository_device *dev);
-static inline int ps3_repository_find_first_device(
-	enum ps3_bus_type bus_type, enum ps3_dev_type dev_type,
-	struct ps3_repository_device *dev)
+static inline struct ps3_repository_device *ps3_repository_bump_device(
+	struct ps3_repository_device *repo)
 {
-	return ps3_repository_find_device(bus_type, dev_type, NULL, dev);
+	repo->dev_index++;
+	return repo;
 }
-int ps3_repository_find_interrupt(const struct ps3_repository_device *dev,
+int ps3_repository_find_device(struct ps3_repository_device *repo);
+int ps3_repository_find_devices(enum ps3_bus_type bus_type,
+	int (*callback)(const struct ps3_repository_device *repo));
+int ps3_repository_find_bus(enum ps3_bus_type bus_type, unsigned int from,
+	unsigned int *bus_index);
+int ps3_repository_find_interrupt(const struct ps3_repository_device *repo,
 	enum ps3_interrupt_type intr_type, unsigned int *interrupt_id);
-int ps3_repository_find_reg(const struct ps3_repository_device *dev,
+int ps3_repository_find_reg(const struct ps3_repository_device *repo,
 	enum ps3_reg_type reg_type, u64 *bus_addr, u64 *len);
 
 /* repository block device info */
@@ -217,6 +221,11 @@ int ps3_repository_read_num_spu_resource
 int ps3_repository_read_spu_resource_id(unsigned int res_index,
 	enum ps3_spu_resource_type* resource_type, unsigned int *resource_id);
 
+/* repository vuart info */
+
+int ps3_repository_read_vuart_av_port(unsigned int *port);
+int ps3_repository_read_vuart_sysmgr_port(unsigned int *port);
+
 /* Page table entries */
 #define IOPTE_PP_W		0x8000000000000000ul /* protection: write */
 #define IOPTE_PP_R		0x4000000000000000ul /* protection: read */
arch/powerpc/platforms/ps3/repository.c +319 -271

689 lines not on this page · raw message

#43 lore raw

PATCH 13/18 PS3: USB system-bus rework

In reply to a message not in the archive

USB HCD glue updates to reflect the new PS3 unifed device support.
- Fixed remove() routine.
- Added shutdown() routine.
- Added request_mem_region() call.
- Fixed MODULE_ALIAS().
- Made a proper fix for the hack done to support muti-platform in commit 48fda45120a819ca40cadc50144b55bff1c4c78d.

---
 drivers/usb/host/ehci-hcd.c |   22 +++--------
 drivers/usb/host/ehci-ps3.c |   86 +++++++++++++++++++++++++++++++++++++------
 drivers/usb/host/ohci-hcd.c |   20 +++-------
 drivers/usb/host/ohci-ps3.c |   87 +++++++++++++++++++++++++++++++++++++-------
 4 files changed, 162 insertions(+), 53 deletions(-)
drivers/usb/host/ehci-hcd.c +7 -15
@@ -41,10 +41,6 @@
 #include <asm/irq.h>
 #include <asm/system.h>
 #include <asm/unaligned.h>
-#ifdef CONFIG_PPC_PS3
-#include <asm/firmware.h>
-#endif
-
 
 /*-------------------------------------------------------------------------*/
 
@@ -937,7 +933,7 @@ MODULE_LICENSE ("GPL");
 
 #ifdef CONFIG_PPC_PS3
 #include "ehci-ps3.c"
-#define	PS3_SYSTEM_BUS_DRIVER	ps3_ehci_sb_driver
+#define	PS3_SYSTEM_BUS_DRIVER	ps3_ehci_driver
 #endif
 
 #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
@@ -971,18 +967,15 @@ static int __init ehci_hcd_init(void)
 #endif
 
 #ifdef PS3_SYSTEM_BUS_DRIVER
-	if (firmware_has_feature(FW_FEATURE_PS3_LV1)) {
-		retval = ps3_system_bus_driver_register(
-				&PS3_SYSTEM_BUS_DRIVER);
-		if (retval < 0) {
+	retval = ps3_ehci_driver_register(&PS3_SYSTEM_BUS_DRIVER);
+	if (retval < 0) {
 #ifdef PLATFORM_DRIVER
-			platform_driver_unregister(&PLATFORM_DRIVER);
+		platform_driver_unregister(&PLATFORM_DRIVER);
 #endif
 #ifdef PCI_DRIVER
-			pci_unregister_driver(&PCI_DRIVER);
+		pci_unregister_driver(&PCI_DRIVER);
 #endif
-			return retval;
-		}
+		return retval;
 	}
 #endif
 
@@ -999,8 +992,7 @@ static void __exit ehci_hcd_cleanup(void
 	pci_unregister_driver(&PCI_DRIVER);
 #endif
 #ifdef PS3_SYSTEM_BUS_DRIVER
-	if (firmware_has_feature(FW_FEATURE_PS3_LV1))
-		ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
+	ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
 #endif
 }
 module_exit(ehci_hcd_cleanup);
drivers/usb/host/ehci-ps3.c +74 -12

140 lines not on this page · raw message

drivers/usb/host/ohci-hcd.c +6 -14
@@ -41,9 +41,6 @@
 #include <asm/system.h>
 #include <asm/unaligned.h>
 #include <asm/byteorder.h>
-#ifdef CONFIG_PPC_PS3
-#include <asm/firmware.h>
-#endif
 
 #include "../core/hcd.h"
 
@@ -917,7 +914,7 @@ MODULE_LICENSE ("GPL");
 
 #ifdef CONFIG_PPC_PS3
 #include "ohci-ps3.c"
-#define PS3_SYSTEM_BUS_DRIVER	ps3_ohci_sb_driver
+#define PS3_SYSTEM_BUS_DRIVER	ps3_ohci_driver
 #endif
 
 #if	!defined(PCI_DRIVER) &&		\
@@ -940,12 +937,9 @@ static int __init ohci_hcd_mod_init(void
 		sizeof (struct ed), sizeof (struct td));
 
 #ifdef PS3_SYSTEM_BUS_DRIVER
-	if (firmware_has_feature(FW_FEATURE_PS3_LV1)) {
-		retval = ps3_system_bus_driver_register(
-				&PS3_SYSTEM_BUS_DRIVER);
-		if (retval < 0)
-			goto error_ps3;
-	}
+	retval = ps3_ohci_driver_register(&PS3_SYSTEM_BUS_DRIVER);
+	if (retval < 0)
+		goto error_ps3;
 #endif
 
 #ifdef PLATFORM_DRIVER
@@ -991,8 +985,7 @@ static int __init ohci_hcd_mod_init(void
  error_platform:
 #endif
 #ifdef PS3_SYSTEM_BUS_DRIVER
-	if (firmware_has_feature(FW_FEATURE_PS3_LV1))
-		ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
+	ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
  error_ps3:
 #endif
 	return retval;
@@ -1014,8 +1007,7 @@ static void __exit ohci_hcd_mod_exit(voi
 	platform_driver_unregister(&PLATFORM_DRIVER);
 #endif
 #ifdef PS3_SYSTEM_BUS_DRIVER
-	if (firmware_has_feature(FW_FEATURE_PS3_LV1))
-		ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
+	ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
 #endif
 }
 module_exit(ohci_hcd_mod_exit);
drivers/usb/host/ohci-ps3.c +75 -12

141 lines not on this page · raw message

#44 lore raw

PATCH 13/18 PS3: USB system-bus rework

In reply to a message not in the archive

USB HCD glue updates to reflect the new PS3 unifed device support.
- Fixed remove() routine.
- Added shutdown() routine.
- Added request_mem_region() call.
- Fixed MODULE_ALIAS().
- Made a proper fix for the hack done to support muti-platform in commit 48fda45120a819ca40cadc50144b55bff1c4c78d.

---
 drivers/usb/host/ehci-hcd.c |   22 +++--------
 drivers/usb/host/ehci-ps3.c |   86 +++++++++++++++++++++++++++++++++++++------
 drivers/usb/host/ohci-hcd.c |   20 +++-------
 drivers/usb/host/ohci-ps3.c |   87 +++++++++++++++++++++++++++++++++++++-------
 4 files changed, 162 insertions(+), 53 deletions(-)
drivers/usb/host/ehci-hcd.c +7 -15
@@ -41,10 +41,6 @@
 #include <asm/irq.h>
 #include <asm/system.h>
 #include <asm/unaligned.h>
-#ifdef CONFIG_PPC_PS3
-#include <asm/firmware.h>
-#endif
-
 
 /*-------------------------------------------------------------------------*/
 
@@ -937,7 +933,7 @@ MODULE_LICENSE ("GPL");
 
 #ifdef CONFIG_PPC_PS3
 #include "ehci-ps3.c"
-#define	PS3_SYSTEM_BUS_DRIVER	ps3_ehci_sb_driver
+#define	PS3_SYSTEM_BUS_DRIVER	ps3_ehci_driver
 #endif
 
 #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
@@ -971,18 +967,15 @@ static int __init ehci_hcd_init(void)
 #endif
 
 #ifdef PS3_SYSTEM_BUS_DRIVER
-	if (firmware_has_feature(FW_FEATURE_PS3_LV1)) {
-		retval = ps3_system_bus_driver_register(
-				&PS3_SYSTEM_BUS_DRIVER);
-		if (retval < 0) {
+	retval = ps3_ehci_driver_register(&PS3_SYSTEM_BUS_DRIVER);
+	if (retval < 0) {
 #ifdef PLATFORM_DRIVER
-			platform_driver_unregister(&PLATFORM_DRIVER);
+		platform_driver_unregister(&PLATFORM_DRIVER);
 #endif
 #ifdef PCI_DRIVER
-			pci_unregister_driver(&PCI_DRIVER);
+		pci_unregister_driver(&PCI_DRIVER);
 #endif
-			return retval;
-		}
+		return retval;
 	}
 #endif
 
@@ -999,8 +992,7 @@ static void __exit ehci_hcd_cleanup(void
 	pci_unregister_driver(&PCI_DRIVER);
 #endif
 #ifdef PS3_SYSTEM_BUS_DRIVER
-	if (firmware_has_feature(FW_FEATURE_PS3_LV1))
-		ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
+	ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
 #endif
 }
 module_exit(ehci_hcd_cleanup);
drivers/usb/host/ehci-ps3.c +74 -12

140 lines not on this page · raw message

drivers/usb/host/ohci-hcd.c +6 -14
@@ -41,9 +41,6 @@
 #include <asm/system.h>
 #include <asm/unaligned.h>
 #include <asm/byteorder.h>
-#ifdef CONFIG_PPC_PS3
-#include <asm/firmware.h>
-#endif
 
 #include "../core/hcd.h"
 
@@ -917,7 +914,7 @@ MODULE_LICENSE ("GPL");
 
 #ifdef CONFIG_PPC_PS3
 #include "ohci-ps3.c"
-#define PS3_SYSTEM_BUS_DRIVER	ps3_ohci_sb_driver
+#define PS3_SYSTEM_BUS_DRIVER	ps3_ohci_driver
 #endif
 
 #if	!defined(PCI_DRIVER) &&		\
@@ -940,12 +937,9 @@ static int __init ohci_hcd_mod_init(void
 		sizeof (struct ed), sizeof (struct td));
 
 #ifdef PS3_SYSTEM_BUS_DRIVER
-	if (firmware_has_feature(FW_FEATURE_PS3_LV1)) {
-		retval = ps3_system_bus_driver_register(
-				&PS3_SYSTEM_BUS_DRIVER);
-		if (retval < 0)
-			goto error_ps3;
-	}
+	retval = ps3_ohci_driver_register(&PS3_SYSTEM_BUS_DRIVER);
+	if (retval < 0)
+		goto error_ps3;
 #endif
 
 #ifdef PLATFORM_DRIVER
@@ -991,8 +985,7 @@ static int __init ohci_hcd_mod_init(void
  error_platform:
 #endif
 #ifdef PS3_SYSTEM_BUS_DRIVER
-	if (firmware_has_feature(FW_FEATURE_PS3_LV1))
-		ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
+	ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
  error_ps3:
 #endif
 	return retval;
@@ -1014,8 +1007,7 @@ static void __exit ohci_hcd_mod_exit(voi
 	platform_driver_unregister(&PLATFORM_DRIVER);
 #endif
 #ifdef PS3_SYSTEM_BUS_DRIVER
-	if (firmware_has_feature(FW_FEATURE_PS3_LV1))
-		ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
+	ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
 #endif
 }
 module_exit(ohci_hcd_mod_exit);
drivers/usb/host/ohci-ps3.c +75 -12

141 lines not on this page · raw message

#45 lore raw

PATCH 1/1 PS3: Fix USB return value

Fix a minor error on the return value of ps3_ehci_driver_register() and ps3_ohci_driver_register() when running on non-PS3 systems.

---
Hi Greg,

Testers found a problem with my latest PS3 USB patch. Please add it in.

-Geoff

 drivers/usb/host/ehci-ps3.c |    2 +-
 drivers/usb/host/ohci-ps3.c |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
drivers/usb/host/ehci-ps3.c +1 -1
@@ -227,7 +227,7 @@ static int ps3_ehci_driver_register(stru
 {
 	return firmware_has_feature(FW_FEATURE_PS3_LV1)
 		? ps3_system_bus_driver_register(drv)
-		: -ENODEV;
+		: 0;
 }
 
 static void ps3_ehci_driver_unregister(struct ps3_system_bus_driver *drv)
drivers/usb/host/ohci-ps3.c +1 -1
@@ -230,7 +230,7 @@ static int ps3_ohci_driver_register(stru
 {
 	return firmware_has_feature(FW_FEATURE_PS3_LV1)
 		? ps3_system_bus_driver_register(drv)
-		: -ENODEV;
+		: 0;
 }
 
 static void ps3_ohci_driver_unregister(struct ps3_system_bus_driver *drv)
#46 lore raw

Re: [patch] PS3: Fix USB return value

Quoted 9 lines · Geoff Levand

Fix a minor error on the return value of ps3_ehci_driver_register() and ps3_ohci_driver_register() when running on non-PS3 systems.

---
Hi Greg,

Testers found a problem with my latest PS3 USB patch. Please add it in.

I've merged this with your previous one so that no one hits the bug when doing a 'git bisect'.

thanks,

greg k-h

#47 lore raw

PATCH 14/18 PS3: Vuart rework

In reply to a message not in the archive

PS3 vuart updates to reflect the new PS3 unifed device support.
- Move vuart devices to the PS3 system bus.
- Replace use of ps3_vuart_port_device with ps3_system_bus_device.
- Make the PS3 vuart bus driver a loadable module.
- Add remove() and shutdown() routines.
- Move ps3_vuart_work into ps3_vuart_port_priv.tx_list.
- Remove redundant spinlock ps3_vuart_work.lock.
- No longer free ps3_vuart_port_device.priv on shutdown.
- Cleanup Kconfig defs.
- Export symbols needed for modular port drivers.
- Arrange to use port numbers found in repository.
- Fix bugs in ps3_vuart_read_async() and polled reading
- Cleanup handling of shared interrupt with ps3_vuart_bus_interrupt_get() and ps3_vuart_bus_interrupt_put()
- Add more comments to vuart.c.

---
 arch/powerpc/platforms/ps3/Kconfig     |   21 
 arch/powerpc/platforms/ps3/interrupt.c |    2 
 drivers/ps3/vuart.c                    |  807 +++++++++++++++++++--------------
 drivers/ps3/vuart.h                    |   72 --
 include/asm-powerpc/ps3.h              |   17 
 5 files changed, 523 insertions(+), 396 deletions(-)
arch/powerpc/platforms/ps3/Kconfig +8 -13
@@ -73,18 +73,12 @@ config PS3_USE_LPAR_ADDR
 
 config PS3_VUART
 	depends on PPC_PS3
-	bool "PS3 Virtual UART support" if PS3_ADVANCED
-	default y
-	help
-	  Include support for the PS3 Virtual UART.
-
-	  This support is required for several system services
-	  including the System Manager and AV Settings.  In
-	  general, all users will say Y.
+	tristate
 
 config PS3_PS3AV
+	depends on PPC_PS3
 	tristate "PS3 AV settings driver" if PS3_ADVANCED
-	depends on PS3_VUART
+	select PS3_VUART
 	default y
 	help
 	  Include support for the PS3 AV Settings driver.
@@ -93,13 +87,14 @@ config PS3_PS3AV
 	  general, all users will say Y or M.
 
 config PS3_SYS_MANAGER
-	bool "PS3 System Manager driver" if PS3_ADVANCED
-	depends on PS3_VUART
-	default y
+	depends on PPC_PS3
+	tristate "PS3 System Manager driver" if PS3_ADVANCED
+	select PS3_VUART
+	default m
 	help
 	  Include support for the PS3 System Manager.
 
 	  This support is required for system control.  In
-	  general, all users will say Y.
+	  general, all users will say Y or M.
 
 endmenu
arch/powerpc/platforms/ps3/interrupt.c +2 -0
@@ -561,6 +561,7 @@ int ps3_vuart_irq_setup(enum ps3_cpu_bin
 
 	return result;
 }
+EXPORT_SYMBOL_GPL(ps3_vuart_irq_setup);
 
 int ps3_vuart_irq_destroy(unsigned int virq)
 {
@@ -580,6 +581,7 @@ int ps3_vuart_irq_destroy(unsigned int v
 
 	return result;
 }
+EXPORT_SYMBOL_GPL(ps3_vuart_irq_destroy);
 
 /**
  * ps3_spe_irq_setup - Setup an spe virq.
drivers/ps3/vuart.c +489 -318

1,294 lines not on this page · raw message

drivers/ps3/vuart.h +24 -48

99 lines not on this page · raw message

include/asm-powerpc/ps3.h +0 -17
@@ -408,23 +408,6 @@ static inline void *ps3_system_bus_get_d
 
 extern struct bus_type ps3_system_bus_type;
 
-/* vuart routines */
-
-struct ps3_vuart_port_priv;
-
-/**
- * struct ps3_vuart_port_device - a device on a vuart port
- */
-
-struct ps3_vuart_port_device {
-	enum ps3_match_id match_id;
-	struct device core;
-	struct ps3_vuart_port_priv* priv; /* private driver variables */
-
-};
-
-int ps3_vuart_port_device_register(struct ps3_vuart_port_device *dev);
-
 /* system manager */
 
 #ifdef CONFIG_PS3_SYS_MANAGER
#48 lore raw

PATCH 15/18 PS3: System manager re-work

In reply to a message not in the archive

PS3 sys-manager updates to reflect the new PS3 unifed device support. Fixups to the PS3 sys-manager driver to properly support sys_reboot().
- Add varable request_tag to struct ps3_sys_manager_header.
- Move ctrl_alt_del from PS3_SM_EVENT_POWER_RELEASED to PS3_SM_EVENT_POWER_PRESSED.
- Make the PS3 sys-manager driver a loadable module.
- Add new file sys-manager-core.c.
- Add new struct ps3_sys_manager_ops for dynamic binding.
- Put data sent to device on stack.
- Add support for PS3_SM_SERVICE_ID_REQUEST_ERROR.

---
 drivers/ps3/Makefile           |    1 
 drivers/ps3/sys-manager-core.c |   68 ++++++++++
 drivers/ps3/sys-manager.c      |  278 ++++++++++++++++++++++++++---------------
 include/asm-powerpc/ps3.h      |   15 +-
 4 files changed, 259 insertions(+), 103 deletions(-)
drivers/ps3/Makefile +1 -0
@@ -1,3 +1,4 @@
 obj-$(CONFIG_PS3_VUART) += vuart.o
 obj-$(CONFIG_PS3_PS3AV) += ps3av.o ps3av_cmd.o
+obj-$(CONFIG_PPC_PS3) += sys-manager-core.o
 obj-$(CONFIG_PS3_SYS_MANAGER) += sys-manager.o
drivers/ps3/sys-manager-core.c new file +68 -0

68 lines not on this page · raw message

drivers/ps3/sys-manager.c +181 -97

506 lines not on this page · raw message

include/asm-powerpc/ps3.h +9 -6
@@ -410,13 +410,15 @@ extern struct bus_type ps3_system_bus_ty
 
 /* system manager */
 
-#ifdef CONFIG_PS3_SYS_MANAGER
-void ps3_sys_manager_restart(void);
+struct ps3_sys_manager_ops {
+	struct ps3_system_bus_device *dev;
+	void (*power_off)(struct ps3_system_bus_device *dev);
+	void (*restart)(struct ps3_system_bus_device *dev);
+};
+
+void ps3_sys_manager_register_ops(const struct ps3_sys_manager_ops *ops);
 void ps3_sys_manager_power_off(void);
-#else
-static inline void ps3_sys_manager_restart(void) {}
-static inline void ps3_sys_manager_power_off(void) {}
-#endif
+void ps3_sys_manager_restart(void);
 
 struct ps3_prealloc {
     const char *name;
@@ -427,4 +429,5 @@ struct ps3_prealloc {
 
 extern struct ps3_prealloc ps3fb_videomemory;
 
+
 #endif
#49 lore raw

Re: [patch 15/18] PS3: System manager re-work

Quoted 13 lines · Geoff Levand
drivers/ps3/sys-manager-core.c new file +10 -0
@@ -0,0 +1,68 @@
+/*
+ *  PS3 System Manager core.
+ *
+ *  Copyright (C) 2007 Sony Computer Entertainment Inc.
+ *  Copyright 2007 Sony Corp.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *

drivers/ps3/sys-manager-core.c line 20

Quoted 10 lines
drivers/ps3/sys-manager-core.c new file +10 -0
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#define DEBUG

Woops

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE) [email protected] ------- The Corporate Village, Da Vincilaan 7-D1 Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

#50 lore raw

PATCH 16/18 PS3: Rework AV settings driver

In reply to a message not in the archive

Make the PS3 ps3av driver a loadable module.
- Replace static data with malloc'ed.
o Allocate struct ps3av dynamically, as it contains data used as vuart receive/transmit buffers
o Move static recv_buf from ps3av_do_pkt() to struct ps3av
- Move ps3av_vuart_{read,write}() from drivers/ps3/ps3av_cmd.c to drivers/ps3/ps3av.c and make them static as they're used in.
- Make device a PS3 system-bus device.
- Update copyright formatting.
- Make two new routines ps3av_register_flip_ctl() and ps3av_flip_ctl() to support late binding of the frame buffer filp control routine.

---
 drivers/ps3/Makefile        |    3 
 drivers/ps3/ps3av.c         |  368 +++++++++++++++++++++++---------------------
 drivers/ps3/ps3av_cmd.c     |   35 ----
 include/asm-powerpc/ps3av.h |   36 ++--
 4 files changed, 216 insertions(+), 226 deletions(-)
drivers/ps3/Makefile +2 -1
@@ -1,4 +1,5 @@
 obj-$(CONFIG_PS3_VUART) += vuart.o
-obj-$(CONFIG_PS3_PS3AV) += ps3av.o ps3av_cmd.o
+obj-$(CONFIG_PS3_PS3AV) += ps3av_mod.o
+ps3av_mod-objs		+= ps3av.o ps3av_cmd.o
 obj-$(CONFIG_PPC_PS3) += sys-manager-core.o
 obj-$(CONFIG_PS3_SYS_MANAGER) += sys-manager.o
drivers/ps3/ps3av.c +194 -174

729 lines not on this page · raw message

drivers/ps3/ps3av_cmd.c +2 -33
@@ -868,7 +868,7 @@ int ps3av_cmd_avb_param(struct ps3av_pkt
 {
 	int res;
 
-	ps3fb_flip_ctl(0);	/* flip off */
+	ps3av_flip_ctl(0);	/* flip off */
 
 	/* avb packet */
 	res = ps3av_do_pkt(PS3AV_CID_AVB_PARAM, send_len, sizeof(*avb),
@@ -882,7 +882,7 @@ int ps3av_cmd_avb_param(struct ps3av_pkt
 			 res);
 
       out:
-	ps3fb_flip_ctl(1);	/* flip on */
+	ps3av_flip_ctl(1);	/* flip on */
 	return res;
 }
 
@@ -1003,34 +1003,3 @@ void ps3av_cmd_av_monitor_info_dump(cons
 		| PS3AV_CMD_AV_LAYOUT_176 \
 		| PS3AV_CMD_AV_LAYOUT_192)
 
-/************************* vuart ***************************/
-
-#define POLLING_INTERVAL  25	/* in msec */
-
-int ps3av_vuart_write(struct ps3_vuart_port_device *dev, const void *buf,
-		      unsigned long size)
-{
-	int error = ps3_vuart_write(dev, buf, size);
-	return error ? error : size;
-}
-
-int ps3av_vuart_read(struct ps3_vuart_port_device *dev, void *buf,
-		     unsigned long size, int timeout)
-{
-	int error;
-	int loopcnt = 0;
-
-	timeout = (timeout + POLLING_INTERVAL - 1) / POLLING_INTERVAL;
-	while (loopcnt++ <= timeout) {
-		error = ps3_vuart_read(dev, buf, size);
-		if (!error)
-			return size;
-		if (error != -EAGAIN) {
-			printk(KERN_ERR "%s: ps3_vuart_read failed %d\n",
-			       __func__, error);
-			return error;
-		}
-		msleep(POLLING_INTERVAL);
-	}
-	return -EWOULDBLOCK;
-}
include/asm-powerpc/ps3av.h +18 -18
@@ -1,20 +1,23 @@
 /*
- * Copyright (C) 2006 Sony Computer Entertainment Inc.
- * Copyright 2006, 2007 Sony Corporation
+ *  PS3 AV backend support.
  *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published
- * by the Free Software Foundation; version 2 of the License.
+ *  Copyright (C) 2007 Sony Computer Entertainment Inc.
+ *  Copyright 2007 Sony Corp.
  *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
  *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
+
 #ifndef _ASM_POWERPC_PS3AV_H_
 #define _ASM_POWERPC_PS3AV_H_
 
@@ -705,12 +708,6 @@ static inline void ps3av_cmd_av_monitor_
 extern int ps3av_cmd_video_get_monitor_info(struct ps3av_pkt_av_get_monitor_info *,
 					    u32);
 
-struct ps3_vuart_port_device;
-extern int ps3av_vuart_write(struct ps3_vuart_port_device *dev,
-			     const void *buf, unsigned long size);
-extern int ps3av_vuart_read(struct ps3_vuart_port_device *dev, void *buf,
-			    unsigned long size, int timeout);
-
 extern int ps3av_set_video_mode(u32, int);
 extern int ps3av_set_audio_mode(u32, u32, u32, u32, u32);
 extern int ps3av_get_auto_mode(int);
@@ -723,6 +720,9 @@ extern int ps3av_video_mute(int);
 extern int ps3av_audio_mute(int);
 extern int ps3av_dev_open(void);
 extern int ps3av_dev_close(void);
+extern void ps3av_register_flip_ctl(void (*flip_ctl)(int on, void *data),
+				    void *flip_data);
+extern void ps3av_flip_ctl(int on);
 
 #endif /* __KERNEL__ */
 #endif	/* _ASM_POWERPC_PS3AV_H_ */
#51 lore raw

Re: [patch 16/18] PS3: Rework AV settings driver

Quoted 2 lines · Geoff Levand
drivers/ps3/ps3av.c +0 -0

...

Quoted 1 line

+#define DEBUG

Another one

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE) [email protected] ------- The Corporate Village, Da Vincilaan 7-D1 Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

#52 lore raw

PATCH 17/18 PS3: Frame buffer system-bus rework

In reply to a message not in the archive

Convert the ps3fb device from a platform device to a PS3 system bus device. Fix the remove and shutdown methods to support kexec and to make ps3fb a loadable module.

---
 arch/powerpc/platforms/ps3/setup.c |    9 -
 drivers/video/Kconfig              |    4 
 drivers/video/ps3fb.c              |  300 +++++++++++++++++--------------------
 include/asm-powerpc/ps3fb.h        |   12 -
 4 files changed, 145 insertions(+), 180 deletions(-)
arch/powerpc/platforms/ps3/setup.c +5 -4
@@ -107,7 +107,7 @@ static void ps3_panic(char *str)
 	while(1);
 }
 
-#ifdef CONFIG_FB_PS3
+#if defined(CONFIG_FB_PS3) || defined(CONFIG_FB_PS3_MODULE)
 static void prealloc(struct ps3_prealloc *p)
 {
 	if (!p->size)
@@ -125,10 +125,11 @@ static void prealloc(struct ps3_prealloc
 }
 
 struct ps3_prealloc ps3fb_videomemory = {
-    .name = "ps3fb videomemory",
-    .size = CONFIG_FB_PS3_DEFAULT_SIZE_M*1024*1024,
-    .align = 1024*1024			/* the GPU requires 1 MiB alignment */
+	.name = "ps3fb videomemory",
+	.size = CONFIG_FB_PS3_DEFAULT_SIZE_M*1024*1024,
+	.align = 1024*1024		/* the GPU requires 1 MiB alignment */
 };
+EXPORT_SYMBOL_GPL(ps3fb_videomemory);
 #define prealloc_ps3fb_videomemory()	prealloc(&ps3fb_videomemory)
 
 static int __init early_parse_ps3fb(char *p)
drivers/video/Kconfig +2 -2
@@ -1790,8 +1790,8 @@ config FB_IBM_GXT4500
 	  adaptor, found on some IBM System P (pSeries) machines.
 
 config FB_PS3
-	bool "PS3 GPU framebuffer driver"
-	depends on (FB = y) && PS3_PS3AV
+	tristate "PS3 GPU framebuffer driver"
+	depends on FB && PS3_PS3AV
 	select FB_SYS_FILLRECT
 	select FB_SYS_COPYAREA
 	select FB_SYS_IMAGEBLIT
drivers/video/ps3fb.c +138 -162

457 lines not on this page · raw message

include/asm-powerpc/ps3fb.h +0 -12
@@ -41,16 +41,4 @@ struct ps3fb_ioctl_res {
 	__u32 num_frames; /* num of frame buffers */
 };
 
-#ifdef __KERNEL__
-
-#ifdef CONFIG_FB_PS3
-extern void ps3fb_flip_ctl(int on);
-extern void ps3fb_cleanup(void);
-#else
-static inline void ps3fb_flip_ctl(int on) {}
-static inline void ps3fb_cleanup(void) {}
-#endif
-
-#endif /* __KERNEL__ */
-
 #endif /* _ASM_POWERPC_PS3FB_H_ */
#53 lore raw

Re: [patch 17/18] PS3: Frame buffer system-bus rework

This one should go through linux-fbdev-devel (CC) for review, but Paul can merge it because it depends on the PS3 system bus device rework.

Quoted 550 lines · Geoff Levand

Convert the ps3fb device from a platform device to a PS3 system bus device. Fix the remove and shutdown methods to support kexec and to make ps3fb a loadable module.

---
 arch/powerpc/platforms/ps3/setup.c |    9 -
 drivers/video/Kconfig              |    4 
 drivers/video/ps3fb.c              |  300 +++++++++++++++++--------------------
 include/asm-powerpc/ps3fb.h        |   12 -
 4 files changed, 145 insertions(+), 180 deletions(-)
arch/powerpc/platforms/ps3/setup.c +5 -4
@@ -107,7 +107,7 @@ static void ps3_panic(char *str)
 	while(1);
 }
 
-#ifdef CONFIG_FB_PS3
+#if defined(CONFIG_FB_PS3) || defined(CONFIG_FB_PS3_MODULE)
 static void prealloc(struct ps3_prealloc *p)
 {
 	if (!p->size)
@@ -125,10 +125,11 @@ static void prealloc(struct ps3_prealloc
 }
 
 struct ps3_prealloc ps3fb_videomemory = {
-    .name = "ps3fb videomemory",
-    .size = CONFIG_FB_PS3_DEFAULT_SIZE_M*1024*1024,
-    .align = 1024*1024			/* the GPU requires 1 MiB alignment */
+	.name = "ps3fb videomemory",
+	.size = CONFIG_FB_PS3_DEFAULT_SIZE_M*1024*1024,
+	.align = 1024*1024		/* the GPU requires 1 MiB alignment */
 };
+EXPORT_SYMBOL_GPL(ps3fb_videomemory);
 #define prealloc_ps3fb_videomemory()	prealloc(&ps3fb_videomemory)
 
 static int __init early_parse_ps3fb(char *p)
drivers/video/Kconfig +2 -2
@@ -1790,8 +1790,8 @@ config FB_IBM_GXT4500
 	  adaptor, found on some IBM System P (pSeries) machines.
 
 config FB_PS3
-	bool "PS3 GPU framebuffer driver"
-	depends on (FB = y) && PS3_PS3AV
+	tristate "PS3 GPU framebuffer driver"
+	depends on FB && PS3_PS3AV
 	select FB_SYS_FILLRECT
 	select FB_SYS_COPYAREA
 	select FB_SYS_IMAGEBLIT
drivers/video/ps3fb.c +138 -162
@@ -27,7 +27,6 @@
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
-#include <linux/platform_device.h>
 #include <linux/console.h>
 #include <linux/ioctl.h>
 #include <linux/notifier.h>
@@ -46,6 +45,9 @@
 #include <asm/ps3fb.h>
 #include <asm/ps3.h>
 
+
+#define DEVICE_NAME		"ps3fb"
+
 #ifdef PS3FB_DEBUG
 #define DPRINTK(fmt, args...) printk("%s: " fmt, __func__ , ##args)
 #else
@@ -126,7 +128,6 @@ struct gpu_driver_info {
 
 struct ps3fb_priv {
 	unsigned int irq_no;
-	void *dev;
 
 	u64 context_handle, memory_handle;
 	void *xdr_ea;
@@ -171,7 +172,7 @@ static const struct ps3fb_res_table ps3f
 	{    0,    0,   0,   0 , 0} };
 
 /* default resolution */
-#define GPU_RES_INDEX 0		/* 720 x 480 */
+#define GPU_RES_INDEX	0		/* 720 x 480 */
 
 static const struct fb_videomode ps3fb_modedb[] = {
     /* 60 Hz broadcast modes (modes "1" to "5") */
@@ -298,10 +299,9 @@ static const struct fb_videomode ps3fb_m
 #define FB_OFF(i)	(GPU_OFFSET - VP_OFF(i) % GPU_OFFSET)
 
 static int ps3fb_mode;
-module_param(ps3fb_mode, bool, 0);
-
-static char *mode_option __initdata;
+module_param(ps3fb_mode, int, 0);
 
+static char *mode_option __devinitdata;
 
 static int ps3fb_get_res_table(u32 xres, u32 yres)
 {
@@ -681,15 +681,15 @@ int ps3fb_wait_for_vsync(u32 crtc)
 
 EXPORT_SYMBOL_GPL(ps3fb_wait_for_vsync);
 
-void ps3fb_flip_ctl(int on)
+void ps3fb_flip_ctl(int on, void *data)
 {
+	struct ps3fb_priv *priv = data;
 	if (on)
-		atomic_dec_if_positive(&ps3fb.ext_flip);
+		atomic_dec_if_positive(&priv->ext_flip);
 	else
-		atomic_inc(&ps3fb.ext_flip);
+		atomic_inc(&priv->ext_flip);
 }
 
-EXPORT_SYMBOL_GPL(ps3fb_flip_ctl);
 
     /*
      * ioctl
@@ -851,37 +851,9 @@ static irqreturn_t ps3fb_vsync_interrupt
 	return IRQ_HANDLED;
 }
 
-#ifndef MODULE
-static int __init ps3fb_setup(char *options)
-{
-	char *this_opt;
-	int mode = 0;
-
-	if (!options || !*options)
-		return 0;	/* no options */
-
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!*this_opt)
-			continue;
-		if (!strncmp(this_opt, "mode:", 5))
-			mode = simple_strtoul(this_opt + 5, NULL, 0);
-		else
-			mode_option = this_opt;
-	}
-	return mode;
-}
-#endif	/* MODULE */
-
-    /*
-     *  Initialisation
-     */
-
-static void ps3fb_platform_release(struct device *device)
-{
-	/* This is called when the reference count goes to zero. */
-}
 
-static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo, void *dev)
+static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo,
+				struct ps3_system_bus_device *dev)
 {
 	int error;
 
@@ -897,7 +869,6 @@ static int ps3fb_vsync_settings(struct g
 		return -EINVAL;
 	}
 
-	ps3fb.dev = dev;
 	error = ps3_irq_plug_setup(PS3_BINDING_CPU_ANY, dinfo->irq.irq_outlet,
 				   &ps3fb.irq_no);
 	if (error) {
@@ -907,7 +878,7 @@ static int ps3fb_vsync_settings(struct g
 	}
 
 	error = request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt, IRQF_DISABLED,
-			    "ps3fb vsync", ps3fb.dev);
+			    DEVICE_NAME, dev);
 	if (error) {
 		printk(KERN_ERR "%s: request_irq failed %d\n", __func__,
 		       error);
@@ -966,16 +937,47 @@ static struct fb_ops ps3fb_ops = {
 };
 
 static struct fb_fix_screeninfo ps3fb_fix __initdata = {
-	.id =		"PS3 FB",
+	.id =		DEVICE_NAME,
 	.type =		FB_TYPE_PACKED_PIXELS,
 	.visual =	FB_VISUAL_TRUECOLOR,
 	.accel =	FB_ACCEL_NONE,
 };
 
-static int __init ps3fb_probe(struct platform_device *dev)
+static int ps3fb_set_sync(void)
+{
+	int status;
+
+#ifdef HEAD_A
+	status = lv1_gpu_context_attribute(0x0,
+					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
+					   0, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);
+	if (status) {
+		printk(KERN_ERR
+		       "%s: lv1_gpu_context_attribute DISPLAY_SYNC failed: %d\n",
+		       __func__, status);
+		return -1;
+	}
+#endif
+#ifdef HEAD_B
+	status = lv1_gpu_context_attribute(0x0,
+					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
+					   1, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);
+
+	if (status) {
+		printk(KERN_ERR
+		       "%s: lv1_gpu_context_attribute DISPLAY_MODE failed: %d\n",
+		       __func__, status);
+		return -1;
+	}
+#endif
+	return 0;
+}
+
+static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
 {
 	struct fb_info *info;
 	int retval = -ENOMEM;
+	u32 xres, yres;
 	u64 ddr_lpar = 0;
 	u64 lpar_dma_control = 0;
 	u64 lpar_driver_info = 0;
@@ -986,6 +988,32 @@ static int __init ps3fb_probe(struct pla
 	unsigned long offset;
 	struct task_struct *task;
 
+	printk(" -> %s:%u\n", __func__, __LINE__);
+
+	status = ps3_open_hv_device(dev);
+	if (status) {
+		printk(KERN_ERR "%s: ps3_open_hv_device failed\n", __func__);
+		goto err;
+	}
+
+	if (!ps3fb_mode)
+		ps3fb_mode = ps3av_get_mode();
+	DPRINTK("ps3av_mode:%d\n", ps3fb_mode);
+
+	if (ps3fb_mode > 0 &&
+	    !ps3av_video_mode2res(ps3fb_mode, &xres, &yres)) {
+		ps3fb.res_index = ps3fb_get_res_table(xres, yres);
+		DPRINTK("res_index:%d\n", ps3fb.res_index);
+	} else
+		ps3fb.res_index = GPU_RES_INDEX;
+
+	atomic_set(&ps3fb.f_count, -1);	/* fbcon opens ps3fb */
+	atomic_set(&ps3fb.ext_flip, 0);	/* for flip with vsync */
+	init_waitqueue_head(&ps3fb.wait_vsync);
+	ps3fb.num_frames = 1;
+
+	ps3fb_set_sync();
+
 	/* get gpu context handle */
 	status = lv1_gpu_memory_allocate(DDR_SIZE, 0, 0, 0, 0,
 					 &ps3fb.memory_handle, &ddr_lpar);
@@ -1029,7 +1057,7 @@ static int __init ps3fb_probe(struct pla
 	 * leakage into userspace
 	 */
 	memset(ps3fb.xdr_ea, 0, ps3fb_videomemory.size);
-	info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
+	info = framebuffer_alloc(sizeof(u32) * 16, &dev->core);
 	if (!info)
 		goto err_free_irq;
 
@@ -1061,20 +1089,22 @@ static int __init ps3fb_probe(struct pla
 	if (retval < 0)
 		goto err_fb_dealloc;
 
-	platform_set_drvdata(dev, info);
+	dev->core.driver_data = info;
 
 	printk(KERN_INFO
 	       "fb%d: PS3 frame buffer device, using %ld KiB of video memory\n",
 	       info->node, ps3fb_videomemory.size >> 10);
 
-	task = kthread_run(ps3fbd, info, "ps3fbd");
+	task = kthread_run(ps3fbd, info, DEVICE_NAME);
 	if (IS_ERR(task)) {
 		retval = PTR_ERR(task);
 		goto err_unregister_framebuffer;
 	}
 
 	ps3fb.task = task;
+	ps3av_register_flip_ctl(ps3fb_flip_ctl, &ps3fb);
 
+	printk(" <- %s:%u\n", __func__, __LINE__);
 	return 0;
 
 err_unregister_framebuffer:
@@ -1084,7 +1114,7 @@ err_fb_dealloc:
 err_framebuffer_release:
 	framebuffer_release(info);
 err_free_irq:
-	free_irq(ps3fb.irq_no, ps3fb.dev);
+	free_irq(ps3fb.irq_no, dev);
 	ps3_irq_plug_destroy(ps3fb.irq_no);
 err_iounmap_dinfo:
 	iounmap((u8 __iomem *)ps3fb.dinfo);
@@ -1096,26 +1126,39 @@ err:
 	return retval;
 }
 
-static void ps3fb_shutdown(struct platform_device *dev)
+static int __devexit ps3fb_remove(struct ps3_system_bus_device *dev)
 {
-	ps3fb_flip_ctl(0);	/* flip off */
-	ps3fb.dinfo->irq.mask = 0;
-	free_irq(ps3fb.irq_no, ps3fb.dev);
-	ps3_irq_plug_destroy(ps3fb.irq_no);
-	iounmap((u8 __iomem *)ps3fb.dinfo);
+	BUG();
+	return 0;
 }
 
-void ps3fb_cleanup(void)
+static int ps3fb_shutdown(struct ps3_system_bus_device *dev)
 {
 	int status;
+	struct fb_info *info = dev->core.driver_data;
+
+	printk(" -> %s:%d\n", __func__, __LINE__);
+
+	// is this stuff ok here??
+	// just set .shutdown = ps3fb_remove???
+
+	ps3fb_flip_ctl(0, &ps3fb);	/* flip off */
+	ps3fb.dinfo->irq.mask = 0;
+
+	if (info) {
+		unregister_framebuffer(info);
+		fb_dealloc_cmap(&info->cmap);
+		framebuffer_release(info);
+	}
 
+	ps3av_register_flip_ctl(NULL, NULL);
 	if (ps3fb.task) {
 		struct task_struct *task = ps3fb.task;
 		ps3fb.task = NULL;
 		kthread_stop(task);
 	}
 	if (ps3fb.irq_no) {
-		free_irq(ps3fb.irq_no, ps3fb.dev);
+		free_irq(ps3fb.irq_no, dev);
 		ps3_irq_plug_destroy(ps3fb.irq_no);
 	}
 	iounmap((u8 __iomem *)ps3fb.dinfo);
@@ -1128,134 +1171,67 @@ void ps3fb_cleanup(void)
 	if (status)
 		DPRINTK("lv1_gpu_memory_free failed: %d\n", status);
 
-	ps3av_dev_close();
-}
-
-EXPORT_SYMBOL_GPL(ps3fb_cleanup);
+	ps3_close_hv_device(dev);
+	printk(" <- %s:%d\n", __func__, __LINE__);
 
-static int ps3fb_remove(struct platform_device *dev)
-{
-	struct fb_info *info = platform_get_drvdata(dev);
-
-	if (info) {
-		unregister_framebuffer(info);
-		fb_dealloc_cmap(&info->cmap);
-		framebuffer_release(info);
-	}
-	ps3fb_cleanup();
 	return 0;
 }
 
-static struct platform_driver ps3fb_driver = {
-	.probe	= ps3fb_probe,
-	.remove = ps3fb_remove,
-	.shutdown = ps3fb_shutdown,
-	.driver = { .name = "ps3fb" }
-};
-
-static struct platform_device ps3fb_device = {
-	.name	= "ps3fb",
-	.id	= 0,
-	.dev	= { .release = ps3fb_platform_release }
+static struct ps3_system_bus_driver ps3fb_driver = {
+	.match_id	= PS3_MATCH_ID_GRAPHICS,
+	.core.name	= DEVICE_NAME,
+	.core.owner	= THIS_MODULE,
+	.probe		= ps3fb_probe,
+	.remove		= __devexit_p(ps3fb_remove),
+	.shutdown	= ps3fb_shutdown,
 };
 
-int ps3fb_set_sync(void)
+static int __init ps3fb_setup(void)
 {
-	int status;
+	char *options, *this_opt;
 
-#ifdef HEAD_A
-	status = lv1_gpu_context_attribute(0x0,
-					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
-					   0, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);
-	if (status) {
-		printk(KERN_ERR
-		       "%s: lv1_gpu_context_attribute DISPLAY_SYNC failed: %d\n",
-		       __func__, status);
-		return -1;
-	}
+#ifdef MODULE
+	return 0;
 #endif
-#ifdef HEAD_B
-	status = lv1_gpu_context_attribute(0x0,
-					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
-					   1, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);
 
-	if (status) {
-		printk(KERN_ERR
-		       "%s: lv1_gpu_context_attribute DISPLAY_MODE failed: %d\n",
-		       __func__, status);
-		return -1;
+	if (fb_get_options(DEVICE_NAME, &options))
+		return -ENXIO;
+
+	if (!options || !*options)
+		return 0;
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!*this_opt)
+			continue;
+		if (!strncmp(this_opt, "mode:", 5))
+			ps3fb_mode = simple_strtoul(this_opt + 5, NULL, 0);
+		else
+			mode_option = this_opt;
 	}
-#endif
 	return 0;
 }
 
-EXPORT_SYMBOL_GPL(ps3fb_set_sync);
-
 static int __init ps3fb_init(void)
 {
-	int error;
-#ifndef MODULE
-	int mode;
-	char *option = NULL;
-
-	if (fb_get_options("ps3fb", &option))
-		goto err;
-#endif
-
-	if (!ps3fb_videomemory.address)
-		goto err;
-
-	error = ps3av_dev_open();
-	if (error) {
-		printk(KERN_ERR "%s: ps3av_dev_open failed\n", __func__);
-		goto err;
-	}
-
-	ps3fb_mode = ps3av_get_mode();
-	DPRINTK("ps3av_mode:%d\n", ps3fb_mode);
-#ifndef MODULE
-	mode = ps3fb_setup(option);	/* check boot option */
-	if (mode)
-		ps3fb_mode = mode;
-#endif
-	if (ps3fb_mode > 0) {
-		u32 xres, yres;
-		ps3av_video_mode2res(ps3fb_mode, &xres, &yres);
-		ps3fb.res_index = ps3fb_get_res_table(xres, yres);
-		DPRINTK("res_index:%d\n", ps3fb.res_index);
-	} else
-		ps3fb.res_index = GPU_RES_INDEX;
-
-	atomic_set(&ps3fb.f_count, -1);	/* fbcon opens ps3fb */
-	atomic_set(&ps3fb.ext_flip, 0);	/* for flip with vsync */
-	init_waitqueue_head(&ps3fb.wait_vsync);
-	ps3fb.num_frames = 1;
-
-	error = platform_driver_register(&ps3fb_driver);
-	if (!error) {
-		error = platform_device_register(&ps3fb_device);
-		if (error)
-			platform_driver_unregister(&ps3fb_driver);
-	}
-
-	ps3fb_set_sync();
-
-	return error;
+	if (!ps3fb_videomemory.address ||  ps3fb_setup())
+		return -ENXIO;
 
-err:
-	return -ENXIO;
+	return ps3_system_bus_driver_register(&ps3fb_driver);
 }
 
-module_init(ps3fb_init);
-
-#ifdef MODULE
 static void __exit ps3fb_exit(void)
 {
-	platform_device_unregister(&ps3fb_device);
-	platform_driver_unregister(&ps3fb_driver);
+	printk(" -> %s:%d\n", __func__, __LINE__);
+	ps3_system_bus_driver_unregister(&ps3fb_driver);
+	printk(" <- %s:%d\n", __func__, __LINE__);
 }
 
-module_exit(ps3fb_exit);
+module_init(ps3fb_init);
+#if 0
+module_exit(ps3fb_exit);	/* FIXME: need to fix fbcon to support remove */
+#endif
 
 MODULE_LICENSE("GPL");
-#endif				/* MODULE */
+MODULE_DESCRIPTION("PS3 GPU Frame Buffer Driver");
+MODULE_AUTHOR("Sony Computer Entertainment Inc.");
+MODULE_ALIAS(PS3_MODULE_ALIAS_GRAPHICS);
include/asm-powerpc/ps3fb.h +0 -12
@@ -41,16 +41,4 @@ struct ps3fb_ioctl_res {
 	__u32 num_frames; /* num of frame buffers */
 };
 
-#ifdef __KERNEL__
-
-#ifdef CONFIG_FB_PS3
-extern void ps3fb_flip_ctl(int on);
-extern void ps3fb_cleanup(void);
-#else
-static inline void ps3fb_flip_ctl(int on) {}
-static inline void ps3fb_cleanup(void) {}
-#endif
-
-#endif /* __KERNEL__ */
-
 #endif /* _ASM_POWERPC_PS3FB_H_ */
Signature · 1 line
-- 

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE) [email protected] ------- The Corporate Village, Da Vincilaan 7-D1 Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

#54 lore raw

Re: [Linux-fbdev-devel] [patch 17/18] PS3: Frame buffer system-bus rework

Quoted 5 lines · Geert Uytterhoeven

This one should go through linux-fbdev-devel (CC) for review, but Paul can merge it because it depends on the PS3 system bus device rework.

Quoted 1 line
Quoted 9 lines

drivers/video/ps3fb.c err: · line 1131

Quoted 9 lines
drivers/video/ps3fb.c +2 -6
-static void ps3fb_shutdown(struct platform_device *dev)
+static int __devexit ps3fb_remove(struct ps3_system_bus_device *dev)
 {
-	ps3fb_flip_ctl(0);	/* flip off */
-	ps3fb.dinfo->irq.mask = 0;
-	free_irq(ps3fb.irq_no, ps3fb.dev);
-	ps3_irq_plug_destroy(ps3fb.irq_no);
-	iounmap((u8 __iomem *)ps3fb.dinfo);
+	BUG();

Why BUG()?

Tony

#55 lore raw

Re: [Linux-fbdev-devel] [patch 17/18] PS3: Frame buffer system-bus rework

Hi.

Quoted 6 lines · Antonino A. Daplas
Quoted 5 lines · Geert Uytterhoeven

This one should go through linux-fbdev-devel (CC) for review, but Paul can merge it because it depends on the PS3 system bus device rework.

Quoted 1 line
Quoted 11 lines
Quoted 9 lines

drivers/video/ps3fb.c err: · line 1131

Quoted 9 lines
drivers/video/ps3fb.c +2 -6
-static void ps3fb_shutdown(struct platform_device *dev)
+static int __devexit ps3fb_remove(struct ps3_system_bus_device *dev)
 {
-	ps3fb_flip_ctl(0);	/* flip off */
-	ps3fb.dinfo->irq.mask = 0;
-	free_irq(ps3fb.irq_no, ps3fb.dev);
-	ps3_irq_plug_destroy(ps3fb.irq_no);
-	iounmap((u8 __iomem *)ps3fb.dinfo);
+	BUG();

Why BUG()?

remove() doesn't work because lack of support from fbcon. I'll remove this though, since it independent of the fbcon fix.

-Geoff

#56 lore raw

Re: [Linux-fbdev-devel] [patch 17/18] PS3: Frame buffer system-bus rework

Quoted 21 lines · Geoff Levand

Hi.

Quoted 6 lines · Antonino A. Daplas
Quoted 5 lines · Geert Uytterhoeven

This one should go through linux-fbdev-devel (CC) for review, but Paul can merge it because it depends on the PS3 system bus device rework.

Quoted 1 line
Quoted 11 lines
Quoted 9 lines

drivers/video/ps3fb.c err: · line 1131

Quoted 9 lines
drivers/video/ps3fb.c +2 -6
-static void ps3fb_shutdown(struct platform_device *dev)
+static int __devexit ps3fb_remove(struct ps3_system_bus_device *dev)
 {
-	ps3fb_flip_ctl(0);	/* flip off */
-	ps3fb.dinfo->irq.mask = 0;
-	free_irq(ps3fb.irq_no, ps3fb.dev);
-	ps3_irq_plug_destroy(ps3fb.irq_no);
-	iounmap((u8 __iomem *)ps3fb.dinfo);
+	BUG();

Why BUG()?

Quoted 1 line

remove() doesn't work because lack of support from fbcon.

We already have console registration/unregistration support for the past few kernel versions.

Quoted 2 lines

I'll remove
this though, since it independent of the fbcon fix.

This is part of module_exit(), correct? Then yes, module-init-tools will disallow rmmod to remove the module if fbcon is holding a reference count to it. However, if fbcon is not loaded, or fbcon is not bound to it (with an echo 0 > /sys/class/vtconsole/vtcon1/bind), then rmmod will succeed, and so should ps3fb_remove().

Tony

#57 lore raw

PATCH 18/18 PS3: Device registration routines.

In reply to a message not in the archive

Add routines to probe devices present on the system and to register those devices with the LDM.

---
 arch/powerpc/platforms/ps3/Makefile      |    1 
 arch/powerpc/platforms/ps3/device-init.c |  791 +++++++++++++++++++++++++++++++
 2 files changed, 792 insertions(+)
arch/powerpc/platforms/ps3/Makefile +1 -0
@@ -4,3 +4,4 @@ obj-y += system-bus.o
 
 obj-$(CONFIG_SMP) += smp.o
 obj-$(CONFIG_SPU_BASE) += spu.o
+obj-y += device-init.o
arch/powerpc/platforms/ps3/device-init.c new file +791 -0

791 lines not on this page · raw message

#58 lore raw

Re: [patch 18/18] PS3: Device registration routines.

Quoted 2 lines · Geoff Levand

Add routines to probe devices present on the system and to register those devices with the LDM.

This one depends on the storage driver core, which I submitted for review on May 25, but which have changed in the mean time due to the PS3 system bus device rework.

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE) [email protected] ------- The Corporate Village, Da Vincilaan 7-D1 Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium

#59 lore raw

Re: [patch 18/18] PS3: Device registration routines.

In reply to Geoff Levand
Quoted 6 lines · Geoff Levand
(quoted diff) +6 -0
+static int __init ps3_register_vuart_devices(void)
+{
+	int result;
+	unsigned int port_number;
+
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);

Review

Quoted 10 lines
(quoted diff) +10 -0
+
+	result = ps3_repository_read_vuart_av_port(&port_number);
+
+	if (result)
+		port_number = 0; /* av default */
+
+	result = ps3_setup_vuart_device(PS3_MATCH_ID_AV_SETTINGS, port_number);
+	WARN_ON(result);
+
+	ps3_repository_read_vuart_sysmgr_port(&port_number);
    ^^^^

Review

Quoted 3 lines
(quoted diff) +3 -0
+
+	if (result)
+		port_number = 2; /* sysmgr default */

You forgot to assign the return value of ps3_repository_read_vuart_sysmgr_port(). As the system manager vuart port number is not in the repository on the firmware I'm using, port_number contains garbage, and ps3_vuart_probe() will BUG().

As this problem is present in your current git tree, here's a patch:

Subject: [PATCH] Check return value of ps3_repository_read_vuart_sysmgr_port()

Add a missing assignment of the return value of ps3_repository_read_vuart_sysmgr_port(). As the system manager vuart port number is not in the repository on the firmware I'm using, port_number contains garbage, and ps3_vuart_probe() will BUG().

arch/powerpc/platforms/ps3/device-init.c +1 -3
@@ -505,15 +505,13 @@ static int __init ps3_register_vuart_dev
 	pr_debug(" -> %s:%d\n", __func__, __LINE__);
 
 	result = ps3_repository_read_vuart_av_port(&port_number);
-
 	if (result)
 		port_number = 0; /* av default */
 
 	result = ps3_setup_vuart_device(PS3_MATCH_ID_AV_SETTINGS, port_number);
 	WARN_ON(result);
 
-	ps3_repository_read_vuart_sysmgr_port(&port_number);
-
+	result = ps3_repository_read_vuart_sysmgr_port(&port_number);
 	if (result)
 		port_number = 2; /* sysmgr default */
 

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- Sony Network and Software Technology Center Europe (NSCE) [email protected] ------- The Corporate Village, Da Vincilaan 7-D1 Voice +32-2-7008453 Fax +32-2-7008622 ---------------- B-1935 Zaventem, Belgium