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:
Linus Torvalds 2017-07-03 20:55:59 -07:00
commit f4dd029ee0
167 changed files with 12819 additions and 1630 deletions

View file

@ -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;
}

View file

@ -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);
}
/*

View file

@ -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);

View file

@ -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

View file

@ -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;