mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 03:01:39 -04:00
Char/Misc patches for 4.13-rc1
Here is the "big" char/misc driver patchset for 4.13-rc1. Lots of stuff in here, a large thunderbolt update, w1 driver header reorg, the new mux driver subsystem, google firmware driver updates, and a raft of other smaller things. Full details in the shortlog. All of these have been in linux-next for a while with the only reported issue being a merge problem with this tree and the jc-docs tree in the w1 documentation area. The fix should be obvious for what to do when it happens, if not, we can send a follow-up patch for it afterward. Signed-off-by: Greg Kroah-Hartman <[email protected]> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCWVpXKA8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ynLrQCdG9SxRjAbOd6pT9Fr2NAzpUG84YsAoLw+I3iO EMi60UXWqAFJbtVMS9Aj =yrSq -----END PGP SIGNATURE----- Merge tag 'char-misc-4.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc Pull char/misc updates from Greg KH: "Here is the "big" char/misc driver patchset for 4.13-rc1. Lots of stuff in here, a large thunderbolt update, w1 driver header reorg, the new mux driver subsystem, google firmware driver updates, and a raft of other smaller things. Full details in the shortlog. All of these have been in linux-next for a while with the only reported issue being a merge problem with this tree and the jc-docs tree in the w1 documentation area" * tag 'char-misc-4.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (147 commits) misc: apds990x: Use sysfs_match_string() helper mei: drop unreachable code in mei_start mei: validate the message header only in first fragment. DocBook: w1: Update W1 file locations and names in DocBook mux: adg792a: always require I2C support nvmem: rockchip-efuse: add support for rk322x-efuse nvmem: core: add locking to nvmem_find_cell nvmem: core: Call put_device() in nvmem_unregister() nvmem: core: fix leaks on registration errors nvmem: correct Broadcom OTP controller driver writes w1: Add subsystem kernel public interface drivers/fsi: Add module license to core driver drivers/fsi: Use asynchronous slave mode drivers/fsi: Add hub master support drivers/fsi: Add SCOM FSI client device driver drivers/fsi/gpio: Add tracepoints for GPIO master drivers/fsi: Add GPIO based FSI master drivers/fsi: Document FSI master sysfs files in ABI drivers/fsi: Add error handling for slave drivers/fsi: Add tracepoints for low-level operations ...
This commit is contained in:
commit
f4dd029ee0
167 changed files with 12819 additions and 1630 deletions
|
|
@ -26,12 +26,52 @@
|
|||
|
||||
/* CBMEM firmware console log descriptor. */
|
||||
struct cbmem_cons {
|
||||
u32 buffer_size;
|
||||
u32 buffer_cursor;
|
||||
u8 buffer_body[0];
|
||||
u32 size_dont_access_after_boot;
|
||||
u32 cursor;
|
||||
u8 body[0];
|
||||
} __packed;
|
||||
|
||||
#define CURSOR_MASK ((1 << 28) - 1)
|
||||
#define OVERFLOW (1 << 31)
|
||||
|
||||
static struct cbmem_cons __iomem *cbmem_console;
|
||||
static u32 cbmem_console_size;
|
||||
|
||||
/*
|
||||
* The cbmem_console structure is read again on every access because it may
|
||||
* change at any time if runtime firmware logs new messages. This may rarely
|
||||
* lead to race conditions where the firmware overwrites the beginning of the
|
||||
* ring buffer with more lines after we have already read |cursor|. It should be
|
||||
* rare and harmless enough that we don't spend extra effort working around it.
|
||||
*/
|
||||
static ssize_t memconsole_coreboot_read(char *buf, loff_t pos, size_t count)
|
||||
{
|
||||
u32 cursor = cbmem_console->cursor & CURSOR_MASK;
|
||||
u32 flags = cbmem_console->cursor & ~CURSOR_MASK;
|
||||
u32 size = cbmem_console_size;
|
||||
struct seg { /* describes ring buffer segments in logical order */
|
||||
u32 phys; /* physical offset from start of mem buffer */
|
||||
u32 len; /* length of segment */
|
||||
} seg[2] = { {0}, {0} };
|
||||
size_t done = 0;
|
||||
int i;
|
||||
|
||||
if (flags & OVERFLOW) {
|
||||
if (cursor > size) /* Shouldn't really happen, but... */
|
||||
cursor = 0;
|
||||
seg[0] = (struct seg){.phys = cursor, .len = size - cursor};
|
||||
seg[1] = (struct seg){.phys = 0, .len = cursor};
|
||||
} else {
|
||||
seg[0] = (struct seg){.phys = 0, .len = min(cursor, size)};
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(seg) && count > done; i++) {
|
||||
done += memory_read_from_buffer(buf + done, count - done, &pos,
|
||||
cbmem_console->body + seg[i].phys, seg[i].len);
|
||||
pos -= seg[i].len;
|
||||
}
|
||||
return done;
|
||||
}
|
||||
|
||||
static int memconsole_coreboot_init(phys_addr_t physaddr)
|
||||
{
|
||||
|
|
@ -42,17 +82,17 @@ static int memconsole_coreboot_init(phys_addr_t physaddr)
|
|||
if (!tmp_cbmc)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Read size only once to prevent overrun attack through /dev/mem. */
|
||||
cbmem_console_size = tmp_cbmc->size_dont_access_after_boot;
|
||||
cbmem_console = memremap(physaddr,
|
||||
tmp_cbmc->buffer_size + sizeof(*cbmem_console),
|
||||
cbmem_console_size + sizeof(*cbmem_console),
|
||||
MEMREMAP_WB);
|
||||
memunmap(tmp_cbmc);
|
||||
|
||||
if (!cbmem_console)
|
||||
return -ENOMEM;
|
||||
|
||||
memconsole_setup(cbmem_console->buffer_body,
|
||||
min(cbmem_console->buffer_cursor, cbmem_console->buffer_size));
|
||||
|
||||
memconsole_setup(memconsole_coreboot_read);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -48,6 +48,15 @@ struct biosmemcon_ebda {
|
|||
};
|
||||
} __packed;
|
||||
|
||||
static char *memconsole_baseaddr;
|
||||
static size_t memconsole_length;
|
||||
|
||||
static ssize_t memconsole_read(char *buf, loff_t pos, size_t count)
|
||||
{
|
||||
return memory_read_from_buffer(buf, count, &pos, memconsole_baseaddr,
|
||||
memconsole_length);
|
||||
}
|
||||
|
||||
static void found_v1_header(struct biosmemcon_ebda *hdr)
|
||||
{
|
||||
pr_info("memconsole: BIOS console v1 EBDA structure found at %p\n",
|
||||
|
|
@ -56,7 +65,9 @@ static void found_v1_header(struct biosmemcon_ebda *hdr)
|
|||
hdr->v1.buffer_addr, hdr->v1.start,
|
||||
hdr->v1.end, hdr->v1.num_chars);
|
||||
|
||||
memconsole_setup(phys_to_virt(hdr->v1.buffer_addr), hdr->v1.num_chars);
|
||||
memconsole_baseaddr = phys_to_virt(hdr->v1.buffer_addr);
|
||||
memconsole_length = hdr->v1.num_chars;
|
||||
memconsole_setup(memconsole_read);
|
||||
}
|
||||
|
||||
static void found_v2_header(struct biosmemcon_ebda *hdr)
|
||||
|
|
@ -67,8 +78,9 @@ static void found_v2_header(struct biosmemcon_ebda *hdr)
|
|||
hdr->v2.buffer_addr, hdr->v2.start,
|
||||
hdr->v2.end, hdr->v2.num_bytes);
|
||||
|
||||
memconsole_setup(phys_to_virt(hdr->v2.buffer_addr + hdr->v2.start),
|
||||
hdr->v2.end - hdr->v2.start);
|
||||
memconsole_baseaddr = phys_to_virt(hdr->v2.buffer_addr + hdr->v2.start);
|
||||
memconsole_length = hdr->v2.end - hdr->v2.start;
|
||||
memconsole_setup(memconsole_read);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -22,15 +22,15 @@
|
|||
|
||||
#include "memconsole.h"
|
||||
|
||||
static char *memconsole_baseaddr;
|
||||
static size_t memconsole_length;
|
||||
static ssize_t (*memconsole_read_func)(char *, loff_t, size_t);
|
||||
|
||||
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);
|
||||
if (WARN_ON_ONCE(!memconsole_read_func))
|
||||
return -EIO;
|
||||
return memconsole_read_func(buf, pos, count);
|
||||
}
|
||||
|
||||
static struct bin_attribute memconsole_bin_attr = {
|
||||
|
|
@ -38,16 +38,14 @@ static struct bin_attribute memconsole_bin_attr = {
|
|||
.read = memconsole_read,
|
||||
};
|
||||
|
||||
void memconsole_setup(void *baseaddr, size_t length)
|
||||
void memconsole_setup(ssize_t (*read_func)(char *, loff_t, size_t))
|
||||
{
|
||||
memconsole_baseaddr = baseaddr;
|
||||
memconsole_length = length;
|
||||
memconsole_read_func = read_func;
|
||||
}
|
||||
EXPORT_SYMBOL(memconsole_setup);
|
||||
|
||||
int memconsole_sysfs_init(void)
|
||||
{
|
||||
memconsole_bin_attr.size = memconsole_length;
|
||||
return sysfs_create_bin_file(firmware_kobj, &memconsole_bin_attr);
|
||||
}
|
||||
EXPORT_SYMBOL(memconsole_sysfs_init);
|
||||
|
|
|
|||
|
|
@ -18,13 +18,14 @@
|
|||
#ifndef __FIRMWARE_GOOGLE_MEMCONSOLE_H
|
||||
#define __FIRMWARE_GOOGLE_MEMCONSOLE_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/*
|
||||
* memconsole_setup
|
||||
*
|
||||
* Initialize the memory console from raw (virtual) base
|
||||
* address and length.
|
||||
* Initialize the memory console, passing the function to handle read accesses.
|
||||
*/
|
||||
void memconsole_setup(void *baseaddr, size_t length);
|
||||
void memconsole_setup(ssize_t (*read_func)(char *, loff_t, size_t));
|
||||
|
||||
/*
|
||||
* memconsole_sysfs_init
|
||||
|
|
|
|||
|
|
@ -118,14 +118,13 @@ static int vpd_section_attrib_add(const u8 *key, s32 key_len,
|
|||
info = kzalloc(sizeof(*info), GFP_KERNEL);
|
||||
if (!info)
|
||||
return -ENOMEM;
|
||||
info->key = kzalloc(key_len + 1, GFP_KERNEL);
|
||||
|
||||
info->key = kstrndup(key, key_len, GFP_KERNEL);
|
||||
if (!info->key) {
|
||||
ret = -ENOMEM;
|
||||
goto free_info;
|
||||
}
|
||||
|
||||
memcpy(info->key, key, key_len);
|
||||
|
||||
sysfs_bin_attr_init(&info->bin_attr);
|
||||
info->bin_attr.attr.name = info->key;
|
||||
info->bin_attr.attr.mode = 0444;
|
||||
|
|
@ -191,8 +190,7 @@ static int vpd_section_create_attribs(struct vpd_section *sec)
|
|||
static int vpd_section_init(const char *name, struct vpd_section *sec,
|
||||
phys_addr_t physaddr, size_t size)
|
||||
{
|
||||
int ret;
|
||||
int raw_len;
|
||||
int err;
|
||||
|
||||
sec->baseaddr = memremap(physaddr, size, MEMREMAP_WB);
|
||||
if (!sec->baseaddr)
|
||||
|
|
@ -201,10 +199,11 @@ static int vpd_section_init(const char *name, struct vpd_section *sec,
|
|||
sec->name = name;
|
||||
|
||||
/* We want to export the raw partion with name ${name}_raw */
|
||||
raw_len = strlen(name) + 5;
|
||||
sec->raw_name = kzalloc(raw_len, GFP_KERNEL);
|
||||
strncpy(sec->raw_name, name, raw_len);
|
||||
strncat(sec->raw_name, "_raw", raw_len);
|
||||
sec->raw_name = kasprintf(GFP_KERNEL, "%s_raw", name);
|
||||
if (!sec->raw_name) {
|
||||
err = -ENOMEM;
|
||||
goto err_iounmap;
|
||||
}
|
||||
|
||||
sysfs_bin_attr_init(&sec->bin_attr);
|
||||
sec->bin_attr.attr.name = sec->raw_name;
|
||||
|
|
@ -213,14 +212,14 @@ static int vpd_section_init(const char *name, struct vpd_section *sec,
|
|||
sec->bin_attr.read = vpd_section_read;
|
||||
sec->bin_attr.private = sec;
|
||||
|
||||
ret = sysfs_create_bin_file(vpd_kobj, &sec->bin_attr);
|
||||
if (ret)
|
||||
goto free_sec;
|
||||
err = sysfs_create_bin_file(vpd_kobj, &sec->bin_attr);
|
||||
if (err)
|
||||
goto err_free_raw_name;
|
||||
|
||||
sec->kobj = kobject_create_and_add(name, vpd_kobj);
|
||||
if (!sec->kobj) {
|
||||
ret = -EINVAL;
|
||||
goto sysfs_remove;
|
||||
err = -EINVAL;
|
||||
goto err_sysfs_remove;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&sec->attribs);
|
||||
|
|
@ -230,14 +229,13 @@ static int vpd_section_init(const char *name, struct vpd_section *sec,
|
|||
|
||||
return 0;
|
||||
|
||||
sysfs_remove:
|
||||
err_sysfs_remove:
|
||||
sysfs_remove_bin_file(vpd_kobj, &sec->bin_attr);
|
||||
|
||||
free_sec:
|
||||
err_free_raw_name:
|
||||
kfree(sec->raw_name);
|
||||
err_iounmap:
|
||||
iounmap(sec->baseaddr);
|
||||
|
||||
return ret;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int vpd_section_destroy(struct vpd_section *sec)
|
||||
|
|
@ -319,9 +317,6 @@ static int __init vpd_platform_init(void)
|
|||
if (!vpd_kobj)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(&ro_vpd, 0, sizeof(ro_vpd));
|
||||
memset(&rw_vpd, 0, sizeof(rw_vpd));
|
||||
|
||||
platform_driver_register(&vpd_driver);
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
Loading…
Reference in a new issue