LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 02/14] spufs: scheduler support for NUMA.
From: Arnd Bergmann @ 2006-10-04 15:26 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: Arnd Bergmann, linuxppc-dev, cbe-oss-dev, linux-kernel
In-Reply-To: <20061004152610.151599000@dyn-9-152-242-103.boeblingen.de.ibm.com>

From: Mark Nutter <mnutter@us.ibm.com>

This patch adds NUMA support to the the spufs scheduler.

The new arch/powerpc/platforms/cell/spufs/sched.c is greatly
simplified, in an attempt to reduce complexity while adding
support for NUMA scheduler domains.  SPUs are allocated starting 
from the calling thread's node, moving to others as supported by 
current->cpus_allowed.  Preemption is gone as it was buggy, but 
should be re-enabled in another patch when stable.

The new arch/powerpc/platforms/cell/spu_base.c maintains idle 
lists on a per-node basis, and allows caller to specify which
node(s) an SPU should be allocated from, while passing -1 tells
spu_alloc() that any node is allowed.

Since the patch removes the currently implemented preemptive
scheduling, it is technically a regression, but practically
all users have since migrated to this version, as it is
part of the IBM SDK and the yellowdog distribution, so there
is not much point holding it back while the new preemptive
scheduling patch gets delayed further.

Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>

Index: linux-2.6/arch/powerpc/platforms/cell/spu_base.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/spu_base.c
+++ linux-2.6/arch/powerpc/platforms/cell/spu_base.c
@@ -317,7 +317,7 @@ static void spu_free_irqs(struct spu *sp
 		free_irq(spu->irqs[2], spu);
 }
 
-static LIST_HEAD(spu_list);
+static struct list_head spu_list[MAX_NUMNODES];
 static DEFINE_MUTEX(spu_mutex);
 
 static void spu_init_channels(struct spu *spu)
@@ -354,32 +354,42 @@ static void spu_init_channels(struct spu
 	}
 }
 
-struct spu *spu_alloc(void)
+struct spu *spu_alloc_node(int node)
 {
-	struct spu *spu;
+	struct spu *spu = NULL;
 
 	mutex_lock(&spu_mutex);
-	if (!list_empty(&spu_list)) {
-		spu = list_entry(spu_list.next, struct spu, list);
+	if (!list_empty(&spu_list[node])) {
+		spu = list_entry(spu_list[node].next, struct spu, list);
 		list_del_init(&spu->list);
-		pr_debug("Got SPU %x %d\n", spu->isrc, spu->number);
-	} else {
-		pr_debug("No SPU left\n");
-		spu = NULL;
+		pr_debug("Got SPU %x %d %d\n",
+			 spu->isrc, spu->number, spu->node);
+		spu_init_channels(spu);
 	}
 	mutex_unlock(&spu_mutex);
 
-	if (spu)
-		spu_init_channels(spu);
+	return spu;
+}
+EXPORT_SYMBOL_GPL(spu_alloc_node);
+
+struct spu *spu_alloc(void)
+{
+	struct spu *spu = NULL;
+	int node;
+
+	for (node = 0; node < MAX_NUMNODES; node++) {
+		spu = spu_alloc_node(node);
+		if (spu)
+			break;
+	}
 
 	return spu;
 }
-EXPORT_SYMBOL_GPL(spu_alloc);
 
 void spu_free(struct spu *spu)
 {
 	mutex_lock(&spu_mutex);
-	list_add_tail(&spu->list, &spu_list);
+	list_add_tail(&spu->list, &spu_list[spu->node]);
 	mutex_unlock(&spu_mutex);
 }
 EXPORT_SYMBOL_GPL(spu_free);
@@ -712,7 +722,7 @@ static int __init create_spu(struct devi
 	if (ret)
 		goto out_free_irqs;
 
-	list_add(&spu->list, &spu_list);
+	list_add(&spu->list, &spu_list[spu->node]);
 	mutex_unlock(&spu_mutex);
 
 	pr_debug(KERN_DEBUG "Using SPE %s %02x %p %p %p %p %d\n",
@@ -745,9 +755,13 @@ static void destroy_spu(struct spu *spu)
 static void cleanup_spu_base(void)
 {
 	struct spu *spu, *tmp;
+	int node;
+
 	mutex_lock(&spu_mutex);
-	list_for_each_entry_safe(spu, tmp, &spu_list, list)
-		destroy_spu(spu);
+	for (node = 0; node < MAX_NUMNODES; node++) {
+		list_for_each_entry_safe(spu, tmp, &spu_list[node], list)
+			destroy_spu(spu);
+	}
 	mutex_unlock(&spu_mutex);
 	sysdev_class_unregister(&spu_sysdev_class);
 }
@@ -756,13 +770,16 @@ module_exit(cleanup_spu_base);
 static int __init init_spu_base(void)
 {
 	struct device_node *node;
-	int ret;
+	int i, ret;
 
 	/* create sysdev class for spus */
 	ret = sysdev_class_register(&spu_sysdev_class);
 	if (ret)
 		return ret;
 
+	for (i = 0; i < MAX_NUMNODES; i++)
+		INIT_LIST_HEAD(&spu_list[i]);
+
 	ret = -ENODEV;
 	for (node = of_find_node_by_type(NULL, "spe");
 			node; node = of_find_node_by_type(node, "spe")) {
Index: linux-2.6/arch/powerpc/platforms/cell/spufs/sched.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/sched.c
+++ linux-2.6/arch/powerpc/platforms/cell/spufs/sched.c
@@ -3,11 +3,7 @@
  * Copyright (C) IBM 2005
  * Author: Mark Nutter <mnutter@us.ibm.com>
  *
- * SPU scheduler, based on Linux thread priority.  For now use
- * a simple "cooperative" yield model with no preemption.  SPU
- * scheduling will eventually be preemptive: When a thread with
- * a higher static priority gets ready to run, then an active SPU
- * context will be preempted and returned to the waitq.
+ * 2006-03-31	NUMA domains added.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -37,6 +33,8 @@
 #include <linux/smp_lock.h>
 #include <linux/stddef.h>
 #include <linux/unistd.h>
+#include <linux/numa.h>
+#include <linux/mutex.h>
 
 #include <asm/io.h>
 #include <asm/mmu_context.h>
@@ -49,125 +47,38 @@
 
 #define SPU_BITMAP_SIZE (((MAX_PRIO+BITS_PER_LONG)/BITS_PER_LONG)+1)
 struct spu_prio_array {
-	atomic_t nr_blocked;
 	unsigned long bitmap[SPU_BITMAP_SIZE];
 	wait_queue_head_t waitq[MAX_PRIO];
+	struct list_head active_list[MAX_NUMNODES];
+	struct mutex active_mutex[MAX_NUMNODES];
 };
 
-/* spu_runqueue - This is the main runqueue data structure for SPUs. */
-struct spu_runqueue {
-	struct semaphore sem;
-	unsigned long nr_active;
-	unsigned long nr_idle;
-	unsigned long nr_switches;
-	struct list_head active_list;
-	struct list_head idle_list;
-	struct spu_prio_array prio;
-};
-
-static struct spu_runqueue *spu_runqueues = NULL;
-
-static inline struct spu_runqueue *spu_rq(void)
-{
-	/* Future: make this a per-NODE array,
-	 * and use cpu_to_node(smp_processor_id())
-	 */
-	return spu_runqueues;
-}
-
-static inline struct spu *del_idle(struct spu_runqueue *rq)
-{
-	struct spu *spu;
-
-	BUG_ON(rq->nr_idle <= 0);
-	BUG_ON(list_empty(&rq->idle_list));
-	/* Future: Move SPU out of low-power SRI state. */
-	spu = list_entry(rq->idle_list.next, struct spu, sched_list);
-	list_del_init(&spu->sched_list);
-	rq->nr_idle--;
-	return spu;
-}
-
-static inline void del_active(struct spu_runqueue *rq, struct spu *spu)
-{
-	BUG_ON(rq->nr_active <= 0);
-	BUG_ON(list_empty(&rq->active_list));
-	list_del_init(&spu->sched_list);
-	rq->nr_active--;
-}
-
-static inline void add_idle(struct spu_runqueue *rq, struct spu *spu)
-{
-	/* Future: Put SPU into low-power SRI state. */
-	list_add_tail(&spu->sched_list, &rq->idle_list);
-	rq->nr_idle++;
-}
-
-static inline void add_active(struct spu_runqueue *rq, struct spu *spu)
-{
-	rq->nr_active++;
-	rq->nr_switches++;
-	list_add_tail(&spu->sched_list, &rq->active_list);
-}
-
-static void prio_wakeup(struct spu_runqueue *rq)
-{
-	if (atomic_read(&rq->prio.nr_blocked) && rq->nr_idle) {
-		int best = sched_find_first_bit(rq->prio.bitmap);
-		if (best < MAX_PRIO) {
-			wait_queue_head_t *wq = &rq->prio.waitq[best];
-			wake_up_interruptible_nr(wq, 1);
-		}
-	}
-}
-
-static void prio_wait(struct spu_runqueue *rq, struct spu_context *ctx,
-		      u64 flags)
-{
-	int prio = current->prio;
-	wait_queue_head_t *wq = &rq->prio.waitq[prio];
-	DEFINE_WAIT(wait);
-
-	__set_bit(prio, rq->prio.bitmap);
-	atomic_inc(&rq->prio.nr_blocked);
-	prepare_to_wait_exclusive(wq, &wait, TASK_INTERRUPTIBLE);
-	if (!signal_pending(current)) {
-		up(&rq->sem);
-		up_write(&ctx->state_sema);
-		pr_debug("%s: pid=%d prio=%d\n", __FUNCTION__,
-			 current->pid, current->prio);
-		schedule();
-		down_write(&ctx->state_sema);
-		down(&rq->sem);
-	}
-	finish_wait(wq, &wait);
-	atomic_dec(&rq->prio.nr_blocked);
-	if (!waitqueue_active(wq))
-		__clear_bit(prio, rq->prio.bitmap);
-}
+static struct spu_prio_array *spu_prio;
 
-static inline int is_best_prio(struct spu_runqueue *rq)
+static inline int node_allowed(int node)
 {
-	int best_prio;
+	cpumask_t mask;
 
-	best_prio = sched_find_first_bit(rq->prio.bitmap);
-	return (current->prio < best_prio) ? 1 : 0;
+	if (!nr_cpus_node(node))
+		return 0;
+	mask = node_to_cpumask(node);
+	if (!cpus_intersects(mask, current->cpus_allowed))
+		return 0;
+	return 1;
 }
 
 static inline void mm_needs_global_tlbie(struct mm_struct *mm)
 {
+	int nr = (NR_CPUS > 1) ? NR_CPUS : NR_CPUS + 1;
+
 	/* Global TLBIE broadcast required with SPEs. */
-#if (NR_CPUS > 1)
-	__cpus_setall(&mm->cpu_vm_mask, NR_CPUS);
-#else
-	__cpus_setall(&mm->cpu_vm_mask, NR_CPUS+1); /* is this ok? */
-#endif
+	__cpus_setall(&mm->cpu_vm_mask, nr);
 }
 
 static inline void bind_context(struct spu *spu, struct spu_context *ctx)
 {
-	pr_debug("%s: pid=%d SPU=%d\n", __FUNCTION__, current->pid,
-		 spu->number);
+	pr_debug("%s: pid=%d SPU=%d NODE=%d\n", __FUNCTION__, current->pid,
+		 spu->number, spu->node);
 	spu->ctx = ctx;
 	spu->flags = 0;
 	ctx->flags = 0;
@@ -185,12 +96,13 @@ static inline void bind_context(struct s
 	spu_unmap_mappings(ctx);
 	spu_restore(&ctx->csa, spu);
 	spu->timestamp = jiffies;
+	spu_cpu_affinity_set(spu, raw_smp_processor_id());
 }
 
 static inline void unbind_context(struct spu *spu, struct spu_context *ctx)
 {
-	pr_debug("%s: unbind pid=%d SPU=%d\n", __FUNCTION__,
-		 spu->pid, spu->number);
+	pr_debug("%s: unbind pid=%d SPU=%d NODE=%d\n", __FUNCTION__,
+		 spu->pid, spu->number, spu->node);
 	spu_unmap_mappings(ctx);
 	spu_save(&ctx->csa, spu);
 	spu->timestamp = jiffies;
@@ -209,163 +121,148 @@ static inline void unbind_context(struct
 	spu->ctx = NULL;
 }
 
-static void spu_reaper(void *data)
+static inline void spu_add_wq(wait_queue_head_t * wq, wait_queue_t * wait,
+			      int prio)
 {
-	struct spu_context *ctx = data;
-	struct spu *spu;
-
-	down_write(&ctx->state_sema);
-	spu = ctx->spu;
-	if (spu && test_bit(SPU_CONTEXT_PREEMPT, &ctx->flags)) {
-		if (atomic_read(&spu->rq->prio.nr_blocked)) {
-			pr_debug("%s: spu=%d\n", __func__, spu->number);
-			ctx->ops->runcntl_stop(ctx);
-			spu_deactivate(ctx);
-			wake_up_all(&ctx->stop_wq);
-		} else {
-			clear_bit(SPU_CONTEXT_PREEMPT, &ctx->flags);
-		}
-	}
-	up_write(&ctx->state_sema);
-	put_spu_context(ctx);
+	prepare_to_wait_exclusive(wq, wait, TASK_INTERRUPTIBLE);
+	set_bit(prio, spu_prio->bitmap);
 }
 
-static void schedule_spu_reaper(struct spu_runqueue *rq, struct spu *spu)
+static inline void spu_del_wq(wait_queue_head_t * wq, wait_queue_t * wait,
+			      int prio)
 {
-	struct spu_context *ctx = get_spu_context(spu->ctx);
-	unsigned long now = jiffies;
-	unsigned long expire = spu->timestamp + SPU_MIN_TIMESLICE;
+	u64 flags;
 
-	set_bit(SPU_CONTEXT_PREEMPT, &ctx->flags);
-	INIT_WORK(&ctx->reap_work, spu_reaper, ctx);
-	if (time_after(now, expire))
-		schedule_work(&ctx->reap_work);
-	else
-		schedule_delayed_work(&ctx->reap_work, expire - now);
-}
+	__set_current_state(TASK_RUNNING);
 
-static void check_preempt_active(struct spu_runqueue *rq)
-{
-	struct list_head *p;
-	struct spu *worst = NULL;
+	spin_lock_irqsave(&wq->lock, flags);
 
-	list_for_each(p, &rq->active_list) {
-		struct spu *spu = list_entry(p, struct spu, sched_list);
-		struct spu_context *ctx = spu->ctx;
-		if (!test_bit(SPU_CONTEXT_PREEMPT, &ctx->flags)) {
-			if (!worst || (spu->prio > worst->prio)) {
-				worst = spu;
-			}
-		}
-	}
-	if (worst && (current->prio < worst->prio))
-		schedule_spu_reaper(rq, worst);
+	remove_wait_queue_locked(wq, wait);
+	if (list_empty(&wq->task_list))
+		clear_bit(prio, spu_prio->bitmap);
+
+	spin_unlock_irqrestore(&wq->lock, flags);
 }
 
-static struct spu *get_idle_spu(struct spu_context *ctx, u64 flags)
+static void spu_prio_wait(struct spu_context *ctx, u64 flags)
 {
-	struct spu_runqueue *rq;
-	struct spu *spu = NULL;
+	int prio = current->prio;
+	wait_queue_head_t *wq = &spu_prio->waitq[prio];
+	DEFINE_WAIT(wait);
 
-	rq = spu_rq();
-	down(&rq->sem);
-	for (;;) {
-		if (rq->nr_idle > 0) {
-			if (is_best_prio(rq)) {
-				/* Fall through. */
-				spu = del_idle(rq);
-				break;
-			} else {
-				prio_wakeup(rq);
-				up(&rq->sem);
-				yield();
-				if (signal_pending(current)) {
-					return NULL;
-				}
-				rq = spu_rq();
-				down(&rq->sem);
-				continue;
-			}
-		} else {
-			check_preempt_active(rq);
-			prio_wait(rq, ctx, flags);
-			if (signal_pending(current)) {
-				prio_wakeup(rq);
-				spu = NULL;
-				break;
-			}
-			continue;
-		}
+	if (ctx->spu)
+		return;
+
+	spu_add_wq(wq, &wait, prio);
+
+	if (!signal_pending(current)) {
+		up_write(&ctx->state_sema);
+		pr_debug("%s: pid=%d prio=%d\n", __FUNCTION__,
+			 current->pid, current->prio);
+		schedule();
+		down_write(&ctx->state_sema);
 	}
-	up(&rq->sem);
-	return spu;
+
+	spu_del_wq(wq, &wait, prio);
 }
 
-static void put_idle_spu(struct spu *spu)
+static void spu_prio_wakeup(void)
 {
-	struct spu_runqueue *rq = spu->rq;
-
-	down(&rq->sem);
-	add_idle(rq, spu);
-	prio_wakeup(rq);
-	up(&rq->sem);
+	int best = sched_find_first_bit(spu_prio->bitmap);
+	if (best < MAX_PRIO) {
+		wait_queue_head_t *wq = &spu_prio->waitq[best];
+		wake_up_interruptible_nr(wq, 1);
+	}
 }
 
 static int get_active_spu(struct spu *spu)
 {
-	struct spu_runqueue *rq = spu->rq;
-	struct list_head *p;
+	int node = spu->node;
 	struct spu *tmp;
 	int rc = 0;
 
-	down(&rq->sem);
-	list_for_each(p, &rq->active_list) {
-		tmp = list_entry(p, struct spu, sched_list);
+	mutex_lock(&spu_prio->active_mutex[node]);
+	list_for_each_entry(tmp, &spu_prio->active_list[node], list) {
 		if (tmp == spu) {
-			del_active(rq, spu);
+			list_del_init(&spu->list);
 			rc = 1;
 			break;
 		}
 	}
-	up(&rq->sem);
+	mutex_unlock(&spu_prio->active_mutex[node]);
 	return rc;
 }
 
 static void put_active_spu(struct spu *spu)
 {
-	struct spu_runqueue *rq = spu->rq;
+	int node = spu->node;
 
-	down(&rq->sem);
-	add_active(rq, spu);
-	up(&rq->sem);
+	mutex_lock(&spu_prio->active_mutex[node]);
+	list_add_tail(&spu->list, &spu_prio->active_list[node]);
+	mutex_unlock(&spu_prio->active_mutex[node]);
 }
 
-/* Lock order:
- *	spu_activate() & spu_deactivate() require the
- *	caller to have down_write(&ctx->state_sema).
+static struct spu *spu_get_idle(struct spu_context *ctx, u64 flags)
+{
+	struct spu *spu = NULL;
+	int node = cpu_to_node(raw_smp_processor_id());
+	int n;
+
+	for (n = 0; n < MAX_NUMNODES; n++, node++) {
+		node = (node < MAX_NUMNODES) ? node : 0;
+		if (!node_allowed(node))
+			continue;
+		spu = spu_alloc_node(node);
+		if (spu)
+			break;
+	}
+	return spu;
+}
+
+static inline struct spu *spu_get(struct spu_context *ctx, u64 flags)
+{
+	/* Future: spu_get_idle() if possible,
+	 * otherwise try to preempt an active
+	 * context.
+	 */
+	return spu_get_idle(ctx, flags);
+}
+
+/* The three externally callable interfaces
+ * for the scheduler begin here.
  *
- *	The rq->sem is breifly held (inside or outside a
- *	given ctx lock) for list management, but is never
- *	held during save/restore.
+ *	spu_activate	- bind a context to SPU, waiting as needed.
+ *	spu_deactivate	- unbind a context from its SPU.
+ *	spu_yield	- yield an SPU if others are waiting.
  */
 
 int spu_activate(struct spu_context *ctx, u64 flags)
 {
 	struct spu *spu;
+	int ret = 0;
 
-	if (ctx->spu)
-		return 0;
-	spu = get_idle_spu(ctx, flags);
-	if (!spu)
-		return (signal_pending(current)) ? -ERESTARTSYS : -EAGAIN;
-	bind_context(spu, ctx);
-	/*
-	 * We're likely to wait for interrupts on the same
-	 * CPU that we are now on, so send them here.
-	 */
-	spu_cpu_affinity_set(spu, raw_smp_processor_id());
-	put_active_spu(spu);
-	return 0;
+	for (;;) {
+		if (ctx->spu)
+			return 0;
+		spu = spu_get(ctx, flags);
+		if (spu != NULL) {
+			if (ctx->spu != NULL) {
+				spu_free(spu);
+				spu_prio_wakeup();
+				break;
+			}
+			bind_context(spu, ctx);
+			put_active_spu(spu);
+			break;
+		}
+		spu_prio_wait(ctx, flags);
+		if (signal_pending(current)) {
+			ret = -ERESTARTSYS;
+			spu_prio_wakeup();
+			break;
+		}
+	}
+	return ret;
 }
 
 void spu_deactivate(struct spu_context *ctx)
@@ -378,8 +275,10 @@ void spu_deactivate(struct spu_context *
 		return;
 	needs_idle = get_active_spu(spu);
 	unbind_context(spu, ctx);
-	if (needs_idle)
-		put_idle_spu(spu);
+	if (needs_idle) {
+		spu_free(spu);
+		spu_prio_wakeup();
+	}
 }
 
 void spu_yield(struct spu_context *ctx)
@@ -387,77 +286,60 @@ void spu_yield(struct spu_context *ctx)
 	struct spu *spu;
 	int need_yield = 0;
 
-	down_write(&ctx->state_sema);
-	spu = ctx->spu;
-	if (spu && (sched_find_first_bit(spu->rq->prio.bitmap) < MAX_PRIO)) {
-		pr_debug("%s: yielding SPU %d\n", __FUNCTION__, spu->number);
-		spu_deactivate(ctx);
-		ctx->state = SPU_STATE_SAVED;
-		need_yield = 1;
-	} else if (spu) {
-		spu->prio = MAX_PRIO;
+	if (down_write_trylock(&ctx->state_sema)) {
+		if ((spu = ctx->spu) != NULL) {
+			int best = sched_find_first_bit(spu_prio->bitmap);
+			if (best < MAX_PRIO) {
+				pr_debug("%s: yielding SPU %d NODE %d\n",
+					 __FUNCTION__, spu->number, spu->node);
+				spu_deactivate(ctx);
+				ctx->state = SPU_STATE_SAVED;
+				need_yield = 1;
+			} else {
+				spu->prio = MAX_PRIO;
+			}
+		}
+		up_write(&ctx->state_sema);
 	}
-	up_write(&ctx->state_sema);
 	if (unlikely(need_yield))
 		yield();
 }
 
 int __init spu_sched_init(void)
 {
-	struct spu_runqueue *rq;
-	struct spu *spu;
 	int i;
 
-	rq = spu_runqueues = kmalloc(sizeof(struct spu_runqueue), GFP_KERNEL);
-	if (!rq) {
-		printk(KERN_WARNING "%s: Unable to allocate runqueues.\n",
+	spu_prio = kzalloc(sizeof(struct spu_prio_array), GFP_KERNEL);
+	if (!spu_prio) {
+		printk(KERN_WARNING "%s: Unable to allocate priority queue.\n",
 		       __FUNCTION__);
 		return 1;
 	}
-	memset(rq, 0, sizeof(struct spu_runqueue));
-	init_MUTEX(&rq->sem);
-	INIT_LIST_HEAD(&rq->active_list);
-	INIT_LIST_HEAD(&rq->idle_list);
-	rq->nr_active = 0;
-	rq->nr_idle = 0;
-	rq->nr_switches = 0;
-	atomic_set(&rq->prio.nr_blocked, 0);
 	for (i = 0; i < MAX_PRIO; i++) {
-		init_waitqueue_head(&rq->prio.waitq[i]);
-		__clear_bit(i, rq->prio.bitmap);
+		init_waitqueue_head(&spu_prio->waitq[i]);
+		__clear_bit(i, spu_prio->bitmap);
 	}
-	__set_bit(MAX_PRIO, rq->prio.bitmap);
-	for (;;) {
-		spu = spu_alloc();
-		if (!spu)
-			break;
-		pr_debug("%s: adding SPU[%d]\n", __FUNCTION__, spu->number);
-		add_idle(rq, spu);
-		spu->rq = rq;
-		spu->timestamp = jiffies;
-	}
-	if (!rq->nr_idle) {
-		printk(KERN_WARNING "%s: No available SPUs.\n", __FUNCTION__);
-		kfree(rq);
-		return 1;
+	__set_bit(MAX_PRIO, spu_prio->bitmap);
+	for (i = 0; i < MAX_NUMNODES; i++) {
+		mutex_init(&spu_prio->active_mutex[i]);
+		INIT_LIST_HEAD(&spu_prio->active_list[i]);
 	}
 	return 0;
 }
 
 void __exit spu_sched_exit(void)
 {
-	struct spu_runqueue *rq = spu_rq();
-	struct spu *spu;
+	struct spu *spu, *tmp;
+	int node;
 
-	if (!rq) {
-		printk(KERN_WARNING "%s: no runqueues!\n", __FUNCTION__);
-		return;
-	}
-	while (rq->nr_idle > 0) {
-		spu = del_idle(rq);
-		if (!spu)
-			break;
-		spu_free(spu);
+	for (node = 0; node < MAX_NUMNODES; node++) {
+		mutex_lock(&spu_prio->active_mutex[node]);
+		list_for_each_entry_safe(spu, tmp, &spu_prio->active_list[node],
+					 list) {
+			list_del_init(&spu->list);
+			spu_free(spu);
+		}
+		mutex_unlock(&spu_prio->active_mutex[node]);
 	}
-	kfree(rq);
+	kfree(spu_prio);
 }
Index: linux-2.6/include/asm-powerpc/spu.h
===================================================================
--- linux-2.6.orig/include/asm-powerpc/spu.h
+++ linux-2.6/include/asm-powerpc/spu.h
@@ -147,6 +147,7 @@ struct spu {
 };
 
 struct spu *spu_alloc(void);
+struct spu *spu_alloc_node(int node);
 void spu_free(struct spu *spu);
 int spu_irq_class_0_bottom(struct spu *spu);
 int spu_irq_class_1_bottom(struct spu *spu);

--

^ permalink raw reply

* [PATCH 03/14] spufs: fix context switch during page fault
From: Arnd Bergmann @ 2006-10-04 15:26 UTC (permalink / raw)
  To: Paul Mackerras
  Cc: Arnd Bergmann, linux-kernel, linuxppc-dev, cbe-oss-dev,
	HyeonSeung Jang
In-Reply-To: <20061004152610.151599000@dyn-9-152-242-103.boeblingen.de.ibm.com>

From: HyeonSeung Jang <hs8848.jang@samsung.com>

For better explanation, I break down the page fault handling into steps:

1) There is a page fault caused by DMA operation initiated by SPU and
DMA is suspended.

2) The interrupt handler 'spu_irq_class_1()/__spu_trap_data_map()' is
called and it just wakes up the sleeping spe-manager thread.

3) by PPE scheduler, the corresponding bottom half,
spu_irq_class_1_bottom() is called in process context and DMA is
restarted.

There can be a quite large time gap between 2) and 3) and I found
the following problem:

Between 2) and 3) If the context becomes unbound, 3) is not executed
because when the spe-manager thread is awaken, the context is already
saved. (This situation can happen, for example, when a high priority spe
thread newly started in that time gap)

But the actual problem is that the corresponding SPU context does not
work even if it is bound again to a SPU.

Besides I can see the following warning in mambo simulator when the
context becomes
unbound(in save_mfc_cmd()), i.e. when unbind() is called for the
context after step 2) before 3) :

'WARNING: 61392752237: SPE2: MFC_CMD_QUEUE channel count of 15 is
inconsistent with number of available DMA queue entries of 16'

After I go through available documents, I found that the problem is
because the suspended DMA is not restarted when it is bound again.

Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>

Index: linux-2.6/arch/powerpc/platforms/cell/spufs/switch.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/switch.c
+++ linux-2.6/arch/powerpc/platforms/cell/spufs/switch.c
@@ -1779,6 +1779,15 @@ static inline void restore_mfc_cntl(stru
 	 */
 	out_be64(&priv2->mfc_control_RW, csa->priv2.mfc_control_RW);
 	eieio();
+	/*
+	 * FIXME: this is to restart a DMA that we were processing
+	 *        before the save. better remember the fault information
+	 *        in the csa instead.
+	 */
+	if ((csa->priv2.mfc_control_RW & MFC_CNTL_SUSPEND_DMA_QUEUE_MASK)) {
+		out_be64(&priv2->mfc_control_RW, MFC_CNTL_RESTART_DMA_COMMAND);
+		eieio();
+	}
 }
 
 static inline void enable_user_access(struct spu_state *csa, struct spu *spu)

--

^ permalink raw reply

* [PATCH 04/14] spufs: implement error event delivery to user space
From: Arnd Bergmann @ 2006-10-04 15:26 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: Arnd Bergmann, linuxppc-dev, cbe-oss-dev, linux-kernel
In-Reply-To: <20061004152610.151599000@dyn-9-152-242-103.boeblingen.de.ibm.com>

This tries to fix spufs so we have an interface closer
to what is specified in the man page for events
returned in the third argument of spu_run.

Fortunately, libspe has never been using the returned
contents of that register, as they were the same
as the return code of spu_run (duh!).

Unlike the specification that we never implemented
correctly, we now require a SPU_CREATE_EVENTS_ENABLED
flag passed to spu_create, in order to get the
new behavior. When this flag is not passed, spu_run
will simply ignore the third argument now.

Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Index: linux-2.6/arch/powerpc/platforms/cell/spufs/run.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/run.c
+++ linux-2.6/arch/powerpc/platforms/cell/spufs/run.c
@@ -14,6 +14,26 @@ void spufs_stop_callback(struct spu *spu
 	wake_up_all(&ctx->stop_wq);
 }
 
+void spufs_dma_callback(struct spu *spu, int type)
+{
+	struct spu_context *ctx = spu->ctx;
+
+	if (ctx->flags & SPU_CREATE_EVENTS_ENABLED) {
+		ctx->event_return |= type;
+		wake_up_all(&ctx->stop_wq);
+	} else {
+		switch (type) {
+		case SPE_EVENT_DMA_ALIGNMENT:
+		case SPE_EVENT_INVALID_DMA:
+			force_sig(SIGBUS, /* info, */ current);
+			break;
+		case SPE_EVENT_SPE_ERROR:
+			force_sig(SIGILL, /* info */ current);
+			break;
+		}
+	}
+}
+
 static inline int spu_stopped(struct spu_context *ctx, u32 * stat)
 {
 	struct spu *spu;
@@ -28,8 +48,7 @@ static inline int spu_stopped(struct spu
 	return (!(*stat & 0x1) || pte_fault || spu->class_0_pending) ? 1 : 0;
 }
 
-static inline int spu_run_init(struct spu_context *ctx, u32 * npc,
-			       u32 * status)
+static inline int spu_run_init(struct spu_context *ctx, u32 * npc)
 {
 	int ret;
 
@@ -72,7 +91,7 @@ static inline int spu_reacquire_runnable
 		       SPU_STATUS_STOPPED_BY_HALT)) {
 		return *status;
 	}
-	if ((ret = spu_run_init(ctx, npc, status)) != 0)
+	if ((ret = spu_run_init(ctx, npc)) != 0)
 		return ret;
 	return 0;
 }
@@ -177,46 +196,49 @@ static inline int spu_process_events(str
 }
 
 long spufs_run_spu(struct file *file, struct spu_context *ctx,
-		   u32 * npc, u32 * status)
+		   u32 *npc, u32 *event)
 {
 	int ret;
+	u32 status;
 
 	if (down_interruptible(&ctx->run_sema))
 		return -ERESTARTSYS;
 
-	ret = spu_run_init(ctx, npc, status);
+	ctx->event_return = 0;
+	ret = spu_run_init(ctx, npc);
 	if (ret)
 		goto out;
 
 	do {
-		ret = spufs_wait(ctx->stop_wq, spu_stopped(ctx, status));
+		ret = spufs_wait(ctx->stop_wq, spu_stopped(ctx, &status));
 		if (unlikely(ret))
 			break;
-		if ((*status & SPU_STATUS_STOPPED_BY_STOP) &&
-		    (*status >> SPU_STOP_STATUS_SHIFT == 0x2104)) {
+		if ((status & SPU_STATUS_STOPPED_BY_STOP) &&
+		    (status >> SPU_STOP_STATUS_SHIFT == 0x2104)) {
 			ret = spu_process_callback(ctx);
 			if (ret)
 				break;
-			*status &= ~SPU_STATUS_STOPPED_BY_STOP;
+			status &= ~SPU_STATUS_STOPPED_BY_STOP;
 		}
 		if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) {
-			ret = spu_reacquire_runnable(ctx, npc, status);
+			ret = spu_reacquire_runnable(ctx, npc, &status);
 			if (ret)
 				goto out;
 			continue;
 		}
 		ret = spu_process_events(ctx);
 
-	} while (!ret && !(*status & (SPU_STATUS_STOPPED_BY_STOP |
+	} while (!ret && !(status & (SPU_STATUS_STOPPED_BY_STOP |
 				      SPU_STATUS_STOPPED_BY_HALT)));
 
 	ctx->ops->runcntl_stop(ctx);
-	ret = spu_run_fini(ctx, npc, status);
+	ret = spu_run_fini(ctx, npc, &status);
 	if (!ret)
-		ret = *status;
+		ret = status;
 	spu_yield(ctx);
 
 out:
+	*event = ctx->event_return;
 	up(&ctx->run_sema);
 	return ret;
 }
Index: linux-2.6/arch/powerpc/platforms/cell/spufs/syscalls.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/syscalls.c
+++ linux-2.6/arch/powerpc/platforms/cell/spufs/syscalls.c
@@ -38,7 +38,7 @@ static long do_spu_run(struct file *filp
 	u32 npc, status;
 
 	ret = -EFAULT;
-	if (get_user(npc, unpc) || get_user(status, ustatus))
+	if (get_user(npc, unpc))
 		goto out;
 
 	/* check if this file was created by spu_create */
@@ -49,7 +49,10 @@ static long do_spu_run(struct file *filp
 	i = SPUFS_I(filp->f_dentry->d_inode);
 	ret = spufs_run_spu(filp, i->i_ctx, &npc, &status);
 
-	if (put_user(npc, unpc) || put_user(status, ustatus))
+	if (put_user(npc, unpc))
+		ret = -EFAULT;
+
+	if (ustatus && put_user(status, ustatus))
 		ret = -EFAULT;
 out:
 	return ret;
Index: linux-2.6/arch/powerpc/platforms/cell/spu_base.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/spu_base.c
+++ linux-2.6/arch/powerpc/platforms/cell/spu_base.c
@@ -46,21 +46,21 @@ EXPORT_SYMBOL_GPL(spu_priv1_ops);
 static int __spu_trap_invalid_dma(struct spu *spu)
 {
 	pr_debug("%s\n", __FUNCTION__);
-	force_sig(SIGBUS, /* info, */ current);
+	spu->dma_callback(spu, SPE_EVENT_INVALID_DMA);
 	return 0;
 }
 
 static int __spu_trap_dma_align(struct spu *spu)
 {
 	pr_debug("%s\n", __FUNCTION__);
-	force_sig(SIGBUS, /* info, */ current);
+	spu->dma_callback(spu, SPE_EVENT_DMA_ALIGNMENT);
 	return 0;
 }
 
 static int __spu_trap_error(struct spu *spu)
 {
 	pr_debug("%s\n", __FUNCTION__);
-	force_sig(SIGILL, /* info, */ current);
+	spu->dma_callback(spu, SPE_EVENT_SPE_ERROR);
 	return 0;
 }
 
Index: linux-2.6/arch/powerpc/platforms/cell/spufs/inode.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/inode.c
+++ linux-2.6/arch/powerpc/platforms/cell/spufs/inode.c
@@ -224,7 +224,8 @@ struct file_operations spufs_context_fop
 };
 
 static int
-spufs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags,
+		int mode)
 {
 	int ret;
 	struct inode *inode;
@@ -244,6 +245,8 @@ spufs_mkdir(struct inode *dir, struct de
 	if (!ctx)
 		goto out_iput;
 
+	ctx->flags = flags;
+
 	inode->i_op = &spufs_dir_inode_operations;
 	inode->i_fop = &simple_dir_operations;
 	ret = spufs_fill_dir(dentry, spufs_dir_contents, mode, ctx);
@@ -304,7 +307,7 @@ long spufs_create_thread(struct nameidat
 		goto out;
 
 	/* all flags are reserved */
-	if (flags)
+	if (flags & (~SPU_CREATE_FLAG_ALL))
 		goto out;
 
 	dentry = lookup_create(nd, 1);
@@ -317,7 +320,7 @@ long spufs_create_thread(struct nameidat
 		goto out_dput;
 
 	mode &= ~current->fs->umask;
-	ret = spufs_mkdir(nd->dentry->d_inode, dentry, mode & S_IRWXUGO);
+	ret = spufs_mkdir(nd->dentry->d_inode, dentry, flags, mode & S_IRWXUGO);
 	if (ret)
 		goto out_dput;
 
Index: linux-2.6/arch/powerpc/platforms/cell/spufs/sched.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/sched.c
+++ linux-2.6/arch/powerpc/platforms/cell/spufs/sched.c
@@ -81,7 +81,6 @@ static inline void bind_context(struct s
 		 spu->number, spu->node);
 	spu->ctx = ctx;
 	spu->flags = 0;
-	ctx->flags = 0;
 	ctx->spu = spu;
 	ctx->ops = &spu_hw_ops;
 	spu->pid = current->pid;
@@ -92,6 +91,7 @@ static inline void bind_context(struct s
 	spu->wbox_callback = spufs_wbox_callback;
 	spu->stop_callback = spufs_stop_callback;
 	spu->mfc_callback = spufs_mfc_callback;
+	spu->dma_callback = spufs_dma_callback;
 	mb();
 	spu_unmap_mappings(ctx);
 	spu_restore(&ctx->csa, spu);
@@ -111,12 +111,12 @@ static inline void unbind_context(struct
 	spu->wbox_callback = NULL;
 	spu->stop_callback = NULL;
 	spu->mfc_callback = NULL;
+	spu->dma_callback = NULL;
 	spu->mm = NULL;
 	spu->pid = 0;
 	spu->prio = MAX_PRIO;
 	ctx->ops = &spu_backing_ops;
 	ctx->spu = NULL;
-	ctx->flags = 0;
 	spu->flags = 0;
 	spu->ctx = NULL;
 }
Index: linux-2.6/arch/powerpc/platforms/cell/spufs/spufs.h
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/spufs.h
+++ linux-2.6/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -66,7 +66,8 @@ struct spu_context {
 	u32 tagwait;
 	struct spu_context_ops *ops;
 	struct work_struct reap_work;
-	u64 flags;
+	unsigned long flags;
+	unsigned long event_return;
 };
 
 struct mfc_dma_command {
@@ -183,5 +184,6 @@ void spufs_ibox_callback(struct spu *spu
 void spufs_wbox_callback(struct spu *spu);
 void spufs_stop_callback(struct spu *spu);
 void spufs_mfc_callback(struct spu *spu);
+void spufs_dma_callback(struct spu *spu, int type);
 
 #endif
Index: linux-2.6/include/asm-powerpc/spu.h
===================================================================
--- linux-2.6.orig/include/asm-powerpc/spu.h
+++ linux-2.6/include/asm-powerpc/spu.h
@@ -138,6 +138,7 @@ struct spu {
 	void (* ibox_callback)(struct spu *spu);
 	void (* stop_callback)(struct spu *spu);
 	void (* mfc_callback)(struct spu *spu);
+	void (* dma_callback)(struct spu *spu, int type);
 
 	char irq_c0[8];
 	char irq_c1[8];
@@ -169,6 +170,19 @@ extern struct spufs_calls {
 	struct module *owner;
 } spufs_calls;
 
+/* return status from spu_run, same as in libspe */
+#define SPE_EVENT_DMA_ALIGNMENT		0x0008	/*A DMA alignment error */
+#define SPE_EVENT_SPE_ERROR		0x0010	/*An illegal instruction error*/
+#define SPE_EVENT_SPE_DATA_SEGMENT	0x0020	/*A DMA segmentation error    */
+#define SPE_EVENT_SPE_DATA_STORAGE	0x0040	/*A DMA storage error */
+#define SPE_EVENT_INVALID_DMA		0x0800	/* Invalid MFC DMA */
+
+/*
+ * Flags for sys_spu_create.
+ */
+#define SPU_CREATE_EVENTS_ENABLED	0x0001
+#define SPU_CREATE_FLAG_ALL		0x0001 /* mask of all valid flags */
+
 #ifdef CONFIG_SPU_FS_MODULE
 int register_spu_syscalls(struct spufs_calls *calls);
 void unregister_spu_syscalls(struct spufs_calls *calls);

--

^ permalink raw reply

* [PATCH 05/14] spufs: Add infrastructure needed for gang scheduling
From: Arnd Bergmann @ 2006-10-04 15:26 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: Arnd Bergmann, linuxppc-dev, cbe-oss-dev, linux-kernel
In-Reply-To: <20061004152610.151599000@dyn-9-152-242-103.boeblingen.de.ibm.com>

Add the concept of a gang to spufs as a new type of object.
So far, this has no impact whatsover on scheduling, but makes
it possible to add that later.

A new type of object in spufs is now a spu_gang. It is created
with the spu_create system call with the flags argument set
to SPU_CREATE_GANG (0x2). Inside of a spu_gang, it
is then possible to create spu_context objects, which until
now was only possible at the root of spufs.

There is a new member in struct spu_context pointing to
the spu_gang it belongs to, if any. The spu_gang maintains
a list of spu_context structures that are its children.
This information can then be used in the scheduler in the
future.

There is still a bug that needs to be resolved in this
basic infrastructure regarding the order in which objects
are removed. When the spu_gang file descriptor is closed
before the spu_context descriptors, we leak the dentry
and inode for the gang. Any ideas how to cleanly solve
this are appreciated.

Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Index: linux-2.6/arch/powerpc/platforms/cell/spufs/Makefile
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/Makefile
+++ linux-2.6/arch/powerpc/platforms/cell/spufs/Makefile
@@ -2,7 +2,7 @@ obj-y += switch.o
 
 obj-$(CONFIG_SPU_FS) += spufs.o
 spufs-y += inode.o file.o context.o syscalls.o
-spufs-y += sched.o backing_ops.o hw_ops.o run.o
+spufs-y += sched.o backing_ops.o hw_ops.o run.o gang.o
 
 # Rules to build switch.o with the help of SPU tool chain
 SPU_CROSS	:= spu-
Index: linux-2.6/arch/powerpc/platforms/cell/spufs/context.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/context.c
+++ linux-2.6/arch/powerpc/platforms/cell/spufs/context.c
@@ -27,7 +27,7 @@
 #include <asm/spu_csa.h>
 #include "spufs.h"
 
-struct spu_context *alloc_spu_context(void)
+struct spu_context *alloc_spu_context(struct spu_gang *gang)
 {
 	struct spu_context *ctx;
 	ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
@@ -51,6 +51,8 @@ struct spu_context *alloc_spu_context(vo
 	ctx->state = SPU_STATE_SAVED;
 	ctx->ops = &spu_backing_ops;
 	ctx->owner = get_task_mm(current);
+	if (gang)
+		spu_gang_add_ctx(gang, ctx);
 	goto out;
 out_free:
 	kfree(ctx);
@@ -67,6 +69,8 @@ void destroy_spu_context(struct kref *kr
 	spu_deactivate(ctx);
 	up_write(&ctx->state_sema);
 	spu_fini_csa(&ctx->csa);
+	if (ctx->gang)
+		spu_gang_remove_ctx(ctx->gang, ctx);
 	kfree(ctx);
 }
 
Index: linux-2.6/arch/powerpc/platforms/cell/spufs/gang.c
===================================================================
--- /dev/null
+++ linux-2.6/arch/powerpc/platforms/cell/spufs/gang.c
@@ -0,0 +1,81 @@
+/*
+ * SPU file system
+ *
+ * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
+ *
+ * Author: Arnd Bergmann <arndb@de.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/list.h>
+#include <linux/slab.h>
+
+#include "spufs.h"
+
+struct spu_gang *alloc_spu_gang(void)
+{
+	struct spu_gang *gang;
+
+	gang = kzalloc(sizeof *gang, GFP_KERNEL);
+	if (!gang)
+		goto out;
+
+	kref_init(&gang->kref);
+	mutex_init(&gang->mutex);
+	INIT_LIST_HEAD(&gang->list);
+
+out:
+	return gang;
+}
+
+static void destroy_spu_gang(struct kref *kref)
+{
+	struct spu_gang *gang;
+	gang = container_of(kref, struct spu_gang, kref);
+	WARN_ON(gang->contexts || !list_empty(&gang->list));
+	kfree(gang);
+}
+
+struct spu_gang *get_spu_gang(struct spu_gang *gang)
+{
+	kref_get(&gang->kref);
+	return gang;
+}
+
+int put_spu_gang(struct spu_gang *gang)
+{
+	return kref_put(&gang->kref, &destroy_spu_gang);
+}
+
+void spu_gang_add_ctx(struct spu_gang *gang, struct spu_context *ctx)
+{
+	mutex_lock(&gang->mutex);
+	ctx->gang = get_spu_gang(gang);
+	list_add(&ctx->gang_list, &gang->list);
+	gang->contexts++;
+	mutex_unlock(&gang->mutex);
+}
+
+void spu_gang_remove_ctx(struct spu_gang *gang, struct spu_context *ctx)
+{
+	mutex_lock(&gang->mutex);
+	WARN_ON(ctx->gang != gang);
+	list_del_init(&ctx->gang_list);
+	gang->contexts--;
+	mutex_unlock(&gang->mutex);
+
+	put_spu_gang(gang);
+}
Index: linux-2.6/arch/powerpc/platforms/cell/spufs/inode.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/inode.c
+++ linux-2.6/arch/powerpc/platforms/cell/spufs/inode.c
@@ -50,6 +50,10 @@ spufs_alloc_inode(struct super_block *sb
 	ei = kmem_cache_alloc(spufs_inode_cache, SLAB_KERNEL);
 	if (!ei)
 		return NULL;
+
+	ei->i_gang = NULL;
+	ei->i_ctx = NULL;
+
 	return &ei->vfs_inode;
 }
 
@@ -128,14 +132,19 @@ out:
 static void
 spufs_delete_inode(struct inode *inode)
 {
-	if (SPUFS_I(inode)->i_ctx)
-		put_spu_context(SPUFS_I(inode)->i_ctx);
+	struct spufs_inode_info *ei = SPUFS_I(inode);
+
+	if (ei->i_ctx)
+		put_spu_context(ei->i_ctx);
+	if (ei->i_gang)
+		put_spu_gang(ei->i_gang);
 	clear_inode(inode);
 }
 
 static void spufs_prune_dir(struct dentry *dir)
 {
 	struct dentry *dentry, *tmp;
+
 	mutex_lock(&dir->d_inode->i_mutex);
 	list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_u.d_child) {
 		spin_lock(&dcache_lock);
@@ -156,13 +165,13 @@ static void spufs_prune_dir(struct dentr
 	mutex_unlock(&dir->d_inode->i_mutex);
 }
 
-/* Caller must hold root->i_mutex */
-static int spufs_rmdir(struct inode *root, struct dentry *dir_dentry)
+/* Caller must hold parent->i_mutex */
+static int spufs_rmdir(struct inode *parent, struct dentry *dir)
 {
 	/* remove all entries */
-	spufs_prune_dir(dir_dentry);
+	spufs_prune_dir(dir);
 
-	return simple_rmdir(root, dir_dentry);
+	return simple_rmdir(parent, dir);
 }
 
 static int spufs_fill_dir(struct dentry *dir, struct tree_descr *files,
@@ -191,17 +200,17 @@ out:
 static int spufs_dir_close(struct inode *inode, struct file *file)
 {
 	struct spu_context *ctx;
-	struct inode *dir;
-	struct dentry *dentry;
+	struct inode *parent;
+	struct dentry *dir;
 	int ret;
 
-	dentry = file->f_dentry;
-	dir = dentry->d_parent->d_inode;
-	ctx = SPUFS_I(dentry->d_inode)->i_ctx;
-
-	mutex_lock(&dir->i_mutex);
-	ret = spufs_rmdir(dir, dentry);
-	mutex_unlock(&dir->i_mutex);
+	dir = file->f_dentry;
+	parent = dir->d_parent->d_inode;
+	ctx = SPUFS_I(dir->d_inode)->i_ctx;
+
+	mutex_lock(&parent->i_mutex);
+	ret = spufs_rmdir(parent, dir);
+	mutex_unlock(&parent->i_mutex);
 	WARN_ON(ret);
 
 	/* We have to give up the mm_struct */
@@ -240,7 +249,7 @@ spufs_mkdir(struct inode *dir, struct de
 		inode->i_gid = dir->i_gid;
 		inode->i_mode &= S_ISGID;
 	}
-	ctx = alloc_spu_context();
+	ctx = alloc_spu_context(SPUFS_I(dir)->i_gang); /* XXX gang */
 	SPUFS_I(inode)->i_ctx = ctx;
 	if (!ctx)
 		goto out_iput;
@@ -292,24 +301,177 @@ out:
 	return ret;
 }
 
+static int spufs_create_context(struct inode *inode,
+			struct dentry *dentry,
+			struct vfsmount *mnt, int flags, int mode)
+{
+	int ret;
+
+	ret = spufs_mkdir(inode, dentry, flags, mode & S_IRWXUGO);
+	if (ret)
+		goto out_unlock;
+
+	/*
+	 * get references for dget and mntget, will be released
+	 * in error path of *_open().
+	 */
+	ret = spufs_context_open(dget(dentry), mntget(mnt));
+	if (ret < 0) {
+		WARN_ON(spufs_rmdir(inode, dentry));
+		mutex_unlock(&inode->i_mutex);
+		spu_forget(SPUFS_I(dentry->d_inode)->i_ctx);
+		goto out;
+	}
+
+out_unlock:
+	mutex_unlock(&inode->i_mutex);
+out:
+	dput(dentry);
+	return ret;
+}
+
+static int spufs_rmgang(struct inode *root, struct dentry *dir)
+{
+	/* FIXME: this fails if the dir is not empty,
+	          which causes a leak of gangs. */
+	return simple_rmdir(root, dir);
+}
+
+static int spufs_gang_close(struct inode *inode, struct file *file)
+{
+	struct inode *parent;
+	struct dentry *dir;
+	int ret;
+
+	dir = file->f_dentry;
+	parent = dir->d_parent->d_inode;
+
+	ret = spufs_rmgang(parent, dir);
+	WARN_ON(ret);
+
+	return dcache_dir_close(inode, file);
+}
+
+struct file_operations spufs_gang_fops = {
+	.open		= dcache_dir_open,
+	.release	= spufs_gang_close,
+	.llseek		= dcache_dir_lseek,
+	.read		= generic_read_dir,
+	.readdir	= dcache_readdir,
+	.fsync		= simple_sync_file,
+};
+
+static int
+spufs_mkgang(struct inode *dir, struct dentry *dentry, int mode)
+{
+	int ret;
+	struct inode *inode;
+	struct spu_gang *gang;
+
+	ret = -ENOSPC;
+	inode = spufs_new_inode(dir->i_sb, mode | S_IFDIR);
+	if (!inode)
+		goto out;
+
+	ret = 0;
+	if (dir->i_mode & S_ISGID) {
+		inode->i_gid = dir->i_gid;
+		inode->i_mode &= S_ISGID;
+	}
+	gang = alloc_spu_gang();
+	SPUFS_I(inode)->i_ctx = NULL;
+	SPUFS_I(inode)->i_gang = gang;
+	if (!gang)
+		goto out_iput;
+
+	inode->i_op = &spufs_dir_inode_operations;
+	inode->i_fop = &simple_dir_operations;
+
+	d_instantiate(dentry, inode);
+	dget(dentry);
+	dir->i_nlink++;
+	dentry->d_inode->i_nlink++;
+	return ret;
+
+out_iput:
+	iput(inode);
+out:
+	return ret;
+}
+
+static int spufs_gang_open(struct dentry *dentry, struct vfsmount *mnt)
+{
+	int ret;
+	struct file *filp;
+
+	ret = get_unused_fd();
+	if (ret < 0) {
+		dput(dentry);
+		mntput(mnt);
+		goto out;
+	}
+
+	filp = dentry_open(dentry, mnt, O_RDONLY);
+	if (IS_ERR(filp)) {
+		put_unused_fd(ret);
+		ret = PTR_ERR(filp);
+		goto out;
+	}
+
+	filp->f_op = &spufs_gang_fops;
+	fd_install(ret, filp);
+out:
+	return ret;
+}
+
+static int spufs_create_gang(struct inode *inode,
+			struct dentry *dentry,
+			struct vfsmount *mnt, int mode)
+{
+	int ret;
+
+	ret = spufs_mkgang(inode, dentry, mode & S_IRWXUGO);
+	if (ret)
+		goto out;
+
+	/*
+	 * get references for dget and mntget, will be released
+	 * in error path of *_open().
+	 */
+	ret = spufs_gang_open(dget(dentry), mntget(mnt));
+	if (ret < 0)
+		WARN_ON(spufs_rmgang(inode, dentry));
+
+out:
+	mutex_unlock(&inode->i_mutex);
+	dput(dentry);
+	return ret;
+}
+
+
 static struct file_system_type spufs_type;
 
-long spufs_create_thread(struct nameidata *nd,
-			 unsigned int flags, mode_t mode)
+long spufs_create(struct nameidata *nd, unsigned int flags, mode_t mode)
 {
 	struct dentry *dentry;
 	int ret;
 
-	/* need to be at the root of spufs */
 	ret = -EINVAL;
-	if (nd->dentry->d_sb->s_type != &spufs_type ||
-	    nd->dentry != nd->dentry->d_sb->s_root)
+	/* check if we are on spufs */
+	if (nd->dentry->d_sb->s_type != &spufs_type)
 		goto out;
 
-	/* all flags are reserved */
+	/* don't accept undefined flags */
 	if (flags & (~SPU_CREATE_FLAG_ALL))
 		goto out;
 
+	/* only threads can be underneath a gang */
+	if (nd->dentry != nd->dentry->d_sb->s_root) {
+		if ((flags & SPU_CREATE_GANG) ||
+		    !SPUFS_I(nd->dentry->d_inode)->i_gang)
+			goto out;
+	}
+
 	dentry = lookup_create(nd, 1);
 	ret = PTR_ERR(dentry);
 	if (IS_ERR(dentry))
@@ -320,22 +482,13 @@ long spufs_create_thread(struct nameidat
 		goto out_dput;
 
 	mode &= ~current->fs->umask;
-	ret = spufs_mkdir(nd->dentry->d_inode, dentry, flags, mode & S_IRWXUGO);
-	if (ret)
-		goto out_dput;
 
-	/*
-	 * get references for dget and mntget, will be released
-	 * in error path of *_open().
-	 */
-	ret = spufs_context_open(dget(dentry), mntget(nd->mnt));
-	if (ret < 0) {
-		WARN_ON(spufs_rmdir(nd->dentry->d_inode, dentry));
-		mutex_unlock(&nd->dentry->d_inode->i_mutex);
-		spu_forget(SPUFS_I(dentry->d_inode)->i_ctx);
-		dput(dentry);
-		goto out;
-	}
+	if (flags & SPU_CREATE_GANG)
+		return spufs_create_gang(nd->dentry->d_inode,
+					dentry, nd->mnt, mode);
+	else
+		return spufs_create_context(nd->dentry->d_inode,
+					dentry, nd->mnt, flags, mode);
 
 out_dput:
 	dput(dentry);
Index: linux-2.6/arch/powerpc/platforms/cell/spufs/spufs.h
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/spufs.h
+++ linux-2.6/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -39,6 +39,8 @@ struct spu_context_ops;
 
 #define SPU_CONTEXT_PREEMPT          0UL
 
+struct spu_gang;
+
 struct spu_context {
 	struct spu *spu;		  /* pointer to a physical SPU */
 	struct spu_state csa;		  /* SPU context save area. */
@@ -68,6 +70,16 @@ struct spu_context {
 	struct work_struct reap_work;
 	unsigned long flags;
 	unsigned long event_return;
+
+	struct list_head gang_list;
+	struct spu_gang *gang;
+};
+
+struct spu_gang {
+	struct list_head list;
+	struct mutex mutex;
+	struct kref kref;
+	int contexts;
 };
 
 struct mfc_dma_command {
@@ -115,6 +127,7 @@ extern struct spu_context_ops spu_backin
 
 struct spufs_inode_info {
 	struct spu_context *i_ctx;
+	struct spu_gang *i_gang;
 	struct inode vfs_inode;
 };
 #define SPUFS_I(inode) \
@@ -125,12 +138,19 @@ extern struct tree_descr spufs_dir_conte
 /* system call implementation */
 long spufs_run_spu(struct file *file,
 		   struct spu_context *ctx, u32 *npc, u32 *status);
-long spufs_create_thread(struct nameidata *nd,
+long spufs_create(struct nameidata *nd,
 			 unsigned int flags, mode_t mode);
 extern struct file_operations spufs_context_fops;
 
+/* gang management */
+struct spu_gang *alloc_spu_gang(void);
+struct spu_gang *get_spu_gang(struct spu_gang *gang);
+int put_spu_gang(struct spu_gang *gang);
+void spu_gang_remove_ctx(struct spu_gang *gang, struct spu_context *ctx);
+void spu_gang_add_ctx(struct spu_gang *gang, struct spu_context *ctx);
+
 /* context management */
-struct spu_context * alloc_spu_context(void);
+struct spu_context * alloc_spu_context(struct spu_gang *gang);
 void destroy_spu_context(struct kref *kref);
 struct spu_context * get_spu_context(struct spu_context *ctx);
 int put_spu_context(struct spu_context *ctx);
Index: linux-2.6/arch/powerpc/platforms/cell/spufs/syscalls.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/syscalls.c
+++ linux-2.6/arch/powerpc/platforms/cell/spufs/syscalls.c
@@ -90,7 +90,7 @@ asmlinkage long sys_spu_create(const cha
 		ret = path_lookup(tmp, LOOKUP_PARENT|
 				LOOKUP_OPEN|LOOKUP_CREATE, &nd);
 		if (!ret) {
-			ret = spufs_create_thread(&nd, flags, mode);
+			ret = spufs_create(&nd, flags, mode);
 			path_release(&nd);
 		}
 		putname(tmp);
Index: linux-2.6/include/asm-powerpc/spu.h
===================================================================
--- linux-2.6.orig/include/asm-powerpc/spu.h
+++ linux-2.6/include/asm-powerpc/spu.h
@@ -181,7 +181,10 @@ extern struct spufs_calls {
  * Flags for sys_spu_create.
  */
 #define SPU_CREATE_EVENTS_ENABLED	0x0001
-#define SPU_CREATE_FLAG_ALL		0x0001 /* mask of all valid flags */
+#define SPU_CREATE_GANG			0x0002
+
+#define SPU_CREATE_FLAG_ALL		0x0003 /* mask of all valid flags */
+
 
 #ifdef CONFIG_SPU_FS_MODULE
 int register_spu_syscalls(struct spufs_calls *calls);

--

^ permalink raw reply

* [PATCH 06/14] spufs: use correct pg_prot for mapping spu LS
From: Arnd Bergmann @ 2006-10-04 15:26 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: Arnd Bergmann, linuxppc-dev, cbe-oss-dev, linux-kernel
In-Reply-To: <20061004152610.151599000@dyn-9-152-242-103.boeblingen.de.ibm.com>

This hopefully fixes a long-standing bug in the spu file system.
An spu context comes with local memory that can be either saved
in kernel pages or point directly to a physical SPE.

When mapping the physical SPE, that mapping needs to be cache-inhibited.
For simplicity, we used to map the kernel backing memory that way
too, but unfortunately that was not only inefficient, but also incorrect
because the same page could then be accessed simultaneously through
a cacheable and a cache-inhibited mapping, which is not allowed
by the powerpc specification and in our case caused data inconsistency
for which we did a really ugly workaround in user space.

Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>

Index: linux-2.6/arch/powerpc/platforms/cell/spufs/file.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/file.c
+++ linux-2.6/arch/powerpc/platforms/cell/spufs/file.c
@@ -102,12 +102,16 @@ spufs_mem_mmap_nopage(struct vm_area_str
 
 	spu_acquire(ctx);
 
-	if (ctx->state == SPU_STATE_SAVED)
+	if (ctx->state == SPU_STATE_SAVED) {
+		vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
+					& ~(_PAGE_NO_CACHE | _PAGE_GUARDED));
 		page = vmalloc_to_page(ctx->csa.lscsa->ls + offset);
-	else
+	} else {
+		vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
+					| _PAGE_NO_CACHE | _PAGE_GUARDED);
 		page = pfn_to_page((ctx->spu->local_store_phys + offset)
 				   >> PAGE_SHIFT);
-
+	}
 	spu_release(ctx);
 
 	if (type)

--

^ permalink raw reply

* [PATCH 07/14] spufs: make mailbox functions handle multiple elements
From: Arnd Bergmann @ 2006-10-04 15:26 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: Arnd Bergmann, linuxppc-dev, cbe-oss-dev, linux-kernel
In-Reply-To: <20061004152610.151599000@dyn-9-152-242-103.boeblingen.de.ibm.com>

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 6171 bytes --]

Since libspe2 will provide a function that can read/write
multiple mailbox elements at once, the kernel should handle
that efficiently.

read/write on the three mailbox files can now access the
spe context multiple times to operate on any number of
mailbox data elements.

If the spu application keeps writing to its outbound
mailbox, the read call will pick up all the data in a
single system call.

Unfortunately, if the user passes an invalid pointer,
we may lose a mailbox element on read, since we can't
put it back. This probably impossible to solve, if the
user also accesses the mailbox through direct register
access.

Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>

Index: linux-2.6/arch/powerpc/platforms/cell/spufs/file.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/file.c
+++ linux-2.6/arch/powerpc/platforms/cell/spufs/file.c
@@ -354,27 +354,54 @@ static int spufs_pipe_open(struct inode 
 	return nonseekable_open(inode, file);
 }
 
+/*
+ * Read as many bytes from the mailbox as possible, until
+ * one of the conditions becomes true:
+ *
+ * - no more data available in the mailbox
+ * - end of the user provided buffer
+ * - end of the mapped area
+ */
 static ssize_t spufs_mbox_read(struct file *file, char __user *buf,
 			size_t len, loff_t *pos)
 {
 	struct spu_context *ctx = file->private_data;
-	u32 mbox_data;
-	int ret;
+	u32 mbox_data, __user *udata;
+	ssize_t count;
 
 	if (len < 4)
 		return -EINVAL;
 
+	if (!access_ok(VERIFY_WRITE, buf, len))
+		return -EFAULT;
+
+	udata = (void __user *)buf;
+
 	spu_acquire(ctx);
-	ret = ctx->ops->mbox_read(ctx, &mbox_data);
+	for (count = 0; count <= len; count += 4, udata++) {
+		int ret;
+		ret = ctx->ops->mbox_read(ctx, &mbox_data);
+		if (ret == 0)
+			break;
+
+		/*
+		 * at the end of the mapped area, we can fault
+		 * but still need to return the data we have
+		 * read successfully so far.
+		 */
+		ret = __put_user(mbox_data, udata);
+		if (ret) {
+			if (!count)
+				count = -EFAULT;
+			break;
+		}
+	}
 	spu_release(ctx);
 
-	if (!ret)
-		return -EAGAIN;
-
-	if (copy_to_user(buf, &mbox_data, sizeof mbox_data))
-		return -EFAULT;
+	if (!count)
+		count = -EAGAIN;
 
-	return 4;
+	return count;
 }
 
 static struct file_operations spufs_mbox_fops = {
@@ -430,36 +457,70 @@ void spufs_ibox_callback(struct spu *spu
 	kill_fasync(&ctx->ibox_fasync, SIGIO, POLLIN);
 }
 
+/*
+ * Read as many bytes from the interrupt mailbox as possible, until
+ * one of the conditions becomes true:
+ *
+ * - no more data available in the mailbox
+ * - end of the user provided buffer
+ * - end of the mapped area
+ *
+ * If the file is opened without O_NONBLOCK, we wait here until
+ * any data is available, but return when we have been able to
+ * read something.
+ */
 static ssize_t spufs_ibox_read(struct file *file, char __user *buf,
 			size_t len, loff_t *pos)
 {
 	struct spu_context *ctx = file->private_data;
-	u32 ibox_data;
-	ssize_t ret;
+	u32 ibox_data, __user *udata;
+	ssize_t count;
 
 	if (len < 4)
 		return -EINVAL;
 
+	if (!access_ok(VERIFY_WRITE, buf, len))
+		return -EFAULT;
+
+	udata = (void __user *)buf;
+
 	spu_acquire(ctx);
 
-	ret = 0;
+	/* wait only for the first element */
+	count = 0;
 	if (file->f_flags & O_NONBLOCK) {
 		if (!spu_ibox_read(ctx, &ibox_data))
-			ret = -EAGAIN;
+			count = -EAGAIN;
 	} else {
-		ret = spufs_wait(ctx->ibox_wq, spu_ibox_read(ctx, &ibox_data));
+		count = spufs_wait(ctx->ibox_wq, spu_ibox_read(ctx, &ibox_data));
 	}
+	if (count)
+		goto out;
 
-	spu_release(ctx);
+	/* if we can't write at all, return -EFAULT */
+	count = __put_user(ibox_data, udata);
+	if (count)
+		goto out;
 
-	if (ret)
-		return ret;
+	for (count = 4, udata++; (count + 4) <= len; count += 4, udata++) {
+		int ret;
+		ret = ctx->ops->ibox_read(ctx, &ibox_data);
+		if (ret == 0)
+			break;
+		/*
+		 * at the end of the mapped area, we can fault
+		 * but still need to return the data we have
+		 * read successfully so far.
+		 */
+		ret = __put_user(ibox_data, udata);
+		if (ret)
+			break;
+	}
 
-	ret = 4;
-	if (copy_to_user(buf, &ibox_data, sizeof ibox_data))
-		ret = -EFAULT;
+out:
+	spu_release(ctx);
 
-	return ret;
+	return count;
 }
 
 static unsigned int spufs_ibox_poll(struct file *file, poll_table *wait)
@@ -532,32 +593,67 @@ void spufs_wbox_callback(struct spu *spu
 	kill_fasync(&ctx->wbox_fasync, SIGIO, POLLOUT);
 }
 
+/*
+ * Write as many bytes to the interrupt mailbox as possible, until
+ * one of the conditions becomes true:
+ *
+ * - the mailbox is full
+ * - end of the user provided buffer
+ * - end of the mapped area
+ *
+ * If the file is opened without O_NONBLOCK, we wait here until
+ * space is availabyl, but return when we have been able to
+ * write something.
+ */
 static ssize_t spufs_wbox_write(struct file *file, const char __user *buf,
 			size_t len, loff_t *pos)
 {
 	struct spu_context *ctx = file->private_data;
-	u32 wbox_data;
-	int ret;
+	u32 wbox_data, __user *udata;
+	ssize_t count;
 
 	if (len < 4)
 		return -EINVAL;
 
-	if (copy_from_user(&wbox_data, buf, sizeof wbox_data))
+	udata = (void __user *)buf;
+	if (!access_ok(VERIFY_READ, buf, len))
+		return -EFAULT;
+
+	if (__get_user(wbox_data, udata))
 		return -EFAULT;
 
 	spu_acquire(ctx);
 
-	ret = 0;
+	/*
+	 * make sure we can at least write one element, by waiting
+	 * in case of !O_NONBLOCK
+	 */
+	count = 0;
 	if (file->f_flags & O_NONBLOCK) {
 		if (!spu_wbox_write(ctx, wbox_data))
-			ret = -EAGAIN;
+			count = -EAGAIN;
 	} else {
-		ret = spufs_wait(ctx->wbox_wq, spu_wbox_write(ctx, wbox_data));
+		count = spufs_wait(ctx->wbox_wq, spu_wbox_write(ctx, wbox_data));
 	}
 
-	spu_release(ctx);
+	if (count)
+		goto out;
+
+	/* write aѕ much as possible */
+	for (count = 4, udata++; (count + 4) <= len; count += 4, udata++) {
+		int ret;
+		ret = __get_user(wbox_data, udata);
+		if (ret)
+			break;
+
+		ret = spu_wbox_write(ctx, wbox_data);
+		if (ret == 0)
+			break;
+	}
 
-	return ret ? ret : sizeof wbox_data;
+out:
+	spu_release(ctx);
+	return count;
 }
 
 static unsigned int spufs_wbox_poll(struct file *file, poll_table *wait)

--

^ permalink raw reply

* [PATCH 08/14] spufs: remove support for ancient firmware
From: Arnd Bergmann @ 2006-10-04 15:26 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: Arnd Bergmann, linuxppc-dev, cbe-oss-dev, linux-kernel
In-Reply-To: <20061004152610.151599000@dyn-9-152-242-103.boeblingen.de.ibm.com>

Any firmware that still uses the 'spc' nodes already
stopped running for other reasons, so lets get rid of this.

Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>

Index: linux-2.6/arch/powerpc/platforms/cell/spu_base.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/spu_base.c
+++ linux-2.6/arch/powerpc/platforms/cell/spu_base.c
@@ -791,18 +791,6 @@ static int __init init_spu_base(void)
 			break;
 		}
 	}
-	/* in some old firmware versions, the spe is called 'spc', so we
-	   look for that as well */
-	for (node = of_find_node_by_type(NULL, "spc");
-			node; node = of_find_node_by_type(node, "spc")) {
-		ret = create_spu(node);
-		if (ret) {
-			printk(KERN_WARNING "%s: Error initializing %s\n",
-				__FUNCTION__, node->name);
-			cleanup_spu_base();
-			break;
-		}
-	}
 	return ret;
 }
 module_init(init_spu_base);

--

^ permalink raw reply

* [PATCH 09/14] spufs: add support for read/write on cntl
From: Arnd Bergmann @ 2006-10-04 15:26 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: Arnd Bergmann, linuxppc-dev, cbe-oss-dev, linux-kernel
In-Reply-To: <20061004152610.151599000@dyn-9-152-242-103.boeblingen.de.ibm.com>

Writing to cntl can be used to stop execution on the
spu and to restart it, reading from cntl gives the
contents of the current status register.

The access is always in ascii, as for most other files.

This was always meant to be there, but we had a little
problem with writing to runctl so it was left out so
far.

Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>

Index: linux-2.6/arch/powerpc/platforms/cell/spufs/file.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/file.c
+++ linux-2.6/arch/powerpc/platforms/cell/spufs/file.c
@@ -211,37 +211,43 @@ static int spufs_cntl_mmap(struct file *
 #define spufs_cntl_mmap NULL
 #endif /* !SPUFS_MMAP_4K */
 
-static int spufs_cntl_open(struct inode *inode, struct file *file)
+static u64 spufs_cntl_get(void *data)
 {
-	struct spufs_inode_info *i = SPUFS_I(inode);
-	struct spu_context *ctx = i->i_ctx;
+	struct spu_context *ctx = data;
+	u64 val;
 
-	file->private_data = ctx;
-	file->f_mapping = inode->i_mapping;
-	ctx->cntl = inode->i_mapping;
-	return 0;
+	spu_acquire(ctx);
+	val = ctx->ops->status_read(ctx);
+	spu_release(ctx);
+
+	return val;
 }
 
-static ssize_t
-spufs_cntl_read(struct file *file, char __user *buffer,
-		size_t size, loff_t *pos)
+static void spufs_cntl_set(void *data, u64 val)
 {
-	/* FIXME: read from spu status */
-	return -EINVAL;
+	struct spu_context *ctx = data;
+
+	spu_acquire(ctx);
+	ctx->ops->runcntl_write(ctx, val);
+	spu_release(ctx);
 }
 
-static ssize_t
-spufs_cntl_write(struct file *file, const char __user *buffer,
-		 size_t size, loff_t *pos)
+static int spufs_cntl_open(struct inode *inode, struct file *file)
 {
-	/* FIXME: write to runctl bit */
-	return -EINVAL;
+	struct spufs_inode_info *i = SPUFS_I(inode);
+	struct spu_context *ctx = i->i_ctx;
+
+	file->private_data = ctx;
+	file->f_mapping = inode->i_mapping;
+	ctx->cntl = inode->i_mapping;
+	return simple_attr_open(inode, file, spufs_cntl_get,
+					spufs_cntl_set, "0x%08lx");
 }
 
 static struct file_operations spufs_cntl_fops = {
 	.open = spufs_cntl_open,
-	.read = spufs_cntl_read,
-	.write = spufs_cntl_write,
+	.read = simple_attr_read,
+	.write = simple_attr_write,
 	.mmap = spufs_cntl_mmap,
 };
 

--

^ permalink raw reply

* [PATCH 10/14] spufs: support new OF device tree format
From: Arnd Bergmann @ 2006-10-04 15:26 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: Arnd Bergmann, linuxppc-dev, cbe-oss-dev, linux-kernel
In-Reply-To: <20061004152610.151599000@dyn-9-152-242-103.boeblingen.de.ibm.com>

The properties we used traditionally in the device tree
are somewhat nonstandard, this adds support for a more
conventional format using 'interrupts' and 'reg'
properties.

The interrupts are specified in three cells (class 0,
1 and 2) and registered at the interrupt-parent.

The reg property contains either three or four register
areas in the order 'local-store', 'problem', 'priv2',
and 'priv1', so the priv1 one can be left out in
case of hypervisor driven systems that access these
through hcalls.

Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>

Index: linux-2.6/arch/powerpc/platforms/cell/spu_base.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/spu_base.c
+++ linux-2.6/arch/powerpc/platforms/cell/spu_base.c
@@ -25,11 +25,13 @@
 #include <linux/interrupt.h>
 #include <linux/list.h>
 #include <linux/module.h>
+#include <linux/pci.h>
 #include <linux/poll.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/wait.h>
 
+#include <asm/firmware.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <linux/mutex.h>
@@ -576,7 +578,7 @@ static void spu_unmap(struct spu *spu)
 }
 
 /* This function shall be abstracted for HV platforms */
-static int __init spu_map_interrupts(struct spu *spu, struct device_node *np)
+static int __init spu_map_interrupts_old(struct spu *spu, struct device_node *np)
 {
 	unsigned int isrc;
 	const u32 *tmp;
@@ -600,7 +602,7 @@ static int __init spu_map_interrupts(str
 	return spu->irqs[2] == NO_IRQ ? -EINVAL : 0;
 }
 
-static int __init spu_map_device(struct spu *spu, struct device_node *node)
+static int __init spu_map_device_old(struct spu *spu, struct device_node *node)
 {
 	const char *prop;
 	int ret;
@@ -645,6 +647,88 @@ out:
 	return ret;
 }
 
+static int __init spu_map_interrupts(struct spu *spu, struct device_node *np)
+{
+	struct of_irq oirq;
+	int ret;
+	int i;
+
+	for (i=0; i < 3; i++) {
+		ret = of_irq_map_one(np, i, &oirq);
+		if (ret)
+			goto err;
+
+		ret = -EINVAL;
+		spu->irqs[i] = irq_create_of_mapping(oirq.controller,
+					oirq.specifier, oirq.size);
+		if (spu->irqs[i] == NO_IRQ)
+			goto err;
+	}
+	return 0;
+
+err:
+	pr_debug("failed to map irq %x for spu %s\n", *oirq.specifier, spu->name);
+	for (; i >= 0; i--) {
+		if (spu->irqs[i] != NO_IRQ)
+			irq_dispose_mapping(spu->irqs[i]);
+	}
+	return ret;
+}
+
+static int spu_map_resource(struct device_node *node, int nr,
+		void __iomem** virt, unsigned long *phys)
+{
+	struct resource resource = { };
+	int ret;
+
+	ret = of_address_to_resource(node, 0, &resource);
+	if (ret)
+		goto out;
+
+	if (phys)
+		*phys = resource.start;
+	*virt = ioremap(resource.start, resource.end - resource.start);
+	if (!*virt)
+		ret = -EINVAL;
+
+out:
+	return ret;
+}
+
+static int __init spu_map_device(struct spu *spu, struct device_node *node)
+{
+	int ret = -ENODEV;
+	spu->name = get_property(node, "name", NULL);
+	if (!spu->name)
+		goto out;
+
+	ret = spu_map_resource(node, 0, (void __iomem**)&spu->local_store,
+					&spu->local_store_phys);
+	if (ret)
+		goto out;
+	ret = spu_map_resource(node, 1, (void __iomem**)&spu->problem,
+					&spu->problem_phys);
+	if (ret)
+		goto out_unmap;
+	ret = spu_map_resource(node, 2, (void __iomem**)&spu->priv2,
+					NULL);
+	if (ret)
+		goto out_unmap;
+
+	if (!firmware_has_feature(FW_FEATURE_LPAR))
+		ret = spu_map_resource(node, 3, (void __iomem**)&spu->priv1,
+					NULL);
+	if (ret)
+		goto out_unmap;
+	return 0;
+
+out_unmap:
+	spu_unmap(spu);
+out:
+	pr_debug("failed to map spe %s: %d\n", spu->name, ret);
+	return ret;
+}
+
 struct sysdev_class spu_sysdev_class = {
 	set_kset_name("spu")
 };
@@ -698,6 +782,9 @@ static int __init create_spu(struct devi
 		goto out;
 
 	ret = spu_map_device(spu, spe);
+	/* try old method */
+	if (ret)
+		ret = spu_map_device_old(spu, spe);
 	if (ret)
 		goto out_free;
 
@@ -707,6 +794,8 @@ static int __init create_spu(struct devi
 		spu->nid = 0;
 	ret = spu_map_interrupts(spu, spe);
 	if (ret)
+		ret = spu_map_interrupts_old(spu, spe);
+	if (ret)
 		goto out_unmap;
 	spin_lock_init(&spu->register_lock);
 	spu_mfc_sdr_set(spu, mfspr(SPRN_SDR1));
@@ -716,7 +805,7 @@ static int __init create_spu(struct devi
 	spu->number = number++;
 	ret = spu_request_irqs(spu);
 	if (ret)
-		goto out_unmap;
+		goto out_unlock;
 
 	ret = spu_create_sysdev(spu);
 	if (ret)
@@ -732,9 +821,9 @@ static int __init create_spu(struct devi
 
 out_free_irqs:
 	spu_free_irqs(spu);
-
-out_unmap:
+out_unlock:
 	mutex_unlock(&spu_mutex);
+out_unmap:
 	spu_unmap(spu);
 out_free:
 	kfree(spu);

--

^ permalink raw reply

* [PATCH 11/14] spufs: add infrastructure for finding elf objects
From: Arnd Bergmann @ 2006-10-04 15:26 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: Arnd Bergmann, linuxppc-dev, cbe-oss-dev, linux-kernel
In-Reply-To: <20061004152610.151599000@dyn-9-152-242-103.boeblingen.de.ibm.com>

This adds an 'object-id' file that the spe library can
use to store a pointer to its ELF object. This was
originally meant for use by oprofile, but is now
also used by the GNU debugger, if available.

In order for oprofile to find the location in an spu-elf
binary where an event counter triggered, we need a way
to identify the binary in the first place.

Unfortunately, that binary itself can be embedded in a
powerpc ELF binary. Since we can assume it is mapped into
the effective address space of the running process,
have that one write the pointer value into a new spufs
file.

When a context switch occurs, pass the user value to
the profiler so that can look at the mapped file (with
some care).

Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>

Index: linux-2.6/arch/powerpc/platforms/cell/spufs/file.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/file.c
+++ linux-2.6/arch/powerpc/platforms/cell/spufs/file.c
@@ -1487,6 +1487,21 @@ static u64 spufs_id_get(void *data)
 }
 DEFINE_SIMPLE_ATTRIBUTE(spufs_id_ops, spufs_id_get, NULL, "0x%llx\n")
 
+static u64 spufs_object_id_get(void *data)
+{
+	struct spu_context *ctx = data;
+	return ctx->object_id;
+}
+
+static void spufs_object_id_set(void *data, u64 id)
+{
+	struct spu_context *ctx = data;
+	ctx->object_id = id;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(spufs_object_id_ops, spufs_object_id_get,
+		spufs_object_id_set, "0x%llx\n");
+
 struct tree_descr spufs_dir_contents[] = {
 	{ "mem",  &spufs_mem_fops,  0666, },
 	{ "regs", &spufs_regs_fops,  0666, },
@@ -1510,7 +1525,8 @@ struct tree_descr spufs_dir_contents[] =
 	{ "spu_tag_mask", &spufs_spu_tag_mask_ops, 0666, },
 	{ "event_mask", &spufs_event_mask_ops, 0666, },
 	{ "srr0", &spufs_srr0_ops, 0666, },
-	{ "phys-id", &spufs_id_ops, 0666, },
 	{ "psmap", &spufs_psmap_fops, 0666, },
+	{ "phys-id", &spufs_id_ops, 0666, },
+	{ "object-id", &spufs_object_id_ops, 0666, },
 	{},
 };
Index: linux-2.6/arch/powerpc/platforms/cell/spufs/spufs.h
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/spufs.h
+++ linux-2.6/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -50,6 +50,7 @@ struct spu_context {
 	struct address_space *cntl; 	   /* 'control' area mappings. */
 	struct address_space *signal1; 	   /* 'signal1' area mappings. */
 	struct address_space *signal2; 	   /* 'signal2' area mappings. */
+	u64 object_id;		   /* user space pointer for oprofile */
 
 	enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state;
 	struct rw_semaphore state_sema;
Index: linux-2.6/arch/powerpc/platforms/cell/spufs/sched.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/sched.c
+++ linux-2.6/arch/powerpc/platforms/cell/spufs/sched.c
@@ -35,6 +35,7 @@
 #include <linux/unistd.h>
 #include <linux/numa.h>
 #include <linux/mutex.h>
+#include <linux/notifier.h>
 
 #include <asm/io.h>
 #include <asm/mmu_context.h>
@@ -75,6 +76,25 @@ static inline void mm_needs_global_tlbie
 	__cpus_setall(&mm->cpu_vm_mask, nr);
 }
 
+static BLOCKING_NOTIFIER_HEAD(spu_switch_notifier);
+
+static void spu_switch_notify(struct spu *spu, struct spu_context *ctx)
+{
+	blocking_notifier_call_chain(&spu_switch_notifier,
+			    ctx ? ctx->object_id : 0, spu);
+}
+
+int spu_switch_event_register(struct notifier_block * n)
+{
+	return blocking_notifier_chain_register(&spu_switch_notifier, n);
+}
+
+int spu_switch_event_unregister(struct notifier_block * n)
+{
+	return blocking_notifier_chain_unregister(&spu_switch_notifier, n);
+}
+
+
 static inline void bind_context(struct spu *spu, struct spu_context *ctx)
 {
 	pr_debug("%s: pid=%d SPU=%d NODE=%d\n", __FUNCTION__, current->pid,
@@ -97,12 +117,14 @@ static inline void bind_context(struct s
 	spu_restore(&ctx->csa, spu);
 	spu->timestamp = jiffies;
 	spu_cpu_affinity_set(spu, raw_smp_processor_id());
+	spu_switch_notify(spu, ctx);
 }
 
 static inline void unbind_context(struct spu *spu, struct spu_context *ctx)
 {
 	pr_debug("%s: unbind pid=%d SPU=%d NODE=%d\n", __FUNCTION__,
 		 spu->pid, spu->number, spu->node);
+	spu_switch_notify(spu, NULL);
 	spu_unmap_mappings(ctx);
 	spu_save(&ctx->csa, spu);
 	spu->timestamp = jiffies;
Index: linux-2.6/include/asm-powerpc/spu.h
===================================================================
--- linux-2.6.orig/include/asm-powerpc/spu.h
+++ linux-2.6/include/asm-powerpc/spu.h
@@ -201,6 +201,24 @@ static inline void unregister_spu_syscal
 
 
 /*
+ * Notifier blocks:
+ *
+ * oprofile can get notified when a context switch is performed
+ * on an spe. The notifer function that gets called is passed
+ * a pointer to the SPU structure as well as the object-id that
+ * identifies the binary running on that SPU now.
+ *
+ * For a context save, the object-id that is passed is zero,
+ * identifying that the kernel will run from that moment on.
+ *
+ * For a context restore, the object-id is the value written
+ * to object-id spufs file from user space and the notifer
+ * function can assume that spu->ctx is valid.
+ */
+int spu_switch_event_register(struct notifier_block * n);
+int spu_switch_event_unregister(struct notifier_block * n);
+
+/*
  * This defines the Local Store, Problem Area and Privlege Area of an SPU.
  */
 

--

^ permalink raw reply

* [PATCH 12/14] powerpc: update cell_defconfig
From: Arnd Bergmann @ 2006-10-04 15:26 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: Arnd Bergmann, linuxppc-dev, cbe-oss-dev, linux-kernel
In-Reply-To: <20061004152610.151599000@dyn-9-152-242-103.boeblingen.de.ibm.com>

This adds defaults for new configuration options added since
2.6.18 and it enables the option for 64kb pages by default.

Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Index: linux-2.6/arch/powerpc/configs/cell_defconfig
===================================================================
--- linux-2.6.orig/arch/powerpc/configs/cell_defconfig
+++ linux-2.6/arch/powerpc/configs/cell_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc6
-# Sun Sep 10 10:20:32 2006
+# Linux kernel version: 2.6.18
+# Wed Oct  4 15:30:50 2006
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -22,6 +22,7 @@ CONFIG_ARCH_MAY_HAVE_PC_FDC=y
 CONFIG_PPC_OF=y
 CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
 # CONFIG_DEFAULT_UIMAGE is not set
 
 #
@@ -52,10 +53,11 @@ CONFIG_LOCALVERSION=""
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
-CONFIG_SYSCTL=y
+# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
@@ -63,7 +65,9 @@ CONFIG_CPUSETS=y
 # CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
 # CONFIG_EMBEDDED is not set
+# CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -72,12 +76,12 @@ CONFIG_PRINTK=y
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -96,6 +100,7 @@ CONFIG_STOP_MACHINE=y
 #
 # Block layer
 #
+CONFIG_BLOCK=y
 # CONFIG_BLK_DEV_IO_TRACE is not set
 
 #
@@ -115,12 +120,13 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
 # Platform support
 #
 CONFIG_PPC_MULTIPLATFORM=y
-# CONFIG_PPC_ISERIES is not set
 # CONFIG_EMBEDDED6xx is not set
 # CONFIG_APUS is not set
 # CONFIG_PPC_PSERIES is not set
+# CONFIG_PPC_ISERIES is not set
 # CONFIG_PPC_PMAC is not set
 # CONFIG_PPC_MAPLE is not set
+# CONFIG_PPC_PASEMI is not set
 CONFIG_PPC_CELL=y
 CONFIG_PPC_CELL_NATIVE=y
 CONFIG_PPC_IBM_CELL_BLADE=y
@@ -142,7 +148,6 @@ CONFIG_MMIO_NVRAM=y
 #
 CONFIG_SPU_FS=m
 CONFIG_SPU_BASE=y
-CONFIG_SPUFS_MMAP=y
 CONFIG_CBE_RAS=y
 
 #
@@ -158,7 +163,7 @@ CONFIG_PREEMPT_NONE=y
 CONFIG_PREEMPT_BKL=y
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=m
-CONFIG_FORCE_MAX_ZONEORDER=13
+CONFIG_FORCE_MAX_ZONEORDER=9
 # CONFIG_IOMMU_VMERGE is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_KEXEC=y
@@ -168,6 +173,7 @@ CONFIG_NUMA=y
 CONFIG_NODES_SHIFT=4
 CONFIG_ARCH_SELECT_MEMORY_MODEL=y
 CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_SELECT_MEMORY_MODEL=y
 # CONFIG_FLATMEM_MANUAL is not set
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -178,12 +184,12 @@ CONFIG_HAVE_MEMORY_PRESENT=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPARSEMEM_EXTREME=y
 CONFIG_MEMORY_HOTPLUG=y
+CONFIG_MEMORY_HOTPLUG_SPARSE=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
 CONFIG_MIGRATION=y
 CONFIG_RESOURCES_64BIT=y
-CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
 CONFIG_ARCH_MEMORY_PROBE=y
-# CONFIG_PPC_64K_PAGES is not set
+CONFIG_PPC_64K_PAGES=y
 CONFIG_SCHED_SMT=y
 CONFIG_PROC_DEVICETREE=y
 # CONFIG_CMDLINE_BOOL is not set
@@ -201,6 +207,7 @@ CONFIG_GENERIC_ISA_DMA=y
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 CONFIG_PCIEPORTBUS=y
+# CONFIG_PCI_MULTITHREAD_PROBE is not set
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -228,6 +235,7 @@ CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -249,7 +257,8 @@ CONFIG_INET_XFRM_MODE_TUNNEL=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
 
 #
 # IP: Virtual Server Configuration
@@ -261,11 +270,15 @@ CONFIG_IPV6=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+# CONFIG_IPV6_MIP6 is not set
 CONFIG_INET6_XFRM_TUNNEL=m
 CONFIG_INET6_TUNNEL=m
 CONFIG_INET6_XFRM_MODE_TRANSPORT=y
 CONFIG_INET6_XFRM_MODE_TUNNEL=y
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
 CONFIG_IPV6_TUNNEL=m
+# CONFIG_IPV6_SUBTREES is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
 # CONFIG_NETWORK_SECMARK is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
@@ -322,7 +335,6 @@ CONFIG_IP_NF_QUEUE=m
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 
@@ -434,6 +446,7 @@ CONFIG_BLK_DEV_AEC62XX=y
 # CONFIG_BLK_DEV_CS5530 is not set
 # CONFIG_BLK_DEV_HPT34X is not set
 # CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_PIIX is not set
 # CONFIG_BLK_DEV_IT821X is not set
@@ -456,6 +469,12 @@ CONFIG_IDEDMA_AUTO=y
 #
 # CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -470,6 +489,7 @@ CONFIG_MD_RAID1=m
 # CONFIG_MD_MULTIPATH is not set
 # CONFIG_MD_FAULTY is not set
 CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_MIRROR=m
@@ -504,7 +524,7 @@ CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 CONFIG_BONDING=y
 # CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
+CONFIG_TUN=y
 
 #
 # ARCnet devices
@@ -552,7 +572,7 @@ CONFIG_SKGE=m
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 CONFIG_SPIDER_NET=m
-# CONFIG_MV643XX_ETH is not set
+# CONFIG_QLA3XXX is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -599,6 +619,7 @@ CONFIG_SPIDER_NET=m
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
 
 #
 # Userland interfaces
@@ -865,6 +886,7 @@ CONFIG_INFINIBAND_USER_ACCESS=m
 CONFIG_INFINIBAND_ADDR_TRANS=y
 CONFIG_INFINIBAND_MTHCA=m
 CONFIG_INFINIBAND_MTHCA_DEBUG=y
+# CONFIG_INFINIBAND_AMSO1100 is not set
 CONFIG_INFINIBAND_IPOIB=m
 CONFIG_INFINIBAND_IPOIB_DEBUG=y
 CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y
@@ -916,7 +938,7 @@ CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
+CONFIG_AUTOFS4_FS=m
 # CONFIG_FUSE_FS is not set
 
 #
@@ -943,8 +965,10 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
 CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
@@ -1084,6 +1108,7 @@ CONFIG_PLIST=y
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
 CONFIG_DEBUG_KERNEL=y
@@ -1102,6 +1127,7 @@ CONFIG_DEBUG_SPINLOCK_SLEEP=y
 # CONFIG_DEBUG_INFO is not set
 CONFIG_DEBUG_FS=y
 # CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
 # CONFIG_FORCED_INLINING is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_DEBUG_STACKOVERFLOW is not set
@@ -1123,6 +1149,10 @@ CONFIG_IRQSTACKS=y
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=y
+# CONFIG_CRYPTO_MANAGER is not set
 CONFIG_CRYPTO_HMAC=y
 # CONFIG_CRYPTO_NULL is not set
 # CONFIG_CRYPTO_MD4 is not set
@@ -1132,6 +1162,8 @@ CONFIG_CRYPTO_SHA1=m
 # CONFIG_CRYPTO_SHA512 is not set
 # CONFIG_CRYPTO_WP512 is not set
 # CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
 CONFIG_CRYPTO_DES=m
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set

--

^ permalink raw reply

* [PATCH 13/14] spiderpic: enable new style devtree support
From: Arnd Bergmann @ 2006-10-04 15:26 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: Arnd Bergmann, linuxppc-dev, cbe-oss-dev, linux-kernel
In-Reply-To: <20061004152610.151599000@dyn-9-152-242-103.boeblingen.de.ibm.com>

This enables support for new firmware test releases.

Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>

Index: linux-2.6/arch/powerpc/platforms/cell/spider-pic.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/spider-pic.c
+++ linux-2.6/arch/powerpc/platforms/cell/spider-pic.c
@@ -244,7 +244,6 @@ static unsigned int __init spider_find_c
 	int imaplen, intsize, unit;
 	struct device_node *iic;
 
-#if 0 /* Enable that when we have a way to retreive the node as well */
 	/* First, we check wether we have a real "interrupts" in the device
 	 * tree in case the device-tree is ever fixed
 	 */
@@ -252,9 +251,8 @@ static unsigned int __init spider_find_c
 	if (of_irq_map_one(pic->of_node, 0, &oirq) == 0) {
 		virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
 					     oirq.size);
-		goto bail;
+		return virq;
 	}
-#endif
 
 	/* Now do the horrible hacks */
 	tmp = get_property(pic->of_node, "#interrupt-cells", NULL);

--

^ permalink raw reply

* [PATCH 14/14] cell: fix bugs found by sparse
From: Arnd Bergmann @ 2006-10-04 15:26 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: Arnd Bergmann, linuxppc-dev, cbe-oss-dev, linux-kernel
In-Reply-To: <20061004152610.151599000@dyn-9-152-242-103.boeblingen.de.ibm.com>

- Some long constants should be marked 'ul'.
- When using desc->handler_data to pass an __iomem
  register area, we need to add casts to and from
  __iomem.

Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Index: linux-2.6/arch/powerpc/platforms/cell/interrupt.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/interrupt.c
+++ linux-2.6/arch/powerpc/platforms/cell/interrupt.c
@@ -101,7 +101,7 @@ static void iic_ioexc_eoi(unsigned int i
 static void iic_ioexc_cascade(unsigned int irq, struct irq_desc *desc,
 			    struct pt_regs *regs)
 {
-	struct cbe_iic_regs *node_iic = desc->handler_data;
+	struct cbe_iic_regs __iomem *node_iic = (void __iomem *)desc->handler_data;
 	unsigned int base = (irq & 0xffffff00) | IIC_IRQ_TYPE_IOEXC;
 	unsigned long bits, ack;
 	int cascade;
@@ -320,7 +320,7 @@ static int __init setup_iic(void)
 	struct device_node *dn;
 	struct resource r0, r1;
 	unsigned int node, cascade, found = 0;
-	struct cbe_iic_regs *node_iic;
+	struct cbe_iic_regs __iomem *node_iic;
 	const u32 *np;
 
 	for (dn = NULL;
@@ -357,7 +357,11 @@ static int __init setup_iic(void)
 		cascade = irq_create_mapping(iic_host, cascade);
 		if (cascade == NO_IRQ)
 			continue;
-		set_irq_data(cascade, node_iic);
+		/*
+		 * irq_data is a generic pointer that gets passed back
+		 * to us later, so the forced cast is fine.
+		 */
+		set_irq_data(cascade, (void __force *)node_iic);
 		set_irq_chained_handler(cascade , iic_ioexc_cascade);
 		out_be64(&node_iic->iic_ir,
 			 (1 << 12)		/* priority */ |
Index: linux-2.6/arch/powerpc/platforms/cell/iommu.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/iommu.c
+++ linux-2.6/arch/powerpc/platforms/cell/iommu.c
@@ -345,8 +345,8 @@ static int cell_map_iommu_hardcoded(int 
 
 	/* node 0 */
 	iommu = &cell_iommus[0];
-	iommu->mapped_base = ioremap(0x20000511000, 0x1000);
-	iommu->mapped_mmio_base = ioremap(0x20000510000, 0x1000);
+	iommu->mapped_base = ioremap(0x20000511000ul, 0x1000);
+	iommu->mapped_mmio_base = ioremap(0x20000510000ul, 0x1000);
 
 	enable_mapping(iommu->mapped_base, iommu->mapped_mmio_base);
 
@@ -358,8 +358,8 @@ static int cell_map_iommu_hardcoded(int 
 
 	/* node 1 */
 	iommu = &cell_iommus[1];
-	iommu->mapped_base = ioremap(0x30000511000, 0x1000);
-	iommu->mapped_mmio_base = ioremap(0x30000510000, 0x1000);
+	iommu->mapped_base = ioremap(0x30000511000ul, 0x1000);
+	iommu->mapped_mmio_base = ioremap(0x30000510000ul, 0x1000);
 
 	enable_mapping(iommu->mapped_base, iommu->mapped_mmio_base);
 
Index: linux-2.6/arch/powerpc/platforms/cell/spider-pic.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/spider-pic.c
+++ linux-2.6/arch/powerpc/platforms/cell/spider-pic.c
@@ -367,7 +367,7 @@ void __init spider_init_IRQ(void)
 		} else if (device_is_compatible(dn, "sti,platform-spider-pic")
 			   && (chip < 2)) {
 			static long hard_coded_pics[] =
-				{ 0x24000008000, 0x34000008000 };
+				{ 0x24000008000ul, 0x34000008000ul};
 			r.start = hard_coded_pics[chip];
 		} else
 			continue;

--

^ permalink raw reply

* Re: uboot-1.1.4 linux-2.6.10: Image bootproblems
From: Wolfgang Denk @ 2006-10-04 15:40 UTC (permalink / raw)
  To: Armin Steck; +Cc: linuxppc-embedded
In-Reply-To: <20061004090425.57760@gmx.net>

In message <20061004090425.57760@gmx.net> you wrote:
> 
> uboot==> bootm 0x00040000
> ## Booting image at 00040000 ...
>    Image Name:   Linux-2.6.10
>    Image Type:   ARM Linux Kernel Image (gzip compressed)

You are off topic here. This is the PowerPC list.

Best regards,

Wolfgang Denk

-- 
Software Engineering:  Embedded and Realtime Systems,  Embedded Linux
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
You see things; and you say ``Why?'' But I dream  things  that  never
were; and I say ``Why not?''
       - George Bernard Shaw _Back to Methuselah_ (1921) pt. 1, act 1

^ permalink raw reply

* [PATCH] Add DTS for MPC8349E-mITX board
From: timur @ 2006-10-04 16:03 UTC (permalink / raw)
  To: linuxppc-dev

From: Timur Tabi <timur@freescale.com>

Add the DTS for the Freescale MPC 8349E-mITX reference board.  Contact 
Vitesse for the driver for the VSC 7385.

Signed-off-by: Timur Tabi <timur@freescale.com>
---
 arch/powerpc/boot/dts/mpc8349emitx.dts |  246 ++++++++++++++++++++++++++++++++
 1 files changed, 246 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/boot/dts/mpc8349emitx.dts b/arch/powerpc/boot/dts/mpc8349emitx.dts
new file mode 100644
index 0000000..27807fc
--- /dev/null
+++ b/arch/powerpc/boot/dts/mpc8349emitx.dts
@@ -0,0 +1,246 @@
+/*
+ * MPC8349E-mITX Device Tree Source
+ *
+ * Copyright 2006 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+/ {
+	model = "MPC8349EMITX";
+	compatible = "MPC834xMITX";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#cpus = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,8349@0 {
+			device_type = "cpu";
+			reg = <0>;
+			d-cache-line-size = <20>;
+			i-cache-line-size = <20>;
+			d-cache-size = <8000>;
+			i-cache-size = <8000>;
+			timebase-frequency = <0>;	// from bootloader
+			bus-frequency = <0>;		// from bootloader
+			clock-frequency = <0>;		// from bootloader
+			32-bit;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <00000000 10000000>;
+	};
+
+	soc8349@e0000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		#interrupt-cells = <2>;
+		device_type = "soc";
+		ranges = <0 e0000000 00100000>;
+		reg = <e0000000 00000200>;
+		bus-frequency = <0>;                    // from bootloader
+
+		wdt@200 {
+			device_type = "watchdog";
+			compatible = "mpc83xx_wdt";
+			reg = <200 100>;
+		};
+
+		i2c@3000 {
+			device_type = "i2c";
+			compatible = "fsl-i2c";
+			reg = <3000 100>;
+			interrupts = <e 8>;
+			interrupt-parent = <700>;
+			dfsrr;
+		};
+
+		i2c@3100 {
+			device_type = "i2c";
+			compatible = "fsl-i2c";
+			reg = <3100 100>;
+			interrupts = <f 8>;
+			interrupt-parent = <700>;
+			dfsrr;
+		};
+
+		spi@7000 {
+			device_type = "spi";
+			compatible = "mpc83xx_spi";
+			reg = <7000 1000>;
+			interrupts = <10 8>;
+			interrupt-parent = <700>;
+			mode = <0>;
+		};
+
+		usb@22000 {
+			device_type = "usb";
+			compatible = "fsl-usb2-mph";
+			reg = <22000 1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupt-parent = <700>;
+			interrupts = <27 2>;
+			phy_type = "ulpi";
+			port1;
+		};
+
+		usb@23000 {
+			device_type = "usb";
+			compatible = "fsl-usb2-dr";
+			reg = <23000 1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupt-parent = <700>;
+			interrupts = <26 2>;
+			phy_type = "ulpi";
+		};
+
+		mdio@24520 {
+			device_type = "mdio";
+			compatible = "gianfar";
+			reg = <24520 20>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			linux,phandle = <24520>;
+
+			/* Vitesse 8201 */
+			ethernet-phy@1c {
+				linux,phandle = <245201c>;
+				interrupt-parent = <700>;
+				interrupts = <12 2>;
+				reg = <1c>;
+				device_type = "ethernet-phy";
+			};
+
+			/* Vitesse 7385 */
+			ethernet-phy@1f {
+				linux,phandle = <245201f>;
+				interrupt-parent = <700>;
+				interrupts = <12 2>;
+				reg = <1f>;
+				device_type = "ethernet-phy";
+			};
+		};
+
+		ethernet@24000 {
+			device_type = "network";
+			model = "TSEC";
+			compatible = "gianfar";
+			reg = <24000 1000>;
+			address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <20 8 21 8 22 8>;
+			interrupt-parent = <700>;
+			phy-handle = <245201c>;
+		};
+
+		ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			device_type = "network";
+			model = "TSEC";
+			compatible = "gianfar";
+			reg = <25000 1000>;
+			address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <23 8 24 8 25 8>;
+			interrupt-parent = <700>;
+			phy-handle = <245201f>;
+		};
+
+		serial@4500 {
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <4500 100>;
+			clock-frequency = <0>;		// from bootloader
+			interrupts = <9 8>;
+			interrupt-parent = <700>;
+		};
+
+		serial@4600 {
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <4600 100>;
+			clock-frequency = <0>;		// from bootloader
+			interrupts = <a 8>;
+			interrupt-parent = <700>;
+		};
+
+		pci@8500 {
+			interrupt-map-mask = <f800 0 0 7>;
+			interrupt-map = <
+					/* IDSEL 0x10 - SATA */
+					8000 0 0 1 700 16 8 /* SATA_INTA */
+					>;
+			interrupt-parent = <700>;
+			interrupts = <42 8>;
+			bus-range = <0 0>;
+			ranges = <42000000 0 80000000 80000000 0 10000000
+				  02000000 0 90000000 90000000 0 10000000
+				  01000000 0 00000000 e2000000 0 01000000>;
+			clock-frequency = <3f940aa>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			reg = <8500 100>;
+			compatible = "83xx";
+			device_type = "pci";
+		};
+
+		pci@8600 {
+			interrupt-map-mask = <f800 0 0 7>;
+			interrupt-map = <
+					/* IDSEL 0x0E - MiniPCI Slot */
+					7000 0 0 1 700 15 8 /* PCI_INTA */
+
+					/* IDSEL 0x0F - PCI Slot */
+					7800 0 0 1 700 14 8 /* PCI_INTA */
+					7800 0 0 2 700 15 8 /* PCI_INTB */
+					 >;
+			interrupt-parent = <700>;
+			interrupts = <43 8>;
+			bus-range = <1 1>;
+			ranges = <42000000 0 a0000000 a0000000 0 10000000
+				  02000000 0 b0000000 b0000000 0 10000000
+				  01000000 0 00000000 e3000000 0 01000000>;
+			clock-frequency = <3f940aa>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			reg = <8600 100>;
+			compatible = "83xx";
+			device_type = "pci";
+		};
+
+		crypto@30000 {
+			device_type = "crypto";
+			model = "SEC2";
+			compatible = "talitos";
+			reg = <30000 10000>;
+			interrupts = <b 8>;
+			interrupt-parent = <700>;
+			num-channels = <4>;
+			channel-fifo-len = <18>;
+			exec-units-mask = <0000007e>;
+			descriptor-types-mask = <01010ebf>;
+		};
+
+		pic@700 {
+			linux,phandle = <700>;
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <700 100>;
+			built-in;
+			device_type = "ipic";
+		};
+	};
+};
-- 
1.4.2.1

^ permalink raw reply related

* Re: [PATCH 10/11] Add MPC8360EMDS board support
From: Jerry Van Baren @ 2006-10-04 16:05 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <80EE3621-ED80-408E-BF04-BA3CB985C769@embeddedalley.com>

Dan Malek wrote:
> On Oct 4, 2006, at 1:52 AM, Benjamin Herrenschmidt wrote:
> 
>> I don't see how a mecanism of feature call at the board support  
>> level is
>> in any way incompatible with the device-tree thing.
> 
> It isn't.
> 
>> ...  I'm happy mixing
>> both on powermac :)
> 
> I know.  This was just an opportunity to make people
> realize that a board port does require the writing of
> some board specific code.  Using the feature call is
> an excellent model of portability and flexibility.  My
> point was that any BCSR access is necessary to be
> hidden behind such a function, because it is truly
> board specific.  You can't require the drivers to
> have this kind of logic in them, they must call out
> to board support functions for assistance.
> 
> Just like the powermac ports, embedded drivers
> will need a feature call at some points during
> their processing (set up clock routing, IO pin
> configuration, board specific bus connections,
> power management, etc).  Some board ports
> may do nothing, others may do lots of work.
> 
> Therefore, I see no reason why a BSCR address
> and all of it's associated format can't simply
> be a #define in a board specific file.  There is no
> need for this in the device tree.
> 
> 
> 	-- Dan

The promise of OF for me is that it promises to keep configuration 
information in _one place_.  My experience to date is that my u-boot has 
a bunch of semi-hardcoded constants, my linux drivers have a bunch of 
semi-hardcoded constants that likely do not match 1:1 (name and 
definitely not location) with the equivalent u-boot constants, and some 
constants are passed from u-boot to linux using the BD structure, which 
is never defined the same (for me) in u-boot and linux.

The result is that, when I upgrade my u-boot and/or linux sources, I end 
up having to re-find all the places where the constants live (and find 
some new places), fix them, and then make the u-boot and linux BD 
structures match.  Granted, this isn't insurmountable, but it is a major 
hassle and should be unnecessary.

In a perfect world perhaps we would have one (set of) #include file(s) 
that had all the configuration information necessary to build u-boot and 
linux.  In the current world, u-boot and linux are in different 
repositories with different people with different machines (and agendas) 
doing different development on them, and the result is disjoint.

I look at OF to be the /lingua franca/ of PowerPC bootloaders and linux.

gvb

^ permalink raw reply

* Re: [PATCH] Add of_platform_device_scan().
From: Scott Wood @ 2006-10-04 16:32 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: linuxppc-dev
In-Reply-To: <200610040118.09416.arnd@arndb.de>

Arnd Bergmann wrote:
> I think it would be much more helpful to have working probing of all
> SOC buses during bootup.

I agree; I avoided doing that for now because I was uneasy about 
duplicating device nodes for SOC devices covered under the non-OF 
platform bus via code in sysdev/fsl_soc.c.  It probably won't cause any 
real problems unless a single device matches drivers on both buses (in 
which case the of_device driver would probably be calling 
of_platform_device_scan() anyway), but still...

What I'd really like (long-term, of course) is if platform_device and 
of_device were merged, with device tree support (or at least a means of 
passing on properties that *could* come from a device tree without 
special glue code that knows about each property) in arch-neutral code; 
the mechanism for discovering devices ideally shouldn't depend on the 
CPU's instruction set.

> +	for (child = NULL; (child = of_get_next_child(root, child)); ) {
> +		if (strcmp(child->type, "spider") == 0) {
> +			ret = of_soc_device_create(child, NULL);
> +			if (ret)
> +				goto out3;
> +		}
> +	}

Why only spider?

-Scott

^ permalink raw reply

* Re: booting 2.6 kernel on ML403
From: Pradeep Sampath @ 2006-10-04 16:35 UTC (permalink / raw)
  To: Ming Liu, ammubhai; +Cc: linuxppc-embedded
In-Reply-To: <BAY110-F79748D36D754E6D6B2A99B21D0@phx.gbl>

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

Hello Ameet/Ming,
   
  First of all really appreciate your inputs on this... 
  Problem 1 :
  I was using the factory shipped compact flash as is which comes with a DOS FAT16 partition and a linux 83 partition with ext3 filesystem. I tried it on 2 factory shipped CFs and its the same behavior - . When i plug-in the CF card reader to the linux box it always reads it as "sda" and in the linux2.6.17.1/Documentation/devices.txt - sda is the device file for SCSI disk devices. Wonerding how you guys configured the root option as "/dev/xsa".
   
  Now i re-formatted my CF, created a ext2 filesystem using busybox-1.1.0 like the BYU instructions. Created 2 partitions on CF card 1. FAT16 partition & 2. linux partition and then created 1. dos file system using mkdosfs and 2. linux ext2 filesystem using mke2fs.
   
  But the problem still persists and i get "Please append a correct "root=" boot option :"
  :(
   
  Problem 2: After i included the TEMAC driver and sysace drivers, the kernel just hangs. I thought i'll fix problem 1 before i get to problem 2... 
   
  With your help i am getting the confidence that i can make this all work!
  thanks once again.
  -Pradeep



Ming Liu <eemingliu@hotmail.com> wrote:
  Hello Ameet,
I am using that driver very well now. There is only one problem. It seems 
that the driver for TEMAC only support Gigabit Enet, not 10/100/1000M 
adapted. But because I want to use the Gigabit enet, I don't care that. So 
it's OK, at lease for 1Gbit/s.

So I don't think Pradeep's problem is caused by Temac. I still suspect that 
he didn't pass a right parameter to "root=", just like what I posted 
before.

Regards
Ming


>From: Ameet Patil 
>To: Ming Liu 
>CC: pradeepsampath@yahoo.com, linuxppc-embedded@ozlabs.org
>Subject: Re: booting 2.6 kernel on ML403
>Date: Wed, 04 Oct 2006 09:35:07 +0100
>
>Ming Liu wrote:
> > Hi,
> >
> >> [ 3.093694] TCP bic registered
> >> [ 3.129458] NET: Registered protocol family 8
> >> [ 3.181412] NET: Registered protocol family 20
> >> [ 3.236744] VFS: Cannot open root device "xsa2" or unknown-block(0,0)
> >> [ 3.313092] Please append a correct "root=" boot option
> >
> > It looks that some errors still exist in the parameters you passed to
> > "root=". Please double check it, or post it in the maillist for deep
> > analysis.
> > Regards
> > Ming
> >
> > _________________________________________________________________
> > ÏíÓÃÊÀ½çÉÏ×î´óµÄµç×ÓÓʼþϵͳ¡ª MSN Hotmail¡£ http://www.hotmail.com
> > 
------------------------------------------------------------------------
> >
> > _______________________________________________
> > Linuxppc-embedded mailing list
> > Linuxppc-embedded@ozlabs.org
> > https://ozlabs.org/mailman/listinfo/linuxppc-embedded
>Hi Ming,
>IIRC, you are or were using the TEMAC driver along with my System Ace
>driver, isn't it? Does my driver patch ***-after-TEMAC.patch work for
>you? I ask this because Pradeep is having some problems using it (see
>Problem 2 in his email). Could you please update on this?
>
>Thanks,
>-Ameet

_________________________________________________________________
ÓëÁª»úµÄÅóÓѽøÐн»Á÷£¬ÇëʹÓà MSN Messenger: http://messenger.msn.com/cn 

_______________________________________________
Linuxppc-embedded mailing list
Linuxppc-embedded@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-embedded

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

^ permalink raw reply

* Re: [PATCH] Add of_platform_device_scan().
From: Arnd Bergmann @ 2006-10-04 16:37 UTC (permalink / raw)
  To: Scott Wood; +Cc: linuxppc-dev
In-Reply-To: <4523E214.5060404@freescale.com>

On Wednesday 04 October 2006 18:32, Scott Wood wrote:
> What I'd really like (long-term, of course) is if platform_device and=20
> of_device were merged, with device tree support (or at least a means of=20
> passing on properties that *could* come from a device tree without=20
> special glue code that knows about each property) in arch-neutral code;=20
> the mechanism for discovering devices ideally shouldn't depend on the=20
> CPU's instruction set.

My guess is that this won't happen, because other architectures
normally don't describe their platform devices in a way that is
anywhere near what we have on powerpc.

Benh suggested moving some of the functionality of of_platform_device
into the common of_device so we don't really have to use an
of_platform_device for stuff that can be automatically probed.

I guess we'll see a patch from him soon.

> > +=A0=A0=A0=A0=A0for (child =3D NULL; (child =3D of_get_next_child(root,=
 child)); ) {
> > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0if (strcmp(child->type, "spider=
") =3D=3D 0) {
> > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0ret =3D=
 of_soc_device_create(child, NULL);
> > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0if (ret)
> > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=
=A0=A0=A0=A0=A0=A0goto out3;
> > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0}
> > +=A0=A0=A0=A0=A0}
>=20
> Why only spider?

Mistake on my side. That's what I have in my experimental device tree.
It should be more generic.

	Arnd <><

^ permalink raw reply

* Re: booting 2.6 kernel on ML403
From: Pradeep Sampath @ 2006-10-04 16:47 UTC (permalink / raw)
  To: Ameet Patil; +Cc: linuxppc-embedded
In-Reply-To: <45236A0F.6000204@gmail.com>

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

Ameet,
   
  loaded at:     00400000 0051513C
board data at: 00513124 0051313C
relocated to:  004050E8 00405100
zimage at:     004057FD 0051230A
avail ram:     00516000 04000000
  Linux/PPC load: console=ttyS0,9600 root=/dev/xsa2
Uncompressing Linux...done.
Now booting the kernel


Please could send me all the boot messages until the point where it 
stops. This will help me better identify the problem.

Thanks,
-Ameet




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

^ permalink raw reply

* Problem with initrd
From: Glenn.G.Hart @ 2006-10-04 16:55 UTC (permalink / raw)
  To: linuxppc-embedded

I am trying to get Linux running on the PPC of a Xilinx V4-FX12 FPGA.  I am
using the Linux 2.6.17.9 kernel (I have also tried 2.6.17.1 with the same
results) and have gotten through the kernel initialization to the point
where it mounts the root file system.  At this point I can an Oops and a
kernel panic.  I traced the kernel and found it was happening on the gunzip
of the ramdisk image.  I tried without compressing the ramdisk image and I
got a slightly different error.  I have attached this output as well.  I am
not a kernel expert, but I am guessing it is having trouble accessing the
RAM for the ramdisk.  Can anybody offer some advice?

Thanks,
Glenn

With compress ramdisk image:

loaded at:     00400000 0052B13C
board data at: 00529124 0052913C
relocated to:  004050F0 00405108
zimage at:     00405805 004D072E
initrd at:     004D1000 00528981
avail ram:     0052C000 10000000

Linux/PPC load: console=ttyS0,9600 console=tty0 root=/dev/ram rw
Uncompressing Linux...done.
Now booting the kernel
initrd start c04d1000 end c0528981
Linux version 2.6.17.9 (root@AFedora3) (gcc version 3.4.5) #32 PREEMPT Tue
Oct 3 23:25:12 EDT 2006
Xilinx Virtex-II Pro port
Port by MontaVista Software, Inc. (source@mvista.com)
Built 1 zonelists
Kernel command line: console=ttyS0,9600 console=tty0 root=/dev/ram rw
Xilinx INTC #0 at 0x41200000 mapped to 0xFDFFE000
PID hash table entries: 2048 (order: 11, 8192 bytes)
Console: colour dummy device 80x25
Dentry cache hash table entries: 32768 (order: 5, 131072 bytes)
Inode-cache hash table entries: 16384 (order: 4, 65536 bytes)
Memory: 257408k available (1424k kernel code, 368k data, 80k init, 0k
highmem)
Mount-cache hash table entries: 512
checking if image is initramfs...it isn't (no cpio magic); looks like an
initrd
Freeing initrd memory: 350k freed
NET: Registered protocol family 16
NET: Registered protocol family 2
IP route cache hash table entries: 2048 (order: 1, 8192 bytes)
TCP established hash table entries: 8192 (order: 3, 32768 bytes)
TCP bind hash table entries: 4096 (order: 2, 16384 bytes)
TCP: Hash tables configured (established 8192 bind 4096)
TCP reno registered
io scheduler noop registered (default)
Serial: 8250/16550 driver $Revision: 1.90 $ 1 ports, IRQ sharing disabled
serial8250.0: ttyS0 at MMIO 0x40401003 (irq = 1) is a 16450
RAMDISK driver initialized: 1 RAM disks of 4096K size 1024 blocksize
loop: loaded (max 2 devices)
nbd: registered device at major 43
eth0: using fifo mode.
eth0: Xilinx EMAC #0 at 0x80400000 mapped to 0xD1000000, irq=0
eth0: id 2.0a; block id 0, type 8
mice: PS/2 mouse device common for all mice
TCP bic registered
NET: Registered protocol family 1
NET: Registered protocol family 17
RAMDISK: Compressed image found at block 0
allocated in buffer
allocated window buffer
make crc
gunzip
Oops: kernel access of bad area, sig: 11 [#1]
PREEMPT
NIP: C004115C LR: C0041148 CTR: C00FA29C
REGS: c0421610 TRAP: 0300   Not tainted  (2.6.17.9)
MSR: 00029030 <EE,ME,IR,DR>  CR: 35035093  XER: E0000000
DAR: 00001000, DSISR: 00800000
TASK = c0529b10[1] 'swapper' THREAD: c0420000
GPR00: C0041148 C04216C0 C0529B10 00000000 00000001 00000001 C04216A8
00000000
GPR08: 00000000 00001000 00000400 00000000 35035099 FFFF9620 00000001
C04216D0
GPR16: C018CD50 C04C88A0 C052FC08 00000000 00001000 00010000 C052FCA8
00000000
GPR24: 00140000 C0450000 00000000 00001000 C01E3F20 00001000 00001000
00000000
NIP [C004115C] generic_file_buffered_write+0x4ec/0x5bc
LR [C0041148] generic_file_buffered_write+0x4d8/0x5bc
Call Trace:
[C04216C0] [C0041148] generic_file_buffered_write+0x4d8/0x5bc (unreliable)
[C0421780] [C0041A10] __generic_file_aio_write_nolock+0x4d4/0x50c
[C0421810] [C0041DB8] generic_file_aio_write_nolock+0x28/0x98
[C0421830] [C0041EA0] generic_file_write_nolock+0x78/0xa8
[C04218D0] [C00657F8] blkdev_file_write+0x20/0x30
[C04218E0] [C005B400] vfs_write+0xc8/0x190
[C0421900] [C005B5A0] sys_write+0x4c/0x8c
[C0421930] [C01AD2D4] flush_window+0x34/0xe4
[C0421950] [C01AD8B8] inflate_codes+0x468/0x4b0
[C04219A0] [C01AE0E0] inflate_dynamic+0x64c/0x690
[C0421EE0] [C01AEA1C] rd_load_image+0x8f4/0x106c
[C0421F40] [C01AF33C] initrd_load+0x4c/0x304
[C0421F70] [C01ACCB8] prepare_namespace+0xa8/0x11c
[C0421F90] [C0002580] init+0x1b4/0x280
[C0421FF0] [C00051FC] kernel_thread+0x44/0x60
Instruction dump:
48006591 2f9d0000 419c001c 7ec3b378 38800001 4800441d 48120851 2f930000
409efbe8 8061005c 81210064 2f830000 <92e90000> 93090004 41be0008 48006555
Kernel panic - not syncing: Attempted to kill init!
 <0>Rebooting in 180 seconds.


With uncompress ramdisk image:

loaded at:     00400000 008D313C
board data at: 008D1124 008D113C
relocated to:  004050F0 00405108
zimage at:     00405805 004D072C
initrd at:     004D1000 008D1000
avail ram:     008D4000 10000000

Linux/PPC load: console=ttyS0,9600 console=tty0 root=/dev/ram rw
Uncompressing Linux...done.
Now booting the kernel
initrd start c04d1000 end c08d1000
Linux version 2.6.17.9 (root@AFedora3) (gcc version 3.4.5) #33 PREEMPT Wed
Oct 4 00:18:59 EDT 2006
Xilinx Virtex-II Pro port
Port by MontaVista Software, Inc. (source@mvista.com)
Built 1 zonelists
Kernel command line: console=ttyS0,9600 console=tty0 root=/dev/ram rw
Xilinx INTC #0 at 0x41200000 mapped to 0xFDFFE000
PID hash table entries: 2048 (order: 11, 8192 bytes)
Console: colour dummy device 80x25
Dentry cache hash table entries: 32768 (order: 5, 131072 bytes)
Inode-cache hash table entries: 16384 (order: 4, 65536 bytes)
Memory: 253696k available (1424k kernel code, 368k data, 80k init, 0k
highmem)
Mount-cache hash table entries: 512
checking if image is initramfs...it isn't (bad gzip magic numbers); looks
like an initrd
Freeing initrd memory: 4096k freed
NET: Registered protocol family 16
NET: Registered protocol family 2
IP route cache hash table entries: 2048 (order: 1, 8192 bytes)
TCP established hash table entries: 8192 (order: 3, 32768 bytes)
TCP bind hash table entries: 4096 (order: 2, 16384 bytes)
TCP: Hash tables configured (established 8192 bind 4096)
TCP reno registered
io scheduler noop registered (default)
Serial: 8250/16550 driver $Revision: 1.90 $ 1 ports, IRQ sharing disabled
serial8250.0: ttyS0 at MMIO 0x40401003 (irq = 1) is a 16450
RAMDISK driver initialized: 1 RAM disks of 4096K size 1024 blocksize
loop: loaded (max 2 devices)
nbd: registered device at major 43
eth0: using fifo mode.
eth0: Xilinx EMAC #0 at 0x80400000 mapped to 0xD1000000, irq=0
eth0: id 2.0a; block id 0, type 8
mice: PS/2 mouse device common for all mice
TCP bic registered
NET: Registered protocol family 1
NET: Registered protocol family 17
RAMDISK: ext2 filesystem found at block 0
found ramdisk # blocks = 4096 /initrd.image
RAMDISK: Loading 4096KiB [1 disk] into ram disk... Oops: Exception in
kernel mode, sig: 4 [#1]
PREEMPT
NIP: C0079058 LR: C0079018 CTR: 00000000
REGS: c08e1c20 TRAP: 0700   Not tainted  (2.6.17.9)
MSR: 00029030 <EE,ME,IR,DR>  CR: 35005093  XER: C0000000
TASK = c04c9b10[1] 'swapper' THREAD: c08e0000
GPR00: 11A49A00 C08E1CD0 C04C9B10 C08E1CD8 C08E1CB8 00000001 C08D4C00
00000003
GPR08: 11A49A00 11A49A00 11A49A00 C08D26AC 00000400 FFFF9620 00000002
C08D2664
GPR16: 00000002 00000001 C08E1EC0 C04C26C0 00000000 C08E1DA0 000003FF
C08D2704
GPR24: 00001000 00000000 00400000 00000400 00000001 00000400 00000000
C08D2664
NIP [C0079058] touch_atime+0xc4/0xd8
LR [C0079018] touch_atime+0x84/0xd8
Call Trace:
[C08E1CD0] [C0079018] touch_atime+0x84/0xd8 (unreliable)
[C08E1CF0] [C003FBF0] do_generic_mapping_read+0x490/0x4a4
[C08E1D90] [C00420BC] __generic_file_aio_read+0x1ec/0x238
[C08E1DE0] [C0042238] generic_file_read+0x88/0xb8
[C08E1E90] [C005B16C] vfs_read+0xc8/0x190
[C08E1EB0] [C005B514] sys_read+0x4c/0x8c
[C08E1EE0] [C01AF100] rd_load_image+0xfd8/0x106c
[C08E1F40] [C01AF33C] initrd_load+0x4c/0x304
[C08E1F70] [C01ACCB8] prepare_namespace+0xa8/0x11c
[C08E1F90] [C0002580] init+0x1b4/0x280
[C08E1FF0] [C00051FC] kernel_thread+0x44/0x60
Instruction dump:
409e0014 800b0004 8121000c 7f804800 419e0020 81210008 8141000c 7fe3fb78
913f0048 915f004c 38800001 4800b1a1 <00000000> 00000800 7c0803a6 38210020
Kernel panic - not syncing: Attempted to kill init!
 <0>Rebooting in 180 seconds..

^ permalink raw reply

* RE: booting 2.6 kernel on ML403
From: John Bonesio @ 2006-10-04 17:17 UTC (permalink / raw)
  To: Pradeep Sampath, Ming Liu, ammubhai; +Cc: linuxppc-embedded

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

A quick amendment to my previous email:

The device name you should use in the CONFIG_CMDLINE  "root=..." can be found in the routine call to register_blkdev() in the driver source code. The first parameter to register_blkdev() is the major number of the device. The second parameter is the name of the device, as in /dev/xsda2, or /dev/xsysace2. This second parameter will contain just the 'xsda' or 'xsysace' in it, and it may be a preprocessor constant defined earlier in the file, such as #define MAJOR_NAME "xsda", but it might not be a constant either. It depends on the code.

 

Hopefully this clears things up a bit.

 

- John

 

________________________________

From: linuxppc-embedded-bounces+jbonesio=xilinx.com@ozlabs.org [mailto:linuxppc-embedded-bounces+jbonesio=xilinx.com@ozlabs.org] On Behalf Of Pradeep Sampath
Sent: Wednesday, October 04, 2006 10:35 AM
To: Ming Liu; ammubhai@gmail.com
Cc: linuxppc-embedded@ozlabs.org
Subject: Re: booting 2.6 kernel on ML403

 

Hello Ameet/Ming,

 

First of all really appreciate your inputs on this... 

Problem 1 :

I was using the factory shipped compact flash as is which comes with a DOS FAT16 partition and a linux 83 partition with ext3 filesystem. I tried it on 2 factory shipped CFs and its the same behavior - . When i plug-in the CF card reader to the linux box it always reads it as "sda" and in the linux2.6.17.1/Documentation/devices.txt - sda is the device file for SCSI disk devices. Wonerding how you guys configured the root option as "/dev/xsa".

 

Now i re-formatted my CF, created a ext2 filesystem using busybox-1.1.0 like the BYU instructions. Created 2 partitions on CF card 1. FAT16 partition & 2. linux partition and then created 1. dos file system using mkdosfs and 2. linux ext2 filesystem using mke2fs.

 

But the problem still persists and i get "Please append a correct "root=" boot option :"

:(

 

Problem 2: After i included the TEMAC driver and sysace drivers, the kernel just hangs. I thought i'll fix problem 1 before i get to problem 2... 

 

With your help i am getting the confidence that i can make this all work!

thanks once again.

-Pradeep



Ming Liu <eemingliu@hotmail.com> wrote:

	Hello Ameet,
	I am using that driver very well now. There is only one problem. It seems 
	that the driver for TEMAC only support Gigabit Enet, not 10/100/1000M 
	adapted. But because I want to use the Gigabit enet, I don't care that. So 
	it's OK, at lease for 1Gbit/s.
	
	So I don't think Pradeep's problem is caused by Temac. I still suspect that 
	he didn't pass a right parameter to "root=", just like what I posted 
	before.
	
	Regards
	Ming
	
	
	>From: Ameet Patil 
	>To: Ming Liu 
	>CC: pradeepsampath@yahoo.com, linuxppc-embedded@ozlabs.org
	>Subject: Re: booting 2.6 kernel on ML403
	>Date: Wed, 04 Oct 2006 09:35:07 +0100
	>
	>Ming Liu wrote:
	> > Hi,
	> >
	> >> [ 3.093694] TCP bic registered
	> >> [ 3.129458] NET: Registered protocol family 8
	> >> [ 3.181412] NET: Registered protocol family 20
	> >> [ 3.236744] VFS: Cannot open root device "xsa2" or unknown-block(0,0)
	> >> [ 3.313092] Please append a correct "root=" boot option
	> >
	> > It looks that some errors still exist in the parameters you passed to
	> > "root=". Please double check it, or post it in the maillist for deep
	> > analysis.
	> > Regards
	> > Ming
	> >
	> > _________________________________________________________________
	> > ÏíÓÃÊÀ½çÉÏ×î´óµÄµç×ÓÓʼþϵͳ¡ª MSN Hotmail¡£ http://www.hotmail.com
	> > 
	------------------------------------------------------------------------
	> >
	> > _______________________________________________
	> > Linuxppc-embedded mailing list
	> > Linuxppc-embedded@ozlabs.org
	> > https://ozlabs.org/mailman/listinfo/linuxppc-embedded
	>Hi Ming,
	>IIRC, you are or were using the TEMAC driver along with my System Ace
	>driver, isn't it? Does my driver patch ***-after-TEMAC.patch work for
	>you? I ask this because Pradeep is having some problems using it (see
	>Problem 2 in his email). Could you please update on this?
	>
	>Thanks,
	>-Ameet
	
	_________________________________________________________________
	ÓëÁª»úµÄÅóÓѽøÐн»Á÷£¬ÇëʹÓà MSN Messenger: http://messenger.msn.com/cn 
	
	_______________________________________________
	Linuxppc-embedded mailing list
	Linuxppc-embedded@ozlabs.org
	https://ozlabs.org/mailman/listinfo/linuxppc-embedded

 


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

^ permalink raw reply

* RE: booting 2.6 kernel on ML403
From: John Bonesio @ 2006-10-04 17:09 UTC (permalink / raw)
  To: Pradeep Sampath, Ming Liu, ammubhai; +Cc: linuxppc-embedded

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

Hi Pradeep,

 

If you are using the MontaVista/Xilinx driver for sysace for linux 2.6, the CONFIG_CMDLINE item in .config should have

    root=/dev/xsysace2 rw

in it. From the text below it's not clear what driver you are using. If you are using a different driver, you may be able to search for

    #define MAJOR_NAME

in the source code of the sysace driver. I believe that will indicate which device name you should use in the CONFIG_CMDLINE.

 

As you probably already know, the '2' in '/dev/xsysace2' refers to the partition number it should use - partition 2 in this case.

 

For Problem 2: Do you see any error leds light up on the board? It's possible that the drivers you are using for one or both of those cores is not meant for the version of the cores you are using. The core most likely to be suspect is the TEMAC soft core, as that has changed recently. Even though you are using the hard TEMAC core, there is a soft wrapper around it to connect it up to the bus and what not. This soft wrapper has changed from version 2 to version 3 not too long ago. While the TEMAC driver that MontaVista has (and I believe posted to this mailing list) is for version 2 of the soft TEMAC core.

 

Hope this helps,

 

- John

 

________________________________

From: linuxppc-embedded-bounces+jbonesio=xilinx.com@ozlabs.org [mailto:linuxppc-embedded-bounces+jbonesio=xilinx.com@ozlabs.org] On Behalf Of Pradeep Sampath
Sent: Wednesday, October 04, 2006 10:35 AM
To: Ming Liu; ammubhai@gmail.com
Cc: linuxppc-embedded@ozlabs.org
Subject: Re: booting 2.6 kernel on ML403

 

Hello Ameet/Ming,

 

First of all really appreciate your inputs on this... 

Problem 1 :

I was using the factory shipped compact flash as is which comes with a DOS FAT16 partition and a linux 83 partition with ext3 filesystem. I tried it on 2 factory shipped CFs and its the same behavior - . When i plug-in the CF card reader to the linux box it always reads it as "sda" and in the linux2.6.17.1/Documentation/devices.txt - sda is the device file for SCSI disk devices. Wonerding how you guys configured the root option as "/dev/xsa".

 

Now i re-formatted my CF, created a ext2 filesystem using busybox-1.1.0 like the BYU instructions. Created 2 partitions on CF card 1. FAT16 partition & 2. linux partition and then created 1. dos file system using mkdosfs and 2. linux ext2 filesystem using mke2fs.

 

But the problem still persists and i get "Please append a correct "root=" boot option :"

:(

 

Problem 2: After i included the TEMAC driver and sysace drivers, the kernel just hangs. I thought i'll fix problem 1 before i get to problem 2... 

 

With your help i am getting the confidence that i can make this all work!

thanks once again.

-Pradeep



Ming Liu <eemingliu@hotmail.com> wrote:

	Hello Ameet,
	I am using that driver very well now. There is only one problem. It seems 
	that the driver for TEMAC only support Gigabit Enet, not 10/100/1000M 
	adapted. But because I want to use the Gigabit enet, I don't care that. So 
	it's OK, at lease for 1Gbit/s.
	
	So I don't think Pradeep's problem is caused by Temac. I still suspect that 
	he didn't pass a right parameter to "root=", just like what I posted 
	before.
	
	Regards
	Ming
	
	
	>From: Ameet Patil 
	>To: Ming Liu 
	>CC: pradeepsampath@yahoo.com, linuxppc-embedded@ozlabs.org
	>Subject: Re: booting 2.6 kernel on ML403
	>Date: Wed, 04 Oct 2006 09:35:07 +0100
	>
	>Ming Liu wrote:
	> > Hi,
	> >
	> >> [ 3.093694] TCP bic registered
	> >> [ 3.129458] NET: Registered protocol family 8
	> >> [ 3.181412] NET: Registered protocol family 20
	> >> [ 3.236744] VFS: Cannot open root device "xsa2" or unknown-block(0,0)
	> >> [ 3.313092] Please append a correct "root=" boot option
	> >
	> > It looks that some errors still exist in the parameters you passed to
	> > "root=". Please double check it, or post it in the maillist for deep
	> > analysis.
	> > Regards
	> > Ming
	> >
	> > _________________________________________________________________
	> > ÏíÓÃÊÀ½çÉÏ×î´óµÄµç×ÓÓʼþϵͳ¡ª MSN Hotmail¡£ http://www.hotmail.com
	> > 
	------------------------------------------------------------------------
	> >
	> > _______________________________________________
	> > Linuxppc-embedded mailing list
	> > Linuxppc-embedded@ozlabs.org
	> > https://ozlabs.org/mailman/listinfo/linuxppc-embedded
	>Hi Ming,
	>IIRC, you are or were using the TEMAC driver along with my System Ace
	>driver, isn't it? Does my driver patch ***-after-TEMAC.patch work for
	>you? I ask this because Pradeep is having some problems using it (see
	>Problem 2 in his email). Could you please update on this?
	>
	>Thanks,
	>-Ameet
	
	_________________________________________________________________
	ÓëÁª»úµÄÅóÓѽøÐн»Á÷£¬ÇëʹÓà MSN Messenger: http://messenger.msn.com/cn 
	
	_______________________________________________
	Linuxppc-embedded mailing list
	Linuxppc-embedded@ozlabs.org
	https://ozlabs.org/mailman/listinfo/linuxppc-embedded

 


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

^ permalink raw reply

* Re: [PATCH 10/11] Add MPC8360EMDS board support
From: Tim Bird @ 2006-10-04 17:28 UTC (permalink / raw)
  To: Dan Malek; +Cc: Olof Johansson, linuxppc-dev, Paul Mackerras
In-Reply-To: <2867EA41-5135-43F7-9873-044C617EAC1B@embeddedalley.com>

Dan Malek wrote:
> I'm not against using the device tree (or platform data
> or #defines) when it's appropriate to do so.  I think our
> obsession to represent everything there is what is
> creating the complexity.  If a #define in a board
> specific port file makes sense, then just do that,
> even if it is a BSCR address.  The device tree just
> seems like the new toy that everyone wants to play
> with, and we are forgetting that the old fashioned way
> of just writing some C code may be the way
> to implement what we need.

I'd like to "second" a lot of what Dan is saying.

Linux increasingly drifts away from simple, adequate
solutions (that admittedly require a bit of embedded
developer elbow grease), towards these types of
"grand unification" schemes, which actually interfere
with goals in the embedded space.

=============================
Tim Bird
Architecture Group Chair, CE Linux Forum
Senior Staff Engineer, Sony Electronics
=============================

^ permalink raw reply

* [PATCH] use-generic-bug-for-ppc
From: Judith Lebzelter @ 2006-10-04 18:49 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev, jeremy, linux-kernel

For 2.6.18-mm3, the 32-bit 'ppc' architectures won't compile due to errors:

arch/ppc/kernel/built-in.o: In function `find_bug':
arch/ppc/kernel/traps.c:582: undefined reference to `module_find_bug'
arch/powerpc/kernel/built-in.o: In function `module_arch_cleanup':
arch/powerpc/kernel/module_32.c:282: undefined reference to `module_bug_cleanup'
arch/powerpc/kernel/built-in.o: In function `module_finalize':
arch/powerpc/kernel/module_32.c:277: undefined reference to `module_bug_finalize'
make: [.tmp_vmlinux3] Error 1 (ignored)
  KSYM    .tmp_kallsyms3.S
powerpc-750-linux-gnu-nm: '.tmp_vmlinux3': No such file
No valid symbol.
make: [.tmp_kallsyms3.S] Error 1 (ignored)
  AS      .tmp_kallsyms3.o
  LD      vmlinux
arch/ppc/kernel/built-in.o: In function `find_bug':
arch/ppc/kernel/traps.c:582: undefined reference to `module_find_bug'
arch/powerpc/kernel/built-in.o: In function `module_arch_cleanup':
arch/powerpc/kernel/module_32.c:282: undefined reference to `module_bug_cleanup'
arch/powerpc/kernel/built-in.o: In function `module_finalize':
arch/powerpc/kernel/module_32.c:277: undefined reference to `module_bug_finalize'
make: [vmlinux] Error 1 (ignored)

These changes match changes for using the generic bug libraries as in 
'use-generic-bug-for-powerpc.patch' and gets rid of the compile errors.

Signed-off-by: Judith Lebzelter <judith@osdl.org>

---

Files Edited:
arch/ppc/kernel/traps.c
arch/ppc/Kconfig


Index: linux/arch/ppc/Kconfig
===================================================================
--- linux.orig/arch/ppc/Kconfig	2006-10-03 16:11:26.456655259 -0700
+++ linux/arch/ppc/Kconfig	2006-10-03 17:10:09.398320057 -0700
@@ -52,6 +52,11 @@
 	bool
 	default y
 
+config GENERIC_BUG
+	bool
+	default y
+	depends on BUG
+
 source "init/Kconfig"
 
 menu "Processor"
Index: linux/arch/ppc/kernel/traps.c
===================================================================
--- linux.orig/arch/ppc/kernel/traps.c	2006-10-03 16:11:26.461653713 -0700
+++ linux/arch/ppc/kernel/traps.c	2006-10-04 10:00:21.198907987 -0700
@@ -28,6 +28,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/prctl.h>
+#include <linux/bug.h>
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
@@ -568,55 +569,9 @@
  */
 extern struct bug_entry __start___bug_table[], __stop___bug_table[];
 
-#ifndef CONFIG_MODULES
-#define module_find_bug(x)	NULL
-#endif
-
-struct bug_entry *find_bug(unsigned long bugaddr)
+int is_valid_bugaddr(unsigned long addr)
 {
-	struct bug_entry *bug;
-
-	for (bug = __start___bug_table; bug < __stop___bug_table; ++bug)
-		if (bugaddr == bug->bug_addr)
-			return bug;
-	return module_find_bug(bugaddr);
-}
-
-int check_bug_trap(struct pt_regs *regs)
-{
-	struct bug_entry *bug;
-	unsigned long addr;
-
-	if (regs->msr & MSR_PR)
-		return 0;	/* not in kernel */
-	addr = regs->nip;	/* address of trap instruction */
-	if (addr < PAGE_OFFSET)
-		return 0;
-	bug = find_bug(regs->nip);
-	if (bug == NULL)
-		return 0;
-	if (bug->line & BUG_WARNING_TRAP) {
-		/* this is a WARN_ON rather than BUG/BUG_ON */
-#ifdef CONFIG_XMON
-		xmon_printf(KERN_ERR "Badness in %s at %s:%ld\n",
-		       bug->function, bug->file,
-		       bug->line & ~BUG_WARNING_TRAP);
-#endif /* CONFIG_XMON */		
-		printk(KERN_ERR "Badness in %s at %s:%ld\n",
-		       bug->function, bug->file,
-		       bug->line & ~BUG_WARNING_TRAP);
-		dump_stack();
-		return 1;
-	}
-#ifdef CONFIG_XMON
-	xmon_printf(KERN_CRIT "kernel BUG in %s at %s:%ld!\n",
-	       bug->function, bug->file, bug->line);
-	xmon(regs);
-#endif /* CONFIG_XMON */
-	printk(KERN_CRIT "kernel BUG in %s at %s:%ld!\n",
-	       bug->function, bug->file, bug->line);
-
-	return 0;
+	return addr >= PAGE_OFFSET;
 }
 
 void program_check_exception(struct pt_regs *regs)
@@ -671,7 +626,9 @@
 		/* trap exception */
 		if (debugger_bpt(regs))
 			return;
-		if (check_bug_trap(regs)) {
+
+		if (!(regs->msr & MSR_PR) &&  /* not user-mode */
+		    report_bug(regs->nip) == BUG_TRAP_TYPE_WARN) {
 			regs->nip += 4;
 			return;
 		}

^ 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