LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 7/7] [v2] drivers/misc: introduce Freescale hypervisor management driver
From: Timur Tabi @ 2011-06-01 18:35 UTC (permalink / raw)
  To: kumar.gala, benh, greg, akpm, linuxppc-dev, linux-kernel,
	linux-console

The Freescale hypervisor management driver provides several services to
drivers and applications related to the Freescale hypervisor:

1. An ioctl interface for querying and managing partitions

2. A file interface to reading incoming doorbells

3. An interrupt handler for shutting down the partition upon receiving the
   shutdown doorbell from a manager partition

4. An interface for receiving callbacks when a managed partition shuts down.

Signed-off-by: Timur Tabi <timur@freescale.com>
---
 drivers/misc/Kconfig           |    7 +
 drivers/misc/Makefile          |    1 +
 drivers/misc/fsl_hypervisor.c  |  941 ++++++++++++++++++++++++++++++++++++++++
 include/linux/Kbuild           |    1 +
 include/linux/fsl_hypervisor.h |  203 +++++++++
 5 files changed, 1153 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/fsl_hypervisor.c
 create mode 100644 include/linux/fsl_hypervisor.h

diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index d80dcde..3e016b3 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -216,6 +216,13 @@ config ENCLOSURE_SERVICES
 	  driver (SCSI/ATA) which supports enclosures
 	  or a SCSI enclosure device (SES) to use these services.
 
+config FSL_HV_MANAGER
+	tristate "Freescale hypervisor management driver"
+	depends on FSL_SOC
+	help
+	  This driver allows applications to communicate with the Freescale
+	  Hypervisor.
+
 config SGI_XP
 	tristate "Support communication between SGI SSIs"
 	depends on NET
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 848e846..d93bd76 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_SENSORS_BH1770)	+= bh1770glc.o
 obj-$(CONFIG_SENSORS_APDS990X)	+= apds990x.o
 obj-$(CONFIG_SGI_IOC4)		+= ioc4.o
 obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o
+obj-$(CONFIG_FSL_HV_MANAGER)	+= fsl_hypervisor.o
 obj-$(CONFIG_KGDB_TESTS)	+= kgdbts.o
 obj-$(CONFIG_SGI_XP)		+= sgi-xp/
 obj-$(CONFIG_SGI_GRU)		+= sgi-gru/
diff --git a/drivers/misc/fsl_hypervisor.c b/drivers/misc/fsl_hypervisor.c
new file mode 100644
index 0000000..a03aa7b
--- /dev/null
+++ b/drivers/misc/fsl_hypervisor.c
@@ -0,0 +1,941 @@
+/** @file
+ * Freescale Hypervisor Management Driver
+ *
+ * This driver contains functions to support the Freescale hypervisor.
+ */
+/* Copyright (C) 2008-2010 Freescale Semiconductor, Inc.
+ * Author: Timur Tabi <timur@freescale.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <linux/of.h>
+#include <linux/reboot.h>
+#include <linux/uaccess.h>
+#include <linux/notifier.h>
+
+#include <linux/io.h>
+#include <asm/fsl_hcalls.h>
+
+#include <linux/fsl_hypervisor.h>
+
+static BLOCKING_NOTIFIER_HEAD(failover_subscribers);
+
+/**
+ * ioctl_restart: ioctl interface for FSL_HV_IOCTL_PARTITION_RESTART
+ *
+ * Restart a running partition
+ */
+static long ioctl_restart(struct fsl_hv_ioctl_restart __user *p)
+{
+	struct fsl_hv_ioctl_restart param;
+
+	/* Get the parameters from the user */
+	if (copy_from_user(&param, p, sizeof(struct fsl_hv_ioctl_restart)))
+		return -EFAULT;
+
+	param.ret = fh_partition_restart(param.partition);
+
+	if (copy_to_user(&p->ret, &param.ret, sizeof(__u32)))
+		return -EFAULT;
+
+	return 0;
+}
+
+/**
+ * ioctl_status: ioctl interface for FSL_HV_IOCTL_PARTITION_STATUS
+ *
+ * Query the status of a partition
+ */
+static long ioctl_status(struct fsl_hv_ioctl_status __user *p)
+{
+	struct fsl_hv_ioctl_status param;
+	u32 status;
+
+	/* Get the parameters from the user */
+	if (copy_from_user(&param, p, sizeof(struct fsl_hv_ioctl_status)))
+		return -EFAULT;
+
+	param.ret = fh_partition_get_status(param.partition, &status);
+	if (!param.ret)
+		param.status = status;
+
+	if (copy_to_user(p, &param, sizeof(struct fsl_hv_ioctl_status)))
+		return -EFAULT;
+
+	return 0;
+}
+
+/**
+ * ioctl_start: ioctl interface for FSL_HV_IOCTL_PARTITION_START
+ *
+ * Start a stopped partition.
+ */
+static long ioctl_start(struct fsl_hv_ioctl_start __user *p)
+{
+	struct fsl_hv_ioctl_start param;
+
+	/* Get the parameters from the user */
+	if (copy_from_user(&param, p, sizeof(struct fsl_hv_ioctl_start)))
+		return -EFAULT;
+
+	param.ret = fh_partition_start(param.partition, param.entry_point,
+				       param.load);
+
+	if (copy_to_user(&p->ret, &param.ret, sizeof(__u32)))
+		return -EFAULT;
+
+	return 0;
+}
+
+/**
+ * ioctl_stop: ioctl interface for FSL_HV_IOCTL_PARTITION_STOP
+ *
+ * Stop a running partition
+ */
+static long ioctl_stop(struct fsl_hv_ioctl_stop __user *p)
+{
+	struct fsl_hv_ioctl_stop param;
+
+	/* Get the parameters from the user */
+	if (copy_from_user(&param, p, sizeof(struct fsl_hv_ioctl_stop)))
+		return -EFAULT;
+
+	param.ret = fh_partition_stop(param.partition);
+
+	if (copy_to_user(&p->ret, &param.ret, sizeof(__u32)))
+		return -EFAULT;
+
+	return 0;
+}
+
+/**
+ * ioctl_memcpy: ioctl interface for FSL_HV_IOCTL_MEMCPY
+ *
+ * The FH_MEMCPY hypercall takes an array of address/address/size structures
+ * to represent the data being copied.  As a convenience to the user, this
+ * ioctl takes a user-create buffer and a pointer to a guest physically
+ * contiguous buffer in the remote partition, and creates the
+ * address/address/size array for the hypercall.
+ */
+static long ioctl_memcpy(struct fsl_hv_ioctl_memcpy __user *p)
+{
+	struct fsl_hv_ioctl_memcpy param;
+
+	struct page **pages = NULL;
+	void *sg_list_unaligned = NULL;
+	struct fh_sg_list *sg_list = NULL;
+
+	unsigned int nr_pages;
+	unsigned long lb_offset; /* Offset within a page of the local buffer */
+
+	unsigned int i;
+	long ret = 0;
+	phys_addr_t remote_paddr; /* The next address in the remote buffer */
+	uint32_t count; /* The number of bytes left to copy */
+
+	/* Get the parameters from the user */
+	if (copy_from_user(&param, p, sizeof(struct fsl_hv_ioctl_memcpy)))
+		return -EFAULT;
+
+	/* One partition must be local, the other must be remote.  In other
+	   words, if source and target are both -1, or are both not -1, then
+	   return an error. */
+	if ((param.source == -1) == (param.target == -1))
+		return -EINVAL;
+
+	/*
+	 * The array of pages returned by get_user_pages() covers only
+	 * page-aligned memory.  Since the user buffer is probably not
+	 * page-aligned, we need to handle the discrepancy.
+	 *
+	 * We calculate the offset within a page of the S/G list, and make
+	 * adjustments accordingly.  This will result in a page list that looks
+	 * like this:
+	 *
+	 *      ----    <-- first page starts before the buffer
+	 *     |    |
+	 *     |////|-> ----
+	 *     |////|  |    |
+	 *      ----   |    |
+	 *             |    |
+	 *      ----   |    |
+	 *     |////|  |    |
+	 *     |////|  |    |
+	 *     |////|  |    |
+	 *      ----   |    |
+	 *             |    |
+	 *      ----   |    |
+	 *     |////|  |    |
+	 *     |////|  |    |
+	 *     |////|  |    |
+	 *      ----   |    |
+	 *             |    |
+	 *      ----   |    |
+	 *     |////|  |    |
+	 *     |////|-> ----
+	 *     |    |   <-- last page ends after the buffer
+	 *      ----
+	 *
+	 * The distance between the start of the first page and the start of the
+	 * buffer is lb_offset.  The hashed (///) areas are the parts of the
+	 * page list that contain the actual buffer.
+	 *
+	 * The advantage of this approach is that the number of pages is
+	 * equal to the number of entries in the S/G list that we give to the
+	 * hypervisor.
+	 */
+	lb_offset = param.local_vaddr & (PAGE_SIZE - 1);
+	nr_pages = (param.count + lb_offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+	/* Allocate the buffers we need */
+
+	/* pages is an array of struct page pointers that's initialized by
+	   get_user_pages() */
+	pages = kzalloc(nr_pages * sizeof(struct page *), GFP_KERNEL);
+	if (!pages) {
+		pr_debug("fsl-hv: could not allocate page list\n");
+		return -ENOMEM;
+	}
+
+	/* sg_list is the list of fh_sg_list objects that we pass to the
+	   hypervisor */
+	sg_list_unaligned = kmalloc(nr_pages * sizeof(struct fh_sg_list) +
+		sizeof(struct fh_sg_list) - 1, GFP_KERNEL);
+	if (!sg_list_unaligned) {
+		pr_debug("fsl-hv: could not allocate S/G list\n");
+		return -ENOMEM;
+	}
+	sg_list = PTR_ALIGN(sg_list_unaligned, sizeof(struct fh_sg_list));
+
+	/* Get the physical addresses of the source buffer */
+	down_read(&current->mm->mmap_sem);
+	ret = get_user_pages(current, current->mm,
+		param.local_vaddr - lb_offset, nr_pages,
+		(param.source == -1) ? READ : WRITE,
+		0, pages, NULL);
+	up_read(&current->mm->mmap_sem);
+
+	if (ret != nr_pages) {
+		/* get_user_pages() failed */
+		pr_debug("fsl-hv: could not lock source buffer\n");
+		ret = -EACCES;
+		goto exit;
+	}
+
+	/* reset ret here */
+	ret = 0;
+
+	/* Build the fh_sg_list[] array.  The first page is special
+	   because it's misaligned.*/
+	if (param.source == -1) {
+		sg_list[0].source = page_to_phys(pages[0]) + lb_offset;
+		sg_list[0].target = param.remote_paddr;
+	} else {
+		sg_list[0].source = param.remote_paddr;
+		sg_list[0].target = page_to_phys(pages[0]) + lb_offset;
+	}
+	sg_list[0].size = min_t(uint64_t, param.count, PAGE_SIZE - lb_offset);
+
+	remote_paddr = param.remote_paddr + sg_list[0].size;
+	count = param.count - sg_list[0].size;
+
+	for (i = 1; i < nr_pages; i++) {
+		if (param.source == -1) {
+			/* local to remote */
+			sg_list[i].source = page_to_phys(pages[i]);
+			sg_list[i].target = remote_paddr;
+		} else {
+			/* remote to local */
+			sg_list[i].source = remote_paddr;
+			sg_list[i].target = page_to_phys(pages[i]);
+		}
+		sg_list[i].size = min_t(uint64_t, count, PAGE_SIZE);
+
+		remote_paddr += sg_list[i].size;
+		count -= sg_list[i].size;
+	}
+
+	param.ret = fh_partition_memcpy(param.source, param.target,
+		virt_to_phys(sg_list), nr_pages);
+
+exit:
+	if (pages) {
+		for (i = 0; i < nr_pages; i++)
+			if (pages[i])
+				page_cache_release(pages[i]);
+	}
+
+	kfree(sg_list_unaligned);
+	kfree(pages);
+
+	if (!ret)
+		if (copy_to_user(&p->ret, &param.ret, sizeof(__u32)))
+			return -EFAULT;
+
+	return ret;
+}
+
+/**
+ * ioctl_doorbell: ioctl interface for FSL_HV_IOCTL_DOORBELL
+ *
+ * Ring a doorbell
+ */
+static long ioctl_doorbell(struct fsl_hv_ioctl_doorbell __user *p)
+{
+	struct fsl_hv_ioctl_doorbell param;
+
+	/* Get the parameters from the user */
+	if (copy_from_user(&param, p, sizeof(struct fsl_hv_ioctl_doorbell)))
+		return -EFAULT;
+
+	param.ret = ev_doorbell_send(param.doorbell);
+
+	if (copy_to_user(&p->ret, &param.ret, sizeof(__u32)))
+		return -EFAULT;
+
+	return 0;
+}
+
+static char *strdup_from_user(const char __user *ustr, size_t max)
+{
+	size_t len;
+	char *str;
+
+	len = strnlen_user(ustr, max);
+	if (len > max)
+		return ERR_PTR(-ENAMETOOLONG);
+
+	str = kmalloc(len, GFP_KERNEL);
+	if (!str)
+		return ERR_PTR(-ENOMEM);
+
+	if (copy_from_user(str, ustr, len))
+		return ERR_PTR(-EFAULT);
+
+	return str;
+}
+
+static long ioctl_dtprop(struct fsl_hv_ioctl_prop __user *p, int set)
+{
+	struct fsl_hv_ioctl_prop param;
+	char __user *upath, *upropname;
+	void __user *upropval;
+	char *path = NULL, *propname = NULL;
+	void *propval = NULL;
+	int ret = 0;
+
+	/* Get the parameters from the user */
+	if (copy_from_user(&param, p, sizeof(struct fsl_hv_ioctl_prop)))
+		return -EFAULT;
+
+	upath = (char __user *)(uintptr_t)param.path;
+	upropname = (char __user *)(uintptr_t)param.propname;
+	upropval = (void __user *)(uintptr_t)param.propval;
+
+	path = strdup_from_user(upath, FH_DTPROP_MAX_PATHLEN);
+	if (IS_ERR(path)) {
+		ret = PTR_ERR(path);
+		goto out;
+	}
+
+	propname = strdup_from_user(upropname, FH_DTPROP_MAX_PATHLEN);
+	if (IS_ERR(propname)) {
+		ret = PTR_ERR(propname);
+		goto out;
+	}
+
+	if (param.proplen > FH_DTPROP_MAX_PROPLEN) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	propval = kmalloc(param.proplen, GFP_KERNEL);
+	if (!propval) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	if (set) {
+		if (copy_from_user(propval, upropval, param.proplen)) {
+			ret = -EFAULT;
+			goto out;
+		}
+
+		param.ret = fh_partition_set_dtprop(param.handle,
+						    virt_to_phys(path),
+						    virt_to_phys(propname),
+						    virt_to_phys(propval),
+						    param.proplen);
+	} else {
+		param.ret = fh_partition_get_dtprop(param.handle,
+						    virt_to_phys(path),
+						    virt_to_phys(propname),
+						    virt_to_phys(propval),
+						    &param.proplen);
+
+		if (param.ret == 0) {
+			if (copy_to_user(upropval, propval, param.proplen) ||
+			    put_user(param.proplen, &p->proplen)) {
+				ret = -EFAULT;
+				goto out;
+			}
+		}
+	}
+
+	if (put_user(param.ret, &p->ret))
+		ret = -EFAULT;
+
+out:
+	kfree(path);
+	kfree(propval);
+	kfree(propname);
+
+	return ret;
+}
+
+/**
+ * fsl_hv_ioctl: ioctl main entry point
+ */
+static long fsl_hv_ioctl(struct file *file, unsigned int cmd,
+			 unsigned long argaddr)
+{
+	union fsl_hv_ioctl_param __user *arg =
+		(union fsl_hv_ioctl_param __user *)argaddr;
+	long ret;
+
+	/* Make sure the application is called the right driver. */
+	if (_IOC_TYPE(cmd) != 0) {
+		pr_debug("fsl-hv: ioctl type %u should be 0\n", _IOC_TYPE(cmd));
+		return -EINVAL;
+	}
+
+	/* Make sure the application set the direction flag correctly. */
+	if (_IOC_DIR(cmd) != (_IOC_READ | _IOC_WRITE)) {
+		pr_debug("fsl-hv: ioctl direction should be _IOWR\n");
+		return -EINVAL;
+	}
+
+	/* Make sure the application is passing the right structure to us. */
+	if (_IOC_SIZE(cmd) < sizeof(union fsl_hv_ioctl_param)) {
+		pr_debug("fsl-hv: ioctl size %u is too small (should be %u)\n",
+			 _IOC_SIZE(cmd), sizeof(union fsl_hv_ioctl_param));
+		return -EINVAL;
+	}
+
+	switch (_IOC_NR(cmd)) {
+	case FSL_HV_IOCTL_PARTITION_RESTART:
+		ret = ioctl_restart(&arg->restart);
+		break;
+	case FSL_HV_IOCTL_PARTITION_GET_STATUS:
+		ret = ioctl_status(&arg->status);
+		break;
+	case FSL_HV_IOCTL_PARTITION_START:
+		ret = ioctl_start(&arg->start);
+		break;
+	case FSL_HV_IOCTL_PARTITION_STOP:
+		ret = ioctl_stop(&arg->stop);
+		break;
+	case FSL_HV_IOCTL_MEMCPY:
+		ret = ioctl_memcpy(&arg->memcpy);
+		break;
+	case FSL_HV_IOCTL_DOORBELL:
+		ret = ioctl_doorbell(&arg->doorbell);
+		break;
+	case FSL_HV_IOCTL_GETPROP:
+		ret = ioctl_dtprop(&arg->prop, 0);
+		break;
+	case FSL_HV_IOCTL_SETPROP:
+		ret = ioctl_dtprop(&arg->prop, 1);
+		break;
+	default:
+		pr_debug("fsl-hv: unknown ioctl %u\n", cmd);
+		ret = -ENOIOCTLCMD;
+		break;
+	}
+
+	return ret;
+}
+
+/* Linked list of processes that have us open */
+struct list_head db_list;
+
+/* spinlock for db_list */
+static DEFINE_SPINLOCK(db_list_lock);
+
+/* The size of the doorbell event queue.  This must be a power of two. */
+#define QSIZE	16
+
+/* Returns the next head/tail pointer, wrapping around the queue if necessary */
+#define nextp(x) (((x) + 1) & (QSIZE - 1))
+
+/* Per-open data structure */
+struct doorbell_queue {
+	struct list_head list;
+	spinlock_t lock;
+	wait_queue_head_t wait;
+	unsigned int head;
+	unsigned int tail;
+	uint32_t q[QSIZE];
+};
+
+/* Linked list of ISRs that we registered */
+struct list_head isr_list;
+
+/* Per-ISR data structure */
+struct doorbell_isr {
+	struct list_head list;
+	unsigned int irq;
+	uint32_t doorbell;	/* The doorbell handle */
+	uint32_t partition;	/* The partition handle, if used */
+	struct work_struct work;
+};
+
+/**
+ * fsl_hv_isr - interrupt handler for all doorbells
+ * @param irq - the IRQ (a.k.a. receive handle)
+ *
+ * We use the same interrupt handler for all doorbells.  Whenever a doorbell
+ * is rung, and we receive an interrupt, we just put the handle for that
+ * doorbell (passed to us as *data) into all of the queues.
+ *
+ */
+static irqreturn_t fsl_hv_isr(int irq, void *data)
+{
+	struct doorbell_queue *dbq;
+	unsigned long flags;
+
+	/* Prevent another core from modifying db_list */
+	spin_lock_irqsave(&db_list_lock, flags);
+
+	list_for_each_entry(dbq, &db_list, list) {
+		if (dbq->head != nextp(dbq->tail)) {
+			dbq->q[dbq->tail] = (uint32_t) (uintptr_t) data;
+			/* This memory barrier eliminates the need to grab
+			 * the spinlock for dbq.
+			 */
+			smp_wmb();
+			dbq->tail = nextp(dbq->tail);
+			wake_up_interruptible(&dbq->wait);
+		}
+	}
+
+	spin_unlock_irqrestore(&db_list_lock, flags);
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * fsl_hv_state_change_work_func -- state change worker function
+ *
+ * The state change notification arrives in an interrupt, but we can't call
+ * blocking_notifier_call_chain() in an interrupt handler.  We could call
+ * atomic_notifier_call_chain(), but that would require the clients' call-back
+ * function to run in interrupt context.  Since we don't want to impose that
+ * restriction on the clients, we create a work queue to process the
+ * notification in kernel context.
+ */
+static void fsl_hv_state_change_work_func(struct work_struct *work)
+{
+	struct doorbell_isr *dbisr =
+		container_of(work, struct doorbell_isr, work);
+
+	blocking_notifier_call_chain(&failover_subscribers, dbisr->partition,
+				     NULL);
+}
+
+/**
+ * fsl_hv_state_change_isr - interrupt handler for state-change doorbells
+ */
+static irqreturn_t fsl_hv_state_change_isr(int irq, void *data)
+{
+	unsigned int status;
+	struct doorbell_isr *dbisr = data;
+	int ret;
+
+	/* Determine the new state, and if it's stopped, notify the clients. */
+	ret = fh_partition_get_status(dbisr->partition, &status);
+	if (!ret && (status == FH_PARTITION_STOPPED))
+		schedule_work(&dbisr->work);
+
+	/* Call the normal handler */
+	return fsl_hv_isr(irq, (void *) (uintptr_t) dbisr->doorbell);
+}
+
+/**
+ * fsl_hv_poll - returns a bitmask indicating whether a read will block
+ *
+ * @return unsigned int
+ */
+static unsigned int fsl_hv_poll(struct file *filp, struct poll_table_struct *p)
+{
+	struct doorbell_queue *dbq = filp->private_data;
+	unsigned long flags;
+	unsigned int mask;
+
+	spin_lock_irqsave(&dbq->lock, flags);
+
+	poll_wait(filp, &dbq->wait, p);
+	mask = (dbq->head == dbq->tail) ? 0 : (POLLIN | POLLRDNORM);
+
+	spin_unlock_irqrestore(&dbq->lock, flags);
+
+	return mask;
+}
+
+/**
+ * fsl_hv_read - return the handles for any incoming doorbells
+ *
+ * If there are doorbell handles in the queue for this open instance, then
+ * return them to the caller as an array of 32-bit integers.  Otherwise,
+ * block until there is at least one handle to return.
+ */
+static ssize_t fsl_hv_read(struct file *filp, char __user *buf, size_t len,
+			   loff_t *off)
+{
+	struct doorbell_queue *dbq = filp->private_data;
+	uint32_t __user *p = (uint32_t __user *) buf; /* for put_user() */
+	unsigned long flags;
+	ssize_t count = 0;
+
+	/* Make sure we stop when the user buffer is full. */
+	while (len >= sizeof(uint32_t)) {
+		uint32_t dbell;	/* Local copy of doorbell queue data */
+
+		spin_lock_irqsave(&dbq->lock, flags);
+
+		/* If the queue is empty, then either we're done or we need
+		 * to block.  If the application specified O_NONBLOCK, then
+		 * we return the appropriate error code.
+		 */
+		if (dbq->head == dbq->tail) {
+			spin_unlock_irqrestore(&dbq->lock, flags);
+			if (count)
+				break;
+			if (filp->f_flags & O_NONBLOCK)
+				return -EAGAIN;
+			if (wait_event_interruptible(dbq->wait,
+						     dbq->head != dbq->tail))
+				return -ERESTARTSYS;
+			continue;
+		}
+
+		/* Even though we have an smp_wmb() in the ISR, the core
+		 * might speculatively execute the "dbell = ..." below while
+		 * it's evaluating the if-statement above.  In that case, the
+		 * value put into dbell could be stale if the core accepts the
+		 * speculation. To prevent that, we need a read memory barrier
+		 * here as well.
+		 */
+		smp_rmb();
+
+		/* Copy the data to a temporary local buffer, because
+		 * we can't call copy_to_user() from inside a spinlock
+		 */
+		dbell = dbq->q[dbq->head];
+		dbq->head = nextp(dbq->head);
+
+		spin_unlock_irqrestore(&dbq->lock, flags);
+
+		if (put_user(dbell, p))
+			return -EFAULT;
+		p++;
+		count += sizeof(uint32_t);
+		len -= sizeof(uint32_t);
+	}
+
+	return count;
+}
+
+/**
+ * fsl_hv_open - open the driver
+ *
+ * Open the driver and prepare for reading doorbells.
+ *
+ * Every time an application opens the driver, we create a doorbell queue
+ * for that file handle.  This queue is used for any incoming doorbells.
+ */
+static int fsl_hv_open(struct inode *inode, struct file *filp)
+{
+	struct doorbell_queue *dbq;
+	unsigned long flags;
+	int ret = 0;
+
+	dbq = kzalloc(sizeof(struct doorbell_queue), GFP_KERNEL);
+	if (!dbq) {
+		pr_err("fsl-hv: out of memory\n");
+		return -ENOMEM;
+	}
+
+	spin_lock_init(&dbq->lock);
+	init_waitqueue_head(&dbq->wait);
+
+	spin_lock_irqsave(&db_list_lock, flags);
+	list_add(&dbq->list, &db_list);
+	spin_unlock_irqrestore(&db_list_lock, flags);
+
+	filp->private_data = dbq;
+
+	return ret;
+}
+
+/**
+ * fsl_hv_close - close the driver
+ */
+static int fsl_hv_close(struct inode *inode, struct file *filp)
+{
+	struct doorbell_queue *dbq = filp->private_data;
+	unsigned long flags;
+
+	int ret = 0;
+
+	spin_lock_irqsave(&db_list_lock, flags);
+	list_del(&dbq->list);
+	spin_unlock_irqrestore(&db_list_lock, flags);
+
+	kfree(dbq);
+
+	return ret;
+}
+
+static const struct file_operations fsl_hv_fops = {
+	.owner = THIS_MODULE,
+	.open = fsl_hv_open,
+	.release = fsl_hv_close,
+	.poll = fsl_hv_poll,
+	.read = fsl_hv_read,
+	.unlocked_ioctl = fsl_hv_ioctl,
+};
+
+static struct miscdevice fsl_hv_misc_dev = {
+	MISC_DYNAMIC_MINOR,
+	"fsl-hv",
+	&fsl_hv_fops
+};
+
+static DECLARE_WORK(power_off, (work_func_t) kernel_power_off);
+
+static irqreturn_t fsl_hv_shutdown_isr(int irq, void *data)
+{
+	schedule_work(&power_off);
+
+	/* We should never get here */
+	return IRQ_NONE;
+}
+
+/**
+ * get_parent_handle -- returns the handle of the parent of the given node
+ *
+ * The handle is the value of the 'reg' property
+ */
+static int get_parent_handle(struct device_node *np)
+{
+	struct device_node *parent;
+	const uint32_t *prop;
+	int len;
+
+	parent = of_get_parent(np);
+	if (!parent)
+		/* It's not really possible for this to fail */
+		return -ENODEV;
+
+	prop = of_get_property(parent, "reg", &len);
+	of_node_put(parent);
+
+	if (!prop || (len != sizeof(uint32_t)))
+		/* This can happen only if the node is malformed */
+		return -ENODEV;
+
+	return *prop;
+}
+
+/**
+ * fsl_hv_failover_register -- register a callback for failover events
+ *
+ * This function is called by device drivers to register their callback
+ * functions for fail-over events.
+ */
+int fsl_hv_failover_register(struct notifier_block *nb)
+{
+	return blocking_notifier_chain_register(&failover_subscribers, nb);
+}
+EXPORT_SYMBOL(fsl_hv_failover_register);
+
+/**
+ * fsl_hv_failover_unregister -- unregister a callback for failover events
+ */
+int fsl_hv_failover_unregister(struct notifier_block *nb)
+{
+	return blocking_notifier_chain_unregister(&failover_subscribers, nb);
+}
+EXPORT_SYMBOL(fsl_hv_failover_unregister);
+
+/**
+ * has_fsl_hypervisor - return TRUE if we're running under FSL hypervisor
+ *
+ * This function checks to see if we're running under the Freescale
+ * hypervisor, and returns zero if we're not, or non-zero if we are.
+ *
+ * First, it checks if MSR[GS]==1, which means we're running under some
+ * hypervisor.  Then it checks if there is a hypervisor node in the device
+ * tree.  Currently, that means there needs to be a node in the root called
+ * "hypervisor" and which has a property named "fsl,hv-version".
+ */
+static int has_fsl_hypervisor(void)
+{
+	struct device_node *node;
+	int ret;
+
+	if (!(mfmsr() & MSR_GS))
+		return 0;
+
+	node = of_find_node_by_path("/hypervisor");
+	if (!node)
+		return 0;
+
+	ret = of_find_property(node, "fsl,hv-version", NULL) != NULL;
+
+	of_node_put(node);
+
+	return ret;
+}
+
+/**
+ * fsl_hypervisor_init: Freescale hypervisor management driver init
+ *
+ * This function is called when this module is loaded.
+ *
+ * Register ourselves as a miscellaneous driver.  This will register the
+ * fops structure and create the right sysfs entries for udev.
+ */
+static int __init fsl_hypervisor_init(void)
+{
+	struct device_node *np;
+	struct doorbell_isr *dbisr, *n;
+	int ret;
+
+	pr_info("Freescale hypervisor management driver\n");
+
+	if (!has_fsl_hypervisor()) {
+		pr_info("fsl-hv: no hypervisor found\n");
+		return -ENODEV;
+	}
+
+	ret = misc_register(&fsl_hv_misc_dev);
+	if (ret) {
+		pr_err("fsl-hv: cannot register device\n");
+		return ret;
+	}
+
+	INIT_LIST_HEAD(&db_list);
+	INIT_LIST_HEAD(&isr_list);
+
+	for_each_compatible_node(np, NULL, "epapr,hv-receive-doorbell") {
+		unsigned int irq;
+		const uint32_t *handle;
+
+		handle = of_get_property(np, "interrupts", NULL);
+		irq = irq_of_parse_and_map(np, 0);
+		if (!handle || (irq == NO_IRQ)) {
+			pr_err("fsl-hv: no 'interrupts' property in %s node\n",
+				np->full_name);
+			continue;
+		}
+
+		dbisr = kzalloc(sizeof(*dbisr), GFP_KERNEL);
+		if (!dbisr)
+			goto out_of_memory;
+
+		dbisr->irq = irq;
+		dbisr->doorbell = *handle;
+		INIT_WORK(&dbisr->work, fsl_hv_state_change_work_func);
+
+		if (of_device_is_compatible(np, "fsl,hv-shutdown-doorbell")) {
+			/* The shutdown doorbell gets its own ISR */
+			ret = request_irq(irq, fsl_hv_shutdown_isr, 0,
+					  np->name, dbisr);
+		} else if (of_device_is_compatible(np,
+			"fsl,hv-state-change-doorbell")) {
+			/* The state change doorbell triggers a notification if
+			 * the state of the managed partition changes to
+			 * "stopped". We need a separate interrupt handler for
+			 * that, and we also need to know the handle of the
+			 * target partition, not just the handle of the
+			 * doorbell.
+			 */
+			dbisr->partition = ret = get_parent_handle(np);
+			if (ret < 0) {
+				pr_err("fsl-hv: node %s has missing or "
+				       "malformed parent\n", np->full_name);
+				kfree(dbisr);
+				continue;
+			}
+			ret = request_irq(irq, fsl_hv_state_change_isr, 0,
+					  np->name, dbisr);
+		} else
+			ret = request_irq(irq, fsl_hv_isr, 0, np->name, dbisr);
+
+		if (ret < 0) {
+			pr_err("fsl-hv: could not request irq %u for node %s\n",
+			       irq, np->full_name);
+			kfree(dbisr);
+			continue;
+		}
+
+		list_add(&dbisr->list, &isr_list);
+
+		pr_info("fsl-hv: registered handler for doorbell %u\n",
+			*handle);
+	}
+
+	return 0;
+
+out_of_memory:
+	list_for_each_entry_safe(dbisr, n, &isr_list, list) {
+		free_irq(dbisr->irq, dbisr);
+		list_del(&dbisr->list);
+		kfree(dbisr);
+	}
+
+	misc_deregister(&fsl_hv_misc_dev);
+
+	return -ENOMEM;
+}
+
+/**
+ * fsl_hypervisor_exit: Freescale hypervisor management driver termination
+ *
+ * This function is called when this driver is unloaded.
+ */
+static void __exit fsl_hypervisor_exit(void)
+{
+	struct doorbell_isr *dbisr, *n;
+
+	list_for_each_entry_safe(dbisr, n, &isr_list, list) {
+		free_irq(dbisr->irq, dbisr);
+		list_del(&dbisr->list);
+		kfree(dbisr);
+	}
+
+	misc_deregister(&fsl_hv_misc_dev);
+}
+
+module_init(fsl_hypervisor_init);
+module_exit(fsl_hypervisor_exit);
+
+MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
+MODULE_DESCRIPTION("Freescale hypervisor management driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 75cf611..68c341a 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -134,6 +134,7 @@ header-y += firewire-cdev.h
 header-y += firewire-constants.h
 header-y += flat.h
 header-y += fs.h
+header-y += fsl_hypervisor.h
 header-y += fuse.h
 header-y += futex.h
 header-y += gameport.h
diff --git a/include/linux/fsl_hypervisor.h b/include/linux/fsl_hypervisor.h
new file mode 100644
index 0000000..63740a2
--- /dev/null
+++ b/include/linux/fsl_hypervisor.h
@@ -0,0 +1,203 @@
+/*
+ * Freescale hypervisor ioctl interface
+ *
+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
+ * This file is used by the Freescale hypervisor management driver.  It can
+ * also be included by applications that need to communicate with the driver
+ * via the ioctl interface.
+ */
+
+#ifndef FSL_HYPERVISOR_H
+#define FSL_HYPERVISOR_H
+
+#include <linux/types.h>
+
+/**
+ * Freescale hypervisor ioctl parameter
+ */
+union fsl_hv_ioctl_param {
+
+	/**
+	 * @ret: Return value.
+	 *
+	 * This is always the first word of any structure.
+	 */
+	__u32 ret;
+
+	/**
+	 * struct fsl_hv_ioctl_restart: restart a partition
+	 * @ret: return error code from the hypervisor
+	 * @partition: the ID of the partition to restart, or -1 for the
+	 *             calling partition
+	 *
+	 * Used by FSL_HV_IOCTL_PARTITION_RESTART
+	 */
+	struct fsl_hv_ioctl_restart {
+		__u32 ret;
+		__u32 partition;
+	} restart;
+
+	/**
+	 * struct fsl_hv_ioctl_status: get a partition's status
+	 * @ret: return error code from the hypervisor
+	 * @partition: the ID of the partition to query, or -1 for the
+	 *             calling partition
+	 * @status: The returned status of the partition
+	 *
+	 * Used by FSL_HV_IOCTL_PARTITION_GET_STATUS
+	 *
+	 * Values of 'status':
+	 *    0 = Stopped
+	 *    1 = Running
+	 *    2 = Starting
+	 *    3 = Stopping
+	 */
+	struct fsl_hv_ioctl_status {
+		__u32 ret;
+		__u32 partition;
+		__u32 status;
+	} status;
+
+	/**
+	 * struct fsl_hv_ioctl_start: start a partition
+	 * @ret: return error code from the hypervisor
+	 * @partition: the ID of the partition to control
+	 * @entry_point: The offset within the guest IMA to start execution
+	 * @load: If non-zero, reload the partition's images before starting
+	 *
+	 * Used by FSL_HV_IOCTL_PARTITION_START
+	 */
+	struct fsl_hv_ioctl_start {
+		__u32 ret;
+		__u32 partition;
+		__u32 entry_point;
+		__u32 load;
+	} start;
+
+	/**
+	 * struct fsl_hv_ioctl_stop: stop a partition
+	 * @ret: return error code from the hypervisor
+	 * @partition: the ID of the partition to stop, or -1 for the calling
+	 *             partition
+	 *
+	 * Used by FSL_HV_IOCTL_PARTITION_STOP
+	 */
+	struct fsl_hv_ioctl_stop {
+		__u32 ret;
+		__u32 partition;
+	} stop;
+
+	/**
+	 * struct fsl_hv_ioctl_memcpy: copy memory between partitions
+	 * @ret: return error code from the hypervisor
+	 * @source: the partition ID of the source partition, or -1 for this
+	 *          partition
+	 * @target: the partition ID of the target partition, or -1 for this
+	 *          partition
+	 * @local_addr: user-space virtual address of a buffer in the local
+	 *              partition
+	 * @remote_addr: guest physical address of a buffer in the
+	 *           remote partition
+	 * @count: the number of bytes to copy.  Both the local and remote
+	 *         buffers must be at least 'count' bytes long
+	 *
+	 * Used by FSL_HV_IOCTL_MEMCPY
+	 *
+	 * The 'local' partition is the partition that calls this ioctl.  The
+	 * 'remote' partition is a different partition.  The data is copied from
+	 * the 'source' paritition' to the 'target' partition.
+	 *
+	 * The buffer in the remote partition must be guest physically
+	 * contiguous.
+	 *
+	 * This ioctl does not support copying memory between two remote
+	 * partitions or within the same partition, so either 'source' or
+	 * 'target' (but not both) must be -1.  In other words, either
+	 *
+	 *      source == local and target == remote
+	 * or
+	 *      source == remote and target == local
+	 */
+	struct fsl_hv_ioctl_memcpy {
+		__u32 ret;
+		__u32 source;
+		__u32 target;
+		__u64 local_vaddr;
+		__u64 remote_paddr;
+		__u64 count;
+	} memcpy;
+
+	/**
+	 * struct fsl_hv_ioctl_doorbell: ring a doorbell
+	 * @ret: return error code from the hypervisor
+	 * @doorbell: the handle of the doorbell to ring doorbell
+	 *
+	 * Used by FSL_HV_IOCTL_DOORBELL
+	 */
+	struct fsl_hv_ioctl_doorbell {
+		__u32 ret;
+		__u32 doorbell;
+	} doorbell;
+
+	/**
+	 * struct fsl_hv_ioctl_prop: get/set a device tree property
+	 * @ret: return error code from the hypervisor
+	 * @handle: handle of partition whose tree to access
+	 * @path: virtual address of path name of node to access
+	 * @propname: virtual address of name of property to access
+	 * @propval: virtual address of property data buffer
+	 * @proplen: Size of property data buffer
+	 *
+	 * Used by FSL_HV_IOCTL_DOORBELL
+	 */
+	struct fsl_hv_ioctl_prop {
+		__u32 ret;
+		__u32 handle;
+		__u64 path;
+		__u64 propname;
+		__u64 propval;
+		__u32 proplen;
+	} prop;
+};
+
+/*
+ * ioctl commands.
+ */
+enum {
+	FSL_HV_IOCTL_PARTITION_RESTART = 1, /* Boot another partition */
+	FSL_HV_IOCTL_PARTITION_GET_STATUS = 2, /* Boot another partition */
+	FSL_HV_IOCTL_PARTITION_START = 3, /* Boot another partition */
+	FSL_HV_IOCTL_PARTITION_STOP = 4, /* Stop this or another partition */
+	FSL_HV_IOCTL_MEMCPY = 5, /* Copy data from one partition to another */
+	FSL_HV_IOCTL_DOORBELL = 6, /* Ring a doorbell */
+
+	/* Get a property from another guest's device tree */
+	FSL_HV_IOCTL_GETPROP = 7,
+
+	/* Set a property in another guest's device tree */
+	FSL_HV_IOCTL_SETPROP = 8,
+};
+
+#ifdef __KERNEL__
+
+/**
+ * fsl_hv_event_register -- register a callback for failover events
+ *
+ * This function is called by device drivers to register their callback
+ * functions for fail-over events.
+ */
+int fsl_hv_failover_register(struct notifier_block *nb);
+
+/**
+ * fsl_hv_event_unregister -- unregister a callback for failover events
+ */
+int fsl_hv_failover_unregister(struct notifier_block *nb);
+
+#endif
+
+#endif
-- 
1.7.3.4

^ permalink raw reply related

* Re: [PATCH] Fix build warning of the defconfigs
From: Wolfram Sang @ 2011-06-01 18:16 UTC (permalink / raw)
  To: Wanlong Gao
  Cc: linux-mips, david.woodhouse, linux-sh, paulus, gxt, sam, linux,
	manuel.lauss, rientjes, mingo, vapier, arnd, u.kleine-koenig,
	anton, linux-arm-kernel, linux-kernel, ralf, lethal,
	uclinux-dist-devel, akpm, linuxppc-dev, hans-christian.egtvedt
In-Reply-To: <1306945763-6583-1-git-send-email-wanlong.gao@gmail.com>

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

On Thu, Jun 02, 2011 at 12:29:23AM +0800, Wanlong Gao wrote:
> RTC_CLASS is changed to bool.
> So value 'm' is invalid.
> 
> Signed-off-by: Wanlong Gao <wanlong.gao@gmail.com>
> ---
>  arch/arm/configs/davinci_all_defconfig     |    2 +-
>  arch/arm/configs/mxs_defconfig             |    2 +-
>  arch/arm/configs/netx_defconfig            |    2 +-
>  arch/arm/configs/viper_defconfig           |    2 +-
>  arch/arm/configs/xcep_defconfig            |    2 +-
>  arch/arm/configs/zeus_defconfig            |    2 +-
>  arch/avr32/configs/atngw100_mrmt_defconfig |    2 +-
>  arch/blackfin/configs/CM-BF548_defconfig   |    2 +-
>  arch/mips/configs/mtx1_defconfig           |    2 +-
>  arch/powerpc/configs/52xx/pcm030_defconfig |    2 +-
>  arch/powerpc/configs/ps3_defconfig         |    2 +-
>  arch/sh/configs/titan_defconfig            |    2 +-
>  arch/unicore32/configs/debug_defconfig     |    2 +-
>  13 files changed, 13 insertions(+), 13 deletions(-)

The mxs-part has already been sent by Shawn Guo (shouldn't harm).

Thanks for doing tree-wide:

Acked-by: Wolfram Sang <w.sang@pengutronix.de>

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

^ permalink raw reply

* Re: [PATCH] Fix build warning of the defconfigs
From: Mike Frysinger @ 2011-06-01 17:00 UTC (permalink / raw)
  To: Wanlong Gao
  Cc: linux-mips, david.woodhouse, linux-sh, paulus, gxt, sam, linux,
	manuel.lauss, rientjes, mingo, arnd, u.kleine-koenig, anton,
	linux-arm-kernel, linux-kernel, ralf, lethal, uclinux-dist-devel,
	akpm, linuxppc-dev, hans-christian.egtvedt
In-Reply-To: <1306945763-6583-1-git-send-email-wanlong.gao@gmail.com>

On Wed, Jun 1, 2011 at 12:29, Wanlong Gao wrote:
> =C2=A0arch/blackfin/configs/CM-BF548_defconfig =C2=A0 | =C2=A0 =C2=A02 +-

Acked-by: Mike Frysinger <vapier@gentoo.org>
-mike

^ permalink raw reply

* Re: [PATCH 1/2] ppc/85xx: create a platform node for PCI EDAC device
From: Scott Wood @ 2011-06-01 16:48 UTC (permalink / raw)
  To: Dmitry Eremin-Solenikov
  Cc: Paul Mackerras, Anton Vorontsov, linuxppc-dev, bluesmoke-devel
In-Reply-To: <BANLkTi=xFcZRd4x1FQSKJzmt3A7_tZs+sQ@mail.gmail.com>

On Wed, 1 Jun 2011 18:55:35 +0400
Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> wrote:

> On 6/1/11, Anton Vorontsov <avorontsov@mvista.com> wrote:
> > On Wed, Jun 01, 2011 at 04:28:11PM +0400, Dmitry Eremin-Solenikov wrote:
> > [...]
> > Also, why not add this call to the fsl_add_bridge(), so you
> > won't need to touch board files at all.
> 
> Because fsl_add_bridge is called too early, so allocation
> of platform device fails.

That doesn't seem like a good reason for putting more stuff in board
files that isn't board-specific.  Why not just make fsl_add_pci_err() an
initcall?  It already only works when a compatible device tree node is
found.  Is there any case where a board would not want this PCI code to be
used, even if the device tree node is present?  If so, fsl_add_bridge could
set a flag that fsl_add_pci_err() could check -- but I doubt it's needed.

-Scott

^ permalink raw reply

* [PATCH] Fix build warning of the defconfigs
From: Wanlong Gao @ 2011-06-01 16:29 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel, uclinux-dist-devel, linux-mips,
	linuxppc-dev, linux-sh
  Cc: rientjes, vapier, david.woodhouse, arnd, Wanlong Gao, mingo, ralf,
	manuel.lauss, lethal, paulus, anton, u.kleine-koenig, linux, akpm,
	gxt, sam, hans-christian.egtvedt

RTC_CLASS is changed to bool.
So value 'm' is invalid.

Signed-off-by: Wanlong Gao <wanlong.gao@gmail.com>
---
 arch/arm/configs/davinci_all_defconfig     |    2 +-
 arch/arm/configs/mxs_defconfig             |    2 +-
 arch/arm/configs/netx_defconfig            |    2 +-
 arch/arm/configs/viper_defconfig           |    2 +-
 arch/arm/configs/xcep_defconfig            |    2 +-
 arch/arm/configs/zeus_defconfig            |    2 +-
 arch/avr32/configs/atngw100_mrmt_defconfig |    2 +-
 arch/blackfin/configs/CM-BF548_defconfig   |    2 +-
 arch/mips/configs/mtx1_defconfig           |    2 +-
 arch/powerpc/configs/52xx/pcm030_defconfig |    2 +-
 arch/powerpc/configs/ps3_defconfig         |    2 +-
 arch/sh/configs/titan_defconfig            |    2 +-
 arch/unicore32/configs/debug_defconfig     |    2 +-
 13 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/arch/arm/configs/davinci_all_defconfig b/arch/arm/configs/davinci_all_defconfig
index 889922a..67b5abb6 100644
--- a/arch/arm/configs/davinci_all_defconfig
+++ b/arch/arm/configs/davinci_all_defconfig
@@ -157,7 +157,7 @@ CONFIG_LEDS_GPIO=m
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=m
 CONFIG_LEDS_TRIGGER_HEARTBEAT=m
-CONFIG_RTC_CLASS=m
+CONFIG_RTC_CLASS=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 CONFIG_XFS_FS=m
diff --git a/arch/arm/configs/mxs_defconfig b/arch/arm/configs/mxs_defconfig
index 2bf2243..5a6ff7c 100644
--- a/arch/arm/configs/mxs_defconfig
+++ b/arch/arm/configs/mxs_defconfig
@@ -89,7 +89,7 @@ CONFIG_DISPLAY_SUPPORT=m
 # CONFIG_USB_SUPPORT is not set
 CONFIG_MMC=y
 CONFIG_MMC_MXS=y
-CONFIG_RTC_CLASS=m
+CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_DS1307=m
 CONFIG_DMADEVICES=y
 CONFIG_MXS_DMA=y
diff --git a/arch/arm/configs/netx_defconfig b/arch/arm/configs/netx_defconfig
index 316af54..9c0ad79 100644
--- a/arch/arm/configs/netx_defconfig
+++ b/arch/arm/configs/netx_defconfig
@@ -60,7 +60,7 @@ CONFIG_FB_ARMCLCD=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_LOGO=y
-CONFIG_RTC_CLASS=m
+CONFIG_RTC_CLASS=y
 CONFIG_INOTIFY=y
 CONFIG_TMPFS=y
 CONFIG_JFFS2_FS=y
diff --git a/arch/arm/configs/viper_defconfig b/arch/arm/configs/viper_defconfig
index 8b0c717..1d01ddd 100644
--- a/arch/arm/configs/viper_defconfig
+++ b/arch/arm/configs/viper_defconfig
@@ -142,7 +142,7 @@ CONFIG_USB_GADGETFS=m
 CONFIG_USB_FILE_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_G_PRINTER=m
-CONFIG_RTC_CLASS=m
+CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_DS1307=m
 CONFIG_RTC_DRV_SA1100=m
 CONFIG_EXT2_FS=m
diff --git a/arch/arm/configs/xcep_defconfig b/arch/arm/configs/xcep_defconfig
index 5b55041..721832f 100644
--- a/arch/arm/configs/xcep_defconfig
+++ b/arch/arm/configs/xcep_defconfig
@@ -73,7 +73,7 @@ CONFIG_SENSORS_MAX6650=m
 # CONFIG_VGA_CONSOLE is not set
 # CONFIG_HID_SUPPORT is not set
 # CONFIG_USB_SUPPORT is not set
-CONFIG_RTC_CLASS=m
+CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_SA1100=m
 CONFIG_DMADEVICES=y
 # CONFIG_DNOTIFY is not set
diff --git a/arch/arm/configs/zeus_defconfig b/arch/arm/configs/zeus_defconfig
index 960f655..59577ad 100644
--- a/arch/arm/configs/zeus_defconfig
+++ b/arch/arm/configs/zeus_defconfig
@@ -158,7 +158,7 @@ CONFIG_LEDS_TRIGGER_HEARTBEAT=m
 CONFIG_LEDS_TRIGGER_BACKLIGHT=m
 CONFIG_LEDS_TRIGGER_GPIO=m
 CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
-CONFIG_RTC_CLASS=m
+CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_ISL1208=m
 CONFIG_RTC_DRV_PXA=m
 CONFIG_EXT2_FS=y
diff --git a/arch/avr32/configs/atngw100_mrmt_defconfig b/arch/avr32/configs/atngw100_mrmt_defconfig
index 19f6cee..fb6dab8 100644
--- a/arch/avr32/configs/atngw100_mrmt_defconfig
+++ b/arch/avr32/configs/atngw100_mrmt_defconfig
@@ -109,7 +109,7 @@ CONFIG_LEDS_GPIO=y
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=y
 CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-CONFIG_RTC_CLASS=m
+CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_S35390A=m
 CONFIG_RTC_DRV_AT32AP700X=m
 CONFIG_DMADEVICES=y
diff --git a/arch/blackfin/configs/CM-BF548_defconfig b/arch/blackfin/configs/CM-BF548_defconfig
index 31d9542..9f1d084 100644
--- a/arch/blackfin/configs/CM-BF548_defconfig
+++ b/arch/blackfin/configs/CM-BF548_defconfig
@@ -112,7 +112,7 @@ CONFIG_USB_G_SERIAL=m
 CONFIG_USB_G_PRINTER=m
 CONFIG_MMC=m
 CONFIG_SDH_BFIN=m
-CONFIG_RTC_CLASS=m
+CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_BFIN=m
 CONFIG_EXT2_FS=m
 # CONFIG_DNOTIFY is not set
diff --git a/arch/mips/configs/mtx1_defconfig b/arch/mips/configs/mtx1_defconfig
index 37862b2..807c97e 100644
--- a/arch/mips/configs/mtx1_defconfig
+++ b/arch/mips/configs/mtx1_defconfig
@@ -678,7 +678,7 @@ CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=y
 CONFIG_LEDS_TRIGGER_HEARTBEAT=y
 CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
-CONFIG_RTC_CLASS=m
+CONFIG_RTC_CLASS=y
 CONFIG_RTC_INTF_DEV_UIE_EMUL=y
 CONFIG_RTC_DRV_TEST=m
 CONFIG_RTC_DRV_DS1307=m
diff --git a/arch/powerpc/configs/52xx/pcm030_defconfig b/arch/powerpc/configs/52xx/pcm030_defconfig
index 7f7e4a8..22e7195 100644
--- a/arch/powerpc/configs/52xx/pcm030_defconfig
+++ b/arch/powerpc/configs/52xx/pcm030_defconfig
@@ -85,7 +85,7 @@ CONFIG_USB_OHCI_HCD=m
 CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
 # CONFIG_USB_OHCI_HCD_PCI is not set
 CONFIG_USB_STORAGE=m
-CONFIG_RTC_CLASS=m
+CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_PCF8563=m
 CONFIG_EXT2_FS=m
 CONFIG_EXT3_FS=m
diff --git a/arch/powerpc/configs/ps3_defconfig b/arch/powerpc/configs/ps3_defconfig
index 6472322..185c292 100644
--- a/arch/powerpc/configs/ps3_defconfig
+++ b/arch/powerpc/configs/ps3_defconfig
@@ -141,7 +141,7 @@ CONFIG_USB_EHCI_TT_NEWSCHED=y
 # CONFIG_USB_EHCI_HCD_PPC_OF is not set
 CONFIG_USB_OHCI_HCD=m
 CONFIG_USB_STORAGE=m
-CONFIG_RTC_CLASS=m
+CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_PS3=m
 CONFIG_EXT2_FS=m
 CONFIG_EXT3_FS=m
diff --git a/arch/sh/configs/titan_defconfig b/arch/sh/configs/titan_defconfig
index 0f55891..e2cbd92 100644
--- a/arch/sh/configs/titan_defconfig
+++ b/arch/sh/configs/titan_defconfig
@@ -227,7 +227,7 @@ CONFIG_USB_SERIAL=m
 CONFIG_USB_SERIAL_GENERIC=y
 CONFIG_USB_SERIAL_ARK3116=m
 CONFIG_USB_SERIAL_PL2303=m
-CONFIG_RTC_CLASS=m
+CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_SH=m
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
diff --git a/arch/unicore32/configs/debug_defconfig b/arch/unicore32/configs/debug_defconfig
index b5fbde9..1c367f0 100644
--- a/arch/unicore32/configs/debug_defconfig
+++ b/arch/unicore32/configs/debug_defconfig
@@ -168,7 +168,7 @@ CONFIG_LEDS_TRIGGER_HEARTBEAT=y
 
 #	Real Time Clock
 CONFIG_RTC_LIB=m
-CONFIG_RTC_CLASS=m
+CONFIG_RTC_CLASS=y
 
 ### File systems
 CONFIG_EXT2_FS=m
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH 1/2] ppc/85xx: create a platform node for PCI EDAC device
From: Dmitry Eremin-Solenikov @ 2011-06-01 16:08 UTC (permalink / raw)
  To: bluesmoke-devel, linuxppc-dev, Benjamin Herrenschmidt,
	Paul Mackerras
In-Reply-To: <20110601145911.GA30312@oksana.dev.rtsoft.ru>

As a device for pci node isn't created, create a special platform_device
for PCI EDAC device on MPC85xx.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
---
 arch/powerpc/platforms/85xx/ksi8560.c     |    2 +
 arch/powerpc/platforms/85xx/mpc8536_ds.c  |    2 +
 arch/powerpc/platforms/85xx/mpc85xx_ads.c |    2 +
 arch/powerpc/platforms/85xx/mpc85xx_cds.c |    2 +
 arch/powerpc/platforms/85xx/mpc85xx_ds.c  |    2 +
 arch/powerpc/platforms/85xx/mpc85xx_mds.c |    4 +++
 arch/powerpc/platforms/85xx/mpc85xx_rdb.c |    2 +
 arch/powerpc/platforms/85xx/p1022_ds.c    |    2 +
 arch/powerpc/platforms/85xx/sbc8548.c     |    2 +
 arch/powerpc/platforms/85xx/sbc8560.c     |    2 +
 arch/powerpc/platforms/85xx/socrates.c    |    2 +
 arch/powerpc/platforms/85xx/stx_gp3.c     |    2 +
 arch/powerpc/platforms/85xx/tqm85xx.c     |    2 +
 arch/powerpc/platforms/85xx/xes_mpc85xx.c |    2 +
 arch/powerpc/sysdev/fsl_pci.c             |   30 +++++++++++++++++++++++++++++
 arch/powerpc/sysdev/fsl_pci.h             |    5 ++++
 16 files changed, 65 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/platforms/85xx/ksi8560.c b/arch/powerpc/platforms/85xx/ksi8560.c
index c46f935..288fc4686 100644
--- a/arch/powerpc/platforms/85xx/ksi8560.c
+++ b/arch/powerpc/platforms/85xx/ksi8560.c
@@ -228,6 +228,8 @@ static int __init declare_of_platform_devices(void)
 {
 	of_platform_bus_probe(NULL, of_bus_ids, NULL);
 
+	fsl_add_pci_err();
+
 	return 0;
 }
 machine_device_initcall(ksi8560, declare_of_platform_devices);
diff --git a/arch/powerpc/platforms/85xx/mpc8536_ds.c b/arch/powerpc/platforms/85xx/mpc8536_ds.c
index f79f2f1..cfcbd88 100644
--- a/arch/powerpc/platforms/85xx/mpc8536_ds.c
+++ b/arch/powerpc/platforms/85xx/mpc8536_ds.c
@@ -114,6 +114,8 @@ static struct of_device_id __initdata mpc8536_ds_ids[] = {
 
 static int __init mpc8536_ds_publish_devices(void)
 {
+	fsl_add_pci_err();
+
 	return of_platform_bus_probe(NULL, mpc8536_ds_ids, NULL);
 }
 machine_device_initcall(mpc8536_ds, mpc8536_ds_publish_devices);
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
index 3b2c9bb..6af50d4 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
@@ -235,6 +235,8 @@ static int __init declare_of_platform_devices(void)
 {
 	of_platform_bus_probe(NULL, of_bus_ids, NULL);
 
+	fsl_add_pci_err();
+
 	return 0;
 }
 machine_device_initcall(mpc85xx_ads, declare_of_platform_devices);
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
index 6299a2a..2785c75 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_cds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
@@ -341,6 +341,8 @@ static struct of_device_id __initdata of_bus_ids[] = {
 
 static int __init declare_of_platform_devices(void)
 {
+	fsl_add_pci_err();
+
 	return of_platform_bus_probe(NULL, of_bus_ids, NULL);
 }
 machine_device_initcall(mpc85xx_cds, declare_of_platform_devices);
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ds.c b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
index c7b97f7..2d0a138 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
@@ -228,6 +228,8 @@ static struct of_device_id __initdata mpc85xxds_ids[] = {
 
 static int __init mpc85xxds_publish_devices(void)
 {
+	fsl_add_pci_err();
+
 	return of_platform_bus_probe(NULL, mpc85xxds_ids, NULL);
 }
 machine_device_initcall(mpc8544_ds, mpc85xxds_publish_devices);
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
index 747d1ee..2ff879a 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -455,6 +455,8 @@ static int __init mpc85xx_publish_devices(void)
 	if (machine_is(mpc8569_mds))
 		simple_gpiochip_init("fsl,mpc8569mds-bcsr-gpio");
 
+	fsl_add_pci_err();
+
 	of_platform_bus_probe(NULL, mpc85xx_ids, NULL);
 	mpc85xx_publish_qe_devices();
 
@@ -463,6 +465,8 @@ static int __init mpc85xx_publish_devices(void)
 
 static int __init p1021_publish_devices(void)
 {
+	fsl_add_pci_err();
+
 	of_platform_bus_probe(NULL, p1021_ids, NULL);
 	mpc85xx_publish_qe_devices();
 
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
index 088f30b..511a86c 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
@@ -118,6 +118,8 @@ static struct of_device_id __initdata mpc85xxrdb_ids[] = {
 
 static int __init mpc85xxrdb_publish_devices(void)
 {
+	fsl_add_pci_err();
+
 	return of_platform_bus_probe(NULL, mpc85xxrdb_ids, NULL);
 }
 machine_device_initcall(p2020_rdb, mpc85xxrdb_publish_devices);
diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c
index 7eb5c40..249f302 100644
--- a/arch/powerpc/platforms/85xx/p1022_ds.c
+++ b/arch/powerpc/platforms/85xx/p1022_ds.c
@@ -326,6 +326,8 @@ static struct of_device_id __initdata p1022_ds_ids[] = {
 
 static int __init p1022_ds_publish_devices(void)
 {
+	fsl_add_pci_err();
+
 	return of_platform_bus_probe(NULL, p1022_ds_ids, NULL);
 }
 machine_device_initcall(p1022_ds, p1022_ds_publish_devices);
diff --git a/arch/powerpc/platforms/85xx/sbc8548.c b/arch/powerpc/platforms/85xx/sbc8548.c
index ecdd8c0..f3dcd88 100644
--- a/arch/powerpc/platforms/85xx/sbc8548.c
+++ b/arch/powerpc/platforms/85xx/sbc8548.c
@@ -162,6 +162,8 @@ static int __init declare_of_platform_devices(void)
 {
 	of_platform_bus_probe(NULL, of_bus_ids, NULL);
 
+	fsl_add_pci_err();
+
 	return 0;
 }
 machine_device_initcall(sbc8548, declare_of_platform_devices);
diff --git a/arch/powerpc/platforms/85xx/sbc8560.c b/arch/powerpc/platforms/85xx/sbc8560.c
index d2dfd46..6abdda7 100644
--- a/arch/powerpc/platforms/85xx/sbc8560.c
+++ b/arch/powerpc/platforms/85xx/sbc8560.c
@@ -222,6 +222,8 @@ static int __init declare_of_platform_devices(void)
 {
 	of_platform_bus_probe(NULL, of_bus_ids, NULL);
 
+	fsl_add_pci_err();
+
 	return 0;
 }
 machine_device_initcall(sbc8560, declare_of_platform_devices);
diff --git a/arch/powerpc/platforms/85xx/socrates.c b/arch/powerpc/platforms/85xx/socrates.c
index 747d8fb..d1546a3 100644
--- a/arch/powerpc/platforms/85xx/socrates.c
+++ b/arch/powerpc/platforms/85xx/socrates.c
@@ -104,6 +104,8 @@ static struct of_device_id __initdata socrates_of_bus_ids[] = {
 
 static int __init socrates_publish_devices(void)
 {
+	fsl_add_pci_err();
+
 	return of_platform_bus_probe(NULL, socrates_of_bus_ids, NULL);
 }
 machine_device_initcall(socrates, socrates_publish_devices);
diff --git a/arch/powerpc/platforms/85xx/stx_gp3.c b/arch/powerpc/platforms/85xx/stx_gp3.c
index 5387e9f..b5bf6b0 100644
--- a/arch/powerpc/platforms/85xx/stx_gp3.c
+++ b/arch/powerpc/platforms/85xx/stx_gp3.c
@@ -154,6 +154,8 @@ static int __init declare_of_platform_devices(void)
 {
 	of_platform_bus_probe(NULL, of_bus_ids, NULL);
 
+	fsl_add_pci_err();
+
 	return 0;
 }
 machine_device_initcall(stx_gp3, declare_of_platform_devices);
diff --git a/arch/powerpc/platforms/85xx/tqm85xx.c b/arch/powerpc/platforms/85xx/tqm85xx.c
index 325de77..88d8bb8 100644
--- a/arch/powerpc/platforms/85xx/tqm85xx.c
+++ b/arch/powerpc/platforms/85xx/tqm85xx.c
@@ -183,6 +183,8 @@ static int __init declare_of_platform_devices(void)
 {
 	of_platform_bus_probe(NULL, of_bus_ids, NULL);
 
+	fsl_add_pci_err();
+
 	return 0;
 }
 machine_device_initcall(tqm85xx, declare_of_platform_devices);
diff --git a/arch/powerpc/platforms/85xx/xes_mpc85xx.c b/arch/powerpc/platforms/85xx/xes_mpc85xx.c
index 0125604..3771a2c 100644
--- a/arch/powerpc/platforms/85xx/xes_mpc85xx.c
+++ b/arch/powerpc/platforms/85xx/xes_mpc85xx.c
@@ -187,6 +187,8 @@ static struct of_device_id __initdata xes_mpc85xx_ids[] = {
 
 static int __init xes_mpc85xx_publish_devices(void)
 {
+	fsl_add_pci_err();
+
 	return of_platform_bus_probe(NULL, xes_mpc85xx_ids, NULL);
 }
 machine_device_initcall(xes_mpc8572, xes_mpc85xx_publish_devices);
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 68ca929..8c64b91 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -381,6 +381,36 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary)
 	return 0;
 }
 
+void __init fsl_add_pci_err(void)
+{
+	struct device_node *np;
+
+	for_each_node_by_type(np, "pci") {
+		/* Only PCI, not PCI Express! */
+		if (of_device_is_compatible(np, "fsl,mpc8540-pci")) {
+			struct resource r[2];
+
+			r[0].parent = NULL;
+			r[1].parent = NULL;
+
+			if (of_address_to_resource(np, 0, &r[0])) {
+				printk(KERN_WARNING
+						"Can't get register base for PCI EDAC!\n");
+				continue;
+			}
+			r[0].start += 0xe00;
+
+			if (of_irq_to_resource(np, 0, &r[1]) == NO_IRQ) {
+				printk(KERN_WARNING
+						"Can't get irq for PCI EDAC!\n");
+				continue;
+			}
+			platform_device_register_simple("mpc85xx_pci_err", -1,
+					r, ARRAY_SIZE(r));
+		}
+	}
+}
+
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8548E, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8548, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8543E, quirk_fsl_pcie_header);
diff --git a/arch/powerpc/sysdev/fsl_pci.h b/arch/powerpc/sysdev/fsl_pci.h
index a39ed5c..e7abc37 100644
--- a/arch/powerpc/sysdev/fsl_pci.h
+++ b/arch/powerpc/sysdev/fsl_pci.h
@@ -92,6 +92,11 @@ extern int fsl_add_bridge(struct device_node *dev, int is_primary);
 extern void fsl_pcibios_fixup_bus(struct pci_bus *bus);
 extern int mpc83xx_add_bridge(struct device_node *dev);
 u64 fsl_pci_immrbar_base(struct pci_controller *hose);
+#ifdef CONFIG_PCI
+void fsl_add_pci_err(void);
+#else
+static inline void fsl_add_pci_err(void) {}
+#endif
 
 #endif /* __POWERPC_FSL_PCI_H */
 #endif /* __KERNEL__ */
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH] ppc/85xx: specify interrupt for pq3-localbus devices
From: Dmitry Eremin-Solenikov @ 2011-06-01 15:15 UTC (permalink / raw)
  To: linuxppc-dev, Benjamin Herrenschmidt, Paul Mackerras

fsl-lbc driver requires an interrupt to bind to localbus device.
Populate 85xx boards' dts trees with lbc interrupt info.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
---
 arch/powerpc/boot/dts/mpc8568mds.dts       |    2 ++
 arch/powerpc/boot/dts/socrates.dts         |    2 ++
 arch/powerpc/boot/dts/tqm8540.dts          |    2 ++
 arch/powerpc/boot/dts/tqm8548-bigflash.dts |    2 ++
 arch/powerpc/boot/dts/tqm8548.dts          |    2 ++
 arch/powerpc/boot/dts/tqm8560.dts          |    2 ++
 arch/powerpc/boot/dts/xpedite5200.dts      |    2 ++
 arch/powerpc/boot/dts/xpedite5200_xmon.dts |    2 ++
 8 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/boot/dts/mpc8568mds.dts b/arch/powerpc/boot/dts/mpc8568mds.dts
index 30cf0e0..647daf8 100644
--- a/arch/powerpc/boot/dts/mpc8568mds.dts
+++ b/arch/powerpc/boot/dts/mpc8568mds.dts
@@ -60,6 +60,8 @@
 		compatible = "fsl,mpc8568-localbus", "fsl,pq3-localbus",
 			     "simple-bus";
 		reg = <0xe0005000 0x1000>;
+		interrupt-parent = <&mpic>;
+		interrupts = <19 2>;
 
 		ranges = <0x0 0x0 0xfe000000 0x02000000
 			  0x1 0x0 0xf8000000 0x00008000
diff --git a/arch/powerpc/boot/dts/socrates.dts b/arch/powerpc/boot/dts/socrates.dts
index feb4ef6..38c3540 100644
--- a/arch/powerpc/boot/dts/socrates.dts
+++ b/arch/powerpc/boot/dts/socrates.dts
@@ -240,6 +240,8 @@
 		#address-cells = <2>;
 		#size-cells = <1>;
 		reg = <0xe0005000 0x40>;
+		interrupt-parent = <&mpic>;
+		interrupts = <19 2>;
 
 		ranges = <0 0 0xfc000000 0x04000000
 			  2 0 0xc8000000 0x04000000
diff --git a/arch/powerpc/boot/dts/tqm8540.dts b/arch/powerpc/boot/dts/tqm8540.dts
index e028457..0a4cedb 100644
--- a/arch/powerpc/boot/dts/tqm8540.dts
+++ b/arch/powerpc/boot/dts/tqm8540.dts
@@ -283,6 +283,8 @@
 		compatible = "fsl,mpc8540-localbus", "fsl,pq3-localbus",
 			     "simple-bus";
 		reg = <0xe0005000 0x1000>;
+		interrupt-parent = <&mpic>;
+		interrupts = <19 2>;
 
 		ranges = <0x0 0x0 0xfe000000 0x02000000>;
 
diff --git a/arch/powerpc/boot/dts/tqm8548-bigflash.dts b/arch/powerpc/boot/dts/tqm8548-bigflash.dts
index 5dbb36e..9452c3c 100644
--- a/arch/powerpc/boot/dts/tqm8548-bigflash.dts
+++ b/arch/powerpc/boot/dts/tqm8548-bigflash.dts
@@ -346,6 +346,8 @@
 		#address-cells = <2>;
 		#size-cells = <1>;
 		reg = <0xa0005000 0x100>;	// BRx, ORx, etc.
+		interrupt-parent = <&mpic>;
+		interrupts = <19 2>;
 
 		ranges = <
 			0 0x0 0xfc000000 0x04000000	// NOR FLASH bank 1
diff --git a/arch/powerpc/boot/dts/tqm8548.dts b/arch/powerpc/boot/dts/tqm8548.dts
index a050ae4..619776f 100644
--- a/arch/powerpc/boot/dts/tqm8548.dts
+++ b/arch/powerpc/boot/dts/tqm8548.dts
@@ -346,6 +346,8 @@
 		#address-cells = <2>;
 		#size-cells = <1>;
 		reg = <0xe0005000 0x100>;	// BRx, ORx, etc.
+		interrupt-parent = <&mpic>;
+		interrupts = <19 2>;
 
 		ranges = <
 			0 0x0 0xfc000000 0x04000000	// NOR FLASH bank 1
diff --git a/arch/powerpc/boot/dts/tqm8560.dts b/arch/powerpc/boot/dts/tqm8560.dts
index 22ec39b..7665a16 100644
--- a/arch/powerpc/boot/dts/tqm8560.dts
+++ b/arch/powerpc/boot/dts/tqm8560.dts
@@ -312,6 +312,8 @@
 		#address-cells = <2>;
 		#size-cells = <1>;
 		reg = <0xe0005000 0x100>;	// BRx, ORx, etc.
+		interrupt-parent = <&mpic>;
+		interrupts = <19 2>;
 
 		ranges = <
 			0 0x0 0xfc000000 0x04000000	// NOR FLASH bank 1
diff --git a/arch/powerpc/boot/dts/xpedite5200.dts b/arch/powerpc/boot/dts/xpedite5200.dts
index a0cf53f..c41a80c 100644
--- a/arch/powerpc/boot/dts/xpedite5200.dts
+++ b/arch/powerpc/boot/dts/xpedite5200.dts
@@ -374,6 +374,8 @@
 		#address-cells = <2>;
 		#size-cells = <1>;
 		reg = <0xef005000 0x100>;	// BRx, ORx, etc.
+		interrupt-parent = <&mpic>;
+		interrupts = <19 2>;
 
 		ranges = <
 			0 0x0 0xfc000000 0x04000000	// NOR boot flash
diff --git a/arch/powerpc/boot/dts/xpedite5200_xmon.dts b/arch/powerpc/boot/dts/xpedite5200_xmon.dts
index c5b2975..c0efcbb 100644
--- a/arch/powerpc/boot/dts/xpedite5200_xmon.dts
+++ b/arch/powerpc/boot/dts/xpedite5200_xmon.dts
@@ -378,6 +378,8 @@
 		#address-cells = <2>;
 		#size-cells = <1>;
 		reg = <0xef005000 0x100>;	// BRx, ORx, etc.
+		interrupt-parent = <&mpic>;
+		interrupts = <19 2>;
 
 		ranges = <
 			0 0x0 0xf8000000 0x08000000	// NOR boot flash
-- 
1.7.4.4

^ permalink raw reply related

* Re: [PATCH 1/2] ppc/85xx: create a platform node for PCI EDAC device
From: Anton Vorontsov @ 2011-06-01 14:59 UTC (permalink / raw)
  To: Dmitry Eremin-Solenikov; +Cc: linuxppc-dev, bluesmoke-devel, Paul Mackerras
In-Reply-To: <BANLkTi=xFcZRd4x1FQSKJzmt3A7_tZs+sQ@mail.gmail.com>

On Wed, Jun 01, 2011 at 06:55:35PM +0400, Dmitry Eremin-Solenikov wrote:
> On 6/1/11, Anton Vorontsov <avorontsov@mvista.com> wrote:
> > On Wed, Jun 01, 2011 at 04:28:11PM +0400, Dmitry Eremin-Solenikov wrote:
> > [...]
> >> --- a/arch/powerpc/sysdev/fsl_pci.h
> >> +++ b/arch/powerpc/sysdev/fsl_pci.h
> >> @@ -92,6 +92,7 @@ extern int fsl_add_bridge(struct device_node *dev, int
> >> is_primary);
> >>  extern void fsl_pcibios_fixup_bus(struct pci_bus *bus);
> >>  extern int mpc83xx_add_bridge(struct device_node *dev);
> >>  u64 fsl_pci_immrbar_base(struct pci_controller *hose);
> >> +int fsl_add_pci_err(void);
> >
> > With
> >
> > #ifdef CONFIG_PCI
> > int fsl_add_pci_err(void);
> > #else
> > static inline int fsl_add_pci_err(void) { return -ENODEV; }
> > #endif
> >
> > You won't need endless ifdefs in the board files:
> 
> OK, will redo this patch.

Btw, if you don't check return value of fsl_add_pci_err(), then
it would probably make sense to return void. And if you do
check it somewhere, be sure to include linux/errno.h for
-ENODEV. :-)

Thanks,

-- 
Anton Vorontsov
Email: cbouatmailru@gmail.com

^ permalink raw reply

* Re: [PATCH 1/2] ppc/85xx: create a platform node for PCI EDAC device
From: Dmitry Eremin-Solenikov @ 2011-06-01 14:55 UTC (permalink / raw)
  To: Anton Vorontsov; +Cc: linuxppc-dev, bluesmoke-devel, Paul Mackerras
In-Reply-To: <20110601132519.GA16125@oksana.dev.rtsoft.ru>

On 6/1/11, Anton Vorontsov <avorontsov@mvista.com> wrote:
> On Wed, Jun 01, 2011 at 04:28:11PM +0400, Dmitry Eremin-Solenikov wrote:
> [...]
>> --- a/arch/powerpc/sysdev/fsl_pci.h
>> +++ b/arch/powerpc/sysdev/fsl_pci.h
>> @@ -92,6 +92,7 @@ extern int fsl_add_bridge(struct device_node *dev, int
>> is_primary);
>>  extern void fsl_pcibios_fixup_bus(struct pci_bus *bus);
>>  extern int mpc83xx_add_bridge(struct device_node *dev);
>>  u64 fsl_pci_immrbar_base(struct pci_controller *hose);
>> +int fsl_add_pci_err(void);
>
> With
>
> #ifdef CONFIG_PCI
> int fsl_add_pci_err(void);
> #else
> static inline int fsl_add_pci_err(void) { return -ENODEV; }
> #endif
>
> You won't need endless ifdefs in the board files:

OK, will redo this patch.

>
> #ifdef CONFIG_PCI
> 	fsl_add_pci_err();
> #endif
>
> Also, why not add this call to the fsl_add_bridge(), so you
> won't need to touch board files at all.

Because fsl_add_bridge is called too early, so allocation
of platform device fails.

-- 
With best wishes
Dmitry

^ permalink raw reply

* Re: [PATCH 1/2] ppc/85xx: create a platform node for PCI EDAC device
From: Anton Vorontsov @ 2011-06-01 13:25 UTC (permalink / raw)
  To: Dmitry Eremin-Solenikov; +Cc: linuxppc-dev, bluesmoke-devel, Paul Mackerras
In-Reply-To: <1306931292-2313-1-git-send-email-dbaryshkov@gmail.com>

On Wed, Jun 01, 2011 at 04:28:11PM +0400, Dmitry Eremin-Solenikov wrote:
[...]
> --- a/arch/powerpc/sysdev/fsl_pci.h
> +++ b/arch/powerpc/sysdev/fsl_pci.h
> @@ -92,6 +92,7 @@ extern int fsl_add_bridge(struct device_node *dev, int is_primary);
>  extern void fsl_pcibios_fixup_bus(struct pci_bus *bus);
>  extern int mpc83xx_add_bridge(struct device_node *dev);
>  u64 fsl_pci_immrbar_base(struct pci_controller *hose);
> +int fsl_add_pci_err(void);

With

#ifdef CONFIG_PCI
int fsl_add_pci_err(void);
#else
static inline int fsl_add_pci_err(void) { return -ENODEV; }
#endif

You won't need endless ifdefs in the board files:

#ifdef CONFIG_PCI
	fsl_add_pci_err();
#endif

Also, why not add this call to the fsl_add_bridge(), so you
won't need to touch board files at all.

Thanks,

-- 
Anton Vorontsov
Email: cbouatmailru@gmail.com

^ permalink raw reply

* [PATCH] perf_events: Enable idle state tracing for pseries (ppc64)
From: Deepthi Dharwar @ 2011-06-01 12:35 UTC (permalink / raw)
  To: linuxppc-dev, linux-pm, linux-kernel

Hi,

Please find below a patch, which has perf_events added for pseries (ppc64)
platform in order to emit the trace required for perf timechart. 
It essentially enables perf timechart for pseries platfrom to analyse
power savings events like cpuidle states.

Steps to enable and disable the trace;
1) Mount  debugfs;
   mount -t debugfs none /sys/kernel/debug
2) Then, enable the event using;
    echo 1 > /sys/kernel/debug/tracing/events/power/cpu_idle/enable
3) The output of the trace can be seen in /sys/kernel/debug/tracing/trace
4) To disable the trace use;
    echo 0 > sys/kernel/debug/tracing/events/power/cpu_idle/enable

Trace .svg o/p can be viewed for pseries (ppc64) systems showing various 
cpu-idle states as a part of perf timechart tool. 
References: http://blog.fenrus.org/?p=5

Issue command 'perf timechart record' to enable tracing. 
This generates the trace and records in  perf.data file by default.
One can generate output.svg file by issuing 'perf timechart'. 

Sample o/p from the trace file: 
===============================

State 1 -> Snooze
State 2 -> Cede

# tracer: nop
#
TASK-PID    CPU#    TIMESTAMP  FUNCTION
  | |       |          |         |
<idle>-0     [000]   292.482314: cpu_idle: state=1 cpu_id=0 
						^^ Enter Snooze
<idle>-0     [001]   292.482363: cpu_idle: state=1 cpu_id=1
<idle>-0     [000]   292.492315: cpu_idle: state=4294967295 cpu_id=0
						^^ Exit Snooze 	
<idle>-0     [000]   292.492316: cpu_idle: state=2 cpu_id=0 
						^^ Enter  Cede 
<idle>-0     [001]   292.492364: cpu_idle: state=4294967295 cpu_id=1
<idle>-0     [001]   292.492364: cpu_idle: state=2 cpu_id=1	
<idle>-0     [000]   292.504198: cpu_idle: state=4294967295 cpu_id=0 
						^^Exit Cede 
<idle>-0     [000]   292.504204: cpu_idle: state=1 cpu_id=0
<idle>-0     [001]   292.504921: cpu_idle: state=4294967295 cpu_id=1
<idle>-0     [001]   292.504936: cpu_idle: state=1 cpu_id=1
<idle>-0     [000]   292.514205: cpu_idle: state=4294967295 cpu_id=0    

This patch applies on 2.6.39 and tested on a IBM POWER7 machine.  

-Deepthi

Adding perf events to trace various cpu idle states on ppc64 (pseries) platform.
Signed-off-by: Deepthi Dharwar <deepthi@linux.vnet.ibm.com>

pseries.h |    4 ++++
setup.c   |   14 ++++++++++++++
2 files changed, 18 insertions(+)

Index: linux-2.6.39/arch/powerpc/platforms/pseries/setup.c
===================================================================
--- linux-2.6.39.orig/arch/powerpc/platforms/pseries/setup.c	2011-05-19 00:06:34.000000000 -0400
+++ linux-2.6.39/arch/powerpc/platforms/pseries/setup.c	2011-06-01 07:46:00.000000000 -0400
@@ -39,6 +39,7 @@
 #include <linux/irq.h>
 #include <linux/seq_file.h>
 #include <linux/root_dev.h>
+#include <trace/events/power.h>
 
 #include <asm/mmu.h>
 #include <asm/processor.h>
@@ -582,6 +583,10 @@
 	 * while, do so.
 	 */
 	if (snooze) {
+
+		trace_power_start(POWER_CSTATE, CPU_IDLE_SNOOZE, cpu);
+		trace_cpu_idle(CPU_IDLE_SNOOZE, cpu);
+
 		start_snooze = get_tb() + snooze * tb_ticks_per_usec;
 		local_irq_enable();
 		set_thread_flag(TIF_POLLING_NRFLAG);
@@ -602,9 +607,19 @@
 			goto out;
 	}
 
+	trace_power_end(cpu);
+	trace_cpu_idle(PWR_EVENT_EXIT, cpu);
+
+	trace_power_start(POWER_CSTATE, CPU_IDLE_CEDE, cpu);
+	trace_cpu_idle(CPU_IDLE_CEDE, cpu);
+
 	cede_processor();
 
 out:
+
+	trace_power_end(cpu);
+	trace_cpu_idle(PWR_EVENT_EXIT, cpu);
+
 	HMT_medium();
 	out_purr = mfspr(SPRN_PURR);
 	get_lppaca()->wait_state_cycles += out_purr - in_purr;
Index: linux-2.6.39/arch/powerpc/platforms/pseries/pseries.h
===================================================================
--- linux-2.6.39.orig/arch/powerpc/platforms/pseries/pseries.h	2011-05-19 00:06:34.000000000 -0400
+++ linux-2.6.39/arch/powerpc/platforms/pseries/pseries.h	2011-06-01 07:53:24.000000000 -0400
@@ -12,6 +12,9 @@
 
 #include <linux/interrupt.h>
 
+#define CPU_IDLE_SNOOZE 1
+#define CPU_IDLE_CEDE	 2
+
 struct device_node;
 
 extern void request_event_sources_irqs(struct device_node *np,
@@ -56,4 +59,5 @@
 extern int dlpar_attach_node(struct device_node *);
 extern int dlpar_detach_node(struct device_node *);
 
+
 #endif /* _PSERIES_PSERIES_H */

^ permalink raw reply

* [PATCH 2/2] mpc85xx_edac: adapt to ppc/85xx changes for mpc85xx_pci_err
From: Dmitry Eremin-Solenikov @ 2011-06-01 12:28 UTC (permalink / raw)
  To: bluesmoke-devel, linuxppc-dev, Benjamin Herrenschmidt,
	Paul Mackerras
In-Reply-To: <1306931292-2313-1-git-send-email-dbaryshkov@gmail.com>

Currently mpc85xx_edac fails to bind to PCI host device node. Adapt it
to bind to special platform device mpc85xx_pci_err.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
---
 drivers/edac/mpc85xx_edac.c |   33 ++++++++++++---------------------
 1 files changed, 12 insertions(+), 21 deletions(-)

diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
index c42e483..e91e8fb 100644
--- a/drivers/edac/mpc85xx_edac.c
+++ b/drivers/edac/mpc85xx_edac.c
@@ -204,7 +204,7 @@ static int __devinit mpc85xx_pci_err_probe(struct platform_device *op)
 {
 	struct edac_pci_ctl_info *pci;
 	struct mpc85xx_pci_pdata *pdata;
-	struct resource r;
+	struct resource *r;
 	int res = 0;
 
 	if (!devres_open_group(&op->dev, mpc85xx_pci_err_probe, GFP_KERNEL))
@@ -228,17 +228,15 @@ static int __devinit mpc85xx_pci_err_probe(struct platform_device *op)
 
 	pdata->edac_idx = edac_pci_idx++;
 
-	res = of_address_to_resource(op->dev.of_node, 0, &r);
-	if (res) {
+	r = platform_get_resource(op, IORESOURCE_MEM, 0);
+	if (!r) {
 		printk(KERN_ERR "%s: Unable to get resource for "
 		       "PCI err regs\n", __func__);
+		res = -ENODEV;
 		goto err;
 	}
 
-	/* we only need the error registers */
-	r.start += 0xe00;
-
-	if (!devm_request_mem_region(&op->dev, r.start, resource_size(&r),
+	if (!devm_request_mem_region(&op->dev, r->start, resource_size(r),
 					pdata->name)) {
 		printk(KERN_ERR "%s: Error while requesting mem region\n",
 		       __func__);
@@ -246,7 +244,7 @@ static int __devinit mpc85xx_pci_err_probe(struct platform_device *op)
 		goto err;
 	}
 
-	pdata->pci_vbase = devm_ioremap(&op->dev, r.start, resource_size(&r));
+	pdata->pci_vbase = devm_ioremap(&op->dev, r->start, resource_size(r));
 	if (!pdata->pci_vbase) {
 		printk(KERN_ERR "%s: Unable to setup PCI err regs\n", __func__);
 		res = -ENOMEM;
@@ -273,7 +271,11 @@ static int __devinit mpc85xx_pci_err_probe(struct platform_device *op)
 	}
 
 	if (edac_op_state == EDAC_OPSTATE_INT) {
-		pdata->irq = irq_of_parse_and_map(op->dev.of_node, 0);
+		res =  platform_get_irq(op, 0);
+		if (res >= 0)
+			pdata->irq = res;
+		else
+			goto err2;
 		res = devm_request_irq(&op->dev, pdata->irq,
 				       mpc85xx_pci_isr, IRQF_DISABLED,
 				       "[EDAC] PCI err", pci);
@@ -281,7 +283,6 @@ static int __devinit mpc85xx_pci_err_probe(struct platform_device *op)
 			printk(KERN_ERR
 			       "%s: Unable to requiest irq %d for "
 			       "MPC85xx PCI err\n", __func__, pdata->irq);
-			irq_dispose_mapping(pdata->irq);
 			res = -ENODEV;
 			goto err2;
 		}
@@ -326,16 +327,7 @@ static int mpc85xx_pci_err_remove(struct platform_device *op)
 	return 0;
 }
 
-static struct of_device_id mpc85xx_pci_err_of_match[] = {
-	{
-	 .compatible = "fsl,mpc8540-pcix",
-	 },
-	{
-	 .compatible = "fsl,mpc8540-pci",
-	},
-	{},
-};
-MODULE_DEVICE_TABLE(of, mpc85xx_pci_err_of_match);
+MODULE_ALIAS("platform:mpc85xx_pci_err");
 
 static struct platform_driver mpc85xx_pci_err_driver = {
 	.probe = mpc85xx_pci_err_probe,
@@ -343,7 +335,6 @@ static struct platform_driver mpc85xx_pci_err_driver = {
 	.driver = {
 		.name = "mpc85xx_pci_err",
 		.owner = THIS_MODULE,
-		.of_match_table = mpc85xx_pci_err_of_match,
 	},
 };
 
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH 1/2] ppc/85xx: create a platform node for PCI EDAC device
From: Dmitry Eremin-Solenikov @ 2011-06-01 12:28 UTC (permalink / raw)
  To: bluesmoke-devel, linuxppc-dev, Benjamin Herrenschmidt,
	Paul Mackerras

As a device for pci node isn't created, create a special platform_device
for PCI EDAC device on MPC85xx.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
---
 arch/powerpc/platforms/85xx/ksi8560.c     |    4 +++
 arch/powerpc/platforms/85xx/mpc8536_ds.c  |    4 +++
 arch/powerpc/platforms/85xx/mpc85xx_ads.c |    4 +++
 arch/powerpc/platforms/85xx/mpc85xx_cds.c |    4 +++
 arch/powerpc/platforms/85xx/mpc85xx_ds.c  |    4 +++
 arch/powerpc/platforms/85xx/mpc85xx_mds.c |    8 +++++++
 arch/powerpc/platforms/85xx/mpc85xx_rdb.c |    4 +++
 arch/powerpc/platforms/85xx/p1022_ds.c    |    4 +++
 arch/powerpc/platforms/85xx/sbc8548.c     |    4 +++
 arch/powerpc/platforms/85xx/sbc8560.c     |    4 +++
 arch/powerpc/platforms/85xx/socrates.c    |    4 +++
 arch/powerpc/platforms/85xx/stx_gp3.c     |    4 +++
 arch/powerpc/platforms/85xx/tqm85xx.c     |    4 +++
 arch/powerpc/platforms/85xx/xes_mpc85xx.c |    4 +++
 arch/powerpc/sysdev/fsl_pci.c             |   32 +++++++++++++++++++++++++++++
 arch/powerpc/sysdev/fsl_pci.h             |    1 +
 16 files changed, 93 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/platforms/85xx/ksi8560.c b/arch/powerpc/platforms/85xx/ksi8560.c
index c46f935..0b4e98c 100644
--- a/arch/powerpc/platforms/85xx/ksi8560.c
+++ b/arch/powerpc/platforms/85xx/ksi8560.c
@@ -228,6 +228,10 @@ static int __init declare_of_platform_devices(void)
 {
 	of_platform_bus_probe(NULL, of_bus_ids, NULL);
 
+#ifdef CONFIG_PCI
+	fsl_add_pci_err();
+#endif
+
 	return 0;
 }
 machine_device_initcall(ksi8560, declare_of_platform_devices);
diff --git a/arch/powerpc/platforms/85xx/mpc8536_ds.c b/arch/powerpc/platforms/85xx/mpc8536_ds.c
index f79f2f1..fe4d835 100644
--- a/arch/powerpc/platforms/85xx/mpc8536_ds.c
+++ b/arch/powerpc/platforms/85xx/mpc8536_ds.c
@@ -114,6 +114,10 @@ static struct of_device_id __initdata mpc8536_ds_ids[] = {
 
 static int __init mpc8536_ds_publish_devices(void)
 {
+#ifdef CONFIG_PCI
+	fsl_add_pci_err();
+#endif
+
 	return of_platform_bus_probe(NULL, mpc8536_ds_ids, NULL);
 }
 machine_device_initcall(mpc8536_ds, mpc8536_ds_publish_devices);
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
index 3b2c9bb..d5ef029 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
@@ -235,6 +235,10 @@ static int __init declare_of_platform_devices(void)
 {
 	of_platform_bus_probe(NULL, of_bus_ids, NULL);
 
+#ifdef CONFIG_PCI
+	fsl_add_pci_err();
+#endif
+
 	return 0;
 }
 machine_device_initcall(mpc85xx_ads, declare_of_platform_devices);
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
index 6299a2a..1101608 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_cds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
@@ -341,6 +341,10 @@ static struct of_device_id __initdata of_bus_ids[] = {
 
 static int __init declare_of_platform_devices(void)
 {
+#ifdef CONFIG_PCI
+	fsl_add_pci_err();
+#endif
+
 	return of_platform_bus_probe(NULL, of_bus_ids, NULL);
 }
 machine_device_initcall(mpc85xx_cds, declare_of_platform_devices);
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ds.c b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
index c7b97f7..d17a49f 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
@@ -228,6 +228,10 @@ static struct of_device_id __initdata mpc85xxds_ids[] = {
 
 static int __init mpc85xxds_publish_devices(void)
 {
+#ifdef CONFIG_PCI
+	fsl_add_pci_err();
+#endif
+
 	return of_platform_bus_probe(NULL, mpc85xxds_ids, NULL);
 }
 machine_device_initcall(mpc8544_ds, mpc85xxds_publish_devices);
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
index 747d1ee..856ba60 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -455,6 +455,10 @@ static int __init mpc85xx_publish_devices(void)
 	if (machine_is(mpc8569_mds))
 		simple_gpiochip_init("fsl,mpc8569mds-bcsr-gpio");
 
+#ifdef CONFIG_PCI
+	fsl_add_pci_err();
+#endif
+
 	of_platform_bus_probe(NULL, mpc85xx_ids, NULL);
 	mpc85xx_publish_qe_devices();
 
@@ -463,6 +467,10 @@ static int __init mpc85xx_publish_devices(void)
 
 static int __init p1021_publish_devices(void)
 {
+#ifdef CONFIG_PCI
+	fsl_add_pci_err();
+#endif
+
 	of_platform_bus_probe(NULL, p1021_ids, NULL);
 	mpc85xx_publish_qe_devices();
 
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
index 088f30b..918b7b6 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
@@ -118,6 +118,10 @@ static struct of_device_id __initdata mpc85xxrdb_ids[] = {
 
 static int __init mpc85xxrdb_publish_devices(void)
 {
+#ifdef CONFIG_PCI
+	fsl_add_pci_err();
+#endif
+
 	return of_platform_bus_probe(NULL, mpc85xxrdb_ids, NULL);
 }
 machine_device_initcall(p2020_rdb, mpc85xxrdb_publish_devices);
diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c
index 7eb5c40..e5012e9 100644
--- a/arch/powerpc/platforms/85xx/p1022_ds.c
+++ b/arch/powerpc/platforms/85xx/p1022_ds.c
@@ -326,6 +326,10 @@ static struct of_device_id __initdata p1022_ds_ids[] = {
 
 static int __init p1022_ds_publish_devices(void)
 {
+#ifdef CONFIG_PCI
+	fsl_add_pci_err();
+#endif
+
 	return of_platform_bus_probe(NULL, p1022_ds_ids, NULL);
 }
 machine_device_initcall(p1022_ds, p1022_ds_publish_devices);
diff --git a/arch/powerpc/platforms/85xx/sbc8548.c b/arch/powerpc/platforms/85xx/sbc8548.c
index ecdd8c0..74fb9e6 100644
--- a/arch/powerpc/platforms/85xx/sbc8548.c
+++ b/arch/powerpc/platforms/85xx/sbc8548.c
@@ -162,6 +162,10 @@ static int __init declare_of_platform_devices(void)
 {
 	of_platform_bus_probe(NULL, of_bus_ids, NULL);
 
+#ifdef CONFIG_PCI
+	fsl_add_pci_err();
+#endif
+
 	return 0;
 }
 machine_device_initcall(sbc8548, declare_of_platform_devices);
diff --git a/arch/powerpc/platforms/85xx/sbc8560.c b/arch/powerpc/platforms/85xx/sbc8560.c
index d2dfd46..c58d11f 100644
--- a/arch/powerpc/platforms/85xx/sbc8560.c
+++ b/arch/powerpc/platforms/85xx/sbc8560.c
@@ -222,6 +222,10 @@ static int __init declare_of_platform_devices(void)
 {
 	of_platform_bus_probe(NULL, of_bus_ids, NULL);
 
+#ifdef CONFIG_PCI
+	fsl_add_pci_err();
+#endif
+
 	return 0;
 }
 machine_device_initcall(sbc8560, declare_of_platform_devices);
diff --git a/arch/powerpc/platforms/85xx/socrates.c b/arch/powerpc/platforms/85xx/socrates.c
index 747d8fb..54a17cd 100644
--- a/arch/powerpc/platforms/85xx/socrates.c
+++ b/arch/powerpc/platforms/85xx/socrates.c
@@ -104,6 +104,10 @@ static struct of_device_id __initdata socrates_of_bus_ids[] = {
 
 static int __init socrates_publish_devices(void)
 {
+#ifdef CONFIG_PCI
+	fsl_add_pci_err();
+#endif
+
 	return of_platform_bus_probe(NULL, socrates_of_bus_ids, NULL);
 }
 machine_device_initcall(socrates, socrates_publish_devices);
diff --git a/arch/powerpc/platforms/85xx/stx_gp3.c b/arch/powerpc/platforms/85xx/stx_gp3.c
index 5387e9f..661ba4a 100644
--- a/arch/powerpc/platforms/85xx/stx_gp3.c
+++ b/arch/powerpc/platforms/85xx/stx_gp3.c
@@ -154,6 +154,10 @@ static int __init declare_of_platform_devices(void)
 {
 	of_platform_bus_probe(NULL, of_bus_ids, NULL);
 
+#ifdef CONFIG_PCI
+	fsl_add_pci_err();
+#endif
+
 	return 0;
 }
 machine_device_initcall(stx_gp3, declare_of_platform_devices);
diff --git a/arch/powerpc/platforms/85xx/tqm85xx.c b/arch/powerpc/platforms/85xx/tqm85xx.c
index 325de77..3ef01bc 100644
--- a/arch/powerpc/platforms/85xx/tqm85xx.c
+++ b/arch/powerpc/platforms/85xx/tqm85xx.c
@@ -183,6 +183,10 @@ static int __init declare_of_platform_devices(void)
 {
 	of_platform_bus_probe(NULL, of_bus_ids, NULL);
 
+#ifdef CONFIG_PCI
+	fsl_add_pci_err();
+#endif
+
 	return 0;
 }
 machine_device_initcall(tqm85xx, declare_of_platform_devices);
diff --git a/arch/powerpc/platforms/85xx/xes_mpc85xx.c b/arch/powerpc/platforms/85xx/xes_mpc85xx.c
index 0125604..5e8a09f 100644
--- a/arch/powerpc/platforms/85xx/xes_mpc85xx.c
+++ b/arch/powerpc/platforms/85xx/xes_mpc85xx.c
@@ -187,6 +187,10 @@ static struct of_device_id __initdata xes_mpc85xx_ids[] = {
 
 static int __init xes_mpc85xx_publish_devices(void)
 {
+#ifdef CONFIG_PCI
+	fsl_add_pci_err();
+#endif
+
 	return of_platform_bus_probe(NULL, xes_mpc85xx_ids, NULL);
 }
 machine_device_initcall(xes_mpc8572, xes_mpc85xx_publish_devices);
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 68ca929..52eea53 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -381,6 +381,38 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary)
 	return 0;
 }
 
+int __init fsl_add_pci_err(void)
+{
+	struct device_node *np;
+
+	for_each_node_by_type(np, "pci") {
+		/* Only PCI, not PCI Express! */
+		if (of_device_is_compatible(np, "fsl,mpc8540-pci")) {
+			struct resource r[2];
+
+			r[0].parent = NULL;
+			r[1].parent = NULL;
+
+			if (of_address_to_resource(np, 0, &r[0])) {
+				printk(KERN_WARNING
+						"Can't get register base for PCI EDAC!\n");
+				return -ENOMEM;
+			}
+			r[0].start += 0xe00;
+
+			if (of_irq_to_resource(np, 0, &r[1]) == NO_IRQ) {
+				printk(KERN_WARNING
+						"Can't get irq for PCI EDAC!\n");
+				return -ENOMEM;
+			}
+			platform_device_register_simple("mpc85xx_pci_err", -1,
+					r, ARRAY_SIZE(r));
+		}
+	}
+
+	return 0;
+}
+
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8548E, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8548, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8543E, quirk_fsl_pcie_header);
diff --git a/arch/powerpc/sysdev/fsl_pci.h b/arch/powerpc/sysdev/fsl_pci.h
index a39ed5c..2e1950b 100644
--- a/arch/powerpc/sysdev/fsl_pci.h
+++ b/arch/powerpc/sysdev/fsl_pci.h
@@ -92,6 +92,7 @@ extern int fsl_add_bridge(struct device_node *dev, int is_primary);
 extern void fsl_pcibios_fixup_bus(struct pci_bus *bus);
 extern int mpc83xx_add_bridge(struct device_node *dev);
 u64 fsl_pci_immrbar_base(struct pci_controller *hose);
+int fsl_add_pci_err(void);
 
 #endif /* __POWERPC_FSL_PCI_H */
 #endif /* __KERNEL__ */
-- 
1.7.4.4

^ permalink raw reply related

* Re: [PATCH] powerpc/fsl: Use irq_data_get_irq_handler_data() in chain handler
From: Thomas Gleixner @ 2011-06-01 10:14 UTC (permalink / raw)
  To: Geert Uytterhoeven; +Cc: Linux/PPC Development, Linux Kernel Development
In-Reply-To: <alpine.DEB.2.00.1106011042080.30334@ayla.of.borg>

On Wed, 1 Jun 2011, Geert Uytterhoeven wrote:

> If you already have a pointer to a struct irq_data , it's more efficient
> to use irq_data_get_irq_handler_data().
> irq_get_handler_data() has to look up the struct irq_desc pointer again,
> which was already passed to the chain handler.
> 
> Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
> ---
> Completely untested, not even compile-tested.
> If this is correct, there are probably more of these?
> 
>  arch/powerpc/sysdev/fsl_msi.c |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
> index 92e7833..9b92c82 100644
> --- a/arch/powerpc/sysdev/fsl_msi.c
> +++ b/arch/powerpc/sysdev/fsl_msi.c
> @@ -193,7 +193,7 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
>  	u32 have_shift = 0;
>  	struct fsl_msi_cascade_data *cascade_data;
>  
> -	cascade_data = irq_get_handler_data(irq);
> +	cascade_data = irq_data_get_irq_handler_data(idata);

  cascade_data = irq_desc_get_handler_data(desc);

Might compile and work :)

^ permalink raw reply

* [RFT][PATCH 3.0] ssb: fix PCI(e) driver regression causing oops on PCI cards
From: Rafał Miłecki @ 2011-06-01  9:01 UTC (permalink / raw)
  To: Andreas Schwab, linux-wireless, John W. Linville,
	Michael Büsch
  Cc: linuxppc-dev, Rafał Miłecki, b43-dev

We were incorrectly executing PCIe specific workarounds on PCI cards.
This resulted in:
Machine check in kernel mode.
Caused by (from SRR1=149030): Transfer error ack signal
Oops: Machine check, sig: 7 [#1]

Reported-by: Andreas Schwab <schwab@linux-m68k.org>
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
---
 drivers/ssb/driver_pcicore.c |   10 ++++++----
 1 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c
index 82feb34..2a20dab 100644
--- a/drivers/ssb/driver_pcicore.c
+++ b/drivers/ssb/driver_pcicore.c
@@ -539,10 +539,12 @@ void ssb_pcicore_init(struct ssb_pcicore *pc)
 	if (!pc->hostmode)
 		ssb_pcicore_init_clientmode(pc);
 
-	/* Additional always once-executed workarounds */
-	ssb_pcicore_serdes_workaround(pc);
-	/* TODO: ASPM */
-	/* TODO: Clock Request Update */
+	/* Additional PCIe always once-executed workarounds */
+	if (dev->id.coreid == SSB_DEV_PCIE) {
+		ssb_pcicore_serdes_workaround(pc);
+		/* TODO: ASPM */
+		/* TODO: Clock Request Update */
+	}
 }
 
 static u32 ssb_pcie_read(struct ssb_pcicore *pc, u32 address)
-- 
1.7.1

^ permalink raw reply related

* [PATCH] powerpc/fsl: Use irq_data_get_irq_handler_data() in chain handler
From: Geert Uytterhoeven @ 2011-06-01  8:44 UTC (permalink / raw)
  To: Linux/PPC Development; +Cc: Thomas Gleixner, Linux Kernel Development

If you already have a pointer to a struct irq_data , it's more efficient
to use irq_data_get_irq_handler_data().
irq_get_handler_data() has to look up the struct irq_desc pointer again,
which was already passed to the chain handler.

Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
---
Completely untested, not even compile-tested.
If this is correct, there are probably more of these?

 arch/powerpc/sysdev/fsl_msi.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
index 92e7833..9b92c82 100644
--- a/arch/powerpc/sysdev/fsl_msi.c
+++ b/arch/powerpc/sysdev/fsl_msi.c
@@ -193,7 +193,7 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
 	u32 have_shift = 0;
 	struct fsl_msi_cascade_data *cascade_data;
 
-	cascade_data = irq_get_handler_data(irq);
+	cascade_data = irq_data_get_irq_handler_data(idata);
 	msi_data = cascade_data->msi_data;
 
 	raw_spin_lock(&desc->lock);
-- 
1.7.0.4

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
							    -- Linus Torvalds

^ permalink raw reply related

* [088/165] seqlock: Dont smp_rmb in seqlock reader spin loop
From: Greg KH @ 2011-06-01  8:10 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Nick Piggin, Eric Dumazet, torvalds, Greg Kroah-Hartman,
	Milton Miller, Andi Kleen, Thomas Gleixner, Anton Blanchard, akpm,
	Paul McKenney, linuxppc-dev, stable-review, alan
In-Reply-To: <20110601081349.GA10017@kroah.com>

2.6.39-stable review patch.  If anyone has any objections, please let us know.

------------------
Content-Length: 2553
Lines: 71

From: Milton Miller <miltonm@bga.com>

commit 5db1256a5131d3b133946fa02ac9770a784e6eb2 upstream.

Move the smp_rmb after cpu_relax loop in read_seqlock and add
ACCESS_ONCE to make sure the test and return are consistent.

A multi-threaded core in the lab didn't like the update
from 2.6.35 to 2.6.36, to the point it would hang during
boot when multiple threads were active.  Bisection showed
af5ab277ded04bd9bc6b048c5a2f0e7d70ef0867 (clockevents:
Remove the per cpu tick skew) as the culprit and it is
supported with stack traces showing xtime_lock waits including
tick_do_update_jiffies64 and/or update_vsyscall.

Experimentation showed the combination of cpu_relax and smp_rmb
was significantly slowing the progress of other threads sharing
the core, and this patch is effective in avoiding the hang.

A theory is the rmb is affecting the whole core while the
cpu_relax is causing a resource rebalance flush, together they
cause an interfernce cadance that is unbroken when the seqlock
reader has interrupts disabled.

At first I was confused why the refactor in
3c22cd5709e8143444a6d08682a87f4c57902df3 (kernel: optimise
seqlock) didn't affect this patch application, but after some
study that affected seqcount not seqlock. The new seqcount was
not factored back into the seqlock.  I defer that the future.

While the removal of the timer interrupt offset created
contention for the xtime lock while a cpu does the
additonal work to update the system clock, the seqlock
implementation with the tight rmb spin loop goes back much
further, and is just waiting for the right trigger.

Signed-off-by: Milton Miller <miltonm@bga.com>
Cc: <linuxppc-dev@lists.ozlabs.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: Nick Piggin <npiggin@kernel.dk>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Anton Blanchard <anton@samba.org>
Cc: Paul McKenney <paulmck@linux.vnet.ibm.com>
Acked-by: Eric Dumazet <eric.dumazet@gmail.com>
Link: http://lkml.kernel.org/r/%3Cseqlock-rmb%40mdm.bga.com%3E
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
 include/linux/seqlock.h |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

--- a/include/linux/seqlock.h
+++ b/include/linux/seqlock.h
@@ -88,12 +88,12 @@ static __always_inline unsigned read_seq
 	unsigned ret;
 
 repeat:
-	ret = sl->sequence;
-	smp_rmb();
+	ret = ACCESS_ONCE(sl->sequence);
 	if (unlikely(ret & 1)) {
 		cpu_relax();
 		goto repeat;
 	}
+	smp_rmb();
 
 	return ret;
 }

^ permalink raw reply

* [086/146] seqlock: Dont smp_rmb in seqlock reader spin loop
From: Greg KH @ 2011-06-01  8:00 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Nick Piggin, Eric Dumazet, torvalds, Greg Kroah-Hartman,
	Milton Miller, Andi Kleen, Thomas Gleixner, Anton Blanchard, akpm,
	Paul McKenney, linuxppc-dev, stable-review, alan
In-Reply-To: <20110601080606.GA522@kroah.com>

2.6.38-stable review patch.  If anyone has any objections, please let us know.

------------------

From: Milton Miller <miltonm@bga.com>

commit 5db1256a5131d3b133946fa02ac9770a784e6eb2 upstream.

Move the smp_rmb after cpu_relax loop in read_seqlock and add
ACCESS_ONCE to make sure the test and return are consistent.

A multi-threaded core in the lab didn't like the update
from 2.6.35 to 2.6.36, to the point it would hang during
boot when multiple threads were active.  Bisection showed
af5ab277ded04bd9bc6b048c5a2f0e7d70ef0867 (clockevents:
Remove the per cpu tick skew) as the culprit and it is
supported with stack traces showing xtime_lock waits including
tick_do_update_jiffies64 and/or update_vsyscall.

Experimentation showed the combination of cpu_relax and smp_rmb
was significantly slowing the progress of other threads sharing
the core, and this patch is effective in avoiding the hang.

A theory is the rmb is affecting the whole core while the
cpu_relax is causing a resource rebalance flush, together they
cause an interfernce cadance that is unbroken when the seqlock
reader has interrupts disabled.

At first I was confused why the refactor in
3c22cd5709e8143444a6d08682a87f4c57902df3 (kernel: optimise
seqlock) didn't affect this patch application, but after some
study that affected seqcount not seqlock. The new seqcount was
not factored back into the seqlock.  I defer that the future.

While the removal of the timer interrupt offset created
contention for the xtime lock while a cpu does the
additonal work to update the system clock, the seqlock
implementation with the tight rmb spin loop goes back much
further, and is just waiting for the right trigger.

Signed-off-by: Milton Miller <miltonm@bga.com>
Cc: <linuxppc-dev@lists.ozlabs.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: Nick Piggin <npiggin@kernel.dk>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Anton Blanchard <anton@samba.org>
Cc: Paul McKenney <paulmck@linux.vnet.ibm.com>
Acked-by: Eric Dumazet <eric.dumazet@gmail.com>
Link: http://lkml.kernel.org/r/%3Cseqlock-rmb%40mdm.bga.com%3E
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
 include/linux/seqlock.h |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

--- a/include/linux/seqlock.h
+++ b/include/linux/seqlock.h
@@ -88,12 +88,12 @@ static __always_inline unsigned read_seq
 	unsigned ret;
 
 repeat:
-	ret = sl->sequence;
-	smp_rmb();
+	ret = ACCESS_ONCE(sl->sequence);
 	if (unlikely(ret & 1)) {
 		cpu_relax();
 		goto repeat;
 	}
+	smp_rmb();
 
 	return ret;
 }

^ permalink raw reply

* Re: [PATCH v2 0/12] Hypervisor-mode KVM on POWER7
From: Olof Johansson @ 2011-06-01  5:31 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: kvm-ppc, linuxppc-dev, Alexander Graf, kvm
In-Reply-To: <20110531123521.GL2505@brick.ozlabs.ibm.com>

On Tue, May 31, 2011 at 5:35 AM, Paul Mackerras <paulus@samba.org> wrote:
> On Tue, May 31, 2011 at 12:40:31PM +0200, Alexander Graf wrote:
>
>> Thinking about the testability of this a bit more ... how much
>> effort would it be to get this code running on a 970MP with SLOF?
>> There should only be a few POWER7 specific pieces, right?
>
> Do you have a 970MP that has a usable hypervisor mode, i.e. not an
> Apple machine? =A0The 970s in Apple machines have the HV hard-wired to
> 1, which means they do have a hypervisor mode but it isn't any use.
>
> If you do have such a machine, then we would have to look at some
> details like the instruction sequence for the partition switch, and
> make sure we don't try to use SMT4 mode. =A0Also, I believe we will have
> to flush the TLB on partition switches, since Power processors prior
> to POWER7 didn't tag the TLB entries with the partition ID.
>
> So it should be quite feasible if you have a non-Apple machine.
> I will check whether the 970MP machines that Terrasoft were
> distributing would be suitable. =A0We have one of them in the lab.

PA6T is closer to power7 than 970 when it comes to hypervisor features
(i.e. VRMA, LPCR, mediated interrupts are all available there). I can
try to find some old hardware if there's any interest from anyone to
use it.

Of course, there isn't much of a roadmap. But 970 isn't really going
anywhere either. :)


-Olof

^ permalink raw reply

* Re: [PATCH v2 0/12] Hypervisor-mode KVM on POWER7
From: Paul Mackerras @ 2011-06-01  5:20 UTC (permalink / raw)
  To: Alexander Graf; +Cc: linuxppc-dev, kvm-ppc, kvm
In-Reply-To: <A857E6BF-D88C-46E3-BF09-268A43B7F7CF@suse.de>

On Tue, May 31, 2011 at 02:50:20PM +0200, Alexander Graf wrote:
> 
> On 31.05.2011, at 14:35, Paul Mackerras wrote:
> 
> > On Tue, May 31, 2011 at 12:40:31PM +0200, Alexander Graf wrote:
> > 
> >> Thinking about the testability of this a bit more ... how much
> >> effort would it be to get this code running on a 970MP with SLOF?
> >> There should only be a few POWER7 specific pieces, right?
> > 
> > Do you have a 970MP that has a usable hypervisor mode, i.e. not an
> > Apple machine?  The 970s in Apple machines have the HV hard-wired to
> > 1, which means they do have a hypervisor mode but it isn't any use.
> > 
> > If you do have such a machine, then we would have to look at some
> > details like the instruction sequence for the partition switch, and
> > make sure we don't try to use SMT4 mode.  Also, I believe we will have
> > to flush the TLB on partition switches, since Power processors prior
> > to POWER7 didn't tag the TLB entries with the partition ID.
> > 
> > So it should be quite feasible if you have a non-Apple machine.
> > I will check whether the 970MP machines that Terrasoft were
> > distributing would be suitable.  We have one of them in the lab.
> 
> That's the one I was thinking of and yes, I have one available. That
> way I could test 99% of your code, you don't have to release
> hardware, and everyone's happy :).

I checked our YDL PowerStation and it does appear to have a usable
hypervisor mode. :)

As Jimi X pointed out, there are a few things that POWER7 has that 970
doesn't.  In particular the lack of VRMA mode means that we will have
to find 64MB of physically contiguous memory, aligned on a 64MB
address boundary, for the real mode area (RMO) for the guest.  64MB is
the smallest RMO size that the 970 supports; it also supports 128MB,
256MB, 1GB, 16GB and 256GB.  I think we'll have to reserve some memory
at boot.  We may get away with bumping up CONFIG_FORCE_MAX_ZONEORDER,
but relying on allocating a physically contiguous 64MB at runtime
seems somewhat fragile.  Also, we'll need some qemu changes since it
won't be able to allocate the RMO itself.

The other thing is that we have to flush the TLB on every partitions
switch, plus make sure that we're not switching the partition ID while
any other cpu in the same partition is doing a tlbie or tlbsync.
Still, it should all be doable.

Paul.

^ permalink raw reply

* Re: [PATCH 10/13] kvm/powerpc: Add support for Book3S processors in hypervisor mode
From: Paul Mackerras @ 2011-06-01  5:11 UTC (permalink / raw)
  To: Segher Boessenkool
  Cc: kvm-ppc, Linuxppc-dev, Alexander Graf, KVM list, Jimi Xenidis
In-Reply-To: <c71b71560e43813012b6f293230dc78e@kernel.crashing.org>

On Wed, Jun 01, 2011 at 12:34:43AM +0200, Segher Boessenkool wrote:

> There's a loop of 128 iterations of 3 insns.
> 
> I'm not saying it is actually bad, just that that 50 is slightly off ;-)

That would be the TLB invalidation.  On POWER7 we only need to do that
if the virtual cpu last ran on a different physical cpu, or if this
physical cpu last ran a different virtual cpu in the same partition.
So hopefully we don't have to do it very often.

The reason we have to do it in that case is to allow the optimization
where we use tlbiel for TLB invalidations if the guest claims that
the translation being invalidated was only ever used on this virtual
cpu.  That means that we have to guard against stale TLB entries left
behind when a virtual cpu moves from one physical cpu to another.

Paul.

^ permalink raw reply

* Hooking up SM501 on TQM5200 (MPC5200) board via device tree?
From: Josh Triplett @ 2011-06-01  5:07 UTC (permalink / raw)
  To: linux-kernel, devicetree-discuss, linuxppc-dev; +Cc: Jamey Sharp

We have a TQM5200 board, which has GPIO lines hooked up to an SM501.
I've managed to come up with the following patch to the tqm5200 device
tree, which manages to convince the sm501 driver to attach an sm501-fb:

--- a/arch/powerpc/boot/dts/tqm5200.dts  2009-11-23 03:13:27.000000000 -0800
+++ b/arch/powerpc/boot/dts/tqm5200.dts  2011-05-31 22:00:28.000580627 -0700
@@ -177,7 +177,8 @@
                compatible = "fsl,mpc5200-lpb","simple-bus";
                #address-cells = <2>;
                #size-cells = <1>;
-               ranges = <0 0 0xfc000000 0x02000000>;
+               ranges = <0 0 0xfc000000 0x02000000
+                         1 0 0xe0000000 0x04000000>;
 
                flash@0,0 {
                        compatible = "cfi-flash";
@@ -187,6 +188,13 @@
                        #size-cells = <1>;
                        #address-cells = <1>;
                };
+
+               display@1,0 {
+                       compatible = "smi,sm501";
+                       reg = <1 0x00000000 0x00800000
+                              1 0x03e00000 0x00200000>;
+                       interrupts = <1 1 3>;
+               };
        };
 
        pci@f0000d00 {


However, this doesn't hook up the sm501-gpio bits.  Reading the sm501
driver carefully, it looks like it only hooks up sm501-gpio if it has
platform_data available which sets some flags and other information.
So, if I understand correctly, hooking up sm501-gpio would require
adding functionality the driver to get the GPIO information from the
device tree in preference to the platform_data, if available, and fall
back to the platform_data for existing users?

What should the necessary device tree properties look like to replace
sm501_initdata?

- Josh Triplett

^ permalink raw reply

* RE: [PATCH 0/1] ppc4xx: Fix PCIe scanning for the 460SX
From: Tirumala Marri @ 2011-05-31 21:27 UTC (permalink / raw)
  To: Ayman El-Khashab, Benjamin Herrenschmidt; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <20110527165108.GA1752@crust.elkhashab.com>

Not sure how I would know --  But with my eiger kit, I got a
cd from amcc that had a patched 2.6.30 or something kernel
in it to support the 460SX.  The pci code was basically
subverted by adding a "port->link=1" at the very end of the
link check to always force it to succeed.  However this code
never appeared in the public git repositories, so I am not
sure how the 460SX functioned (if it ever did) since the
link check that is in there now can't work on that SOC.


[marri]I don't know what PCI-E devices you use. We use E1000
As a device for testing. Link-up was working before the submission.
There were some changes happened afterwards to the common code
Which seems to affected all 4xx devices. I will try latest code
On our other SoCs.


I took care of that in my patch.  Basically it let the
system go to gen-2 speeds and negotiate down.
[marri] Great thx.

^ permalink raw reply

* RE: [PATCH 0/1] ppc4xx: Fix PCIe scanning for the 460SX
From: Tirumala Marri @ 2011-05-31 21:18 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: Paul Mackerras, Ayman El-Khashab, linuxppc-dev
In-Reply-To: <1306208412.7481.214.camel@pasglop>

The interesting question of course is whether that 460SX stuff is the
same as what we're using internally :-)
[marri] Sometimes open-source and internal releases may not be the same
Because of open-source standards.

Can we fix that ?
[marri] Sure I will take a look at it.

^ permalink raw reply

* Re: 3.0-rc1: powerpc hangs at Kernel virtual memory layout
From: Benjamin Herrenschmidt @ 2011-06-01  3:49 UTC (permalink / raw)
  To: Christian Kujau; +Cc: Linus Torvalds, linux ppc dev, LKML
In-Reply-To: <alpine.DEB.2.01.1105311959000.21697@trent.utfs.org>

On Tue, 2011-05-31 at 20:02 -0700, Christian Kujau wrote:
> (Cc'in Linus)
> 
> On Tue, 31 May 2011 at 17:48, Christian Kujau wrote:
> > In the meantime, "git bisect" behaves kinda weird, I don't know what went 
> > wrong here:
> > 
> >  $ git bisect start
> >  $ git bisect good         # Linux 2.6.39
> >  $ git bisect bad v3.0-rc1 # Linux 3.0-rc1
> >  $ git bisect bad          # c44dead70a...
> >  $ git bisect bad          # d93515611b..
> > 
> > ...yet the ./Makefile shows[0] that I'm already way behind: 2.6.39-rc2. 
> > Maybe "git bisect" got confused with that whole 2.6.x -> 3.0 renaming?
> 
> Hm, I tried again, from a clean v3.0-rc1 (git reset --hard), but after the 
> 2nd "git bad" I'm at 2.6.39-rc2 again - while I /should/ be somwhere 
> inbetween v2.6.39..v3.0-rc1, right?

Kernel version is totally irrelevant when bisecting. You are not walking
through a linear series of patches but a complex tree of merges which
might have forked off different versions in the first place.

Cheers,
Ben.

^ 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