mirror of
https://github.com/torvalds/linux.git
synced 2024-12-28 05:41:55 +00:00
Driver core / sysfs patches for 3.15-rc1
Here's the big driver core / sysfs update for 3.15-rc1. Lots of kernfs updates to make it useful for other subsystems, and a few other tiny driver core patches. All have been in linux-next for a while. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iEYEABECAAYFAlM7A0wACgkQMUfUDdst+ynJNACfZlY+KNKIhNFt1OOW8rQfSZzy 1PYAnjYuOoly01JlPrpJD5b4TdxaAq71 =GVUg -----END PGP SIGNATURE----- Merge tag 'driver-core-3.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core Pull driver core and sysfs updates from Greg KH: "Here's the big driver core / sysfs update for 3.15-rc1. Lots of kernfs updates to make it useful for other subsystems, and a few other tiny driver core patches. All have been in linux-next for a while" * tag 'driver-core-3.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (42 commits) Revert "sysfs, driver-core: remove unused {sysfs|device}_schedule_callback_owner()" kernfs: cache atomic_write_len in kernfs_open_file numa: fix NULL pointer access and memory leak in unregister_one_node() Revert "driver core: synchronize device shutdown" kernfs: fix off by one error. kernfs: remove duplicate dir.c at the top dir x86: align x86 arch with generic CPU modalias handling cpu: add generic support for CPU feature based module autoloading sysfs: create bin_attributes under the requested group driver core: unexport static function create_syslog_header firmware: use power efficient workqueue for unloading and aborting fw load firmware: give a protection when map page failed firmware: google memconsole driver fixes firmware: fix google/gsmi duplicate efivars_sysfs_init() drivers/base: delete non-required instances of include <linux/init.h> kernfs: fix kernfs_node_from_dentry() ACPI / platform: drop redundant ACPI_HANDLE check kernfs: fix hash calculation in kernfs_rename_ns() kernfs: add CONFIG_KERNFS sysfs, kobject: add sysfs wrapper for kernfs_enable_ns() ...
This commit is contained in:
commit
158e0d3621
@ -23,6 +23,7 @@ struct ccwgroup_device {
|
||||
unsigned int count;
|
||||
struct device dev;
|
||||
struct ccw_device *cdev[0];
|
||||
struct work_struct ungroup_work;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -48,29 +48,27 @@ static ssize_t show_pfgid(struct device *dev, struct device_attribute *attr,
|
||||
}
|
||||
static DEVICE_ATTR(pfgid, S_IRUGO, show_pfgid, NULL);
|
||||
|
||||
static void recover_callback(struct device *dev)
|
||||
static ssize_t store_recover(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct zpci_dev *zdev = get_zdev(pdev);
|
||||
int ret;
|
||||
|
||||
if (!device_remove_file_self(dev, attr))
|
||||
return count;
|
||||
|
||||
pci_stop_and_remove_bus_device(pdev);
|
||||
ret = zpci_disable_device(zdev);
|
||||
if (ret)
|
||||
return;
|
||||
return ret;
|
||||
|
||||
ret = zpci_enable_device(zdev);
|
||||
if (ret)
|
||||
return;
|
||||
return ret;
|
||||
|
||||
pci_rescan_bus(zdev->bus);
|
||||
}
|
||||
|
||||
static ssize_t store_recover(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int rc = device_schedule_callback(dev, recover_callback);
|
||||
return rc ? rc : count;
|
||||
return count;
|
||||
}
|
||||
static DEVICE_ATTR(recover, S_IWUSR, NULL, store_recover);
|
||||
|
||||
|
@ -127,6 +127,7 @@ config X86
|
||||
select HAVE_DEBUG_STACKOVERFLOW
|
||||
select HAVE_IRQ_EXIT_ON_IRQ_STACK if X86_64
|
||||
select HAVE_CC_STACKPROTECTOR
|
||||
select GENERIC_CPU_AUTOPROBE
|
||||
|
||||
config INSTRUCTION_DECODER
|
||||
def_bool y
|
||||
@ -195,9 +196,6 @@ config ARCH_HAS_CPU_RELAX
|
||||
config ARCH_HAS_CACHE_LINE_SIZE
|
||||
def_bool y
|
||||
|
||||
config ARCH_HAS_CPU_AUTOPROBE
|
||||
def_bool y
|
||||
|
||||
config HAVE_SETUP_PER_CPU_AREA
|
||||
def_bool y
|
||||
|
||||
|
@ -546,6 +546,13 @@ static __always_inline __pure bool _static_cpu_has_safe(u16 bit)
|
||||
#define static_cpu_has_bug(bit) static_cpu_has((bit))
|
||||
#define boot_cpu_has_bug(bit) cpu_has_bug(&boot_cpu_data, (bit))
|
||||
|
||||
#define MAX_CPU_FEATURES (NCAPINTS * 32)
|
||||
#define cpu_have_feature boot_cpu_has
|
||||
|
||||
#define CPU_FEATURE_TYPEFMT "x86,ven%04Xfam%04Xmod%04X"
|
||||
#define CPU_FEATURE_TYPEVAL boot_cpu_data.x86_vendor, boot_cpu_data.x86, \
|
||||
boot_cpu_data.x86_model
|
||||
|
||||
#endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */
|
||||
|
||||
#endif /* _ASM_X86_CPUFEATURE_H */
|
||||
|
@ -47,45 +47,3 @@ const struct x86_cpu_id *x86_match_cpu(const struct x86_cpu_id *match)
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(x86_match_cpu);
|
||||
|
||||
ssize_t arch_print_cpu_modalias(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *bufptr)
|
||||
{
|
||||
int size = PAGE_SIZE;
|
||||
int i, n;
|
||||
char *buf = bufptr;
|
||||
|
||||
n = snprintf(buf, size, "x86cpu:vendor:%04X:family:%04X:"
|
||||
"model:%04X:feature:",
|
||||
boot_cpu_data.x86_vendor,
|
||||
boot_cpu_data.x86,
|
||||
boot_cpu_data.x86_model);
|
||||
size -= n;
|
||||
buf += n;
|
||||
size -= 1;
|
||||
for (i = 0; i < NCAPINTS*32; i++) {
|
||||
if (boot_cpu_has(i)) {
|
||||
n = snprintf(buf, size, ",%04X", i);
|
||||
if (n >= size) {
|
||||
WARN(1, "x86 features overflow page\n");
|
||||
break;
|
||||
}
|
||||
size -= n;
|
||||
buf += n;
|
||||
}
|
||||
}
|
||||
*buf++ = '\n';
|
||||
return buf - bufptr;
|
||||
}
|
||||
|
||||
int arch_cpu_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||
{
|
||||
char *buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
|
||||
if (buf) {
|
||||
arch_print_cpu_modalias(NULL, NULL, buf);
|
||||
add_uevent_var(env, "MODALIAS=%s", buf);
|
||||
kfree(buf);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -185,6 +185,9 @@ config GENERIC_CPU_DEVICES
|
||||
bool
|
||||
default n
|
||||
|
||||
config GENERIC_CPU_AUTOPROBE
|
||||
bool
|
||||
|
||||
config SOC_BUS
|
||||
bool
|
||||
|
||||
|
@ -12,7 +12,6 @@
|
||||
*/
|
||||
|
||||
#include <linux/attribute_container.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -23,7 +23,6 @@
|
||||
#include <linux/genhd.h>
|
||||
#include <linux/kallsyms.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/async.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/sysfs.h>
|
||||
@ -570,6 +569,23 @@ void device_remove_file(struct device *dev,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_remove_file);
|
||||
|
||||
/**
|
||||
* device_remove_file_self - remove sysfs attribute file from its own method.
|
||||
* @dev: device.
|
||||
* @attr: device attribute descriptor.
|
||||
*
|
||||
* See kernfs_remove_self() for details.
|
||||
*/
|
||||
bool device_remove_file_self(struct device *dev,
|
||||
const struct device_attribute *attr)
|
||||
{
|
||||
if (dev)
|
||||
return sysfs_remove_file_self(&dev->kobj, &attr->attr);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_remove_file_self);
|
||||
|
||||
/**
|
||||
* device_create_bin_file - create sysfs binary attribute file for device.
|
||||
* @dev: device.
|
||||
@ -2003,7 +2019,6 @@ void device_shutdown(void)
|
||||
spin_lock(&devices_kset->list_lock);
|
||||
}
|
||||
spin_unlock(&devices_kset->list_lock);
|
||||
async_synchronize_full();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2058,7 +2073,6 @@ create_syslog_header(const struct device *dev, char *hdr, size_t hdrlen)
|
||||
|
||||
return pos;
|
||||
}
|
||||
EXPORT_SYMBOL(create_syslog_header);
|
||||
|
||||
int dev_vprintk_emit(int level, const struct device *dev,
|
||||
const char *fmt, va_list args)
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <linux/percpu.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/cpufeature.h>
|
||||
|
||||
#include "base.h"
|
||||
|
||||
@ -286,6 +287,41 @@ static void cpu_device_release(struct device *dev)
|
||||
*/
|
||||
}
|
||||
|
||||
#ifdef CONFIG_GENERIC_CPU_AUTOPROBE
|
||||
static ssize_t print_cpu_modalias(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
ssize_t n;
|
||||
u32 i;
|
||||
|
||||
n = sprintf(buf, "cpu:type:" CPU_FEATURE_TYPEFMT ":feature:",
|
||||
CPU_FEATURE_TYPEVAL);
|
||||
|
||||
for (i = 0; i < MAX_CPU_FEATURES; i++)
|
||||
if (cpu_have_feature(i)) {
|
||||
if (PAGE_SIZE < n + sizeof(",XXXX\n")) {
|
||||
WARN(1, "CPU features overflow page\n");
|
||||
break;
|
||||
}
|
||||
n += sprintf(&buf[n], ",%04X", i);
|
||||
}
|
||||
buf[n++] = '\n';
|
||||
return n;
|
||||
}
|
||||
|
||||
static int cpu_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||
{
|
||||
char *buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
|
||||
if (buf) {
|
||||
print_cpu_modalias(NULL, NULL, buf);
|
||||
add_uevent_var(env, "MODALIAS=%s", buf);
|
||||
kfree(buf);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* register_cpu - Setup a sysfs device for a CPU.
|
||||
* @cpu - cpu->hotpluggable field set to 1 will generate a control file in
|
||||
@ -306,8 +342,8 @@ int register_cpu(struct cpu *cpu, int num)
|
||||
cpu->dev.offline_disabled = !cpu->hotpluggable;
|
||||
cpu->dev.offline = !cpu_online(num);
|
||||
cpu->dev.of_node = of_get_cpu_node(num, NULL);
|
||||
#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
|
||||
cpu->dev.bus->uevent = arch_cpu_uevent;
|
||||
#ifdef CONFIG_GENERIC_CPU_AUTOPROBE
|
||||
cpu->dev.bus->uevent = cpu_uevent;
|
||||
#endif
|
||||
cpu->dev.groups = common_cpu_attr_groups;
|
||||
if (cpu->hotpluggable)
|
||||
@ -330,8 +366,8 @@ struct device *get_cpu_device(unsigned cpu)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(get_cpu_device);
|
||||
|
||||
#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
|
||||
static DEVICE_ATTR(modalias, 0444, arch_print_cpu_modalias, NULL);
|
||||
#ifdef CONFIG_GENERIC_CPU_AUTOPROBE
|
||||
static DEVICE_ATTR(modalias, 0444, print_cpu_modalias, NULL);
|
||||
#endif
|
||||
|
||||
static struct attribute *cpu_root_attrs[] = {
|
||||
@ -344,7 +380,7 @@ static struct attribute *cpu_root_attrs[] = {
|
||||
&cpu_attrs[2].attr.attr,
|
||||
&dev_attr_kernel_max.attr,
|
||||
&dev_attr_offline.attr,
|
||||
#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
|
||||
#ifdef CONFIG_GENERIC_CPU_AUTOPROBE
|
||||
&dev_attr_modalias.attr,
|
||||
#endif
|
||||
NULL
|
||||
|
@ -251,9 +251,8 @@ EXPORT_SYMBOL_GPL(dma_buf_put);
|
||||
* @dmabuf: [in] buffer to attach device to.
|
||||
* @dev: [in] device to be attached.
|
||||
*
|
||||
* Returns struct dma_buf_attachment * for this attachment; may return negative
|
||||
* error codes.
|
||||
*
|
||||
* Returns struct dma_buf_attachment * for this attachment; returns ERR_PTR on
|
||||
* error.
|
||||
*/
|
||||
struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
|
||||
struct device *dev)
|
||||
@ -319,9 +318,8 @@ EXPORT_SYMBOL_GPL(dma_buf_detach);
|
||||
* @attach: [in] attachment whose scatterlist is to be returned
|
||||
* @direction: [in] direction of DMA transfer
|
||||
*
|
||||
* Returns sg_table containing the scatterlist to be returned; may return NULL
|
||||
* or ERR_PTR.
|
||||
*
|
||||
* Returns sg_table containing the scatterlist to be returned; returns ERR_PTR
|
||||
* on error.
|
||||
*/
|
||||
struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
|
||||
enum dma_data_direction direction)
|
||||
@ -334,6 +332,8 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
sg_table = attach->dmabuf->ops->map_dma_buf(attach, direction);
|
||||
if (!sg_table)
|
||||
sg_table = ERR_PTR(-ENOMEM);
|
||||
|
||||
return sg_table;
|
||||
}
|
||||
@ -544,6 +544,8 @@ EXPORT_SYMBOL_GPL(dma_buf_mmap);
|
||||
* These calls are optional in drivers. The intended use for them
|
||||
* is for mapping objects linear in kernel space for high use objects.
|
||||
* Please attempt to use kmap/kunmap before thinking about these interfaces.
|
||||
*
|
||||
* Returns NULL on error.
|
||||
*/
|
||||
void *dma_buf_vmap(struct dma_buf *dmabuf)
|
||||
{
|
||||
@ -566,7 +568,9 @@ void *dma_buf_vmap(struct dma_buf *dmabuf)
|
||||
BUG_ON(dmabuf->vmap_ptr);
|
||||
|
||||
ptr = dmabuf->ops->vmap(dmabuf);
|
||||
if (IS_ERR_OR_NULL(ptr))
|
||||
if (WARN_ON_ONCE(IS_ERR(ptr)))
|
||||
ptr = NULL;
|
||||
if (!ptr)
|
||||
goto out_unlock;
|
||||
|
||||
dmabuf->vmap_ptr = ptr;
|
||||
|
@ -649,7 +649,9 @@ static ssize_t firmware_loading_store(struct device *dev,
|
||||
* see the mapped 'buf->data' once the loading
|
||||
* is completed.
|
||||
* */
|
||||
fw_map_pages_buf(fw_buf);
|
||||
if (fw_map_pages_buf(fw_buf))
|
||||
dev_err(dev, "%s: map pages failed\n",
|
||||
__func__);
|
||||
list_del_init(&fw_buf->pending_list);
|
||||
complete_all(&fw_buf->completion);
|
||||
break;
|
||||
@ -900,7 +902,8 @@ static int _request_firmware_load(struct firmware_priv *fw_priv,
|
||||
dev_set_uevent_suppress(f_dev, false);
|
||||
dev_dbg(f_dev, "firmware: requesting %s\n", buf->fw_id);
|
||||
if (timeout != MAX_SCHEDULE_TIMEOUT)
|
||||
schedule_delayed_work(&fw_priv->timeout_work, timeout);
|
||||
queue_delayed_work(system_power_efficient_wq,
|
||||
&fw_priv->timeout_work, timeout);
|
||||
|
||||
kobject_uevent(&fw_priv->dev.kobj, KOBJ_ADD);
|
||||
}
|
||||
@ -908,6 +911,8 @@ static int _request_firmware_load(struct firmware_priv *fw_priv,
|
||||
wait_for_completion(&buf->completion);
|
||||
|
||||
cancel_delayed_work_sync(&fw_priv->timeout_work);
|
||||
if (!buf->data)
|
||||
retval = -ENOMEM;
|
||||
|
||||
device_remove_file(f_dev, &dev_attr_loading);
|
||||
err_del_bin_attr:
|
||||
@ -1570,8 +1575,8 @@ static void device_uncache_fw_images_work(struct work_struct *work)
|
||||
*/
|
||||
static void device_uncache_fw_images_delay(unsigned long delay)
|
||||
{
|
||||
schedule_delayed_work(&fw_cache.work,
|
||||
msecs_to_jiffies(delay));
|
||||
queue_delayed_work(system_power_efficient_wq, &fw_cache.work,
|
||||
msecs_to_jiffies(delay));
|
||||
}
|
||||
|
||||
static int fw_pm_notify(struct notifier_block *notify_block,
|
||||
|
@ -599,7 +599,11 @@ int register_one_node(int nid)
|
||||
|
||||
void unregister_one_node(int nid)
|
||||
{
|
||||
if (!node_devices[nid])
|
||||
return;
|
||||
|
||||
unregister_node(node_devices[nid]);
|
||||
kfree(node_devices[nid]);
|
||||
node_devices[nid] = NULL;
|
||||
}
|
||||
|
||||
|
@ -481,11 +481,10 @@ static int platform_drv_probe(struct device *_dev)
|
||||
struct platform_device *dev = to_platform_device(_dev);
|
||||
int ret;
|
||||
|
||||
if (ACPI_HANDLE(_dev))
|
||||
acpi_dev_pm_attach(_dev, true);
|
||||
acpi_dev_pm_attach(_dev, true);
|
||||
|
||||
ret = drv->probe(dev);
|
||||
if (ret && ACPI_HANDLE(_dev))
|
||||
if (ret)
|
||||
acpi_dev_pm_detach(_dev, true);
|
||||
|
||||
if (drv->prevent_deferred_probe && ret == -EPROBE_DEFER) {
|
||||
@ -508,8 +507,7 @@ static int platform_drv_remove(struct device *_dev)
|
||||
int ret;
|
||||
|
||||
ret = drv->remove(dev);
|
||||
if (ACPI_HANDLE(_dev))
|
||||
acpi_dev_pm_detach(_dev, true);
|
||||
acpi_dev_pm_detach(_dev, true);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -520,8 +518,7 @@ static void platform_drv_shutdown(struct device *_dev)
|
||||
struct platform_device *dev = to_platform_device(_dev);
|
||||
|
||||
drv->shutdown(dev);
|
||||
if (ACPI_HANDLE(_dev))
|
||||
acpi_dev_pm_detach(_dev, true);
|
||||
acpi_dev_pm_detach(_dev, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -6,7 +6,6 @@
|
||||
* This file is released under the GPLv2.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/io.h>
|
||||
|
@ -6,7 +6,6 @@
|
||||
* This file is released under the GPLv2.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/export.h>
|
||||
|
@ -6,7 +6,6 @@
|
||||
* This file is released under the GPLv2.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
@ -6,7 +6,6 @@
|
||||
* This file is released under the GPLv2.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/pm_qos.h>
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/device.h>
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
static int regmap_i2c_write(void *context, const void *data, size_t count)
|
||||
{
|
||||
|
@ -18,7 +18,6 @@
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/regmap.h>
|
||||
|
@ -12,7 +12,6 @@
|
||||
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
@ -23,7 +23,6 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/module.h>
|
||||
|
@ -892,13 +892,6 @@ static __init int gsmi_init(void)
|
||||
goto out_remove_sysfs_files;
|
||||
}
|
||||
|
||||
ret = efivars_sysfs_init();
|
||||
if (ret) {
|
||||
printk(KERN_INFO "gsmi: Failed to create efivars files\n");
|
||||
efivars_unregister(&efivars);
|
||||
goto out_remove_sysfs_files;
|
||||
}
|
||||
|
||||
register_reboot_notifier(&gsmi_reboot_notifier);
|
||||
register_die_notifier(&gsmi_die_notifier);
|
||||
atomic_notifier_chain_register(&panic_notifier_list,
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/io.h>
|
||||
#include <asm/bios_ebda.h>
|
||||
|
||||
#define BIOS_MEMCONSOLE_V1_MAGIC 0xDEADBABE
|
||||
@ -41,15 +42,25 @@ struct biosmemcon_ebda {
|
||||
};
|
||||
} __packed;
|
||||
|
||||
static char *memconsole_baseaddr;
|
||||
static u32 memconsole_baseaddr;
|
||||
static size_t memconsole_length;
|
||||
|
||||
static ssize_t memconsole_read(struct file *filp, struct kobject *kobp,
|
||||
struct bin_attribute *bin_attr, char *buf,
|
||||
loff_t pos, size_t count)
|
||||
{
|
||||
return memory_read_from_buffer(buf, count, &pos, memconsole_baseaddr,
|
||||
memconsole_length);
|
||||
char *memconsole;
|
||||
ssize_t ret;
|
||||
|
||||
memconsole = ioremap_cache(memconsole_baseaddr, memconsole_length);
|
||||
if (!memconsole) {
|
||||
pr_err("memconsole: ioremap_cache failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
ret = memory_read_from_buffer(buf, count, &pos, memconsole,
|
||||
memconsole_length);
|
||||
iounmap(memconsole);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct bin_attribute memconsole_bin_attr = {
|
||||
@ -58,43 +69,42 @@ static struct bin_attribute memconsole_bin_attr = {
|
||||
};
|
||||
|
||||
|
||||
static void found_v1_header(struct biosmemcon_ebda *hdr)
|
||||
static void __init found_v1_header(struct biosmemcon_ebda *hdr)
|
||||
{
|
||||
printk(KERN_INFO "BIOS console v1 EBDA structure found at %p\n", hdr);
|
||||
printk(KERN_INFO "BIOS console buffer at 0x%.8x, "
|
||||
pr_info("BIOS console v1 EBDA structure found at %p\n", hdr);
|
||||
pr_info("BIOS console buffer at 0x%.8x, "
|
||||
"start = %d, end = %d, num = %d\n",
|
||||
hdr->v1.buffer_addr, hdr->v1.start,
|
||||
hdr->v1.end, hdr->v1.num_chars);
|
||||
|
||||
memconsole_length = hdr->v1.num_chars;
|
||||
memconsole_baseaddr = phys_to_virt(hdr->v1.buffer_addr);
|
||||
memconsole_baseaddr = hdr->v1.buffer_addr;
|
||||
}
|
||||
|
||||
static void found_v2_header(struct biosmemcon_ebda *hdr)
|
||||
static void __init found_v2_header(struct biosmemcon_ebda *hdr)
|
||||
{
|
||||
printk(KERN_INFO "BIOS console v2 EBDA structure found at %p\n", hdr);
|
||||
printk(KERN_INFO "BIOS console buffer at 0x%.8x, "
|
||||
pr_info("BIOS console v2 EBDA structure found at %p\n", hdr);
|
||||
pr_info("BIOS console buffer at 0x%.8x, "
|
||||
"start = %d, end = %d, num_bytes = %d\n",
|
||||
hdr->v2.buffer_addr, hdr->v2.start,
|
||||
hdr->v2.end, hdr->v2.num_bytes);
|
||||
|
||||
memconsole_length = hdr->v2.end - hdr->v2.start;
|
||||
memconsole_baseaddr = phys_to_virt(hdr->v2.buffer_addr
|
||||
+ hdr->v2.start);
|
||||
memconsole_baseaddr = hdr->v2.buffer_addr + hdr->v2.start;
|
||||
}
|
||||
|
||||
/*
|
||||
* Search through the EBDA for the BIOS Memory Console, and
|
||||
* set the global variables to point to it. Return true if found.
|
||||
*/
|
||||
static bool found_memconsole(void)
|
||||
static bool __init found_memconsole(void)
|
||||
{
|
||||
unsigned int address;
|
||||
size_t length, cur;
|
||||
|
||||
address = get_bios_ebda();
|
||||
if (!address) {
|
||||
printk(KERN_INFO "BIOS EBDA non-existent.\n");
|
||||
pr_info("BIOS EBDA non-existent.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -122,7 +132,7 @@ static bool found_memconsole(void)
|
||||
}
|
||||
}
|
||||
|
||||
printk(KERN_INFO "BIOS console EBDA structure not found!\n");
|
||||
pr_info("BIOS console EBDA structure not found!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -139,8 +149,6 @@ MODULE_DEVICE_TABLE(dmi, memconsole_dmi_table);
|
||||
|
||||
static int __init memconsole_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!dmi_check_system(memconsole_dmi_table))
|
||||
return -ENODEV;
|
||||
|
||||
@ -148,10 +156,7 @@ static int __init memconsole_init(void)
|
||||
return -ENODEV;
|
||||
|
||||
memconsole_bin_attr.size = memconsole_length;
|
||||
|
||||
ret = sysfs_create_bin_file(firmware_kobj, &memconsole_bin_attr);
|
||||
|
||||
return ret;
|
||||
return sysfs_create_bin_file(firmware_kobj, &memconsole_bin_attr);
|
||||
}
|
||||
|
||||
static void __exit memconsole_exit(void)
|
||||
|
@ -471,7 +471,7 @@ struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
|
||||
get_dma_buf(dma_buf);
|
||||
|
||||
sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
|
||||
if (IS_ERR_OR_NULL(sgt)) {
|
||||
if (IS_ERR(sgt)) {
|
||||
ret = PTR_ERR(sgt);
|
||||
goto fail_detach;
|
||||
}
|
||||
|
@ -224,7 +224,7 @@ struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev,
|
||||
get_dma_buf(dma_buf);
|
||||
|
||||
sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
|
||||
if (IS_ERR_OR_NULL(sgt)) {
|
||||
if (IS_ERR(sgt)) {
|
||||
ret = PTR_ERR(sgt);
|
||||
goto err_buf_detach;
|
||||
}
|
||||
|
@ -719,7 +719,7 @@ static int vb2_dc_map_dmabuf(void *mem_priv)
|
||||
|
||||
/* get the associated scatterlist for this buffer */
|
||||
sgt = dma_buf_map_attachment(buf->db_attach, buf->dma_dir);
|
||||
if (IS_ERR_OR_NULL(sgt)) {
|
||||
if (IS_ERR(sgt)) {
|
||||
pr_err("Error getting dmabuf scatterlist\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -351,28 +351,17 @@ static struct device_attribute dev_rescan_attr = __ATTR(rescan,
|
||||
(S_IWUSR|S_IWGRP),
|
||||
NULL, dev_rescan_store);
|
||||
|
||||
static void remove_callback(struct device *dev)
|
||||
{
|
||||
pci_stop_and_remove_bus_device_locked(to_pci_dev(dev));
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
remove_store(struct device *dev, struct device_attribute *dummy,
|
||||
remove_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long val;
|
||||
|
||||
if (kstrtoul(buf, 0, &val) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* An attribute cannot be unregistered by one of its own methods,
|
||||
* so we have to use this roundabout approach.
|
||||
*/
|
||||
if (val)
|
||||
ret = device_schedule_callback(dev, remove_callback);
|
||||
if (ret)
|
||||
count = ret;
|
||||
if (val && device_remove_file_self(dev, attr))
|
||||
pci_stop_and_remove_bus_device_locked(to_pci_dev(dev));
|
||||
return count;
|
||||
}
|
||||
static struct device_attribute dev_remove_attr = __ATTR(remove,
|
||||
|
@ -304,12 +304,6 @@ dcssblk_load_segment(char *name, struct segment_info **seg_info)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void dcssblk_unregister_callback(struct device *dev)
|
||||
{
|
||||
device_unregister(dev);
|
||||
put_device(dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* device attribute for switching shared/nonshared (exclusive)
|
||||
* operation (show + store)
|
||||
@ -397,7 +391,13 @@ removeseg:
|
||||
blk_cleanup_queue(dev_info->dcssblk_queue);
|
||||
dev_info->gd->queue = NULL;
|
||||
put_disk(dev_info->gd);
|
||||
rc = device_schedule_callback(dev, dcssblk_unregister_callback);
|
||||
up_write(&dcssblk_devices_sem);
|
||||
|
||||
if (device_remove_file_self(dev, attr)) {
|
||||
device_unregister(dev);
|
||||
put_device(dev);
|
||||
}
|
||||
return rc;
|
||||
out:
|
||||
up_write(&dcssblk_devices_sem);
|
||||
return rc;
|
||||
|
@ -168,14 +168,12 @@ static ssize_t ccwgroup_online_show(struct device *dev,
|
||||
* Provide an 'ungroup' attribute so the user can remove group devices no
|
||||
* longer needed or accidentially created. Saves memory :)
|
||||
*/
|
||||
static void ccwgroup_ungroup_callback(struct device *dev)
|
||||
static void ccwgroup_ungroup(struct ccwgroup_device *gdev)
|
||||
{
|
||||
struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
|
||||
|
||||
mutex_lock(&gdev->reg_mutex);
|
||||
if (device_is_registered(&gdev->dev)) {
|
||||
__ccwgroup_remove_symlinks(gdev);
|
||||
device_unregister(dev);
|
||||
device_unregister(&gdev->dev);
|
||||
__ccwgroup_remove_cdev_refs(gdev);
|
||||
}
|
||||
mutex_unlock(&gdev->reg_mutex);
|
||||
@ -195,10 +193,9 @@ static ssize_t ccwgroup_ungroup_store(struct device *dev,
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
/* Note that we cannot unregister the device from one of its
|
||||
* attribute methods, so we have to use this roundabout approach.
|
||||
*/
|
||||
rc = device_schedule_callback(dev, ccwgroup_ungroup_callback);
|
||||
|
||||
if (device_remove_file_self(dev, attr))
|
||||
ccwgroup_ungroup(gdev);
|
||||
out:
|
||||
if (rc) {
|
||||
if (rc != -EAGAIN)
|
||||
@ -224,6 +221,14 @@ static const struct attribute_group *ccwgroup_attr_groups[] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
static void ccwgroup_ungroup_workfn(struct work_struct *work)
|
||||
{
|
||||
struct ccwgroup_device *gdev =
|
||||
container_of(work, struct ccwgroup_device, ungroup_work);
|
||||
|
||||
ccwgroup_ungroup(gdev);
|
||||
}
|
||||
|
||||
static void ccwgroup_release(struct device *dev)
|
||||
{
|
||||
kfree(to_ccwgroupdev(dev));
|
||||
@ -323,6 +328,7 @@ int ccwgroup_create_dev(struct device *parent, struct ccwgroup_driver *gdrv,
|
||||
atomic_set(&gdev->onoff, 0);
|
||||
mutex_init(&gdev->reg_mutex);
|
||||
mutex_lock(&gdev->reg_mutex);
|
||||
INIT_WORK(&gdev->ungroup_work, ccwgroup_ungroup_workfn);
|
||||
gdev->count = num_devices;
|
||||
gdev->dev.bus = &ccwgroup_bus_type;
|
||||
gdev->dev.parent = parent;
|
||||
@ -404,10 +410,10 @@ EXPORT_SYMBOL(ccwgroup_create_dev);
|
||||
static int ccwgroup_notifier(struct notifier_block *nb, unsigned long action,
|
||||
void *data)
|
||||
{
|
||||
struct device *dev = data;
|
||||
struct ccwgroup_device *gdev = to_ccwgroupdev(data);
|
||||
|
||||
if (action == BUS_NOTIFY_UNBIND_DRIVER)
|
||||
device_schedule_callback(dev, ccwgroup_ungroup_callback);
|
||||
schedule_work(&gdev->ungroup_work);
|
||||
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
@ -649,23 +649,12 @@ store_rescan_field (struct device *dev, struct device_attribute *attr,
|
||||
}
|
||||
static DEVICE_ATTR(rescan, S_IWUSR, NULL, store_rescan_field);
|
||||
|
||||
static void sdev_store_delete_callback(struct device *dev)
|
||||
{
|
||||
scsi_remove_device(to_scsi_device(dev));
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
sdev_store_delete(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* An attribute cannot be unregistered by one of its own methods,
|
||||
* so we have to use this roundabout approach.
|
||||
*/
|
||||
rc = device_schedule_callback(dev, sdev_store_delete_callback);
|
||||
if (rc)
|
||||
count = rc;
|
||||
if (device_remove_file_self(dev, attr))
|
||||
scsi_remove_device(to_scsi_device(dev));
|
||||
return count;
|
||||
};
|
||||
static DEVICE_ATTR(delete, S_IWUSR, NULL, sdev_store_delete);
|
||||
|
@ -96,6 +96,7 @@ endif # BLOCK
|
||||
menu "Pseudo filesystems"
|
||||
|
||||
source "fs/proc/Kconfig"
|
||||
source "fs/kernfs/Kconfig"
|
||||
source "fs/sysfs/Kconfig"
|
||||
|
||||
config TMPFS
|
||||
|
@ -52,7 +52,8 @@ obj-$(CONFIG_FHANDLE) += fhandle.o
|
||||
obj-y += quota/
|
||||
|
||||
obj-$(CONFIG_PROC_FS) += proc/
|
||||
obj-$(CONFIG_SYSFS) += sysfs/ kernfs/
|
||||
obj-$(CONFIG_KERNFS) += kernfs/
|
||||
obj-$(CONFIG_SYSFS) += sysfs/
|
||||
obj-$(CONFIG_CONFIGFS_FS) += configfs/
|
||||
obj-y += devpts/
|
||||
|
||||
|
7
fs/kernfs/Kconfig
Normal file
7
fs/kernfs/Kconfig
Normal file
@ -0,0 +1,7 @@
|
||||
#
|
||||
# KERNFS should be selected by its users
|
||||
#
|
||||
|
||||
config KERNFS
|
||||
bool
|
||||
default n
|
758
fs/kernfs/dir.c
758
fs/kernfs/dir.c
File diff suppressed because it is too large
Load Diff
@ -252,10 +252,18 @@ static ssize_t kernfs_fop_write(struct file *file, const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct kernfs_open_file *of = kernfs_of(file);
|
||||
ssize_t len = min_t(size_t, count, PAGE_SIZE);
|
||||
const struct kernfs_ops *ops;
|
||||
size_t len;
|
||||
char *buf;
|
||||
|
||||
if (of->atomic_write_len) {
|
||||
len = count;
|
||||
if (len > of->atomic_write_len)
|
||||
return -E2BIG;
|
||||
} else {
|
||||
len = min_t(size_t, count, PAGE_SIZE);
|
||||
}
|
||||
|
||||
buf = kmalloc(len + 1, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
@ -652,6 +660,12 @@ static int kernfs_fop_open(struct inode *inode, struct file *file)
|
||||
of->kn = kn;
|
||||
of->file = file;
|
||||
|
||||
/*
|
||||
* Write path needs to atomic_write_len outside active reference.
|
||||
* Cache it in open_file. See kernfs_fop_write() for details.
|
||||
*/
|
||||
of->atomic_write_len = ops->atomic_write_len;
|
||||
|
||||
/*
|
||||
* Always instantiate seq_file even if read access doesn't use
|
||||
* seq_file or is not requested. This unifies private data access
|
||||
@ -820,7 +834,6 @@ struct kernfs_node *__kernfs_create_file(struct kernfs_node *parent,
|
||||
bool name_is_static,
|
||||
struct lock_class_key *key)
|
||||
{
|
||||
struct kernfs_addrm_cxt acxt;
|
||||
struct kernfs_node *kn;
|
||||
unsigned flags;
|
||||
int rc;
|
||||
@ -855,10 +868,7 @@ struct kernfs_node *__kernfs_create_file(struct kernfs_node *parent,
|
||||
if (ops->mmap)
|
||||
kn->flags |= KERNFS_HAS_MMAP;
|
||||
|
||||
kernfs_addrm_start(&acxt);
|
||||
rc = kernfs_add_one(&acxt, kn);
|
||||
kernfs_addrm_finish(&acxt);
|
||||
|
||||
rc = kernfs_add_one(kn);
|
||||
if (rc) {
|
||||
kernfs_put(kn);
|
||||
return ERR_PTR(rc);
|
||||
|
@ -26,7 +26,8 @@ struct kernfs_iattrs {
|
||||
struct simple_xattrs xattrs;
|
||||
};
|
||||
|
||||
#define KN_DEACTIVATED_BIAS INT_MIN
|
||||
/* +1 to avoid triggering overflow warning when negating it */
|
||||
#define KN_DEACTIVATED_BIAS (INT_MIN + 1)
|
||||
|
||||
/* KERNFS_TYPE_MASK and types are defined in include/linux/kernfs.h */
|
||||
|
||||
@ -44,13 +45,6 @@ static inline struct kernfs_root *kernfs_root(struct kernfs_node *kn)
|
||||
return kn->dir.root;
|
||||
}
|
||||
|
||||
/*
|
||||
* Context structure to be used while adding/removing nodes.
|
||||
*/
|
||||
struct kernfs_addrm_cxt {
|
||||
struct kernfs_node *removed;
|
||||
};
|
||||
|
||||
/*
|
||||
* mount.c
|
||||
*/
|
||||
@ -71,6 +65,7 @@ struct kernfs_super_info {
|
||||
};
|
||||
#define kernfs_info(SB) ((struct kernfs_super_info *)(SB->s_fs_info))
|
||||
|
||||
extern const struct super_operations kernfs_sops;
|
||||
extern struct kmem_cache *kernfs_node_cache;
|
||||
|
||||
/*
|
||||
@ -100,9 +95,7 @@ extern const struct inode_operations kernfs_dir_iops;
|
||||
|
||||
struct kernfs_node *kernfs_get_active(struct kernfs_node *kn);
|
||||
void kernfs_put_active(struct kernfs_node *kn);
|
||||
void kernfs_addrm_start(struct kernfs_addrm_cxt *acxt);
|
||||
int kernfs_add_one(struct kernfs_addrm_cxt *acxt, struct kernfs_node *kn);
|
||||
void kernfs_addrm_finish(struct kernfs_addrm_cxt *acxt);
|
||||
int kernfs_add_one(struct kernfs_node *kn);
|
||||
struct kernfs_node *kernfs_new_node(struct kernfs_node *parent,
|
||||
const char *name, umode_t mode,
|
||||
unsigned flags);
|
||||
|
@ -19,12 +19,49 @@
|
||||
|
||||
struct kmem_cache *kernfs_node_cache;
|
||||
|
||||
static const struct super_operations kernfs_sops = {
|
||||
static int kernfs_sop_remount_fs(struct super_block *sb, int *flags, char *data)
|
||||
{
|
||||
struct kernfs_root *root = kernfs_info(sb)->root;
|
||||
struct kernfs_syscall_ops *scops = root->syscall_ops;
|
||||
|
||||
if (scops && scops->remount_fs)
|
||||
return scops->remount_fs(root, flags, data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kernfs_sop_show_options(struct seq_file *sf, struct dentry *dentry)
|
||||
{
|
||||
struct kernfs_root *root = kernfs_root(dentry->d_fsdata);
|
||||
struct kernfs_syscall_ops *scops = root->syscall_ops;
|
||||
|
||||
if (scops && scops->show_options)
|
||||
return scops->show_options(sf, root);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct super_operations kernfs_sops = {
|
||||
.statfs = simple_statfs,
|
||||
.drop_inode = generic_delete_inode,
|
||||
.evict_inode = kernfs_evict_inode,
|
||||
|
||||
.remount_fs = kernfs_sop_remount_fs,
|
||||
.show_options = kernfs_sop_show_options,
|
||||
};
|
||||
|
||||
/**
|
||||
* kernfs_root_from_sb - determine kernfs_root associated with a super_block
|
||||
* @sb: the super_block in question
|
||||
*
|
||||
* Return the kernfs_root associated with @sb. If @sb is not a kernfs one,
|
||||
* %NULL is returned.
|
||||
*/
|
||||
struct kernfs_root *kernfs_root_from_sb(struct super_block *sb)
|
||||
{
|
||||
if (sb->s_op == &kernfs_sops)
|
||||
return kernfs_info(sb)->root;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int kernfs_fill_super(struct super_block *sb)
|
||||
{
|
||||
struct kernfs_super_info *info = kernfs_info(sb);
|
||||
|
@ -27,7 +27,6 @@ struct kernfs_node *kernfs_create_link(struct kernfs_node *parent,
|
||||
struct kernfs_node *target)
|
||||
{
|
||||
struct kernfs_node *kn;
|
||||
struct kernfs_addrm_cxt acxt;
|
||||
int error;
|
||||
|
||||
kn = kernfs_new_node(parent, name, S_IFLNK|S_IRWXUGO, KERNFS_LINK);
|
||||
@ -39,10 +38,7 @@ struct kernfs_node *kernfs_create_link(struct kernfs_node *parent,
|
||||
kn->symlink.target_kn = target;
|
||||
kernfs_get(target); /* ref owned by symlink */
|
||||
|
||||
kernfs_addrm_start(&acxt);
|
||||
error = kernfs_add_one(&acxt, kn);
|
||||
kernfs_addrm_finish(&acxt);
|
||||
|
||||
error = kernfs_add_one(kn);
|
||||
if (!error)
|
||||
return kn;
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
config SYSFS
|
||||
bool "sysfs file system support" if EXPERT
|
||||
default y
|
||||
select KERNFS
|
||||
help
|
||||
The sysfs filesystem is a virtual filesystem that the kernel uses to
|
||||
export internal kernel objects, their attributes, and their
|
||||
|
@ -19,39 +19,18 @@
|
||||
|
||||
DEFINE_SPINLOCK(sysfs_symlink_target_lock);
|
||||
|
||||
/**
|
||||
* sysfs_pathname - return full path to sysfs dirent
|
||||
* @kn: kernfs_node whose path we want
|
||||
* @path: caller allocated buffer of size PATH_MAX
|
||||
*
|
||||
* Gives the name "/" to the sysfs_root entry; any path returned
|
||||
* is relative to wherever sysfs is mounted.
|
||||
*/
|
||||
static char *sysfs_pathname(struct kernfs_node *kn, char *path)
|
||||
{
|
||||
if (kn->parent) {
|
||||
sysfs_pathname(kn->parent, path);
|
||||
strlcat(path, "/", PATH_MAX);
|
||||
}
|
||||
strlcat(path, kn->name, PATH_MAX);
|
||||
return path;
|
||||
}
|
||||
|
||||
void sysfs_warn_dup(struct kernfs_node *parent, const char *name)
|
||||
{
|
||||
char *path;
|
||||
char *buf, *path = NULL;
|
||||
|
||||
path = kzalloc(PATH_MAX, GFP_KERNEL);
|
||||
if (path) {
|
||||
sysfs_pathname(parent, path);
|
||||
strlcat(path, "/", PATH_MAX);
|
||||
strlcat(path, name, PATH_MAX);
|
||||
}
|
||||
buf = kzalloc(PATH_MAX, GFP_KERNEL);
|
||||
if (buf)
|
||||
path = kernfs_path(parent, buf, PATH_MAX);
|
||||
|
||||
WARN(1, KERN_WARNING "sysfs: cannot create duplicate filename '%s'\n",
|
||||
path ? path : name);
|
||||
WARN(1, KERN_WARNING "sysfs: cannot create duplicate filename '%s/%s'\n",
|
||||
path, name);
|
||||
|
||||
kfree(path);
|
||||
kfree(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -122,9 +101,13 @@ void sysfs_remove_dir(struct kobject *kobj)
|
||||
int sysfs_rename_dir_ns(struct kobject *kobj, const char *new_name,
|
||||
const void *new_ns)
|
||||
{
|
||||
struct kernfs_node *parent = kobj->sd->parent;
|
||||
struct kernfs_node *parent;
|
||||
int ret;
|
||||
|
||||
return kernfs_rename_ns(kobj->sd, parent, new_name, new_ns);
|
||||
parent = kernfs_get_parent(kobj->sd);
|
||||
ret = kernfs_rename_ns(kobj->sd, parent, new_name, new_ns);
|
||||
kernfs_put(parent);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sysfs_move_dir_ns(struct kobject *kobj, struct kobject *new_parent_kobj,
|
||||
@ -133,7 +116,6 @@ int sysfs_move_dir_ns(struct kobject *kobj, struct kobject *new_parent_kobj,
|
||||
struct kernfs_node *kn = kobj->sd;
|
||||
struct kernfs_node *new_parent;
|
||||
|
||||
BUG_ON(!kn->parent);
|
||||
new_parent = new_parent_kobj && new_parent_kobj->sd ?
|
||||
new_parent_kobj->sd : sysfs_root_kn;
|
||||
|
||||
|
@ -372,6 +372,29 @@ void sysfs_remove_file_ns(struct kobject *kobj, const struct attribute *attr,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sysfs_remove_file_ns);
|
||||
|
||||
/**
|
||||
* sysfs_remove_file_self - remove an object attribute from its own method
|
||||
* @kobj: object we're acting for
|
||||
* @attr: attribute descriptor
|
||||
*
|
||||
* See kernfs_remove_self() for details.
|
||||
*/
|
||||
bool sysfs_remove_file_self(struct kobject *kobj, const struct attribute *attr)
|
||||
{
|
||||
struct kernfs_node *parent = kobj->sd;
|
||||
struct kernfs_node *kn;
|
||||
bool ret;
|
||||
|
||||
kn = kernfs_find_and_get(parent, attr->name);
|
||||
if (WARN_ON_ONCE(!kn))
|
||||
return false;
|
||||
|
||||
ret = kernfs_remove_self(kn);
|
||||
|
||||
kernfs_put(kn);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void sysfs_remove_files(struct kobject *kobj, const struct attribute **ptr)
|
||||
{
|
||||
int i;
|
||||
|
@ -70,8 +70,11 @@ static int create_files(struct kernfs_node *parent, struct kobject *kobj,
|
||||
if (grp->bin_attrs) {
|
||||
for (bin_attr = grp->bin_attrs; *bin_attr; bin_attr++) {
|
||||
if (update)
|
||||
sysfs_remove_bin_file(kobj, *bin_attr);
|
||||
error = sysfs_create_bin_file(kobj, *bin_attr);
|
||||
kernfs_remove_by_name(parent,
|
||||
(*bin_attr)->attr.name);
|
||||
error = sysfs_add_file_mode_ns(parent,
|
||||
&(*bin_attr)->attr, true,
|
||||
(*bin_attr)->attr.mode, NULL);
|
||||
if (error)
|
||||
break;
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ int __init sysfs_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
sysfs_root = kernfs_create_root(NULL, NULL);
|
||||
sysfs_root = kernfs_create_root(NULL, 0, NULL);
|
||||
if (IS_ERR(sysfs_root))
|
||||
return PTR_ERR(sysfs_root);
|
||||
|
||||
|
@ -46,13 +46,6 @@ extern ssize_t arch_cpu_release(const char *, size_t);
|
||||
#endif
|
||||
struct notifier_block;
|
||||
|
||||
#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
|
||||
extern int arch_cpu_uevent(struct device *dev, struct kobj_uevent_env *env);
|
||||
extern ssize_t arch_print_cpu_modalias(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *bufptr);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* CPU notifier priorities.
|
||||
*/
|
||||
|
60
include/linux/cpufeature.h
Normal file
60
include/linux/cpufeature.h
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_CPUFEATURE_H
|
||||
#define __LINUX_CPUFEATURE_H
|
||||
|
||||
#ifdef CONFIG_GENERIC_CPU_AUTOPROBE
|
||||
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <asm/cpufeature.h>
|
||||
|
||||
/*
|
||||
* Macros imported from <asm/cpufeature.h>:
|
||||
* - cpu_feature(x) ordinal value of feature called 'x'
|
||||
* - cpu_have_feature(u32 n) whether feature #n is available
|
||||
* - MAX_CPU_FEATURES upper bound for feature ordinal values
|
||||
* Optional:
|
||||
* - CPU_FEATURE_TYPEFMT format string fragment for printing the cpu type
|
||||
* - CPU_FEATURE_TYPEVAL set of values matching the format string above
|
||||
*/
|
||||
|
||||
#ifndef CPU_FEATURE_TYPEFMT
|
||||
#define CPU_FEATURE_TYPEFMT "%s"
|
||||
#endif
|
||||
|
||||
#ifndef CPU_FEATURE_TYPEVAL
|
||||
#define CPU_FEATURE_TYPEVAL ELF_PLATFORM
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Use module_cpu_feature_match(feature, module_init_function) to
|
||||
* declare that
|
||||
* a) the module shall be probed upon discovery of CPU feature 'feature'
|
||||
* (typically at boot time using udev)
|
||||
* b) the module must not be loaded if CPU feature 'feature' is not present
|
||||
* (not even by manual insmod).
|
||||
*
|
||||
* For a list of legal values for 'feature', please consult the file
|
||||
* 'asm/cpufeature.h' of your favorite architecture.
|
||||
*/
|
||||
#define module_cpu_feature_match(x, __init) \
|
||||
static struct cpu_feature const cpu_feature_match_ ## x[] = \
|
||||
{ { .feature = cpu_feature(x) }, { } }; \
|
||||
MODULE_DEVICE_TABLE(cpu, cpu_feature_match_ ## x); \
|
||||
\
|
||||
static int cpu_feature_match_ ## x ## _init(void) \
|
||||
{ \
|
||||
if (!cpu_have_feature(cpu_feature(x))) \
|
||||
return -ENODEV; \
|
||||
return __init(); \
|
||||
} \
|
||||
module_init(cpu_feature_match_ ## x ## _init)
|
||||
|
||||
#endif
|
||||
#endif
|
@ -560,6 +560,8 @@ extern int device_create_file(struct device *device,
|
||||
const struct device_attribute *entry);
|
||||
extern void device_remove_file(struct device *dev,
|
||||
const struct device_attribute *attr);
|
||||
extern bool device_remove_file_self(struct device *dev,
|
||||
const struct device_attribute *attr);
|
||||
extern int __must_check device_create_bin_file(struct device *dev,
|
||||
const struct bin_attribute *attr);
|
||||
extern void device_remove_bin_file(struct device *dev,
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include <linux/lockdep.h>
|
||||
#include <linux/rbtree.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/wait.h>
|
||||
|
||||
struct file;
|
||||
struct dentry;
|
||||
@ -35,16 +35,22 @@ enum kernfs_node_type {
|
||||
};
|
||||
|
||||
#define KERNFS_TYPE_MASK 0x000f
|
||||
#define KERNFS_ACTIVE_REF KERNFS_FILE
|
||||
#define KERNFS_FLAG_MASK ~KERNFS_TYPE_MASK
|
||||
|
||||
enum kernfs_node_flag {
|
||||
KERNFS_REMOVED = 0x0010,
|
||||
KERNFS_ACTIVATED = 0x0010,
|
||||
KERNFS_NS = 0x0020,
|
||||
KERNFS_HAS_SEQ_SHOW = 0x0040,
|
||||
KERNFS_HAS_MMAP = 0x0080,
|
||||
KERNFS_LOCKDEP = 0x0100,
|
||||
KERNFS_STATIC_NAME = 0x0200,
|
||||
KERNFS_SUICIDAL = 0x0400,
|
||||
KERNFS_SUICIDED = 0x0800,
|
||||
};
|
||||
|
||||
/* @flags for kernfs_create_root() */
|
||||
enum kernfs_root_flag {
|
||||
KERNFS_ROOT_CREATE_DEACTIVATED = 0x0001,
|
||||
};
|
||||
|
||||
/* type-specific structures for kernfs_node union members */
|
||||
@ -85,17 +91,17 @@ struct kernfs_node {
|
||||
#ifdef CONFIG_DEBUG_LOCK_ALLOC
|
||||
struct lockdep_map dep_map;
|
||||
#endif
|
||||
/* the following two fields are published */
|
||||
/*
|
||||
* Use kernfs_get_parent() and kernfs_name/path() instead of
|
||||
* accessing the following two fields directly. If the node is
|
||||
* never moved to a different parent, it is safe to access the
|
||||
* parent directly.
|
||||
*/
|
||||
struct kernfs_node *parent;
|
||||
const char *name;
|
||||
|
||||
struct rb_node rb;
|
||||
|
||||
union {
|
||||
struct completion *completion;
|
||||
struct kernfs_node *removed_list;
|
||||
} u;
|
||||
|
||||
const void *ns; /* namespace tag */
|
||||
unsigned int hash; /* ns + name hash */
|
||||
union {
|
||||
@ -113,12 +119,16 @@ struct kernfs_node {
|
||||
};
|
||||
|
||||
/*
|
||||
* kernfs_dir_ops may be specified on kernfs_create_root() to support
|
||||
* directory manipulation syscalls. These optional callbacks are invoked
|
||||
* on the matching syscalls and can perform any kernfs operations which
|
||||
* don't necessarily have to be the exact operation requested.
|
||||
* kernfs_syscall_ops may be specified on kernfs_create_root() to support
|
||||
* syscalls. These optional callbacks are invoked on the matching syscalls
|
||||
* and can perform any kernfs operations which don't necessarily have to be
|
||||
* the exact operation requested. An active reference is held for each
|
||||
* kernfs_node parameter.
|
||||
*/
|
||||
struct kernfs_dir_ops {
|
||||
struct kernfs_syscall_ops {
|
||||
int (*remount_fs)(struct kernfs_root *root, int *flags, char *data);
|
||||
int (*show_options)(struct seq_file *sf, struct kernfs_root *root);
|
||||
|
||||
int (*mkdir)(struct kernfs_node *parent, const char *name,
|
||||
umode_t mode);
|
||||
int (*rmdir)(struct kernfs_node *kn);
|
||||
@ -129,22 +139,26 @@ struct kernfs_dir_ops {
|
||||
struct kernfs_root {
|
||||
/* published fields */
|
||||
struct kernfs_node *kn;
|
||||
unsigned int flags; /* KERNFS_ROOT_* flags */
|
||||
|
||||
/* private fields, do not use outside kernfs proper */
|
||||
struct ida ino_ida;
|
||||
struct kernfs_dir_ops *dir_ops;
|
||||
struct kernfs_syscall_ops *syscall_ops;
|
||||
wait_queue_head_t deactivate_waitq;
|
||||
};
|
||||
|
||||
struct kernfs_open_file {
|
||||
/* published fields */
|
||||
struct kernfs_node *kn;
|
||||
struct file *file;
|
||||
void *priv;
|
||||
|
||||
/* private fields, do not use outside kernfs proper */
|
||||
struct mutex mutex;
|
||||
int event;
|
||||
struct list_head list;
|
||||
|
||||
size_t atomic_write_len;
|
||||
bool mmapped;
|
||||
const struct vm_operations_struct *vm_ops;
|
||||
};
|
||||
@ -171,9 +185,13 @@ struct kernfs_ops {
|
||||
loff_t off);
|
||||
|
||||
/*
|
||||
* write() is bounced through kernel buffer and a write larger than
|
||||
* PAGE_SIZE results in partial operation of PAGE_SIZE.
|
||||
* write() is bounced through kernel buffer. If atomic_write_len
|
||||
* is not set, a write larger than PAGE_SIZE results in partial
|
||||
* operations of PAGE_SIZE chunks. If atomic_write_len is set,
|
||||
* writes upto the specified size are executed atomically but
|
||||
* larger ones are rejected with -E2BIG.
|
||||
*/
|
||||
size_t atomic_write_len;
|
||||
ssize_t (*write)(struct kernfs_open_file *of, char *buf, size_t bytes,
|
||||
loff_t off);
|
||||
|
||||
@ -184,7 +202,7 @@ struct kernfs_ops {
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SYSFS
|
||||
#ifdef CONFIG_KERNFS
|
||||
|
||||
static inline enum kernfs_node_type kernfs_type(struct kernfs_node *kn)
|
||||
{
|
||||
@ -217,13 +235,22 @@ static inline bool kernfs_ns_enabled(struct kernfs_node *kn)
|
||||
return kn->flags & KERNFS_NS;
|
||||
}
|
||||
|
||||
int kernfs_name(struct kernfs_node *kn, char *buf, size_t buflen);
|
||||
char * __must_check kernfs_path(struct kernfs_node *kn, char *buf,
|
||||
size_t buflen);
|
||||
void pr_cont_kernfs_name(struct kernfs_node *kn);
|
||||
void pr_cont_kernfs_path(struct kernfs_node *kn);
|
||||
struct kernfs_node *kernfs_get_parent(struct kernfs_node *kn);
|
||||
struct kernfs_node *kernfs_find_and_get_ns(struct kernfs_node *parent,
|
||||
const char *name, const void *ns);
|
||||
void kernfs_get(struct kernfs_node *kn);
|
||||
void kernfs_put(struct kernfs_node *kn);
|
||||
|
||||
struct kernfs_root *kernfs_create_root(struct kernfs_dir_ops *kdops,
|
||||
void *priv);
|
||||
struct kernfs_node *kernfs_node_from_dentry(struct dentry *dentry);
|
||||
struct kernfs_root *kernfs_root_from_sb(struct super_block *sb);
|
||||
|
||||
struct kernfs_root *kernfs_create_root(struct kernfs_syscall_ops *scops,
|
||||
unsigned int flags, void *priv);
|
||||
void kernfs_destroy_root(struct kernfs_root *root);
|
||||
|
||||
struct kernfs_node *kernfs_create_dir_ns(struct kernfs_node *parent,
|
||||
@ -239,7 +266,11 @@ struct kernfs_node *__kernfs_create_file(struct kernfs_node *parent,
|
||||
struct kernfs_node *kernfs_create_link(struct kernfs_node *parent,
|
||||
const char *name,
|
||||
struct kernfs_node *target);
|
||||
void kernfs_activate(struct kernfs_node *kn);
|
||||
void kernfs_remove(struct kernfs_node *kn);
|
||||
void kernfs_break_active_protection(struct kernfs_node *kn);
|
||||
void kernfs_unbreak_active_protection(struct kernfs_node *kn);
|
||||
bool kernfs_remove_self(struct kernfs_node *kn);
|
||||
int kernfs_remove_by_name_ns(struct kernfs_node *parent, const char *name,
|
||||
const void *ns);
|
||||
int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent,
|
||||
@ -255,7 +286,7 @@ void kernfs_kill_sb(struct super_block *sb);
|
||||
|
||||
void kernfs_init(void);
|
||||
|
||||
#else /* CONFIG_SYSFS */
|
||||
#else /* CONFIG_KERNFS */
|
||||
|
||||
static inline enum kernfs_node_type kernfs_type(struct kernfs_node *kn)
|
||||
{ return 0; } /* whatever */
|
||||
@ -265,6 +296,19 @@ static inline void kernfs_enable_ns(struct kernfs_node *kn) { }
|
||||
static inline bool kernfs_ns_enabled(struct kernfs_node *kn)
|
||||
{ return false; }
|
||||
|
||||
static inline int kernfs_name(struct kernfs_node *kn, char *buf, size_t buflen)
|
||||
{ return -ENOSYS; }
|
||||
|
||||
static inline char * __must_check kernfs_path(struct kernfs_node *kn, char *buf,
|
||||
size_t buflen)
|
||||
{ return NULL; }
|
||||
|
||||
static inline void pr_cont_kernfs_name(struct kernfs_node *kn) { }
|
||||
static inline void pr_cont_kernfs_path(struct kernfs_node *kn) { }
|
||||
|
||||
static inline struct kernfs_node *kernfs_get_parent(struct kernfs_node *kn)
|
||||
{ return NULL; }
|
||||
|
||||
static inline struct kernfs_node *
|
||||
kernfs_find_and_get_ns(struct kernfs_node *parent, const char *name,
|
||||
const void *ns)
|
||||
@ -273,8 +317,15 @@ kernfs_find_and_get_ns(struct kernfs_node *parent, const char *name,
|
||||
static inline void kernfs_get(struct kernfs_node *kn) { }
|
||||
static inline void kernfs_put(struct kernfs_node *kn) { }
|
||||
|
||||
static inline struct kernfs_node *kernfs_node_from_dentry(struct dentry *dentry)
|
||||
{ return NULL; }
|
||||
|
||||
static inline struct kernfs_root *kernfs_root_from_sb(struct super_block *sb)
|
||||
{ return NULL; }
|
||||
|
||||
static inline struct kernfs_root *
|
||||
kernfs_create_root(struct kernfs_dir_ops *kdops, void *priv)
|
||||
kernfs_create_root(struct kernfs_syscall_ops *scops, unsigned int flags,
|
||||
void *priv)
|
||||
{ return ERR_PTR(-ENOSYS); }
|
||||
|
||||
static inline void kernfs_destroy_root(struct kernfs_root *root) { }
|
||||
@ -296,8 +347,13 @@ kernfs_create_link(struct kernfs_node *parent, const char *name,
|
||||
struct kernfs_node *target)
|
||||
{ return ERR_PTR(-ENOSYS); }
|
||||
|
||||
static inline void kernfs_activate(struct kernfs_node *kn) { }
|
||||
|
||||
static inline void kernfs_remove(struct kernfs_node *kn) { }
|
||||
|
||||
static inline bool kernfs_remove_self(struct kernfs_node *kn)
|
||||
{ return false; }
|
||||
|
||||
static inline int kernfs_remove_by_name_ns(struct kernfs_node *kn,
|
||||
const char *name, const void *ns)
|
||||
{ return -ENOSYS; }
|
||||
@ -325,7 +381,7 @@ static inline void kernfs_kill_sb(struct super_block *sb) { }
|
||||
|
||||
static inline void kernfs_init(void) { }
|
||||
|
||||
#endif /* CONFIG_SYSFS */
|
||||
#endif /* CONFIG_KERNFS */
|
||||
|
||||
static inline struct kernfs_node *
|
||||
kernfs_find_and_get(struct kernfs_node *kn, const char *name)
|
||||
@ -367,6 +423,13 @@ static inline int kernfs_remove_by_name(struct kernfs_node *parent,
|
||||
return kernfs_remove_by_name_ns(parent, name, NULL);
|
||||
}
|
||||
|
||||
static inline int kernfs_rename(struct kernfs_node *kn,
|
||||
struct kernfs_node *new_parent,
|
||||
const char *new_name)
|
||||
{
|
||||
return kernfs_rename_ns(kn, new_parent, new_name, NULL);
|
||||
}
|
||||
|
||||
static inline struct dentry *
|
||||
kernfs_mount(struct file_system_type *fs_type, int flags,
|
||||
struct kernfs_root *root, bool *new_sb_created)
|
||||
|
@ -572,6 +572,15 @@ struct x86_cpu_id {
|
||||
#define X86_MODEL_ANY 0
|
||||
#define X86_FEATURE_ANY 0 /* Same as FPU, you can't test for that */
|
||||
|
||||
/*
|
||||
* Generic table type for matching CPU features.
|
||||
* @feature: the bit number of the feature (0 - 65535)
|
||||
*/
|
||||
|
||||
struct cpu_feature {
|
||||
__u16 feature;
|
||||
};
|
||||
|
||||
#define IPACK_ANY_FORMAT 0xff
|
||||
#define IPACK_ANY_ID (~0)
|
||||
struct ipack_device_id {
|
||||
|
@ -198,6 +198,7 @@ int __must_check sysfs_chmod_file(struct kobject *kobj,
|
||||
const struct attribute *attr, umode_t mode);
|
||||
void sysfs_remove_file_ns(struct kobject *kobj, const struct attribute *attr,
|
||||
const void *ns);
|
||||
bool sysfs_remove_file_self(struct kobject *kobj, const struct attribute *attr);
|
||||
void sysfs_remove_files(struct kobject *kobj, const struct attribute **attr);
|
||||
|
||||
int __must_check sysfs_create_bin_file(struct kobject *kobj,
|
||||
@ -246,6 +247,11 @@ void sysfs_notify(struct kobject *kobj, const char *dir, const char *attr);
|
||||
|
||||
int __must_check sysfs_init(void);
|
||||
|
||||
static inline void sysfs_enable_ns(struct kernfs_node *kn)
|
||||
{
|
||||
return kernfs_enable_ns(kn);
|
||||
}
|
||||
|
||||
#else /* CONFIG_SYSFS */
|
||||
|
||||
static inline int sysfs_schedule_callback(struct kobject *kobj,
|
||||
@ -301,6 +307,12 @@ static inline void sysfs_remove_file_ns(struct kobject *kobj,
|
||||
{
|
||||
}
|
||||
|
||||
static inline bool sysfs_remove_file_self(struct kobject *kobj,
|
||||
const struct attribute *attr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void sysfs_remove_files(struct kobject *kobj,
|
||||
const struct attribute **attr)
|
||||
{
|
||||
@ -418,6 +430,10 @@ static inline int __must_check sysfs_init(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void sysfs_enable_ns(struct kernfs_node *kn)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SYSFS */
|
||||
|
||||
static inline int __must_check sysfs_create_file(struct kobject *kobj,
|
||||
|
@ -94,7 +94,7 @@ static int create_dir(struct kobject *kobj)
|
||||
BUG_ON(ops->type >= KOBJ_NS_TYPES);
|
||||
BUG_ON(!kobj_ns_type_registered(ops->type));
|
||||
|
||||
kernfs_enable_ns(kobj->sd);
|
||||
sysfs_enable_ns(kobj->sd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -174,6 +174,9 @@ int main(void)
|
||||
DEVID_FIELD(x86_cpu_id, model);
|
||||
DEVID_FIELD(x86_cpu_id, vendor);
|
||||
|
||||
DEVID(cpu_feature);
|
||||
DEVID_FIELD(cpu_feature, feature);
|
||||
|
||||
DEVID(mei_cl_device_id);
|
||||
DEVID_FIELD(mei_cl_device_id, name);
|
||||
|
||||
|
@ -1110,7 +1110,7 @@ static int do_amba_entry(const char *filename,
|
||||
}
|
||||
ADD_TO_DEVTABLE("amba", amba_id, do_amba_entry);
|
||||
|
||||
/* LOOKS like x86cpu:vendor:VVVV:family:FFFF:model:MMMM:feature:*,FEAT,*
|
||||
/* LOOKS like cpu:type:x86,venVVVVfamFFFFmodMMMM:feature:*,FEAT,*
|
||||
* All fields are numbers. It would be nicer to use strings for vendor
|
||||
* and feature, but getting those out of the build system here is too
|
||||
* complicated.
|
||||
@ -1124,10 +1124,10 @@ static int do_x86cpu_entry(const char *filename, void *symval,
|
||||
DEF_FIELD(symval, x86_cpu_id, model);
|
||||
DEF_FIELD(symval, x86_cpu_id, vendor);
|
||||
|
||||
strcpy(alias, "x86cpu:");
|
||||
ADD(alias, "vendor:", vendor != X86_VENDOR_ANY, vendor);
|
||||
ADD(alias, ":family:", family != X86_FAMILY_ANY, family);
|
||||
ADD(alias, ":model:", model != X86_MODEL_ANY, model);
|
||||
strcpy(alias, "cpu:type:x86,");
|
||||
ADD(alias, "ven", vendor != X86_VENDOR_ANY, vendor);
|
||||
ADD(alias, "fam", family != X86_FAMILY_ANY, family);
|
||||
ADD(alias, "mod", model != X86_MODEL_ANY, model);
|
||||
strcat(alias, ":feature:*");
|
||||
if (feature != X86_FEATURE_ANY)
|
||||
sprintf(alias + strlen(alias), "%04X*", feature);
|
||||
@ -1135,6 +1135,16 @@ static int do_x86cpu_entry(const char *filename, void *symval,
|
||||
}
|
||||
ADD_TO_DEVTABLE("x86cpu", x86_cpu_id, do_x86cpu_entry);
|
||||
|
||||
/* LOOKS like cpu:type:*:feature:*FEAT* */
|
||||
static int do_cpu_entry(const char *filename, void *symval, char *alias)
|
||||
{
|
||||
DEF_FIELD(symval, cpu_feature, feature);
|
||||
|
||||
sprintf(alias, "cpu:type:*:feature:*%04X*", feature);
|
||||
return 1;
|
||||
}
|
||||
ADD_TO_DEVTABLE("cpu", cpu_feature, do_cpu_entry);
|
||||
|
||||
/* Looks like: mei:S */
|
||||
static int do_mei_entry(const char *filename, void *symval,
|
||||
char *alias)
|
||||
|
Loading…
Reference in New Issue
Block a user