diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-30 17:20:32 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-30 17:20:32 -0800 |
commit | cdfc83075fb76369a31e6c187d0cebcab9f8b9c8 (patch) | |
tree | 33d1cdca3e2cb610451ed30943189f55652bac4c /arch/mips/kernel/vpe-cmp.c | |
parent | 04a24ae45d018e177db7e4ae2d03a70f79149782 (diff) | |
parent | b26a21c1eacdb7daf22a304fa857413df2650cfe (diff) |
Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus
Pull MIPS updates from Ralf Baechle:
"The most notable new addition inside this pull request is the support
for MIPS's latest and greatest core called "inter/proAptiv". The
patch series describes this core as follows.
"The interAptiv is a power-efficient multi-core microprocessor
for use in system-on-chip (SoC) applications. The interAptiv combines
a multi-threading pipeline with a coherence manager to deliver improved
computational throughput and power efficiency. The interAptiv can
contain one to four MIPS32R3 interAptiv cores, system level
coherence manager with L2 cache, optional coherent I/O port,
and optional floating point unit."
The platform specific patches touch all 3 Broadcom families. It adds
support for the new Broadcom/Netlogix XLP9xx Soc, building a common
BCM63XX SMP kernel for all BCM63XX SoCs regardless of core type/count
and full gpio button/led descriptions for BCM47xx.
The rest of the series are cleanups and bug fixes that are MIPS
generic and consist largely of changes that Imgtec/MIPS had published
in their linux-mti-3.10.git stable tree. Random other cleanups and
patches preparing code to be merged in 3.15"
* 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus: (139 commits)
mips: select ARCH_MIGHT_HAVE_PC_SERIO
mips: delete non-required instances of include <linux/init.h>
MIPS: KVM: remove shadow_tlb code
MIPS: KVM: use common EHINV aware UNIQUE_ENTRYHI
mips/ide: flush dcache also if icache does not snoop dcache
MIPS: BCM47XX: fix position of cpu_wait disabling
MIPS: BCM63XX: select correct MIPS_L1_CACHE_SHIFT value
MIPS: update MIPS_L1_CACHE_SHIFT based on MIPS_L1_CACHE_SHIFT_<N>
MIPS: introduce MIPS_L1_CACHE_SHIFT_<N>
MIPS: ZBOOT: gather string functions into string.c
arch/mips/pci: don't check resource with devm_ioremap_resource
arch/mips/lantiq/xway: don't check resource with devm_ioremap_resource
bcma: gpio: don't cast u32 to unsigned long
ssb: gpio: add own IRQ domain
MIPS: BCM47XX: fix sparse warnings in board.c
MIPS: BCM47XX: add board detection for Linksys WRT54GS V1
MIPS: BCM47XX: fix detection for some boards
MIPS: BCM47XX: Enable buttons support on SSB
MIPS: BCM47XX: Convert WNDR4500 to new syntax
MIPS: BCM47XX: Use "timer" trigger for status LEDs
...
Diffstat (limited to 'arch/mips/kernel/vpe-cmp.c')
-rw-r--r-- | arch/mips/kernel/vpe-cmp.c | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/arch/mips/kernel/vpe-cmp.c b/arch/mips/kernel/vpe-cmp.c new file mode 100644 index 000000000000..9268ebc0f61e --- /dev/null +++ b/arch/mips/kernel/vpe-cmp.c @@ -0,0 +1,180 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2004, 2005 MIPS Technologies, Inc. All rights reserved. + * Copyright (C) 2013 Imagination Technologies Ltd. + */ +#include <linux/kernel.h> +#include <linux/device.h> +#include <linux/fs.h> +#include <linux/slab.h> +#include <linux/export.h> + +#include <asm/vpe.h> + +static int major; + +void cleanup_tc(struct tc *tc) +{ + +} + +static ssize_t store_kill(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len) +{ + struct vpe *vpe = get_vpe(aprp_cpu_index()); + struct vpe_notifications *notifier; + + list_for_each_entry(notifier, &vpe->notify, list) + notifier->stop(aprp_cpu_index()); + + release_progmem(vpe->load_addr); + vpe->state = VPE_STATE_UNUSED; + + return len; +} +static DEVICE_ATTR(kill, S_IWUSR, NULL, store_kill); + +static ssize_t ntcs_show(struct device *cd, struct device_attribute *attr, + char *buf) +{ + struct vpe *vpe = get_vpe(aprp_cpu_index()); + + return sprintf(buf, "%d\n", vpe->ntcs); +} + +static ssize_t ntcs_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len) +{ + struct vpe *vpe = get_vpe(aprp_cpu_index()); + unsigned long new; + int ret; + + ret = kstrtoul(buf, 0, &new); + if (ret < 0) + return ret; + + /* APRP can only reserve one TC in a VPE and no more. */ + if (new != 1) + return -EINVAL; + + vpe->ntcs = new; + + return len; +} +static DEVICE_ATTR_RW(ntcs); + +static struct attribute *vpe_attrs[] = { + &dev_attr_kill.attr, + &dev_attr_ntcs.attr, + NULL, +}; +ATTRIBUTE_GROUPS(vpe); + +static void vpe_device_release(struct device *cd) +{ + kfree(cd); +} + +static struct class vpe_class = { + .name = "vpe", + .owner = THIS_MODULE, + .dev_release = vpe_device_release, + .dev_groups = vpe_groups, +}; + +static struct device vpe_device; + +int __init vpe_module_init(void) +{ + struct vpe *v = NULL; + struct tc *t; + int err; + + if (!cpu_has_mipsmt) { + pr_warn("VPE loader: not a MIPS MT capable processor\n"); + return -ENODEV; + } + + if (num_possible_cpus() - aprp_cpu_index() < 1) { + pr_warn("No VPEs reserved for AP/SP, not initialize VPE loader\n" + "Pass maxcpus=<n> argument as kernel argument\n"); + return -ENODEV; + } + + major = register_chrdev(0, VPE_MODULE_NAME, &vpe_fops); + if (major < 0) { + pr_warn("VPE loader: unable to register character device\n"); + return major; + } + + err = class_register(&vpe_class); + if (err) { + pr_err("vpe_class registration failed\n"); + goto out_chrdev; + } + + device_initialize(&vpe_device); + vpe_device.class = &vpe_class, + vpe_device.parent = NULL, + dev_set_name(&vpe_device, "vpe_sp"); + vpe_device.devt = MKDEV(major, VPE_MODULE_MINOR); + err = device_add(&vpe_device); + if (err) { + pr_err("Adding vpe_device failed\n"); + goto out_class; + } + + t = alloc_tc(aprp_cpu_index()); + if (!t) { + pr_warn("VPE: unable to allocate TC\n"); + err = -ENOMEM; + goto out_dev; + } + + /* VPE */ + v = alloc_vpe(aprp_cpu_index()); + if (v == NULL) { + pr_warn("VPE: unable to allocate VPE\n"); + kfree(t); + err = -ENOMEM; + goto out_dev; + } + + v->ntcs = 1; + + /* add the tc to the list of this vpe's tc's. */ + list_add(&t->tc, &v->tc); + + /* TC */ + t->pvpe = v; /* set the parent vpe */ + + return 0; + +out_dev: + device_del(&vpe_device); + +out_class: + class_unregister(&vpe_class); + +out_chrdev: + unregister_chrdev(major, VPE_MODULE_NAME); + + return err; +} + +void __exit vpe_module_exit(void) +{ + struct vpe *v, *n; + + device_del(&vpe_device); + class_unregister(&vpe_class); + unregister_chrdev(major, VPE_MODULE_NAME); + + /* No locking needed here */ + list_for_each_entry_safe(v, n, &vpecontrol.vpe_list, list) + if (v->state != VPE_STATE_UNUSED) + release_vpe(v); +} |