Commit 39ab05c8 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'driver-core-next' of...

Merge branch 'driver-core-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6

* 'driver-core-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6: (44 commits)
  debugfs: Silence DEBUG_STRICT_USER_COPY_CHECKS=y warning
  sysfs: remove "last sysfs file:" line from the oops messages
  drivers/base/memory.c: fix warning due to "memory hotplug: Speed up add/remove when blocks are larger than PAGES_PER_SECTION"
  memory hotplug: Speed up add/remove when blocks are larger than PAGES_PER_SECTION
  SYSFS: Fix erroneous comments for sysfs_update_group().
  driver core: remove the driver-model structures from the documentation
  driver core: Add the device driver-model structures to kerneldoc
  Translated Documentation/email-clients.txt
  RAW driver: Remove call to kobject_put().
  reboot: disable usermodehelper to prevent fs access
  efivars: prevent oops on unload when efi is not enabled
  Allow setting of number of raw devices as a module parameter
  Introduce CONFIG_GOOGLE_FIRMWARE
  driver: Google Memory Console
  driver: Google EFI SMI
  x86: Better comments for get_bios_ebda()
  x86: get_bios_ebda_length()
  misc: fix ti-st build issues
  params.c: Use new strtobool function to process boolean inputs
  debugfs: move to new strtobool
  ...

Fix up trivial conflicts in fs/debugfs/file.c due to the same patch
being applied twice, and an unrelated cleanup nearby.
parents 1477fcc2 c42d2237
......@@ -14,14 +14,15 @@ Description:
DMI is structured as a large table of entries, where
each entry has a common header indicating the type and
length of the entry, as well as 'handle' that is
supposed to be unique amongst all entries.
length of the entry, as well as a firmware-provided
'handle' that is supposed to be unique amongst all
entries.
Some entries are required by the specification, but many
others are optional. In general though, users should
never expect to find a specific entry type on their
system unless they know for certain what their firmware
is doing. Machine to machine will vary.
is doing. Machine to machine experiences will vary.
Multiple entries of the same type are allowed. In order
to handle these duplicate entry types, each entry is
......@@ -67,25 +68,24 @@ Description:
and the two terminating nul characters.
type : The type of the entry. This value is the same
as found in the directory name. It indicates
how the rest of the entry should be
interpreted.
how the rest of the entry should be interpreted.
instance: The instance ordinal of the entry for the
given type. This value is the same as found
in the parent directory name.
position: The position of the entry within the entirety
of the entirety.
position: The ordinal position (zero-based) of the entry
within the entirety of the DMI entry table.
=== Entry Specialization ===
Some entry types may have other information available in
sysfs.
sysfs. Not all types are specialized.
--- Type 15 - System Event Log ---
This entry allows the firmware to export a log of
events the system has taken. This information is
typically backed by nvram, but the implementation
details are abstracted by this table. This entries data
details are abstracted by this table. This entry's data
is exported in the directory:
/sys/firmware/dmi/entries/15-0/system_event_log
......
What: /sys/firmware/gsmi
Date: March 2011
Contact: Mike Waychison <mikew@google.com>
Description:
Some servers used internally at Google have firmware
that provides callback functionality via explicit SMI
triggers. Some of the callbacks are similar to those
provided by the EFI runtime services page, but due to
historical reasons this different entry-point has been
used.
The gsmi driver implements the kernel's abstraction for
these firmware callbacks. Currently, this functionality
is limited to handling the system event log and getting
access to EFI-style variables stored in nvram.
Layout:
/sys/firmware/gsmi/vars:
This directory has the same layout (and
underlying implementation as /sys/firmware/efi/vars.
See Documentation/ABI/*/sysfs-firmware-efi-vars
for more information on how to interact with
this structure.
/sys/firmware/gsmi/append_to_eventlog - write-only:
This file takes a binary blob and passes it onto
the firmware to be timestamped and appended to
the system eventlog. The binary format is
interpreted by the firmware and may change from
platform to platform. The only kernel-enforced
requirement is that the blob be prefixed with a
32bit host-endian type used as part of the
firmware call.
/sys/firmware/gsmi/clear_config - write-only:
Writing any value to this file will cause the
entire firmware configuration to be reset to
"factory defaults". Callers should assume that
a reboot is required for the configuration to be
cleared.
/sys/firmware/gsmi/clear_eventlog - write-only:
This file is used to clear out a portion/the
whole of the system event log. Values written
should be values between 1 and 100 inclusive (in
ASCII) representing the fraction of the log to
clear. Not all platforms support fractional
clearing though, and this writes to this file
will error out if the firmware doesn't like your
submitted fraction.
Callers should assume that a reboot is needed
for this operation to complete.
What: /sys/firmware/log
Date: February 2011
Contact: Mike Waychison <mikew@google.com>
Description:
The /sys/firmware/log is a binary file that represents a
read-only copy of the firmware's log if one is
available.
What: /sys/kernel/fscaps
Date: February 2011
KernelVersion: 2.6.38
Contact: Ludwig Nussel <ludwig.nussel@suse.de>
Description
Shows whether file system capabilities are honored
when executing a binary
......@@ -96,10 +96,10 @@ X!Iinclude/linux/kobject.h
<chapter id="devdrivers">
<title>Device drivers infrastructure</title>
<sect1><title>The Basic Device Driver-Model Structures </title>
!Iinclude/linux/device.h
</sect1>
<sect1><title>Device Drivers Base</title>
<!--
X!Iinclude/linux/device.h
-->
!Edrivers/base/driver.c
!Edrivers/base/core.c
!Edrivers/base/class.c
......
......@@ -3,24 +3,7 @@ Bus Types
Definition
~~~~~~~~~~
struct bus_type {
char * name;
struct subsystem subsys;
struct kset drivers;
struct kset devices;
struct bus_attribute * bus_attrs;
struct device_attribute * dev_attrs;
struct driver_attribute * drv_attrs;
int (*match)(struct device * dev, struct device_driver * drv);
int (*hotplug) (struct device *dev, char **envp,
int num_envp, char *buffer, int buffer_size);
int (*suspend)(struct device * dev, pm_message_t state);
int (*resume)(struct device * dev);
};
See the kerneldoc for the struct bus_type.
int bus_register(struct bus_type * bus);
......
......@@ -27,22 +27,7 @@ The device class structure looks like:
typedef int (*devclass_add)(struct device *);
typedef void (*devclass_remove)(struct device *);
struct device_class {
char * name;
rwlock_t lock;
u32 devnum;
struct list_head node;
struct list_head drivers;
struct list_head intf_list;
struct driver_dir_entry dir;
struct driver_dir_entry device_dir;
struct driver_dir_entry driver_dir;
devclass_add add_device;
devclass_remove remove_device;
};
See the kerneldoc for the struct class.
A typical device class definition would look like:
......
......@@ -2,96 +2,7 @@
The Basic Device Structure
~~~~~~~~~~~~~~~~~~~~~~~~~~
struct device {
struct list_head g_list;
struct list_head node;
struct list_head bus_list;
struct list_head driver_list;
struct list_head intf_list;
struct list_head children;
struct device * parent;
char name[DEVICE_NAME_SIZE];
char bus_id[BUS_ID_SIZE];
spinlock_t lock;
atomic_t refcount;
struct bus_type * bus;
struct driver_dir_entry dir;
u32 class_num;
struct device_driver *driver;
void *driver_data;
void *platform_data;
u32 current_state;
unsigned char *saved_state;
void (*release)(struct device * dev);
};
Fields
~~~~~~
g_list: Node in the global device list.
node: Node in device's parent's children list.
bus_list: Node in device's bus's devices list.
driver_list: Node in device's driver's devices list.
intf_list: List of intf_data. There is one structure allocated for
each interface that the device supports.
children: List of child devices.
parent: *** FIXME ***
name: ASCII description of device.
Example: " 3Com Corporation 3c905 100BaseTX [Boomerang]"
bus_id: ASCII representation of device's bus position. This
field should be a name unique across all devices on the
bus type the device belongs to.
Example: PCI bus_ids are in the form of
<bus number>:<slot number>.<function number>
This name is unique across all PCI devices in the system.
lock: Spinlock for the device.
refcount: Reference count on the device.
bus: Pointer to struct bus_type that device belongs to.
dir: Device's sysfs directory.
class_num: Class-enumerated value of the device.
driver: Pointer to struct device_driver that controls the device.
driver_data: Driver-specific data.
platform_data: Platform data specific to the device.
Example: for devices on custom boards, as typical of embedded
and SOC based hardware, Linux often uses platform_data to point
to board-specific structures describing devices and how they
are wired. That can include what ports are available, chip
variants, which GPIO pins act in what additional roles, and so
on. This shrinks the "Board Support Packages" (BSPs) and
minimizes board-specific #ifdefs in drivers.
current_state: Current power state of the device.
saved_state: Pointer to saved state of the device. This is usable by
the device driver controlling the device.
release: Callback to free the device after all references have
gone away. This should be set by the allocator of the
device (i.e. the bus driver that discovered the device).
See the kerneldoc for the struct device.
Programming Interface
......
Device Drivers
struct device_driver {
char * name;
struct bus_type * bus;
struct completion unloaded;
struct kobject kobj;
list_t devices;
struct module *owner;
int (*probe) (struct device * dev);
int (*remove) (struct device * dev);
int (*suspend) (struct device * dev, pm_message_t state);
int (*resume) (struct device * dev);
};
See the kerneldoc for the struct device_driver.
Allocation
......
This diff is collapsed.
This diff is collapsed.
......@@ -234,7 +234,6 @@ static int __die(const char *str, int err, struct thread_info *thread, struct pt
printk(KERN_EMERG "Internal error: %s: %x [#%d]" S_PREEMPT S_SMP "\n",
str, err, ++die_counter);
sysfs_printk_last_file();
/* trap and error numbers are mostly meaningless on ARM */
ret = notify_die(DIE_OOPS, str, regs, err, tsk->thread.trap_no, SIGSEGV);
......
......@@ -143,7 +143,6 @@ int die(const char *str, struct pt_regs *regs, long err)
#endif
printk("%s\n", ppc_md.name ? ppc_md.name : "");
sysfs_printk_last_file();
if (notify_die(DIE_OOPS, str, regs, err, 255,
SIGSEGV) == NOTIFY_STOP)
return 1;
......
......@@ -87,7 +87,6 @@ void die(const char * str, struct pt_regs * regs, long err)
bust_spinlocks(1);
printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
sysfs_printk_last_file();
print_modules();
show_regs(regs);
......
......@@ -192,7 +192,6 @@ static int __die(const char *str, int err, struct thread_info *thread,
printk(KERN_EMERG "Internal error: %s: %x [#%d]\n",
str, err, ++die_counter);
sysfs_printk_last_file();
/* trap and error numbers are mostly meaningless on UniCore */
ret = notify_die(DIE_OOPS, str, regs, err, tsk->thread.trap_no, \
......
......@@ -4,16 +4,40 @@
#include <asm/io.h>
/*
* there is a real-mode segmented pointer pointing to the
* 4K EBDA area at 0x40E.
* Returns physical address of EBDA. Returns 0 if there is no EBDA.
*/
static inline unsigned int get_bios_ebda(void)
{
/*
* There is a real-mode segmented pointer pointing to the
* 4K EBDA area at 0x40E.
*/
unsigned int address = *(unsigned short *)phys_to_virt(0x40E);
address <<= 4;
return address; /* 0 means none */
}
/*
* Return the sanitized length of the EBDA in bytes, if it exists.
*/
static inline unsigned int get_bios_ebda_length(void)
{
unsigned int address;
unsigned int length;
address = get_bios_ebda();
if (!address)
return 0;
/* EBDA length is byte 0 of the EBDA (stored in KiB) */
length = *(unsigned char *)phys_to_virt(address);
length <<= 10;
/* Trim the length if it extends beyond 640KiB */
length = min_t(unsigned int, (640 * 1024) - address, length);
return length;
}
void reserve_ebda_region(void);
#ifdef CONFIG_X86_CHECK_BIOS_CORRUPTION
......
......@@ -263,7 +263,6 @@ int __kprobes __die(const char *str, struct pt_regs *regs, long err)
printk("DEBUG_PAGEALLOC");
#endif
printk("\n");
sysfs_printk_last_file();
if (notify_die(DIE_OOPS, str, regs, err,
current->thread.trap_no, SIGSEGV) == NOTIFY_STOP)
return 1;
......
......@@ -400,7 +400,7 @@ static void device_remove_groups(struct device *dev,
static int device_add_attrs(struct device *dev)
{
struct class *class = dev->class;
struct device_type *type = dev->type;
const struct device_type *type = dev->type;
int error;
if (class) {
......@@ -440,7 +440,7 @@ static int device_add_attrs(struct device *dev)
static void device_remove_attrs(struct device *dev)
{
struct class *class = dev->class;
struct device_type *type = dev->type;
const struct device_type *type = dev->type;
device_remove_groups(dev, dev->groups);
......@@ -1314,8 +1314,7 @@ EXPORT_SYMBOL_GPL(put_device);
EXPORT_SYMBOL_GPL(device_create_file);
EXPORT_SYMBOL_GPL(device_remove_file);
struct root_device
{
struct root_device {
struct device dev;
struct module *owner;
};
......
......@@ -245,6 +245,10 @@ int device_attach(struct device *dev)
device_lock(dev);
if (dev->driver) {
if (klist_node_attached(&dev->p->knode_driver)) {
ret = 1;
goto out_unlock;
}
ret = device_bind_driver(dev);
if (ret == 0)
ret = 1;
......@@ -257,6 +261,7 @@ int device_attach(struct device *dev)
ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
pm_runtime_put_sync(dev);
}
out_unlock:
device_unlock(dev);
return ret;
}
......@@ -408,17 +413,16 @@ void *dev_get_drvdata(const struct device *dev)
}
EXPORT_SYMBOL(dev_get_drvdata);
void dev_set_drvdata(struct device *dev, void *data)
int dev_set_drvdata(struct device *dev, void *data)
{
int error;
if (!dev)
return;
if (!dev->p) {
error = device_private_init(dev);
if (error)
return;
return error;
}
dev->p->driver_data = data;
return 0;
}
EXPORT_SYMBOL(dev_set_drvdata);
......@@ -48,7 +48,8 @@ static const char *memory_uevent_name(struct kset *kset, struct kobject *kobj)
return MEMORY_CLASS_NAME;
}
static int memory_uevent(struct kset *kset, struct kobject *obj, struct kobj_uevent_env *env)
static int memory_uevent(struct kset *kset, struct kobject *obj,
struct kobj_uevent_env *env)
{
int retval = 0;
......@@ -228,10 +229,11 @@ int memory_isolate_notify(unsigned long val, void *v)
* OK to have direct references to sparsemem variables in here.
*/
static int
memory_section_action(unsigned long phys_index, unsigned long action)
memory_block_action(unsigned long phys_index, unsigned long action)
{
int i;
unsigned long start_pfn, start_paddr;
unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block;
struct page *first_page;
int ret;
......@@ -243,7 +245,7 @@ memory_section_action(unsigned long phys_index, unsigned long action)
* that way.
*/
if (action == MEM_ONLINE) {
for (i = 0; i < PAGES_PER_SECTION; i++) {
for (i = 0; i < nr_pages; i++) {
if (PageReserved(first_page+i))
continue;
......@@ -257,12 +259,12 @@ memory_section_action(unsigned long phys_index, unsigned long action)
switch (action) {
case MEM_ONLINE:
start_pfn = page_to_pfn(first_page);
ret = online_pages(start_pfn, PAGES_PER_SECTION);
ret = online_pages(start_pfn, nr_pages);
break;
case MEM_OFFLINE:
start_paddr = page_to_pfn(first_page) << PAGE_SHIFT;
ret = remove_memory(start_paddr,
PAGES_PER_SECTION << PAGE_SHIFT);
nr_pages << PAGE_SHIFT);
break;
default:
WARN(1, KERN_WARNING "%s(%ld, %ld) unknown action: "
......@@ -276,7 +278,7 @@ memory_section_action(unsigned long phys_index, unsigned long action)
static int memory_block_change_state(struct memory_block *mem,
unsigned long to_state, unsigned long from_state_req)
{
int i, ret = 0;
int ret = 0;
mutex_lock(&mem->state_mutex);
......@@ -288,20 +290,11 @@ static int memory_block_change_state(struct memory_block *mem,
if (to_state == MEM_OFFLINE)
mem->state = MEM_GOING_OFFLINE;
for (i = 0; i < sections_per_block; i++) {
ret = memory_section_action(mem->start_section_nr + i,
to_state);
if (ret)
break;
}
if (ret) {
for (i = 0; i < sections_per_block; i++)
memory_section_action(mem->start_section_nr + i,
from_state_req);
ret = memory_block_action(mem->start_section_nr, to_state);
if (ret)
mem->state = from_state_req;
} else
else
mem->state = to_state;
out:
......
......@@ -192,18 +192,18 @@ EXPORT_SYMBOL_GPL(platform_device_alloc);
int platform_device_add_resources(struct platform_device *pdev,
const struct resource *res, unsigned int num)
{
struct resource *r;
if (!res)
return 0;
struct resource *r = NULL;
if (res) {
r = kmemdup(res, sizeof(struct resource) * num, GFP_KERNEL);
if (r) {
if (!r)
return -ENOMEM;
}
kfree(pdev->resource);
pdev->resource = r;
pdev->num_resources = num;
return 0;
}
return -ENOMEM;
}
EXPORT_SYMBOL_GPL(platform_device_add_resources);
......@@ -220,17 +220,17 @@ EXPORT_SYMBOL_GPL(platform_device_add_resources);
int platform_device_add_data(struct platform_device *pdev, const void *data,
size_t size)
{
void *d;
if (!data)
return 0;
void *d = NULL;
if (data) {
d = kmemdup(data, size, GFP_KERNEL);
if (d) {
if (!d)
return -ENOMEM;
}
kfree(pdev->dev.platform_data);
pdev->dev.platform_data = d;
return 0;
}
return -ENOMEM;
}
EXPORT_SYMBOL_GPL(platform_device_add_data);
......
......@@ -523,7 +523,7 @@ config RAW_DRIVER
with the O_DIRECT flag.
config MAX_RAW_DEVS
int "Maximum number of RAW devices to support (1-8192)"
int "Maximum number of RAW devices to support (1-65536)"
depends on RAW_DRIVER
default "256"
help
......
......@@ -806,29 +806,41 @@ static const struct file_operations oldmem_fops = {
};
#endif
static ssize_t kmsg_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
static ssize_t kmsg_writev(struct kiocb *iocb, const struct iovec *iv,
unsigned long count, loff_t pos)
{
char *tmp;
ssize_t ret;
char *line, *p;
int i;
ssize_t ret = -EFAULT;
size_t len = iov_length(iv, count);
tmp = kmalloc(count + 1, GFP_KERNEL);
if (tmp == NULL)
line = kmalloc(len + 1, GFP_KERNEL);
if (line == NULL)
return -ENOMEM;
ret = -EFAULT;
if (!copy_from_user(tmp, buf, count)) {
tmp[count] = 0;
ret = printk("%s", tmp);
if (ret > count)
/* printk can add a prefix */
ret = count;
/*
* copy all vectors into a single string, to ensure we do
* not interleave our log line with other printk calls
*/
p = line;
for (i = 0; i < count; i++) {
if (copy_from_user(p, iv[i].iov_base, iv[i].iov_len))
goto out;
p += iv[i].iov_len;
}
kfree(tmp);
p[0] = '\0';
ret = printk("%s", line);
/* printk can add a prefix */
if (ret > len)
ret = len;
out:
kfree(line);
return ret;
}
static const struct file_operations kmsg_fops = {
.write = kmsg_write,
.aio_write = kmsg_writev,
.llseek = noop_llseek,
};
......
......@@ -21,6 +21,7 @@
#include <linux/mutex.h>
#include <linux/gfp.h>
#include <linux/compat.h>
#include <linux/vmalloc.h>
#include <asm/uaccess.h>
......@@ -30,10 +31,15 @@ struct raw_device_data {
};
static struct class *raw_class;
static struct raw_device_data raw_devices[MAX_RAW_MINORS];
static struct raw_device_data *raw_devices;
static DEFINE_MUTEX(raw_mutex);
static const struct file_operations raw_ctl_fops; /* forward declaration */
static int max_raw_minors = MAX_RAW_MINORS;
module_param(max_raw_minors, int, 0);
MODULE_PARM_DESC(max_raw_minors, "Maximum number of raw devices (1-65536)");
/*
* Open/close code for raw IO.
*
......@@ -125,7 +131,7 @@ static int bind_set(int number, u64 major, u64 minor)
struct raw_device_data *rawdev;
int err = 0;
if (number <= 0 || number >= MAX_RAW_MINORS)
if (number <= 0 || number >= max_raw_minors)
return -EINVAL;
if (MAJOR(dev) != major || MINOR(dev) != minor)
......@@ -312,14 +318,27 @@ static int __init raw_init(void)
dev_t dev = MKDEV(RAW_MAJOR, 0);
int ret;
ret = register_chrdev_region(dev, MAX_RAW_MINORS, "raw");
if (max_raw_minors < 1 || max_raw_minors > 65536) {
printk(KERN_WARNING "raw: invalid max_raw_minors (must be"
" between 1 and 65536), using %d\n", MAX_RAW_MINORS);
max_raw_minors = MAX_RAW_MINORS;
}
raw_devices = vmalloc(sizeof(struct raw_device_data) * max_raw_minors);
if (!raw_devices) {
printk(KERN_ERR "Not enough memory for raw device structures\n");
ret = -ENOMEM;
goto error;
}
memset(raw_devices, 0, sizeof(struct raw_device_data) * max_raw_minors);
ret = register_chrdev_region(dev, max_raw_minors, "raw");
if (ret)
goto error;
cdev_init(&raw_cdev, &raw_fops);
ret = cdev_add(&raw_cdev, dev, MAX_RAW_MINORS);
ret = cdev_add(&raw_cdev, dev, max_raw_minors);
if (ret) {
kobject_put(&raw_cdev.kobj);
goto error_region;
}
......@@ -336,8 +355,9 @@ static int __init raw_init(void)
return 0;
error_region:
unregister_chrdev_region(dev, MAX_RAW_MINORS);
unregister_chrdev_region(dev, max_raw_minors);
error:
vfree(raw_devices);
return ret;
}
......@@ -346,7 +366,7 @@ static void __exit raw_exit(void)
device_destroy(raw_class, MKDEV(RAW_MAJOR, 0));
class_destroy(raw_class);
cdev_del(&raw_cdev);
unregister_chrdev_region(MKDEV(RAW_MAJOR, 0), MAX_RAW_MINORS);
unregister_chrdev_region(MKDEV(RAW_MAJOR, 0), max_raw_minors);
}
module_init(raw_init);
......
......@@ -157,4 +157,6 @@ config SIGMA
If unsure, say N here. Drivers that need these helpers will select
this option automatically.
source "drivers/firmware/google/Kconfig"
endmenu
......@@ -13,3 +13,5 @@ obj-$(CONFIG_ISCSI_IBFT_FIND) += iscsi_ibft_find.o
obj-$(CONFIG_ISCSI_IBFT) += iscsi_ibft.o
obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o
obj-$(CONFIG_SIGMA) += sigma.o
obj-$(CONFIG_GOOGLE_FIRMWARE) += google/
......@@ -677,8 +677,8 @@ create_efivars_bin_attributes(struct efivars *efivars)
return 0;
out_free:
kfree(efivars->new_var);
efivars->new_var = NULL;
kfree(efivars->del_var);
efivars->del_var = NULL;
kfree(efivars->new_var);
efivars->new_var = NULL;
return error;
......@@ -803,6 +803,8 @@ efivars_init(void)
ops.set_variable = efi.set_variable;
ops.get_next_variable = efi.get_next_variable;
error = register_efivars(&__efivars, &ops, efi_kobj);
if (error)
goto err_put;
/* Don't forget the systab entry */
error = sysfs_create_group(efi_kobj, &efi_subsys_attr_group);
......@@ -810,18 +812,25 @@ efivars_init(void)
printk(KERN_ERR
"efivars: Sysfs attribute export failed with error %d.\n",
error);
unregister_efivars(&__efivars);
kobject_put(efi_kobj);
goto err_unregister;
}
return 0;
err_unregister:
unregister_efivars(&__efivars);
err_put:
kobject_put(efi_kobj);
return error;
}
static void __exit
efivars_exit(void)
{
if (efi_enabled) {
unregister_efivars(&__efivars);
kobject_put(efi_kobj);
}
}
module_init(efivars_init);
......
config GOOGLE_FIRMWARE
bool "Google Firmware Drivers"
depends on X86
default n
help
These firmware drivers are used by Google's servers. They are
only useful if you are working directly on one of their
proprietary servers. If in doubt, say "N".
menu "Google Firmware Drivers"
depends on GOOGLE_FIRMWARE
config GOOGLE_SMI
tristate "SMI interface for Google platforms"
depends on ACPI && DMI
select EFI_VARS
help
Say Y here if you want to enable SMI callbacks for Google
platforms. This provides an interface for writing to and
clearing the EFI event log and reading and writing NVRAM
variables.
config GOOGLE_MEMCONSOLE
tristate "Firmware Memory Console"
depends on DMI
help
This option enables the kernel to search for a firmware log in
the EBDA on Google servers. If found, this log is exported to
userland in the file /sys/firmware/log.
endmenu
obj-$(CONFIG_GOOGLE_SMI) += gsmi.o
obj-$(CONFIG_GOOGLE_MEMCONSOLE) += memconsole.o
This diff is collapsed.
/*
* memconsole.c
*
* Infrastructure for importing the BIOS memory based console
* into the kernel log ringbuffer.
*
* Copyright 2010 Google Inc. All rights reserved.
*/
#include <linux/ctype.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/sysfs.h>
#include <linux/kobject.h>
#include <linux/module.h>
#include <linux/dmi.h>
#include <asm/bios_ebda.h>
#define BIOS_MEMCONSOLE_V1_MAGIC 0xDEADBABE
#define BIOS_MEMCONSOLE_V2_MAGIC (('M')|('C'<<8)|('O'<<16)|('N'<<24))
struct biosmemcon_ebda {
u32 signature;
union {
struct {
u8 enabled;
u32 buffer_addr;
u16 start;
u16 end;
u16 num_chars;
u8 wrapped;
} __packed v1;
struct {
u32 buffer_addr;
/* Misdocumented as number of pages! */
u16 num_bytes;
u16 start;
u16 end;
} __packed v2;
};
} __packed;
static char *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);
}
static struct bin_attribute memconsole_bin_attr = {
.attr = {.name = "log", .mode = 0444},
.read = memconsole_read,
};
static void 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, "
"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);
}
static void 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, "
"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);
}
/*
* 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)
{
unsigned int address;
size_t length, cur;
address = get_bios_ebda();
if (!address) {
printk(KERN_INFO "BIOS EBDA non-existent.\n");
return false;
}
/* EBDA length is byte 0 of EBDA (in KB) */
length = *(u8 *)phys_to_virt(address);
length <<= 10; /* convert to bytes */
/*
* Search through EBDA for BIOS memory console structure
* note: signature is not necessarily dword-aligned
*/
for (cur = 0; cur < length; cur++) {
struct biosmemcon_ebda *hdr = phys_to_virt(address + cur);
/* memconsole v1 */
if (hdr->signature == BIOS_MEMCONSOLE_V1_MAGIC) {
found_v1_header(hdr);
return true;
}
/* memconsole v2 */
if (hdr->signature == BIOS_MEMCONSOLE_V2_MAGIC) {
found_v2_header(hdr);
return true;
}
}
printk(KERN_INFO "BIOS console EBDA structure not found!\n");
return false;
}
static struct dmi_system_id memconsole_dmi_table[] __initdata = {
{
.ident = "Google Board",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Google, Inc."),
},
},
{}
};
MODULE_DEVICE_TABLE(dmi, memconsole_dmi_table);
static int __init memconsole_init(void)
{
int ret;
if (!dmi_check_system(memconsole_dmi_table))
return -ENODEV;
if (!found_memconsole())
return -ENODEV;
memconsole_bin_attr.size = memconsole_length;
ret = sysfs_create_bin_file(firmware_kobj, &memconsole_bin_attr);
return ret;
}
static void __exit memconsole_exit(void)
{
sysfs_remove_bin_file(firmware_kobj, &memconsole_bin_attr);
}
module_init(memconsole_init);
module_exit(memconsole_exit);
MODULE_AUTHOR("Google, Inc.");
MODULE_LICENSE("GPL");
......@@ -5,7 +5,7 @@
menu "Texas Instruments shared transport line discipline"
config TI_ST
tristate "Shared transport core driver"
depends on RFKILL
depends on NET && GPIOLIB
select FW_LOADER
help
This enables the shared transport core driver for TI
......
......@@ -43,13 +43,15 @@ static void add_channel_to_table(struct st_data_s *st_gdata,
pr_info("%s: id %d\n", __func__, new_proto->chnl_id);
/* list now has the channel id as index itself */
st_gdata->list[new_proto->chnl_id] = new_proto;
st_gdata->is_registered[new_proto->chnl_id] = true;
}
static void remove_channel_from_table(struct st_data_s *st_gdata,
struct st_proto_s *proto)
{
pr_info("%s: id %d\n", __func__, proto->chnl_id);
st_gdata->list[proto->chnl_id] = NULL;
/* st_gdata->list[proto->chnl_id] = NULL; */
st_gdata->is_registered[proto->chnl_id] = false;
}
/*
......@@ -104,7 +106,7 @@ void st_send_frame(unsigned char chnl_id, struct st_data_s *st_gdata)
if (unlikely
(st_gdata == NULL || st_gdata->rx_skb == NULL
|| st_gdata->list[chnl_id] == NULL)) {
|| st_gdata->is_registered[chnl_id] == false)) {
pr_err("chnl_id %d not registered, no data to send?",
chnl_id);
kfree_skb(st_gdata->rx_skb);
......@@ -141,14 +143,15 @@ void st_reg_complete(struct st_data_s *st_gdata, char err)
unsigned char i = 0;
pr_info(" %s ", __func__);
for (i = 0; i < ST_MAX_CHANNELS; i++) {
if (likely(st_gdata != NULL && st_gdata->list[i] != NULL &&
if (likely(st_gdata != NULL &&
st_gdata->is_registered[i] == true &&
st_gdata->list[i]->reg_complete_cb != NULL)) {
st_gdata->list[i]->reg_complete_cb
(st_gdata->list[i]->priv_data, err);
pr_info("protocol %d's cb sent %d\n", i, err);
if (err) { /* cleanup registered protocol */
st_gdata->protos_registered--;
st_gdata->list[i] = NULL;
st_gdata->is_registered[i] = false;
}
}
}
......@@ -475,9 +478,9 @@ void kim_st_list_protocols(struct st_data_s *st_gdata, void *buf)
{
seq_printf(buf, "[%d]\nBT=%c\nFM=%c\nGPS=%c\n",
st_gdata->protos_registered,
st_gdata->list[0x04] != NULL ? 'R' : 'U',
st_gdata->list[0x08] != NULL ? 'R' : 'U',
st_gdata->list[0x09] != NULL ? 'R' : 'U');
st_gdata->is_registered[0x04] == true ? 'R' : 'U',
st_gdata->is_registered[0x08] == true ? 'R' : 'U',
st_gdata->is_registered[0x09] == true ? 'R' : 'U');
}
/********************************************************************/
......@@ -504,7 +507,7 @@ long st_register(struct st_proto_s *new_proto)
return -EPROTONOSUPPORT;
}
if (st_gdata->list[new_proto->chnl_id] != NULL) {
if (st_gdata->is_registered[new_proto->chnl_id] == true) {
pr_err("chnl_id %d already registered", new_proto->chnl_id);
return -EALREADY;
}
......@@ -563,7 +566,7 @@ long st_register(struct st_proto_s *new_proto)
/* check for already registered once more,
* since the above check is old
*/
if (st_gdata->list[new_proto->chnl_id] != NULL) {
if (st_gdata->is_registered[new_proto->chnl_id] == true) {
pr_err(" proto %d already registered ",
new_proto->chnl_id);
return -EALREADY;
......
......@@ -30,6 +30,7 @@
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/sched.h>
#include <linux/sysfs.h>
#include <linux/tty.h>
#include <linux/skbuff.h>
......
......@@ -381,7 +381,13 @@ static int uio_get_minor(struct uio_device *idev)
retval = -ENOMEM;
goto exit;
}
idev->minor = id & MAX_ID_MASK;
if (id < UIO_MAX_DEVICES) {
idev->minor = id;
} else {
dev_err(idev->dev, "too many uio devices\n");
retval = -EINVAL;
idr_remove(&uio_idr, id);
}
exit:
mutex_unlock(&minor_lock);
return retval;
......@@ -587,14 +593,12 @@ static ssize_t uio_write(struct file *filep, const char __user *buf,
static int uio_find_mem_index(struct vm_area_struct *vma)
{
int mi;
struct uio_device *idev = vma->vm_private_data;
for (mi = 0; mi < MAX_UIO_MAPS; mi++) {
if (idev->info->mem[mi].size == 0)
if (vma->vm_pgoff < MAX_UIO_MAPS) {
if (idev->info->mem[vma->vm_pgoff].size == 0)
return -1;
if (vma->vm_pgoff == mi)
return mi;
return (int)vma->vm_pgoff;
}
return -1;
}
......
......@@ -18,6 +18,9 @@
#define PCI_VENDOR_ID_HILSCHER 0x15CF
#define PCI_DEVICE_ID_HILSCHER_NETX 0x0000
#define PCI_DEVICE_ID_HILSCHER_NETPLC 0x0010
#define PCI_SUBDEVICE_ID_NETPLC_RAM 0x0000
#define PCI_SUBDEVICE_ID_NETPLC_FLASH 0x0001
#define PCI_SUBDEVICE_ID_NXSB_PCA 0x3235
#define PCI_SUBDEVICE_ID_NXPCA 0x3335
......@@ -66,6 +69,10 @@ static int __devinit netx_pci_probe(struct pci_dev *dev,
bar = 0;
info->name = "netx";
break;
case PCI_DEVICE_ID_HILSCHER_NETPLC:
bar = 0;
info->name = "netplc";
break;
default:
bar = 2;
info->name = "netx_plx";
......@@ -133,6 +140,18 @@ static struct pci_device_id netx_pci_ids[] = {
.subvendor = 0,
.subdevice = 0,
},
{
.vendor = PCI_VENDOR_ID_HILSCHER,
.device = PCI_DEVICE_ID_HILSCHER_NETPLC,
.subvendor = PCI_VENDOR_ID_HILSCHER,
.subdevice = PCI_SUBDEVICE_ID_NETPLC_RAM,
},
{
.vendor = PCI_VENDOR_ID_HILSCHER,
.device = PCI_DEVICE_ID_HILSCHER_NETPLC,
.subvendor = PCI_VENDOR_ID_HILSCHER,
.subdevice = PCI_SUBDEVICE_ID_NETPLC_FLASH,
},
{
.vendor = PCI_VENDOR_ID_PLX,
.device = PCI_DEVICE_ID_PLX_9030,
......
......@@ -189,6 +189,10 @@ static int uio_pdrv_genirq_remove(struct platform_device *pdev)
uio_unregister_device(priv->uioinfo);
pm_runtime_disable(&pdev->dev);
priv->uioinfo->handler = NULL;
priv->uioinfo->irqcontrol = NULL;
kfree(priv);
return 0;
}
......
......@@ -428,7 +428,7 @@ static ssize_t write_file_bool(struct file *file, const char __user *user_buf,
size_t count, loff_t *ppos)
{
char buf[32];
int buf_size;
size_t buf_size;
bool bv;
u32 *val = file->private_data;
......
......@@ -24,13 +24,6 @@
#include "sysfs.h"
/* used in crash dumps to help with debugging */
static char last_sysfs_file[PATH_MAX];
void sysfs_printk_last_file(void)
{
printk(KERN_EMERG "last sysfs file: %s\n", last_sysfs_file);
}
/*
* There's one sysfs_buffer for each open file and one
* sysfs_open_dirent for each sysfs_dirent with one or more open
......@@ -337,11 +330,6 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
struct sysfs_buffer *buffer;
const struct sysfs_ops *ops;
int error = -EACCES;
char *p;
p = d_path(&file->f_path, last_sysfs_file, sizeof(last_sysfs_file));
if (!IS_ERR(p))
memmove(last_sysfs_file, p, strlen(p) + 1);
/* need attr_sd for attr and ops, its parent for kobj */
if (!sysfs_get_active(attr_sd))
......
......@@ -101,9 +101,9 @@ int sysfs_create_group(struct kobject *kobj,
}
/**
* sysfs_update_group - given a directory kobject, create an attribute group
* @kobj: The kobject to create the group on
* @grp: The attribute group to create
* sysfs_update_group - given a directory kobject, update an attribute group
* @kobj: The kobject to update the group on
* @grp: The attribute group to update
*
* This function updates an attribute group. Unlike
* sysfs_create_group(), it will explicitly not warn or error if any
......
This diff is collapsed.
......@@ -176,7 +176,6 @@ struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
const unsigned char *name);
struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd);
void sysfs_put(struct sysfs_dirent *sd);
void sysfs_printk_last_file(void);
/* Called to clear a ns tag when it is no longer valid */
void sysfs_exit_ns(enum kobj_ns_type type, const void *tag);
......@@ -348,10 +347,6 @@ static inline int __must_check sysfs_init(void)
return 0;
}
static inline void sysfs_printk_last_file(void)
{
}
#endif /* CONFIG_SYSFS */
#endif /* _SYSFS_H_ */
......@@ -140,12 +140,12 @@ extern long st_unregister(struct st_proto_s *);
*/
struct st_data_s {
unsigned long st_state;
struct tty_struct *tty;
struct sk_buff *tx_skb;
#define ST_TX_SENDING 1
#define ST_TX_WAKEUP 2
unsigned long tx_state;
struct st_proto_s *list[ST_MAX_CHANNELS];
bool is_registered[ST_MAX_CHANNELS];
unsigned long rx_state;
unsigned long rx_count;
struct sk_buff *rx_skb;
......@@ -155,6 +155,7 @@ struct st_data_s {
unsigned char protos_registered;
unsigned long ll_state;
void *kim_data;
struct tty_struct *tty;
};
/*
......
......@@ -16,6 +16,7 @@
#include <linux/kexec.h>
#include <linux/profile.h>
#include <linux/sched.h>
#include <linux/capability.h>
#define KERNEL_ATTR_RO(_name) \
static struct kobj_attribute _name##_attr = __ATTR_RO(_name)
......@@ -131,6 +132,14 @@ KERNEL_ATTR_RO(vmcoreinfo);
#endif /* CONFIG_KEXEC */
/* whether file capabilities are enabled */
static ssize_t fscaps_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
return sprintf(buf, "%d\n", file_caps_enabled);
}
KERNEL_ATTR_RO(fscaps);
/*
* Make /sys/kernel/notes give the raw contents of our kernel .notes section.
*/
......@@ -158,6 +167,7 @@ struct kobject *kernel_kobj;
EXPORT_SYMBOL_GPL(kernel_kobj);
static struct attribute * kernel_attrs[] = {
&fscaps_attr.attr,
#if defined(CONFIG_HOTPLUG)
&uevent_seqnum_attr.attr,
&uevent_helper_attr.attr,
......
......@@ -314,6 +314,7 @@ void kernel_restart_prepare(char *cmd)
{
blocking_notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd);
system_state = SYSTEM_RESTART;
usermodehelper_disable();
device_shutdown();
syscore_shutdown();
}
......@@ -343,6 +344,7 @@ static void kernel_shutdown_prepare(enum system_states state)
blocking_notifier_call_chain(&reboot_notifier_list,
(state == SYSTEM_HALT)?SYS_HALT:SYS_POWER_OFF, NULL);
system_state = state;
usermodehelper_disable();
device_shutdown();
}
/**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment