Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 96252
b: refs/heads/master
c: 2a5f2e3
h: refs/heads/master
v: v3
  • Loading branch information
Paul Mackerras committed May 9, 2008
1 parent 7e355b4 commit 31f86a1
Show file tree
Hide file tree
Showing 13 changed files with 197 additions and 69 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 78be76476a34a77f0ea9db2f78ba46a2b0fd5ab5
refs/heads/master: 2a5f2e3e6cd1ce9fb3f8b186b6bc9aa1f1497a92
53 changes: 51 additions & 2 deletions trunk/arch/powerpc/platforms/cell/interrupt.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include <linux/percpu.h>
#include <linux/types.h>
#include <linux/ioport.h>
#include <linux/kernel_stat.h>

#include <asm/io.h>
#include <asm/pgtable.h>
Expand Down Expand Up @@ -231,6 +232,54 @@ static int iic_host_match(struct irq_host *h, struct device_node *node)
"IBM,CBEA-Internal-Interrupt-Controller");
}

extern int noirqdebug;

static void handle_iic_irq(unsigned int irq, struct irq_desc *desc)
{
const unsigned int cpu = smp_processor_id();

spin_lock(&desc->lock);

desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);

/*
* If we're currently running this IRQ, or its disabled,
* we shouldn't process the IRQ. Mark it pending, handle
* the necessary masking and go out
*/
if (unlikely((desc->status & (IRQ_INPROGRESS | IRQ_DISABLED)) ||
!desc->action)) {
desc->status |= IRQ_PENDING;
goto out_eoi;
}

kstat_cpu(cpu).irqs[irq]++;

/* Mark the IRQ currently in progress.*/
desc->status |= IRQ_INPROGRESS;

do {
struct irqaction *action = desc->action;
irqreturn_t action_ret;

if (unlikely(!action))
goto out_eoi;

desc->status &= ~IRQ_PENDING;
spin_unlock(&desc->lock);
action_ret = handle_IRQ_event(irq, action);
if (!noirqdebug)
note_interrupt(irq, desc, action_ret);
spin_lock(&desc->lock);

} while ((desc->status & (IRQ_PENDING | IRQ_DISABLED)) == IRQ_PENDING);

desc->status &= ~IRQ_INPROGRESS;
out_eoi:
desc->chip->eoi(irq);
spin_unlock(&desc->lock);
}

static int iic_host_map(struct irq_host *h, unsigned int virq,
irq_hw_number_t hw)
{
Expand All @@ -240,10 +289,10 @@ static int iic_host_map(struct irq_host *h, unsigned int virq,
break;
case IIC_IRQ_TYPE_IOEXC:
set_irq_chip_and_handler(virq, &iic_ioexc_chip,
handle_fasteoi_irq);
handle_iic_irq);
break;
default:
set_irq_chip_and_handler(virq, &iic_chip, handle_fasteoi_irq);
set_irq_chip_and_handler(virq, &iic_chip, handle_iic_irq);
}
return 0;
}
Expand Down
31 changes: 22 additions & 9 deletions trunk/arch/powerpc/platforms/cell/spu_base.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,10 @@ static void spu_restart_dma(struct spu *spu)

if (!test_bit(SPU_CONTEXT_SWITCH_PENDING, &spu->flags))
out_be64(&priv2->mfc_control_RW, MFC_CNTL_RESTART_DMA_COMMAND);
else {
set_bit(SPU_CONTEXT_FAULT_PENDING, &spu->flags);
mb();
}
}

static inline void spu_load_slb(struct spu *spu, int slbe, struct spu_slb *slb)
Expand Down Expand Up @@ -226,11 +230,13 @@ static int __spu_trap_data_map(struct spu *spu, unsigned long ea, u64 dsisr)
return 0;
}

spu->class_0_pending = 0;
spu->dar = ea;
spu->dsisr = dsisr;
spu->class_1_dar = ea;
spu->class_1_dsisr = dsisr;

spu->stop_callback(spu, 1);

spu->stop_callback(spu);
spu->class_1_dar = 0;
spu->class_1_dsisr = 0;

return 0;
}
Expand Down Expand Up @@ -318,11 +324,15 @@ spu_irq_class_0(int irq, void *data)
stat = spu_int_stat_get(spu, 0) & mask;

spu->class_0_pending |= stat;
spu->dsisr = spu_mfc_dsisr_get(spu);
spu->dar = spu_mfc_dar_get(spu);
spu->class_0_dsisr = spu_mfc_dsisr_get(spu);
spu->class_0_dar = spu_mfc_dar_get(spu);
spin_unlock(&spu->register_lock);

spu->stop_callback(spu);
spu->stop_callback(spu, 0);

spu->class_0_pending = 0;
spu->class_0_dsisr = 0;
spu->class_0_dar = 0;

spu_int_stat_clear(spu, 0, stat);

Expand Down Expand Up @@ -363,6 +373,9 @@ spu_irq_class_1(int irq, void *data)
if (stat & CLASS1_LS_COMPARE_SUSPEND_ON_PUT_INTR)
;

spu->class_1_dsisr = 0;
spu->class_1_dar = 0;

return stat ? IRQ_HANDLED : IRQ_NONE;
}

Expand Down Expand Up @@ -396,10 +409,10 @@ spu_irq_class_2(int irq, void *data)
spu->ibox_callback(spu);

if (stat & CLASS2_SPU_STOP_INTR)
spu->stop_callback(spu);
spu->stop_callback(spu, 2);

if (stat & CLASS2_SPU_HALT_INTR)
spu->stop_callback(spu);
spu->stop_callback(spu, 2);

if (stat & CLASS2_SPU_DMA_TAG_GROUP_COMPLETE_INTR)
spu->mfc_callback(spu);
Expand Down
16 changes: 14 additions & 2 deletions trunk/arch/powerpc/platforms/cell/spu_priv1_mmio.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <linux/io.h>
#include <linux/mutex.h>
#include <linux/device.h>
#include <linux/sched.h>

#include <asm/spu.h>
#include <asm/spu_priv1.h>
Expand Down Expand Up @@ -75,8 +76,19 @@ static u64 int_stat_get(struct spu *spu, int class)

static void cpu_affinity_set(struct spu *spu, int cpu)
{
u64 target = iic_get_target_id(cpu);
u64 route = target << 48 | target << 32 | target << 16;
u64 target;
u64 route;

if (nr_cpus_node(spu->node)) {
cpumask_t spumask = node_to_cpumask(spu->node);
cpumask_t cpumask = node_to_cpumask(cpu_to_node(cpu));

if (!cpus_intersects(spumask, cpumask))
return;
}

target = iic_get_target_id(cpu);
route = target << 48 | target << 32 | target << 16;
out_be64(&spu->priv1->int_route_RW, route);
}

Expand Down
17 changes: 11 additions & 6 deletions trunk/arch/powerpc/platforms/cell/spufs/fault.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,18 @@ int spufs_handle_class0(struct spu_context *ctx)
return 0;

if (stat & CLASS0_DMA_ALIGNMENT_INTR)
spufs_handle_event(ctx, ctx->csa.dar, SPE_EVENT_DMA_ALIGNMENT);
spufs_handle_event(ctx, ctx->csa.class_0_dar,
SPE_EVENT_DMA_ALIGNMENT);

if (stat & CLASS0_INVALID_DMA_COMMAND_INTR)
spufs_handle_event(ctx, ctx->csa.dar, SPE_EVENT_INVALID_DMA);
spufs_handle_event(ctx, ctx->csa.class_0_dar,
SPE_EVENT_INVALID_DMA);

if (stat & CLASS0_SPU_ERROR_INTR)
spufs_handle_event(ctx, ctx->csa.dar, SPE_EVENT_SPE_ERROR);
spufs_handle_event(ctx, ctx->csa.class_0_dar,
SPE_EVENT_SPE_ERROR);

ctx->csa.class_0_pending = 0;

return -EIO;
}
Expand Down Expand Up @@ -119,8 +124,8 @@ int spufs_handle_class1(struct spu_context *ctx)
* in time, we can still expect to get the same fault
* the immediately after the context restore.
*/
ea = ctx->csa.dar;
dsisr = ctx->csa.dsisr;
ea = ctx->csa.class_1_dar;
dsisr = ctx->csa.class_1_dsisr;

if (!(dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED)))
return 0;
Expand Down Expand Up @@ -158,7 +163,7 @@ int spufs_handle_class1(struct spu_context *ctx)
* time slicing will not preempt the context while the page fault
* handler is running. Context switch code removes mappings.
*/
ctx->csa.dar = ctx->csa.dsisr = 0;
ctx->csa.class_1_dar = ctx->csa.class_1_dsisr = 0;

/*
* If we handled the fault successfully and are in runnable
Expand Down
10 changes: 7 additions & 3 deletions trunk/arch/powerpc/platforms/cell/spufs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

#include <linux/file.h>
#include <linux/fs.h>
#include <linux/fsnotify.h>
#include <linux/backing-dev.h>
#include <linux/init.h>
#include <linux/ioctl.h>
Expand Down Expand Up @@ -223,7 +224,7 @@ static int spufs_dir_close(struct inode *inode, struct file *file)
parent = dir->d_parent->d_inode;
ctx = SPUFS_I(dir->d_inode)->i_ctx;

mutex_lock(&parent->i_mutex);
mutex_lock_nested(&parent->i_mutex, I_MUTEX_PARENT);
ret = spufs_rmdir(parent, dir);
mutex_unlock(&parent->i_mutex);
WARN_ON(ret);
Expand Down Expand Up @@ -618,12 +619,15 @@ long spufs_create(struct nameidata *nd, unsigned int flags, mode_t mode,
mode &= ~current->fs->umask;

if (flags & SPU_CREATE_GANG)
return spufs_create_gang(nd->path.dentry->d_inode,
ret = spufs_create_gang(nd->path.dentry->d_inode,
dentry, nd->path.mnt, mode);
else
return spufs_create_context(nd->path.dentry->d_inode,
ret = spufs_create_context(nd->path.dentry->d_inode,
dentry, nd->path.mnt, flags, mode,
filp);
if (ret >= 0)
fsnotify_mkdir(nd->path.dentry->d_inode, dentry);
return ret;

out_dput:
dput(dentry);
Expand Down
38 changes: 23 additions & 15 deletions trunk/arch/powerpc/platforms/cell/spufs/run.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#include "spufs.h"

/* interrupt-level stop callback function. */
void spufs_stop_callback(struct spu *spu)
void spufs_stop_callback(struct spu *spu, int irq)
{
struct spu_context *ctx = spu->ctx;

Expand All @@ -24,21 +24,26 @@ void spufs_stop_callback(struct spu *spu)
*/
if (ctx) {
/* Copy exception arguments into module specific structure */
ctx->csa.class_0_pending = spu->class_0_pending;
ctx->csa.dsisr = spu->dsisr;
ctx->csa.dar = spu->dar;
switch(irq) {
case 0 :
ctx->csa.class_0_pending = spu->class_0_pending;
ctx->csa.class_0_dsisr = spu->class_0_dsisr;
ctx->csa.class_0_dar = spu->class_0_dar;
break;
case 1 :
ctx->csa.class_1_dsisr = spu->class_1_dsisr;
ctx->csa.class_1_dar = spu->class_1_dar;
break;
case 2 :
break;
}

/* ensure that the exception status has hit memory before a
* thread waiting on the context's stop queue is woken */
smp_wmb();

wake_up_all(&ctx->stop_wq);
}

/* Clear callback arguments from spu structure */
spu->class_0_pending = 0;
spu->dsisr = 0;
spu->dar = 0;
}

int spu_stopped(struct spu_context *ctx, u32 *stat)
Expand All @@ -56,7 +61,11 @@ int spu_stopped(struct spu_context *ctx, u32 *stat)
if (!(*stat & SPU_STATUS_RUNNING) && (*stat & stopped))
return 1;

dsisr = ctx->csa.dsisr;
dsisr = ctx->csa.class_0_dsisr;
if (dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED))
return 1;

dsisr = ctx->csa.class_1_dsisr;
if (dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED))
return 1;

Expand Down Expand Up @@ -294,7 +303,7 @@ static int spu_process_callback(struct spu_context *ctx)
u32 ls_pointer, npc;
void __iomem *ls;
long spu_ret;
int ret, ret2;
int ret;

/* get syscall block from local store */
npc = ctx->ops->npc_read(ctx) & ~3;
Expand All @@ -316,11 +325,9 @@ static int spu_process_callback(struct spu_context *ctx)
if (spu_ret <= -ERESTARTSYS) {
ret = spu_handle_restartsys(ctx, &spu_ret, &npc);
}
ret2 = spu_acquire(ctx);
mutex_lock(&ctx->state_mutex);
if (ret == -ERESTARTSYS)
return ret;
if (ret2)
return -EINTR;
}

/* need to re-get the ls, as it may have changed when we released the
Expand All @@ -343,13 +350,14 @@ long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *event)
if (mutex_lock_interruptible(&ctx->run_mutex))
return -ERESTARTSYS;

spu_enable_spu(ctx);
ctx->event_return = 0;

ret = spu_acquire(ctx);
if (ret)
goto out_unlock;

spu_enable_spu(ctx);

spu_update_sched_info(ctx);

ret = spu_run_init(ctx, npc);
Expand Down
7 changes: 5 additions & 2 deletions trunk/arch/powerpc/platforms/cell/spufs/sched.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@ void __spu_update_sched_info(struct spu_context *ctx)
* if it is timesliced or preempted.
*/
ctx->cpus_allowed = current->cpus_allowed;

/* Save the current cpu id for spu interrupt routing. */
ctx->last_ran = raw_smp_processor_id();
}

void spu_update_sched_info(struct spu_context *ctx)
Expand Down Expand Up @@ -243,7 +246,6 @@ static void spu_bind_context(struct spu *spu, struct spu_context *ctx)
spu_switch_log_notify(spu, ctx, SWITCH_LOG_START, 0);
spu_restore(&ctx->csa, spu);
spu->timestamp = jiffies;
spu_cpu_affinity_set(spu, raw_smp_processor_id());
spu_switch_notify(spu, ctx);
ctx->state = SPU_STATE_RUNNABLE;

Expand Down Expand Up @@ -657,7 +659,8 @@ static struct spu *find_victim(struct spu_context *ctx)

victim->stats.invol_ctx_switch++;
spu->stats.invol_ctx_switch++;
spu_add_to_rq(victim);
if (test_bit(SPU_SCHED_SPU_RUN, &ctx->sched_flags))
spu_add_to_rq(victim);

mutex_unlock(&victim->state_mutex);

Expand Down
3 changes: 2 additions & 1 deletion trunk/arch/powerpc/platforms/cell/spufs/spufs.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ struct spu_context {
cpumask_t cpus_allowed;
int policy;
int prio;
int last_ran;

/* statistics */
struct {
Expand Down Expand Up @@ -331,7 +332,7 @@ size_t spu_ibox_read(struct spu_context *ctx, u32 *data);
/* irq callback funcs. */
void spufs_ibox_callback(struct spu *spu);
void spufs_wbox_callback(struct spu *spu);
void spufs_stop_callback(struct spu *spu);
void spufs_stop_callback(struct spu *spu, int irq);
void spufs_mfc_callback(struct spu *spu);
void spufs_dma_callback(struct spu *spu, int type);

Expand Down
Loading

0 comments on commit 31f86a1

Please sign in to comment.