diff --git a/[refs] b/[refs] index 61e1b6106d18..bef92185934a 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 143a275984b37058d2d3ab1ec0e5be9026fda24d +refs/heads/master: eff3414b7277c4792debfa227f5408238d925f16 diff --git a/trunk/Documentation/powerpc/booting-without-of.txt b/trunk/Documentation/powerpc/booting-without-of.txt index d42d98107d49..b49ce169a63a 100644 --- a/trunk/Documentation/powerpc/booting-without-of.txt +++ b/trunk/Documentation/powerpc/booting-without-of.txt @@ -1,6 +1,7 @@ Booting the Linux/ppc kernel without Open Firmware -------------------------------------------------- + (c) 2005 Benjamin Herrenschmidt , IBM Corp. (c) 2005 Becky Bruce , @@ -8,62 +9,6 @@ (c) 2006 MontaVista Software, Inc. Flash chip node definition -Table of Contents -================= - - I - Introduction - 1) Entry point for arch/powerpc - 2) Board support - - II - The DT block format - 1) Header - 2) Device tree generalities - 3) Device tree "structure" block - 4) Device tree "strings" block - - III - Required content of the device tree - 1) Note about cells and address representation - 2) Note about "compatible" properties - 3) Note about "name" properties - 4) Note about node and property names and character set - 5) Required nodes and properties - a) The root node - b) The /cpus node - c) The /cpus/* nodes - d) the /memory node(s) - e) The /chosen node - f) the /soc node - - IV - "dtc", the device tree compiler - - V - Recommendations for a bootloader - - VI - System-on-a-chip devices and nodes - 1) Defining child nodes of an SOC - 2) Representing devices without a current OF specification - a) MDIO IO device - c) PHY nodes - b) Gianfar-compatible ethernet nodes - d) Interrupt controllers - e) I2C - f) Freescale SOC USB controllers - g) Freescale SOC SEC Security Engines - h) Board Control and Status (BCSR) - i) Freescale QUICC Engine module (QE) - g) Flash chip nodes - - VII - Specifying interrupt information for devices - 1) interrupts property - 2) interrupt-parent property - 3) OpenPIC Interrupt Controllers - 4) ISA Interrupt Controllers - - Appendix A - Sample SOC node for MPC8540 - - -Revision Information -==================== - May 18, 2005: Rev 0.1 - Initial draft, no chapter III yet. May 19, 2005: Rev 0.2 - Add chapter III and bits & pieces here or @@ -1742,7 +1687,7 @@ platforms are moved over to use the flattened-device-tree model. }; }; - j) Flash chip nodes + g) Flash chip nodes Flash chips (Memory Technology Devices) are often used for solid state file systems on embedded devices. diff --git a/trunk/arch/powerpc/boot/crt0.S b/trunk/arch/powerpc/boot/crt0.S index f1c4dfc635be..5a4215c4b014 100644 --- a/trunk/arch/powerpc/boot/crt0.S +++ b/trunk/arch/powerpc/boot/crt0.S @@ -13,7 +13,6 @@ .text /* a procedure descriptor used when booting this as a COFF file */ - .globl _zimage_start_opd _zimage_start_opd: .long _zimage_start, 0, 0, 0 diff --git a/trunk/arch/powerpc/kernel/of_platform.c b/trunk/arch/powerpc/kernel/of_platform.c index d454f61c9c7c..d501c23e5159 100644 --- a/trunk/arch/powerpc/kernel/of_platform.c +++ b/trunk/arch/powerpc/kernel/of_platform.c @@ -433,7 +433,7 @@ static int __devinit of_pci_phb_probe(struct of_device *dev, * Note also that we don't do ISA, this will also be fixed with a * more massive rework. */ - pci_setup_phb_io(phb, pci_io_base == 0); + pci_setup_phb_io(phb, 0); /* Init pci_dn data structures */ pci_devs_phb_init_dynamic(phb); diff --git a/trunk/arch/powerpc/platforms/cell/cbe_cpufreq.c b/trunk/arch/powerpc/platforms/cell/cbe_cpufreq.c index ac445998d831..f9ac3fe3be97 100644 --- a/trunk/arch/powerpc/platforms/cell/cbe_cpufreq.c +++ b/trunk/arch/powerpc/platforms/cell/cbe_cpufreq.c @@ -67,7 +67,6 @@ static u64 MIC_Slow_Next_Timer_table[] = { 0x00003FC000000000ull, }; -static unsigned int pmi_frequency_limit = 0; /* * hardware specific functions */ @@ -165,6 +164,7 @@ static int set_pmode(int cpu, unsigned int slow_mode) { static void cbe_cpufreq_handle_pmi(struct of_device *dev, pmi_message_t pmi_msg) { + struct cpufreq_policy policy; u8 cpu; u8 cbe_pmode_new; @@ -173,27 +173,15 @@ static void cbe_cpufreq_handle_pmi(struct of_device *dev, pmi_message_t pmi_msg) cpu = cbe_node_to_cpu(pmi_msg.data1); cbe_pmode_new = pmi_msg.data2; - pmi_frequency_limit = cbe_freqs[cbe_pmode_new].frequency; + cpufreq_get_policy(&policy, cpu); - pr_debug("cbe_handle_pmi: max freq=%d\n", pmi_frequency_limit); -} - -static int pmi_notifier(struct notifier_block *nb, - unsigned long event, void *data) -{ - struct cpufreq_policy *policy = data; + policy.max = min(policy.max, cbe_freqs[cbe_pmode_new].frequency); + policy.min = min(policy.min, policy.max); - if (event != CPUFREQ_INCOMPATIBLE) - return 0; - - cpufreq_verify_within_limits(policy, 0, pmi_frequency_limit); - return 0; + pr_debug("cbe_handle_pmi: new policy.min=%d policy.max=%d\n", policy.min, policy.max); + cpufreq_set_policy(&policy); } -static struct notifier_block pmi_notifier_block = { - .notifier_call = pmi_notifier, -}; - static struct pmi_handler cbe_pmi_handler = { .type = PMI_TYPE_FREQ_CHANGE, .handle_pmi_message = cbe_cpufreq_handle_pmi, @@ -250,21 +238,12 @@ static int cbe_cpufreq_cpu_init(struct cpufreq_policy *policy) cpufreq_frequency_table_get_attr(cbe_freqs, policy->cpu); - if (pmi_dev) { - /* frequency might get limited later, initialize limit with max_freq */ - pmi_frequency_limit = max_freq; - cpufreq_register_notifier(&pmi_notifier_block, CPUFREQ_POLICY_NOTIFIER); - } - /* this ensures that policy->cpuinfo_min and policy->cpuinfo_max are set correctly */ return cpufreq_frequency_table_cpuinfo(policy, cbe_freqs); } static int cbe_cpufreq_cpu_exit(struct cpufreq_policy *policy) { - if (pmi_dev) - cpufreq_unregister_notifier(&pmi_notifier_block, CPUFREQ_POLICY_NOTIFIER); - cpufreq_frequency_table_put_attr(policy->cpu); return 0; } diff --git a/trunk/arch/powerpc/platforms/cell/spufs/context.c b/trunk/arch/powerpc/platforms/cell/spufs/context.c index 7c51cb54bca1..8654749e317b 100644 --- a/trunk/arch/powerpc/platforms/cell/spufs/context.c +++ b/trunk/arch/powerpc/platforms/cell/spufs/context.c @@ -39,7 +39,7 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang) if (spu_init_csa(&ctx->csa)) goto out_free; spin_lock_init(&ctx->mmio_lock); - mutex_init(&ctx->mapping_lock); + spin_lock_init(&ctx->mapping_lock); kref_init(&ctx->kref); mutex_init(&ctx->state_mutex); mutex_init(&ctx->run_mutex); @@ -103,7 +103,6 @@ void spu_forget(struct spu_context *ctx) void spu_unmap_mappings(struct spu_context *ctx) { - mutex_lock(&ctx->mapping_lock); if (ctx->local_store) unmap_mapping_range(ctx->local_store, 0, LS_SIZE, 1); if (ctx->mfc) @@ -118,7 +117,6 @@ void spu_unmap_mappings(struct spu_context *ctx) unmap_mapping_range(ctx->mss, 0, 0x1000, 1); if (ctx->psmap) unmap_mapping_range(ctx->psmap, 0, 0x20000, 1); - mutex_unlock(&ctx->mapping_lock); } /** diff --git a/trunk/arch/powerpc/platforms/cell/spufs/file.c b/trunk/arch/powerpc/platforms/cell/spufs/file.c index b1e7e2f8a2e9..45614c73c784 100644 --- a/trunk/arch/powerpc/platforms/cell/spufs/file.c +++ b/trunk/arch/powerpc/platforms/cell/spufs/file.c @@ -45,11 +45,11 @@ spufs_mem_open(struct inode *inode, struct file *file) struct spufs_inode_info *i = SPUFS_I(inode); struct spu_context *ctx = i->i_ctx; - mutex_lock(&ctx->mapping_lock); + spin_lock(&ctx->mapping_lock); file->private_data = ctx; if (!i->i_openers++) ctx->local_store = inode->i_mapping; - mutex_unlock(&ctx->mapping_lock); + spin_unlock(&ctx->mapping_lock); return 0; } @@ -59,10 +59,10 @@ spufs_mem_release(struct inode *inode, struct file *file) struct spufs_inode_info *i = SPUFS_I(inode); struct spu_context *ctx = i->i_ctx; - mutex_lock(&ctx->mapping_lock); + spin_lock(&ctx->mapping_lock); if (!--i->i_openers) ctx->local_store = NULL; - mutex_unlock(&ctx->mapping_lock); + spin_unlock(&ctx->mapping_lock); return 0; } @@ -217,7 +217,6 @@ unsigned long spufs_get_unmapped_area(struct file *file, unsigned long addr, static const struct file_operations spufs_mem_fops = { .open = spufs_mem_open, - .release = spufs_mem_release, .read = spufs_mem_read, .write = spufs_mem_write, .llseek = generic_file_llseek, @@ -310,11 +309,11 @@ static int spufs_cntl_open(struct inode *inode, struct file *file) struct spufs_inode_info *i = SPUFS_I(inode); struct spu_context *ctx = i->i_ctx; - mutex_lock(&ctx->mapping_lock); + spin_lock(&ctx->mapping_lock); file->private_data = ctx; if (!i->i_openers++) ctx->cntl = inode->i_mapping; - mutex_unlock(&ctx->mapping_lock); + spin_unlock(&ctx->mapping_lock); return simple_attr_open(inode, file, spufs_cntl_get, spufs_cntl_set, "0x%08lx"); } @@ -327,10 +326,10 @@ spufs_cntl_release(struct inode *inode, struct file *file) simple_attr_close(inode, file); - mutex_lock(&ctx->mapping_lock); + spin_lock(&ctx->mapping_lock); if (!--i->i_openers) ctx->cntl = NULL; - mutex_unlock(&ctx->mapping_lock); + spin_unlock(&ctx->mapping_lock); return 0; } @@ -813,11 +812,11 @@ static int spufs_signal1_open(struct inode *inode, struct file *file) struct spufs_inode_info *i = SPUFS_I(inode); struct spu_context *ctx = i->i_ctx; - mutex_lock(&ctx->mapping_lock); + spin_lock(&ctx->mapping_lock); file->private_data = ctx; if (!i->i_openers++) ctx->signal1 = inode->i_mapping; - mutex_unlock(&ctx->mapping_lock); + spin_unlock(&ctx->mapping_lock); return nonseekable_open(inode, file); } @@ -827,10 +826,10 @@ spufs_signal1_release(struct inode *inode, struct file *file) struct spufs_inode_info *i = SPUFS_I(inode); struct spu_context *ctx = i->i_ctx; - mutex_lock(&ctx->mapping_lock); + spin_lock(&ctx->mapping_lock); if (!--i->i_openers) ctx->signal1 = NULL; - mutex_unlock(&ctx->mapping_lock); + spin_unlock(&ctx->mapping_lock); return 0; } @@ -937,11 +936,11 @@ static int spufs_signal2_open(struct inode *inode, struct file *file) struct spufs_inode_info *i = SPUFS_I(inode); struct spu_context *ctx = i->i_ctx; - mutex_lock(&ctx->mapping_lock); + spin_lock(&ctx->mapping_lock); file->private_data = ctx; if (!i->i_openers++) ctx->signal2 = inode->i_mapping; - mutex_unlock(&ctx->mapping_lock); + spin_unlock(&ctx->mapping_lock); return nonseekable_open(inode, file); } @@ -951,10 +950,10 @@ spufs_signal2_release(struct inode *inode, struct file *file) struct spufs_inode_info *i = SPUFS_I(inode); struct spu_context *ctx = i->i_ctx; - mutex_lock(&ctx->mapping_lock); + spin_lock(&ctx->mapping_lock); if (!--i->i_openers) ctx->signal2 = NULL; - mutex_unlock(&ctx->mapping_lock); + spin_unlock(&ctx->mapping_lock); return 0; } @@ -1155,10 +1154,10 @@ static int spufs_mss_open(struct inode *inode, struct file *file) file->private_data = i->i_ctx; - mutex_lock(&ctx->mapping_lock); + spin_lock(&ctx->mapping_lock); if (!i->i_openers++) ctx->mss = inode->i_mapping; - mutex_unlock(&ctx->mapping_lock); + spin_unlock(&ctx->mapping_lock); return nonseekable_open(inode, file); } @@ -1168,10 +1167,10 @@ spufs_mss_release(struct inode *inode, struct file *file) struct spufs_inode_info *i = SPUFS_I(inode); struct spu_context *ctx = i->i_ctx; - mutex_lock(&ctx->mapping_lock); + spin_lock(&ctx->mapping_lock); if (!--i->i_openers) ctx->mss = NULL; - mutex_unlock(&ctx->mapping_lock); + spin_unlock(&ctx->mapping_lock); return 0; } @@ -1212,11 +1211,11 @@ static int spufs_psmap_open(struct inode *inode, struct file *file) struct spufs_inode_info *i = SPUFS_I(inode); struct spu_context *ctx = i->i_ctx; - mutex_lock(&ctx->mapping_lock); + spin_lock(&ctx->mapping_lock); file->private_data = i->i_ctx; if (!i->i_openers++) ctx->psmap = inode->i_mapping; - mutex_unlock(&ctx->mapping_lock); + spin_unlock(&ctx->mapping_lock); return nonseekable_open(inode, file); } @@ -1226,10 +1225,10 @@ spufs_psmap_release(struct inode *inode, struct file *file) struct spufs_inode_info *i = SPUFS_I(inode); struct spu_context *ctx = i->i_ctx; - mutex_lock(&ctx->mapping_lock); + spin_lock(&ctx->mapping_lock); if (!--i->i_openers) ctx->psmap = NULL; - mutex_unlock(&ctx->mapping_lock); + spin_unlock(&ctx->mapping_lock); return 0; } @@ -1282,11 +1281,11 @@ static int spufs_mfc_open(struct inode *inode, struct file *file) if (atomic_read(&inode->i_count) != 1) return -EBUSY; - mutex_lock(&ctx->mapping_lock); + spin_lock(&ctx->mapping_lock); file->private_data = ctx; if (!i->i_openers++) ctx->mfc = inode->i_mapping; - mutex_unlock(&ctx->mapping_lock); + spin_unlock(&ctx->mapping_lock); return nonseekable_open(inode, file); } @@ -1296,10 +1295,10 @@ spufs_mfc_release(struct inode *inode, struct file *file) struct spufs_inode_info *i = SPUFS_I(inode); struct spu_context *ctx = i->i_ctx; - mutex_lock(&ctx->mapping_lock); + spin_lock(&ctx->mapping_lock); if (!--i->i_openers) ctx->mfc = NULL; - mutex_unlock(&ctx->mapping_lock); + spin_unlock(&ctx->mapping_lock); return 0; } diff --git a/trunk/arch/powerpc/platforms/cell/spufs/inode.c b/trunk/arch/powerpc/platforms/cell/spufs/inode.c index 9807206e0219..7150730e2ff1 100644 --- a/trunk/arch/powerpc/platforms/cell/spufs/inode.c +++ b/trunk/arch/powerpc/platforms/cell/spufs/inode.c @@ -177,7 +177,7 @@ static int spufs_rmdir(struct inode *parent, struct dentry *dir) static int spufs_fill_dir(struct dentry *dir, struct tree_descr *files, int mode, struct spu_context *ctx) { - struct dentry *dentry, *tmp; + struct dentry *dentry; int ret; while (files->name && files->name[0]) { @@ -193,20 +193,7 @@ static int spufs_fill_dir(struct dentry *dir, struct tree_descr *files, } return 0; out: - /* - * remove all children from dir. dir->inode is not set so don't - * just simply use spufs_prune_dir() and panic afterwards :) - * dput() looks like it will do the right thing: - * - dec parent's ref counter - * - remove child from parent's child list - * - free child's inode if possible - * - free child - */ - list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_u.d_child) { - dput(dentry); - } - - shrink_dcache_parent(dir); + spufs_prune_dir(dir); return ret; } @@ -287,7 +274,6 @@ spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags, goto out; out_free_ctx: - spu_forget(ctx); put_spu_context(ctx); out_iput: iput(inode); @@ -363,6 +349,37 @@ static int spufs_create_context(struct inode *inode, 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_path.dentry; + parent = dir->d_parent->d_inode; + + ret = spufs_rmgang(parent, dir); + WARN_ON(ret); + + return dcache_dir_close(inode, file); +} + +const 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) { @@ -390,6 +407,7 @@ spufs_mkgang(struct inode *dir, struct dentry *dentry, int mode) inode->i_fop = &simple_dir_operations; d_instantiate(dentry, inode); + dget(dentry); dir->i_nlink++; dentry->d_inode->i_nlink++; return ret; @@ -419,7 +437,7 @@ static int spufs_gang_open(struct dentry *dentry, struct vfsmount *mnt) goto out; } - filp->f_op = &simple_dir_operations; + filp->f_op = &spufs_gang_fops; fd_install(ret, filp); out: return ret; @@ -440,10 +458,8 @@ static int spufs_create_gang(struct inode *inode, * in error path of *_open(). */ ret = spufs_gang_open(dget(dentry), mntget(mnt)); - if (ret < 0) { - int err = simple_rmdir(inode, dentry); - WARN_ON(err); - } + if (ret < 0) + WARN_ON(spufs_rmgang(inode, dentry)); out: mutex_unlock(&inode->i_mutex); @@ -584,10 +600,6 @@ spufs_create_root(struct super_block *sb, void *data) struct inode *inode; int ret; - ret = -ENODEV; - if (!spu_management_ops) - goto out; - ret = -ENOMEM; inode = spufs_new_inode(sb, S_IFDIR | 0775); if (!inode) diff --git a/trunk/arch/powerpc/platforms/cell/spufs/sched.c b/trunk/arch/powerpc/platforms/cell/spufs/sched.c index 3b831e07f1ed..b6ecb30e7d58 100644 --- a/trunk/arch/powerpc/platforms/cell/spufs/sched.c +++ b/trunk/arch/powerpc/platforms/cell/spufs/sched.c @@ -93,6 +93,43 @@ void spu_stop_tick(struct spu_context *ctx) } } +void spu_sched_tick(struct work_struct *work) +{ + struct spu_context *ctx = + container_of(work, struct spu_context, sched_work.work); + struct spu *spu; + int preempted = 0; + + /* + * If this context is being stopped avoid rescheduling from the + * scheduler tick because we would block on the state_mutex. + * The caller will yield the spu later on anyway. + */ + if (test_bit(SPU_SCHED_EXITING, &ctx->sched_flags)) + return; + + mutex_lock(&ctx->state_mutex); + spu = ctx->spu; + if (spu) { + int best = sched_find_first_bit(spu_prio->bitmap); + if (best <= ctx->prio) { + spu_deactivate(ctx); + preempted = 1; + } + } + mutex_unlock(&ctx->state_mutex); + + if (preempted) { + /* + * We need to break out of the wait loop in spu_run manually + * to ensure this context gets put on the runqueue again + * ASAP. + */ + wake_up(&ctx->stop_wq); + } else + spu_start_tick(ctx); +} + /** * spu_add_to_active_list - add spu to active list * @spu: spu to add to the active list @@ -236,6 +273,34 @@ static void spu_prio_wait(struct spu_context *ctx) remove_wait_queue(&ctx->stop_wq, &wait); } +/** + * spu_reschedule - try to find a runnable context for a spu + * @spu: spu available + * + * This function is called whenever a spu becomes idle. It looks for the + * most suitable runnable spu context and schedules it for execution. + */ +static void spu_reschedule(struct spu *spu) +{ + int best; + + spu_free(spu); + + spin_lock(&spu_prio->runq_lock); + best = sched_find_first_bit(spu_prio->bitmap); + if (best < MAX_PRIO) { + struct list_head *rq = &spu_prio->runq[best]; + struct spu_context *ctx; + + BUG_ON(list_empty(rq)); + + ctx = list_entry(rq->next, struct spu_context, rq); + __spu_del_from_rq(ctx); + wake_up(&ctx->stop_wq); + } + spin_unlock(&spu_prio->runq_lock); +} + static struct spu *spu_get_idle(struct spu_context *ctx) { struct spu *spu = NULL; @@ -363,51 +428,6 @@ int spu_activate(struct spu_context *ctx, unsigned long flags) return -ERESTARTSYS; } -/** - * grab_runnable_context - try to find a runnable context - * - * Remove the highest priority context on the runqueue and return it - * to the caller. Returns %NULL if no runnable context was found. - */ -static struct spu_context *grab_runnable_context(int prio) -{ - struct spu_context *ctx = NULL; - int best; - - spin_lock(&spu_prio->runq_lock); - best = sched_find_first_bit(spu_prio->bitmap); - if (best < prio) { - struct list_head *rq = &spu_prio->runq[best]; - - BUG_ON(list_empty(rq)); - - ctx = list_entry(rq->next, struct spu_context, rq); - __spu_del_from_rq(ctx); - } - spin_unlock(&spu_prio->runq_lock); - - return ctx; -} - -static int __spu_deactivate(struct spu_context *ctx, int force, int max_prio) -{ - struct spu *spu = ctx->spu; - struct spu_context *new = NULL; - - if (spu) { - new = grab_runnable_context(max_prio); - if (new || force) { - spu_unbind_context(spu, ctx); - spu_free(spu); - if (new) - wake_up(&new->stop_wq); - } - - } - - return new != NULL; -} - /** * spu_deactivate - unbind a context from it's physical spu * @ctx: spu context to unbind @@ -417,7 +437,12 @@ static int __spu_deactivate(struct spu_context *ctx, int force, int max_prio) */ void spu_deactivate(struct spu_context *ctx) { - __spu_deactivate(ctx, 1, MAX_PRIO); + struct spu *spu = ctx->spu; + + if (spu) { + spu_unbind_context(spu, ctx); + spu_reschedule(spu); + } } /** @@ -430,40 +455,18 @@ void spu_deactivate(struct spu_context *ctx) */ void spu_yield(struct spu_context *ctx) { - if (!(ctx->flags & SPU_CREATE_NOSCHED)) { - mutex_lock(&ctx->state_mutex); - __spu_deactivate(ctx, 0, MAX_PRIO); - mutex_unlock(&ctx->state_mutex); - } -} - -void spu_sched_tick(struct work_struct *work) -{ - struct spu_context *ctx = - container_of(work, struct spu_context, sched_work.work); - int preempted; - - /* - * If this context is being stopped avoid rescheduling from the - * scheduler tick because we would block on the state_mutex. - * The caller will yield the spu later on anyway. - */ - if (test_bit(SPU_SCHED_EXITING, &ctx->sched_flags)) - return; - - mutex_lock(&ctx->state_mutex); - preempted = __spu_deactivate(ctx, 0, ctx->prio + 1); - mutex_unlock(&ctx->state_mutex); + struct spu *spu; - if (preempted) { - /* - * We need to break out of the wait loop in spu_run manually - * to ensure this context gets put on the runqueue again - * ASAP. - */ - wake_up(&ctx->stop_wq); - } else { - spu_start_tick(ctx); + if (mutex_trylock(&ctx->state_mutex)) { + 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); + } + } + mutex_unlock(&ctx->state_mutex); } } diff --git a/trunk/arch/powerpc/platforms/cell/spufs/spufs.h b/trunk/arch/powerpc/platforms/cell/spufs/spufs.h index 47617e8014a5..0a947fd7de57 100644 --- a/trunk/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/trunk/arch/powerpc/platforms/cell/spufs/spufs.h @@ -55,7 +55,7 @@ struct spu_context { struct address_space *signal2; /* 'signal2' area mappings. */ struct address_space *mss; /* 'mss' area mappings. */ struct address_space *psmap; /* 'psmap' area mappings. */ - struct mutex mapping_lock; + spinlock_t mapping_lock; u64 object_id; /* user space pointer for oprofile */ enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state; diff --git a/trunk/arch/powerpc/platforms/celleb/Makefile b/trunk/arch/powerpc/platforms/celleb/Makefile index 5240046d8671..f4f82520dc4f 100644 --- a/trunk/arch/powerpc/platforms/celleb/Makefile +++ b/trunk/arch/powerpc/platforms/celleb/Makefile @@ -4,5 +4,5 @@ obj-y += interrupt.o iommu.o setup.o \ obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_PPC_UDBG_BEAT) += udbg_beat.o -obj-$(CONFIG_SERIAL_TXX9) += scc_sio.o +obj-$(CONFIG_HAS_TXX9_SERIAL) += scc_sio.o obj-$(CONFIG_SPU_BASE) += spu_priv1.o diff --git a/trunk/arch/powerpc/platforms/pasemi/iommu.c b/trunk/arch/powerpc/platforms/pasemi/iommu.c index f33b21b9f5d4..95fa6a7d15ee 100644 --- a/trunk/arch/powerpc/platforms/pasemi/iommu.c +++ b/trunk/arch/powerpc/platforms/pasemi/iommu.c @@ -31,6 +31,8 @@ #define IOBMAP_PAGE_SIZE (1 << IOBMAP_PAGE_SHIFT) #define IOBMAP_PAGE_MASK (IOBMAP_PAGE_SIZE - 1) +#define IOBMAP_PAGE_FACTOR (PAGE_SHIFT - IOBMAP_PAGE_SHIFT) + #define IOB_BASE 0xe0000000 #define IOB_SIZE 0x3000 /* Configuration registers */ @@ -95,6 +97,9 @@ static void iobmap_build(struct iommu_table *tbl, long index, bus_addr = (tbl->it_offset + index) << PAGE_SHIFT; + npages <<= IOBMAP_PAGE_FACTOR; + index <<= IOBMAP_PAGE_FACTOR; + ip = ((u32 *)tbl->it_base) + index; while (npages--) { @@ -120,6 +125,9 @@ static void iobmap_free(struct iommu_table *tbl, long index, bus_addr = (tbl->it_offset + index) << PAGE_SHIFT; + npages <<= IOBMAP_PAGE_FACTOR; + index <<= IOBMAP_PAGE_FACTOR; + ip = ((u32 *)tbl->it_base) + index; while (npages--) { diff --git a/trunk/arch/sparc64/kernel/Makefile b/trunk/arch/sparc64/kernel/Makefile index d8d19093d12f..f964bf28d21a 100644 --- a/trunk/arch/sparc64/kernel/Makefile +++ b/trunk/arch/sparc64/kernel/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.70 2002/02/09 19:49:30 davem Exp $ +# # Makefile for the linux kernel. # @@ -8,7 +8,7 @@ EXTRA_CFLAGS := -Werror extra-y := head.o init_task.o vmlinux.lds obj-y := process.o setup.o cpu.o idprom.o \ - traps.o auxio.o una_asm.o \ + traps.o auxio.o una_asm.o sysfs.o \ irq.o ptrace.o time.o sys_sparc.o signal.o \ unaligned.o central.o pci.o starfire.o semaphore.o \ power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o \ diff --git a/trunk/arch/sparc64/kernel/setup.c b/trunk/arch/sparc64/kernel/setup.c index de9b4c13f1c7..7490cc670a53 100644 --- a/trunk/arch/sparc64/kernel/setup.c +++ b/trunk/arch/sparc64/kernel/setup.c @@ -513,22 +513,3 @@ void sun_do_break(void) int serial_console = -1; int stop_a_enabled = 1; - -static int __init topology_init(void) -{ - int i, err; - - err = -ENOMEM; - - for_each_possible_cpu(i) { - struct cpu *p = kzalloc(sizeof(*p), GFP_KERNEL); - if (p) { - register_cpu(p, i); - err = 0; - } - } - - return err; -} - -subsys_initcall(topology_init); diff --git a/trunk/arch/sparc64/kernel/sysfs.c b/trunk/arch/sparc64/kernel/sysfs.c new file mode 100644 index 000000000000..0808c214dc73 --- /dev/null +++ b/trunk/arch/sparc64/kernel/sysfs.c @@ -0,0 +1,26 @@ +/* sysfs.c: Toplogy sysfs support code for sparc64. + * + * Copyright (C) 2007 David S. Miller + */ +#include +#include +#include +#include +#include + +static DEFINE_PER_CPU(struct cpu, cpu_devices); + +static int __init topology_init(void) +{ + int cpu; + + for_each_possible_cpu(cpu) { + struct cpu *c = &per_cpu(cpu_devices, cpu); + + register_cpu(c, cpu); + } + + return 0; +} + +subsys_initcall(topology_init); diff --git a/trunk/kernel/signal.c b/trunk/kernel/signal.c index fe590e00db8d..acdfc0549c6f 100644 --- a/trunk/kernel/signal.c +++ b/trunk/kernel/signal.c @@ -105,11 +105,7 @@ static int recalc_sigpending_tsk(struct task_struct *t) set_tsk_thread_flag(t, TIF_SIGPENDING); return 1; } - /* - * We must never clear the flag in another thread, or in current - * when it's possible the current syscall is returning -ERESTART*. - * So we don't clear it here, and only callers who know they should do. - */ + clear_tsk_thread_flag(t, TIF_SIGPENDING); return 0; } @@ -125,9 +121,7 @@ void recalc_sigpending_and_wake(struct task_struct *t) void recalc_sigpending(void) { - if (!recalc_sigpending_tsk(current)) - clear_thread_flag(TIF_SIGPENDING); - + recalc_sigpending_tsk(current); } /* Given the mask, find the first available signal that should be serviced. */ @@ -391,8 +385,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info) } } } - if (likely(tsk == current)) - recalc_sigpending(); + recalc_sigpending_tsk(tsk); if (signr && unlikely(sig_kernel_stop(signr))) { /* * Set a marker that we have dequeued a stop signal. Our @@ -1587,9 +1580,8 @@ static void ptrace_stop(int exit_code, int nostop_code, siginfo_t *info) /* * Queued signals ignored us while we were stopped for tracing. * So check for any that we should take before resuming user mode. - * This sets TIF_SIGPENDING, but never clears it. */ - recalc_sigpending_tsk(current); + recalc_sigpending(); } void ptrace_notify(int exit_code) diff --git a/trunk/scripts/checkpatch.pl b/trunk/scripts/checkpatch.pl old mode 100755 new mode 100644