LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [patch 21/33] PS3: Use clear_bit
From: Geoff Levand @ 2007-06-15 22:06 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev
In-Reply-To: <20070615204749.629571012@am.sony.com>

Replace the inline asm with bitops in the PS3 interrupt
chip mask routines.

Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
 arch/powerpc/platforms/ps3/interrupt.c |   26 ++------------------------
 1 file changed, 2 insertions(+), 24 deletions(-)

--- a/arch/powerpc/platforms/ps3/interrupt.c
+++ b/arch/powerpc/platforms/ps3/interrupt.c
@@ -100,24 +100,13 @@ static DEFINE_PER_CPU(struct ps3_private
 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: thread_id %lu, virq %d\n", __func__, __LINE__,
 		pd->thread_id, 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" );
-
+	clear_bit(63 - virq, &pd->bmp.mask);
 	lv1_did_update_interrupt_mask(pd->ppe_id, pd->thread_id);
 	local_irq_restore(flags);
 }
@@ -132,24 +121,13 @@ static void ps3_chip_mask(unsigned int v
 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: thread_id %lu, virq %d\n", __func__, __LINE__,
 		pd->thread_id, 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" );
-
+	set_bit(63 - virq, &pd->bmp.mask);
 	lv1_did_update_interrupt_mask(pd->ppe_id, pd->thread_id);
 	local_irq_restore(flags);
 }

-- 

^ permalink raw reply

* [patch 16/33] PS3: System manager re-work
From: Geoff Levand @ 2007-06-15 22:03 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev
In-Reply-To: <20070615204749.629571012@am.sony.com>

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.

Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
 drivers/ps3/Makefile           |    1 
 drivers/ps3/sys-manager-core.c |   68 +++++++++
 drivers/ps3/sys-manager.c      |  290 +++++++++++++++++++++++++++--------------
 include/asm-powerpc/ps3.h      |   15 +-
 4 files changed, 269 insertions(+), 105 deletions(-)

--- a/drivers/ps3/Makefile
+++ b/drivers/ps3/Makefile
@@ -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
--- /dev/null
+++ b/drivers/ps3/sys-manager-core.c
@@ -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.
+ *
+ *  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
+ */
+
+#include <linux/kernel.h>
+#include <asm/ps3.h>
+
+/**
+ * Staticly linked routines that allow late binding of a loaded sys-manager
+ * module.
+ */
+
+static struct ps3_sys_manager_ops ps3_sys_manager_ops;
+
+/**
+ * ps3_register_sys_manager_ops - Bind ps3_sys_manager_ops to a module.
+ * @ops: struct ps3_sys_manager_ops.
+ *
+ * To be called from ps3_sys_manager_probe() and ps3_sys_manager_remove() to
+ * register call back ops for power control.  Copies data to the static
+ * variable ps3_sys_manager_ops.
+ */
+
+void ps3_sys_manager_register_ops(const struct ps3_sys_manager_ops *ops)
+{
+	BUG_ON(!ops);
+	BUG_ON(!ops->dev);
+	ps3_sys_manager_ops = ops ? *ops : ps3_sys_manager_ops;
+}
+EXPORT_SYMBOL_GPL(ps3_sys_manager_register_ops);
+
+void ps3_sys_manager_power_off(void)
+{
+	if (ps3_sys_manager_ops.power_off)
+		ps3_sys_manager_ops.power_off(ps3_sys_manager_ops.dev);
+
+	printk(KERN_EMERG "System Halted, OK to turn off power\n");
+	local_irq_disable();
+	while (1)
+		(void)0;
+}
+
+void ps3_sys_manager_restart(void)
+{
+	if (ps3_sys_manager_ops.restart)
+		ps3_sys_manager_ops.restart(ps3_sys_manager_ops.dev);
+
+	printk(KERN_EMERG "System Halted, OK to turn off power\n");
+	local_irq_disable();
+	while (1)
+		(void)0;
+}
--- a/drivers/ps3/sys-manager.c
+++ b/drivers/ps3/sys-manager.c
@@ -35,7 +35,7 @@ MODULE_DESCRIPTION("PS3 System Manager")
 /**
  * ps3_sys_manager - PS3 system manager driver.
  *
- * The system manager provides an asyncronous system event notification
+ * The system manager provides an asynchronous system event notification
  * mechanism for reporting events like thermal alert and button presses to
  * guests.  It also provides support to control system shutdown and startup.
  *
@@ -52,6 +52,7 @@ MODULE_DESCRIPTION("PS3 System Manager")
  * @size: Header size in bytes, curently 16.
  * @payload_size: Message payload size in bytes.
  * @service_id: Message type, one of enum ps3_sys_manager_service_id.
+ * @request_tag: Unique number to identify reply.
  */
 
 struct ps3_sys_manager_header {
@@ -61,29 +62,49 @@ struct ps3_sys_manager_header {
 	u16 reserved_1;
 	u32 payload_size;
 	u16 service_id;
-	u16 reserved_2[3];
+	u16 reserved_2;
+	u32 request_tag;
 };
 
+#define dump_sm_header(_h) _dump_sm_header(_h, __func__, __LINE__)
+static void __maybe_unused _dump_sm_header(
+	const struct ps3_sys_manager_header *h, const char *func, int line)
+{
+	pr_debug("%s:%d: version:      %xh\n", func, line, h->version);
+	pr_debug("%s:%d: size:         %xh\n", func, line, h->size);
+	pr_debug("%s:%d: payload_size: %xh\n", func, line, h->payload_size);
+	pr_debug("%s:%d: service_id:   %xh\n", func, line, h->service_id);
+	pr_debug("%s:%d: request_tag:  %xh\n", func, line, h->request_tag);
+}
+
 /**
- * @PS3_SM_RX_MSG_LEN - System manager received message length.
+ * @PS3_SM_RX_MSG_LEN_MIN - Shortest received message length.
+ * @PS3_SM_RX_MSG_LEN_MAX - Longest received message length.
  *
- * Currently all messages received from the system manager are the same length
- * (16 bytes header + 16 bytes payload = 32 bytes).  This knowlege is used to
- * simplify the logic.
+ * Currently all messages received from the system manager are either
+ * (16 bytes header + 8 bytes payload = 24 bytes) or (16 bytes header
+ * + 16 bytes payload = 32 bytes).  This knowlege is used to simplify
+ * the logic.
  */
 
 enum {
-	PS3_SM_RX_MSG_LEN = 32,
+	PS3_SM_RX_MSG_LEN_MIN = 24,
+	PS3_SM_RX_MSG_LEN_MAX = 32,
 };
 
 /**
  * enum ps3_sys_manager_service_id - Message header service_id.
- * @PS3_SM_SERVICE_ID_REQUEST:      guest --> sys_manager.
- * @PS3_SM_SERVICE_ID_COMMAND:      guest <-- sys_manager.
- * @PS3_SM_SERVICE_ID_RESPONSE:     guest --> sys_manager.
- * @PS3_SM_SERVICE_ID_SET_ATTR:     guest --> sys_manager.
- * @PS3_SM_SERVICE_ID_EXTERN_EVENT: guest <-- sys_manager.
- * @PS3_SM_SERVICE_ID_SET_NEXT_OP:  guest --> sys_manager.
+ * @PS3_SM_SERVICE_ID_REQUEST:       guest --> sys_manager.
+ * @PS3_SM_SERVICE_ID_REQUEST_ERROR: guest <-- sys_manager.
+ * @PS3_SM_SERVICE_ID_COMMAND:       guest <-- sys_manager.
+ * @PS3_SM_SERVICE_ID_RESPONSE:      guest --> sys_manager.
+ * @PS3_SM_SERVICE_ID_SET_ATTR:      guest --> sys_manager.
+ * @PS3_SM_SERVICE_ID_EXTERN_EVENT:  guest <-- sys_manager.
+ * @PS3_SM_SERVICE_ID_SET_NEXT_OP:   guest --> sys_manager.
+ *
+ * PS3_SM_SERVICE_ID_REQUEST_ERROR is returned for invalid data values in a
+ * a PS3_SM_SERVICE_ID_REQUEST message.  It also seems to be returned when
+ * a REQUEST message is sent at the wrong time.
  */
 
 enum ps3_sys_manager_service_id {
@@ -93,6 +114,7 @@ enum ps3_sys_manager_service_id {
 	PS3_SM_SERVICE_ID_COMMAND = 3,
 	PS3_SM_SERVICE_ID_EXTERN_EVENT = 4,
 	PS3_SM_SERVICE_ID_SET_NEXT_OP = 5,
+	PS3_SM_SERVICE_ID_REQUEST_ERROR = 6,
 	PS3_SM_SERVICE_ID_SET_ATTR = 8,
 };
 
@@ -185,11 +207,21 @@ enum ps3_sys_manager_cmd {
 };
 
 /**
+ * ps3_sm_force_power_off - Poweroff helper.
+ *
+ * A global variable used to force a poweroff when the power button has
+ * been pressed irrespective of how init handles the ctrl_alt_del signal.
+ *
+ */
+
+static unsigned int ps3_sm_force_power_off;
+
+/**
  * ps3_sys_manager_write - Helper to write a two part message to the vuart.
  *
  */
 
-static int ps3_sys_manager_write(struct ps3_vuart_port_device *dev,
+static int ps3_sys_manager_write(struct ps3_system_bus_device *dev,
 	const struct ps3_sys_manager_header *header, const void *payload)
 {
 	int result;
@@ -213,15 +245,10 @@ static int ps3_sys_manager_write(struct 
  *
  */
 
-static int ps3_sys_manager_send_attr(struct ps3_vuart_port_device *dev,
+static int ps3_sys_manager_send_attr(struct ps3_system_bus_device *dev,
 	enum ps3_sys_manager_attr attr)
 {
-	static const struct ps3_sys_manager_header header = {
-		.version = 1,
-		.size = 16,
-		.payload_size = 16,
-		.service_id = PS3_SM_SERVICE_ID_SET_ATTR,
-	};
+	struct ps3_sys_manager_header header;
 	struct {
 		u8 version;
 		u8 reserved_1[3];
@@ -232,6 +259,12 @@ static int ps3_sys_manager_send_attr(str
 
 	dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, attr);
 
+	memset(&header, 0, sizeof(header));
+	header.version = 1;
+	header.size = 16;
+	header.payload_size = 16;
+	header.service_id = PS3_SM_SERVICE_ID_SET_ATTR;
+
 	memset(&payload, 0, sizeof(payload));
 	payload.version = 1;
 	payload.attribute = attr;
@@ -245,16 +278,11 @@ static int ps3_sys_manager_send_attr(str
  * Tell the system manager what to do after this lpar is destroyed.
  */
 
-static int ps3_sys_manager_send_next_op(struct ps3_vuart_port_device *dev,
+static int ps3_sys_manager_send_next_op(struct ps3_system_bus_device *dev,
 	enum ps3_sys_manager_next_op op,
 	enum ps3_sys_manager_wake_source wake_source)
 {
-	static const struct ps3_sys_manager_header header = {
-		.version = 1,
-		.size = 16,
-		.payload_size = 16,
-		.service_id = PS3_SM_SERVICE_ID_SET_NEXT_OP,
-	};
+	struct ps3_sys_manager_header header;
 	struct {
 		u8 version;
 		u8 type;
@@ -268,6 +296,12 @@ static int ps3_sys_manager_send_next_op(
 
 	dev_dbg(&dev->core, "%s:%d: (%xh)\n", __func__, __LINE__, op);
 
+	memset(&header, 0, sizeof(header));
+	header.version = 1;
+	header.size = 16;
+	header.payload_size = 16;
+	header.service_id = PS3_SM_SERVICE_ID_SET_NEXT_OP;
+
 	memset(&payload, 0, sizeof(payload));
 	payload.version = 3;
 	payload.type = op;
@@ -286,32 +320,35 @@ static int ps3_sys_manager_send_next_op(
  * the command is then communicated back to the system manager with a response
  * message.
  *
- * Currently, the only supported request it the 'shutdown self' request.
+ * Currently, the only supported request is the 'shutdown self' request.
  */
 
-static int ps3_sys_manager_send_request_shutdown(struct ps3_vuart_port_device *dev)
+static int ps3_sys_manager_send_request_shutdown(
+	struct ps3_system_bus_device *dev)
 {
-	static const struct ps3_sys_manager_header header = {
-		.version = 1,
-		.size = 16,
-		.payload_size = 16,
-		.service_id = PS3_SM_SERVICE_ID_REQUEST,
-	};
+	struct ps3_sys_manager_header header;
 	struct {
 		u8 version;
 		u8 type;
 		u8 gos_id;
 		u8 reserved_1[13];
-	} static const payload = {
-		.version = 1,
-		.type = 1, /* shutdown */
-		.gos_id = 0, /* self */
-	};
+	} payload;
 
 	BUILD_BUG_ON(sizeof(payload) != 16);
 
 	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
 
+	memset(&header, 0, sizeof(header));
+	header.version = 1;
+	header.size = 16;
+	header.payload_size = 16;
+	header.service_id = PS3_SM_SERVICE_ID_REQUEST;
+
+	memset(&payload, 0, sizeof(payload));
+	payload.version = 1;
+	payload.type = 1; /* shutdown */
+	payload.gos_id = 0; /* self */
+
 	return ps3_sys_manager_write(dev, &header, &payload);
 }
 
@@ -323,15 +360,10 @@ static int ps3_sys_manager_send_request_
  * failure of a command sent by the system manager.
  */
 
-static int ps3_sys_manager_send_response(struct ps3_vuart_port_device *dev,
+static int ps3_sys_manager_send_response(struct ps3_system_bus_device *dev,
 	u64 status)
 {
-	static const struct ps3_sys_manager_header header = {
-		.version = 1,
-		.size = 16,
-		.payload_size = 16,
-		.service_id = PS3_SM_SERVICE_ID_RESPONSE,
-	};
+	struct ps3_sys_manager_header header;
 	struct {
 		u8 version;
 		u8 reserved_1[3];
@@ -344,6 +376,12 @@ static int ps3_sys_manager_send_response
 	dev_dbg(&dev->core, "%s:%d: (%s)\n", __func__, __LINE__,
 		(status ? "nak" : "ack"));
 
+	memset(&header, 0, sizeof(header));
+	header.version = 1;
+	header.size = 16;
+	header.payload_size = 16;
+	header.service_id = PS3_SM_SERVICE_ID_RESPONSE;
+
 	memset(&payload, 0, sizeof(payload));
 	payload.version = 1;
 	payload.status = status;
@@ -356,7 +394,7 @@ static int ps3_sys_manager_send_response
  *
  */
 
-static int ps3_sys_manager_handle_event(struct ps3_vuart_port_device *dev)
+static int ps3_sys_manager_handle_event(struct ps3_system_bus_device *dev)
 {
 	int result;
 	struct {
@@ -370,7 +408,7 @@ static int ps3_sys_manager_handle_event(
 	BUILD_BUG_ON(sizeof(event) != 16);
 
 	result = ps3_vuart_read(dev, &event, sizeof(event));
-	BUG_ON(result);
+	BUG_ON(result && "need to retry here");
 
 	if (event.version != 1) {
 		dev_dbg(&dev->core, "%s:%d: unsupported event version (%u)\n",
@@ -382,11 +420,34 @@ static int ps3_sys_manager_handle_event(
 	case PS3_SM_EVENT_POWER_PRESSED:
 		dev_dbg(&dev->core, "%s:%d: POWER_PRESSED\n",
 			__func__, __LINE__);
+		ps3_sm_force_power_off = 1;
+		/*
+		 * A memory barrier is use here to sync memory since
+		 * ps3_sys_manager_final_restart() could be called on
+		 * another cpu.
+		 */
+		wmb();
+		kill_cad_pid(SIGINT, 1); /* ctrl_alt_del */
 		break;
 	case PS3_SM_EVENT_POWER_RELEASED:
 		dev_dbg(&dev->core, "%s:%d: POWER_RELEASED (%u ms)\n",
 			__func__, __LINE__, event.value);
-		kill_cad_pid(SIGINT, 1);
+		break;
+	case PS3_SM_EVENT_RESET_PRESSED:
+		dev_dbg(&dev->core, "%s:%d: RESET_PRESSED\n",
+			__func__, __LINE__);
+		ps3_sm_force_power_off = 0;
+		/*
+		 * A memory barrier is use here to sync memory since
+		 * ps3_sys_manager_final_restart() could be called on
+		 * another cpu.
+		 */
+		wmb();
+		kill_cad_pid(SIGINT, 1); /* ctrl_alt_del */
+		break;
+	case PS3_SM_EVENT_RESET_RELEASED:
+		dev_dbg(&dev->core, "%s:%d: RESET_RELEASED (%u ms)\n",
+			__func__, __LINE__, event.value);
 		break;
 	case PS3_SM_EVENT_THERMAL_ALERT:
 		dev_dbg(&dev->core, "%s:%d: THERMAL_ALERT (zone %u)\n",
@@ -411,7 +472,7 @@ static int ps3_sys_manager_handle_event(
  * The system manager sends this in reply to a 'request' message from the guest.
  */
 
-static int ps3_sys_manager_handle_cmd(struct ps3_vuart_port_device *dev)
+static int ps3_sys_manager_handle_cmd(struct ps3_system_bus_device *dev)
 {
 	int result;
 	struct {
@@ -425,6 +486,7 @@ static int ps3_sys_manager_handle_cmd(st
 	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
 
 	result = ps3_vuart_read(dev, &cmd, sizeof(cmd));
+	BUG_ON(result && "need to retry here");
 
 	if(result)
 		return result;
@@ -448,9 +510,10 @@ static int ps3_sys_manager_handle_cmd(st
 /**
  * ps3_sys_manager_handle_msg - First stage msg handler.
  *
+ * Can be called directly to manually poll vuart and pump message handler.
  */
 
-static int ps3_sys_manager_handle_msg(struct ps3_vuart_port_device *dev)
+static int ps3_sys_manager_handle_msg(struct ps3_system_bus_device *dev)
 {
 	int result;
 	struct ps3_sys_manager_header header;
@@ -464,12 +527,17 @@ static int ps3_sys_manager_handle_msg(st
 	if (header.version != 1) {
 		dev_dbg(&dev->core, "%s:%d: unsupported header version (%u)\n",
 			__func__, __LINE__, header.version);
+		dump_sm_header(&header);
 		goto fail_header;
 	}
 
 	BUILD_BUG_ON(sizeof(header) != 16);
-	BUG_ON(header.size != 16);
-	BUG_ON(header.payload_size != 16);
+
+	if (header.size != 16 || (header.payload_size != 8
+		&& header.payload_size != 16)) {
+		dump_sm_header(&header);
+		BUG();
+	}
 
 	switch (header.service_id) {
 	case PS3_SM_SERVICE_ID_EXTERN_EVENT:
@@ -478,6 +546,11 @@ static int ps3_sys_manager_handle_msg(st
 	case PS3_SM_SERVICE_ID_COMMAND:
 		dev_dbg(&dev->core, "%s:%d: COMMAND\n", __func__, __LINE__);
 		return ps3_sys_manager_handle_cmd(dev);
+	case PS3_SM_SERVICE_ID_REQUEST_ERROR:
+		dev_dbg(&dev->core, "%s:%d: REQUEST_ERROR\n", __func__,
+			__LINE__);
+		dump_sm_header(&header);
+		break;
 	default:
 		dev_dbg(&dev->core, "%s:%d: unknown service_id (%u)\n",
 			__func__, __LINE__, header.service_id);
@@ -494,45 +567,25 @@ fail_id:
 }
 
 /**
- * ps3_sys_manager_work - Asyncronous read handler.
+ * ps3_sys_manager_final_power_off - The final platform machine_power_off routine.
  *
- * Signaled when a complete message arrives at the vuart port.
- */
-
-static void ps3_sys_manager_work(struct work_struct *work)
-{
-	struct ps3_vuart_port_device *dev = ps3_vuart_work_to_port_device(work);
-
-	ps3_sys_manager_handle_msg(dev);
-	ps3_vuart_read_async(dev, ps3_sys_manager_work, PS3_SM_RX_MSG_LEN);
-}
-
-struct {
-	struct ps3_vuart_port_device *dev;
-} static drv_priv;
-
-/**
- * ps3_sys_manager_restart - The final platform machine_restart routine.
- *
- * This routine never returns.  The routine disables asyncronous vuart reads
+ * This routine never returns.  The routine disables asynchronous vuart reads
  * then spins calling ps3_sys_manager_handle_msg() to receive and acknowledge
  * the shutdown command sent from the system manager.  Soon after the
  * acknowledgement is sent the lpar is destroyed by the HV.  This routine
- * should only be called from ps3_restart().
+ * should only be called from ps3_power_off() through
+ * ps3_sys_manager_ops.power_off.
  */
 
-void ps3_sys_manager_restart(void)
+static void ps3_sys_manager_final_power_off(struct ps3_system_bus_device *dev)
 {
-	struct ps3_vuart_port_device *dev = drv_priv.dev;
-
-	BUG_ON(!drv_priv.dev);
+	BUG_ON(!dev);
 
 	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
 
 	ps3_vuart_cancel_async(dev);
 
-	ps3_sys_manager_send_attr(dev, 0);
-	ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_LPAR_REBOOT,
+	ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_SYS_SHUTDOWN,
 		PS3_SM_WAKE_DEFAULT);
 	ps3_sys_manager_send_request_shutdown(dev);
 
@@ -543,26 +596,33 @@ void ps3_sys_manager_restart(void)
 }
 
 /**
- * ps3_sys_manager_power_off - The final platform machine_power_off routine.
+ * ps3_sys_manager_final_restart - The final platform machine_restart routine.
  *
- * This routine never returns.  The routine disables asyncronous vuart reads
+ * This routine never returns.  The routine disables asynchronous vuart reads
  * then spins calling ps3_sys_manager_handle_msg() to receive and acknowledge
  * the shutdown command sent from the system manager.  Soon after the
  * acknowledgement is sent the lpar is destroyed by the HV.  This routine
- * should only be called from ps3_power_off().
+ * should only be called from ps3_restart() through ps3_sys_manager_ops.restart.
  */
 
-void ps3_sys_manager_power_off(void)
+static void ps3_sys_manager_final_restart(struct ps3_system_bus_device *dev)
 {
-	struct ps3_vuart_port_device *dev = drv_priv.dev;
-
-	BUG_ON(!drv_priv.dev);
+	BUG_ON(!dev);
 
 	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
 
+	/* Check if we got here via a power button event. */
+
+	if (ps3_sm_force_power_off) {
+		dev_dbg(&dev->core, "%s:%d: forcing poweroff\n",
+			__func__, __LINE__);
+		ps3_sys_manager_final_power_off(dev);
+	}
+
 	ps3_vuart_cancel_async(dev);
 
-	ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_SYS_SHUTDOWN,
+	ps3_sys_manager_send_attr(dev, 0);
+	ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_LPAR_REBOOT,
 		PS3_SM_WAKE_DEFAULT);
 	ps3_sys_manager_send_request_shutdown(dev);
 
@@ -572,31 +632,60 @@ void ps3_sys_manager_power_off(void)
 		ps3_sys_manager_handle_msg(dev);
 }
 
-static int ps3_sys_manager_probe(struct ps3_vuart_port_device *dev)
+/**
+ * ps3_sys_manager_work - Asynchronous read handler.
+ *
+ * Signaled when PS3_SM_RX_MSG_LEN_MIN bytes arrive at the vuart port.
+ */
+
+static void ps3_sys_manager_work(struct ps3_system_bus_device *dev)
+{
+	ps3_sys_manager_handle_msg(dev);
+	ps3_vuart_read_async(dev, PS3_SM_RX_MSG_LEN_MIN);
+}
+
+static int ps3_sys_manager_probe(struct ps3_system_bus_device *dev)
 {
 	int result;
+	struct ps3_sys_manager_ops ops;
 
 	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
 
-	BUG_ON(drv_priv.dev);
-	drv_priv.dev = dev;
+	ops.power_off = ps3_sys_manager_final_power_off;
+	ops.restart = ps3_sys_manager_final_restart;
+	ops.dev = dev;
+
+	/* ps3_sys_manager_register_ops copies ops. */
+
+	ps3_sys_manager_register_ops(&ops);
 
 	result = ps3_sys_manager_send_attr(dev, PS3_SM_ATTR_ALL);
 	BUG_ON(result);
 
-	result = ps3_vuart_read_async(dev, ps3_sys_manager_work,
-		PS3_SM_RX_MSG_LEN);
+	result = ps3_vuart_read_async(dev, PS3_SM_RX_MSG_LEN_MIN);
 	BUG_ON(result);
 
 	return result;
 }
 
+static int ps3_sys_manager_remove(struct ps3_system_bus_device *dev)
+{
+	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+	return 0;
+}
+
+static void ps3_sys_manager_shutdown(struct ps3_system_bus_device *dev)
+{
+	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+}
+
 static struct ps3_vuart_port_driver ps3_sys_manager = {
-	.match_id = PS3_MATCH_ID_SYSTEM_MANAGER,
-	.core = {
-		.name = "ps3_sys_manager",
-	},
+	.core.match_id = PS3_MATCH_ID_SYSTEM_MANAGER,
+	.core.core.name = "ps3_sys_manager",
 	.probe = ps3_sys_manager_probe,
+	.remove = ps3_sys_manager_remove,
+	.shutdown = ps3_sys_manager_shutdown,
+	.work = ps3_sys_manager_work,
 };
 
 static int __init ps3_sys_manager_init(void)
@@ -608,3 +697,6 @@ static int __init ps3_sys_manager_init(v
 }
 
 module_init(ps3_sys_manager_init);
+/* Module remove not supported. */
+
+MODULE_ALIAS(PS3_MODULE_ALIAS_SYSTEM_MANAGER);
--- a/include/asm-powerpc/ps3.h
+++ b/include/asm-powerpc/ps3.h
@@ -409,13 +409,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;
@@ -426,4 +428,5 @@ struct ps3_prealloc {
 
 extern struct ps3_prealloc ps3fb_videomemory;
 
+
 #endif

-- 

^ permalink raw reply

* [patch 04/33] PS3: Compare firmware version
From: Geoff Levand @ 2007-06-15 21:18 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev
In-Reply-To: <20070615204749.629571012@am.sony.com>

From: Masakazu Mokuno <mokuno@sm.sony.co.jp>

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

Signed-off-by: Masakazu Mokuno <mokuno@sm.sony.co.jp>
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
 arch/powerpc/platforms/ps3/setup.c |   32 ++++++++++++++++++++------------
 include/asm-powerpc/ps3.h          |    3 ++-
 2 files changed, 22 insertions(+), 13 deletions(-)

--- a/arch/powerpc/platforms/ps3/setup.c
+++ b/arch/powerpc/platforms/ps3/setup.c
@@ -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();
--- a/include/asm-powerpc/ps3.h
+++ b/include/asm-powerpc/ps3.h
@@ -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 */
 

-- 

^ permalink raw reply

* [patch 23/33] powerpc: Localize mmu_off
From: Geoff Levand @ 2007-06-15 22:06 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev
In-Reply-To: <20070615204749.629571012@am.sony.com>

This just removes the dependency __mmu_off has on the symbol
__after_prom_start.  I found the current code inconvenient when I
wanted to put some debugging code between the call to __mmu_off
and the branch to __after_prom_start.

Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
 arch/powerpc/kernel/head_64.S |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -1695,9 +1695,11 @@ _GLOBAL(__start_initialization_multiplat
 2:
 
 	/* Switch off MMU if not already */
-	LOAD_REG_IMMEDIATE(r4, .__after_prom_start - KERNELBASE)
+	LOAD_REG_IMMEDIATE(r4, __mmu_off_return - KERNELBASE)
 	add	r4,r4,r30
 	bl	.__mmu_off
+__mmu_off_return:
+
 	b	.__after_prom_start
 
 _STATIC(__boot_from_prom)

-- 

^ permalink raw reply

* [patch 18/33] PS3: Frame buffer system-bus rework
From: Geoff Levand @ 2007-06-15 22:05 UTC (permalink / raw)
  To: paulus; +Cc: Geert Uytterhoeven, linuxppc-dev, linux-fbdev-devel
In-Reply-To: <20070615204749.629571012@am.sony.com>

From: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>

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.

Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
 arch/powerpc/platforms/ps3/setup.c |    9 -
 drivers/video/Kconfig              |    4 
 drivers/video/ps3fb.c              |  290 ++++++++++++++++---------------------
 include/asm-powerpc/ps3fb.h        |   12 -
 4 files changed, 134 insertions(+), 181 deletions(-)

--- a/arch/powerpc/platforms/ps3/setup.c
+++ b/arch/powerpc/platforms/ps3/setup.c
@@ -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)
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -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
--- a/drivers/video/ps3fb.c
+++ b/drivers/video/ps3fb.c
@@ -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,45 @@ 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 +986,30 @@ static int __init ps3fb_probe(struct pla
 	unsigned long offset;
 	struct task_struct *task;
 
+	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 +1053,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,19 +1085,20 @@ 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);
 
 	return 0;
 
@@ -1084,7 +1109,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 +1121,30 @@ err:
 	return retval;
 }
 
-static void ps3fb_shutdown(struct platform_device *dev)
+static int ps3fb_shutdown(struct ps3_system_bus_device *dev)
 {
-	ps3fb_flip_ctl(0);	/* flip off */
+	int status;
+	struct fb_info *info = dev->core.driver_data;
+
+	DPRINTK(" -> %s:%d\n", __func__, __LINE__);
+
+	ps3fb_flip_ctl(0, &ps3fb);	/* 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);
-}
 
-void ps3fb_cleanup(void)
-{
-	int status;
+	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 +1157,69 @@ void ps3fb_cleanup(void)
 	if (status)
 		DPRINTK("lv1_gpu_memory_free failed: %d\n", status);
 
-	ps3av_dev_close();
-}
+	ps3_close_hv_device(dev);
+	DPRINTK(" <- %s:%d\n", __func__, __LINE__);
 
-EXPORT_SYMBOL_GPL(ps3fb_cleanup);
-
-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		= ps3fb_shutdown,
+	.shutdown	= ps3fb_shutdown,
 };
 
-int ps3fb_set_sync(void)
+static int __init ps3fb_setup(void)
 {
-	int status;
+	char *options;
 
-#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
+#ifdef MODULE
 	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;
-	}
+	if (fb_get_options(DEVICE_NAME, &options))
+		return -ENXIO;
 
-	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;
+	if (!options || !*options)
+		return 0;
 
-	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;
+	while (1) {
+		char *this_opt = strsep(&options, ",");
 
-	error = platform_driver_register(&ps3fb_driver);
-	if (!error) {
-		error = platform_device_register(&ps3fb_device);
-		if (error)
-			platform_driver_unregister(&ps3fb_driver);
+		if (!this_opt)
+			break;
+		if (!*this_opt)
+			continue;
+		if (!strncmp(this_opt, "mode:", 5))
+			ps3fb_mode = simple_strtoul(this_opt + 5, NULL, 0);
+		else
+			mode_option = this_opt;
 	}
+	return 0;
+}
 
-	ps3fb_set_sync();
-
-	return error;
+static int __init ps3fb_init(void)
+{
+	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);
+	DPRINTK(" -> %s:%d\n", __func__, __LINE__);
+	ps3_system_bus_driver_unregister(&ps3fb_driver);
+	DPRINTK(" <- %s:%d\n", __func__, __LINE__);
 }
 
+module_init(ps3fb_init);
 module_exit(ps3fb_exit);
 
 MODULE_LICENSE("GPL");
-#endif				/* MODULE */
+MODULE_DESCRIPTION("PS3 GPU Frame Buffer Driver");
+MODULE_AUTHOR("Sony Computer Entertainment Inc.");
+MODULE_ALIAS(PS3_MODULE_ALIAS_GRAPHICS);
--- a/include/asm-powerpc/ps3fb.h
+++ b/include/asm-powerpc/ps3fb.h
@@ -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_ */

-- 

^ permalink raw reply

* [patch 17/33] PS3: Rework AV settings driver
From: Geoff Levand @ 2007-06-15 22:05 UTC (permalink / raw)
  To: paulus; +Cc: Geert Uytterhoeven, linuxppc-dev
In-Reply-To: <20070615204749.629571012@am.sony.com>

Make the PS3 ps3av driver a loadable module.
  - Replace static data with kmalloc()'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 that file only.
  - 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 flip control routine.

Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
 drivers/ps3/Makefile        |    3 
 drivers/ps3/ps3av.c         |  372 +++++++++++++++++++++++---------------------
 drivers/ps3/ps3av_cmd.c     |   35 ----
 include/asm-powerpc/ps3av.h |   36 ++--
 4 files changed, 220 insertions(+), 226 deletions(-)

--- a/drivers/ps3/Makefile
+++ b/drivers/ps3/Makefile
@@ -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
--- a/drivers/ps3/ps3av.c
+++ b/drivers/ps3/ps3av.c
@@ -1,32 +1,30 @@
 /*
- * Copyright (C) 2006 Sony Computer Entertainment Inc.
- * Copyright 2006, 2007 Sony Corporation
+ *  PS3 AV backend support.
  *
- * AV backend support for PS3
+ *  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.
+ *  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.
  *
- * 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 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.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *  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
  */
 
+#include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/kernel.h>
 #include <linux/ioctl.h>
 
 #include <asm/firmware.h>
-#include <asm/lv1call.h>
 #include <asm/ps3av.h>
 #include <asm/ps3.h>
 
@@ -39,13 +37,12 @@ static int timeout = 5000;	/* in msec ( 
 module_param(timeout, int, 0644);
 
 static struct ps3av {
-	int available;
 	struct mutex mutex;
 	struct work_struct work;
 	struct completion done;
 	struct workqueue_struct *wq;
 	int open_count;
-	struct ps3_vuart_port_device *dev;
+	struct ps3_system_bus_device *dev;
 
 	int region;
 	struct ps3av_pkt_av_get_hw_conf av_hw_conf;
@@ -55,11 +52,13 @@ static struct ps3av {
 	u32 audio_port;
 	int ps3av_mode;
 	int ps3av_mode_old;
-} ps3av;
-
-static struct ps3_vuart_port_device ps3av_dev = {
-	.match_id = PS3_MATCH_ID_AV_SETTINGS
-};
+	union {
+		struct ps3av_reply_hdr reply_hdr;
+		u8 raw[PS3AV_BUF_SIZE];
+	} recv_buf;
+	void (*flip_ctl)(int on, void *data);
+	void *flip_data;
+} *ps3av;
 
 /* color space */
 #define YUV444 PS3AV_CMD_VIDEO_CS_YUV444_8
@@ -169,7 +168,7 @@ static int ps3av_parse_event_packet(cons
 	if (hdr->cid & PS3AV_EVENT_CMD_MASK) {
 		table = ps3av_search_cmd_table(hdr->cid, PS3AV_EVENT_CMD_MASK);
 		if (table)
-			dev_dbg(&ps3av_dev.core,
+			dev_dbg(&ps3av->dev->core,
 				"recv event packet cid:%08x port:0x%x size:%d\n",
 				hdr->cid, ps3av_event_get_port_id(hdr->cid),
 				hdr->size);
@@ -182,6 +181,41 @@ static int ps3av_parse_event_packet(cons
 	return 0;
 }
 
+
+#define POLLING_INTERVAL  25	/* in msec */
+
+static int ps3av_vuart_write(struct ps3_system_bus_device *dev,
+			     const void *buf, unsigned long size)
+{
+	int error;
+	dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
+	error = ps3_vuart_write(dev, buf, size);
+	dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
+	return error ? error : size;
+}
+
+static int ps3av_vuart_read(struct ps3_system_bus_device *dev, void *buf,
+			    unsigned long size, int timeout)
+{
+	int error;
+	int loopcnt = 0;
+
+	dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
+	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;
+}
+
 static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf,
 			      struct ps3av_reply_hdr *recv_buf, int write_len,
 			      int read_len)
@@ -190,13 +224,13 @@ static int ps3av_send_cmd_pkt(const stru
 	u32 cmd;
 	int event;
 
-	if (!ps3av.available)
+	if (!ps3av)
 		return -ENODEV;
 
 	/* send pkt */
-	res = ps3av_vuart_write(ps3av.dev, send_buf, write_len);
+	res = ps3av_vuart_write(ps3av->dev, send_buf, write_len);
 	if (res < 0) {
-		dev_dbg(&ps3av_dev.core,
+		dev_dbg(&ps3av->dev->core,
 			"%s: ps3av_vuart_write() failed (result=%d)\n",
 			__func__, res);
 		return res;
@@ -206,20 +240,20 @@ static int ps3av_send_cmd_pkt(const stru
 	cmd = send_buf->cid;
 	do {
 		/* read header */
-		res = ps3av_vuart_read(ps3av.dev, recv_buf, PS3AV_HDR_SIZE,
+		res = ps3av_vuart_read(ps3av->dev, recv_buf, PS3AV_HDR_SIZE,
 				       timeout);
 		if (res != PS3AV_HDR_SIZE) {
-			dev_dbg(&ps3av_dev.core,
+			dev_dbg(&ps3av->dev->core,
 				"%s: ps3av_vuart_read() failed (result=%d)\n",
 				__func__, res);
 			return res;
 		}
 
 		/* read body */
-		res = ps3av_vuart_read(ps3av.dev, &recv_buf->cid,
+		res = ps3av_vuart_read(ps3av->dev, &recv_buf->cid,
 				       recv_buf->size, timeout);
 		if (res < 0) {
-			dev_dbg(&ps3av_dev.core,
+			dev_dbg(&ps3av->dev->core,
 				"%s: ps3av_vuart_read() failed (result=%d)\n",
 				__func__, res);
 			return res;
@@ -230,7 +264,7 @@ static int ps3av_send_cmd_pkt(const stru
 	} while (event);
 
 	if ((cmd | PS3AV_REPLY_BIT) != recv_buf->cid) {
-		dev_dbg(&ps3av_dev.core, "%s: reply err (result=%x)\n",
+		dev_dbg(&ps3av->dev->core, "%s: reply err (result=%x)\n",
 			__func__, recv_buf->cid);
 		return -EINVAL;
 	}
@@ -245,7 +279,7 @@ static int ps3av_process_reply_packet(st
 	int return_len;
 
 	if (recv_buf->version != PS3AV_VERSION) {
-		dev_dbg(&ps3av_dev.core, "reply_packet invalid version:%x\n",
+		dev_dbg(&ps3av->dev->core, "reply_packet invalid version:%x\n",
 			recv_buf->version);
 		return -EFAULT;
 	}
@@ -267,16 +301,11 @@ int ps3av_do_pkt(u32 cid, u16 send_len, 
 		 struct ps3av_send_hdr *buf)
 {
 	int res = 0;
-	static union {
-		struct ps3av_reply_hdr reply_hdr;
-		u8 raw[PS3AV_BUF_SIZE];
-	} recv_buf;
-
 	u32 *table;
 
-	BUG_ON(!ps3av.available);
+	BUG_ON(!ps3av);
 
-	mutex_lock(&ps3av.mutex);
+	mutex_lock(&ps3av->mutex);
 
 	table = ps3av_search_cmd_table(cid, PS3AV_CID_MASK);
 	BUG_ON(!table);
@@ -288,7 +317,7 @@ int ps3av_do_pkt(u32 cid, u16 send_len, 
 	ps3av_set_hdr(cid, send_len, buf);
 
 	/* send packet via vuart */
-	res = ps3av_send_cmd_pkt(buf, &recv_buf.reply_hdr, send_len,
+	res = ps3av_send_cmd_pkt(buf, &ps3av->recv_buf.reply_hdr, send_len,
 				 usr_buf_size);
 	if (res < 0) {
 		printk(KERN_ERR
@@ -298,7 +327,7 @@ int ps3av_do_pkt(u32 cid, u16 send_len, 
 	}
 
 	/* process reply packet */
-	res = ps3av_process_reply_packet(buf, &recv_buf.reply_hdr,
+	res = ps3av_process_reply_packet(buf, &ps3av->recv_buf.reply_hdr,
 					 usr_buf_size);
 	if (res < 0) {
 		printk(KERN_ERR "%s: put_return_status() failed (result=%d)\n",
@@ -306,11 +335,11 @@ int ps3av_do_pkt(u32 cid, u16 send_len, 
 		goto err;
 	}
 
-	mutex_unlock(&ps3av.mutex);
+	mutex_unlock(&ps3av->mutex);
 	return 0;
 
       err:
-	mutex_unlock(&ps3av.mutex);
+	mutex_unlock(&ps3av->mutex);
 	printk(KERN_ERR "%s: failed cid:%x res:%d\n", __func__, cid, res);
 	return res;
 }
@@ -319,11 +348,11 @@ static int ps3av_set_av_video_mute(u32 m
 {
 	int i, num_of_av_port, res;
 
-	num_of_av_port = ps3av.av_hw_conf.num_of_hdmi +
-			 ps3av.av_hw_conf.num_of_avmulti;
+	num_of_av_port = ps3av->av_hw_conf.num_of_hdmi +
+			 ps3av->av_hw_conf.num_of_avmulti;
 	/* video mute on */
 	for (i = 0; i < num_of_av_port; i++) {
-		res = ps3av_cmd_av_video_mute(1, &ps3av.av_port[i], mute);
+		res = ps3av_cmd_av_video_mute(1, &ps3av->av_port[i], mute);
 		if (res < 0)
 			return -1;
 	}
@@ -335,13 +364,13 @@ static int ps3av_set_video_disable_sig(v
 {
 	int i, num_of_hdmi_port, num_of_av_port, res;
 
-	num_of_hdmi_port = ps3av.av_hw_conf.num_of_hdmi;
-	num_of_av_port = ps3av.av_hw_conf.num_of_hdmi +
-			 ps3av.av_hw_conf.num_of_avmulti;
+	num_of_hdmi_port = ps3av->av_hw_conf.num_of_hdmi;
+	num_of_av_port = ps3av->av_hw_conf.num_of_hdmi +
+			 ps3av->av_hw_conf.num_of_avmulti;
 
 	/* tv mute */
 	for (i = 0; i < num_of_hdmi_port; i++) {
-		res = ps3av_cmd_av_tv_mute(ps3av.av_port[i],
+		res = ps3av_cmd_av_tv_mute(ps3av->av_port[i],
 					   PS3AV_CMD_MUTE_ON);
 		if (res < 0)
 			return -1;
@@ -350,11 +379,11 @@ static int ps3av_set_video_disable_sig(v
 
 	/* video mute on */
 	for (i = 0; i < num_of_av_port; i++) {
-		res = ps3av_cmd_av_video_disable_sig(ps3av.av_port[i]);
+		res = ps3av_cmd_av_video_disable_sig(ps3av->av_port[i]);
 		if (res < 0)
 			return -1;
 		if (i < num_of_hdmi_port) {
-			res = ps3av_cmd_av_tv_mute(ps3av.av_port[i],
+			res = ps3av_cmd_av_tv_mute(ps3av->av_port[i],
 						   PS3AV_CMD_MUTE_OFF);
 			if (res < 0)
 				return -1;
@@ -369,17 +398,17 @@ static int ps3av_set_audio_mute(u32 mute
 {
 	int i, num_of_av_port, num_of_opt_port, res;
 
-	num_of_av_port = ps3av.av_hw_conf.num_of_hdmi +
-			 ps3av.av_hw_conf.num_of_avmulti;
-	num_of_opt_port = ps3av.av_hw_conf.num_of_spdif;
+	num_of_av_port = ps3av->av_hw_conf.num_of_hdmi +
+			 ps3av->av_hw_conf.num_of_avmulti;
+	num_of_opt_port = ps3av->av_hw_conf.num_of_spdif;
 
 	for (i = 0; i < num_of_av_port; i++) {
-		res = ps3av_cmd_av_audio_mute(1, &ps3av.av_port[i], mute);
+		res = ps3av_cmd_av_audio_mute(1, &ps3av->av_port[i], mute);
 		if (res < 0)
 			return -1;
 	}
 	for (i = 0; i < num_of_opt_port; i++) {
-		res = ps3av_cmd_audio_mute(1, &ps3av.opt_port[i], mute);
+		res = ps3av_cmd_audio_mute(1, &ps3av->opt_port[i], mute);
 		if (res < 0)
 			return -1;
 	}
@@ -394,40 +423,40 @@ int ps3av_set_audio_mode(u32 ch, u32 fs,
 	struct ps3av_pkt_audio_mode audio_mode;
 	u32 len = 0;
 
-	num_of_audio = ps3av.av_hw_conf.num_of_hdmi +
-		       ps3av.av_hw_conf.num_of_avmulti +
-		       ps3av.av_hw_conf.num_of_spdif;
+	num_of_audio = ps3av->av_hw_conf.num_of_hdmi +
+		       ps3av->av_hw_conf.num_of_avmulti +
+		       ps3av->av_hw_conf.num_of_spdif;
 
 	avb_param.num_of_video_pkt = 0;
 	avb_param.num_of_audio_pkt = PS3AV_AVB_NUM_AUDIO;	/* always 0 */
 	avb_param.num_of_av_video_pkt = 0;
-	avb_param.num_of_av_audio_pkt = ps3av.av_hw_conf.num_of_hdmi;
+	avb_param.num_of_av_audio_pkt = ps3av->av_hw_conf.num_of_hdmi;
 
-	vid = video_mode_table[ps3av.ps3av_mode].vid;
+	vid = video_mode_table[ps3av->ps3av_mode].vid;
 
 	/* audio mute */
 	ps3av_set_audio_mute(PS3AV_CMD_MUTE_ON);
 
 	/* audio inactive */
-	res = ps3av_cmd_audio_active(0, ps3av.audio_port);
+	res = ps3av_cmd_audio_active(0, ps3av->audio_port);
 	if (res < 0)
-		dev_dbg(&ps3av_dev.core,
+		dev_dbg(&ps3av->dev->core,
 			"ps3av_cmd_audio_active OFF failed\n");
 
 	/* audio_pkt */
 	for (i = 0; i < num_of_audio; i++) {
-		ps3av_cmd_set_audio_mode(&audio_mode, ps3av.av_port[i], ch, fs,
-					 word_bits, format, source);
-		if (i < ps3av.av_hw_conf.num_of_hdmi) {
+		ps3av_cmd_set_audio_mode(&audio_mode, ps3av->av_port[i], ch,
+					 fs, word_bits, format, source);
+		if (i < ps3av->av_hw_conf.num_of_hdmi) {
 			/* hdmi only */
 			len += ps3av_cmd_set_av_audio_param(&avb_param.buf[len],
-							    ps3av.av_port[i],
+							    ps3av->av_port[i],
 							    &audio_mode, vid);
 		}
 		/* audio_mode pkt should be sent separately */
 		res = ps3av_cmd_audio_mode(&audio_mode);
 		if (res < 0)
-			dev_dbg(&ps3av_dev.core,
+			dev_dbg(&ps3av->dev->core,
 				"ps3av_cmd_audio_mode failed, port:%x\n", i);
 	}
 
@@ -435,15 +464,16 @@ int ps3av_set_audio_mode(u32 ch, u32 fs,
 	len += offsetof(struct ps3av_pkt_avb_param, buf);
 	res = ps3av_cmd_avb_param(&avb_param, len);
 	if (res < 0)
-		dev_dbg(&ps3av_dev.core, "ps3av_cmd_avb_param failed\n");
+		dev_dbg(&ps3av->dev->core, "ps3av_cmd_avb_param failed\n");
 
 	/* audio mute */
 	ps3av_set_audio_mute(PS3AV_CMD_MUTE_OFF);
 
 	/* audio active */
-	res = ps3av_cmd_audio_active(1, ps3av.audio_port);
+	res = ps3av_cmd_audio_active(1, ps3av->audio_port);
 	if (res < 0)
-		dev_dbg(&ps3av_dev.core, "ps3av_cmd_audio_active ON failed\n");
+		dev_dbg(&ps3av->dev->core,
+			"ps3av_cmd_audio_active ON failed\n");
 
 	return 0;
 }
@@ -456,7 +486,7 @@ static int ps3av_set_videomode(void)
 	ps3av_set_av_video_mute(PS3AV_CMD_MUTE_ON);
 
 	/* wake up ps3avd to do the actual video mode setting */
-	queue_work(ps3av.wq, &ps3av.work);
+	queue_work(ps3av->wq, &ps3av->work);
 
 	return 0;
 }
@@ -473,8 +503,8 @@ static void ps3av_set_videomode_cont(u32
 
 	avb_param.num_of_video_pkt = PS3AV_AVB_NUM_VIDEO;	/* num of head */
 	avb_param.num_of_audio_pkt = 0;
-	avb_param.num_of_av_video_pkt = ps3av.av_hw_conf.num_of_hdmi +
-					ps3av.av_hw_conf.num_of_avmulti;
+	avb_param.num_of_av_video_pkt = ps3av->av_hw_conf.num_of_hdmi +
+					ps3av->av_hw_conf.num_of_avmulti;
 	avb_param.num_of_av_audio_pkt = 0;
 
 	/* video signal off */
@@ -484,21 +514,21 @@ static void ps3av_set_videomode_cont(u32
 	if (id & PS3AV_MODE_HDCP_OFF) {
 		res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_HDCP_OFF);
 		if (res == PS3AV_STATUS_UNSUPPORTED_HDMI_MODE)
-			dev_dbg(&ps3av_dev.core, "Not supported\n");
+			dev_dbg(&ps3av->dev->core, "Not supported\n");
 		else if (res)
-			dev_dbg(&ps3av_dev.core,
+			dev_dbg(&ps3av->dev->core,
 				"ps3av_cmd_av_hdmi_mode failed\n");
 	} else if (old_id & PS3AV_MODE_HDCP_OFF) {
 		res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_MODE_NORMAL);
 		if (res < 0 && res != PS3AV_STATUS_UNSUPPORTED_HDMI_MODE)
-			dev_dbg(&ps3av_dev.core,
+			dev_dbg(&ps3av->dev->core,
 				"ps3av_cmd_av_hdmi_mode failed\n");
 	}
 
 	/* video_pkt */
 	for (i = 0; i < avb_param.num_of_video_pkt; i++)
 		len += ps3av_cmd_set_video_mode(&avb_param.buf[len],
-						ps3av.head[i], video_mode->vid,
+						ps3av->head[i], video_mode->vid,
 						video_mode->fmt, id);
 	/* av_video_pkt */
 	for (i = 0; i < avb_param.num_of_av_video_pkt; i++) {
@@ -507,12 +537,12 @@ static void ps3av_set_videomode_cont(u32
 		else
 			av_video_cs = video_mode->cs;
 #ifndef PS3AV_HDMI_YUV
-		if (ps3av.av_port[i] == PS3AV_CMD_AVPORT_HDMI_0 ||
-		    ps3av.av_port[i] == PS3AV_CMD_AVPORT_HDMI_1)
+		if (ps3av->av_port[i] == PS3AV_CMD_AVPORT_HDMI_0 ||
+		    ps3av->av_port[i] == PS3AV_CMD_AVPORT_HDMI_1)
 			av_video_cs = RGB8;	/* use RGB for HDMI */
 #endif
 		len += ps3av_cmd_set_av_video_cs(&avb_param.buf[len],
-						 ps3av.av_port[i],
+						 ps3av->av_port[i],
 						 video_mode->vid, av_video_cs,
 						 video_mode->aspect, id);
 	}
@@ -524,7 +554,7 @@ static void ps3av_set_videomode_cont(u32
 		       "%s: Command failed. Please try your request again. \n",
 		       __func__);
 	else if (res)
-		dev_dbg(&ps3av_dev.core, "ps3av_cmd_avb_param failed\n");
+		dev_dbg(&ps3av->dev->core, "ps3av_cmd_avb_param failed\n");
 
 	msleep(1500);
 	/* av video mute */
@@ -533,8 +563,8 @@ static void ps3av_set_videomode_cont(u32
 
 static void ps3avd(struct work_struct *work)
 {
-	ps3av_set_videomode_cont(ps3av.ps3av_mode, ps3av.ps3av_mode_old);
-	complete(&ps3av.done);
+	ps3av_set_videomode_cont(ps3av->ps3av_mode, ps3av->ps3av_mode_old);
+	complete(&ps3av->done);
 }
 
 static int ps3av_vid2table_id(int vid)
@@ -601,7 +631,7 @@ static int ps3av_hdmi_get_vid(struct ps3
 		return vid;
 	}
 
-	if (ps3av.region & PS3AV_REGION_60)
+	if (ps3av->region & PS3AV_REGION_60)
 		vid = PS3AV_DEFAULT_HDMI_VID_REG_60;
 	else
 		vid = PS3AV_DEFAULT_HDMI_VID_REG_50;
@@ -643,16 +673,16 @@ static int ps3av_auto_videomode(struct p
 		vid = PS3AV_DEFAULT_DVI_VID;
 	} else if (vid == -1) {
 		/* no HDMI interface or HDMI is off */
-		if (ps3av.region & PS3AV_REGION_60)
+		if (ps3av->region & PS3AV_REGION_60)
 			vid = PS3AV_DEFAULT_AVMULTI_VID_REG_60;
 		else
 			vid = PS3AV_DEFAULT_AVMULTI_VID_REG_50;
-		if (ps3av.region & PS3AV_REGION_RGB)
+		if (ps3av->region & PS3AV_REGION_RGB)
 			rgb = PS3AV_MODE_RGB;
 	} else if (boot) {
 		/* HDMI: using DEFAULT HDMI_VID while booting up */
 		info = &monitor_info.info;
-		if (ps3av.region & PS3AV_REGION_60) {
+		if (ps3av->region & PS3AV_REGION_60) {
 			if (info->res_60.res_bits & PS3AV_RESBIT_720x480P)
 				vid = PS3AV_DEFAULT_HDMI_VID_REG_60;
 			else if (info->res_50.res_bits & PS3AV_RESBIT_720x576P)
@@ -715,14 +745,14 @@ int ps3av_set_video_mode(u32 id, int boo
 
 	size = ARRAY_SIZE(video_mode_table);
 	if ((id & PS3AV_MODE_MASK) > size - 1 || id < 0) {
-		dev_dbg(&ps3av_dev.core, "%s: error id :%d\n", __func__, id);
+		dev_dbg(&ps3av->dev->core, "%s: error id :%d\n", __func__, id);
 		return -EINVAL;
 	}
 
 	/* auto mode */
 	option = id & ~PS3AV_MODE_MASK;
 	if ((id & PS3AV_MODE_MASK) == 0) {
-		id = ps3av_auto_videomode(&ps3av.av_hw_conf, boot);
+		id = ps3av_auto_videomode(&ps3av->av_hw_conf, boot);
 		if (id < 1) {
 			printk(KERN_ERR "%s: invalid id :%d\n", __func__, id);
 			return -EINVAL;
@@ -731,11 +761,11 @@ int ps3av_set_video_mode(u32 id, int boo
 	}
 
 	/* set videomode */
-	wait_for_completion(&ps3av.done);
-	ps3av.ps3av_mode_old = ps3av.ps3av_mode;
-	ps3av.ps3av_mode = id;
+	wait_for_completion(&ps3av->done);
+	ps3av->ps3av_mode_old = ps3av->ps3av_mode;
+	ps3av->ps3av_mode = id;
 	if (ps3av_set_videomode())
-		ps3av.ps3av_mode = ps3av.ps3av_mode_old;
+		ps3av->ps3av_mode = ps3av->ps3av_mode_old;
 
 	return 0;
 }
@@ -744,7 +774,7 @@ EXPORT_SYMBOL_GPL(ps3av_set_video_mode);
 
 int ps3av_get_auto_mode(int boot)
 {
-	return ps3av_auto_videomode(&ps3av.av_hw_conf, boot);
+	return ps3av_auto_videomode(&ps3av->av_hw_conf, boot);
 }
 
 EXPORT_SYMBOL_GPL(ps3av_get_auto_mode);
@@ -772,7 +802,7 @@ EXPORT_SYMBOL_GPL(ps3av_set_mode);
 
 int ps3av_get_mode(void)
 {
-	return ps3av.ps3av_mode;
+	return ps3av ? ps3av->ps3av_mode : 0;
 }
 
 EXPORT_SYMBOL_GPL(ps3av_get_mode);
@@ -842,82 +872,65 @@ int ps3av_audio_mute(int mute)
 
 EXPORT_SYMBOL_GPL(ps3av_audio_mute);
 
-int ps3av_dev_open(void)
+void ps3av_register_flip_ctl(void (*flip_ctl)(int on, void *data),
+			     void *flip_data)
 {
-	int status = 0;
-
-	mutex_lock(&ps3av.mutex);
-	if (!ps3av.open_count++) {
-		status = lv1_gpu_open(0);
-		if (status) {
-			printk(KERN_ERR "%s: lv1_gpu_open failed %d\n",
-			       __func__, status);
-			ps3av.open_count--;
-		}
-	}
-	mutex_unlock(&ps3av.mutex);
-
-	return status;
+	mutex_lock(&ps3av->mutex);
+	ps3av->flip_ctl = flip_ctl;
+	ps3av->flip_data = flip_data;
+	mutex_unlock(&ps3av->mutex);
 }
+EXPORT_SYMBOL_GPL(ps3av_register_flip_ctl);
 
-EXPORT_SYMBOL_GPL(ps3av_dev_open);
-
-int ps3av_dev_close(void)
+void ps3av_flip_ctl(int on)
 {
-	int status = 0;
-
-	mutex_lock(&ps3av.mutex);
-	if (ps3av.open_count <= 0) {
-		printk(KERN_ERR "%s: GPU already closed\n", __func__);
-		status = -1;
-	} else if (!--ps3av.open_count) {
-		status = lv1_gpu_close();
-		if (status)
-			printk(KERN_WARNING "%s: lv1_gpu_close failed %d\n",
-			       __func__, status);
-	}
-	mutex_unlock(&ps3av.mutex);
-
-	return status;
+	mutex_lock(&ps3av->mutex);
+	if (ps3av->flip_ctl)
+		ps3av->flip_ctl(on, ps3av->flip_data);
+	mutex_unlock(&ps3av->mutex);
 }
 
-EXPORT_SYMBOL_GPL(ps3av_dev_close);
-
-static int ps3av_probe(struct ps3_vuart_port_device *dev)
+static int ps3av_probe(struct ps3_system_bus_device *dev)
 {
 	int res;
 	u32 id;
 
-	dev_dbg(&ps3av_dev.core, "init ...\n");
-	dev_dbg(&ps3av_dev.core, "  timeout=%d\n", timeout);
+	dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
+	dev_dbg(&dev->core, "  timeout=%d\n", timeout);
 
-	memset(&ps3av, 0, sizeof(ps3av));
+	if (ps3av) {
+		dev_err(&dev->core, "Only one ps3av device is supported\n");
+		return -EBUSY;
+	}
 
-	mutex_init(&ps3av.mutex);
-	ps3av.ps3av_mode = 0;
-	ps3av.dev = dev;
-
-	INIT_WORK(&ps3av.work, ps3avd);
-	init_completion(&ps3av.done);
-	complete(&ps3av.done);
-	ps3av.wq = create_singlethread_workqueue("ps3avd");
-	if (!ps3av.wq)
+	ps3av = kzalloc(sizeof(*ps3av), GFP_KERNEL);
+	if (!ps3av)
 		return -ENOMEM;
 
-	ps3av.available = 1;
+	mutex_init(&ps3av->mutex);
+	ps3av->ps3av_mode = 0;
+	ps3av->dev = dev;
+
+	INIT_WORK(&ps3av->work, ps3avd);
+	init_completion(&ps3av->done);
+	complete(&ps3av->done);
+	ps3av->wq = create_singlethread_workqueue("ps3avd");
+	if (!ps3av->wq)
+		goto fail;
+
 	switch (ps3_os_area_get_av_multi_out()) {
 	case PS3_PARAM_AV_MULTI_OUT_NTSC:
-		ps3av.region = PS3AV_REGION_60;
+		ps3av->region = PS3AV_REGION_60;
 		break;
 	case PS3_PARAM_AV_MULTI_OUT_PAL_YCBCR:
 	case PS3_PARAM_AV_MULTI_OUT_SECAM:
-		ps3av.region = PS3AV_REGION_50;
+		ps3av->region = PS3AV_REGION_50;
 		break;
 	case PS3_PARAM_AV_MULTI_OUT_PAL_RGB:
-		ps3av.region = PS3AV_REGION_50 | PS3AV_REGION_RGB;
+		ps3av->region = PS3AV_REGION_50 | PS3AV_REGION_RGB;
 		break;
 	default:
-		ps3av.region = PS3AV_REGION_60;
+		ps3av->region = PS3AV_REGION_60;
 		break;
 	}
 
@@ -927,39 +940,47 @@ static int ps3av_probe(struct ps3_vuart_
 		printk(KERN_ERR "%s: ps3av_cmd_init failed %d\n", __func__,
 		       res);
 
-	ps3av_get_hw_conf(&ps3av);
-	id = ps3av_auto_videomode(&ps3av.av_hw_conf, 1);
-	mutex_lock(&ps3av.mutex);
-	ps3av.ps3av_mode = id;
-	mutex_unlock(&ps3av.mutex);
+	ps3av_get_hw_conf(ps3av);
+	id = ps3av_auto_videomode(&ps3av->av_hw_conf, 1);
+	mutex_lock(&ps3av->mutex);
+	ps3av->ps3av_mode = id;
+	mutex_unlock(&ps3av->mutex);
 
-	dev_dbg(&ps3av_dev.core, "init...done\n");
+	dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
 
 	return 0;
+
+fail:
+	kfree(ps3av);
+	ps3av = NULL;
+	return -ENOMEM;
 }
 
-static int ps3av_remove(struct ps3_vuart_port_device *dev)
+static int ps3av_remove(struct ps3_system_bus_device *dev)
 {
-	if (ps3av.available) {
+	dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
+	if (ps3av) {
 		ps3av_cmd_fin();
-		if (ps3av.wq)
-			destroy_workqueue(ps3av.wq);
-		ps3av.available = 0;
+		if (ps3av->wq)
+			destroy_workqueue(ps3av->wq);
+		kfree(ps3av);
+		ps3av = NULL;
 	}
 
+	dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
 	return 0;
 }
 
-static void ps3av_shutdown(struct ps3_vuart_port_device *dev)
+static void ps3av_shutdown(struct ps3_system_bus_device *dev)
 {
+	dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
 	ps3av_remove(dev);
+	dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
 }
 
 static struct ps3_vuart_port_driver ps3av_driver = {
-	.match_id = PS3_MATCH_ID_AV_SETTINGS,
-	.core = {
-		.name = "ps3_av",
-	},
+	.core.match_id = PS3_MATCH_ID_AV_SETTINGS,
+	.core.core.name = "ps3_av",
 	.probe = ps3av_probe,
 	.remove = ps3av_remove,
 	.shutdown = ps3av_shutdown,
@@ -972,6 +993,8 @@ static int ps3av_module_init(void)
 	if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
 		return -ENODEV;
 
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
 	error = ps3_vuart_port_driver_register(&ps3av_driver);
 	if (error) {
 		printk(KERN_ERR
@@ -980,20 +1003,21 @@ static int ps3av_module_init(void)
 		return error;
 	}
 
-	error = ps3_vuart_port_device_register(&ps3av_dev);
-	if (error)
-		printk(KERN_ERR
-		       "%s: ps3_vuart_port_device_register failed %d\n",
-		       __func__, error);
-
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
 	return error;
 }
 
 static void __exit ps3av_module_exit(void)
 {
-	device_unregister(&ps3av_dev.core);
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);
 	ps3_vuart_port_driver_unregister(&ps3av_driver);
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
 }
 
 subsys_initcall(ps3av_module_init);
 module_exit(ps3av_module_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("PS3 AV Settings Driver");
+MODULE_AUTHOR("Sony Computer Entertainment Inc.");
+MODULE_ALIAS(PS3_MODULE_ALIAS_AV_SETTINGS);
--- a/drivers/ps3/ps3av_cmd.c
+++ b/drivers/ps3/ps3av_cmd.c
@@ -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;
-}
--- a/include/asm-powerpc/ps3av.h
+++ b/include/asm-powerpc/ps3av.h
@@ -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_
 
@@ -704,12 +707,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);
@@ -722,5 +719,8 @@ 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	/* _ASM_POWERPC_PS3AV_H_ */

-- 

^ permalink raw reply

* [patch 25/33] Powerpc: Add signed types to bootwrapper
From: Geoff Levand @ 2007-06-15 22:06 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev
In-Reply-To: <20070615204749.629571012@am.sony.com>

Add signed types to the powerpc zImage bootwrapper. These are needed by the
PS3 hcall interface.

Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
 arch/powerpc/boot/types.h |    4 ++++
 1 file changed, 4 insertions(+)

--- a/arch/powerpc/boot/types.h
+++ b/arch/powerpc/boot/types.h
@@ -7,6 +7,10 @@ typedef unsigned char		u8;
 typedef unsigned short		u16;
 typedef unsigned int		u32;
 typedef unsigned long long	u64;
+typedef signed char		s8;
+typedef short			s16;
+typedef int			s32;
+typedef long long		s64;
 
 #define min(x,y) ({ \
 	typeof(x) _x = (x);	\

-- 

^ permalink raw reply

* [patch 03/33] PS3: Use __maybe_unused
From: Geoff Levand @ 2007-06-15 21:18 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev
In-Reply-To: <20070615204749.629571012@am.sony.com>

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

Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
 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(-)

--- a/arch/powerpc/platforms/ps3/interrupt.c
+++ b/arch/powerpc/platforms/ps3/interrupt.c
@@ -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;
--- a/arch/powerpc/platforms/ps3/time.c
+++ b/arch/powerpc/platforms/ps3/time.c
@@ -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;
--- a/drivers/ps3/vuart.c
+++ b/drivers/ps3/vuart.c
@@ -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)

-- 

^ permalink raw reply

* [patch 22/33] powerpc: Output params value in early_init_devtree
From: Geoff Levand @ 2007-06-15 22:06 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev
In-Reply-To: <20070615204749.629571012@am.sony.com>

Add a printout of the params value to early_init_devtree.
This value is handy to have for comparison when debugging the
bootwrapper code.

Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
 arch/powerpc/kernel/prom.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -1005,7 +1005,7 @@ static void __init early_reserve_mem(voi
 
 void __init early_init_devtree(void *params)
 {
-	DBG(" -> early_init_devtree()\n");
+	DBG(" -> early_init_devtree(%p)\n", params);
 
 	/* Setup flat device-tree pointer */
 	initial_boot_params = params;

-- 

^ permalink raw reply

* [patch 09/33] PS3: Simplify definition of DBG
From: Geoff Levand @ 2007-06-15 21:19 UTC (permalink / raw)
  To: paulus; +Cc: Geert Uytterhoeven, linuxppc-dev
In-Reply-To: <20070615204749.629571012@am.sony.com>

From: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>

Simplify the PS3 definition of DBG.

Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
 arch/powerpc/platforms/ps3/htab.c      |    4 ++--
 arch/powerpc/platforms/ps3/interrupt.c |    4 ++--
 arch/powerpc/platforms/ps3/mm.c        |    4 ++--
 arch/powerpc/platforms/ps3/setup.c     |    4 ++--
 arch/powerpc/platforms/ps3/smp.c       |    4 ++--
 5 files changed, 10 insertions(+), 10 deletions(-)

--- a/arch/powerpc/platforms/ps3/htab.c
+++ b/arch/powerpc/platforms/ps3/htab.c
@@ -29,9 +29,9 @@
 #include "platform.h"
 
 #if defined(DEBUG)
-#define DBG(fmt...) udbg_printf(fmt)
+#define DBG udbg_printf
 #else
-#define DBG(fmt...) do{if(0)printk(fmt);}while(0)
+#define DBG pr_debug
 #endif
 
 static hpte_t *htab;
--- a/arch/powerpc/platforms/ps3/interrupt.c
+++ b/arch/powerpc/platforms/ps3/interrupt.c
@@ -30,9 +30,9 @@
 #include "platform.h"
 
 #if defined(DEBUG)
-#define DBG(fmt...) udbg_printf(fmt)
+#define DBG udbg_printf
 #else
-#define DBG(fmt...) do{if(0)printk(fmt);}while(0)
+#define DBG pr_debug
 #endif
 
 /**
--- a/arch/powerpc/platforms/ps3/mm.c
+++ b/arch/powerpc/platforms/ps3/mm.c
@@ -30,9 +30,9 @@
 #include "platform.h"
 
 #if defined(DEBUG)
-#define DBG(fmt...) udbg_printf(fmt)
+#define DBG udbg_printf
 #else
-#define DBG(fmt...) do{if(0)printk(fmt);}while(0)
+#define DBG pr_debug
 #endif
 
 enum {
--- a/arch/powerpc/platforms/ps3/setup.c
+++ b/arch/powerpc/platforms/ps3/setup.c
@@ -37,9 +37,9 @@
 #include "platform.h"
 
 #if defined(DEBUG)
-#define DBG(fmt...) udbg_printf(fmt)
+#define DBG udbg_printf
 #else
-#define DBG(fmt...) do{if(0)printk(fmt);}while(0)
+#define DBG pr_debug
 #endif
 
 #if !defined(CONFIG_SMP)
--- a/arch/powerpc/platforms/ps3/smp.c
+++ b/arch/powerpc/platforms/ps3/smp.c
@@ -27,9 +27,9 @@
 #include "platform.h"
 
 #if defined(DEBUG)
-#define DBG(fmt...) udbg_printf(fmt)
+#define DBG udbg_printf
 #else
-#define DBG(fmt...) do{if(0)printk(fmt);}while(0)
+#define DBG pr_debug
 #endif
 
 static irqreturn_t ipi_function_handler(int irq, void *msg)

-- 

^ permalink raw reply

* [patch 00/33] PS3 patches for 2.6.23, take 3
From: Geoff Levand @ 2007-06-15 21:17 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev

	Hi Paul.
	
	I feel these patches are now ready.  There are no outstanding issues.
	We did a lot of format cleanups since the last set, so these have a
	lot of small differences.
	
	There are three new patches.  Patch 31 to set CONFIG_MEMORY_HOTPLUG
	for PS3 builds, Patch 32 a collection of sparse warning fixes,
	and Patch 33 to update ps3_defconfig.
	
	[01/32] Cell: Add spu shutdown method
	[02/32] PS3: Rename IPI symbols
	[03/32] PS3: Use __maybe_unused
	[04/32] PS3: Compare firmware version
	[05/32] PS3: Use ioremap_flags
	[06/32] PS3: Fix sparse warnings
	[07/32] PS3: Add support for HDMI RGB Full Range mode
	[08/32] PS3: Move chip mask defs up
	[09/32] PS3: Simplify definition of DBG
	[10/32] PS3: Kexec support
	[11/32] PS3: System-bus rework
	[12/32] PS3: System-bus uevent
	[13/32] PS3: System-bus modinfo attribute
	[14/32] PS3: Repository probe cleanups
	[15/32] PS3: Vuart rework
	[16/32] PS3: System manager re-work
	[17/32] PS3: Rework AV settings driver
	[18/32] PS3: Frame buffer system-bus rework
	[19/32] PS3: Device registration routines.
	[20/32] PS3: Rename processor id symbols
	[21/32] PS3: Use clear_bit
	[22/32] powerpc: Output params value in early_init_devtree
	[23/32] powerpc: Localize mmu_off
	[24/32] powerpc: Correct __secondary_hold comment
	[25/32] Powerpc: Add signed types to bootwrapper
	[26/32] Powerpc: Add u64 printf to bootwrapper
	[27/32] Powerpc: Fix constantness of bootwrapper arg
	[28/32] powerpc: Bootwrapper global scope kernel_entry_t.
	[29/32] PS3: Device tree source.
	[30/32] PS3: Bootwrapper support.
	[31/32] PS3: Select MEMORY_HOTPLUG.
	[32/32] PS3: Fix more sparse warnings
	[33/33] PS3: Update ps3_defconfig

	-Geoff

-- 

^ permalink raw reply

* [patch 13/33] PS3: System-bus modinfo attribute
From: Geoff Levand @ 2007-06-15 21:55 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev, David Woodhouse
In-Reply-To: <20070615204749.629571012@am.sony.com>

From: David Woodhouse <dwmw2@infradead.org>

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 

Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
  o Fixed WS.

 arch/powerpc/platforms/ps3/system-bus.c |   15 +++++++++++++++
 1 file changed, 15 insertions(+)

--- a/arch/powerpc/platforms/ps3/system-bus.c
+++ b/arch/powerpc/platforms/ps3/system-bus.c
@@ -452,6 +452,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,
@@ -459,6 +473,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)

-- 

^ permalink raw reply

* [patch 33/33] PS3: Update ps3_defconfig
From: Geoff Levand @ 2007-06-15 22:07 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev
In-Reply-To: <20070615204749.629571012@am.sony.com>

Update ps3_defconfig.

Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
 arch/powerpc/configs/ps3_defconfig |  131 +++++++++++++++----------------------
 1 file changed, 55 insertions(+), 76 deletions(-)

--- a/arch/powerpc/configs/ps3_defconfig
+++ b/arch/powerpc/configs/ps3_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21
-# Fri May 11 10:16:27 2007
+# Linux kernel version: 2.6.22-rc4
+# Thu Jun 14 19:52:01 2007
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -87,7 +87,11 @@ CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_SLAB=y
@@ -152,7 +156,11 @@ CONFIG_PS3_HTAB_SIZE=20
 CONFIG_PS3_USE_LPAR_ADDR=y
 CONFIG_PS3_VUART=y
 CONFIG_PS3_PS3AV=y
-CONFIG_PS3_SYS_MANAGER=y
+CONFIG_PS3_SYS_MANAGER=m
+CONFIG_PS3_STORAGE=y
+CONFIG_PS3_DISK=y
+CONFIG_PS3_ROM=y
+CONFIG_PS3_FLASH=y
 CONFIG_PPC_CELL=y
 # CONFIG_PPC_CELL_NATIVE is not set
 # CONFIG_PPC_IBM_CELL_BLADE is not set
@@ -301,20 +309,8 @@ CONFIG_IPV6_SIT=y
 # CONFIG_IPV6_MULTIPLE_TABLES is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -343,7 +339,7 @@ CONFIG_BT=m
 CONFIG_BT_L2CAP=m
 CONFIG_BT_SCO=m
 CONFIG_BT_RFCOMM=m
-# CONFIG_BT_RFCOMM_TTY is not set
+CONFIG_BT_RFCOMM_TTY=y
 # CONFIG_BT_BNEP is not set
 CONFIG_BT_HIDP=m
 
@@ -352,7 +348,9 @@ CONFIG_BT_HIDP=m
 #
 CONFIG_BT_HCIUSB=m
 CONFIG_BT_HCIUSB_SCO=y
-# CONFIG_BT_HCIUART is not set
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
 # CONFIG_BT_HCIBCM203X is not set
 # CONFIG_BT_HCIBPA10X is not set
 # CONFIG_BT_HCIBFUSB is not set
@@ -418,10 +416,6 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 # Misc devices
 #
 # CONFIG_BLINK is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
 # CONFIG_IDE is not set
 
 #
@@ -447,7 +441,7 @@ CONFIG_CHR_DEV_SG=m
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
 #
-# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_MULTI_LUN=y
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
 # CONFIG_SCSI_SCAN_ASYNC is not set
@@ -467,11 +461,6 @@ CONFIG_SCSI_WAIT_SCAN=m
 #
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_ESP_CORE is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 # CONFIG_ATA is not set
 
 #
@@ -490,27 +479,13 @@ CONFIG_NETDEVICES=y
 # CONFIG_TUN is not set
 
 #
-# PHY device support
-#
-
-#
 # Ethernet (10 or 100Mbit)
 #
 # CONFIG_NET_ETHERNET is not set
 CONFIG_MII=m
-
-#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-CONFIG_MLX4_DEBUG=y
-
-#
-# Token Ring devices
-#
+CONFIG_NETDEV_1000=y
+CONFIG_GELIC_NET=y
+# CONFIG_NETDEV_10000 is not set
 
 #
 # Wireless LAN
@@ -536,10 +511,6 @@ CONFIG_USB_NET_MCS7830=m
 # CONFIG_USB_NET_RNDIS_HOST is not set
 # CONFIG_USB_NET_CDC_SUBSET is not set
 # CONFIG_USB_NET_ZAURUS is not set
-
-#
-# Wan interfaces
-#
 # CONFIG_WAN is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
@@ -563,6 +534,7 @@ CONFIG_USB_NET_MCS7830=m
 #
 CONFIG_INPUT=y
 # CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
 
 #
 # Userland interfaces
@@ -581,7 +553,27 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 #
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
+CONFIG_INPUT_JOYSTICK=y
+# CONFIG_JOYSTICK_ANALOG is not set
+# CONFIG_JOYSTICK_A3D is not set
+# CONFIG_JOYSTICK_ADI is not set
+# CONFIG_JOYSTICK_COBRA is not set
+# CONFIG_JOYSTICK_GF2K is not set
+# CONFIG_JOYSTICK_GRIP is not set
+# CONFIG_JOYSTICK_GRIP_MP is not set
+# CONFIG_JOYSTICK_GUILLEMOT is not set
+# CONFIG_JOYSTICK_INTERACT is not set
+# CONFIG_JOYSTICK_SIDEWINDER is not set
+# CONFIG_JOYSTICK_TMDC is not set
+# CONFIG_JOYSTICK_IFORCE is not set
+# CONFIG_JOYSTICK_WARRIOR is not set
+# CONFIG_JOYSTICK_MAGELLAN is not set
+# CONFIG_JOYSTICK_SPACEORB is not set
+# CONFIG_JOYSTICK_SPACEBALL is not set
+# CONFIG_JOYSTICK_STINGER is not set
+# CONFIG_JOYSTICK_TWIDJOY is not set
+# CONFIG_JOYSTICK_JOYDUMP is not set
+# CONFIG_JOYSTICK_XPAD is not set
 # CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
@@ -598,7 +590,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
-# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_VT_HW_CONSOLE_BINDING=y
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -652,12 +644,8 @@ CONFIG_GEN_RTC=y
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-# CONFIG_USB_DABUSB is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
 
 #
 # Graphics support
@@ -672,13 +660,13 @@ CONFIG_GEN_RTC=y
 CONFIG_FB=y
 # CONFIG_FIRMWARE_EDID is not set
 # CONFIG_FB_DDC is not set
-CONFIG_FB_CFB_FILLRECT=y
-CONFIG_FB_CFB_COPYAREA=y
-CONFIG_FB_CFB_IMAGEBLIT=y
-# CONFIG_FB_SYS_FILLRECT is not set
-# CONFIG_FB_SYS_COPYAREA is not set
-# CONFIG_FB_SYS_IMAGEBLIT is not set
-# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+CONFIG_FB_SYS_FILLRECT=y
+CONFIG_FB_SYS_COPYAREA=y
+CONFIG_FB_SYS_IMAGEBLIT=y
+CONFIG_FB_SYS_FOPS=y
 CONFIG_FB_DEFERRED_IO=y
 # CONFIG_FB_SVGALIB is not set
 # CONFIG_FB_MACMODES is not set
@@ -751,9 +739,10 @@ CONFIG_SND_VERBOSE_PROCFS=y
 #
 # CONFIG_SND_USB_AUDIO is not set
 # CONFIG_SND_USB_USX2Y is not set
+# CONFIG_SND_USB_CAIAQ is not set
 
 #
-# SoC audio support
+# System on Chip audio support
 #
 # CONFIG_SND_SOC is not set
 
@@ -1098,7 +1087,6 @@ CONFIG_NLS_ISO8859_1=y
 #
 # CONFIG_DLM is not set
 # CONFIG_UCC_SLOW is not set
-# CONFIG_UCC_FAST is not set
 
 #
 # Library routines
@@ -1125,7 +1113,7 @@ CONFIG_HAS_DMA=y
 #
 # CONFIG_PRINTK_TIME is not set
 CONFIG_ENABLE_MUST_CHECK=y
-# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
@@ -1155,16 +1143,7 @@ CONFIG_DEBUG_STACKOVERFLOW=y
 # CONFIG_DEBUGGER is not set
 CONFIG_IRQSTACKS=y
 # CONFIG_BOOTX_TEXT is not set
-CONFIG_PPC_EARLY_DEBUG=y
-# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
-# CONFIG_PPC_EARLY_DEBUG_G5 is not set
-# CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL is not set
-# CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set
-# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
-# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
-# CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set
-# CONFIG_PPC_EARLY_DEBUG_BEAT is not set
-# CONFIG_PPC_EARLY_DEBUG_44x is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
 
 #
 # Security options

-- 

^ permalink raw reply

* [patch 30/33] PS3: Bootwrapper support.
From: Geoff Levand @ 2007-06-15 22:07 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev
In-Reply-To: <20070615204749.629571012@am.sony.com>

Add support to build the PS3 flash rom image.

zImage.ps3 is a wrapped image that contains a flat device tree, an lv1
compatible entry point, a wrapper program with a standard entry point,
and an optional initrd.  otheros.bld is the gzip compresed rom image built
from zImage.ps3.  otheros.bld is suitable for programming into the PS3 boot
flash memory.

Also remove the now unneeded lmb calls in the platform code.

Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
 arch/powerpc/boot/Makefile         |   21 ++--
 arch/powerpc/boot/ps3-head.S       |   84 ++++++++++++++++
 arch/powerpc/boot/ps3-hvcall.S     |  184 +++++++++++++++++++++++++++++++++++++
 arch/powerpc/boot/ps3.c            |  158 +++++++++++++++++++++++++++++++
 arch/powerpc/boot/wrapper          |   55 +++++++++++
 arch/powerpc/boot/zImage.ps3.lds.S |   50 ++++++++++
 arch/powerpc/platforms/ps3/mm.c    |    2 
 7 files changed, 543 insertions(+), 11 deletions(-)

--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -41,11 +41,13 @@ zliblinuxheader := zlib.h zconf.h zutil.
 $(addprefix $(obj)/,$(zlib) gunzip_util.o main.o): \
 	$(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader))
 
+src-plat-$(CONFIG_PPC_PS3) += ps3-head.S ps3-hvcall.S ps3.c
+
 src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \
 		ns16550.c serial.c simple_alloc.c div64.S util.S \
 		gunzip_util.c elf_util.c $(zlib) devtree.c \
 		44x.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c
-src-plat := of.c cuboot-83xx.c cuboot-85xx.c holly.c \
+src-plat := $(src-plat-y) of.c cuboot-83xx.c cuboot-85xx.c holly.c \
 		cuboot-ebony.c treeboot-ebony.c prpmc2800.c
 src-boot := $(src-wlib) $(src-plat) empty.c
 
@@ -75,11 +77,11 @@ $(addprefix $(obj)/,$(zliblinuxheader)):
 $(obj)/empty.c:
 	@touch $@
 
-$(obj)/zImage.lds $(obj)/zImage.coff.lds: $(obj)/%: $(srctree)/$(src)/%.S
+$(obj)/zImage.lds $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds: $(obj)/%: $(srctree)/$(src)/%.S
 	@cp $< $@
 
 clean-files := $(zlib) $(zlibheader) $(zliblinuxheader) \
-		empty.c zImage.coff.lds zImage.lds
+		empty.c zImage zImage.coff.lds zImage.ps3.lds zImage.lds
 
 quiet_cmd_bootcc = BOOTCC  $@
       cmd_bootcc = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $<
@@ -102,7 +104,7 @@ hostprogs-y	:= addnote addRamDisk hack-c
 
 targets		+= $(patsubst $(obj)/%,%,$(obj-boot) wrapper.a)
 extra-y		:= $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \
-		   $(obj)/zImage.lds $(obj)/zImage.coff.lds
+		   $(obj)/zImage.lds $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds
 
 wrapper		:=$(srctree)/$(src)/wrapper
 wrapperbits	:= $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree) \
@@ -187,11 +189,12 @@ $(obj)/zImage.%: vmlinux $(wrapperbits)
 $(obj)/zImage.iseries: vmlinux
 	$(STRIP) -s -R .comment $< -o $@
 
-$(obj)/zImage.ps3: vmlinux
-	$(STRIP) -s -R .comment $< -o $@
+$(obj)/zImage.ps3: vmlinux  $(wrapper) $(wrapperbits) $(srctree)/$(src)/dts/ps3.dts
+	$(STRIP) -s -R .comment $< -o vmlinux.strip
+	$(call cmd,wrap,ps3,$(srctree)/$(src)/dts/ps3.dts,,)
 
-$(obj)/zImage.initrd.ps3: vmlinux
-	@echo "  WARNING zImage.initrd.ps3 not supported (yet)"
+$(obj)/zImage.initrd.ps3: vmlinux  $(wrapper) $(wrapperbits) $(srctree)/$(src)/dts/ps3.dts $(obj)/ramdisk.image.gz
+	$(call cmd,wrap,ps3,$(srctree)/$(src)/dts/ps3.dts,,$(obj)/ramdisk.image.gz)
 
 $(obj)/zImage.holly-elf: vmlinux $(wrapperbits)
 	$(call if_changed,wrap,holly,$(obj)/dts/holly.dts,,)
@@ -230,7 +233,7 @@ install: $(CONFIGURE) $(addprefix $(obj)
 
 # anything not in $(targets)
 clean-files += $(image-) $(initrd-) zImage zImage.initrd cuImage.* \
-	treeImage.* zImage.dts zImage.dts_initrd
+	treeImage.* zImage.dts zImage.dts_initrd otheros.bld
 
 # clean up files cached by wrapper
 clean-kernel := vmlinux.strip vmlinux.bin
--- /dev/null
+++ b/arch/powerpc/boot/ps3-head.S
@@ -0,0 +1,84 @@
+/*
+ *  PS3 bootwrapper entry.
+ *
+ *  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.
+ *
+ *  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
+ */
+
+#include "ppc_asm.h"
+
+	.text
+
+/*
+ * __system_reset_overlay - The PS3 first stage entry.
+ *
+ * The bootwraper build script copies the 0x100 bytes at symbol
+ * __system_reset_overlay to offset 0x100 of the rom image.
+ */
+
+	.globl __system_reset_overlay
+__system_reset_overlay:
+
+	/* Switch to 32-bit mode. */
+
+	mfmsr	r9
+	clrldi	r9,r9,1
+	mtmsrd	r9
+	nop
+
+	/* Get thread number in r3 and branch. */
+
+	mfspr	r3, 0x88
+	cntlzw.	r3, r3
+	li	r4, 0
+	li	r5, 0
+	beq	1f
+
+	/* Secondary goes to __secondary_hold in kernel. */
+
+	li	r4, 0x60
+	mtctr	r4
+	bctr
+
+	/* Primary waits for __secondary_hold_acknowledge. */
+1:
+	li	r5, 0x10 /* __secondary_hold_acknowledge */
+	or	28, 28, 28 /* db8cyc */
+
+	ld	r4, 0(r5)
+	cmpdi	r4, 0
+	beq	1b
+
+	/* Primary goes to _zimage_start in wrapper. */
+
+	lis	r4, _zimage_start@ha
+	addi	r4, r4, _zimage_start@l
+	mtctr	r4
+	bctr
+
+/*
+ * __system_reset_kernel - Place holder for the kernel reset vector.
+ *
+ * The bootwrapper build script copies 0x100 bytes from offset 0x100
+ * of the rom image to the symbol __system_reset_kernel.  At runtime
+ * the bootwrapper program copies the 0x100 bytes at __system_reset_kernel
+ * to ram address 0x100.  This symbol must occupy 0x100 bytes.
+ */
+
+	.globl __system_reset_kernel
+__system_reset_kernel:
+
+	. = __system_reset_kernel + 0x100
--- /dev/null
+++ b/arch/powerpc/boot/ps3-hvcall.S
@@ -0,0 +1,184 @@
+/*
+ *  PS3 bootwrapper hvcalls.
+ *
+ *  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.
+ *
+ *  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
+ */
+
+#include "ppc_asm.h"
+
+/*
+ * The PS3 hypervisor uses a 64 bit "C" language calling convention.
+ * The routines here marshal arguments between the 32 bit wrapper
+ * program and the 64 bit hvcalls.
+ *
+ *  wrapper           lv1
+ *  32-bit (h,l)      64-bit
+ *
+ *  1: r3,r4          <-> r3
+ *  2: r5,r6          <-> r4
+ *  3: r7,r8          <-> r5
+ *  4: r9,r10         <-> r6
+ *  5: 8(r1),12(r1)   <-> r7
+ *  6: 16(r1),20(r1)  <-> r8
+ *  7: 24(r1),28(r1)  <-> r9
+ *  8: 32(r1),36(r1)  <-> r10
+ *
+ */
+
+.macro GLOBAL name
+	.section ".text"
+	.balign 4
+	.globl \name
+\name:
+.endm
+
+.macro NO_SUPPORT name
+	GLOBAL \name
+	b ps3_no_support
+.endm
+
+.macro HVCALL num
+	li r11, \num
+	.long 0x44000022
+	extsw r3, r3
+.endm
+
+.macro SAVE_LR offset=4
+	mflr r0
+	stw r0, \offset(r1)
+.endm
+
+.macro LOAD_LR offset=4
+	lwz r0, \offset(r1)
+	mtlr r0
+.endm
+
+.macro LOAD_64_REG target,high,low
+	sldi r11, \high, 32
+	or \target, r11, \low
+.endm
+
+.macro LOAD_64_STACK target,offset
+	ld \target, \offset(r1)
+.endm
+
+.macro LOAD_R3
+	LOAD_64_REG r3,r3,r4
+.endm
+
+.macro LOAD_R4
+	LOAD_64_REG r4,r5,r6
+.endm
+
+.macro LOAD_R5
+	LOAD_64_REG r5,r7,r8
+.endm
+
+.macro LOAD_R6
+	LOAD_64_REG r6,r9,r10
+.endm
+
+.macro LOAD_R7
+	LOAD_64_STACK r7,8
+.endm
+
+.macro LOAD_R8
+	LOAD_64_STACK r8,16
+.endm
+
+.macro LOAD_R9
+	LOAD_64_STACK r9,24
+.endm
+
+.macro LOAD_R10
+	LOAD_64_STACK r10,32
+.endm
+
+.macro LOAD_REGS_0
+	stwu 1,-16(1)
+	stw 3, 8(1)
+.endm
+
+.macro LOAD_REGS_5
+	LOAD_R3
+	LOAD_R4
+	LOAD_R5
+	LOAD_R6
+	LOAD_R7
+.endm
+
+.macro LOAD_REGS_6
+	LOAD_REGS_5
+	LOAD_R8
+.endm
+
+.macro LOAD_REGS_8
+	LOAD_REGS_6
+	LOAD_R9
+	LOAD_R10
+.endm
+
+.macro STORE_REGS_0_1
+	lwz r11, 8(r1)
+	std r4, 0(r11)
+	mr r4, r3
+	li r3, 0
+	addi r1,r1,16
+.endm
+
+.macro STORE_REGS_5_2
+	lwz r11, 16(r1)
+	std r4, 0(r11)
+	lwz r11, 24(r1)
+	std r5, 0(r11)
+.endm
+
+.macro STORE_REGS_6_1
+	lwz r11, 24(r1)
+	std r4, 0(r11)
+.endm
+
+GLOBAL lv1_get_logical_ppe_id
+	SAVE_LR
+	LOAD_REGS_0
+	HVCALL 69
+	STORE_REGS_0_1
+	LOAD_LR
+	blr
+
+GLOBAL lv1_get_logical_partition_id
+	SAVE_LR
+	LOAD_REGS_0
+	HVCALL 74
+	STORE_REGS_0_1
+	LOAD_LR
+	blr
+
+GLOBAL lv1_get_repository_node_value
+	SAVE_LR
+	LOAD_REGS_5
+	HVCALL 91
+	STORE_REGS_5_2
+	LOAD_LR
+	blr
+
+GLOBAL lv1_panic
+	SAVE_LR
+	LOAD_REGS_8
+	HVCALL 255
+	LOAD_LR
+	blr
--- /dev/null
+++ b/arch/powerpc/boot/ps3.c
@@ -0,0 +1,158 @@
+/*
+ *  PS3 bootwrapper support.
+ *
+ *  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.
+ *
+ *  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
+ */
+
+#include <stdarg.h>
+#include <stddef.h>
+#include "types.h"
+#include "elf.h"
+#include "string.h"
+#include "stdio.h"
+#include "page.h"
+#include "ops.h"
+
+extern s64 lv1_panic(u64 in_1);
+extern s64 lv1_get_logical_partition_id(u64 *out_1);
+extern s64 lv1_get_logical_ppe_id(u64 *out_1);
+extern s64 lv1_get_repository_node_value(u64 in_1, u64 in_2, u64 in_3,
+	u64 in_4, u64 in_5, u64 *out_1, u64 *out_2);
+
+#ifdef DEBUG
+#define DBG(fmt...) printf(fmt)
+#else
+static inline int __attribute__ ((format (printf, 1, 2))) DBG(
+	const char *fmt, ...) {return 0;}
+#endif
+
+BSS_STACK(4096);
+
+/* A buffer that may be edited by tools operating on a zImage binary so as to
+ * edit the command line passed to vmlinux (by setting /chosen/bootargs).
+ * The buffer is put in it's own section so that tools may locate it easier.
+ */
+static char cmdline[COMMAND_LINE_SIZE]
+	__attribute__((__section__("__builtin_cmdline")));
+
+static void prep_cmdline(void *chosen)
+{
+	if (cmdline[0] == '\0')
+		getprop(chosen, "bootargs", cmdline, COMMAND_LINE_SIZE-1);
+	else
+		setprop_str(chosen, "bootargs", cmdline);
+
+	printf("cmdline: '%s'\n", cmdline);
+}
+
+static void ps3_console_write(const char *buf, int len)
+{
+}
+
+static void ps3_exit(void)
+{
+	printf("ps3_exit\n");
+	lv1_panic(0); /* zero = no reboot */
+	while (1);
+}
+
+static int ps3_repository_read_rm_size(u64 *rm_size)
+{
+	s64 result;
+	u64 lpar_id;
+	u64 ppe_id;
+	u64 v2;
+
+	result = lv1_get_logical_partition_id(&lpar_id);
+
+	if (result)
+		return -1;
+
+	result = lv1_get_logical_ppe_id(&ppe_id);
+
+	if (result)
+		return -1;
+
+	/*
+	 * n1: 0000000062690000 : ....bi..
+	 * n2: 7075000000000000 : pu......
+	 * n3: 0000000000000001 : ........
+	 * n4: 726d5f73697a6500 : rm_size.
+	*/
+
+	result = lv1_get_repository_node_value(lpar_id, 0x0000000062690000ULL,
+		0x7075000000000000ULL, ppe_id, 0x726d5f73697a6500ULL, rm_size,
+		&v2);
+
+	printf("%s:%d: ppe_id  %lu \n", __func__, __LINE__,
+		(unsigned long)ppe_id);
+	printf("%s:%d: lpar_id %lu \n", __func__, __LINE__,
+		(unsigned long)lpar_id);
+	printf("%s:%d: rm_size %llxh \n", __func__, __LINE__, *rm_size);
+
+	return result ? -1 : 0;
+}
+
+void ps3_copy_vectors(void)
+{
+	extern char __system_reset_kernel[];
+
+	memcpy((void *)0x100, __system_reset_kernel, 0x100);
+	flush_cache((void *)0x100, 0x100);
+}
+
+void platform_init(void)
+{
+	extern char _end[];
+	extern char _dtb_start[];
+	extern char _initrd_start[];
+	extern char _initrd_end[];
+	const u32 heapsize = 0x1000000 - (u32)_end; /* 16MiB */
+	void *chosen;
+	unsigned long ft_addr;
+	u64 rm_size;
+
+	console_ops.write = ps3_console_write;
+	platform_ops.exit = ps3_exit;
+
+	printf("\n-- PS3 bootwrapper --\n");
+
+	simple_alloc_init(_end, heapsize, 32, 64);
+	ft_init(_dtb_start, 0, 4);
+
+	chosen = finddevice("/chosen");
+
+	ps3_repository_read_rm_size(&rm_size);
+	dt_fixup_memory(0, rm_size);
+
+	if (_initrd_end > _initrd_start) {
+		setprop_val(chosen, "linux,initrd-start", (u32)(_initrd_start));
+		setprop_val(chosen, "linux,initrd-end", (u32)(_initrd_end));
+	}
+
+	prep_cmdline(chosen);
+
+	ft_addr = dt_ops.finalize();
+
+	ps3_copy_vectors();
+
+	printf(" flat tree at 0x%lx\n\r", ft_addr);
+
+	((kernel_entry_t)0)(ft_addr, 0, NULL);
+
+	ps3_exit();
+}
--- a/arch/powerpc/boot/wrapper
+++ b/arch/powerpc/boot/wrapper
@@ -144,6 +144,15 @@ miboot|uboot)
 cuboot*)
     gzip=
     ;;
+ps3)
+    platformo="$object/ps3-head.o $object/ps3-hvcall.o $object/ps3.o"
+    lds=$object/zImage.ps3.lds
+    gzip=
+    ext=bin
+    objflags="-O binary"
+    ksection=.kernel:vmlinux.bin
+    isection=.kernel:initrd
+    ;;
 esac
 
 vmz="$tmpdir/`basename \"$kernel\"`.$ext"
@@ -239,4 +248,50 @@ treeboot*)
     fi
     exit 0
     ;;
+ps3)
+    # The ps3's loader supports loading gzipped binary images from flash
+    # rom to addr zero. The loader enters the image at addr 0x100.  A
+    # bootwrapper overlay is use to arrange for the kernel to be loaded
+    # to addr zero and to have a suitable bootwrapper entry at 0x100.
+    # To construct the rom image, 0x100 bytes from offset 0x100 in the
+    # kernel is copied to the bootwrapper symbol __system_reset_kernel.
+    # The 0x100 bytes at the bootwrapper symbol __system_reset_overlay is
+    # then copied to offset 0x100.  At runtime the bootwrapper program
+    # copies the 0x100 bytes at __system_reset_kernel to addr 0x100.
+
+    system_reset_overlay=0x`${CROSS}nm "$ofile" \
+        | grep ' __system_reset_overlay$'       \
+        | cut -d' ' -f1`
+    system_reset_overlay=`printf "%d" $system_reset_overlay`
+    system_reset_kernel=0x`${CROSS}nm "$ofile" \
+        | grep ' __system_reset_kernel$'       \
+        | cut -d' ' -f1`
+    system_reset_kernel=`printf "%d" $system_reset_kernel`
+    overlay_dest="256"
+    overlay_size="256"
+
+    rm -f "$object/otheros.bld"
+
+    ${CROSS}objcopy -O binary "$ofile" "$ofile.bin"
+
+    msg=$(dd if="$ofile.bin" of="$ofile.bin" conv=notrunc \
+        skip=$overlay_dest seek=$system_reset_kernel      \
+        count=$overlay_size bs=1 2>&1)
+
+    if [ $? -ne "0" ]; then
+       echo $msg
+       exit 1
+    fi
+
+    msg=$(dd if="$ofile.bin" of="$ofile.bin" conv=notrunc \
+        skip=$system_reset_overlay seek=$overlay_dest     \
+        count=$overlay_size bs=1 2>&1)
+
+    if [ $? -ne "0" ]; then
+       echo $msg
+       exit 2
+    fi
+
+    gzip --force -9 --stdout "$ofile.bin" > "$object/otheros.bld"
+    ;;
 esac
--- /dev/null
+++ b/arch/powerpc/boot/zImage.ps3.lds.S
@@ -0,0 +1,50 @@
+OUTPUT_ARCH(powerpc:common)
+ENTRY(_zimage_start)
+EXTERN(_zimage_start)
+SECTIONS
+{
+  _vmlinux_start =  .;
+  .kernel:vmlinux.bin : { *(.kernel:vmlinux.bin) }
+  _vmlinux_end =  .;
+
+  . = ALIGN(8);
+  _dtb_start = .;
+  .kernel:dtb : { *(.kernel:dtb) }
+  _dtb_end = .;
+
+  . = ALIGN(4096);
+  _initrd_start =  .;
+  .kernel:initrd : { *(.kernel:initrd) }
+  _initrd_end =  .;
+
+  _start = .;
+  .text      :
+  {
+    *(.text)
+    *(.fixup)
+  }
+  _etext = .;
+  . = ALIGN(4096);
+  .data    :
+  {
+    *(.rodata*)
+    *(.data*)
+    *(.sdata*)
+    __got2_start = .;
+    *(.got2)
+    __got2_end = .;
+  }
+
+  . = ALIGN(4096);
+  _edata  =  .;
+
+  . = ALIGN(4096);
+  __bss_start = .;
+  .bss       :
+  {
+   *(.sbss)
+   *(.bss)
+  }
+  . = ALIGN(4096);
+  _end = . ;
+}
--- a/arch/powerpc/platforms/ps3/mm.c
+++ b/arch/powerpc/platforms/ps3/mm.c
@@ -1213,8 +1213,6 @@ void __init ps3_mm_init(void)
 	BUG_ON(map.rm.base);
 	BUG_ON(!map.rm.size);
 
-	lmb_add(map.rm.base, map.rm.size);
-	lmb_analyze();
 
 	/* arrange to do this in ps3_mm_add_memory */
 	ps3_mm_region_create(&map.r1, map.total - map.rm.size);

-- 

^ permalink raw reply

* [patch 27/33] Powerpc: Fix constantness of bootwrapper arg
From: Geoff Levand @ 2007-06-15 22:06 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev
In-Reply-To: <20070615204749.629571012@am.sony.com>

Fixes the constantness of the powerpc bootwrapper's console_ops.write
routine.  Allows writing of constant strings.

Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
 arch/powerpc/boot/of.c     |    2 +-
 arch/powerpc/boot/ops.h    |    2 +-
 arch/powerpc/boot/serial.c |    2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

--- a/arch/powerpc/boot/of.c
+++ b/arch/powerpc/boot/of.c
@@ -261,7 +261,7 @@ static int of_console_open(void)
 	return -1;
 }
 
-static void of_console_write(char *buf, int len)
+static void of_console_write(const char *buf, int len)
 {
 	call_prom("write", 3, 1, of_stdout_handle, buf, len);
 }
--- a/arch/powerpc/boot/ops.h
+++ b/arch/powerpc/boot/ops.h
@@ -51,7 +51,7 @@ extern struct dt_ops dt_ops;
 /* Console operations */
 struct console_ops {
 	int	(*open)(void);
-	void	(*write)(char *buf, int len);
+	void	(*write)(const char *buf, int len);
 	void	(*edit_cmdline)(char *buf, int len);
 	void	(*close)(void);
 	void	*data;
--- a/arch/powerpc/boot/serial.c
+++ b/arch/powerpc/boot/serial.c
@@ -27,7 +27,7 @@ static int serial_open(void)
 	return scdp->open();
 }
 
-static void serial_write(char *buf, int len)
+static void serial_write(const char *buf, int len)
 {
 	struct serial_console_data *scdp = console_ops.data;
 

-- 

^ permalink raw reply

* [patch 32/33] PS3: Fix more sparse warnings
From: Geoff Levand @ 2007-06-15 22:07 UTC (permalink / raw)
  To: paulus; +Cc: Geert Uytterhoeven, linuxppc-dev
In-Reply-To: <20070615204749.629571012@am.sony.com>

From: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>

Fix some PS3 build warnings reported by `make C=1'.

Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
 arch/powerpc/platforms/ps3/mm.c |   10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

--- a/arch/powerpc/platforms/ps3/mm.c
+++ b/arch/powerpc/platforms/ps3/mm.c
@@ -239,7 +239,7 @@ void ps3_mm_vas_destroy(void)
  * @size is rounded down to a multiple of the vas large page size.
  */
 
-int ps3_mm_region_create(struct mem_region *r, unsigned long size)
+static int ps3_mm_region_create(struct mem_region *r, unsigned long size)
 {
 	int result;
 	unsigned long muid;
@@ -280,7 +280,7 @@ zero_region:
  * @r: pointer to struct mem_region
  */
 
-void ps3_mm_region_destroy(struct mem_region *r)
+static void ps3_mm_region_destroy(struct mem_region *r)
 {
 	int result;
 
@@ -893,7 +893,7 @@ static int dma_ioc0_map_area(struct ps3_
  * This is the common dma unmap routine.
  */
 
-int dma_sb_unmap_area(struct ps3_dma_region *r, unsigned long bus_addr,
+static int dma_sb_unmap_area(struct ps3_dma_region *r, unsigned long bus_addr,
 	unsigned long len)
 {
 	unsigned long flags;
@@ -929,8 +929,8 @@ int dma_sb_unmap_area(struct ps3_dma_reg
 	return 0;
 }
 
-int dma_ioc0_unmap_area(struct ps3_dma_region *r, unsigned long bus_addr,
-			unsigned long len)
+static int dma_ioc0_unmap_area(struct ps3_dma_region *r,
+			unsigned long bus_addr, unsigned long len)
 {
 	unsigned long flags;
 	struct dma_chunk *c;

-- 

^ permalink raw reply

* [patch 28/33] powerpc: Bootwrapper global scope kernel_entry_t.
From: Geoff Levand @ 2007-06-15 22:06 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev
In-Reply-To: <20070615204749.629571012@am.sony.com>

For the convenience of custom platform code make the powerpc
bootwrapper typdef kernel_entry_t global in scope.

Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
 arch/powerpc/boot/main.c |    2 --
 arch/powerpc/boot/ops.h  |    2 ++
 2 files changed, 2 insertions(+), 2 deletions(-)

--- a/arch/powerpc/boot/main.c
+++ b/arch/powerpc/boot/main.c
@@ -36,8 +36,6 @@ struct addr_range {
 	unsigned long size;
 };
 
-typedef void (*kernel_entry_t)(unsigned long, unsigned long, void *);
-
 #undef DEBUG
 
 static struct addr_range prep_kernel(void)
--- a/arch/powerpc/boot/ops.h
+++ b/arch/powerpc/boot/ops.h
@@ -19,6 +19,8 @@
 #define	MAX_PATH_LEN		256
 #define	MAX_PROP_LEN		256 /* What should this be? */
 
+typedef void (*kernel_entry_t)(unsigned long r3, unsigned long r4, void *r5);
+
 /* Platform specific operations */
 struct platform_ops {
 	void	(*fixups)(void);

-- 

^ permalink raw reply

* [patch 29/33] PS3: Device tree source.
From: Geoff Levand @ 2007-06-15 22:06 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev
In-Reply-To: <20070615204749.629571012@am.sony.com>

The PS3 device tree source.

Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
 o After extended mail and IRC discussions, everyone aggreed on this one.

 arch/powerpc/boot/dts/ps3.dts      |   68 +++++++++++++++++++++++++++++++++++++
 arch/powerpc/platforms/ps3/setup.c |    2 -
 2 files changed, 69 insertions(+), 1 deletion(-)

--- /dev/null
+++ b/arch/powerpc/boot/dts/ps3.dts
@@ -0,0 +1,68 @@
+/*
+ *  PS3 Game Console device tree.
+ *
+ *  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.
+ *
+ *  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
+ */
+
+/ {
+	model = "SonyPS3";
+	compatible = "sony,ps3";
+	#size-cells = <2>;
+	#address-cells = <2>;
+
+	chosen {
+	};
+
+	/*
+	 * We'll get the size of the bootmem block from lv1 after startup,
+	 * so we'll put a null entry here.
+	 */
+
+	memory {
+		device_type = "memory";
+		reg = <0 0 0 0>;
+	};
+
+	/*
+	 * The boot cpu is always zero for PS3.
+	 *
+	 * dtc expects a clock-frequency and timebase-frequency entries, so
+	 * we'll put a null entries here.  These will be initialized after
+	 * startup with data from lv1.
+	 *
+	 * Seems the only way currently to indicate a processor has multiple
+	 * threads is with an ibm,ppc-interrupt-server#s entry.  We'll put one
+	 * here so we can bring up both of ours.  See smp_setup_cpu_maps().
+	 */
+
+	cpus {
+		#size-cells = <0>;
+		#address-cells = <1>;
+
+		cpu@0 {
+			device_type = "cpu";
+			reg = <0>;
+			ibm,ppc-interrupt-server#s = <0 1>;
+			clock-frequency = <0>;
+			timebase-frequency = <0>;
+			i-cache-size = <8000>;
+			d-cache-size = <8000>;
+			i-cache-line-size = <80>;
+			d-cache-line-size = <80>;
+		};
+	};
+};
--- a/arch/powerpc/platforms/ps3/setup.c
+++ b/arch/powerpc/platforms/ps3/setup.c
@@ -193,7 +193,7 @@ static int __init ps3_probe(void)
 	DBG(" -> %s:%d\n", __func__, __LINE__);
 
 	dt_root = of_get_flat_dt_root();
-	if (!of_flat_dt_is_compatible(dt_root, "PS3"))
+	if (!of_flat_dt_is_compatible(dt_root, "sony,ps3"))
 		return 0;
 
 	powerpc_firmware_features |= FW_FEATURE_PS3_POSSIBLE;

-- 

^ permalink raw reply

* [patch 31/33] PS3: Select MEMORY_HOTPLUG.
From: Geoff Levand @ 2007-06-15 22:07 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev
In-Reply-To: <20070615204749.629571012@am.sony.com>

The PS3 uses the kernel's hotplug memory support, so make sure it is
always enabled when building for PS3.

Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
 arch/powerpc/platforms/ps3/Kconfig |    1 +
 1 file changed, 1 insertion(+)

--- a/arch/powerpc/platforms/ps3/Kconfig
+++ b/arch/powerpc/platforms/ps3/Kconfig
@@ -7,6 +7,7 @@ config PPC_PS3
 	select USB_OHCI_BIG_ENDIAN_MMIO
 	select USB_ARCH_HAS_EHCI
 	select USB_EHCI_BIG_ENDIAN_MMIO
+	select MEMORY_HOTPLUG
 	help
 	  This option enables support for the Sony PS3 game console
 	  and other platforms using the PS3 hypervisor.

-- 

^ permalink raw reply

* [patch 26/33] Powerpc: Add u64 printf to bootwrapper
From: Geoff Levand @ 2007-06-15 22:06 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev
In-Reply-To: <20070615204749.629571012@am.sony.com>

Add support for the 'll' (long long) printf qualifier in the powerpc zImage
bootwrapper.  This is useful for bootwrapper debugging on 64 bit platforms.

Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
 arch/powerpc/boot/stdio.c |   10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

--- a/arch/powerpc/boot/stdio.c
+++ b/arch/powerpc/boot/stdio.c
@@ -190,7 +190,11 @@ int vsprintf(char *buf, const char *fmt,
 
 		/* get the conversion qualifier */
 		qualifier = -1;
-		if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') {
+		if (*fmt == 'l' && *(fmt + 1) == 'l') {
+			qualifier = 'q';
+			fmt += 2;
+		} else if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L'
+			|| *fmt == 'Z') {
 			qualifier = *fmt;
 			++fmt;
 		}
@@ -281,6 +285,10 @@ int vsprintf(char *buf, const char *fmt,
 			num = va_arg(args, unsigned long);
 			if (flags & SIGN)
 				num = (signed long) num;
+		} else if (qualifier == 'q') {
+			num = va_arg(args, unsigned long long);
+			if (flags & SIGN)
+				num = (signed long long) num;
 		} else if (qualifier == 'Z') {
 			num = va_arg(args, size_t);
 		} else if (qualifier == 'h') {

-- 

^ permalink raw reply

* [patch 19/33] PS3: Device registration routines.
From: Geoff Levand @ 2007-06-15 22:05 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev
In-Reply-To: <20070615204749.629571012@am.sony.com>

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

Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
  o Fixed __init and __devinit markers.

 arch/powerpc/platforms/ps3/Makefile      |    1 
 arch/powerpc/platforms/ps3/device-init.c |  499 +++++++++++++++++++++++++++++++
 2 files changed, 500 insertions(+)

--- a/arch/powerpc/platforms/ps3/Makefile
+++ b/arch/powerpc/platforms/ps3/Makefile
@@ -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
--- /dev/null
+++ b/arch/powerpc/platforms/ps3/device-init.c
@@ -0,0 +1,499 @@
+/*
+ *  PS3 device registration routines.
+ *
+ *  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.
+ *
+ *  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
+ */
+
+#include <linux/delay.h>
+#include <linux/freezer.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/init.h>
+
+#include <asm/firmware.h>
+#include <asm/lv1call.h>
+
+#include "platform.h"
+
+/**
+ * ps3_setup_gelic_device - Setup and register a gelic device instance.
+ *
+ * Allocates memory for a struct ps3_system_bus_device instance, initialises the
+ * structure members, and registers the device instance with the system bus.
+ */
+
+static int __init ps3_setup_gelic_device(
+	const struct ps3_repository_device *repo)
+{
+	int result;
+	struct layout {
+		struct ps3_system_bus_device dev;
+		struct ps3_dma_region d_region;
+	} *p;
+
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+	BUG_ON(repo->bus_type != PS3_BUS_TYPE_SB);
+	BUG_ON(repo->dev_type != PS3_DEV_TYPE_SB_GELIC);
+
+	p = kzalloc(sizeof(struct layout), GFP_KERNEL);
+
+	if (!p) {
+		result = -ENOMEM;
+		goto fail_malloc;
+	}
+
+	p->dev.match_id = PS3_MATCH_ID_GELIC;
+	p->dev.dev_type = PS3_DEVICE_TYPE_SB;
+	p->dev.bus_id = repo->bus_id;
+	p->dev.dev_id = repo->dev_id;
+	p->dev.d_region = &p->d_region;
+
+	result = ps3_repository_find_interrupt(repo,
+		PS3_INTERRUPT_TYPE_EVENT_PORT, &p->dev.interrupt_id);
+
+	if (result) {
+		pr_debug("%s:%d ps3_repository_find_interrupt failed\n",
+			__func__, __LINE__);
+		goto fail_find_interrupt;
+	}
+
+	BUG_ON(p->dev.interrupt_id != 0);
+
+	result = ps3_dma_region_init(&p->dev, p->dev.d_region, PS3_DMA_64K,
+		PS3_DMA_OTHER, NULL, 0);
+
+	if (result) {
+		pr_debug("%s:%d ps3_dma_region_init failed\n",
+			__func__, __LINE__);
+		goto fail_dma_init;
+	}
+
+	result = ps3_system_bus_device_register(&p->dev);
+
+	if (result) {
+		pr_debug("%s:%d ps3_system_bus_device_register failed\n",
+			__func__, __LINE__);
+		goto fail_device_register;
+	}
+
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	return result;
+
+fail_device_register:
+fail_dma_init:
+fail_find_interrupt:
+	kfree(p);
+fail_malloc:
+	pr_debug(" <- %s:%d: fail.\n", __func__, __LINE__);
+	return result;
+}
+
+static int __init_refok ps3_setup_uhc_device(
+	const struct ps3_repository_device *repo, enum ps3_match_id match_id,
+	enum ps3_interrupt_type interrupt_type, enum ps3_reg_type reg_type)
+{
+	int result;
+	struct layout {
+		struct ps3_system_bus_device dev;
+		struct ps3_dma_region d_region;
+		struct ps3_mmio_region m_region;
+	} *p;
+	u64 bus_addr;
+	u64 len;
+
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+	BUG_ON(repo->bus_type != PS3_BUS_TYPE_SB);
+	BUG_ON(repo->dev_type != PS3_DEV_TYPE_SB_USB);
+
+	p = kzalloc(sizeof(struct layout), GFP_KERNEL);
+
+	if (!p) {
+		result = -ENOMEM;
+		goto fail_malloc;
+	}
+
+	p->dev.match_id = match_id;
+	p->dev.dev_type = PS3_DEVICE_TYPE_SB;
+	p->dev.bus_id = repo->bus_id;
+	p->dev.dev_id = repo->dev_id;
+	p->dev.d_region = &p->d_region;
+	p->dev.m_region = &p->m_region;
+
+	result = ps3_repository_find_interrupt(repo,
+		interrupt_type, &p->dev.interrupt_id);
+
+	if (result) {
+		pr_debug("%s:%d ps3_repository_find_interrupt failed\n",
+			__func__, __LINE__);
+		goto fail_find_interrupt;
+	}
+
+	result = ps3_repository_find_reg(repo, reg_type,
+		&bus_addr, &len);
+
+	if (result) {
+		pr_debug("%s:%d ps3_repository_find_reg failed\n",
+			__func__, __LINE__);
+		goto fail_find_reg;
+	}
+
+	result = ps3_dma_region_init(&p->dev, p->dev.d_region, PS3_DMA_64K,
+		PS3_DMA_INTERNAL, NULL, 0);
+
+	if (result) {
+		pr_debug("%s:%d ps3_dma_region_init failed\n",
+			__func__, __LINE__);
+		goto fail_dma_init;
+	}
+
+	result = ps3_mmio_region_init(&p->dev, p->dev.m_region, bus_addr, len,
+		PS3_MMIO_4K);
+
+	if (result) {
+		pr_debug("%s:%d ps3_mmio_region_init failed\n",
+			__func__, __LINE__);
+		goto fail_mmio_init;
+	}
+
+	result = ps3_system_bus_device_register(&p->dev);
+
+	if (result) {
+		pr_debug("%s:%d ps3_system_bus_device_register failed\n",
+			__func__, __LINE__);
+		goto fail_device_register;
+	}
+
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	return result;
+
+fail_device_register:
+fail_mmio_init:
+fail_dma_init:
+fail_find_reg:
+fail_find_interrupt:
+	kfree(p);
+fail_malloc:
+	pr_debug(" <- %s:%d: fail.\n", __func__, __LINE__);
+	return result;
+}
+
+static int __init ps3_setup_ehci_device(
+	const struct ps3_repository_device *repo)
+{
+	return ps3_setup_uhc_device(repo, PS3_MATCH_ID_EHCI,
+		PS3_INTERRUPT_TYPE_SB_EHCI, PS3_REG_TYPE_SB_EHCI);
+}
+
+static int __init ps3_setup_ohci_device(
+	const struct ps3_repository_device *repo)
+{
+	return ps3_setup_uhc_device(repo, PS3_MATCH_ID_OHCI,
+		PS3_INTERRUPT_TYPE_SB_OHCI, PS3_REG_TYPE_SB_OHCI);
+}
+
+static int __init ps3_setup_vuart_device(enum ps3_match_id match_id,
+	unsigned int port_number)
+{
+	int result;
+	struct layout {
+		struct ps3_system_bus_device dev;
+	} *p;
+
+	pr_debug(" -> %s:%d: match_id %u, port %u\n", __func__, __LINE__,
+		match_id, port_number);
+
+	p = kzalloc(sizeof(struct layout), GFP_KERNEL);
+
+	if (!p)
+		return -ENOMEM;
+
+	p->dev.match_id = match_id;
+	p->dev.dev_type = PS3_DEVICE_TYPE_VUART;
+	p->dev.port_number = port_number;
+
+	result = ps3_system_bus_device_register(&p->dev);
+
+	if (result)
+		pr_debug("%s:%d ps3_system_bus_device_register failed\n",
+			__func__, __LINE__);
+
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	return result;
+}
+
+static int __init ps3_register_vuart_devices(void)
+{
+	int result;
+	unsigned int port_number;
+
+	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);
+
+	result = ps3_repository_read_vuart_sysmgr_port(&port_number);
+	if (result)
+		port_number = 2; /* sysmgr default */
+
+	result = ps3_setup_vuart_device(PS3_MATCH_ID_SYSTEM_MANAGER,
+		port_number);
+	WARN_ON(result);
+
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	return result;
+}
+
+static int __init ps3_register_sound_devices(void)
+{
+	int result;
+	struct layout {
+		struct ps3_system_bus_device dev;
+		struct ps3_dma_region d_region;
+		struct ps3_mmio_region m_region;
+	} *p;
+
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+	p = kzalloc(sizeof(*p), GFP_KERNEL);
+	if (!p)
+		return -ENOMEM;
+
+	p->dev.match_id = PS3_MATCH_ID_SOUND;
+	p->dev.dev_type = PS3_DEVICE_TYPE_IOC0;
+	p->dev.d_region = &p->d_region;
+	p->dev.m_region = &p->m_region;
+
+	result = ps3_system_bus_device_register(&p->dev);
+
+	if (result)
+		pr_debug("%s:%d ps3_system_bus_device_register failed\n",
+			__func__, __LINE__);
+
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	return result;
+}
+
+static int __init ps3_register_graphics_devices(void)
+{
+	int result;
+	struct layout {
+		struct ps3_system_bus_device dev;
+	} *p;
+
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+	p = kzalloc(sizeof(struct layout), GFP_KERNEL);
+
+	if (!p)
+		return -ENOMEM;
+
+	p->dev.match_id = PS3_MATCH_ID_GRAPHICS;
+	p->dev.dev_type = PS3_DEVICE_TYPE_IOC0;
+
+	result = ps3_system_bus_device_register(&p->dev);
+
+	if (result)
+		pr_debug("%s:%d ps3_system_bus_device_register failed\n",
+			__func__, __LINE__);
+
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	return result;
+}
+
+/**
+ * ps3_register_repository_device - Register a device from the repositiory info.
+ *
+ */
+
+static int ps3_register_repository_device(
+	const struct ps3_repository_device *repo)
+{
+	int result;
+
+	switch (repo->dev_type) {
+	case PS3_DEV_TYPE_SB_GELIC:
+		result = ps3_setup_gelic_device(repo);
+		if (result) {
+			pr_debug("%s:%d ps3_setup_gelic_device failed\n",
+				__func__, __LINE__);
+		}
+		break;
+	case PS3_DEV_TYPE_SB_USB:
+
+		/* Each USB device has both an EHCI and an OHCI HC */
+
+		result = ps3_setup_ehci_device(repo);
+
+		if (result) {
+			pr_debug("%s:%d ps3_setup_ehci_device failed\n",
+				__func__, __LINE__);
+		}
+
+		result = ps3_setup_ohci_device(repo);
+
+		if (result) {
+			pr_debug("%s:%d ps3_setup_ohci_device failed\n",
+				__func__, __LINE__);
+		}
+		break;
+	default:
+		result = 0;
+		pr_debug("%s:%u: unsupported dev_type %u\n", __func__, __LINE__,
+			repo->dev_type);
+	}
+
+	return result;
+}
+
+/**
+ * ps3_probe_thread - Background repository probing at system startup.
+ *
+ * This implementation only supports background probing on a single bus.
+ */
+
+static int ps3_probe_thread(void *data)
+{
+	struct ps3_repository_device *repo = data;
+	int result;
+	unsigned int ms = 250;
+
+	pr_debug(" -> %s:%u: kthread started\n", __func__, __LINE__);
+
+	do {
+		try_to_freeze();
+
+		pr_debug("%s:%u: probing...\n", __func__, __LINE__);
+
+		do {
+			result = ps3_repository_find_device(repo);
+
+			if (result == -ENODEV)
+				pr_debug("%s:%u: nothing new\n", __func__,
+					__LINE__);
+			else if (result)
+				pr_debug("%s:%u: find device error.\n",
+					__func__, __LINE__);
+			else {
+				pr_debug("%s:%u: found device\n", __func__,
+					__LINE__);
+				ps3_register_repository_device(repo);
+				ps3_repository_bump_device(repo);
+				ms = 250;
+			}
+		} while (!result);
+
+		pr_debug("%s:%u: ms %u\n", __func__, __LINE__, ms);
+
+		if ( ms > 60000)
+			break;
+
+		msleep_interruptible(ms);
+
+		/* An exponential backoff. */
+		ms <<= 1;
+
+	} while (!kthread_should_stop());
+
+	pr_debug(" <- %s:%u: kthread finished\n", __func__, __LINE__);
+
+	return 0;
+}
+
+/**
+ * ps3_start_probe_thread - Starts the background probe thread.
+ *
+ */
+
+static int __init ps3_start_probe_thread(enum ps3_bus_type bus_type)
+{
+	int result;
+	struct task_struct *task;
+	static struct ps3_repository_device repo; /* must be static */
+
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+	memset(&repo, 0, sizeof(repo));
+
+	repo.bus_type = bus_type;
+
+	result = ps3_repository_find_bus(repo.bus_type, 0, &repo.bus_index);
+
+	if (result) {
+		printk(KERN_ERR "%s: Cannot find bus (%d)\n", __func__, result);
+		return -ENODEV;
+	}
+
+	result = ps3_repository_read_bus_id(repo.bus_index, &repo.bus_id);
+
+	if (result) {
+		printk(KERN_ERR "%s: read_bus_id failed %d\n", __func__,
+			result);
+		return -ENODEV;
+	}
+
+	task = kthread_run(ps3_probe_thread, &repo, "ps3-probe-%u", bus_type);
+
+	if (IS_ERR(task)) {
+		result = PTR_ERR(task);
+		printk(KERN_ERR "%s: kthread_run failed %d\n", __func__,
+		       result);
+		return result;
+	}
+
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	return 0;
+}
+
+/**
+ * ps3_register_devices - Probe the system and register devices found.
+ *
+ * A device_initcall() routine.
+ */
+
+static int __init ps3_register_devices(void)
+{
+	int result;
+
+	if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
+		return -ENODEV;
+
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+	/* ps3_repository_dump_bus_info(); */
+
+	result = ps3_start_probe_thread(PS3_BUS_TYPE_STORAGE);
+
+	ps3_register_vuart_devices();
+
+	ps3_register_graphics_devices();
+
+	ps3_repository_find_devices(PS3_BUS_TYPE_SB,
+		ps3_register_repository_device);
+
+	ps3_register_sound_devices();
+
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	return 0;
+}
+
+device_initcall(ps3_register_devices);

-- 

^ permalink raw reply

* [patch 15/33] PS3: Vuart rework
From: Geoff Levand @ 2007-06-15 22:01 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev
In-Reply-To: <20070615204749.629571012@am.sony.com>

PS3 vuart updates to reflect the new PS3 unified 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.

Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
 arch/powerpc/platforms/ps3/Kconfig     |   21 
 arch/powerpc/platforms/ps3/interrupt.c |    2 
 drivers/ps3/vuart.c                    |  813 +++++++++++++++++++--------------
 drivers/ps3/vuart.h                    |   71 --
 include/asm-powerpc/ps3.h              |   17 
 5 files changed, 520 insertions(+), 404 deletions(-)

--- a/arch/powerpc/platforms/ps3/Kconfig
+++ b/arch/powerpc/platforms/ps3/Kconfig
@@ -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
--- a/arch/powerpc/platforms/ps3/interrupt.c
+++ b/arch/powerpc/platforms/ps3/interrupt.c
@@ -564,6 +564,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)
 {
@@ -583,6 +584,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.
--- a/drivers/ps3/vuart.c
+++ b/drivers/ps3/vuart.c
@@ -71,6 +71,34 @@ enum vuart_interrupt_mask {
 };
 
 /**
+ * struct ps3_vuart_port_priv - private vuart device data.
+ */
+
+struct ps3_vuart_port_priv {
+	u64 interrupt_mask;
+
+	struct {
+		spinlock_t lock;
+		struct list_head head;
+	} tx_list;
+	struct {
+		struct ps3_vuart_work work;
+		unsigned long bytes_held;
+		spinlock_t lock;
+		struct list_head head;
+	} rx_list;
+	struct ps3_vuart_stats stats;
+};
+
+static struct ps3_vuart_port_priv *to_port_priv(
+	struct ps3_system_bus_device *dev)
+{
+	BUG_ON(!dev);
+	BUG_ON(!dev->driver_priv);
+	return (struct ps3_vuart_port_priv *)dev->driver_priv;
+}
+
+/**
  * struct ports_bmp - bitmap indicating ports needing service.
  *
  * A 256 bit read only bitmap indicating ports needing service.  Do not write
@@ -89,23 +117,6 @@ static void __maybe_unused _dump_ports_b
 	pr_debug("%s:%d: ports_bmp: %016lxh\n", func, line, bmp->status);
 }
 
-static int ps3_vuart_match_id_to_port(enum ps3_match_id match_id,
-	unsigned int *port_number)
-{
-	switch(match_id) {
-	case PS3_MATCH_ID_AV_SETTINGS:
-		*port_number = 0;
-		return 0;
-	case PS3_MATCH_ID_SYSTEM_MANAGER:
-		*port_number = 2;
-		return 0;
-	default:
-		WARN_ON(1);
-		*port_number = UINT_MAX;
-		return -EINVAL;
-	};
-}
-
 #define dump_port_params(_b) _dump_port_params(_b, __func__, __LINE__)
 static void __maybe_unused _dump_port_params(unsigned int port_number,
 	const char* func, int line)
@@ -144,14 +155,14 @@ struct vuart_triggers {
 	unsigned long tx;
 };
 
-int ps3_vuart_get_triggers(struct ps3_vuart_port_device *dev,
+int ps3_vuart_get_triggers(struct ps3_system_bus_device *dev,
 	struct vuart_triggers *trig)
 {
 	int result;
 	unsigned long size;
 	unsigned long val;
 
-	result = lv1_get_virtual_uart_param(dev->priv->port_number,
+	result = lv1_get_virtual_uart_param(dev->port_number,
 		PARAM_TX_TRIGGER, &trig->tx);
 
 	if (result) {
@@ -160,7 +171,7 @@ int ps3_vuart_get_triggers(struct ps3_vu
 		return result;
 	}
 
-	result = lv1_get_virtual_uart_param(dev->priv->port_number,
+	result = lv1_get_virtual_uart_param(dev->port_number,
 		PARAM_RX_BUF_SIZE, &size);
 
 	if (result) {
@@ -169,7 +180,7 @@ int ps3_vuart_get_triggers(struct ps3_vu
 		return result;
 	}
 
-	result = lv1_get_virtual_uart_param(dev->priv->port_number,
+	result = lv1_get_virtual_uart_param(dev->port_number,
 		PARAM_RX_TRIGGER, &val);
 
 	if (result) {
@@ -186,13 +197,13 @@ int ps3_vuart_get_triggers(struct ps3_vu
 	return result;
 }
 
-int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx,
+int ps3_vuart_set_triggers(struct ps3_system_bus_device *dev, unsigned int tx,
 	unsigned int rx)
 {
 	int result;
 	unsigned long size;
 
-	result = lv1_set_virtual_uart_param(dev->priv->port_number,
+	result = lv1_set_virtual_uart_param(dev->port_number,
 		PARAM_TX_TRIGGER, tx);
 
 	if (result) {
@@ -201,7 +212,7 @@ int ps3_vuart_set_triggers(struct ps3_vu
 		return result;
 	}
 
-	result = lv1_get_virtual_uart_param(dev->priv->port_number,
+	result = lv1_get_virtual_uart_param(dev->port_number,
 		PARAM_RX_BUF_SIZE, &size);
 
 	if (result) {
@@ -210,7 +221,7 @@ int ps3_vuart_set_triggers(struct ps3_vu
 		return result;
 	}
 
-	result = lv1_set_virtual_uart_param(dev->priv->port_number,
+	result = lv1_set_virtual_uart_param(dev->port_number,
 		PARAM_RX_TRIGGER, size - rx);
 
 	if (result) {
@@ -225,10 +236,12 @@ int ps3_vuart_set_triggers(struct ps3_vu
 	return result;
 }
 
-static int ps3_vuart_get_rx_bytes_waiting(struct ps3_vuart_port_device *dev,
+static int ps3_vuart_get_rx_bytes_waiting(struct ps3_system_bus_device *dev,
 	u64 *bytes_waiting)
 {
-	int result = lv1_get_virtual_uart_param(dev->priv->port_number,
+	int result;
+
+	result = lv1_get_virtual_uart_param(dev->port_number,
 		PARAM_RX_BYTES, bytes_waiting);
 
 	if (result)
@@ -240,17 +253,24 @@ static int ps3_vuart_get_rx_bytes_waitin
 	return result;
 }
 
-static int ps3_vuart_set_interrupt_mask(struct ps3_vuart_port_device *dev,
+/**
+ * ps3_vuart_set_interrupt_mask - Enable/disable the port interrupt sources.
+ * @dev: The struct ps3_system_bus_device instance.
+ * @bmp: Logical OR of enum vuart_interrupt_mask values. A zero bit disables.
+ */
+
+static int ps3_vuart_set_interrupt_mask(struct ps3_system_bus_device *dev,
 	unsigned long mask)
 {
 	int result;
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
 
 	dev_dbg(&dev->core, "%s:%d: %lxh\n", __func__, __LINE__, mask);
 
-	dev->priv->interrupt_mask = mask;
+	priv->interrupt_mask = mask;
 
-	result = lv1_set_virtual_uart_param(dev->priv->port_number,
-		PARAM_INTERRUPT_MASK, dev->priv->interrupt_mask);
+	result = lv1_set_virtual_uart_param(dev->port_number,
+		PARAM_INTERRUPT_MASK, priv->interrupt_mask);
 
 	if (result)
 		dev_dbg(&dev->core, "%s:%d: interrupt_mask failed: %s\n",
@@ -259,79 +279,96 @@ static int ps3_vuart_set_interrupt_mask(
 	return result;
 }
 
-static int ps3_vuart_get_interrupt_status(struct ps3_vuart_port_device *dev,
+static int ps3_vuart_get_interrupt_status(struct ps3_system_bus_device *dev,
 	unsigned long *status)
 {
+	int result;
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
 	u64 tmp;
-	int result = lv1_get_virtual_uart_param(dev->priv->port_number,
+
+	result = lv1_get_virtual_uart_param(dev->port_number,
 		PARAM_INTERRUPT_STATUS, &tmp);
 
 	if (result)
 		dev_dbg(&dev->core, "%s:%d: interrupt_status failed: %s\n",
 			__func__, __LINE__, ps3_result(result));
 
-	*status = tmp & dev->priv->interrupt_mask;
+	*status = tmp & priv->interrupt_mask;
 
 	dev_dbg(&dev->core, "%s:%d: m %lxh, s %lxh, m&s %lxh\n",
-		__func__, __LINE__, dev->priv->interrupt_mask, tmp, *status);
+		__func__, __LINE__, priv->interrupt_mask, tmp, *status);
 
 	return result;
 }
 
-int ps3_vuart_enable_interrupt_tx(struct ps3_vuart_port_device *dev)
+int ps3_vuart_enable_interrupt_tx(struct ps3_system_bus_device *dev)
 {
-	return (dev->priv->interrupt_mask & INTERRUPT_MASK_TX) ? 0
-		: ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+
+	return (priv->interrupt_mask & INTERRUPT_MASK_TX) ? 0
+		: ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
 		| INTERRUPT_MASK_TX);
 }
 
-int ps3_vuart_enable_interrupt_rx(struct ps3_vuart_port_device *dev)
+int ps3_vuart_enable_interrupt_rx(struct ps3_system_bus_device *dev)
 {
-	return (dev->priv->interrupt_mask & INTERRUPT_MASK_RX) ? 0
-		: ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+
+	return (priv->interrupt_mask & INTERRUPT_MASK_RX) ? 0
+		: ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
 		| INTERRUPT_MASK_RX);
 }
 
-int ps3_vuart_enable_interrupt_disconnect(struct ps3_vuart_port_device *dev)
+int ps3_vuart_enable_interrupt_disconnect(struct ps3_system_bus_device *dev)
 {
-	return (dev->priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT) ? 0
-		: ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+
+	return (priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT) ? 0
+		: ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
 		| INTERRUPT_MASK_DISCONNECT);
 }
 
-int ps3_vuart_disable_interrupt_tx(struct ps3_vuart_port_device *dev)
+int ps3_vuart_disable_interrupt_tx(struct ps3_system_bus_device *dev)
 {
-	return (dev->priv->interrupt_mask & INTERRUPT_MASK_TX)
-		? ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+
+	return (priv->interrupt_mask & INTERRUPT_MASK_TX)
+		? ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
 		& ~INTERRUPT_MASK_TX) : 0;
 }
 
-int ps3_vuart_disable_interrupt_rx(struct ps3_vuart_port_device *dev)
+int ps3_vuart_disable_interrupt_rx(struct ps3_system_bus_device *dev)
 {
-	return (dev->priv->interrupt_mask & INTERRUPT_MASK_RX)
-		? ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+
+	return (priv->interrupt_mask & INTERRUPT_MASK_RX)
+		? ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
 		& ~INTERRUPT_MASK_RX) : 0;
 }
 
-int ps3_vuart_disable_interrupt_disconnect(struct ps3_vuart_port_device *dev)
+int ps3_vuart_disable_interrupt_disconnect(struct ps3_system_bus_device *dev)
 {
-	return (dev->priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT)
-		? ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+
+	return (priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT)
+		? ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
 		& ~INTERRUPT_MASK_DISCONNECT) : 0;
 }
 
 /**
  * ps3_vuart_raw_write - Low level write helper.
+ * @dev: The struct ps3_system_bus_device instance.
  *
  * Do not call ps3_vuart_raw_write directly, use ps3_vuart_write.
  */
 
-static int ps3_vuart_raw_write(struct ps3_vuart_port_device *dev,
+static int ps3_vuart_raw_write(struct ps3_system_bus_device *dev,
 	const void* buf, unsigned int bytes, unsigned long *bytes_written)
 {
 	int result;
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
 
-	result = lv1_write_virtual_uart(dev->priv->port_number,
+	result = lv1_write_virtual_uart(dev->port_number,
 		ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_written);
 
 	if (result) {
@@ -340,28 +377,30 @@ static int ps3_vuart_raw_write(struct ps
 		return result;
 	}
 
-	dev->priv->stats.bytes_written += *bytes_written;
+	priv->stats.bytes_written += *bytes_written;
 
 	dev_dbg(&dev->core, "%s:%d: wrote %lxh/%xh=>%lxh\n", __func__, __LINE__,
-		*bytes_written, bytes, dev->priv->stats.bytes_written);
+		*bytes_written, bytes, priv->stats.bytes_written);
 
 	return result;
 }
 
 /**
  * ps3_vuart_raw_read - Low level read helper.
+ * @dev: The struct ps3_system_bus_device instance.
  *
  * Do not call ps3_vuart_raw_read directly, use ps3_vuart_read.
  */
 
-static int ps3_vuart_raw_read(struct ps3_vuart_port_device *dev, void* buf,
+static int ps3_vuart_raw_read(struct ps3_system_bus_device *dev, void *buf,
 	unsigned int bytes, unsigned long *bytes_read)
 {
 	int result;
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
 
 	dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, bytes);
 
-	result = lv1_read_virtual_uart(dev->priv->port_number,
+	result = lv1_read_virtual_uart(dev->port_number,
 		ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_read);
 
 	if (result) {
@@ -370,25 +409,27 @@ static int ps3_vuart_raw_read(struct ps3
 		return result;
 	}
 
-	dev->priv->stats.bytes_read += *bytes_read;
+	priv->stats.bytes_read += *bytes_read;
 
 	dev_dbg(&dev->core, "%s:%d: read %lxh/%xh=>%lxh\n", __func__, __LINE__,
-		*bytes_read, bytes, dev->priv->stats.bytes_read);
+		*bytes_read, bytes, priv->stats.bytes_read);
 
 	return result;
 }
 
 /**
  * ps3_vuart_clear_rx_bytes - Discard bytes received.
+ * @dev: The struct ps3_system_bus_device instance.
  * @bytes: Max byte count to discard, zero = all pending.
  *
  * Used to clear pending rx interrupt source.  Will not block.
  */
 
-void ps3_vuart_clear_rx_bytes(struct ps3_vuart_port_device *dev,
+void ps3_vuart_clear_rx_bytes(struct ps3_system_bus_device *dev,
 	unsigned int bytes)
 {
 	int result;
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
 	u64 bytes_waiting;
 	void* tmp;
 
@@ -418,8 +459,9 @@ void ps3_vuart_clear_rx_bytes(struct ps3
 
 	/* Don't include these bytes in the stats. */
 
-	dev->priv->stats.bytes_read -= bytes_waiting;
+	priv->stats.bytes_read -= bytes_waiting;
 }
+EXPORT_SYMBOL_GPL(ps3_vuart_clear_rx_bytes);
 
 /**
  * struct list_buffer - An element for a port device fifo buffer list.
@@ -435,6 +477,7 @@ struct list_buffer {
 
 /**
  * ps3_vuart_write - the entry point for writing data to a port
+ * @dev: The struct ps3_system_bus_device instance.
  *
  * If the port is idle on entry as much of the incoming data is written to
  * the port as the port will accept.  Otherwise a list buffer is created
@@ -442,25 +485,26 @@ struct list_buffer {
  * then enqueued for transmision via the transmit interrupt.
  */
 
-int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf,
+int ps3_vuart_write(struct ps3_system_bus_device *dev, const void *buf,
 	unsigned int bytes)
 {
 	static unsigned long dbg_number;
 	int result;
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
 	unsigned long flags;
 	struct list_buffer *lb;
 
 	dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__,
 		bytes, bytes);
 
-	spin_lock_irqsave(&dev->priv->tx_list.lock, flags);
+	spin_lock_irqsave(&priv->tx_list.lock, flags);
 
-	if (list_empty(&dev->priv->tx_list.head)) {
+	if (list_empty(&priv->tx_list.head)) {
 		unsigned long bytes_written;
 
 		result = ps3_vuart_raw_write(dev, buf, bytes, &bytes_written);
 
-		spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags);
+		spin_unlock_irqrestore(&priv->tx_list.lock, flags);
 
 		if (result) {
 			dev_dbg(&dev->core,
@@ -478,7 +522,7 @@ int ps3_vuart_write(struct ps3_vuart_por
 		bytes -= bytes_written;
 		buf += bytes_written;
 	} else
-		spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags);
+		spin_unlock_irqrestore(&priv->tx_list.lock, flags);
 
 	lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_KERNEL);
 
@@ -491,29 +535,86 @@ int ps3_vuart_write(struct ps3_vuart_por
 	lb->tail = lb->data + bytes;
 	lb->dbg_number = ++dbg_number;
 
-	spin_lock_irqsave(&dev->priv->tx_list.lock, flags);
-	list_add_tail(&lb->link, &dev->priv->tx_list.head);
+	spin_lock_irqsave(&priv->tx_list.lock, flags);
+	list_add_tail(&lb->link, &priv->tx_list.head);
 	ps3_vuart_enable_interrupt_tx(dev);
-	spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags);
+	spin_unlock_irqrestore(&priv->tx_list.lock, flags);
 
 	dev_dbg(&dev->core, "%s:%d: queued buf_%lu, %xh bytes\n",
 		__func__, __LINE__, lb->dbg_number, bytes);
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(ps3_vuart_write);
 
 /**
- * ps3_vuart_read - the entry point for reading data from a port
+ * ps3_vuart_queue_rx_bytes - Queue waiting bytes into the buffer list.
+ * @dev: The struct ps3_system_bus_device instance.
+ * @bytes_queued: Number of bytes queued to the buffer list.
  *
- * If enough bytes to satisfy the request are held in the buffer list those
- * bytes are dequeued and copied to the caller's buffer.  Emptied list buffers
- * are retiered.  If the request cannot be statified by bytes held in the list
- * buffers -EAGAIN is returned.
+ * Must be called with priv->rx_list.lock held.
  */
 
-int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf,
+static int ps3_vuart_queue_rx_bytes(struct ps3_system_bus_device *dev,
+	u64 *bytes_queued)
+{
+	static unsigned long dbg_number;
+	int result;
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+	struct list_buffer *lb;
+	u64 bytes;
+
+	*bytes_queued = 0;
+
+	result = ps3_vuart_get_rx_bytes_waiting(dev, &bytes);
+	BUG_ON(result);
+
+	if (result)
+		return -EIO;
+
+	if (!bytes)
+		return 0;
+
+	/* Add some extra space for recently arrived data. */
+
+	bytes += 128;
+
+	lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_ATOMIC);
+
+	if (!lb)
+		return -ENOMEM;
+
+	ps3_vuart_raw_read(dev, lb->data, bytes, &bytes);
+
+	lb->head = lb->data;
+	lb->tail = lb->data + bytes;
+	lb->dbg_number = ++dbg_number;
+
+	list_add_tail(&lb->link, &priv->rx_list.head);
+	priv->rx_list.bytes_held += bytes;
+
+	dev_dbg(&dev->core, "%s:%d: buf_%lu: queued %lxh bytes\n",
+		__func__, __LINE__, lb->dbg_number, bytes);
+
+	*bytes_queued = bytes;
+
+	return 0;
+}
+
+/**
+ * ps3_vuart_read - The entry point for reading data from a port.
+ *
+ * Queue data waiting at the port, and if enough bytes to satisfy the request
+ * are held in the buffer list those bytes are dequeued and copied to the
+ * caller's buffer.  Emptied list buffers are retiered.  If the request cannot
+ * be statified by bytes held in the list buffers -EAGAIN is returned.
+ */
+
+int ps3_vuart_read(struct ps3_system_bus_device *dev, void *buf,
 	unsigned int bytes)
 {
+	int result;
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
 	unsigned long flags;
 	struct list_buffer *lb, *n;
 	unsigned long bytes_read;
@@ -521,30 +622,37 @@ int ps3_vuart_read(struct ps3_vuart_port
 	dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__,
 		bytes, bytes);
 
-	spin_lock_irqsave(&dev->priv->rx_list.lock, flags);
+	spin_lock_irqsave(&priv->rx_list.lock, flags);
 
-	if (dev->priv->rx_list.bytes_held < bytes) {
-		spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags);
-		dev_dbg(&dev->core, "%s:%d: starved for %lxh bytes\n",
-			__func__, __LINE__,
-			bytes - dev->priv->rx_list.bytes_held);
-		return -EAGAIN;
+	/* Queue rx bytes here for polled reads. */
+
+	while (priv->rx_list.bytes_held < bytes) {
+		u64 tmp;
+
+		result = ps3_vuart_queue_rx_bytes(dev, &tmp);
+		if (result || !tmp) {
+			dev_dbg(&dev->core, "%s:%d: starved for %lxh bytes\n",
+				__func__, __LINE__,
+				bytes - priv->rx_list.bytes_held);
+			spin_unlock_irqrestore(&priv->rx_list.lock, flags);
+			return -EAGAIN;
+		}
 	}
 
-	list_for_each_entry_safe(lb, n, &dev->priv->rx_list.head, link) {
+	list_for_each_entry_safe(lb, n, &priv->rx_list.head, link) {
 		bytes_read = min((unsigned int)(lb->tail - lb->head), bytes);
 
 		memcpy(buf, lb->head, bytes_read);
 		buf += bytes_read;
 		bytes -= bytes_read;
-		dev->priv->rx_list.bytes_held -= bytes_read;
+		priv->rx_list.bytes_held -= bytes_read;
 
 		if (bytes_read < lb->tail - lb->head) {
 			lb->head += bytes_read;
 			dev_dbg(&dev->core, "%s:%d: buf_%lu: dequeued %lxh "
 				"bytes\n", __func__, __LINE__, lb->dbg_number,
 				bytes_read);
-			spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags);
+			spin_unlock_irqrestore(&priv->rx_list.lock, flags);
 			return 0;
 		}
 
@@ -556,16 +664,32 @@ int ps3_vuart_read(struct ps3_vuart_port
 		kfree(lb);
 	}
 
-	spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags);
+	spin_unlock_irqrestore(&priv->rx_list.lock, flags);
 	return 0;
 }
+EXPORT_SYMBOL_GPL(ps3_vuart_read);
 
-int ps3_vuart_read_async(struct ps3_vuart_port_device *dev, work_func_t func,
-	unsigned int bytes)
+/**
+ * ps3_vuart_work - Asynchronous read handler.
+ */
+
+static void ps3_vuart_work(struct work_struct *work)
+{
+	struct ps3_system_bus_device *dev =
+		ps3_vuart_work_to_system_bus_dev(work);
+	struct ps3_vuart_port_driver *drv =
+		ps3_system_bus_dev_to_vuart_drv(dev);
+
+	BUG_ON(!drv);
+	drv->work(dev);
+}
+
+int ps3_vuart_read_async(struct ps3_system_bus_device *dev, unsigned int bytes)
 {
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
 	unsigned long flags;
 
-	if(dev->priv->work.trigger) {
+	if (priv->rx_list.work.trigger) {
 		dev_dbg(&dev->core, "%s:%d: warning, multiple calls\n",
 			__func__, __LINE__);
 		return -EAGAIN;
@@ -573,30 +697,32 @@ int ps3_vuart_read_async(struct ps3_vuar
 
 	BUG_ON(!bytes);
 
-	PREPARE_WORK(&dev->priv->work.work, func);
+	PREPARE_WORK(&priv->rx_list.work.work, ps3_vuart_work);
 
-	spin_lock_irqsave(&dev->priv->work.lock, flags);
-	if(dev->priv->rx_list.bytes_held >= bytes) {
+	spin_lock_irqsave(&priv->rx_list.lock, flags);
+	if (priv->rx_list.bytes_held >= bytes) {
 		dev_dbg(&dev->core, "%s:%d: schedule_work %xh bytes\n",
 			__func__, __LINE__, bytes);
-		schedule_work(&dev->priv->work.work);
-		spin_unlock_irqrestore(&dev->priv->work.lock, flags);
+		schedule_work(&priv->rx_list.work.work);
+		spin_unlock_irqrestore(&priv->rx_list.lock, flags);
 		return 0;
 	}
 
-	dev->priv->work.trigger = bytes;
-	spin_unlock_irqrestore(&dev->priv->work.lock, flags);
+	priv->rx_list.work.trigger = bytes;
+	spin_unlock_irqrestore(&priv->rx_list.lock, flags);
 
 	dev_dbg(&dev->core, "%s:%d: waiting for %u(%xh) bytes\n", __func__,
 		__LINE__, bytes, bytes);
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(ps3_vuart_read_async);
 
-void ps3_vuart_cancel_async(struct ps3_vuart_port_device *dev)
+void ps3_vuart_cancel_async(struct ps3_system_bus_device *dev)
 {
-	dev->priv->work.trigger = 0;
+	to_port_priv(dev)->rx_list.work.trigger = 0;
 }
+EXPORT_SYMBOL_GPL(ps3_vuart_cancel_async);
 
 /**
  * ps3_vuart_handle_interrupt_tx - third stage transmit interrupt handler
@@ -606,18 +732,19 @@ void ps3_vuart_cancel_async(struct ps3_v
  * adjusts the final list buffer state for a partial write.
  */
 
-static int ps3_vuart_handle_interrupt_tx(struct ps3_vuart_port_device *dev)
+static int ps3_vuart_handle_interrupt_tx(struct ps3_system_bus_device *dev)
 {
 	int result = 0;
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
 	unsigned long flags;
 	struct list_buffer *lb, *n;
 	unsigned long bytes_total = 0;
 
 	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
 
-	spin_lock_irqsave(&dev->priv->tx_list.lock, flags);
+	spin_lock_irqsave(&priv->tx_list.lock, flags);
 
-	list_for_each_entry_safe(lb, n, &dev->priv->tx_list.head, link) {
+	list_for_each_entry_safe(lb, n, &priv->tx_list.head, link) {
 
 		unsigned long bytes_written;
 
@@ -651,7 +778,7 @@ static int ps3_vuart_handle_interrupt_tx
 
 	ps3_vuart_disable_interrupt_tx(dev);
 port_full:
-	spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags);
+	spin_unlock_irqrestore(&priv->tx_list.lock, flags);
 	dev_dbg(&dev->core, "%s:%d wrote %lxh bytes total\n",
 		__func__, __LINE__, bytes_total);
 	return result;
@@ -665,60 +792,37 @@ port_full:
  * buffer list.  Buffer list data is dequeued via ps3_vuart_read.
  */
 
-static int ps3_vuart_handle_interrupt_rx(struct ps3_vuart_port_device *dev)
+static int ps3_vuart_handle_interrupt_rx(struct ps3_system_bus_device *dev)
 {
-	static unsigned long dbg_number;
-	int result = 0;
+	int result;
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
 	unsigned long flags;
-	struct list_buffer *lb;
-	unsigned long bytes;
+	u64 bytes;
 
 	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
 
-	result = ps3_vuart_get_rx_bytes_waiting(dev, &bytes);
-
-	if (result)
-		return -EIO;
-
-	BUG_ON(!bytes);
-
-	/* Add some extra space for recently arrived data. */
-
-	bytes += 128;
-
-	lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_ATOMIC);
+	spin_lock_irqsave(&priv->rx_list.lock, flags);
+	result = ps3_vuart_queue_rx_bytes(dev, &bytes);
 
-	if (!lb)
-		return -ENOMEM;
-
-	ps3_vuart_raw_read(dev, lb->data, bytes, &bytes);
-
-	lb->head = lb->data;
-	lb->tail = lb->data + bytes;
-	lb->dbg_number = ++dbg_number;
-
-	spin_lock_irqsave(&dev->priv->rx_list.lock, flags);
-	list_add_tail(&lb->link, &dev->priv->rx_list.head);
-	dev->priv->rx_list.bytes_held += bytes;
-	spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags);
-
-	dev_dbg(&dev->core, "%s:%d: buf_%lu: queued %lxh bytes\n",
-		__func__, __LINE__, lb->dbg_number, bytes);
+	if (result) {
+		spin_unlock_irqrestore(&priv->rx_list.lock, flags);
+		return result;
+	}
 
-	spin_lock_irqsave(&dev->priv->work.lock, flags);
-	if(dev->priv->work.trigger
-		&& dev->priv->rx_list.bytes_held >= dev->priv->work.trigger) {
+	if (priv->rx_list.work.trigger && priv->rx_list.bytes_held
+		>= priv->rx_list.work.trigger) {
 		dev_dbg(&dev->core, "%s:%d: schedule_work %lxh bytes\n",
-			__func__, __LINE__, dev->priv->work.trigger);
-		dev->priv->work.trigger = 0;
-		schedule_work(&dev->priv->work.work);
+			__func__, __LINE__, priv->rx_list.work.trigger);
+		priv->rx_list.work.trigger = 0;
+		schedule_work(&priv->rx_list.work.work);
 	}
-	spin_unlock_irqrestore(&dev->priv->work.lock, flags);
-	return 0;
+
+	spin_unlock_irqrestore(&priv->rx_list.lock, flags);
+	return result;
 }
 
 static int ps3_vuart_handle_interrupt_disconnect(
-	struct ps3_vuart_port_device *dev)
+	struct ps3_system_bus_device *dev)
 {
 	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
 	BUG_ON("no support");
@@ -733,9 +837,10 @@ static int ps3_vuart_handle_interrupt_di
  * stage handler after one iteration.
  */
 
-static int ps3_vuart_handle_port_interrupt(struct ps3_vuart_port_device *dev)
+static int ps3_vuart_handle_port_interrupt(struct ps3_system_bus_device *dev)
 {
 	int result;
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
 	unsigned long status;
 
 	result = ps3_vuart_get_interrupt_status(dev, &status);
@@ -747,21 +852,21 @@ static int ps3_vuart_handle_port_interru
 		status);
 
 	if (status & INTERRUPT_MASK_DISCONNECT) {
-		dev->priv->stats.disconnect_interrupts++;
+		priv->stats.disconnect_interrupts++;
 		result = ps3_vuart_handle_interrupt_disconnect(dev);
 		if (result)
 			ps3_vuart_disable_interrupt_disconnect(dev);
 	}
 
 	if (status & INTERRUPT_MASK_TX) {
-		dev->priv->stats.tx_interrupts++;
+		priv->stats.tx_interrupts++;
 		result = ps3_vuart_handle_interrupt_tx(dev);
 		if (result)
 			ps3_vuart_disable_interrupt_tx(dev);
 	}
 
 	if (status & INTERRUPT_MASK_RX) {
-		dev->priv->stats.rx_interrupts++;
+		priv->stats.rx_interrupts++;
 		result = ps3_vuart_handle_interrupt_rx(dev);
 		if (result)
 			ps3_vuart_disable_interrupt_rx(dev);
@@ -771,11 +876,11 @@ static int ps3_vuart_handle_port_interru
 }
 
 struct vuart_bus_priv {
-	const struct ports_bmp bmp;
+	struct ports_bmp *bmp;
 	unsigned int virq;
 	struct semaphore probe_mutex;
 	int use_count;
-	struct ps3_vuart_port_device *devices[PORT_COUNT];
+	struct ps3_system_bus_device *devices[PORT_COUNT];
 } static vuart_bus_priv;
 
 /**
@@ -788,17 +893,16 @@ struct vuart_bus_priv {
 
 static irqreturn_t ps3_vuart_irq_handler(int irq, void *_private)
 {
-	struct vuart_bus_priv *bus_priv;
+	struct vuart_bus_priv *bus_priv = _private;
 
-	BUG_ON(!_private);
-	bus_priv = (struct vuart_bus_priv *)_private;
+	BUG_ON(!bus_priv);
 
 	while (1) {
 		unsigned int port;
 
-		dump_ports_bmp(&bus_priv->bmp);
+		dump_ports_bmp(bus_priv->bmp);
 
-		port = (BITS_PER_LONG - 1) - __ilog2(bus_priv->bmp.status);
+		port = (BITS_PER_LONG - 1) - __ilog2(bus_priv->bmp->status);
 
 		if (port == BITS_PER_LONG)
 			break;
@@ -812,100 +916,144 @@ static irqreturn_t ps3_vuart_irq_handler
 	return IRQ_HANDLED;
 }
 
-static int ps3_vuart_match(struct device *_dev, struct device_driver *_drv)
+static int ps3_vuart_bus_interrupt_get(void)
 {
 	int result;
-	struct ps3_vuart_port_driver *drv = to_ps3_vuart_port_driver(_drv);
-	struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
 
-	result = dev->match_id == drv->match_id;
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+	vuart_bus_priv.use_count++;
+
+	BUG_ON(vuart_bus_priv.use_count > 2);
+
+	if (vuart_bus_priv.use_count != 1) {
+		return 0;
+	}
+
+	BUG_ON(vuart_bus_priv.bmp);
+
+	vuart_bus_priv.bmp = kzalloc(sizeof(struct ports_bmp), GFP_KERNEL);
 
-	dev_info(&dev->core, "%s:%d: dev=%u(%s), drv=%u(%s): %s\n", __func__,
-		__LINE__, dev->match_id, dev->core.bus_id, drv->match_id,
-		drv->core.name, (result ? "match" : "miss"));
+	if (!vuart_bus_priv.bmp) {
+		pr_debug("%s:%d: kzalloc failed.\n", __func__, __LINE__);
+		result = -ENOMEM;
+		goto fail_bmp_malloc;
+	}
+
+	result = ps3_vuart_irq_setup(PS3_BINDING_CPU_ANY, vuart_bus_priv.bmp,
+		&vuart_bus_priv.virq);
+
+	if (result) {
+		pr_debug("%s:%d: ps3_vuart_irq_setup failed (%d)\n",
+			__func__, __LINE__, result);
+		result = -EPERM;
+		goto fail_alloc_irq;
+	}
 
+	result = request_irq(vuart_bus_priv.virq, ps3_vuart_irq_handler,
+		IRQF_DISABLED, "vuart", &vuart_bus_priv);
+
+	if (result) {
+		pr_debug("%s:%d: request_irq failed (%d)\n",
+			__func__, __LINE__, result);
+		goto fail_request_irq;
+	}
+
+	pr_debug(" <- %s:%d: ok\n", __func__, __LINE__);
 	return result;
+
+fail_request_irq:
+	ps3_vuart_irq_destroy(vuart_bus_priv.virq);
+	vuart_bus_priv.virq = NO_IRQ;
+fail_alloc_irq:
+	kfree(vuart_bus_priv.bmp);
+	vuart_bus_priv.bmp = NULL;
+fail_bmp_malloc:
+	vuart_bus_priv.use_count--;
+	pr_debug(" <- %s:%d: failed\n", __func__, __LINE__);
+	return result;
+}
+
+static int ps3_vuart_bus_interrupt_put(void)
+{
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+	vuart_bus_priv.use_count--;
+
+	BUG_ON(vuart_bus_priv.use_count < 0);
+
+	if (vuart_bus_priv.use_count != 0)
+		return 0;
+
+	free_irq(vuart_bus_priv.virq, &vuart_bus_priv);
+
+	ps3_vuart_irq_destroy(vuart_bus_priv.virq);
+	vuart_bus_priv.virq = NO_IRQ;
+
+	kfree(vuart_bus_priv.bmp);
+	vuart_bus_priv.bmp = NULL;
+
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	return 0;
 }
 
-static int ps3_vuart_probe(struct device *_dev)
+static int ps3_vuart_probe(struct ps3_system_bus_device *dev)
 {
 	int result;
-	unsigned int port_number;
-	struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
-	struct ps3_vuart_port_driver *drv =
-		to_ps3_vuart_port_driver(_dev->driver);
+	struct ps3_vuart_port_driver *drv;
+	struct ps3_vuart_port_priv *priv = NULL;
 
 	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
 
+	drv = ps3_system_bus_dev_to_vuart_drv(dev);
+
+	dev_dbg(&dev->core, "%s:%d: (%s)\n", __func__, __LINE__,
+		drv->core.core.name);
+
 	BUG_ON(!drv);
 
-	down(&vuart_bus_priv.probe_mutex);
+	if (dev->port_number >= PORT_COUNT) {
+		BUG();
+		return -EINVAL;
+	}
 
-	/* Setup vuart_bus_priv.devices[]. */
+	down(&vuart_bus_priv.probe_mutex);
 
-	result = ps3_vuart_match_id_to_port(dev->match_id,
-		&port_number);
+	result = ps3_vuart_bus_interrupt_get();
 
-	if (result) {
-		dev_dbg(&dev->core, "%s:%d: unknown match_id (%d)\n",
-			__func__, __LINE__, dev->match_id);
-		result = -EINVAL;
-		goto fail_match;
-	}
+	if (result)
+		goto fail_setup_interrupt;
 
-	if (vuart_bus_priv.devices[port_number]) {
+	if (vuart_bus_priv.devices[dev->port_number]) {
 		dev_dbg(&dev->core, "%s:%d: port busy (%d)\n", __func__,
-			__LINE__, port_number);
+			__LINE__, dev->port_number);
 		result = -EBUSY;
-		goto fail_match;
+		goto fail_busy;
 	}
 
-	vuart_bus_priv.devices[port_number] = dev;
+	vuart_bus_priv.devices[dev->port_number] = dev;
 
-	/* Setup dev->priv. */
+	/* Setup dev->driver_priv. */
 
-	dev->priv = kzalloc(sizeof(struct ps3_vuart_port_priv), GFP_KERNEL);
+	dev->driver_priv = kzalloc(sizeof(struct ps3_vuart_port_priv),
+		GFP_KERNEL);
 
-	if (!dev->priv) {
+	if (!dev->driver_priv) {
 		result = -ENOMEM;
-		goto fail_alloc;
+		goto fail_dev_malloc;
 	}
 
-	dev->priv->port_number = port_number;
-
-	INIT_LIST_HEAD(&dev->priv->tx_list.head);
-	spin_lock_init(&dev->priv->tx_list.lock);
+	priv = to_port_priv(dev);
 
-	INIT_LIST_HEAD(&dev->priv->rx_list.head);
-	spin_lock_init(&dev->priv->rx_list.lock);
+	INIT_LIST_HEAD(&priv->tx_list.head);
+	spin_lock_init(&priv->tx_list.lock);
 
-	INIT_WORK(&dev->priv->work.work, NULL);
-	spin_lock_init(&dev->priv->work.lock);
-	dev->priv->work.trigger = 0;
-	dev->priv->work.dev = dev;
+	INIT_LIST_HEAD(&priv->rx_list.head);
+	spin_lock_init(&priv->rx_list.lock);
 
-	if (++vuart_bus_priv.use_count == 1) {
-
-		result = ps3_vuart_irq_setup(PS3_BINDING_CPU_ANY,
-			(void*)&vuart_bus_priv.bmp.status, &vuart_bus_priv.virq);
-
-		if (result) {
-			dev_dbg(&dev->core,
-				"%s:%d: ps3_vuart_irq_setup failed (%d)\n",
-				__func__, __LINE__, result);
-			result = -EPERM;
-			goto fail_alloc_irq;
-		}
-
-		result = request_irq(vuart_bus_priv.virq, ps3_vuart_irq_handler,
-			IRQF_DISABLED, "vuart", &vuart_bus_priv);
-
-		if (result) {
-			dev_info(&dev->core, "%s:%d: request_irq failed (%d)\n",
-				__func__, __LINE__, result);
-			goto fail_request_irq;
-		}
-	}
+	INIT_WORK(&priv->rx_list.work.work, NULL);
+	priv->rx_list.work.trigger = 0;
+	priv->rx_list.work.dev = dev;
 
 	/* clear stale pending interrupts */
 
@@ -936,150 +1084,158 @@ static int ps3_vuart_probe(struct device
 
 fail_probe:
 	ps3_vuart_set_interrupt_mask(dev, 0);
-fail_request_irq:
-	ps3_vuart_irq_destroy(vuart_bus_priv.virq);
-	vuart_bus_priv.virq = NO_IRQ;
-fail_alloc_irq:
-	--vuart_bus_priv.use_count;
-	kfree(dev->priv);
-	dev->priv = NULL;
-fail_alloc:
-	vuart_bus_priv.devices[port_number] = NULL;
-fail_match:
+	kfree(dev->driver_priv);
+	dev->driver_priv = NULL;
+fail_dev_malloc:
+	vuart_bus_priv.devices[dev->port_number] = NULL;
+fail_busy:
+	ps3_vuart_bus_interrupt_put();
+fail_setup_interrupt:
 	up(&vuart_bus_priv.probe_mutex);
-	dev_dbg(&dev->core, "%s:%d failed\n", __func__, __LINE__);
+	dev_dbg(&dev->core, "%s:%d: failed\n", __func__, __LINE__);
 	return result;
 }
 
-static int ps3_vuart_remove(struct device *_dev)
+/**
+ * ps3_vuart_cleanup - common cleanup helper.
+ * @dev: The struct ps3_system_bus_device instance.
+ *
+ * Cleans interrupts and HV resources.  Must be called with
+ * vuart_bus_priv.probe_mutex held.  Used by ps3_vuart_remove and
+ * ps3_vuart_shutdown.  After this call, polled reading will still work.
+ */
+
+static int ps3_vuart_cleanup(struct ps3_system_bus_device *dev)
 {
-	struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
-	struct ps3_vuart_port_driver *drv =
-		to_ps3_vuart_port_driver(_dev->driver);
+	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+
+	ps3_vuart_cancel_async(dev);
+	ps3_vuart_set_interrupt_mask(dev, 0);
+	ps3_vuart_bus_interrupt_put();
+	return 0;
+}
+
+/**
+ * ps3_vuart_remove - Completely clean the device instance.
+ * @dev: The struct ps3_system_bus_device instance.
+ *
+ * Cleans all memory, interrupts and HV resources.  After this call the
+ * device can no longer be used.
+ */
+
+static int ps3_vuart_remove(struct ps3_system_bus_device *dev)
+{
+	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+	struct ps3_vuart_port_driver *drv;
+
+	BUG_ON(!dev);
 
 	down(&vuart_bus_priv.probe_mutex);
 
-	dev_dbg(&dev->core, "%s:%d: %s\n", __func__, __LINE__,
-		dev->core.bus_id);
+	dev_dbg(&dev->core, " -> %s:%d: match_id %d\n", __func__, __LINE__,
+		dev->match_id);
 
-	BUG_ON(vuart_bus_priv.use_count < 1);
+	if (!dev->core.driver) {
+		dev_dbg(&dev->core, "%s:%d: no driver bound\n", __func__,
+			__LINE__);
+		up(&vuart_bus_priv.probe_mutex);
+		return 0;
+	}
 
-	if (drv->remove)
-		drv->remove(dev);
-	else
-		dev_dbg(&dev->core, "%s:%d: %s no remove method\n", __func__,
-			__LINE__, dev->core.bus_id);
+	drv = ps3_system_bus_dev_to_vuart_drv(dev);
 
-	vuart_bus_priv.devices[dev->priv->port_number] = NULL;
+	BUG_ON(!drv);
 
-	if (--vuart_bus_priv.use_count == 0) {
+	if (drv->remove) {
+		drv->remove(dev);
+	} else {
+		dev_dbg(&dev->core, "%s:%d: no remove method\n", __func__,
+		__LINE__);
 		BUG();
-		free_irq(vuart_bus_priv.virq, &vuart_bus_priv);
-		ps3_vuart_irq_destroy(vuart_bus_priv.virq);
-		vuart_bus_priv.virq = NO_IRQ;
 	}
 
-	kfree(dev->priv);
-	dev->priv = NULL;
+	ps3_vuart_cleanup(dev);
+
+	vuart_bus_priv.devices[dev->port_number] = NULL;
+	kfree(priv);
+	priv = NULL;
 
+	dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
 	up(&vuart_bus_priv.probe_mutex);
 	return 0;
 }
 
-static void ps3_vuart_shutdown(struct device *_dev)
-{
-	struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
-	struct ps3_vuart_port_driver *drv =
-		to_ps3_vuart_port_driver(_dev->driver);
-
-	dev_dbg(&dev->core, "%s:%d: %s\n", __func__, __LINE__,
-		dev->core.bus_id);
-
-	if (drv->shutdown)
-		drv->shutdown(dev);
-	else
-		dev_dbg(&dev->core, "%s:%d: %s no shutdown method\n", __func__,
-			__LINE__, dev->core.bus_id);
-}
-
 /**
- * ps3_vuart_bus - The vuart bus instance.
+ * ps3_vuart_shutdown - Cleans interrupts and HV resources.
+ * @dev: The struct ps3_system_bus_device instance.
  *
- * The vuart is managed as a bus that port devices connect to.
+ * Cleans interrupts and HV resources.  After this call the
+ * device can still be used in polling mode.  This behavior required
+ * by sys-manager to be able to complete the device power operation
+ * sequence.
  */
 
-struct bus_type ps3_vuart_bus = {
-        .name = "ps3_vuart",
-	.match = ps3_vuart_match,
-	.probe = ps3_vuart_probe,
-	.remove = ps3_vuart_remove,
-	.shutdown = ps3_vuart_shutdown,
-};
-
-int __init ps3_vuart_bus_init(void)
+static int ps3_vuart_shutdown(struct ps3_system_bus_device *dev)
 {
-	int result;
+	struct ps3_vuart_port_driver *drv;
 
-	pr_debug("%s:%d:\n", __func__, __LINE__);
+	BUG_ON(!dev);
 
-	if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
-		return -ENODEV;
+	down(&vuart_bus_priv.probe_mutex);
 
-	init_MUTEX(&vuart_bus_priv.probe_mutex);
-	result = bus_register(&ps3_vuart_bus);
-	BUG_ON(result);
+	dev_dbg(&dev->core, " -> %s:%d: match_id %d\n", __func__, __LINE__,
+		dev->match_id);
 
-	return result;
-}
+	if (!dev->core.driver) {
+		dev_dbg(&dev->core, "%s:%d: no driver bound\n", __func__,
+			__LINE__);
+		up(&vuart_bus_priv.probe_mutex);
+		return 0;
+	}
 
-void __exit ps3_vuart_bus_exit(void)
-{
-	pr_debug("%s:%d:\n", __func__, __LINE__);
-	bus_unregister(&ps3_vuart_bus);
-}
+	drv = ps3_system_bus_dev_to_vuart_drv(dev);
 
-core_initcall(ps3_vuart_bus_init);
-module_exit(ps3_vuart_bus_exit);
+	BUG_ON(!drv);
 
-/**
- * ps3_vuart_port_release_device - Remove a vuart port device.
- */
+	if (drv->shutdown)
+		drv->shutdown(dev);
+	else if (drv->remove) {
+		dev_dbg(&dev->core, "%s:%d: no shutdown, calling remove\n",
+			__func__, __LINE__);
+		drv->remove(dev);
+	} else {
+		dev_dbg(&dev->core, "%s:%d: no shutdown method\n", __func__,
+			__LINE__);
+		BUG();
+	}
 
-static void ps3_vuart_port_release_device(struct device *_dev)
-{
-#if defined(DEBUG)
-	struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
+	ps3_vuart_cleanup(dev);
 
-	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+	dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
 
-	BUG_ON(dev->priv && "forgot to free");
-	memset(&dev->core, 0, sizeof(dev->core));
-#endif
+	up(&vuart_bus_priv.probe_mutex);
+	return 0;
 }
 
-/**
- * ps3_vuart_port_device_register - Add a vuart port device.
- */
-
-int ps3_vuart_port_device_register(struct ps3_vuart_port_device *dev)
+static int __init ps3_vuart_bus_init(void)
 {
-	static unsigned int dev_count = 1;
-
-	BUG_ON(dev->priv && "forgot to free");
+	pr_debug("%s:%d:\n", __func__, __LINE__);
 
-	dev->core.parent = NULL;
-	dev->core.bus = &ps3_vuart_bus;
-	dev->core.release = ps3_vuart_port_release_device;
+	if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
+		return -ENODEV;
 
-	snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), "vuart_%02x",
-		dev_count++);
+	init_MUTEX(&vuart_bus_priv.probe_mutex);
 
-	dev_dbg(&dev->core, "%s:%d register\n", __func__, __LINE__);
+	return 0;
+}
 
-	return device_register(&dev->core);
+static void __exit ps3_vuart_bus_exit(void)
+{
+	pr_debug("%s:%d:\n", __func__, __LINE__);
 }
 
-EXPORT_SYMBOL_GPL(ps3_vuart_port_device_register);
+core_initcall(ps3_vuart_bus_init);
+module_exit(ps3_vuart_bus_exit);
 
 /**
  * ps3_vuart_port_driver_register - Add a vuart port device driver.
@@ -1089,12 +1245,18 @@ int ps3_vuart_port_driver_register(struc
 {
 	int result;
 
-	pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.name);
-	drv->core.bus = &ps3_vuart_bus;
-	result = driver_register(&drv->core);
+	pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.core.name);
+
+	BUG_ON(!drv->core.match_id);
+	BUG_ON(!drv->core.core.name);
+
+	drv->core.probe = ps3_vuart_probe;
+	drv->core.remove = ps3_vuart_remove;
+	drv->core.shutdown = ps3_vuart_shutdown;
+
+	result = ps3_system_bus_driver_register(&drv->core);
 	return result;
 }
-
 EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_register);
 
 /**
@@ -1103,8 +1265,7 @@ EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_
 
 void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv)
 {
-	pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.name);
-	driver_unregister(&drv->core);
+	pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.core.name);
+	ps3_system_bus_driver_unregister(&drv->core);
 }
-
 EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_unregister);
--- a/drivers/ps3/vuart.h
+++ b/drivers/ps3/vuart.h
@@ -34,29 +34,7 @@ struct ps3_vuart_stats {
 struct ps3_vuart_work {
 	struct work_struct work;
 	unsigned long trigger;
-	spinlock_t lock;
-	struct ps3_vuart_port_device* dev; /* to convert work to device */
-};
-
-/**
- * struct ps3_vuart_port_priv - private vuart device data.
- */
-
-struct ps3_vuart_port_priv {
-	unsigned int port_number;
-	u64 interrupt_mask;
-
-	struct {
-		spinlock_t lock;
-		struct list_head head;
-	} tx_list;
-	struct {
-		unsigned long bytes_held;
-		spinlock_t lock;
-		struct list_head head;
-	} rx_list;
-	struct ps3_vuart_stats stats;
-	struct ps3_vuart_work work;
+	struct ps3_system_bus_device *dev; /* to convert work to device */
 };
 
 /**
@@ -64,32 +42,30 @@ struct ps3_vuart_port_priv {
  */
 
 struct ps3_vuart_port_driver {
-	enum ps3_match_id match_id;
-	struct device_driver core;
-	int (*probe)(struct ps3_vuart_port_device *);
-	int (*remove)(struct ps3_vuart_port_device *);
-	void (*shutdown)(struct ps3_vuart_port_device *);
-	int (*tx_event)(struct ps3_vuart_port_device *dev);
-	int (*rx_event)(struct ps3_vuart_port_device *dev);
-	int (*disconnect_event)(struct ps3_vuart_port_device *dev);
-	/* int (*suspend)(struct ps3_vuart_port_device *, pm_message_t); */
-	/* int (*resume)(struct ps3_vuart_port_device *); */
+	struct ps3_system_bus_driver core;
+	int (*probe)(struct ps3_system_bus_device *);
+	int (*remove)(struct ps3_system_bus_device *);
+	void (*shutdown)(struct ps3_system_bus_device *);
+	void (*work)(struct ps3_system_bus_device *);
+	/* int (*tx_event)(struct ps3_system_bus_device *dev); */
+	/* int (*rx_event)(struct ps3_system_bus_device *dev); */
+	/* int (*disconnect_event)(struct ps3_system_bus_device *dev); */
+	/* int (*suspend)(struct ps3_system_bus_device *, pm_message_t); */
+	/* int (*resume)(struct ps3_system_bus_device *); */
 };
 
 int ps3_vuart_port_driver_register(struct ps3_vuart_port_driver *drv);
 void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv);
 
-static inline struct ps3_vuart_port_driver *to_ps3_vuart_port_driver(
-	struct device_driver *_drv)
-{
-	return container_of(_drv, struct ps3_vuart_port_driver, core);
-}
-static inline struct ps3_vuart_port_device *to_ps3_vuart_port_device(
-	struct device *_dev)
+static inline struct ps3_vuart_port_driver *
+	ps3_system_bus_dev_to_vuart_drv(struct ps3_system_bus_device *_dev)
 {
-	return container_of(_dev, struct ps3_vuart_port_device, core);
+	struct ps3_system_bus_driver *sbd =
+		ps3_system_bus_dev_to_system_bus_drv(_dev);
+	BUG_ON(!sbd);
+	return container_of(sbd, struct ps3_vuart_port_driver, core);
 }
-static inline struct ps3_vuart_port_device *ps3_vuart_work_to_port_device(
+static inline struct ps3_system_bus_device *ps3_vuart_work_to_system_bus_dev(
 	struct work_struct *_work)
 {
 	struct ps3_vuart_work *vw = container_of(_work, struct ps3_vuart_work,
@@ -97,14 +73,13 @@ static inline struct ps3_vuart_port_devi
 	return vw->dev;
 }
 
-int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf,
-	unsigned int bytes);
-int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf,
+int ps3_vuart_write(struct ps3_system_bus_device *dev, const void *buf,
 	unsigned int bytes);
-int ps3_vuart_read_async(struct ps3_vuart_port_device *dev, work_func_t func,
+int ps3_vuart_read(struct ps3_system_bus_device *dev, void *buf,
 	unsigned int bytes);
-void ps3_vuart_cancel_async(struct ps3_vuart_port_device *dev);
-void ps3_vuart_clear_rx_bytes(struct ps3_vuart_port_device *dev,
+int ps3_vuart_read_async(struct ps3_system_bus_device *dev, unsigned int bytes);
+void ps3_vuart_cancel_async(struct ps3_system_bus_device *dev);
+void ps3_vuart_clear_rx_bytes(struct ps3_system_bus_device *dev,
 	unsigned int bytes);
 
 #endif
--- a/include/asm-powerpc/ps3.h
+++ b/include/asm-powerpc/ps3.h
@@ -407,23 +407,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

-- 

^ permalink raw reply

* [patch 14/33] PS3: Repository probe cleanups
From: Geoff Levand @ 2007-06-15 21:55 UTC (permalink / raw)
  To: paulus; +Cc: Geert Uytterhoeven, linuxppc-dev
In-Reply-To: <20070615204749.629571012@am.sony.com>

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.

Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
 arch/powerpc/platforms/ps3/platform.h   |   31 +
 arch/powerpc/platforms/ps3/repository.c |  592 +++++++++++++++++---------------
 2 files changed, 340 insertions(+), 283 deletions(-)

--- a/arch/powerpc/platforms/ps3/platform.h
+++ b/arch/powerpc/platforms/ps3/platform.h
@@ -131,24 +131,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 */
@@ -218,6 +222,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 */
--- a/arch/powerpc/platforms/ps3/repository.c
+++ b/arch/powerpc/platforms/ps3/repository.c
@@ -138,7 +138,7 @@ static int read_node(unsigned int lpar_i
 		pr_debug("%s:%d: lv1_get_repository_node_value failed: %s\n",
 			__func__, __LINE__, ps3_result(result));
 		dump_node_name(lpar_id, n1, n2, n3, n4);
-		return result;
+		return -ENOENT;
 	}
 
 	dump_node(lpar_id, n1, n2, n3, n4, v1, v2);
@@ -155,7 +155,7 @@ static int read_node(unsigned int lpar_i
 		pr_debug("%s:%d: warning: discarding non-zero v2: %016lx\n",
 			__func__, __LINE__, v2);
 
-	return result;
+	return 0;
 }
 
 int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str,
@@ -314,324 +314,140 @@ int ps3_repository_read_dev_reg(unsigned
 		reg_index, bus_addr, len);
 }
 
-#if defined(DEBUG)
-int ps3_repository_dump_resource_info(unsigned int bus_index,
-	unsigned int dev_index)
-{
-	int result = 0;
-	unsigned int res_index;
 
-	pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__,
-		bus_index, dev_index);
 
-	for (res_index = 0; res_index < 10; res_index++) {
-		enum ps3_interrupt_type intr_type;
-		unsigned int interrupt_id;
+int ps3_repository_find_device(struct ps3_repository_device *repo)
+{
+	int result;
+	struct ps3_repository_device tmp = *repo;
+	unsigned int num_dev;
 
-		result = ps3_repository_read_dev_intr(bus_index, dev_index,
-			res_index, &intr_type, &interrupt_id);
+	BUG_ON(repo->bus_index > 10);
+	BUG_ON(repo->dev_index > 10);
 
-		if (result) {
-			if (result !=  LV1_NO_ENTRY)
-				pr_debug("%s:%d ps3_repository_read_dev_intr"
-					" (%u:%u) failed\n", __func__, __LINE__,
-					bus_index, dev_index);
-			break;
-		}
+	result = ps3_repository_read_bus_num_dev(tmp.bus_index, &num_dev);
 
-		pr_debug("%s:%d (%u:%u) intr_type %u, interrupt_id %u\n",
-			__func__, __LINE__, bus_index, dev_index, intr_type,
-			interrupt_id);
+	if (result) {
+		pr_debug("%s:%d read_bus_num_dev failed\n", __func__, __LINE__);
+		return result;
 	}
 
-	for (res_index = 0; res_index < 10; res_index++) {
-		enum ps3_reg_type reg_type;
-		u64 bus_addr;
-		u64 len;
-
-		result = ps3_repository_read_dev_reg(bus_index, dev_index,
-			res_index, &reg_type, &bus_addr, &len);
+	pr_debug("%s:%d: bus_type %u, bus_index %u, bus_id %u, num_dev %u\n",
+		__func__, __LINE__, tmp.bus_type, tmp.bus_index, tmp.bus_id,
+		num_dev);
 
-		if (result) {
-			if (result !=  LV1_NO_ENTRY)
-				pr_debug("%s:%d ps3_repository_read_dev_reg"
-					" (%u:%u) failed\n", __func__, __LINE__,
-					bus_index, dev_index);
-			break;
-		}
-
-		pr_debug("%s:%d (%u:%u) reg_type %u, bus_addr %lxh, len %lxh\n",
-			__func__, __LINE__, bus_index, dev_index, reg_type,
-			bus_addr, len);
+	if (tmp.dev_index >= num_dev) {
+		pr_debug("%s:%d: no device found\n", __func__, __LINE__);
+		return -ENODEV;
 	}
 
-	pr_debug(" <- %s:%d\n", __func__, __LINE__);
-	return result;
-}
+	result = ps3_repository_read_dev_type(tmp.bus_index, tmp.dev_index,
+		&tmp.dev_type);
 
-static int dump_stor_dev_info(unsigned int bus_index, unsigned int dev_index)
-{
-	int result = 0;
-	unsigned int num_regions, region_index;
-	u64 port, blk_size, num_blocks;
-
-	pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__,
-		bus_index, dev_index);
-
-	result = ps3_repository_read_stor_dev_info(bus_index, dev_index, &port,
-		&blk_size, &num_blocks, &num_regions);
 	if (result) {
-		pr_debug("%s:%d ps3_repository_read_stor_dev_info"
-			" (%u:%u) failed\n", __func__, __LINE__,
-			bus_index, dev_index);
-		goto out;
+		pr_debug("%s:%d read_dev_type failed\n", __func__, __LINE__);
+		return result;
 	}
 
-	pr_debug("%s:%d  (%u:%u): port %lu, blk_size %lu, num_blocks "
-		 "%lu, num_regions %u\n",
-		 __func__, __LINE__, bus_index, dev_index, port,
-		 blk_size, num_blocks, num_regions);
+	result = ps3_repository_read_dev_id(tmp.bus_index, tmp.dev_index,
+		&tmp.dev_id);
 
-	for (region_index = 0; region_index < num_regions; region_index++) {
-		unsigned int region_id;
-		u64 region_start, region_size;
-
-		result = ps3_repository_read_stor_dev_region(bus_index,
-			dev_index, region_index, &region_id, &region_start,
-			&region_size);
-		if (result) {
-			 pr_debug("%s:%d ps3_repository_read_stor_dev_region"
-				  " (%u:%u) failed\n", __func__, __LINE__,
-				  bus_index, dev_index);
-			break;
-		}
-
-		pr_debug("%s:%d (%u:%u) region_id %u, start %lxh, size %lxh\n",
-			 __func__, __LINE__, bus_index, dev_index, region_id,
-			 region_start, region_size);
+	if (result) {
+		pr_debug("%s:%d ps3_repository_read_dev_id failed\n", __func__,
+		__LINE__);
+		return result;
 	}
 
-out:
-	pr_debug(" <- %s:%d\n", __func__, __LINE__);
-	return result;
-}
-
-static int dump_device_info(unsigned int bus_index, enum ps3_bus_type bus_type,
-			    unsigned int num_dev)
-{
-	int result = 0;
-	unsigned int dev_index;
-
-	pr_debug(" -> %s:%d: bus_%u\n", __func__, __LINE__, bus_index);
-
-	for (dev_index = 0; dev_index < num_dev; dev_index++) {
-		enum ps3_dev_type dev_type;
-		unsigned int dev_id;
+	pr_debug("%s:%d: found: dev_type %u, dev_index %u, dev_id %u\n",
+		__func__, __LINE__, tmp.dev_type, tmp.dev_index, tmp.dev_id);
 
-		result = ps3_repository_read_dev_type(bus_index, dev_index,
-			&dev_type);
-
-		if (result) {
-			pr_debug("%s:%d ps3_repository_read_dev_type"
-				" (%u:%u) failed\n", __func__, __LINE__,
-				bus_index, dev_index);
-			break;
-		}
-
-		result = ps3_repository_read_dev_id(bus_index, dev_index,
-			&dev_id);
-
-		if (result) {
-			pr_debug("%s:%d ps3_repository_read_dev_id"
-				" (%u:%u) failed\n", __func__, __LINE__,
-				bus_index, dev_index);
-			continue;
-		}
-
-		pr_debug("%s:%d  (%u:%u): dev_type %u, dev_id %u\n", __func__,
-			__LINE__, bus_index, dev_index, dev_type, dev_id);
-
-		ps3_repository_dump_resource_info(bus_index, dev_index);
-
-		if (bus_type == PS3_BUS_TYPE_STORAGE)
-			dump_stor_dev_info(bus_index, dev_index);
-	}
-
-	pr_debug(" <- %s:%d\n", __func__, __LINE__);
-	return result;
+	*repo = tmp;
+	return 0;
 }
 
-int ps3_repository_dump_bus_info(void)
+int __devinit ps3_repository_find_devices(enum ps3_bus_type bus_type,
+	int (*callback)(const struct ps3_repository_device *repo))
 {
 	int result = 0;
-	unsigned int bus_index;
+	struct ps3_repository_device repo;
 
-	pr_debug(" -> %s:%d\n", __func__, __LINE__);
+	pr_debug(" -> %s:%d: find bus_type %u\n", __func__, __LINE__, bus_type);
 
-	for (bus_index = 0; bus_index < 10; bus_index++) {
-		enum ps3_bus_type bus_type;
-		unsigned int bus_id;
-		unsigned int num_dev;
+	for (repo.bus_index = 0; repo.bus_index < 10; repo.bus_index++) {
 
-		result = ps3_repository_read_bus_type(bus_index, &bus_type);
+		result = ps3_repository_read_bus_type(repo.bus_index,
+			&repo.bus_type);
 
 		if (result) {
 			pr_debug("%s:%d read_bus_type(%u) failed\n",
-				__func__, __LINE__, bus_index);
+				__func__, __LINE__, repo.bus_index);
 			break;
 		}
 
-		result = ps3_repository_read_bus_id(bus_index, &bus_id);
-
-		if (result) {
-			pr_debug("%s:%d read_bus_id(%u) failed\n",
-				__func__, __LINE__, bus_index);
+		if (repo.bus_type != bus_type) {
+			pr_debug("%s:%d: skip, bus_type %u\n", __func__,
+				__LINE__, repo.bus_type);
 			continue;
 		}
 
-		if (bus_index != bus_id)
-			pr_debug("%s:%d bus_index != bus_id\n",
-				__func__, __LINE__);
-
-		result = ps3_repository_read_bus_num_dev(bus_index, &num_dev);
+		result = ps3_repository_read_bus_id(repo.bus_index,
+			&repo.bus_id);
 
 		if (result) {
-			pr_debug("%s:%d read_bus_num_dev(%u) failed\n",
-				__func__, __LINE__, bus_index);
+			pr_debug("%s:%d read_bus_id(%u) failed\n",
+				__func__, __LINE__, repo.bus_index);
 			continue;
 		}
 
-		pr_debug("%s:%d bus_%u: bus_type %u, bus_id %u, num_dev %u\n",
-			__func__, __LINE__, bus_index, bus_type, bus_id,
-			num_dev);
-
-		dump_device_info(bus_index, bus_type, num_dev);
-	}
+		for (repo.dev_index = 0; ; repo.dev_index++) {
+			result = ps3_repository_find_device(&repo);
 
-	pr_debug(" <- %s:%d\n", __func__, __LINE__);
-	return result;
-}
-#endif /* defined(DEBUG) */
-
-static int find_device(unsigned int bus_index, unsigned int num_dev,
-	unsigned int start_dev_index, enum ps3_dev_type dev_type,
-	struct ps3_repository_device *dev)
-{
-	int result = 0;
-	unsigned int dev_index;
-
-	pr_debug("%s:%d: find dev_type %u\n", __func__, __LINE__, dev_type);
-
-	dev->dev_index = UINT_MAX;
-
-	for (dev_index = start_dev_index; dev_index < num_dev; dev_index++) {
-		enum ps3_dev_type x;
-
-		result = ps3_repository_read_dev_type(bus_index, dev_index,
-			&x);
-
-		if (result) {
-			pr_debug("%s:%d read_dev_type failed\n",
-				__func__, __LINE__);
-			return result;
+			if (result == -ENODEV) {
+				result = 0;
+				break;
+			} else if (result)
+				break;
+
+			result = callback(&repo);
+
+			if (result) {
+				pr_debug("%s:%d: abort at callback\n", __func__,
+					__LINE__);
+				break;
+			}
 		}
-
-		if (x == dev_type)
-			break;
+		break;
 	}
 
-	if (dev_index == num_dev)
-		return -1;
-
-	pr_debug("%s:%d: found dev_type %u at dev_index %u\n",
-		__func__, __LINE__, dev_type, dev_index);
-
-	result = ps3_repository_read_dev_id(bus_index, dev_index,
-		&dev->did.dev_id);
-
-	if (result) {
-		pr_debug("%s:%d read_dev_id failed\n",
-			__func__, __LINE__);
-		return result;
-	}
-
-	dev->dev_index = dev_index;
-
-	pr_debug("%s:%d found: dev_id %u\n", __func__, __LINE__,
-		dev->did.dev_id);
-
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
 	return result;
 }
 
-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)
+int ps3_repository_find_bus(enum ps3_bus_type bus_type, unsigned int from,
+	unsigned int *bus_index)
 {
-	int result = 0;
-	unsigned int bus_index;
-	unsigned int num_dev;
-
-	pr_debug("%s:%d: find bus_type %u, dev_type %u\n", __func__, __LINE__,
-		bus_type, dev_type);
-
-	BUG_ON(start_dev && start_dev->bus_index > 10);
-
-	for (bus_index = start_dev ? start_dev->bus_index : 0; bus_index < 10;
-		bus_index++) {
-		enum ps3_bus_type x;
-
-		result = ps3_repository_read_bus_type(bus_index, &x);
-
-		if (result) {
+	unsigned int i;
+	enum ps3_bus_type type;
+	int error;
+
+	for (i = from; i < 10; i++) {
+		error = ps3_repository_read_bus_type(i, &type);
+		if (error) {
 			pr_debug("%s:%d read_bus_type failed\n",
 				__func__, __LINE__);
-			dev->bus_index = UINT_MAX;
-			return result;
+			*bus_index = UINT_MAX;
+			return error;
+		}
+		if (type == bus_type) {
+			*bus_index = i;
+			return 0;
 		}
-		if (x == bus_type)
-			break;
-	}
-
-	if (bus_index >= 10)
-		return -ENODEV;
-
-	pr_debug("%s:%d: found bus_type %u at bus_index %u\n",
-		__func__, __LINE__, bus_type, bus_index);
-
-	result = ps3_repository_read_bus_num_dev(bus_index, &num_dev);
-
-	if (result) {
-		pr_debug("%s:%d read_bus_num_dev failed\n",
-			__func__, __LINE__);
-		return result;
-	}
-
-	result = find_device(bus_index, num_dev, start_dev
-		? start_dev->dev_index + 1 : 0, dev_type, dev);
-
-	if (result) {
-		pr_debug("%s:%d get_did failed\n", __func__, __LINE__);
-		return result;
-	}
-
-	result = ps3_repository_read_bus_id(bus_index, &dev->did.bus_id);
-
-	if (result) {
-		pr_debug("%s:%d read_bus_id failed\n",
-			__func__, __LINE__);
-		return result;
 	}
-
-	dev->bus_index = bus_index;
-
-	pr_debug("%s:%d found: bus_id %u, dev_id %u\n",
-		__func__, __LINE__, dev->did.bus_id, dev->did.dev_id);
-
-	return result;
+	*bus_index = UINT_MAX;
+	return -ENODEV;
 }
 
-int ps3_repository_find_interrupt(const struct ps3_repository_device *dev,
+int ps3_repository_find_interrupt(const struct ps3_repository_device *repo,
 	enum ps3_interrupt_type intr_type, unsigned int *interrupt_id)
 {
 	int result = 0;
@@ -645,8 +461,8 @@ int ps3_repository_find_interrupt(const 
 		enum ps3_interrupt_type t;
 		unsigned int id;
 
-		result = ps3_repository_read_dev_intr(dev->bus_index,
-			dev->dev_index, res_index, &t, &id);
+		result = ps3_repository_read_dev_intr(repo->bus_index,
+			repo->dev_index, res_index, &t, &id);
 
 		if (result) {
 			pr_debug("%s:%d read_dev_intr failed\n",
@@ -669,7 +485,7 @@ int ps3_repository_find_interrupt(const 
 	return result;
 }
 
-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)
 {
 	int result = 0;
@@ -684,8 +500,8 @@ int ps3_repository_find_reg(const struct
 		u64 a;
 		u64 l;
 
-		result = ps3_repository_read_dev_reg(dev->bus_index,
-			dev->dev_index, res_index, &t, &a, &l);
+		result = ps3_repository_read_dev_reg(repo->bus_index,
+			repo->dev_index, res_index, &t, &a, &l);
 
 		if (result) {
 			pr_debug("%s:%d read_dev_reg failed\n",
@@ -965,6 +781,36 @@ int ps3_repository_read_boot_dat_size(un
 	return result;
 }
 
+int ps3_repository_read_vuart_av_port(unsigned int *port)
+{
+	int result;
+	u64 v1;
+
+	result = read_node(PS3_LPAR_ID_CURRENT,
+		make_first_field("bi", 0),
+		make_field("vir_uart", 0),
+		make_field("port", 0),
+		make_field("avset", 0),
+		&v1, 0);
+	*port = v1;
+	return result;
+}
+
+int ps3_repository_read_vuart_sysmgr_port(unsigned int *port)
+{
+	int result;
+	u64 v1;
+
+	result = read_node(PS3_LPAR_ID_CURRENT,
+		make_first_field("bi", 0),
+		make_field("vir_uart", 0),
+		make_field("port", 0),
+		make_field("sysmgr", 0),
+		&v1, 0);
+	*port = v1;
+	return result;
+}
+
 /**
   * ps3_repository_read_boot_dat_info - Get address and size of cell_ext_os_area.
   * address: lpar address of cell_ext_os_area
@@ -1026,3 +872,205 @@ int ps3_repository_read_be_tb_freq(unsig
 	return result ? result
 		: ps3_repository_read_tb_freq(node_id, tb_freq);
 }
+
+#if defined(DEBUG)
+
+int ps3_repository_dump_resource_info(const struct ps3_repository_device *repo)
+{
+	int result = 0;
+	unsigned int res_index;
+
+	pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__,
+		repo->bus_index, repo->dev_index);
+
+	for (res_index = 0; res_index < 10; res_index++) {
+		enum ps3_interrupt_type intr_type;
+		unsigned int interrupt_id;
+
+		result = ps3_repository_read_dev_intr(repo->bus_index,
+			repo->dev_index, res_index, &intr_type, &interrupt_id);
+
+		if (result) {
+			if (result !=  LV1_NO_ENTRY)
+				pr_debug("%s:%d ps3_repository_read_dev_intr"
+					" (%u:%u) failed\n", __func__, __LINE__,
+					repo->bus_index, repo->dev_index);
+			break;
+		}
+
+		pr_debug("%s:%d (%u:%u) intr_type %u, interrupt_id %u\n",
+			__func__, __LINE__, repo->bus_index, repo->dev_index,
+			intr_type, interrupt_id);
+	}
+
+	for (res_index = 0; res_index < 10; res_index++) {
+		enum ps3_reg_type reg_type;
+		u64 bus_addr;
+		u64 len;
+
+		result = ps3_repository_read_dev_reg(repo->bus_index,
+			repo->dev_index, res_index, &reg_type, &bus_addr, &len);
+
+		if (result) {
+			if (result !=  LV1_NO_ENTRY)
+				pr_debug("%s:%d ps3_repository_read_dev_reg"
+					" (%u:%u) failed\n", __func__, __LINE__,
+					repo->bus_index, repo->dev_index);
+			break;
+		}
+
+		pr_debug("%s:%d (%u:%u) reg_type %u, bus_addr %lxh, len %lxh\n",
+			__func__, __LINE__, repo->bus_index, repo->dev_index,
+			reg_type, bus_addr, len);
+	}
+
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	return result;
+}
+
+static int dump_stor_dev_info(struct ps3_repository_device *repo)
+{
+	int result = 0;
+	unsigned int num_regions, region_index;
+	u64 port, blk_size, num_blocks;
+
+	pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__,
+		repo->bus_index, repo->dev_index);
+
+	result = ps3_repository_read_stor_dev_info(repo->bus_index,
+		repo->dev_index, &port, &blk_size, &num_blocks, &num_regions);
+	if (result) {
+		pr_debug("%s:%d ps3_repository_read_stor_dev_info"
+			" (%u:%u) failed\n", __func__, __LINE__,
+			repo->bus_index, repo->dev_index);
+		goto out;
+	}
+
+	pr_debug("%s:%d  (%u:%u): port %lu, blk_size %lu, num_blocks "
+		 "%lu, num_regions %u\n",
+		 __func__, __LINE__, repo->bus_index, repo->dev_index, port,
+		 blk_size, num_blocks, num_regions);
+
+	for (region_index = 0; region_index < num_regions; region_index++) {
+		unsigned int region_id;
+		u64 region_start, region_size;
+
+		result = ps3_repository_read_stor_dev_region(repo->bus_index,
+			repo->dev_index, region_index, &region_id,
+			&region_start, &region_size);
+		if (result) {
+			 pr_debug("%s:%d ps3_repository_read_stor_dev_region"
+				  " (%u:%u) failed\n", __func__, __LINE__,
+				  repo->bus_index, repo->dev_index);
+			break;
+		}
+
+		pr_debug("%s:%d (%u:%u) region_id %u, start %lxh, size %lxh\n",
+			__func__, __LINE__, repo->bus_index, repo->dev_index,
+			region_id, region_start, region_size);
+	}
+
+out:
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	return result;
+}
+
+static int dump_device_info(struct ps3_repository_device *repo,
+	unsigned int num_dev)
+{
+	int result = 0;
+
+	pr_debug(" -> %s:%d: bus_%u\n", __func__, __LINE__, repo->bus_index);
+
+	for (repo->dev_index = 0; repo->dev_index < num_dev;
+		repo->dev_index++) {
+
+		result = ps3_repository_read_dev_type(repo->bus_index,
+			repo->dev_index, &repo->dev_type);
+
+		if (result) {
+			pr_debug("%s:%d ps3_repository_read_dev_type"
+				" (%u:%u) failed\n", __func__, __LINE__,
+				repo->bus_index, repo->dev_index);
+			break;
+		}
+
+		result = ps3_repository_read_dev_id(repo->bus_index,
+			repo->dev_index, &repo->dev_id);
+
+		if (result) {
+			pr_debug("%s:%d ps3_repository_read_dev_id"
+				" (%u:%u) failed\n", __func__, __LINE__,
+				repo->bus_index, repo->dev_index);
+			continue;
+		}
+
+		pr_debug("%s:%d  (%u:%u): dev_type %u, dev_id %u\n", __func__,
+			__LINE__, repo->bus_index, repo->dev_index,
+			repo->dev_type, repo->dev_id);
+
+		ps3_repository_dump_resource_info(repo);
+
+		if (repo->bus_type == PS3_BUS_TYPE_STORAGE)
+			dump_stor_dev_info(repo);
+	}
+
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	return result;
+}
+
+int ps3_repository_dump_bus_info(void)
+{
+	int result = 0;
+	struct ps3_repository_device repo;
+
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+	memset(&repo, 0, sizeof(repo));
+
+	for (repo.bus_index = 0; repo.bus_index < 10; repo.bus_index++) {
+		unsigned int num_dev;
+
+		result = ps3_repository_read_bus_type(repo.bus_index,
+			&repo.bus_type);
+
+		if (result) {
+			pr_debug("%s:%d read_bus_type(%u) failed\n",
+				__func__, __LINE__, repo.bus_index);
+			break;
+		}
+
+		result = ps3_repository_read_bus_id(repo.bus_index,
+			&repo.bus_id);
+
+		if (result) {
+			pr_debug("%s:%d read_bus_id(%u) failed\n",
+				__func__, __LINE__, repo.bus_index);
+			continue;
+		}
+
+		if (repo.bus_index != repo.bus_id)
+			pr_debug("%s:%d bus_index != bus_id\n",
+				__func__, __LINE__);
+
+		result = ps3_repository_read_bus_num_dev(repo.bus_index,
+			&num_dev);
+
+		if (result) {
+			pr_debug("%s:%d read_bus_num_dev(%u) failed\n",
+				__func__, __LINE__, repo.bus_index);
+			continue;
+		}
+
+		pr_debug("%s:%d bus_%u: bus_type %u, bus_id %u, num_dev %u\n",
+			__func__, __LINE__, repo.bus_index, repo.bus_type,
+			repo.bus_id, num_dev);
+
+		dump_device_info(&repo, num_dev);
+	}
+
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	return result;
+}
+
+#endif /* defined(DEBUG) */

-- 

^ permalink raw reply

* [patch 06/33] PS3: Fix sparse warnings
From: Geoff Levand @ 2007-06-15 21:19 UTC (permalink / raw)
  To: paulus; +Cc: Geert Uytterhoeven, linuxppc-dev
In-Reply-To: <20070615204749.629571012@am.sony.com>

From: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>

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

Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
 arch/powerpc/platforms/ps3/os-area.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

--- a/arch/powerpc/platforms/ps3/os-area.c
+++ b/arch/powerpc/platforms/ps3/os-area.c
@@ -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);

-- 

^ permalink raw reply

* [patch 02/33] PS3: Rename IPI symbols
From: Geoff Levand @ 2007-06-15 21:17 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev
In-Reply-To: <20070615204749.629571012@am.sony.com>

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

Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
 arch/powerpc/platforms/ps3/smp.c |   12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

--- a/arch/powerpc/platforms/ps3/smp.c
+++ b/arch/powerpc/platforms/ps3/smp.c
@@ -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,7 +132,7 @@ 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);

-- 

^ permalink raw reply


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