diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-05 19:20:22 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-05 19:20:22 -0400 |
commit | abf7dba7c4f77d781f6df50fefb19a64c5dc331f (patch) | |
tree | 38648731b502d5aec508f3b33f6616190e598eb6 /drivers/firmware/google/coreboot_table.c | |
parent | 07c4dd3435aa387d3b58f4e941dc516513f14507 (diff) | |
parent | b23220fe054e92f616b82450fae8cd3ab176cc60 (diff) |
Merge tag 'char-misc-4.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char/misc driver updates from Greg KH:
"Here is the "big" char and misc driver patches for 4.18-rc1.
It's not a lot of stuff here, but there are some highlights:
- coreboot driver updates
- soundwire driver updates
- android binder updates
- fpga big sync, mostly documentation
- lots of minor driver updates
All of these have been in linux-next for a while with no reported
issues"
* tag 'char-misc-4.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (81 commits)
vmw_balloon: fixing double free when batching mode is off
MAINTAINERS: Add driver-api/fpga path
fpga: clarify that unregister functions also free
documentation: fpga: move fpga-region.txt to driver-api
documentation: fpga: add bridge document to driver-api
documentation: fpga: move fpga-mgr.txt to driver-api
Documentation: fpga: move fpga overview to driver-api
fpga: region: kernel-doc fixes
fpga: bridge: kernel-doc fixes
fpga: mgr: kernel-doc fixes
fpga: use SPDX
fpga: region: change api, add fpga_region_create/free
fpga: bridge: change api, don't use drvdata
fpga: manager: change api, don't use drvdata
fpga: region: don't use drvdata in common fpga code
Drivers: hv: vmbus: Removed an unnecessary cast from void *
ver_linux: Drop redundant calls to system() to test if file is readable
ver_linux: Move stderr redirection from function parameter to function body
misc: IBM Virtual Management Channel Driver (VMC)
rpmsg: Correct support for MODULE_DEVICE_TABLE()
...
Diffstat (limited to 'drivers/firmware/google/coreboot_table.c')
-rw-r--r-- | drivers/firmware/google/coreboot_table.c | 130 |
1 files changed, 97 insertions, 33 deletions
diff --git a/drivers/firmware/google/coreboot_table.c b/drivers/firmware/google/coreboot_table.c index 0019d3ec18dd..19db5709ae28 100644 --- a/drivers/firmware/google/coreboot_table.c +++ b/drivers/firmware/google/coreboot_table.c | |||
@@ -4,6 +4,7 @@ | |||
4 | * Module providing coreboot table access. | 4 | * Module providing coreboot table access. |
5 | * | 5 | * |
6 | * Copyright 2017 Google Inc. | 6 | * Copyright 2017 Google Inc. |
7 | * Copyright 2017 Samuel Holland <samuel@sholland.org> | ||
7 | * | 8 | * |
8 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License v2.0 as published by | 10 | * it under the terms of the GNU General Public License v2.0 as published by |
@@ -15,37 +16,96 @@ | |||
15 | * GNU General Public License for more details. | 16 | * GNU General Public License for more details. |
16 | */ | 17 | */ |
17 | 18 | ||
19 | #include <linux/device.h> | ||
18 | #include <linux/err.h> | 20 | #include <linux/err.h> |
19 | #include <linux/init.h> | 21 | #include <linux/init.h> |
20 | #include <linux/io.h> | 22 | #include <linux/io.h> |
21 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
22 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/slab.h> | ||
23 | 26 | ||
24 | #include "coreboot_table.h" | 27 | #include "coreboot_table.h" |
25 | 28 | ||
26 | struct coreboot_table_entry { | 29 | #define CB_DEV(d) container_of(d, struct coreboot_device, dev) |
27 | u32 tag; | 30 | #define CB_DRV(d) container_of(d, struct coreboot_driver, drv) |
28 | u32 size; | ||
29 | }; | ||
30 | 31 | ||
31 | static struct coreboot_table_header __iomem *ptr_header; | 32 | static struct coreboot_table_header __iomem *ptr_header; |
32 | 33 | ||
33 | /* | 34 | static int coreboot_bus_match(struct device *dev, struct device_driver *drv) |
34 | * This function parses the coreboot table for an entry that contains the base | ||
35 | * address of the given entry tag. The coreboot table consists of a header | ||
36 | * directly followed by a number of small, variable-sized entries, which each | ||
37 | * contain an identifying tag and their length as the first two fields. | ||
38 | */ | ||
39 | int coreboot_table_find(int tag, void *data, size_t data_size) | ||
40 | { | 35 | { |
41 | struct coreboot_table_header header; | 36 | struct coreboot_device *device = CB_DEV(dev); |
42 | struct coreboot_table_entry entry; | 37 | struct coreboot_driver *driver = CB_DRV(drv); |
43 | void *ptr_entry; | ||
44 | int i; | ||
45 | 38 | ||
46 | if (!ptr_header) | 39 | return device->entry.tag == driver->tag; |
47 | return -EPROBE_DEFER; | 40 | } |
48 | 41 | ||
42 | static int coreboot_bus_probe(struct device *dev) | ||
43 | { | ||
44 | int ret = -ENODEV; | ||
45 | struct coreboot_device *device = CB_DEV(dev); | ||
46 | struct coreboot_driver *driver = CB_DRV(dev->driver); | ||
47 | |||
48 | if (driver->probe) | ||
49 | ret = driver->probe(device); | ||
50 | |||
51 | return ret; | ||
52 | } | ||
53 | |||
54 | static int coreboot_bus_remove(struct device *dev) | ||
55 | { | ||
56 | int ret = 0; | ||
57 | struct coreboot_device *device = CB_DEV(dev); | ||
58 | struct coreboot_driver *driver = CB_DRV(dev->driver); | ||
59 | |||
60 | if (driver->remove) | ||
61 | ret = driver->remove(device); | ||
62 | |||
63 | return ret; | ||
64 | } | ||
65 | |||
66 | static struct bus_type coreboot_bus_type = { | ||
67 | .name = "coreboot", | ||
68 | .match = coreboot_bus_match, | ||
69 | .probe = coreboot_bus_probe, | ||
70 | .remove = coreboot_bus_remove, | ||
71 | }; | ||
72 | |||
73 | static int __init coreboot_bus_init(void) | ||
74 | { | ||
75 | return bus_register(&coreboot_bus_type); | ||
76 | } | ||
77 | module_init(coreboot_bus_init); | ||
78 | |||
79 | static void coreboot_device_release(struct device *dev) | ||
80 | { | ||
81 | struct coreboot_device *device = CB_DEV(dev); | ||
82 | |||
83 | kfree(device); | ||
84 | } | ||
85 | |||
86 | int coreboot_driver_register(struct coreboot_driver *driver) | ||
87 | { | ||
88 | driver->drv.bus = &coreboot_bus_type; | ||
89 | |||
90 | return driver_register(&driver->drv); | ||
91 | } | ||
92 | EXPORT_SYMBOL(coreboot_driver_register); | ||
93 | |||
94 | void coreboot_driver_unregister(struct coreboot_driver *driver) | ||
95 | { | ||
96 | driver_unregister(&driver->drv); | ||
97 | } | ||
98 | EXPORT_SYMBOL(coreboot_driver_unregister); | ||
99 | |||
100 | int coreboot_table_init(struct device *dev, void __iomem *ptr) | ||
101 | { | ||
102 | int i, ret; | ||
103 | void *ptr_entry; | ||
104 | struct coreboot_device *device; | ||
105 | struct coreboot_table_entry entry; | ||
106 | struct coreboot_table_header header; | ||
107 | |||
108 | ptr_header = ptr; | ||
49 | memcpy_fromio(&header, ptr_header, sizeof(header)); | 109 | memcpy_fromio(&header, ptr_header, sizeof(header)); |
50 | 110 | ||
51 | if (strncmp(header.signature, "LBIO", sizeof(header.signature))) { | 111 | if (strncmp(header.signature, "LBIO", sizeof(header.signature))) { |
@@ -54,37 +114,41 @@ int coreboot_table_find(int tag, void *data, size_t data_size) | |||
54 | } | 114 | } |
55 | 115 | ||
56 | ptr_entry = (void *)ptr_header + header.header_bytes; | 116 | ptr_entry = (void *)ptr_header + header.header_bytes; |
57 | |||
58 | for (i = 0; i < header.table_entries; i++) { | 117 | for (i = 0; i < header.table_entries; i++) { |
59 | memcpy_fromio(&entry, ptr_entry, sizeof(entry)); | 118 | memcpy_fromio(&entry, ptr_entry, sizeof(entry)); |
60 | if (entry.tag == tag) { | ||
61 | if (data_size < entry.size) | ||
62 | return -EINVAL; | ||
63 | 119 | ||
64 | memcpy_fromio(data, ptr_entry, entry.size); | 120 | device = kzalloc(sizeof(struct device) + entry.size, GFP_KERNEL); |
121 | if (!device) { | ||
122 | ret = -ENOMEM; | ||
123 | break; | ||
124 | } | ||
125 | |||
126 | dev_set_name(&device->dev, "coreboot%d", i); | ||
127 | device->dev.parent = dev; | ||
128 | device->dev.bus = &coreboot_bus_type; | ||
129 | device->dev.release = coreboot_device_release; | ||
130 | memcpy_fromio(&device->entry, ptr_entry, entry.size); | ||
65 | 131 | ||
66 | return 0; | 132 | ret = device_register(&device->dev); |
133 | if (ret) { | ||
134 | put_device(&device->dev); | ||
135 | break; | ||
67 | } | 136 | } |
68 | 137 | ||
69 | ptr_entry += entry.size; | 138 | ptr_entry += entry.size; |
70 | } | 139 | } |
71 | 140 | ||
72 | return -ENOENT; | 141 | return ret; |
73 | } | ||
74 | EXPORT_SYMBOL(coreboot_table_find); | ||
75 | |||
76 | int coreboot_table_init(void __iomem *ptr) | ||
77 | { | ||
78 | ptr_header = ptr; | ||
79 | |||
80 | return 0; | ||
81 | } | 142 | } |
82 | EXPORT_SYMBOL(coreboot_table_init); | 143 | EXPORT_SYMBOL(coreboot_table_init); |
83 | 144 | ||
84 | int coreboot_table_exit(void) | 145 | int coreboot_table_exit(void) |
85 | { | 146 | { |
86 | if (ptr_header) | 147 | if (ptr_header) { |
148 | bus_unregister(&coreboot_bus_type); | ||
87 | iounmap(ptr_header); | 149 | iounmap(ptr_header); |
150 | ptr_header = NULL; | ||
151 | } | ||
88 | 152 | ||
89 | return 0; | 153 | return 0; |
90 | } | 154 | } |