diff options
33 files changed, 1160 insertions, 519 deletions
@@ -768,6 +768,7 @@ D: Z85230 driver | |||
768 | D: Former security contact point (please use vendor-sec@lst.de) | 768 | D: Former security contact point (please use vendor-sec@lst.de) |
769 | D: ex 2.2 maintainer | 769 | D: ex 2.2 maintainer |
770 | D: 2.1.x modular sound | 770 | D: 2.1.x modular sound |
771 | D: Assigned major/minor numbers maintainer at lanana.org | ||
771 | S: c/o Red Hat UK Ltd | 772 | S: c/o Red Hat UK Ltd |
772 | S: Alexandra House | 773 | S: Alexandra House |
773 | S: Alexandra Terrace | 774 | S: Alexandra Terrace |
diff --git a/Documentation/devices.txt b/Documentation/devices.txt index 87b4c5e82d39..4035eca87144 100644 --- a/Documentation/devices.txt +++ b/Documentation/devices.txt | |||
@@ -1,20 +1,17 @@ | |||
1 | 1 | ||
2 | LINUX ALLOCATED DEVICES (2.6+ version) | 2 | LINUX ALLOCATED DEVICES (4.x+ version) |
3 | |||
4 | Maintained by Alan Cox <device@lanana.org> | ||
5 | |||
6 | Last revised: 6th April 2009 | ||
7 | 3 | ||
8 | This list is the Linux Device List, the official registry of allocated | 4 | This list is the Linux Device List, the official registry of allocated |
9 | device numbers and /dev directory nodes for the Linux operating | 5 | device numbers and /dev directory nodes for the Linux operating |
10 | system. | 6 | system. |
11 | 7 | ||
12 | The latest version of this list is available from | 8 | The LaTeX version of this document is no longer maintained, nor is |
13 | http://www.lanana.org/docs/device-list/ or | 9 | the document that used to reside at lanana.org. This version in the |
14 | ftp://ftp.kernel.org/pub/linux/docs/device-list/. This version may be | 10 | mainline Linux kernel is the master document. Updates shall be sent |
15 | newer than the one distributed with the Linux kernel. | 11 | as patches to the kernel maintainers (see the SubmittingPatches document). |
16 | 12 | Specifically explore the sections titled "CHAR and MISC DRIVERS", and | |
17 | The LaTeX version of this document is no longer maintained. | 13 | "BLOCK LAYER" in the MAINTAINERS file to find the right maintainers |
14 | to involve for character and block devices. | ||
18 | 15 | ||
19 | This document is included by reference into the Filesystem Hierarchy | 16 | This document is included by reference into the Filesystem Hierarchy |
20 | Standard (FHS). The FHS is available from http://www.pathname.com/fhs/. | 17 | Standard (FHS). The FHS is available from http://www.pathname.com/fhs/. |
@@ -23,60 +20,33 @@ Allocations marked (68k/Amiga) apply to Linux/68k on the Amiga | |||
23 | platform only. Allocations marked (68k/Atari) apply to Linux/68k on | 20 | platform only. Allocations marked (68k/Atari) apply to Linux/68k on |
24 | the Atari platform only. | 21 | the Atari platform only. |
25 | 22 | ||
26 | The symbol {2.6} means the allocation is obsolete and scheduled for | 23 | This document is in the public domain. The authors requests, however, |
27 | removal once kernel version 2.6 (or equivalent) is released. Some of these | ||
28 | allocations have already been removed. | ||
29 | |||
30 | This document is in the public domain. The author requests, however, | ||
31 | that semantically altered versions are not distributed without | 24 | that semantically altered versions are not distributed without |
32 | permission of the author, assuming the author can be contacted without | 25 | permission of the authors, assuming the authors can be contacted without |
33 | an unreasonable effort. | 26 | an unreasonable effort. |
34 | 27 | ||
35 | In particular, please don't sent patches for this list to Linus, at | ||
36 | least not without contacting me first. | ||
37 | |||
38 | I do not have any information about these devices beyond what appears | ||
39 | on this list. Any such information requests will be deleted without | ||
40 | reply. | ||
41 | |||
42 | 28 | ||
43 | **** DEVICE DRIVERS AUTHORS PLEASE READ THIS **** | 29 | **** DEVICE DRIVERS AUTHORS PLEASE READ THIS **** |
44 | 30 | ||
45 | To have a major number allocated, or a minor number in situations | 31 | Linux now has extensive support for dynamic allocation of device numbering |
46 | where that applies (e.g. busmice), please contact me with the | 32 | and can use sysfs and udev (systemd) to handle the naming needs. There are |
47 | appropriate device information. Also, if you have additional | 33 | still some exceptions in the serial and boot device area. Before asking |
48 | information regarding any of the devices listed below, or if I have | 34 | for a device number make sure you actually need one. |
49 | made a mistake, I would greatly appreciate a note. | ||
50 | |||
51 | I do, however, make a few requests about the nature of your report. | ||
52 | This is necessary for me to be able to keep this list up to date and | ||
53 | correct in a timely manner. First of all, *please* send it to the | ||
54 | correct address... <device@lanana.org>. I receive hundreds of email | ||
55 | messages a day, so mail sent to other addresses may very well get lost | ||
56 | in the avalanche. Please put in a descriptive subject, so I can find | ||
57 | your mail again should I need to. Too many people send me email | ||
58 | saying just "device number request" in the subject. | ||
59 | |||
60 | Second, please include a description of the device *in the same format | ||
61 | as this list*. The reason for this is that it is the only way I have | ||
62 | found to ensure I have all the requisite information to publish your | ||
63 | device and avoid conflicts. | ||
64 | 35 | ||
65 | Third, please don't assume that the distributed version of the list is | 36 | To have a major number allocated, or a minor number in situations |
66 | up to date. Due to the number of registrations I have to maintain it | 37 | where that applies (e.g. busmice), please submit a patch and send to |
67 | in "batch mode", so there is likely additional registrations that | 38 | the authors as indicated above. |
68 | haven't been listed yet. | ||
69 | 39 | ||
70 | Fourth, remember that Linux now has extensive support for dynamic allocation | 40 | Keep the description of the device *in the same format |
71 | of device numbering and can use sysfs and udev to handle the naming needs. | 41 | as this list*. The reason for this is that it is the only way we have |
72 | There are still some exceptions in the serial and boot device area. Before | 42 | found to ensure we have all the requisite information to publish your |
73 | asking for a device number make sure you actually need one. | 43 | device and avoid conflicts. |
74 | 44 | ||
75 | Finally, sometimes I have to play "namespace police." Please don't be | 45 | Finally, sometimes we have to play "namespace police." Please don't be |
76 | offended. I often get submissions for /dev names that would be bound | 46 | offended. We often get submissions for /dev names that would be bound |
77 | to cause conflicts down the road. I am trying to avoid getting in a | 47 | to cause conflicts down the road. We are trying to avoid getting in a |
78 | situation where we would have to suffer an incompatible forward | 48 | situation where we would have to suffer an incompatible forward |
79 | change. Therefore, please consult with me *before* you make your | 49 | change. Therefore, please consult with us *before* you make your |
80 | device names and numbers in any way public, at least to the point | 50 | device names and numbers in any way public, at least to the point |
81 | where it would be at all difficult to get them changed. | 51 | where it would be at all difficult to get them changed. |
82 | 52 | ||
@@ -3099,9 +3069,9 @@ Your cooperation is appreciated. | |||
3099 | 129 = /dev/ipath_sma Device used by Subnet Management Agent | 3069 | 129 = /dev/ipath_sma Device used by Subnet Management Agent |
3100 | 130 = /dev/ipath_diag Device used by diagnostics programs | 3070 | 130 = /dev/ipath_diag Device used by diagnostics programs |
3101 | 3071 | ||
3102 | 234-239 UNASSIGNED | 3072 | 234-254 char RESERVED FOR DYNAMIC ASSIGNMENT |
3103 | 3073 | Character devices that request a dynamic allocation of major number will | |
3104 | 240-254 char LOCAL/EXPERIMENTAL USE | 3074 | take numbers starting from 254 and downward. |
3105 | 3075 | ||
3106 | 240-254 block LOCAL/EXPERIMENTAL USE | 3076 | 240-254 block LOCAL/EXPERIMENTAL USE |
3107 | Allocated for local/experimental use. For devices not | 3077 | Allocated for local/experimental use. For devices not |
diff --git a/Documentation/isa.txt b/Documentation/isa.txt new file mode 100644 index 000000000000..f232c26a40be --- /dev/null +++ b/Documentation/isa.txt | |||
@@ -0,0 +1,121 @@ | |||
1 | ISA Drivers | ||
2 | ----------- | ||
3 | |||
4 | The following text is adapted from the commit message of the initial | ||
5 | commit of the ISA bus driver authored by Rene Herman. | ||
6 | |||
7 | During the recent "isa drivers using platform devices" discussion it was | ||
8 | pointed out that (ALSA) ISA drivers ran into the problem of not having | ||
9 | the option to fail driver load (device registration rather) upon not | ||
10 | finding their hardware due to a probe() error not being passed up | ||
11 | through the driver model. In the course of that, I suggested a separate | ||
12 | ISA bus might be best; Russell King agreed and suggested this bus could | ||
13 | use the .match() method for the actual device discovery. | ||
14 | |||
15 | The attached does this. For this old non (generically) discoverable ISA | ||
16 | hardware only the driver itself can do discovery so as a difference with | ||
17 | the platform_bus, this isa_bus also distributes match() up to the | ||
18 | driver. | ||
19 | |||
20 | As another difference: these devices only exist in the driver model due | ||
21 | to the driver creating them because it might want to drive them, meaning | ||
22 | that all device creation has been made internal as well. | ||
23 | |||
24 | The usage model this provides is nice, and has been acked from the ALSA | ||
25 | side by Takashi Iwai and Jaroslav Kysela. The ALSA driver module_init's | ||
26 | now (for oldisa-only drivers) become: | ||
27 | |||
28 | static int __init alsa_card_foo_init(void) | ||
29 | { | ||
30 | return isa_register_driver(&snd_foo_isa_driver, SNDRV_CARDS); | ||
31 | } | ||
32 | |||
33 | static void __exit alsa_card_foo_exit(void) | ||
34 | { | ||
35 | isa_unregister_driver(&snd_foo_isa_driver); | ||
36 | } | ||
37 | |||
38 | Quite like the other bus models therefore. This removes a lot of | ||
39 | duplicated init code from the ALSA ISA drivers. | ||
40 | |||
41 | The passed in isa_driver struct is the regular driver struct embedding a | ||
42 | struct device_driver, the normal probe/remove/shutdown/suspend/resume | ||
43 | callbacks, and as indicated that .match callback. | ||
44 | |||
45 | The "SNDRV_CARDS" you see being passed in is a "unsigned int ndev" | ||
46 | parameter, indicating how many devices to create and call our methods | ||
47 | with. | ||
48 | |||
49 | The platform_driver callbacks are called with a platform_device param; | ||
50 | the isa_driver callbacks are being called with a "struct device *dev, | ||
51 | unsigned int id" pair directly -- with the device creation completely | ||
52 | internal to the bus it's much cleaner to not leak isa_dev's by passing | ||
53 | them in at all. The id is the only thing we ever want other then the | ||
54 | struct device * anyways, and it makes for nicer code in the callbacks as | ||
55 | well. | ||
56 | |||
57 | With this additional .match() callback ISA drivers have all options. If | ||
58 | ALSA would want to keep the old non-load behaviour, it could stick all | ||
59 | of the old .probe in .match, which would only keep them registered after | ||
60 | everything was found to be present and accounted for. If it wanted the | ||
61 | behaviour of always loading as it inadvertently did for a bit after the | ||
62 | changeover to platform devices, it could just not provide a .match() and | ||
63 | do everything in .probe() as before. | ||
64 | |||
65 | If it, as Takashi Iwai already suggested earlier as a way of following | ||
66 | the model from saner buses more closely, wants to load when a later bind | ||
67 | could conceivably succeed, it could use .match() for the prerequisites | ||
68 | (such as checking the user wants the card enabled and that port/irq/dma | ||
69 | values have been passed in) and .probe() for everything else. This is | ||
70 | the nicest model. | ||
71 | |||
72 | To the code... | ||
73 | |||
74 | This exports only two functions; isa_{,un}register_driver(). | ||
75 | |||
76 | isa_register_driver() register's the struct device_driver, and then | ||
77 | loops over the passed in ndev creating devices and registering them. | ||
78 | This causes the bus match method to be called for them, which is: | ||
79 | |||
80 | int isa_bus_match(struct device *dev, struct device_driver *driver) | ||
81 | { | ||
82 | struct isa_driver *isa_driver = to_isa_driver(driver); | ||
83 | |||
84 | if (dev->platform_data == isa_driver) { | ||
85 | if (!isa_driver->match || | ||
86 | isa_driver->match(dev, to_isa_dev(dev)->id)) | ||
87 | return 1; | ||
88 | dev->platform_data = NULL; | ||
89 | } | ||
90 | return 0; | ||
91 | } | ||
92 | |||
93 | The first thing this does is check if this device is in fact one of this | ||
94 | driver's devices by seeing if the device's platform_data pointer is set | ||
95 | to this driver. Platform devices compare strings, but we don't need to | ||
96 | do that with everything being internal, so isa_register_driver() abuses | ||
97 | dev->platform_data as a isa_driver pointer which we can then check here. | ||
98 | I believe platform_data is available for this, but if rather not, moving | ||
99 | the isa_driver pointer to the private struct isa_dev is ofcourse fine as | ||
100 | well. | ||
101 | |||
102 | Then, if the the driver did not provide a .match, it matches. If it did, | ||
103 | the driver match() method is called to determine a match. | ||
104 | |||
105 | If it did _not_ match, dev->platform_data is reset to indicate this to | ||
106 | isa_register_driver which can then unregister the device again. | ||
107 | |||
108 | If during all this, there's any error, or no devices matched at all | ||
109 | everything is backed out again and the error, or -ENODEV, is returned. | ||
110 | |||
111 | isa_unregister_driver() just unregisters the matched devices and the | ||
112 | driver itself. | ||
113 | |||
114 | module_isa_driver is a helper macro for ISA drivers which do not do | ||
115 | anything special in module init/exit. This eliminates a lot of | ||
116 | boilerplate code. Each module may only use this macro once, and calling | ||
117 | it replaces module_init and module_exit. | ||
118 | |||
119 | max_num_isa_dev is a macro to determine the maximum possible number of | ||
120 | ISA devices which may be registered in the I/O port address space given | ||
121 | the address extent of the ISA devices. | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 3dc5d894713b..5504c0de47ad 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -6067,6 +6067,13 @@ F: include/linux/irqdomain.h | |||
6067 | F: kernel/irq/irqdomain.c | 6067 | F: kernel/irq/irqdomain.c |
6068 | F: kernel/irq/msi.c | 6068 | F: kernel/irq/msi.c |
6069 | 6069 | ||
6070 | ISA | ||
6071 | M: William Breathitt Gray <vilhelm.gray@gmail.com> | ||
6072 | S: Maintained | ||
6073 | F: Documentation/isa.txt | ||
6074 | F: drivers/base/isa.c | ||
6075 | F: include/linux/isa.h | ||
6076 | |||
6070 | ISAPNP | 6077 | ISAPNP |
6071 | M: Jaroslav Kysela <perex@perex.cz> | 6078 | M: Jaroslav Kysela <perex@perex.cz> |
6072 | S: Maintained | 6079 | S: Maintained |
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index ace79d2da2c3..15f827678843 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -2445,8 +2445,6 @@ config ISA_DMA_API | |||
2445 | Enables ISA-style DMA support for devices requiring such controllers. | 2445 | Enables ISA-style DMA support for devices requiring such controllers. |
2446 | If unsure, say Y. | 2446 | If unsure, say Y. |
2447 | 2447 | ||
2448 | if X86_32 | ||
2449 | |||
2450 | config ISA | 2448 | config ISA |
2451 | bool "ISA support" | 2449 | bool "ISA support" |
2452 | ---help--- | 2450 | ---help--- |
@@ -2456,6 +2454,8 @@ config ISA | |||
2456 | (MCA) or VESA. ISA is an older system, now being displaced by PCI; | 2454 | (MCA) or VESA. ISA is an older system, now being displaced by PCI; |
2457 | newer boards don't support it. If you have ISA, say Y, otherwise N. | 2455 | newer boards don't support it. If you have ISA, say Y, otherwise N. |
2458 | 2456 | ||
2457 | if X86_32 | ||
2458 | |||
2459 | config EISA | 2459 | config EISA |
2460 | bool "EISA support" | 2460 | bool "EISA support" |
2461 | depends on ISA | 2461 | depends on ISA |
diff --git a/drivers/base/devcoredump.c b/drivers/base/devcoredump.c index 1bd120a0b084..240374fd1838 100644 --- a/drivers/base/devcoredump.c +++ b/drivers/base/devcoredump.c | |||
@@ -4,6 +4,7 @@ | |||
4 | * GPL LICENSE SUMMARY | 4 | * GPL LICENSE SUMMARY |
5 | * | 5 | * |
6 | * Copyright(c) 2014 Intel Mobile Communications GmbH | 6 | * Copyright(c) 2014 Intel Mobile Communications GmbH |
7 | * Copyright(c) 2015 Intel Deutschland GmbH | ||
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 version 2 of the GNU General Public License as | 10 | * it under the terms of version 2 of the GNU General Public License as |
@@ -41,12 +42,12 @@ static bool devcd_disabled; | |||
41 | 42 | ||
42 | struct devcd_entry { | 43 | struct devcd_entry { |
43 | struct device devcd_dev; | 44 | struct device devcd_dev; |
44 | const void *data; | 45 | void *data; |
45 | size_t datalen; | 46 | size_t datalen; |
46 | struct module *owner; | 47 | struct module *owner; |
47 | ssize_t (*read)(char *buffer, loff_t offset, size_t count, | 48 | ssize_t (*read)(char *buffer, loff_t offset, size_t count, |
48 | const void *data, size_t datalen); | 49 | void *data, size_t datalen); |
49 | void (*free)(const void *data); | 50 | void (*free)(void *data); |
50 | struct delayed_work del_wk; | 51 | struct delayed_work del_wk; |
51 | struct device *failing_dev; | 52 | struct device *failing_dev; |
52 | }; | 53 | }; |
@@ -174,7 +175,7 @@ static struct class devcd_class = { | |||
174 | }; | 175 | }; |
175 | 176 | ||
176 | static ssize_t devcd_readv(char *buffer, loff_t offset, size_t count, | 177 | static ssize_t devcd_readv(char *buffer, loff_t offset, size_t count, |
177 | const void *data, size_t datalen) | 178 | void *data, size_t datalen) |
178 | { | 179 | { |
179 | if (offset > datalen) | 180 | if (offset > datalen) |
180 | return -EINVAL; | 181 | return -EINVAL; |
@@ -188,6 +189,11 @@ static ssize_t devcd_readv(char *buffer, loff_t offset, size_t count, | |||
188 | return count; | 189 | return count; |
189 | } | 190 | } |
190 | 191 | ||
192 | static void devcd_freev(void *data) | ||
193 | { | ||
194 | vfree(data); | ||
195 | } | ||
196 | |||
191 | /** | 197 | /** |
192 | * dev_coredumpv - create device coredump with vmalloc data | 198 | * dev_coredumpv - create device coredump with vmalloc data |
193 | * @dev: the struct device for the crashed device | 199 | * @dev: the struct device for the crashed device |
@@ -198,10 +204,10 @@ static ssize_t devcd_readv(char *buffer, loff_t offset, size_t count, | |||
198 | * This function takes ownership of the vmalloc'ed data and will free | 204 | * This function takes ownership of the vmalloc'ed data and will free |
199 | * it when it is no longer used. See dev_coredumpm() for more information. | 205 | * it when it is no longer used. See dev_coredumpm() for more information. |
200 | */ | 206 | */ |
201 | void dev_coredumpv(struct device *dev, const void *data, size_t datalen, | 207 | void dev_coredumpv(struct device *dev, void *data, size_t datalen, |
202 | gfp_t gfp) | 208 | gfp_t gfp) |
203 | { | 209 | { |
204 | dev_coredumpm(dev, NULL, data, datalen, gfp, devcd_readv, vfree); | 210 | dev_coredumpm(dev, NULL, data, datalen, gfp, devcd_readv, devcd_freev); |
205 | } | 211 | } |
206 | EXPORT_SYMBOL_GPL(dev_coredumpv); | 212 | EXPORT_SYMBOL_GPL(dev_coredumpv); |
207 | 213 | ||
@@ -213,6 +219,44 @@ static int devcd_match_failing(struct device *dev, const void *failing) | |||
213 | } | 219 | } |
214 | 220 | ||
215 | /** | 221 | /** |
222 | * devcd_free_sgtable - free all the memory of the given scatterlist table | ||
223 | * (i.e. both pages and scatterlist instances) | ||
224 | * NOTE: if two tables allocated with devcd_alloc_sgtable and then chained | ||
225 | * using the sg_chain function then that function should be called only once | ||
226 | * on the chained table | ||
227 | * @table: pointer to sg_table to free | ||
228 | */ | ||
229 | static void devcd_free_sgtable(void *data) | ||
230 | { | ||
231 | _devcd_free_sgtable(data); | ||
232 | } | ||
233 | |||
234 | /** | ||
235 | * devcd_read_from_table - copy data from sg_table to a given buffer | ||
236 | * and return the number of bytes read | ||
237 | * @buffer: the buffer to copy the data to it | ||
238 | * @buf_len: the length of the buffer | ||
239 | * @data: the scatterlist table to copy from | ||
240 | * @offset: start copy from @offset@ bytes from the head of the data | ||
241 | * in the given scatterlist | ||
242 | * @data_len: the length of the data in the sg_table | ||
243 | */ | ||
244 | static ssize_t devcd_read_from_sgtable(char *buffer, loff_t offset, | ||
245 | size_t buf_len, void *data, | ||
246 | size_t data_len) | ||
247 | { | ||
248 | struct scatterlist *table = data; | ||
249 | |||
250 | if (offset > data_len) | ||
251 | return -EINVAL; | ||
252 | |||
253 | if (offset + buf_len > data_len) | ||
254 | buf_len = data_len - offset; | ||
255 | return sg_pcopy_to_buffer(table, sg_nents(table), buffer, buf_len, | ||
256 | offset); | ||
257 | } | ||
258 | |||
259 | /** | ||
216 | * dev_coredumpm - create device coredump with read/free methods | 260 | * dev_coredumpm - create device coredump with read/free methods |
217 | * @dev: the struct device for the crashed device | 261 | * @dev: the struct device for the crashed device |
218 | * @owner: the module that contains the read/free functions, use %THIS_MODULE | 262 | * @owner: the module that contains the read/free functions, use %THIS_MODULE |
@@ -228,10 +272,10 @@ static int devcd_match_failing(struct device *dev, const void *failing) | |||
228 | * function will be called to free the data. | 272 | * function will be called to free the data. |
229 | */ | 273 | */ |
230 | void dev_coredumpm(struct device *dev, struct module *owner, | 274 | void dev_coredumpm(struct device *dev, struct module *owner, |
231 | const void *data, size_t datalen, gfp_t gfp, | 275 | void *data, size_t datalen, gfp_t gfp, |
232 | ssize_t (*read)(char *buffer, loff_t offset, size_t count, | 276 | ssize_t (*read)(char *buffer, loff_t offset, size_t count, |
233 | const void *data, size_t datalen), | 277 | void *data, size_t datalen), |
234 | void (*free)(const void *data)) | 278 | void (*free)(void *data)) |
235 | { | 279 | { |
236 | static atomic_t devcd_count = ATOMIC_INIT(0); | 280 | static atomic_t devcd_count = ATOMIC_INIT(0); |
237 | struct devcd_entry *devcd; | 281 | struct devcd_entry *devcd; |
@@ -291,6 +335,27 @@ void dev_coredumpm(struct device *dev, struct module *owner, | |||
291 | } | 335 | } |
292 | EXPORT_SYMBOL_GPL(dev_coredumpm); | 336 | EXPORT_SYMBOL_GPL(dev_coredumpm); |
293 | 337 | ||
338 | /** | ||
339 | * dev_coredumpmsg - create device coredump that uses scatterlist as data | ||
340 | * parameter | ||
341 | * @dev: the struct device for the crashed device | ||
342 | * @table: the dump data | ||
343 | * @datalen: length of the data | ||
344 | * @gfp: allocation flags | ||
345 | * | ||
346 | * Creates a new device coredump for the given device. If a previous one hasn't | ||
347 | * been read yet, the new coredump is discarded. The data lifetime is determined | ||
348 | * by the device coredump framework and when it is no longer needed | ||
349 | * it will free the data. | ||
350 | */ | ||
351 | void dev_coredumpsg(struct device *dev, struct scatterlist *table, | ||
352 | size_t datalen, gfp_t gfp) | ||
353 | { | ||
354 | dev_coredumpm(dev, NULL, table, datalen, gfp, devcd_read_from_sgtable, | ||
355 | devcd_free_sgtable); | ||
356 | } | ||
357 | EXPORT_SYMBOL_GPL(dev_coredumpsg); | ||
358 | |||
294 | static int __init devcoredump_init(void) | 359 | static int __init devcoredump_init(void) |
295 | { | 360 | { |
296 | return class_register(&devcd_class); | 361 | return class_register(&devcd_class); |
diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c index 1b95475b6aef..0e2011636fbb 100644 --- a/drivers/firmware/qemu_fw_cfg.c +++ b/drivers/firmware/qemu_fw_cfg.c | |||
@@ -125,9 +125,7 @@ static void fw_cfg_io_cleanup(void) | |||
125 | # define FW_CFG_CTRL_OFF 0x00 | 125 | # define FW_CFG_CTRL_OFF 0x00 |
126 | # define FW_CFG_DATA_OFF 0x01 | 126 | # define FW_CFG_DATA_OFF 0x01 |
127 | # else | 127 | # else |
128 | # warning "QEMU FW_CFG may not be available on this architecture!" | 128 | # error "QEMU FW_CFG not available on this architecture!" |
129 | # define FW_CFG_CTRL_OFF 0x00 | ||
130 | # define FW_CFG_DATA_OFF 0x01 | ||
131 | # endif | 129 | # endif |
132 | #endif | 130 | #endif |
133 | 131 | ||
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index d00e7b67be9a..48da857f4774 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -530,30 +530,35 @@ menu "Port-mapped I/O GPIO drivers" | |||
530 | 530 | ||
531 | config GPIO_104_DIO_48E | 531 | config GPIO_104_DIO_48E |
532 | tristate "ACCES 104-DIO-48E GPIO support" | 532 | tristate "ACCES 104-DIO-48E GPIO support" |
533 | depends on ISA | ||
533 | select GPIOLIB_IRQCHIP | 534 | select GPIOLIB_IRQCHIP |
534 | help | 535 | help |
535 | Enables GPIO support for the ACCES 104-DIO-48E family. The base port | 536 | Enables GPIO support for the ACCES 104-DIO-48E series (104-DIO-48E, |
536 | address for the device may be configured via the dio_48e_base module | 537 | 104-DIO-24E). The base port addresses for the devices may be |
537 | parameter. The interrupt line number for the device may be configured | 538 | configured via the base module parameter. The interrupt line numbers |
538 | via the dio_48e_irq module parameter. | 539 | for the devices may be configured via the irq module parameter. |
539 | 540 | ||
540 | config GPIO_104_IDIO_16 | 541 | config GPIO_104_IDIO_16 |
541 | tristate "ACCES 104-IDIO-16 GPIO support" | 542 | tristate "ACCES 104-IDIO-16 GPIO support" |
543 | depends on ISA | ||
542 | select GPIOLIB_IRQCHIP | 544 | select GPIOLIB_IRQCHIP |
543 | help | 545 | help |
544 | Enables GPIO support for the ACCES 104-IDIO-16 family. The base port | 546 | Enables GPIO support for the ACCES 104-IDIO-16 family (104-IDIO-16, |
545 | address for the device may be set via the idio_16_base module | 547 | 104-IDIO-16E, 104-IDO-16, 104-IDIO-8, 104-IDIO-8E, 104-IDO-8). The |
546 | parameter. The interrupt line number for the device may be set via the | 548 | base port addresses for the devices may be configured via the base |
547 | idio_16_irq module parameter. | 549 | module parameter. The interrupt line numbers for the devices may be |
550 | configured via the irq module parameter. | ||
548 | 551 | ||
549 | config GPIO_104_IDI_48 | 552 | config GPIO_104_IDI_48 |
550 | tristate "ACCES 104-IDI-48 GPIO support" | 553 | tristate "ACCES 104-IDI-48 GPIO support" |
554 | depends on ISA | ||
551 | select GPIOLIB_IRQCHIP | 555 | select GPIOLIB_IRQCHIP |
552 | help | 556 | help |
553 | Enables GPIO support for the ACCES 104-IDI-48 family. The base port | 557 | Enables GPIO support for the ACCES 104-IDI-48 family (104-IDI-48A, |
554 | address for the device may be configured via the idi_48_base module | 558 | 104-IDI-48AC, 104-IDI-48B, 104-IDI-48BC). The base port addresses for |
555 | parameter. The interrupt line number for the device may be configured | 559 | the devices may be configured via the base module parameter. The |
556 | via the idi_48_irq module parameter. | 560 | interrupt line numbers for the devices may be configured via the irq |
561 | module parameter. | ||
557 | 562 | ||
558 | config GPIO_F7188X | 563 | config GPIO_F7188X |
559 | tristate "F71869, F71869A, F71882FG, F71889F and F81866 GPIO support" | 564 | tristate "F71869, F71869A, F71882FG, F71889F and F81866 GPIO support" |
@@ -622,12 +627,13 @@ config GPIO_TS5500 | |||
622 | 627 | ||
623 | config GPIO_WS16C48 | 628 | config GPIO_WS16C48 |
624 | tristate "WinSystems WS16C48 GPIO support" | 629 | tristate "WinSystems WS16C48 GPIO support" |
630 | depends on ISA | ||
625 | select GPIOLIB_IRQCHIP | 631 | select GPIOLIB_IRQCHIP |
626 | help | 632 | help |
627 | Enables GPIO support for the WinSystems WS16C48. The base port address | 633 | Enables GPIO support for the WinSystems WS16C48. The base port |
628 | for the device may be configured via the ws16c48_base module | 634 | addresses for the devices may be configured via the base module |
629 | parameter. The interrupt line number for the device may be configured | 635 | parameter. The interrupt line numbers for the devices may be |
630 | via the ws16c48_irq module parameter. | 636 | configured via the irq module parameter. |
631 | 637 | ||
632 | endmenu | 638 | endmenu |
633 | 639 | ||
diff --git a/drivers/gpio/gpio-104-dio-48e.c b/drivers/gpio/gpio-104-dio-48e.c index 448a903089ef..1a647c07be67 100644 --- a/drivers/gpio/gpio-104-dio-48e.c +++ b/drivers/gpio/gpio-104-dio-48e.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * GPIO driver for the ACCES 104-DIO-48E | 2 | * GPIO driver for the ACCES 104-DIO-48E series |
3 | * Copyright (C) 2016 William Breathitt Gray | 3 | * Copyright (C) 2016 William Breathitt Gray |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
@@ -10,6 +10,9 @@ | |||
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | * General Public License for more details. | 12 | * General Public License for more details. |
13 | * | ||
14 | * This driver supports the following ACCES devices: 104-DIO-48E and | ||
15 | * 104-DIO-24E. | ||
13 | */ | 16 | */ |
14 | #include <linux/bitops.h> | 17 | #include <linux/bitops.h> |
15 | #include <linux/device.h> | 18 | #include <linux/device.h> |
@@ -19,18 +22,23 @@ | |||
19 | #include <linux/ioport.h> | 22 | #include <linux/ioport.h> |
20 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
21 | #include <linux/irqdesc.h> | 24 | #include <linux/irqdesc.h> |
25 | #include <linux/isa.h> | ||
22 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
23 | #include <linux/module.h> | 27 | #include <linux/module.h> |
24 | #include <linux/moduleparam.h> | 28 | #include <linux/moduleparam.h> |
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/spinlock.h> | 29 | #include <linux/spinlock.h> |
27 | 30 | ||
28 | static unsigned dio_48e_base; | 31 | #define DIO48E_EXTENT 16 |
29 | module_param(dio_48e_base, uint, 0); | 32 | #define MAX_NUM_DIO48E max_num_isa_dev(DIO48E_EXTENT) |
30 | MODULE_PARM_DESC(dio_48e_base, "ACCES 104-DIO-48E base address"); | 33 | |
31 | static unsigned dio_48e_irq; | 34 | static unsigned int base[MAX_NUM_DIO48E]; |
32 | module_param(dio_48e_irq, uint, 0); | 35 | static unsigned int num_dio48e; |
33 | MODULE_PARM_DESC(dio_48e_irq, "ACCES 104-DIO-48E interrupt line number"); | 36 | module_param_array(base, uint, &num_dio48e, 0); |
37 | MODULE_PARM_DESC(base, "ACCES 104-DIO-48E base addresses"); | ||
38 | |||
39 | static unsigned int irq[MAX_NUM_DIO48E]; | ||
40 | module_param_array(irq, uint, NULL, 0); | ||
41 | MODULE_PARM_DESC(irq, "ACCES 104-DIO-48E interrupt line numbers"); | ||
34 | 42 | ||
35 | /** | 43 | /** |
36 | * struct dio48e_gpio - GPIO device private data structure | 44 | * struct dio48e_gpio - GPIO device private data structure |
@@ -294,23 +302,19 @@ static irqreturn_t dio48e_irq_handler(int irq, void *dev_id) | |||
294 | return IRQ_HANDLED; | 302 | return IRQ_HANDLED; |
295 | } | 303 | } |
296 | 304 | ||
297 | static int __init dio48e_probe(struct platform_device *pdev) | 305 | static int dio48e_probe(struct device *dev, unsigned int id) |
298 | { | 306 | { |
299 | struct device *dev = &pdev->dev; | ||
300 | struct dio48e_gpio *dio48egpio; | 307 | struct dio48e_gpio *dio48egpio; |
301 | const unsigned base = dio_48e_base; | ||
302 | const unsigned extent = 16; | ||
303 | const char *const name = dev_name(dev); | 308 | const char *const name = dev_name(dev); |
304 | int err; | 309 | int err; |
305 | const unsigned irq = dio_48e_irq; | ||
306 | 310 | ||
307 | dio48egpio = devm_kzalloc(dev, sizeof(*dio48egpio), GFP_KERNEL); | 311 | dio48egpio = devm_kzalloc(dev, sizeof(*dio48egpio), GFP_KERNEL); |
308 | if (!dio48egpio) | 312 | if (!dio48egpio) |
309 | return -ENOMEM; | 313 | return -ENOMEM; |
310 | 314 | ||
311 | if (!devm_request_region(dev, base, extent, name)) { | 315 | if (!devm_request_region(dev, base[id], DIO48E_EXTENT, name)) { |
312 | dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", | 316 | dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", |
313 | base, base + extent); | 317 | base[id], base[id] + DIO48E_EXTENT); |
314 | return -EBUSY; | 318 | return -EBUSY; |
315 | } | 319 | } |
316 | 320 | ||
@@ -324,8 +328,8 @@ static int __init dio48e_probe(struct platform_device *pdev) | |||
324 | dio48egpio->chip.direction_output = dio48e_gpio_direction_output; | 328 | dio48egpio->chip.direction_output = dio48e_gpio_direction_output; |
325 | dio48egpio->chip.get = dio48e_gpio_get; | 329 | dio48egpio->chip.get = dio48e_gpio_get; |
326 | dio48egpio->chip.set = dio48e_gpio_set; | 330 | dio48egpio->chip.set = dio48e_gpio_set; |
327 | dio48egpio->base = base; | 331 | dio48egpio->base = base[id]; |
328 | dio48egpio->irq = irq; | 332 | dio48egpio->irq = irq[id]; |
329 | 333 | ||
330 | spin_lock_init(&dio48egpio->lock); | 334 | spin_lock_init(&dio48egpio->lock); |
331 | 335 | ||
@@ -338,19 +342,19 @@ static int __init dio48e_probe(struct platform_device *pdev) | |||
338 | } | 342 | } |
339 | 343 | ||
340 | /* initialize all GPIO as output */ | 344 | /* initialize all GPIO as output */ |
341 | outb(0x80, base + 3); | 345 | outb(0x80, base[id] + 3); |
342 | outb(0x00, base); | 346 | outb(0x00, base[id]); |
343 | outb(0x00, base + 1); | 347 | outb(0x00, base[id] + 1); |
344 | outb(0x00, base + 2); | 348 | outb(0x00, base[id] + 2); |
345 | outb(0x00, base + 3); | 349 | outb(0x00, base[id] + 3); |
346 | outb(0x80, base + 7); | 350 | outb(0x80, base[id] + 7); |
347 | outb(0x00, base + 4); | 351 | outb(0x00, base[id] + 4); |
348 | outb(0x00, base + 5); | 352 | outb(0x00, base[id] + 5); |
349 | outb(0x00, base + 6); | 353 | outb(0x00, base[id] + 6); |
350 | outb(0x00, base + 7); | 354 | outb(0x00, base[id] + 7); |
351 | 355 | ||
352 | /* disable IRQ by default */ | 356 | /* disable IRQ by default */ |
353 | inb(base + 0xB); | 357 | inb(base[id] + 0xB); |
354 | 358 | ||
355 | err = gpiochip_irqchip_add(&dio48egpio->chip, &dio48e_irqchip, 0, | 359 | err = gpiochip_irqchip_add(&dio48egpio->chip, &dio48e_irqchip, 0, |
356 | handle_edge_irq, IRQ_TYPE_NONE); | 360 | handle_edge_irq, IRQ_TYPE_NONE); |
@@ -359,7 +363,7 @@ static int __init dio48e_probe(struct platform_device *pdev) | |||
359 | goto err_gpiochip_remove; | 363 | goto err_gpiochip_remove; |
360 | } | 364 | } |
361 | 365 | ||
362 | err = request_irq(irq, dio48e_irq_handler, 0, name, dio48egpio); | 366 | err = request_irq(irq[id], dio48e_irq_handler, 0, name, dio48egpio); |
363 | if (err) { | 367 | if (err) { |
364 | dev_err(dev, "IRQ handler registering failed (%d)\n", err); | 368 | dev_err(dev, "IRQ handler registering failed (%d)\n", err); |
365 | goto err_gpiochip_remove; | 369 | goto err_gpiochip_remove; |
@@ -372,9 +376,9 @@ err_gpiochip_remove: | |||
372 | return err; | 376 | return err; |
373 | } | 377 | } |
374 | 378 | ||
375 | static int dio48e_remove(struct platform_device *pdev) | 379 | static int dio48e_remove(struct device *dev, unsigned int id) |
376 | { | 380 | { |
377 | struct dio48e_gpio *const dio48egpio = platform_get_drvdata(pdev); | 381 | struct dio48e_gpio *const dio48egpio = dev_get_drvdata(dev); |
378 | 382 | ||
379 | free_irq(dio48egpio->irq, dio48egpio); | 383 | free_irq(dio48egpio->irq, dio48egpio); |
380 | gpiochip_remove(&dio48egpio->chip); | 384 | gpiochip_remove(&dio48egpio->chip); |
@@ -382,48 +386,14 @@ static int dio48e_remove(struct platform_device *pdev) | |||
382 | return 0; | 386 | return 0; |
383 | } | 387 | } |
384 | 388 | ||
385 | static struct platform_device *dio48e_device; | 389 | static struct isa_driver dio48e_driver = { |
386 | 390 | .probe = dio48e_probe, | |
387 | static struct platform_driver dio48e_driver = { | ||
388 | .driver = { | 391 | .driver = { |
389 | .name = "104-dio-48e" | 392 | .name = "104-dio-48e" |
390 | }, | 393 | }, |
391 | .remove = dio48e_remove | 394 | .remove = dio48e_remove |
392 | }; | 395 | }; |
393 | 396 | module_isa_driver(dio48e_driver, num_dio48e); | |
394 | static void __exit dio48e_exit(void) | ||
395 | { | ||
396 | platform_device_unregister(dio48e_device); | ||
397 | platform_driver_unregister(&dio48e_driver); | ||
398 | } | ||
399 | |||
400 | static int __init dio48e_init(void) | ||
401 | { | ||
402 | int err; | ||
403 | |||
404 | dio48e_device = platform_device_alloc(dio48e_driver.driver.name, -1); | ||
405 | if (!dio48e_device) | ||
406 | return -ENOMEM; | ||
407 | |||
408 | err = platform_device_add(dio48e_device); | ||
409 | if (err) | ||
410 | goto err_platform_device; | ||
411 | |||
412 | err = platform_driver_probe(&dio48e_driver, dio48e_probe); | ||
413 | if (err) | ||
414 | goto err_platform_driver; | ||
415 | |||
416 | return 0; | ||
417 | |||
418 | err_platform_driver: | ||
419 | platform_device_del(dio48e_device); | ||
420 | err_platform_device: | ||
421 | platform_device_put(dio48e_device); | ||
422 | return err; | ||
423 | } | ||
424 | |||
425 | module_init(dio48e_init); | ||
426 | module_exit(dio48e_exit); | ||
427 | 397 | ||
428 | MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>"); | 398 | MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>"); |
429 | MODULE_DESCRIPTION("ACCES 104-DIO-48E GPIO driver"); | 399 | MODULE_DESCRIPTION("ACCES 104-DIO-48E GPIO driver"); |
diff --git a/drivers/gpio/gpio-104-idi-48.c b/drivers/gpio/gpio-104-idi-48.c index e37cd4cdda35..6c75c83baf5a 100644 --- a/drivers/gpio/gpio-104-idi-48.c +++ b/drivers/gpio/gpio-104-idi-48.c | |||
@@ -10,6 +10,9 @@ | |||
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | * General Public License for more details. | 12 | * General Public License for more details. |
13 | * | ||
14 | * This driver supports the following ACCES devices: 104-IDI-48A, | ||
15 | * 104-IDI-48AC, 104-IDI-48B, and 104-IDI-48BC. | ||
13 | */ | 16 | */ |
14 | #include <linux/bitops.h> | 17 | #include <linux/bitops.h> |
15 | #include <linux/device.h> | 18 | #include <linux/device.h> |
@@ -19,18 +22,23 @@ | |||
19 | #include <linux/ioport.h> | 22 | #include <linux/ioport.h> |
20 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
21 | #include <linux/irqdesc.h> | 24 | #include <linux/irqdesc.h> |
25 | #include <linux/isa.h> | ||
22 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
23 | #include <linux/module.h> | 27 | #include <linux/module.h> |
24 | #include <linux/moduleparam.h> | 28 | #include <linux/moduleparam.h> |
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/spinlock.h> | 29 | #include <linux/spinlock.h> |
27 | 30 | ||
28 | static unsigned idi_48_base; | 31 | #define IDI_48_EXTENT 8 |
29 | module_param(idi_48_base, uint, 0); | 32 | #define MAX_NUM_IDI_48 max_num_isa_dev(IDI_48_EXTENT) |
30 | MODULE_PARM_DESC(idi_48_base, "ACCES 104-IDI-48 base address"); | 33 | |
31 | static unsigned idi_48_irq; | 34 | static unsigned int base[MAX_NUM_IDI_48]; |
32 | module_param(idi_48_irq, uint, 0); | 35 | static unsigned int num_idi_48; |
33 | MODULE_PARM_DESC(idi_48_irq, "ACCES 104-IDI-48 interrupt line number"); | 36 | module_param_array(base, uint, &num_idi_48, 0); |
37 | MODULE_PARM_DESC(base, "ACCES 104-IDI-48 base addresses"); | ||
38 | |||
39 | static unsigned int irq[MAX_NUM_IDI_48]; | ||
40 | module_param_array(irq, uint, NULL, 0); | ||
41 | MODULE_PARM_DESC(irq, "ACCES 104-IDI-48 interrupt line numbers"); | ||
34 | 42 | ||
35 | /** | 43 | /** |
36 | * struct idi_48_gpio - GPIO device private data structure | 44 | * struct idi_48_gpio - GPIO device private data structure |
@@ -211,23 +219,19 @@ static irqreturn_t idi_48_irq_handler(int irq, void *dev_id) | |||
211 | return IRQ_HANDLED; | 219 | return IRQ_HANDLED; |
212 | } | 220 | } |
213 | 221 | ||
214 | static int __init idi_48_probe(struct platform_device *pdev) | 222 | static int idi_48_probe(struct device *dev, unsigned int id) |
215 | { | 223 | { |
216 | struct device *dev = &pdev->dev; | ||
217 | struct idi_48_gpio *idi48gpio; | 224 | struct idi_48_gpio *idi48gpio; |
218 | const unsigned base = idi_48_base; | ||
219 | const unsigned extent = 8; | ||
220 | const char *const name = dev_name(dev); | 225 | const char *const name = dev_name(dev); |
221 | int err; | 226 | int err; |
222 | const unsigned irq = idi_48_irq; | ||
223 | 227 | ||
224 | idi48gpio = devm_kzalloc(dev, sizeof(*idi48gpio), GFP_KERNEL); | 228 | idi48gpio = devm_kzalloc(dev, sizeof(*idi48gpio), GFP_KERNEL); |
225 | if (!idi48gpio) | 229 | if (!idi48gpio) |
226 | return -ENOMEM; | 230 | return -ENOMEM; |
227 | 231 | ||
228 | if (!devm_request_region(dev, base, extent, name)) { | 232 | if (!devm_request_region(dev, base[id], IDI_48_EXTENT, name)) { |
229 | dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", | 233 | dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", |
230 | base, base + extent); | 234 | base[id], base[id] + IDI_48_EXTENT); |
231 | return -EBUSY; | 235 | return -EBUSY; |
232 | } | 236 | } |
233 | 237 | ||
@@ -239,8 +243,8 @@ static int __init idi_48_probe(struct platform_device *pdev) | |||
239 | idi48gpio->chip.get_direction = idi_48_gpio_get_direction; | 243 | idi48gpio->chip.get_direction = idi_48_gpio_get_direction; |
240 | idi48gpio->chip.direction_input = idi_48_gpio_direction_input; | 244 | idi48gpio->chip.direction_input = idi_48_gpio_direction_input; |
241 | idi48gpio->chip.get = idi_48_gpio_get; | 245 | idi48gpio->chip.get = idi_48_gpio_get; |
242 | idi48gpio->base = base; | 246 | idi48gpio->base = base[id]; |
243 | idi48gpio->irq = irq; | 247 | idi48gpio->irq = irq[id]; |
244 | 248 | ||
245 | spin_lock_init(&idi48gpio->lock); | 249 | spin_lock_init(&idi48gpio->lock); |
246 | 250 | ||
@@ -253,8 +257,8 @@ static int __init idi_48_probe(struct platform_device *pdev) | |||
253 | } | 257 | } |
254 | 258 | ||
255 | /* Disable IRQ by default */ | 259 | /* Disable IRQ by default */ |
256 | outb(0, base + 7); | 260 | outb(0, base[id] + 7); |
257 | inb(base + 7); | 261 | inb(base[id] + 7); |
258 | 262 | ||
259 | err = gpiochip_irqchip_add(&idi48gpio->chip, &idi_48_irqchip, 0, | 263 | err = gpiochip_irqchip_add(&idi48gpio->chip, &idi_48_irqchip, 0, |
260 | handle_edge_irq, IRQ_TYPE_NONE); | 264 | handle_edge_irq, IRQ_TYPE_NONE); |
@@ -263,7 +267,7 @@ static int __init idi_48_probe(struct platform_device *pdev) | |||
263 | goto err_gpiochip_remove; | 267 | goto err_gpiochip_remove; |
264 | } | 268 | } |
265 | 269 | ||
266 | err = request_irq(irq, idi_48_irq_handler, IRQF_SHARED, name, | 270 | err = request_irq(irq[id], idi_48_irq_handler, IRQF_SHARED, name, |
267 | idi48gpio); | 271 | idi48gpio); |
268 | if (err) { | 272 | if (err) { |
269 | dev_err(dev, "IRQ handler registering failed (%d)\n", err); | 273 | dev_err(dev, "IRQ handler registering failed (%d)\n", err); |
@@ -277,9 +281,9 @@ err_gpiochip_remove: | |||
277 | return err; | 281 | return err; |
278 | } | 282 | } |
279 | 283 | ||
280 | static int idi_48_remove(struct platform_device *pdev) | 284 | static int idi_48_remove(struct device *dev, unsigned int id) |
281 | { | 285 | { |
282 | struct idi_48_gpio *const idi48gpio = platform_get_drvdata(pdev); | 286 | struct idi_48_gpio *const idi48gpio = dev_get_drvdata(dev); |
283 | 287 | ||
284 | free_irq(idi48gpio->irq, idi48gpio); | 288 | free_irq(idi48gpio->irq, idi48gpio); |
285 | gpiochip_remove(&idi48gpio->chip); | 289 | gpiochip_remove(&idi48gpio->chip); |
@@ -287,48 +291,14 @@ static int idi_48_remove(struct platform_device *pdev) | |||
287 | return 0; | 291 | return 0; |
288 | } | 292 | } |
289 | 293 | ||
290 | static struct platform_device *idi_48_device; | 294 | static struct isa_driver idi_48_driver = { |
291 | 295 | .probe = idi_48_probe, | |
292 | static struct platform_driver idi_48_driver = { | ||
293 | .driver = { | 296 | .driver = { |
294 | .name = "104-idi-48" | 297 | .name = "104-idi-48" |
295 | }, | 298 | }, |
296 | .remove = idi_48_remove | 299 | .remove = idi_48_remove |
297 | }; | 300 | }; |
298 | 301 | module_isa_driver(idi_48_driver, num_idi_48); | |
299 | static void __exit idi_48_exit(void) | ||
300 | { | ||
301 | platform_device_unregister(idi_48_device); | ||
302 | platform_driver_unregister(&idi_48_driver); | ||
303 | } | ||
304 | |||
305 | static int __init idi_48_init(void) | ||
306 | { | ||
307 | int err; | ||
308 | |||
309 | idi_48_device = platform_device_alloc(idi_48_driver.driver.name, -1); | ||
310 | if (!idi_48_device) | ||
311 | return -ENOMEM; | ||
312 | |||
313 | err = platform_device_add(idi_48_device); | ||
314 | if (err) | ||
315 | goto err_platform_device; | ||
316 | |||
317 | err = platform_driver_probe(&idi_48_driver, idi_48_probe); | ||
318 | if (err) | ||
319 | goto err_platform_driver; | ||
320 | |||
321 | return 0; | ||
322 | |||
323 | err_platform_driver: | ||
324 | platform_device_del(idi_48_device); | ||
325 | err_platform_device: | ||
326 | platform_device_put(idi_48_device); | ||
327 | return err; | ||
328 | } | ||
329 | |||
330 | module_init(idi_48_init); | ||
331 | module_exit(idi_48_exit); | ||
332 | 302 | ||
333 | MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>"); | 303 | MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>"); |
334 | MODULE_DESCRIPTION("ACCES 104-IDI-48 GPIO driver"); | 304 | MODULE_DESCRIPTION("ACCES 104-IDI-48 GPIO driver"); |
diff --git a/drivers/gpio/gpio-104-idio-16.c b/drivers/gpio/gpio-104-idio-16.c index ecc85fe9323d..6787b8fcf0d8 100644 --- a/drivers/gpio/gpio-104-idio-16.c +++ b/drivers/gpio/gpio-104-idio-16.c | |||
@@ -10,6 +10,9 @@ | |||
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | * General Public License for more details. | 12 | * General Public License for more details. |
13 | * | ||
14 | * This driver supports the following ACCES devices: 104-IDIO-16, | ||
15 | * 104-IDIO-16E, 104-IDO-16, 104-IDIO-8, 104-IDIO-8E, and 104-IDO-8. | ||
13 | */ | 16 | */ |
14 | #include <linux/bitops.h> | 17 | #include <linux/bitops.h> |
15 | #include <linux/device.h> | 18 | #include <linux/device.h> |
@@ -19,18 +22,23 @@ | |||
19 | #include <linux/ioport.h> | 22 | #include <linux/ioport.h> |
20 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
21 | #include <linux/irqdesc.h> | 24 | #include <linux/irqdesc.h> |
25 | #include <linux/isa.h> | ||
22 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
23 | #include <linux/module.h> | 27 | #include <linux/module.h> |
24 | #include <linux/moduleparam.h> | 28 | #include <linux/moduleparam.h> |
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/spinlock.h> | 29 | #include <linux/spinlock.h> |
27 | 30 | ||
28 | static unsigned idio_16_base; | 31 | #define IDIO_16_EXTENT 8 |
29 | module_param(idio_16_base, uint, 0); | 32 | #define MAX_NUM_IDIO_16 max_num_isa_dev(IDIO_16_EXTENT) |
30 | MODULE_PARM_DESC(idio_16_base, "ACCES 104-IDIO-16 base address"); | 33 | |
31 | static unsigned idio_16_irq; | 34 | static unsigned int base[MAX_NUM_IDIO_16]; |
32 | module_param(idio_16_irq, uint, 0); | 35 | static unsigned int num_idio_16; |
33 | MODULE_PARM_DESC(idio_16_irq, "ACCES 104-IDIO-16 interrupt line number"); | 36 | module_param_array(base, uint, &num_idio_16, 0); |
37 | MODULE_PARM_DESC(base, "ACCES 104-IDIO-16 base addresses"); | ||
38 | |||
39 | static unsigned int irq[MAX_NUM_IDIO_16]; | ||
40 | module_param_array(irq, uint, NULL, 0); | ||
41 | MODULE_PARM_DESC(irq, "ACCES 104-IDIO-16 interrupt line numbers"); | ||
34 | 42 | ||
35 | /** | 43 | /** |
36 | * struct idio_16_gpio - GPIO device private data structure | 44 | * struct idio_16_gpio - GPIO device private data structure |
@@ -185,23 +193,19 @@ static irqreturn_t idio_16_irq_handler(int irq, void *dev_id) | |||
185 | return IRQ_HANDLED; | 193 | return IRQ_HANDLED; |
186 | } | 194 | } |
187 | 195 | ||
188 | static int __init idio_16_probe(struct platform_device *pdev) | 196 | static int idio_16_probe(struct device *dev, unsigned int id) |
189 | { | 197 | { |
190 | struct device *dev = &pdev->dev; | ||
191 | struct idio_16_gpio *idio16gpio; | 198 | struct idio_16_gpio *idio16gpio; |
192 | const unsigned base = idio_16_base; | ||
193 | const unsigned extent = 8; | ||
194 | const char *const name = dev_name(dev); | 199 | const char *const name = dev_name(dev); |
195 | int err; | 200 | int err; |
196 | const unsigned irq = idio_16_irq; | ||
197 | 201 | ||
198 | idio16gpio = devm_kzalloc(dev, sizeof(*idio16gpio), GFP_KERNEL); | 202 | idio16gpio = devm_kzalloc(dev, sizeof(*idio16gpio), GFP_KERNEL); |
199 | if (!idio16gpio) | 203 | if (!idio16gpio) |
200 | return -ENOMEM; | 204 | return -ENOMEM; |
201 | 205 | ||
202 | if (!devm_request_region(dev, base, extent, name)) { | 206 | if (!devm_request_region(dev, base[id], IDIO_16_EXTENT, name)) { |
203 | dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", | 207 | dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", |
204 | base, base + extent); | 208 | base[id], base[id] + IDIO_16_EXTENT); |
205 | return -EBUSY; | 209 | return -EBUSY; |
206 | } | 210 | } |
207 | 211 | ||
@@ -215,8 +219,8 @@ static int __init idio_16_probe(struct platform_device *pdev) | |||
215 | idio16gpio->chip.direction_output = idio_16_gpio_direction_output; | 219 | idio16gpio->chip.direction_output = idio_16_gpio_direction_output; |
216 | idio16gpio->chip.get = idio_16_gpio_get; | 220 | idio16gpio->chip.get = idio_16_gpio_get; |
217 | idio16gpio->chip.set = idio_16_gpio_set; | 221 | idio16gpio->chip.set = idio_16_gpio_set; |
218 | idio16gpio->base = base; | 222 | idio16gpio->base = base[id]; |
219 | idio16gpio->irq = irq; | 223 | idio16gpio->irq = irq[id]; |
220 | idio16gpio->out_state = 0xFFFF; | 224 | idio16gpio->out_state = 0xFFFF; |
221 | 225 | ||
222 | spin_lock_init(&idio16gpio->lock); | 226 | spin_lock_init(&idio16gpio->lock); |
@@ -230,8 +234,8 @@ static int __init idio_16_probe(struct platform_device *pdev) | |||
230 | } | 234 | } |
231 | 235 | ||
232 | /* Disable IRQ by default */ | 236 | /* Disable IRQ by default */ |
233 | outb(0, base + 2); | 237 | outb(0, base[id] + 2); |
234 | outb(0, base + 1); | 238 | outb(0, base[id] + 1); |
235 | 239 | ||
236 | err = gpiochip_irqchip_add(&idio16gpio->chip, &idio_16_irqchip, 0, | 240 | err = gpiochip_irqchip_add(&idio16gpio->chip, &idio_16_irqchip, 0, |
237 | handle_edge_irq, IRQ_TYPE_NONE); | 241 | handle_edge_irq, IRQ_TYPE_NONE); |
@@ -240,7 +244,7 @@ static int __init idio_16_probe(struct platform_device *pdev) | |||
240 | goto err_gpiochip_remove; | 244 | goto err_gpiochip_remove; |
241 | } | 245 | } |
242 | 246 | ||
243 | err = request_irq(irq, idio_16_irq_handler, 0, name, idio16gpio); | 247 | err = request_irq(irq[id], idio_16_irq_handler, 0, name, idio16gpio); |
244 | if (err) { | 248 | if (err) { |
245 | dev_err(dev, "IRQ handler registering failed (%d)\n", err); | 249 | dev_err(dev, "IRQ handler registering failed (%d)\n", err); |
246 | goto err_gpiochip_remove; | 250 | goto err_gpiochip_remove; |
@@ -253,9 +257,9 @@ err_gpiochip_remove: | |||
253 | return err; | 257 | return err; |
254 | } | 258 | } |
255 | 259 | ||
256 | static int idio_16_remove(struct platform_device *pdev) | 260 | static int idio_16_remove(struct device *dev, unsigned int id) |
257 | { | 261 | { |
258 | struct idio_16_gpio *const idio16gpio = platform_get_drvdata(pdev); | 262 | struct idio_16_gpio *const idio16gpio = dev_get_drvdata(dev); |
259 | 263 | ||
260 | free_irq(idio16gpio->irq, idio16gpio); | 264 | free_irq(idio16gpio->irq, idio16gpio); |
261 | gpiochip_remove(&idio16gpio->chip); | 265 | gpiochip_remove(&idio16gpio->chip); |
@@ -263,48 +267,15 @@ static int idio_16_remove(struct platform_device *pdev) | |||
263 | return 0; | 267 | return 0; |
264 | } | 268 | } |
265 | 269 | ||
266 | static struct platform_device *idio_16_device; | 270 | static struct isa_driver idio_16_driver = { |
267 | 271 | .probe = idio_16_probe, | |
268 | static struct platform_driver idio_16_driver = { | ||
269 | .driver = { | 272 | .driver = { |
270 | .name = "104-idio-16" | 273 | .name = "104-idio-16" |
271 | }, | 274 | }, |
272 | .remove = idio_16_remove | 275 | .remove = idio_16_remove |
273 | }; | 276 | }; |
274 | 277 | ||
275 | static void __exit idio_16_exit(void) | 278 | module_isa_driver(idio_16_driver, num_idio_16); |
276 | { | ||
277 | platform_device_unregister(idio_16_device); | ||
278 | platform_driver_unregister(&idio_16_driver); | ||
279 | } | ||
280 | |||
281 | static int __init idio_16_init(void) | ||
282 | { | ||
283 | int err; | ||
284 | |||
285 | idio_16_device = platform_device_alloc(idio_16_driver.driver.name, -1); | ||
286 | if (!idio_16_device) | ||
287 | return -ENOMEM; | ||
288 | |||
289 | err = platform_device_add(idio_16_device); | ||
290 | if (err) | ||
291 | goto err_platform_device; | ||
292 | |||
293 | err = platform_driver_probe(&idio_16_driver, idio_16_probe); | ||
294 | if (err) | ||
295 | goto err_platform_driver; | ||
296 | |||
297 | return 0; | ||
298 | |||
299 | err_platform_driver: | ||
300 | platform_device_del(idio_16_device); | ||
301 | err_platform_device: | ||
302 | platform_device_put(idio_16_device); | ||
303 | return err; | ||
304 | } | ||
305 | |||
306 | module_init(idio_16_init); | ||
307 | module_exit(idio_16_exit); | ||
308 | 279 | ||
309 | MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>"); | 280 | MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>"); |
310 | MODULE_DESCRIPTION("ACCES 104-IDIO-16 GPIO driver"); | 281 | MODULE_DESCRIPTION("ACCES 104-IDIO-16 GPIO driver"); |
diff --git a/drivers/gpio/gpio-ws16c48.c b/drivers/gpio/gpio-ws16c48.c index 51f41e8fd21e..eaa71d440ccf 100644 --- a/drivers/gpio/gpio-ws16c48.c +++ b/drivers/gpio/gpio-ws16c48.c | |||
@@ -19,18 +19,23 @@ | |||
19 | #include <linux/ioport.h> | 19 | #include <linux/ioport.h> |
20 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
21 | #include <linux/irqdesc.h> | 21 | #include <linux/irqdesc.h> |
22 | #include <linux/isa.h> | ||
22 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
23 | #include <linux/module.h> | 24 | #include <linux/module.h> |
24 | #include <linux/moduleparam.h> | 25 | #include <linux/moduleparam.h> |
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/spinlock.h> | 26 | #include <linux/spinlock.h> |
27 | 27 | ||
28 | static unsigned ws16c48_base; | 28 | #define WS16C48_EXTENT 16 |
29 | module_param(ws16c48_base, uint, 0); | 29 | #define MAX_NUM_WS16C48 max_num_isa_dev(WS16C48_EXTENT) |
30 | MODULE_PARM_DESC(ws16c48_base, "WinSystems WS16C48 base address"); | 30 | |
31 | static unsigned ws16c48_irq; | 31 | static unsigned int base[MAX_NUM_WS16C48]; |
32 | module_param(ws16c48_irq, uint, 0); | 32 | static unsigned int num_ws16c48; |
33 | MODULE_PARM_DESC(ws16c48_irq, "WinSystems WS16C48 interrupt line number"); | 33 | module_param_array(base, uint, &num_ws16c48, 0); |
34 | MODULE_PARM_DESC(base, "WinSystems WS16C48 base addresses"); | ||
35 | |||
36 | static unsigned int irq[MAX_NUM_WS16C48]; | ||
37 | module_param_array(irq, uint, NULL, 0); | ||
38 | MODULE_PARM_DESC(irq, "WinSystems WS16C48 interrupt line numbers"); | ||
34 | 39 | ||
35 | /** | 40 | /** |
36 | * struct ws16c48_gpio - GPIO device private data structure | 41 | * struct ws16c48_gpio - GPIO device private data structure |
@@ -298,23 +303,19 @@ static irqreturn_t ws16c48_irq_handler(int irq, void *dev_id) | |||
298 | return IRQ_HANDLED; | 303 | return IRQ_HANDLED; |
299 | } | 304 | } |
300 | 305 | ||
301 | static int __init ws16c48_probe(struct platform_device *pdev) | 306 | static int ws16c48_probe(struct device *dev, unsigned int id) |
302 | { | 307 | { |
303 | struct device *dev = &pdev->dev; | ||
304 | struct ws16c48_gpio *ws16c48gpio; | 308 | struct ws16c48_gpio *ws16c48gpio; |
305 | const unsigned base = ws16c48_base; | ||
306 | const unsigned extent = 16; | ||
307 | const char *const name = dev_name(dev); | 309 | const char *const name = dev_name(dev); |
308 | int err; | 310 | int err; |
309 | const unsigned irq = ws16c48_irq; | ||
310 | 311 | ||
311 | ws16c48gpio = devm_kzalloc(dev, sizeof(*ws16c48gpio), GFP_KERNEL); | 312 | ws16c48gpio = devm_kzalloc(dev, sizeof(*ws16c48gpio), GFP_KERNEL); |
312 | if (!ws16c48gpio) | 313 | if (!ws16c48gpio) |
313 | return -ENOMEM; | 314 | return -ENOMEM; |
314 | 315 | ||
315 | if (!devm_request_region(dev, base, extent, name)) { | 316 | if (!devm_request_region(dev, base[id], WS16C48_EXTENT, name)) { |
316 | dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", | 317 | dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", |
317 | base, base + extent); | 318 | base[id], base[id] + WS16C48_EXTENT); |
318 | return -EBUSY; | 319 | return -EBUSY; |
319 | } | 320 | } |
320 | 321 | ||
@@ -328,8 +329,8 @@ static int __init ws16c48_probe(struct platform_device *pdev) | |||
328 | ws16c48gpio->chip.direction_output = ws16c48_gpio_direction_output; | 329 | ws16c48gpio->chip.direction_output = ws16c48_gpio_direction_output; |
329 | ws16c48gpio->chip.get = ws16c48_gpio_get; | 330 | ws16c48gpio->chip.get = ws16c48_gpio_get; |
330 | ws16c48gpio->chip.set = ws16c48_gpio_set; | 331 | ws16c48gpio->chip.set = ws16c48_gpio_set; |
331 | ws16c48gpio->base = base; | 332 | ws16c48gpio->base = base[id]; |
332 | ws16c48gpio->irq = irq; | 333 | ws16c48gpio->irq = irq[id]; |
333 | 334 | ||
334 | spin_lock_init(&ws16c48gpio->lock); | 335 | spin_lock_init(&ws16c48gpio->lock); |
335 | 336 | ||
@@ -342,11 +343,11 @@ static int __init ws16c48_probe(struct platform_device *pdev) | |||
342 | } | 343 | } |
343 | 344 | ||
344 | /* Disable IRQ by default */ | 345 | /* Disable IRQ by default */ |
345 | outb(0x80, base + 7); | 346 | outb(0x80, base[id] + 7); |
346 | outb(0, base + 8); | 347 | outb(0, base[id] + 8); |
347 | outb(0, base + 9); | 348 | outb(0, base[id] + 9); |
348 | outb(0, base + 10); | 349 | outb(0, base[id] + 10); |
349 | outb(0xC0, base + 7); | 350 | outb(0xC0, base[id] + 7); |
350 | 351 | ||
351 | err = gpiochip_irqchip_add(&ws16c48gpio->chip, &ws16c48_irqchip, 0, | 352 | err = gpiochip_irqchip_add(&ws16c48gpio->chip, &ws16c48_irqchip, 0, |
352 | handle_edge_irq, IRQ_TYPE_NONE); | 353 | handle_edge_irq, IRQ_TYPE_NONE); |
@@ -355,7 +356,7 @@ static int __init ws16c48_probe(struct platform_device *pdev) | |||
355 | goto err_gpiochip_remove; | 356 | goto err_gpiochip_remove; |
356 | } | 357 | } |
357 | 358 | ||
358 | err = request_irq(irq, ws16c48_irq_handler, IRQF_SHARED, name, | 359 | err = request_irq(irq[id], ws16c48_irq_handler, IRQF_SHARED, name, |
359 | ws16c48gpio); | 360 | ws16c48gpio); |
360 | if (err) { | 361 | if (err) { |
361 | dev_err(dev, "IRQ handler registering failed (%d)\n", err); | 362 | dev_err(dev, "IRQ handler registering failed (%d)\n", err); |
@@ -369,9 +370,9 @@ err_gpiochip_remove: | |||
369 | return err; | 370 | return err; |
370 | } | 371 | } |
371 | 372 | ||
372 | static int ws16c48_remove(struct platform_device *pdev) | 373 | static int ws16c48_remove(struct device *dev, unsigned int id) |
373 | { | 374 | { |
374 | struct ws16c48_gpio *const ws16c48gpio = platform_get_drvdata(pdev); | 375 | struct ws16c48_gpio *const ws16c48gpio = dev_get_drvdata(dev); |
375 | 376 | ||
376 | free_irq(ws16c48gpio->irq, ws16c48gpio); | 377 | free_irq(ws16c48gpio->irq, ws16c48gpio); |
377 | gpiochip_remove(&ws16c48gpio->chip); | 378 | gpiochip_remove(&ws16c48gpio->chip); |
@@ -379,48 +380,15 @@ static int ws16c48_remove(struct platform_device *pdev) | |||
379 | return 0; | 380 | return 0; |
380 | } | 381 | } |
381 | 382 | ||
382 | static struct platform_device *ws16c48_device; | 383 | static struct isa_driver ws16c48_driver = { |
383 | 384 | .probe = ws16c48_probe, | |
384 | static struct platform_driver ws16c48_driver = { | ||
385 | .driver = { | 385 | .driver = { |
386 | .name = "ws16c48" | 386 | .name = "ws16c48" |
387 | }, | 387 | }, |
388 | .remove = ws16c48_remove | 388 | .remove = ws16c48_remove |
389 | }; | 389 | }; |
390 | 390 | ||
391 | static void __exit ws16c48_exit(void) | 391 | module_isa_driver(ws16c48_driver, num_ws16c48); |
392 | { | ||
393 | platform_device_unregister(ws16c48_device); | ||
394 | platform_driver_unregister(&ws16c48_driver); | ||
395 | } | ||
396 | |||
397 | static int __init ws16c48_init(void) | ||
398 | { | ||
399 | int err; | ||
400 | |||
401 | ws16c48_device = platform_device_alloc(ws16c48_driver.driver.name, -1); | ||
402 | if (!ws16c48_device) | ||
403 | return -ENOMEM; | ||
404 | |||
405 | err = platform_device_add(ws16c48_device); | ||
406 | if (err) | ||
407 | goto err_platform_device; | ||
408 | |||
409 | err = platform_driver_probe(&ws16c48_driver, ws16c48_probe); | ||
410 | if (err) | ||
411 | goto err_platform_driver; | ||
412 | |||
413 | return 0; | ||
414 | |||
415 | err_platform_driver: | ||
416 | platform_device_del(ws16c48_device); | ||
417 | err_platform_device: | ||
418 | platform_device_put(ws16c48_device); | ||
419 | return err; | ||
420 | } | ||
421 | |||
422 | module_init(ws16c48_init); | ||
423 | module_exit(ws16c48_exit); | ||
424 | 392 | ||
425 | MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>"); | 393 | MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>"); |
426 | MODULE_DESCRIPTION("WinSystems WS16C48 GPIO driver"); | 394 | MODULE_DESCRIPTION("WinSystems WS16C48 GPIO driver"); |
diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig index a995139f907c..6abcfb8597d9 100644 --- a/drivers/iio/dac/Kconfig +++ b/drivers/iio/dac/Kconfig | |||
@@ -210,7 +210,7 @@ config MCP4922 | |||
210 | 210 | ||
211 | config STX104 | 211 | config STX104 |
212 | tristate "Apex Embedded Systems STX104 DAC driver" | 212 | tristate "Apex Embedded Systems STX104 DAC driver" |
213 | depends on ISA | 213 | depends on X86 && ISA |
214 | help | 214 | help |
215 | Say yes here to build support for the 2-channel DAC on the Apex | 215 | Say yes here to build support for the 2-channel DAC on the Apex |
216 | Embedded Systems STX104 integrated analog PC/104 card. The base port | 216 | Embedded Systems STX104 integrated analog PC/104 card. The base port |
diff --git a/drivers/iio/dac/stx104.c b/drivers/iio/dac/stx104.c index 174f4b75ceed..27941220872f 100644 --- a/drivers/iio/dac/stx104.c +++ b/drivers/iio/dac/stx104.c | |||
@@ -33,16 +33,9 @@ | |||
33 | } | 33 | } |
34 | 34 | ||
35 | #define STX104_EXTENT 16 | 35 | #define STX104_EXTENT 16 |
36 | /** | ||
37 | * The highest base address possible for an ISA device is 0x3FF; this results in | ||
38 | * 1024 possible base addresses. Dividing the number of possible base addresses | ||
39 | * by the address extent taken by each device results in the maximum number of | ||
40 | * devices on a system. | ||
41 | */ | ||
42 | #define MAX_NUM_STX104 (1024 / STX104_EXTENT) | ||
43 | 36 | ||
44 | static unsigned base[MAX_NUM_STX104]; | 37 | static unsigned int base[max_num_isa_dev(STX104_EXTENT)]; |
45 | static unsigned num_stx104; | 38 | static unsigned int num_stx104; |
46 | module_param_array(base, uint, &num_stx104, 0); | 39 | module_param_array(base, uint, &num_stx104, 0); |
47 | MODULE_PARM_DESC(base, "Apex Embedded Systems STX104 base addresses"); | 40 | MODULE_PARM_DESC(base, "Apex Embedded Systems STX104 base addresses"); |
48 | 41 | ||
@@ -134,18 +127,7 @@ static struct isa_driver stx104_driver = { | |||
134 | } | 127 | } |
135 | }; | 128 | }; |
136 | 129 | ||
137 | static void __exit stx104_exit(void) | 130 | module_isa_driver(stx104_driver, num_stx104); |
138 | { | ||
139 | isa_unregister_driver(&stx104_driver); | ||
140 | } | ||
141 | |||
142 | static int __init stx104_init(void) | ||
143 | { | ||
144 | return isa_register_driver(&stx104_driver, num_stx104); | ||
145 | } | ||
146 | |||
147 | module_init(stx104_init); | ||
148 | module_exit(stx104_exit); | ||
149 | 131 | ||
150 | MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>"); | 132 | MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>"); |
151 | MODULE_DESCRIPTION("Apex Embedded Systems STX104 DAC driver"); | 133 | MODULE_DESCRIPTION("Apex Embedded Systems STX104 DAC driver"); |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c index 1ece19dcd9ac..e1b6b2c665eb 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c | |||
@@ -71,7 +71,7 @@ | |||
71 | #include "iwl-csr.h" | 71 | #include "iwl-csr.h" |
72 | 72 | ||
73 | static ssize_t iwl_mvm_read_coredump(char *buffer, loff_t offset, size_t count, | 73 | static ssize_t iwl_mvm_read_coredump(char *buffer, loff_t offset, size_t count, |
74 | const void *data, size_t datalen) | 74 | void *data, size_t datalen) |
75 | { | 75 | { |
76 | const struct iwl_mvm_dump_ptrs *dump_ptrs = data; | 76 | const struct iwl_mvm_dump_ptrs *dump_ptrs = data; |
77 | ssize_t bytes_read; | 77 | ssize_t bytes_read; |
@@ -104,7 +104,7 @@ static ssize_t iwl_mvm_read_coredump(char *buffer, loff_t offset, size_t count, | |||
104 | return bytes_read + bytes_read_trans; | 104 | return bytes_read + bytes_read_trans; |
105 | } | 105 | } |
106 | 106 | ||
107 | static void iwl_mvm_free_coredump(const void *data) | 107 | static void iwl_mvm_free_coredump(void *data) |
108 | { | 108 | { |
109 | const struct iwl_mvm_dump_ptrs *fw_error_dump = data; | 109 | const struct iwl_mvm_dump_ptrs *fw_error_dump = data; |
110 | 110 | ||
diff --git a/drivers/pnp/pnpbios/Kconfig b/drivers/pnp/pnpbios/Kconfig index 50c3dd065e03..a786086b2ec7 100644 --- a/drivers/pnp/pnpbios/Kconfig +++ b/drivers/pnp/pnpbios/Kconfig | |||
@@ -3,7 +3,7 @@ | |||
3 | # | 3 | # |
4 | config PNPBIOS | 4 | config PNPBIOS |
5 | bool "Plug and Play BIOS support" | 5 | bool "Plug and Play BIOS support" |
6 | depends on ISA && X86 | 6 | depends on ISA && X86_32 |
7 | default n | 7 | default n |
8 | ---help--- | 8 | ---help--- |
9 | Linux uses the PNPBIOS as defined in "Plug and Play BIOS | 9 | Linux uses the PNPBIOS as defined in "Plug and Play BIOS |
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 9c4143112e6c..5b45e277697b 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig | |||
@@ -738,7 +738,7 @@ config ALIM7101_WDT | |||
738 | 738 | ||
739 | config EBC_C384_WDT | 739 | config EBC_C384_WDT |
740 | tristate "WinSystems EBC-C384 Watchdog Timer" | 740 | tristate "WinSystems EBC-C384 Watchdog Timer" |
741 | depends on X86 | 741 | depends on X86 && ISA |
742 | select WATCHDOG_CORE | 742 | select WATCHDOG_CORE |
743 | help | 743 | help |
744 | Enables watchdog timer support for the watchdog timer on the | 744 | Enables watchdog timer support for the watchdog timer on the |
diff --git a/drivers/watchdog/ebc-c384_wdt.c b/drivers/watchdog/ebc-c384_wdt.c index 77fda0b4b90e..4b849b8e37c2 100644 --- a/drivers/watchdog/ebc-c384_wdt.c +++ b/drivers/watchdog/ebc-c384_wdt.c | |||
@@ -16,10 +16,10 @@ | |||
16 | #include <linux/errno.h> | 16 | #include <linux/errno.h> |
17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
18 | #include <linux/ioport.h> | 18 | #include <linux/ioport.h> |
19 | #include <linux/isa.h> | ||
19 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
20 | #include <linux/module.h> | 21 | #include <linux/module.h> |
21 | #include <linux/moduleparam.h> | 22 | #include <linux/moduleparam.h> |
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/types.h> | 23 | #include <linux/types.h> |
24 | #include <linux/watchdog.h> | 24 | #include <linux/watchdog.h> |
25 | 25 | ||
@@ -95,9 +95,8 @@ static const struct watchdog_info ebc_c384_wdt_info = { | |||
95 | .identity = MODULE_NAME | 95 | .identity = MODULE_NAME |
96 | }; | 96 | }; |
97 | 97 | ||
98 | static int __init ebc_c384_wdt_probe(struct platform_device *pdev) | 98 | static int ebc_c384_wdt_probe(struct device *dev, unsigned int id) |
99 | { | 99 | { |
100 | struct device *dev = &pdev->dev; | ||
101 | struct watchdog_device *wdd; | 100 | struct watchdog_device *wdd; |
102 | 101 | ||
103 | if (!devm_request_region(dev, BASE_ADDR, ADDR_EXTENT, dev_name(dev))) { | 102 | if (!devm_request_region(dev, BASE_ADDR, ADDR_EXTENT, dev_name(dev))) { |
@@ -122,61 +121,39 @@ static int __init ebc_c384_wdt_probe(struct platform_device *pdev) | |||
122 | dev_warn(dev, "Invalid timeout (%u seconds), using default (%u seconds)\n", | 121 | dev_warn(dev, "Invalid timeout (%u seconds), using default (%u seconds)\n", |
123 | timeout, WATCHDOG_TIMEOUT); | 122 | timeout, WATCHDOG_TIMEOUT); |
124 | 123 | ||
125 | platform_set_drvdata(pdev, wdd); | 124 | dev_set_drvdata(dev, wdd); |
126 | 125 | ||
127 | return watchdog_register_device(wdd); | 126 | return watchdog_register_device(wdd); |
128 | } | 127 | } |
129 | 128 | ||
130 | static int ebc_c384_wdt_remove(struct platform_device *pdev) | 129 | static int ebc_c384_wdt_remove(struct device *dev, unsigned int id) |
131 | { | 130 | { |
132 | struct watchdog_device *wdd = platform_get_drvdata(pdev); | 131 | struct watchdog_device *wdd = dev_get_drvdata(dev); |
133 | 132 | ||
134 | watchdog_unregister_device(wdd); | 133 | watchdog_unregister_device(wdd); |
135 | 134 | ||
136 | return 0; | 135 | return 0; |
137 | } | 136 | } |
138 | 137 | ||
139 | static struct platform_driver ebc_c384_wdt_driver = { | 138 | static struct isa_driver ebc_c384_wdt_driver = { |
139 | .probe = ebc_c384_wdt_probe, | ||
140 | .driver = { | 140 | .driver = { |
141 | .name = MODULE_NAME | 141 | .name = MODULE_NAME |
142 | }, | 142 | }, |
143 | .remove = ebc_c384_wdt_remove | 143 | .remove = ebc_c384_wdt_remove |
144 | }; | 144 | }; |
145 | 145 | ||
146 | static struct platform_device *ebc_c384_wdt_device; | ||
147 | |||
148 | static int __init ebc_c384_wdt_init(void) | 146 | static int __init ebc_c384_wdt_init(void) |
149 | { | 147 | { |
150 | int err; | ||
151 | |||
152 | if (!dmi_match(DMI_BOARD_NAME, "EBC-C384 SBC")) | 148 | if (!dmi_match(DMI_BOARD_NAME, "EBC-C384 SBC")) |
153 | return -ENODEV; | 149 | return -ENODEV; |
154 | 150 | ||
155 | ebc_c384_wdt_device = platform_device_alloc(MODULE_NAME, -1); | 151 | return isa_register_driver(&ebc_c384_wdt_driver, 1); |
156 | if (!ebc_c384_wdt_device) | ||
157 | return -ENOMEM; | ||
158 | |||
159 | err = platform_device_add(ebc_c384_wdt_device); | ||
160 | if (err) | ||
161 | goto err_platform_device; | ||
162 | |||
163 | err = platform_driver_probe(&ebc_c384_wdt_driver, ebc_c384_wdt_probe); | ||
164 | if (err) | ||
165 | goto err_platform_driver; | ||
166 | |||
167 | return 0; | ||
168 | |||
169 | err_platform_driver: | ||
170 | platform_device_del(ebc_c384_wdt_device); | ||
171 | err_platform_device: | ||
172 | platform_device_put(ebc_c384_wdt_device); | ||
173 | return err; | ||
174 | } | 152 | } |
175 | 153 | ||
176 | static void __exit ebc_c384_wdt_exit(void) | 154 | static void __exit ebc_c384_wdt_exit(void) |
177 | { | 155 | { |
178 | platform_device_unregister(ebc_c384_wdt_device); | 156 | isa_unregister_driver(&ebc_c384_wdt_driver); |
179 | platform_driver_unregister(&ebc_c384_wdt_driver); | ||
180 | } | 157 | } |
181 | 158 | ||
182 | module_init(ebc_c384_wdt_init); | 159 | module_init(ebc_c384_wdt_init); |
@@ -185,4 +162,4 @@ module_exit(ebc_c384_wdt_exit); | |||
185 | MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>"); | 162 | MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>"); |
186 | MODULE_DESCRIPTION("WinSystems EBC-C384 watchdog timer driver"); | 163 | MODULE_DESCRIPTION("WinSystems EBC-C384 watchdog timer driver"); |
187 | MODULE_LICENSE("GPL v2"); | 164 | MODULE_LICENSE("GPL v2"); |
188 | MODULE_ALIAS("platform:" MODULE_NAME); | 165 | MODULE_ALIAS("isa:" MODULE_NAME); |
diff --git a/fs/char_dev.c b/fs/char_dev.c index 24b142569ca9..687471dc04a0 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c | |||
@@ -91,6 +91,10 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor, | |||
91 | break; | 91 | break; |
92 | } | 92 | } |
93 | 93 | ||
94 | if (i < CHRDEV_MAJOR_DYN_END) | ||
95 | pr_warn("CHRDEV \"%s\" major number %d goes below the dynamic allocation range", | ||
96 | name, i); | ||
97 | |||
94 | if (i == 0) { | 98 | if (i == 0) { |
95 | ret = -EBUSY; | 99 | ret = -EBUSY; |
96 | goto out; | 100 | goto out; |
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index d2ba12e23ed9..9c1c9a01b7e5 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c | |||
@@ -22,6 +22,12 @@ | |||
22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | #include <linux/atomic.h> | 23 | #include <linux/atomic.h> |
24 | #include <linux/device.h> | 24 | #include <linux/device.h> |
25 | #include <linux/srcu.h> | ||
26 | #include <asm/poll.h> | ||
27 | |||
28 | #include "internal.h" | ||
29 | |||
30 | struct poll_table_struct; | ||
25 | 31 | ||
26 | static ssize_t default_read_file(struct file *file, char __user *buf, | 32 | static ssize_t default_read_file(struct file *file, char __user *buf, |
27 | size_t count, loff_t *ppos) | 33 | size_t count, loff_t *ppos) |
@@ -35,27 +41,293 @@ static ssize_t default_write_file(struct file *file, const char __user *buf, | |||
35 | return count; | 41 | return count; |
36 | } | 42 | } |
37 | 43 | ||
38 | const struct file_operations debugfs_file_operations = { | 44 | const struct file_operations debugfs_noop_file_operations = { |
39 | .read = default_read_file, | 45 | .read = default_read_file, |
40 | .write = default_write_file, | 46 | .write = default_write_file, |
41 | .open = simple_open, | 47 | .open = simple_open, |
42 | .llseek = noop_llseek, | 48 | .llseek = noop_llseek, |
43 | }; | 49 | }; |
44 | 50 | ||
45 | static struct dentry *debugfs_create_mode(const char *name, umode_t mode, | 51 | /** |
46 | struct dentry *parent, void *value, | 52 | * debugfs_use_file_start - mark the beginning of file data access |
47 | const struct file_operations *fops, | 53 | * @dentry: the dentry object whose data is being accessed. |
48 | const struct file_operations *fops_ro, | 54 | * @srcu_idx: a pointer to some memory to store a SRCU index in. |
49 | const struct file_operations *fops_wo) | 55 | * |
56 | * Up to a matching call to debugfs_use_file_finish(), any | ||
57 | * successive call into the file removing functions debugfs_remove() | ||
58 | * and debugfs_remove_recursive() will block. Since associated private | ||
59 | * file data may only get freed after a successful return of any of | ||
60 | * the removal functions, you may safely access it after a successful | ||
61 | * call to debugfs_use_file_start() without worrying about | ||
62 | * lifetime issues. | ||
63 | * | ||
64 | * If -%EIO is returned, the file has already been removed and thus, | ||
65 | * it is not safe to access any of its data. If, on the other hand, | ||
66 | * it is allowed to access the file data, zero is returned. | ||
67 | * | ||
68 | * Regardless of the return code, any call to | ||
69 | * debugfs_use_file_start() must be followed by a matching call | ||
70 | * to debugfs_use_file_finish(). | ||
71 | */ | ||
72 | int debugfs_use_file_start(const struct dentry *dentry, int *srcu_idx) | ||
73 | __acquires(&debugfs_srcu) | ||
74 | { | ||
75 | *srcu_idx = srcu_read_lock(&debugfs_srcu); | ||
76 | barrier(); | ||
77 | if (d_unlinked(dentry)) | ||
78 | return -EIO; | ||
79 | return 0; | ||
80 | } | ||
81 | EXPORT_SYMBOL_GPL(debugfs_use_file_start); | ||
82 | |||
83 | /** | ||
84 | * debugfs_use_file_finish - mark the end of file data access | ||
85 | * @srcu_idx: the SRCU index "created" by a former call to | ||
86 | * debugfs_use_file_start(). | ||
87 | * | ||
88 | * Allow any ongoing concurrent call into debugfs_remove() or | ||
89 | * debugfs_remove_recursive() blocked by a former call to | ||
90 | * debugfs_use_file_start() to proceed and return to its caller. | ||
91 | */ | ||
92 | void debugfs_use_file_finish(int srcu_idx) __releases(&debugfs_srcu) | ||
93 | { | ||
94 | srcu_read_unlock(&debugfs_srcu, srcu_idx); | ||
95 | } | ||
96 | EXPORT_SYMBOL_GPL(debugfs_use_file_finish); | ||
97 | |||
98 | #define F_DENTRY(filp) ((filp)->f_path.dentry) | ||
99 | |||
100 | #define REAL_FOPS_DEREF(dentry) \ | ||
101 | ((const struct file_operations *)(dentry)->d_fsdata) | ||
102 | |||
103 | static int open_proxy_open(struct inode *inode, struct file *filp) | ||
104 | { | ||
105 | const struct dentry *dentry = F_DENTRY(filp); | ||
106 | const struct file_operations *real_fops = NULL; | ||
107 | int srcu_idx, r; | ||
108 | |||
109 | r = debugfs_use_file_start(dentry, &srcu_idx); | ||
110 | if (r) { | ||
111 | r = -ENOENT; | ||
112 | goto out; | ||
113 | } | ||
114 | |||
115 | real_fops = REAL_FOPS_DEREF(dentry); | ||
116 | real_fops = fops_get(real_fops); | ||
117 | if (!real_fops) { | ||
118 | /* Huh? Module did not clean up after itself at exit? */ | ||
119 | WARN(1, "debugfs file owner did not clean up at exit: %pd", | ||
120 | dentry); | ||
121 | r = -ENXIO; | ||
122 | goto out; | ||
123 | } | ||
124 | replace_fops(filp, real_fops); | ||
125 | |||
126 | if (real_fops->open) | ||
127 | r = real_fops->open(inode, filp); | ||
128 | |||
129 | out: | ||
130 | fops_put(real_fops); | ||
131 | debugfs_use_file_finish(srcu_idx); | ||
132 | return r; | ||
133 | } | ||
134 | |||
135 | const struct file_operations debugfs_open_proxy_file_operations = { | ||
136 | .open = open_proxy_open, | ||
137 | }; | ||
138 | |||
139 | #define PROTO(args...) args | ||
140 | #define ARGS(args...) args | ||
141 | |||
142 | #define FULL_PROXY_FUNC(name, ret_type, filp, proto, args) \ | ||
143 | static ret_type full_proxy_ ## name(proto) \ | ||
144 | { \ | ||
145 | const struct dentry *dentry = F_DENTRY(filp); \ | ||
146 | const struct file_operations *real_fops = \ | ||
147 | REAL_FOPS_DEREF(dentry); \ | ||
148 | int srcu_idx; \ | ||
149 | ret_type r; \ | ||
150 | \ | ||
151 | r = debugfs_use_file_start(dentry, &srcu_idx); \ | ||
152 | if (likely(!r)) \ | ||
153 | r = real_fops->name(args); \ | ||
154 | debugfs_use_file_finish(srcu_idx); \ | ||
155 | return r; \ | ||
156 | } | ||
157 | |||
158 | FULL_PROXY_FUNC(llseek, loff_t, filp, | ||
159 | PROTO(struct file *filp, loff_t offset, int whence), | ||
160 | ARGS(filp, offset, whence)); | ||
161 | |||
162 | FULL_PROXY_FUNC(read, ssize_t, filp, | ||
163 | PROTO(struct file *filp, char __user *buf, size_t size, | ||
164 | loff_t *ppos), | ||
165 | ARGS(filp, buf, size, ppos)); | ||
166 | |||
167 | FULL_PROXY_FUNC(write, ssize_t, filp, | ||
168 | PROTO(struct file *filp, const char __user *buf, size_t size, | ||
169 | loff_t *ppos), | ||
170 | ARGS(filp, buf, size, ppos)); | ||
171 | |||
172 | FULL_PROXY_FUNC(unlocked_ioctl, long, filp, | ||
173 | PROTO(struct file *filp, unsigned int cmd, unsigned long arg), | ||
174 | ARGS(filp, cmd, arg)); | ||
175 | |||
176 | static unsigned int full_proxy_poll(struct file *filp, | ||
177 | struct poll_table_struct *wait) | ||
178 | { | ||
179 | const struct dentry *dentry = F_DENTRY(filp); | ||
180 | const struct file_operations *real_fops = REAL_FOPS_DEREF(dentry); | ||
181 | int srcu_idx; | ||
182 | unsigned int r = 0; | ||
183 | |||
184 | if (debugfs_use_file_start(dentry, &srcu_idx)) { | ||
185 | debugfs_use_file_finish(srcu_idx); | ||
186 | return POLLHUP; | ||
187 | } | ||
188 | |||
189 | r = real_fops->poll(filp, wait); | ||
190 | debugfs_use_file_finish(srcu_idx); | ||
191 | return r; | ||
192 | } | ||
193 | |||
194 | static int full_proxy_release(struct inode *inode, struct file *filp) | ||
195 | { | ||
196 | const struct dentry *dentry = F_DENTRY(filp); | ||
197 | const struct file_operations *real_fops = REAL_FOPS_DEREF(dentry); | ||
198 | const struct file_operations *proxy_fops = filp->f_op; | ||
199 | int r = 0; | ||
200 | |||
201 | /* | ||
202 | * We must not protect this against removal races here: the | ||
203 | * original releaser should be called unconditionally in order | ||
204 | * not to leak any resources. Releasers must not assume that | ||
205 | * ->i_private is still being meaningful here. | ||
206 | */ | ||
207 | if (real_fops->release) | ||
208 | r = real_fops->release(inode, filp); | ||
209 | |||
210 | replace_fops(filp, d_inode(dentry)->i_fop); | ||
211 | kfree((void *)proxy_fops); | ||
212 | fops_put(real_fops); | ||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | static void __full_proxy_fops_init(struct file_operations *proxy_fops, | ||
217 | const struct file_operations *real_fops) | ||
218 | { | ||
219 | proxy_fops->release = full_proxy_release; | ||
220 | if (real_fops->llseek) | ||
221 | proxy_fops->llseek = full_proxy_llseek; | ||
222 | if (real_fops->read) | ||
223 | proxy_fops->read = full_proxy_read; | ||
224 | if (real_fops->write) | ||
225 | proxy_fops->write = full_proxy_write; | ||
226 | if (real_fops->poll) | ||
227 | proxy_fops->poll = full_proxy_poll; | ||
228 | if (real_fops->unlocked_ioctl) | ||
229 | proxy_fops->unlocked_ioctl = full_proxy_unlocked_ioctl; | ||
230 | } | ||
231 | |||
232 | static int full_proxy_open(struct inode *inode, struct file *filp) | ||
233 | { | ||
234 | const struct dentry *dentry = F_DENTRY(filp); | ||
235 | const struct file_operations *real_fops = NULL; | ||
236 | struct file_operations *proxy_fops = NULL; | ||
237 | int srcu_idx, r; | ||
238 | |||
239 | r = debugfs_use_file_start(dentry, &srcu_idx); | ||
240 | if (r) { | ||
241 | r = -ENOENT; | ||
242 | goto out; | ||
243 | } | ||
244 | |||
245 | real_fops = REAL_FOPS_DEREF(dentry); | ||
246 | real_fops = fops_get(real_fops); | ||
247 | if (!real_fops) { | ||
248 | /* Huh? Module did not cleanup after itself at exit? */ | ||
249 | WARN(1, "debugfs file owner did not clean up at exit: %pd", | ||
250 | dentry); | ||
251 | r = -ENXIO; | ||
252 | goto out; | ||
253 | } | ||
254 | |||
255 | proxy_fops = kzalloc(sizeof(*proxy_fops), GFP_KERNEL); | ||
256 | if (!proxy_fops) { | ||
257 | r = -ENOMEM; | ||
258 | goto free_proxy; | ||
259 | } | ||
260 | __full_proxy_fops_init(proxy_fops, real_fops); | ||
261 | replace_fops(filp, proxy_fops); | ||
262 | |||
263 | if (real_fops->open) { | ||
264 | r = real_fops->open(inode, filp); | ||
265 | |||
266 | if (filp->f_op != proxy_fops) { | ||
267 | /* No protection against file removal anymore. */ | ||
268 | WARN(1, "debugfs file owner replaced proxy fops: %pd", | ||
269 | dentry); | ||
270 | goto free_proxy; | ||
271 | } | ||
272 | } | ||
273 | |||
274 | goto out; | ||
275 | free_proxy: | ||
276 | kfree(proxy_fops); | ||
277 | fops_put(real_fops); | ||
278 | out: | ||
279 | debugfs_use_file_finish(srcu_idx); | ||
280 | return r; | ||
281 | } | ||
282 | |||
283 | const struct file_operations debugfs_full_proxy_file_operations = { | ||
284 | .open = full_proxy_open, | ||
285 | }; | ||
286 | |||
287 | ssize_t debugfs_attr_read(struct file *file, char __user *buf, | ||
288 | size_t len, loff_t *ppos) | ||
289 | { | ||
290 | ssize_t ret; | ||
291 | int srcu_idx; | ||
292 | |||
293 | ret = debugfs_use_file_start(F_DENTRY(file), &srcu_idx); | ||
294 | if (likely(!ret)) | ||
295 | ret = simple_attr_read(file, buf, len, ppos); | ||
296 | debugfs_use_file_finish(srcu_idx); | ||
297 | return ret; | ||
298 | } | ||
299 | EXPORT_SYMBOL_GPL(debugfs_attr_read); | ||
300 | |||
301 | ssize_t debugfs_attr_write(struct file *file, const char __user *buf, | ||
302 | size_t len, loff_t *ppos) | ||
303 | { | ||
304 | ssize_t ret; | ||
305 | int srcu_idx; | ||
306 | |||
307 | ret = debugfs_use_file_start(F_DENTRY(file), &srcu_idx); | ||
308 | if (likely(!ret)) | ||
309 | ret = simple_attr_write(file, buf, len, ppos); | ||
310 | debugfs_use_file_finish(srcu_idx); | ||
311 | return ret; | ||
312 | } | ||
313 | EXPORT_SYMBOL_GPL(debugfs_attr_write); | ||
314 | |||
315 | static struct dentry *debugfs_create_mode_unsafe(const char *name, umode_t mode, | ||
316 | struct dentry *parent, void *value, | ||
317 | const struct file_operations *fops, | ||
318 | const struct file_operations *fops_ro, | ||
319 | const struct file_operations *fops_wo) | ||
50 | { | 320 | { |
51 | /* if there are no write bits set, make read only */ | 321 | /* if there are no write bits set, make read only */ |
52 | if (!(mode & S_IWUGO)) | 322 | if (!(mode & S_IWUGO)) |
53 | return debugfs_create_file(name, mode, parent, value, fops_ro); | 323 | return debugfs_create_file_unsafe(name, mode, parent, value, |
324 | fops_ro); | ||
54 | /* if there are no read bits set, make write only */ | 325 | /* if there are no read bits set, make write only */ |
55 | if (!(mode & S_IRUGO)) | 326 | if (!(mode & S_IRUGO)) |
56 | return debugfs_create_file(name, mode, parent, value, fops_wo); | 327 | return debugfs_create_file_unsafe(name, mode, parent, value, |
328 | fops_wo); | ||
57 | 329 | ||
58 | return debugfs_create_file(name, mode, parent, value, fops); | 330 | return debugfs_create_file_unsafe(name, mode, parent, value, fops); |
59 | } | 331 | } |
60 | 332 | ||
61 | static int debugfs_u8_set(void *data, u64 val) | 333 | static int debugfs_u8_set(void *data, u64 val) |
@@ -68,9 +340,9 @@ static int debugfs_u8_get(void *data, u64 *val) | |||
68 | *val = *(u8 *)data; | 340 | *val = *(u8 *)data; |
69 | return 0; | 341 | return 0; |
70 | } | 342 | } |
71 | DEFINE_SIMPLE_ATTRIBUTE(fops_u8, debugfs_u8_get, debugfs_u8_set, "%llu\n"); | 343 | DEFINE_DEBUGFS_ATTRIBUTE(fops_u8, debugfs_u8_get, debugfs_u8_set, "%llu\n"); |
72 | DEFINE_SIMPLE_ATTRIBUTE(fops_u8_ro, debugfs_u8_get, NULL, "%llu\n"); | 344 | DEFINE_DEBUGFS_ATTRIBUTE(fops_u8_ro, debugfs_u8_get, NULL, "%llu\n"); |
73 | DEFINE_SIMPLE_ATTRIBUTE(fops_u8_wo, NULL, debugfs_u8_set, "%llu\n"); | 345 | DEFINE_DEBUGFS_ATTRIBUTE(fops_u8_wo, NULL, debugfs_u8_set, "%llu\n"); |
74 | 346 | ||
75 | /** | 347 | /** |
76 | * debugfs_create_u8 - create a debugfs file that is used to read and write an unsigned 8-bit value | 348 | * debugfs_create_u8 - create a debugfs file that is used to read and write an unsigned 8-bit value |
@@ -99,7 +371,7 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_u8_wo, NULL, debugfs_u8_set, "%llu\n"); | |||
99 | struct dentry *debugfs_create_u8(const char *name, umode_t mode, | 371 | struct dentry *debugfs_create_u8(const char *name, umode_t mode, |
100 | struct dentry *parent, u8 *value) | 372 | struct dentry *parent, u8 *value) |
101 | { | 373 | { |
102 | return debugfs_create_mode(name, mode, parent, value, &fops_u8, | 374 | return debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u8, |
103 | &fops_u8_ro, &fops_u8_wo); | 375 | &fops_u8_ro, &fops_u8_wo); |
104 | } | 376 | } |
105 | EXPORT_SYMBOL_GPL(debugfs_create_u8); | 377 | EXPORT_SYMBOL_GPL(debugfs_create_u8); |
@@ -114,9 +386,9 @@ static int debugfs_u16_get(void *data, u64 *val) | |||
114 | *val = *(u16 *)data; | 386 | *val = *(u16 *)data; |
115 | return 0; | 387 | return 0; |
116 | } | 388 | } |
117 | DEFINE_SIMPLE_ATTRIBUTE(fops_u16, debugfs_u16_get, debugfs_u16_set, "%llu\n"); | 389 | DEFINE_DEBUGFS_ATTRIBUTE(fops_u16, debugfs_u16_get, debugfs_u16_set, "%llu\n"); |
118 | DEFINE_SIMPLE_ATTRIBUTE(fops_u16_ro, debugfs_u16_get, NULL, "%llu\n"); | 390 | DEFINE_DEBUGFS_ATTRIBUTE(fops_u16_ro, debugfs_u16_get, NULL, "%llu\n"); |
119 | DEFINE_SIMPLE_ATTRIBUTE(fops_u16_wo, NULL, debugfs_u16_set, "%llu\n"); | 391 | DEFINE_DEBUGFS_ATTRIBUTE(fops_u16_wo, NULL, debugfs_u16_set, "%llu\n"); |
120 | 392 | ||
121 | /** | 393 | /** |
122 | * debugfs_create_u16 - create a debugfs file that is used to read and write an unsigned 16-bit value | 394 | * debugfs_create_u16 - create a debugfs file that is used to read and write an unsigned 16-bit value |
@@ -145,7 +417,7 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_u16_wo, NULL, debugfs_u16_set, "%llu\n"); | |||
145 | struct dentry *debugfs_create_u16(const char *name, umode_t mode, | 417 | struct dentry *debugfs_create_u16(const char *name, umode_t mode, |
146 | struct dentry *parent, u16 *value) | 418 | struct dentry *parent, u16 *value) |
147 | { | 419 | { |
148 | return debugfs_create_mode(name, mode, parent, value, &fops_u16, | 420 | return debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u16, |
149 | &fops_u16_ro, &fops_u16_wo); | 421 | &fops_u16_ro, &fops_u16_wo); |
150 | } | 422 | } |
151 | EXPORT_SYMBOL_GPL(debugfs_create_u16); | 423 | EXPORT_SYMBOL_GPL(debugfs_create_u16); |
@@ -160,9 +432,9 @@ static int debugfs_u32_get(void *data, u64 *val) | |||
160 | *val = *(u32 *)data; | 432 | *val = *(u32 *)data; |
161 | return 0; | 433 | return 0; |
162 | } | 434 | } |
163 | DEFINE_SIMPLE_ATTRIBUTE(fops_u32, debugfs_u32_get, debugfs_u32_set, "%llu\n"); | 435 | DEFINE_DEBUGFS_ATTRIBUTE(fops_u32, debugfs_u32_get, debugfs_u32_set, "%llu\n"); |
164 | DEFINE_SIMPLE_ATTRIBUTE(fops_u32_ro, debugfs_u32_get, NULL, "%llu\n"); | 436 | DEFINE_DEBUGFS_ATTRIBUTE(fops_u32_ro, debugfs_u32_get, NULL, "%llu\n"); |
165 | DEFINE_SIMPLE_ATTRIBUTE(fops_u32_wo, NULL, debugfs_u32_set, "%llu\n"); | 437 | DEFINE_DEBUGFS_ATTRIBUTE(fops_u32_wo, NULL, debugfs_u32_set, "%llu\n"); |
166 | 438 | ||
167 | /** | 439 | /** |
168 | * debugfs_create_u32 - create a debugfs file that is used to read and write an unsigned 32-bit value | 440 | * debugfs_create_u32 - create a debugfs file that is used to read and write an unsigned 32-bit value |
@@ -191,7 +463,7 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_u32_wo, NULL, debugfs_u32_set, "%llu\n"); | |||
191 | struct dentry *debugfs_create_u32(const char *name, umode_t mode, | 463 | struct dentry *debugfs_create_u32(const char *name, umode_t mode, |
192 | struct dentry *parent, u32 *value) | 464 | struct dentry *parent, u32 *value) |
193 | { | 465 | { |
194 | return debugfs_create_mode(name, mode, parent, value, &fops_u32, | 466 | return debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u32, |
195 | &fops_u32_ro, &fops_u32_wo); | 467 | &fops_u32_ro, &fops_u32_wo); |
196 | } | 468 | } |
197 | EXPORT_SYMBOL_GPL(debugfs_create_u32); | 469 | EXPORT_SYMBOL_GPL(debugfs_create_u32); |
@@ -207,9 +479,9 @@ static int debugfs_u64_get(void *data, u64 *val) | |||
207 | *val = *(u64 *)data; | 479 | *val = *(u64 *)data; |
208 | return 0; | 480 | return 0; |
209 | } | 481 | } |
210 | DEFINE_SIMPLE_ATTRIBUTE(fops_u64, debugfs_u64_get, debugfs_u64_set, "%llu\n"); | 482 | DEFINE_DEBUGFS_ATTRIBUTE(fops_u64, debugfs_u64_get, debugfs_u64_set, "%llu\n"); |
211 | DEFINE_SIMPLE_ATTRIBUTE(fops_u64_ro, debugfs_u64_get, NULL, "%llu\n"); | 483 | DEFINE_DEBUGFS_ATTRIBUTE(fops_u64_ro, debugfs_u64_get, NULL, "%llu\n"); |
212 | DEFINE_SIMPLE_ATTRIBUTE(fops_u64_wo, NULL, debugfs_u64_set, "%llu\n"); | 484 | DEFINE_DEBUGFS_ATTRIBUTE(fops_u64_wo, NULL, debugfs_u64_set, "%llu\n"); |
213 | 485 | ||
214 | /** | 486 | /** |
215 | * debugfs_create_u64 - create a debugfs file that is used to read and write an unsigned 64-bit value | 487 | * debugfs_create_u64 - create a debugfs file that is used to read and write an unsigned 64-bit value |
@@ -238,7 +510,7 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_u64_wo, NULL, debugfs_u64_set, "%llu\n"); | |||
238 | struct dentry *debugfs_create_u64(const char *name, umode_t mode, | 510 | struct dentry *debugfs_create_u64(const char *name, umode_t mode, |
239 | struct dentry *parent, u64 *value) | 511 | struct dentry *parent, u64 *value) |
240 | { | 512 | { |
241 | return debugfs_create_mode(name, mode, parent, value, &fops_u64, | 513 | return debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u64, |
242 | &fops_u64_ro, &fops_u64_wo); | 514 | &fops_u64_ro, &fops_u64_wo); |
243 | } | 515 | } |
244 | EXPORT_SYMBOL_GPL(debugfs_create_u64); | 516 | EXPORT_SYMBOL_GPL(debugfs_create_u64); |
@@ -254,9 +526,10 @@ static int debugfs_ulong_get(void *data, u64 *val) | |||
254 | *val = *(unsigned long *)data; | 526 | *val = *(unsigned long *)data; |
255 | return 0; | 527 | return 0; |
256 | } | 528 | } |
257 | DEFINE_SIMPLE_ATTRIBUTE(fops_ulong, debugfs_ulong_get, debugfs_ulong_set, "%llu\n"); | 529 | DEFINE_DEBUGFS_ATTRIBUTE(fops_ulong, debugfs_ulong_get, debugfs_ulong_set, |
258 | DEFINE_SIMPLE_ATTRIBUTE(fops_ulong_ro, debugfs_ulong_get, NULL, "%llu\n"); | 530 | "%llu\n"); |
259 | DEFINE_SIMPLE_ATTRIBUTE(fops_ulong_wo, NULL, debugfs_ulong_set, "%llu\n"); | 531 | DEFINE_DEBUGFS_ATTRIBUTE(fops_ulong_ro, debugfs_ulong_get, NULL, "%llu\n"); |
532 | DEFINE_DEBUGFS_ATTRIBUTE(fops_ulong_wo, NULL, debugfs_ulong_set, "%llu\n"); | ||
260 | 533 | ||
261 | /** | 534 | /** |
262 | * debugfs_create_ulong - create a debugfs file that is used to read and write | 535 | * debugfs_create_ulong - create a debugfs file that is used to read and write |
@@ -286,26 +559,30 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_ulong_wo, NULL, debugfs_ulong_set, "%llu\n"); | |||
286 | struct dentry *debugfs_create_ulong(const char *name, umode_t mode, | 559 | struct dentry *debugfs_create_ulong(const char *name, umode_t mode, |
287 | struct dentry *parent, unsigned long *value) | 560 | struct dentry *parent, unsigned long *value) |
288 | { | 561 | { |
289 | return debugfs_create_mode(name, mode, parent, value, &fops_ulong, | 562 | return debugfs_create_mode_unsafe(name, mode, parent, value, |
290 | &fops_ulong_ro, &fops_ulong_wo); | 563 | &fops_ulong, &fops_ulong_ro, |
564 | &fops_ulong_wo); | ||
291 | } | 565 | } |
292 | EXPORT_SYMBOL_GPL(debugfs_create_ulong); | 566 | EXPORT_SYMBOL_GPL(debugfs_create_ulong); |
293 | 567 | ||
294 | DEFINE_SIMPLE_ATTRIBUTE(fops_x8, debugfs_u8_get, debugfs_u8_set, "0x%02llx\n"); | 568 | DEFINE_DEBUGFS_ATTRIBUTE(fops_x8, debugfs_u8_get, debugfs_u8_set, "0x%02llx\n"); |
295 | DEFINE_SIMPLE_ATTRIBUTE(fops_x8_ro, debugfs_u8_get, NULL, "0x%02llx\n"); | 569 | DEFINE_DEBUGFS_ATTRIBUTE(fops_x8_ro, debugfs_u8_get, NULL, "0x%02llx\n"); |
296 | DEFINE_SIMPLE_ATTRIBUTE(fops_x8_wo, NULL, debugfs_u8_set, "0x%02llx\n"); | 570 | DEFINE_DEBUGFS_ATTRIBUTE(fops_x8_wo, NULL, debugfs_u8_set, "0x%02llx\n"); |
297 | 571 | ||
298 | DEFINE_SIMPLE_ATTRIBUTE(fops_x16, debugfs_u16_get, debugfs_u16_set, "0x%04llx\n"); | 572 | DEFINE_DEBUGFS_ATTRIBUTE(fops_x16, debugfs_u16_get, debugfs_u16_set, |
299 | DEFINE_SIMPLE_ATTRIBUTE(fops_x16_ro, debugfs_u16_get, NULL, "0x%04llx\n"); | 573 | "0x%04llx\n"); |
300 | DEFINE_SIMPLE_ATTRIBUTE(fops_x16_wo, NULL, debugfs_u16_set, "0x%04llx\n"); | 574 | DEFINE_DEBUGFS_ATTRIBUTE(fops_x16_ro, debugfs_u16_get, NULL, "0x%04llx\n"); |
575 | DEFINE_DEBUGFS_ATTRIBUTE(fops_x16_wo, NULL, debugfs_u16_set, "0x%04llx\n"); | ||
301 | 576 | ||
302 | DEFINE_SIMPLE_ATTRIBUTE(fops_x32, debugfs_u32_get, debugfs_u32_set, "0x%08llx\n"); | 577 | DEFINE_DEBUGFS_ATTRIBUTE(fops_x32, debugfs_u32_get, debugfs_u32_set, |
303 | DEFINE_SIMPLE_ATTRIBUTE(fops_x32_ro, debugfs_u32_get, NULL, "0x%08llx\n"); | 578 | "0x%08llx\n"); |
304 | DEFINE_SIMPLE_ATTRIBUTE(fops_x32_wo, NULL, debugfs_u32_set, "0x%08llx\n"); | 579 | DEFINE_DEBUGFS_ATTRIBUTE(fops_x32_ro, debugfs_u32_get, NULL, "0x%08llx\n"); |
580 | DEFINE_DEBUGFS_ATTRIBUTE(fops_x32_wo, NULL, debugfs_u32_set, "0x%08llx\n"); | ||
305 | 581 | ||
306 | DEFINE_SIMPLE_ATTRIBUTE(fops_x64, debugfs_u64_get, debugfs_u64_set, "0x%016llx\n"); | 582 | DEFINE_DEBUGFS_ATTRIBUTE(fops_x64, debugfs_u64_get, debugfs_u64_set, |
307 | DEFINE_SIMPLE_ATTRIBUTE(fops_x64_ro, debugfs_u64_get, NULL, "0x%016llx\n"); | 583 | "0x%016llx\n"); |
308 | DEFINE_SIMPLE_ATTRIBUTE(fops_x64_wo, NULL, debugfs_u64_set, "0x%016llx\n"); | 584 | DEFINE_DEBUGFS_ATTRIBUTE(fops_x64_ro, debugfs_u64_get, NULL, "0x%016llx\n"); |
585 | DEFINE_DEBUGFS_ATTRIBUTE(fops_x64_wo, NULL, debugfs_u64_set, "0x%016llx\n"); | ||
309 | 586 | ||
310 | /* | 587 | /* |
311 | * debugfs_create_x{8,16,32,64} - create a debugfs file that is used to read and write an unsigned {8,16,32,64}-bit value | 588 | * debugfs_create_x{8,16,32,64} - create a debugfs file that is used to read and write an unsigned {8,16,32,64}-bit value |
@@ -328,7 +605,7 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_x64_wo, NULL, debugfs_u64_set, "0x%016llx\n"); | |||
328 | struct dentry *debugfs_create_x8(const char *name, umode_t mode, | 605 | struct dentry *debugfs_create_x8(const char *name, umode_t mode, |
329 | struct dentry *parent, u8 *value) | 606 | struct dentry *parent, u8 *value) |
330 | { | 607 | { |
331 | return debugfs_create_mode(name, mode, parent, value, &fops_x8, | 608 | return debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x8, |
332 | &fops_x8_ro, &fops_x8_wo); | 609 | &fops_x8_ro, &fops_x8_wo); |
333 | } | 610 | } |
334 | EXPORT_SYMBOL_GPL(debugfs_create_x8); | 611 | EXPORT_SYMBOL_GPL(debugfs_create_x8); |
@@ -346,7 +623,7 @@ EXPORT_SYMBOL_GPL(debugfs_create_x8); | |||
346 | struct dentry *debugfs_create_x16(const char *name, umode_t mode, | 623 | struct dentry *debugfs_create_x16(const char *name, umode_t mode, |
347 | struct dentry *parent, u16 *value) | 624 | struct dentry *parent, u16 *value) |
348 | { | 625 | { |
349 | return debugfs_create_mode(name, mode, parent, value, &fops_x16, | 626 | return debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x16, |
350 | &fops_x16_ro, &fops_x16_wo); | 627 | &fops_x16_ro, &fops_x16_wo); |
351 | } | 628 | } |
352 | EXPORT_SYMBOL_GPL(debugfs_create_x16); | 629 | EXPORT_SYMBOL_GPL(debugfs_create_x16); |
@@ -364,7 +641,7 @@ EXPORT_SYMBOL_GPL(debugfs_create_x16); | |||
364 | struct dentry *debugfs_create_x32(const char *name, umode_t mode, | 641 | struct dentry *debugfs_create_x32(const char *name, umode_t mode, |
365 | struct dentry *parent, u32 *value) | 642 | struct dentry *parent, u32 *value) |
366 | { | 643 | { |
367 | return debugfs_create_mode(name, mode, parent, value, &fops_x32, | 644 | return debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x32, |
368 | &fops_x32_ro, &fops_x32_wo); | 645 | &fops_x32_ro, &fops_x32_wo); |
369 | } | 646 | } |
370 | EXPORT_SYMBOL_GPL(debugfs_create_x32); | 647 | EXPORT_SYMBOL_GPL(debugfs_create_x32); |
@@ -382,7 +659,7 @@ EXPORT_SYMBOL_GPL(debugfs_create_x32); | |||
382 | struct dentry *debugfs_create_x64(const char *name, umode_t mode, | 659 | struct dentry *debugfs_create_x64(const char *name, umode_t mode, |
383 | struct dentry *parent, u64 *value) | 660 | struct dentry *parent, u64 *value) |
384 | { | 661 | { |
385 | return debugfs_create_mode(name, mode, parent, value, &fops_x64, | 662 | return debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x64, |
386 | &fops_x64_ro, &fops_x64_wo); | 663 | &fops_x64_ro, &fops_x64_wo); |
387 | } | 664 | } |
388 | EXPORT_SYMBOL_GPL(debugfs_create_x64); | 665 | EXPORT_SYMBOL_GPL(debugfs_create_x64); |
@@ -398,10 +675,10 @@ static int debugfs_size_t_get(void *data, u64 *val) | |||
398 | *val = *(size_t *)data; | 675 | *val = *(size_t *)data; |
399 | return 0; | 676 | return 0; |
400 | } | 677 | } |
401 | DEFINE_SIMPLE_ATTRIBUTE(fops_size_t, debugfs_size_t_get, debugfs_size_t_set, | 678 | DEFINE_DEBUGFS_ATTRIBUTE(fops_size_t, debugfs_size_t_get, debugfs_size_t_set, |
402 | "%llu\n"); /* %llu and %zu are more or less the same */ | 679 | "%llu\n"); /* %llu and %zu are more or less the same */ |
403 | DEFINE_SIMPLE_ATTRIBUTE(fops_size_t_ro, debugfs_size_t_get, NULL, "%llu\n"); | 680 | DEFINE_DEBUGFS_ATTRIBUTE(fops_size_t_ro, debugfs_size_t_get, NULL, "%llu\n"); |
404 | DEFINE_SIMPLE_ATTRIBUTE(fops_size_t_wo, NULL, debugfs_size_t_set, "%llu\n"); | 681 | DEFINE_DEBUGFS_ATTRIBUTE(fops_size_t_wo, NULL, debugfs_size_t_set, "%llu\n"); |
405 | 682 | ||
406 | /** | 683 | /** |
407 | * debugfs_create_size_t - create a debugfs file that is used to read and write an size_t value | 684 | * debugfs_create_size_t - create a debugfs file that is used to read and write an size_t value |
@@ -416,8 +693,9 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_size_t_wo, NULL, debugfs_size_t_set, "%llu\n"); | |||
416 | struct dentry *debugfs_create_size_t(const char *name, umode_t mode, | 693 | struct dentry *debugfs_create_size_t(const char *name, umode_t mode, |
417 | struct dentry *parent, size_t *value) | 694 | struct dentry *parent, size_t *value) |
418 | { | 695 | { |
419 | return debugfs_create_mode(name, mode, parent, value, &fops_size_t, | 696 | return debugfs_create_mode_unsafe(name, mode, parent, value, |
420 | &fops_size_t_ro, &fops_size_t_wo); | 697 | &fops_size_t, &fops_size_t_ro, |
698 | &fops_size_t_wo); | ||
421 | } | 699 | } |
422 | EXPORT_SYMBOL_GPL(debugfs_create_size_t); | 700 | EXPORT_SYMBOL_GPL(debugfs_create_size_t); |
423 | 701 | ||
@@ -431,10 +709,12 @@ static int debugfs_atomic_t_get(void *data, u64 *val) | |||
431 | *val = atomic_read((atomic_t *)data); | 709 | *val = atomic_read((atomic_t *)data); |
432 | return 0; | 710 | return 0; |
433 | } | 711 | } |
434 | DEFINE_SIMPLE_ATTRIBUTE(fops_atomic_t, debugfs_atomic_t_get, | 712 | DEFINE_DEBUGFS_ATTRIBUTE(fops_atomic_t, debugfs_atomic_t_get, |
435 | debugfs_atomic_t_set, "%lld\n"); | 713 | debugfs_atomic_t_set, "%lld\n"); |
436 | DEFINE_SIMPLE_ATTRIBUTE(fops_atomic_t_ro, debugfs_atomic_t_get, NULL, "%lld\n"); | 714 | DEFINE_DEBUGFS_ATTRIBUTE(fops_atomic_t_ro, debugfs_atomic_t_get, NULL, |
437 | DEFINE_SIMPLE_ATTRIBUTE(fops_atomic_t_wo, NULL, debugfs_atomic_t_set, "%lld\n"); | 715 | "%lld\n"); |
716 | DEFINE_DEBUGFS_ATTRIBUTE(fops_atomic_t_wo, NULL, debugfs_atomic_t_set, | ||
717 | "%lld\n"); | ||
438 | 718 | ||
439 | /** | 719 | /** |
440 | * debugfs_create_atomic_t - create a debugfs file that is used to read and | 720 | * debugfs_create_atomic_t - create a debugfs file that is used to read and |
@@ -450,8 +730,9 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_atomic_t_wo, NULL, debugfs_atomic_t_set, "%lld\n"); | |||
450 | struct dentry *debugfs_create_atomic_t(const char *name, umode_t mode, | 730 | struct dentry *debugfs_create_atomic_t(const char *name, umode_t mode, |
451 | struct dentry *parent, atomic_t *value) | 731 | struct dentry *parent, atomic_t *value) |
452 | { | 732 | { |
453 | return debugfs_create_mode(name, mode, parent, value, &fops_atomic_t, | 733 | return debugfs_create_mode_unsafe(name, mode, parent, value, |
454 | &fops_atomic_t_ro, &fops_atomic_t_wo); | 734 | &fops_atomic_t, &fops_atomic_t_ro, |
735 | &fops_atomic_t_wo); | ||
455 | } | 736 | } |
456 | EXPORT_SYMBOL_GPL(debugfs_create_atomic_t); | 737 | EXPORT_SYMBOL_GPL(debugfs_create_atomic_t); |
457 | 738 | ||
@@ -459,9 +740,17 @@ ssize_t debugfs_read_file_bool(struct file *file, char __user *user_buf, | |||
459 | size_t count, loff_t *ppos) | 740 | size_t count, loff_t *ppos) |
460 | { | 741 | { |
461 | char buf[3]; | 742 | char buf[3]; |
462 | bool *val = file->private_data; | 743 | bool val; |
744 | int r, srcu_idx; | ||
463 | 745 | ||
464 | if (*val) | 746 | r = debugfs_use_file_start(F_DENTRY(file), &srcu_idx); |
747 | if (likely(!r)) | ||
748 | val = *(bool *)file->private_data; | ||
749 | debugfs_use_file_finish(srcu_idx); | ||
750 | if (r) | ||
751 | return r; | ||
752 | |||
753 | if (val) | ||
465 | buf[0] = 'Y'; | 754 | buf[0] = 'Y'; |
466 | else | 755 | else |
467 | buf[0] = 'N'; | 756 | buf[0] = 'N'; |
@@ -477,6 +766,7 @@ ssize_t debugfs_write_file_bool(struct file *file, const char __user *user_buf, | |||
477 | char buf[32]; | 766 | char buf[32]; |
478 | size_t buf_size; | 767 | size_t buf_size; |
479 | bool bv; | 768 | bool bv; |
769 | int r, srcu_idx; | ||
480 | bool *val = file->private_data; | 770 | bool *val = file->private_data; |
481 | 771 | ||
482 | buf_size = min(count, (sizeof(buf)-1)); | 772 | buf_size = min(count, (sizeof(buf)-1)); |
@@ -484,8 +774,14 @@ ssize_t debugfs_write_file_bool(struct file *file, const char __user *user_buf, | |||
484 | return -EFAULT; | 774 | return -EFAULT; |
485 | 775 | ||
486 | buf[buf_size] = '\0'; | 776 | buf[buf_size] = '\0'; |
487 | if (strtobool(buf, &bv) == 0) | 777 | if (strtobool(buf, &bv) == 0) { |
488 | *val = bv; | 778 | r = debugfs_use_file_start(F_DENTRY(file), &srcu_idx); |
779 | if (likely(!r)) | ||
780 | *val = bv; | ||
781 | debugfs_use_file_finish(srcu_idx); | ||
782 | if (r) | ||
783 | return r; | ||
784 | } | ||
489 | 785 | ||
490 | return count; | 786 | return count; |
491 | } | 787 | } |
@@ -537,7 +833,7 @@ static const struct file_operations fops_bool_wo = { | |||
537 | struct dentry *debugfs_create_bool(const char *name, umode_t mode, | 833 | struct dentry *debugfs_create_bool(const char *name, umode_t mode, |
538 | struct dentry *parent, bool *value) | 834 | struct dentry *parent, bool *value) |
539 | { | 835 | { |
540 | return debugfs_create_mode(name, mode, parent, value, &fops_bool, | 836 | return debugfs_create_mode_unsafe(name, mode, parent, value, &fops_bool, |
541 | &fops_bool_ro, &fops_bool_wo); | 837 | &fops_bool_ro, &fops_bool_wo); |
542 | } | 838 | } |
543 | EXPORT_SYMBOL_GPL(debugfs_create_bool); | 839 | EXPORT_SYMBOL_GPL(debugfs_create_bool); |
@@ -546,8 +842,15 @@ static ssize_t read_file_blob(struct file *file, char __user *user_buf, | |||
546 | size_t count, loff_t *ppos) | 842 | size_t count, loff_t *ppos) |
547 | { | 843 | { |
548 | struct debugfs_blob_wrapper *blob = file->private_data; | 844 | struct debugfs_blob_wrapper *blob = file->private_data; |
549 | return simple_read_from_buffer(user_buf, count, ppos, blob->data, | 845 | ssize_t r; |
550 | blob->size); | 846 | int srcu_idx; |
847 | |||
848 | r = debugfs_use_file_start(F_DENTRY(file), &srcu_idx); | ||
849 | if (likely(!r)) | ||
850 | r = simple_read_from_buffer(user_buf, count, ppos, blob->data, | ||
851 | blob->size); | ||
852 | debugfs_use_file_finish(srcu_idx); | ||
853 | return r; | ||
551 | } | 854 | } |
552 | 855 | ||
553 | static const struct file_operations fops_blob = { | 856 | static const struct file_operations fops_blob = { |
@@ -584,7 +887,7 @@ struct dentry *debugfs_create_blob(const char *name, umode_t mode, | |||
584 | struct dentry *parent, | 887 | struct dentry *parent, |
585 | struct debugfs_blob_wrapper *blob) | 888 | struct debugfs_blob_wrapper *blob) |
586 | { | 889 | { |
587 | return debugfs_create_file(name, mode, parent, blob, &fops_blob); | 890 | return debugfs_create_file_unsafe(name, mode, parent, blob, &fops_blob); |
588 | } | 891 | } |
589 | EXPORT_SYMBOL_GPL(debugfs_create_blob); | 892 | EXPORT_SYMBOL_GPL(debugfs_create_blob); |
590 | 893 | ||
@@ -689,7 +992,8 @@ struct dentry *debugfs_create_u32_array(const char *name, umode_t mode, | |||
689 | data->array = array; | 992 | data->array = array; |
690 | data->elements = elements; | 993 | data->elements = elements; |
691 | 994 | ||
692 | return debugfs_create_file(name, mode, parent, data, &u32_array_fops); | 995 | return debugfs_create_file_unsafe(name, mode, parent, data, |
996 | &u32_array_fops); | ||
693 | } | 997 | } |
694 | EXPORT_SYMBOL_GPL(debugfs_create_u32_array); | 998 | EXPORT_SYMBOL_GPL(debugfs_create_u32_array); |
695 | 999 | ||
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index 8580831ed237..4bc1f68243c1 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c | |||
@@ -27,9 +27,14 @@ | |||
27 | #include <linux/parser.h> | 27 | #include <linux/parser.h> |
28 | #include <linux/magic.h> | 28 | #include <linux/magic.h> |
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | #include <linux/srcu.h> | ||
31 | |||
32 | #include "internal.h" | ||
30 | 33 | ||
31 | #define DEBUGFS_DEFAULT_MODE 0700 | 34 | #define DEBUGFS_DEFAULT_MODE 0700 |
32 | 35 | ||
36 | DEFINE_SRCU(debugfs_srcu); | ||
37 | |||
33 | static struct vfsmount *debugfs_mount; | 38 | static struct vfsmount *debugfs_mount; |
34 | static int debugfs_mount_count; | 39 | static int debugfs_mount_count; |
35 | static bool debugfs_registered; | 40 | static bool debugfs_registered; |
@@ -39,7 +44,8 @@ static struct inode *debugfs_get_inode(struct super_block *sb) | |||
39 | struct inode *inode = new_inode(sb); | 44 | struct inode *inode = new_inode(sb); |
40 | if (inode) { | 45 | if (inode) { |
41 | inode->i_ino = get_next_ino(); | 46 | inode->i_ino = get_next_ino(); |
42 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; | 47 | inode->i_atime = inode->i_mtime = |
48 | inode->i_ctime = current_fs_time(sb); | ||
43 | } | 49 | } |
44 | return inode; | 50 | return inode; |
45 | } | 51 | } |
@@ -294,6 +300,37 @@ static struct dentry *end_creating(struct dentry *dentry) | |||
294 | return dentry; | 300 | return dentry; |
295 | } | 301 | } |
296 | 302 | ||
303 | static struct dentry *__debugfs_create_file(const char *name, umode_t mode, | ||
304 | struct dentry *parent, void *data, | ||
305 | const struct file_operations *proxy_fops, | ||
306 | const struct file_operations *real_fops) | ||
307 | { | ||
308 | struct dentry *dentry; | ||
309 | struct inode *inode; | ||
310 | |||
311 | if (!(mode & S_IFMT)) | ||
312 | mode |= S_IFREG; | ||
313 | BUG_ON(!S_ISREG(mode)); | ||
314 | dentry = start_creating(name, parent); | ||
315 | |||
316 | if (IS_ERR(dentry)) | ||
317 | return NULL; | ||
318 | |||
319 | inode = debugfs_get_inode(dentry->d_sb); | ||
320 | if (unlikely(!inode)) | ||
321 | return failed_creating(dentry); | ||
322 | |||
323 | inode->i_mode = mode; | ||
324 | inode->i_private = data; | ||
325 | |||
326 | inode->i_fop = proxy_fops; | ||
327 | dentry->d_fsdata = (void *)real_fops; | ||
328 | |||
329 | d_instantiate(dentry, inode); | ||
330 | fsnotify_create(d_inode(dentry->d_parent), dentry); | ||
331 | return end_creating(dentry); | ||
332 | } | ||
333 | |||
297 | /** | 334 | /** |
298 | * debugfs_create_file - create a file in the debugfs filesystem | 335 | * debugfs_create_file - create a file in the debugfs filesystem |
299 | * @name: a pointer to a string containing the name of the file to create. | 336 | * @name: a pointer to a string containing the name of the file to create. |
@@ -324,29 +361,52 @@ struct dentry *debugfs_create_file(const char *name, umode_t mode, | |||
324 | struct dentry *parent, void *data, | 361 | struct dentry *parent, void *data, |
325 | const struct file_operations *fops) | 362 | const struct file_operations *fops) |
326 | { | 363 | { |
327 | struct dentry *dentry; | ||
328 | struct inode *inode; | ||
329 | 364 | ||
330 | if (!(mode & S_IFMT)) | 365 | return __debugfs_create_file(name, mode, parent, data, |
331 | mode |= S_IFREG; | 366 | fops ? &debugfs_full_proxy_file_operations : |
332 | BUG_ON(!S_ISREG(mode)); | 367 | &debugfs_noop_file_operations, |
333 | dentry = start_creating(name, parent); | 368 | fops); |
334 | 369 | } | |
335 | if (IS_ERR(dentry)) | 370 | EXPORT_SYMBOL_GPL(debugfs_create_file); |
336 | return NULL; | ||
337 | 371 | ||
338 | inode = debugfs_get_inode(dentry->d_sb); | 372 | /** |
339 | if (unlikely(!inode)) | 373 | * debugfs_create_file_unsafe - create a file in the debugfs filesystem |
340 | return failed_creating(dentry); | 374 | * @name: a pointer to a string containing the name of the file to create. |
375 | * @mode: the permission that the file should have. | ||
376 | * @parent: a pointer to the parent dentry for this file. This should be a | ||
377 | * directory dentry if set. If this parameter is NULL, then the | ||
378 | * file will be created in the root of the debugfs filesystem. | ||
379 | * @data: a pointer to something that the caller will want to get to later | ||
380 | * on. The inode.i_private pointer will point to this value on | ||
381 | * the open() call. | ||
382 | * @fops: a pointer to a struct file_operations that should be used for | ||
383 | * this file. | ||
384 | * | ||
385 | * debugfs_create_file_unsafe() is completely analogous to | ||
386 | * debugfs_create_file(), the only difference being that the fops | ||
387 | * handed it will not get protected against file removals by the | ||
388 | * debugfs core. | ||
389 | * | ||
390 | * It is your responsibility to protect your struct file_operation | ||
391 | * methods against file removals by means of debugfs_use_file_start() | ||
392 | * and debugfs_use_file_finish(). ->open() is still protected by | ||
393 | * debugfs though. | ||
394 | * | ||
395 | * Any struct file_operations defined by means of | ||
396 | * DEFINE_DEBUGFS_ATTRIBUTE() is protected against file removals and | ||
397 | * thus, may be used here. | ||
398 | */ | ||
399 | struct dentry *debugfs_create_file_unsafe(const char *name, umode_t mode, | ||
400 | struct dentry *parent, void *data, | ||
401 | const struct file_operations *fops) | ||
402 | { | ||
341 | 403 | ||
342 | inode->i_mode = mode; | 404 | return __debugfs_create_file(name, mode, parent, data, |
343 | inode->i_fop = fops ? fops : &debugfs_file_operations; | 405 | fops ? &debugfs_open_proxy_file_operations : |
344 | inode->i_private = data; | 406 | &debugfs_noop_file_operations, |
345 | d_instantiate(dentry, inode); | 407 | fops); |
346 | fsnotify_create(d_inode(dentry->d_parent), dentry); | ||
347 | return end_creating(dentry); | ||
348 | } | 408 | } |
349 | EXPORT_SYMBOL_GPL(debugfs_create_file); | 409 | EXPORT_SYMBOL_GPL(debugfs_create_file_unsafe); |
350 | 410 | ||
351 | /** | 411 | /** |
352 | * debugfs_create_file_size - create a file in the debugfs filesystem | 412 | * debugfs_create_file_size - create a file in the debugfs filesystem |
@@ -461,7 +521,11 @@ struct dentry *debugfs_create_automount(const char *name, | |||
461 | inode->i_flags |= S_AUTOMOUNT; | 521 | inode->i_flags |= S_AUTOMOUNT; |
462 | inode->i_private = data; | 522 | inode->i_private = data; |
463 | dentry->d_fsdata = (void *)f; | 523 | dentry->d_fsdata = (void *)f; |
524 | /* directory inodes start off with i_nlink == 2 (for "." entry) */ | ||
525 | inc_nlink(inode); | ||
464 | d_instantiate(dentry, inode); | 526 | d_instantiate(dentry, inode); |
527 | inc_nlink(d_inode(dentry->d_parent)); | ||
528 | fsnotify_mkdir(d_inode(dentry->d_parent), dentry); | ||
465 | return end_creating(dentry); | 529 | return end_creating(dentry); |
466 | } | 530 | } |
467 | EXPORT_SYMBOL(debugfs_create_automount); | 531 | EXPORT_SYMBOL(debugfs_create_automount); |
@@ -565,6 +629,8 @@ void debugfs_remove(struct dentry *dentry) | |||
565 | inode_unlock(d_inode(parent)); | 629 | inode_unlock(d_inode(parent)); |
566 | if (!ret) | 630 | if (!ret) |
567 | simple_release_fs(&debugfs_mount, &debugfs_mount_count); | 631 | simple_release_fs(&debugfs_mount, &debugfs_mount_count); |
632 | |||
633 | synchronize_srcu(&debugfs_srcu); | ||
568 | } | 634 | } |
569 | EXPORT_SYMBOL_GPL(debugfs_remove); | 635 | EXPORT_SYMBOL_GPL(debugfs_remove); |
570 | 636 | ||
@@ -642,6 +708,8 @@ void debugfs_remove_recursive(struct dentry *dentry) | |||
642 | if (!__debugfs_remove(child, parent)) | 708 | if (!__debugfs_remove(child, parent)) |
643 | simple_release_fs(&debugfs_mount, &debugfs_mount_count); | 709 | simple_release_fs(&debugfs_mount, &debugfs_mount_count); |
644 | inode_unlock(d_inode(parent)); | 710 | inode_unlock(d_inode(parent)); |
711 | |||
712 | synchronize_srcu(&debugfs_srcu); | ||
645 | } | 713 | } |
646 | EXPORT_SYMBOL_GPL(debugfs_remove_recursive); | 714 | EXPORT_SYMBOL_GPL(debugfs_remove_recursive); |
647 | 715 | ||
diff --git a/fs/debugfs/internal.h b/fs/debugfs/internal.h new file mode 100644 index 000000000000..bba52634b995 --- /dev/null +++ b/fs/debugfs/internal.h | |||
@@ -0,0 +1,26 @@ | |||
1 | /* | ||
2 | * internal.h - declarations internal to debugfs | ||
3 | * | ||
4 | * Copyright (C) 2016 Nicolai Stange <nicstange@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License version | ||
8 | * 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #ifndef _DEBUGFS_INTERNAL_H_ | ||
13 | #define _DEBUGFS_INTERNAL_H_ | ||
14 | |||
15 | struct file_operations; | ||
16 | |||
17 | /* declared over in file.c */ | ||
18 | extern const struct file_operations debugfs_noop_file_operations; | ||
19 | extern const struct file_operations debugfs_open_proxy_file_operations; | ||
20 | extern const struct file_operations debugfs_full_proxy_file_operations; | ||
21 | |||
22 | struct dentry *debugfs_create_file_unsafe(const char *name, umode_t mode, | ||
23 | struct dentry *parent, void *data, | ||
24 | const struct file_operations *fops); | ||
25 | |||
26 | #endif /* _DEBUGFS_INTERNAL_H_ */ | ||
diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c index 68a44315d949..8a652404eef6 100644 --- a/fs/kernfs/dir.c +++ b/fs/kernfs/dir.c | |||
@@ -753,7 +753,8 @@ int kernfs_add_one(struct kernfs_node *kn) | |||
753 | ps_iattr = parent->iattr; | 753 | ps_iattr = parent->iattr; |
754 | if (ps_iattr) { | 754 | if (ps_iattr) { |
755 | struct iattr *ps_iattrs = &ps_iattr->ia_iattr; | 755 | struct iattr *ps_iattrs = &ps_iattr->ia_iattr; |
756 | ps_iattrs->ia_ctime = ps_iattrs->ia_mtime = CURRENT_TIME; | 756 | ktime_get_real_ts(&ps_iattrs->ia_ctime); |
757 | ps_iattrs->ia_mtime = ps_iattrs->ia_ctime; | ||
757 | } | 758 | } |
758 | 759 | ||
759 | mutex_unlock(&kernfs_mutex); | 760 | mutex_unlock(&kernfs_mutex); |
@@ -1279,8 +1280,9 @@ static void __kernfs_remove(struct kernfs_node *kn) | |||
1279 | 1280 | ||
1280 | /* update timestamps on the parent */ | 1281 | /* update timestamps on the parent */ |
1281 | if (ps_iattr) { | 1282 | if (ps_iattr) { |
1282 | ps_iattr->ia_iattr.ia_ctime = CURRENT_TIME; | 1283 | ktime_get_real_ts(&ps_iattr->ia_iattr.ia_ctime); |
1283 | ps_iattr->ia_iattr.ia_mtime = CURRENT_TIME; | 1284 | ps_iattr->ia_iattr.ia_mtime = |
1285 | ps_iattr->ia_iattr.ia_ctime; | ||
1284 | } | 1286 | } |
1285 | 1287 | ||
1286 | kernfs_put(pos); | 1288 | kernfs_put(pos); |
diff --git a/fs/kernfs/file.c b/fs/kernfs/file.c index 7247252ee9b1..e1574008adc9 100644 --- a/fs/kernfs/file.c +++ b/fs/kernfs/file.c | |||
@@ -190,15 +190,16 @@ static ssize_t kernfs_file_direct_read(struct kernfs_open_file *of, | |||
190 | char *buf; | 190 | char *buf; |
191 | 191 | ||
192 | buf = of->prealloc_buf; | 192 | buf = of->prealloc_buf; |
193 | if (!buf) | 193 | if (buf) |
194 | mutex_lock(&of->prealloc_mutex); | ||
195 | else | ||
194 | buf = kmalloc(len, GFP_KERNEL); | 196 | buf = kmalloc(len, GFP_KERNEL); |
195 | if (!buf) | 197 | if (!buf) |
196 | return -ENOMEM; | 198 | return -ENOMEM; |
197 | 199 | ||
198 | /* | 200 | /* |
199 | * @of->mutex nests outside active ref and is used both to ensure that | 201 | * @of->mutex nests outside active ref and is used both to ensure that |
200 | * the ops aren't called concurrently for the same open file, and | 202 | * the ops aren't called concurrently for the same open file. |
201 | * to provide exclusive access to ->prealloc_buf (when that exists). | ||
202 | */ | 203 | */ |
203 | mutex_lock(&of->mutex); | 204 | mutex_lock(&of->mutex); |
204 | if (!kernfs_get_active(of->kn)) { | 205 | if (!kernfs_get_active(of->kn)) { |
@@ -214,21 +215,23 @@ static ssize_t kernfs_file_direct_read(struct kernfs_open_file *of, | |||
214 | else | 215 | else |
215 | len = -EINVAL; | 216 | len = -EINVAL; |
216 | 217 | ||
218 | kernfs_put_active(of->kn); | ||
219 | mutex_unlock(&of->mutex); | ||
220 | |||
217 | if (len < 0) | 221 | if (len < 0) |
218 | goto out_unlock; | 222 | goto out_free; |
219 | 223 | ||
220 | if (copy_to_user(user_buf, buf, len)) { | 224 | if (copy_to_user(user_buf, buf, len)) { |
221 | len = -EFAULT; | 225 | len = -EFAULT; |
222 | goto out_unlock; | 226 | goto out_free; |
223 | } | 227 | } |
224 | 228 | ||
225 | *ppos += len; | 229 | *ppos += len; |
226 | 230 | ||
227 | out_unlock: | ||
228 | kernfs_put_active(of->kn); | ||
229 | mutex_unlock(&of->mutex); | ||
230 | out_free: | 231 | out_free: |
231 | if (buf != of->prealloc_buf) | 232 | if (buf == of->prealloc_buf) |
233 | mutex_unlock(&of->prealloc_mutex); | ||
234 | else | ||
232 | kfree(buf); | 235 | kfree(buf); |
233 | return len; | 236 | return len; |
234 | } | 237 | } |
@@ -284,15 +287,22 @@ static ssize_t kernfs_fop_write(struct file *file, const char __user *user_buf, | |||
284 | } | 287 | } |
285 | 288 | ||
286 | buf = of->prealloc_buf; | 289 | buf = of->prealloc_buf; |
287 | if (!buf) | 290 | if (buf) |
291 | mutex_lock(&of->prealloc_mutex); | ||
292 | else | ||
288 | buf = kmalloc(len + 1, GFP_KERNEL); | 293 | buf = kmalloc(len + 1, GFP_KERNEL); |
289 | if (!buf) | 294 | if (!buf) |
290 | return -ENOMEM; | 295 | return -ENOMEM; |
291 | 296 | ||
297 | if (copy_from_user(buf, user_buf, len)) { | ||
298 | len = -EFAULT; | ||
299 | goto out_free; | ||
300 | } | ||
301 | buf[len] = '\0'; /* guarantee string termination */ | ||
302 | |||
292 | /* | 303 | /* |
293 | * @of->mutex nests outside active ref and is used both to ensure that | 304 | * @of->mutex nests outside active ref and is used both to ensure that |
294 | * the ops aren't called concurrently for the same open file, and | 305 | * the ops aren't called concurrently for the same open file. |
295 | * to provide exclusive access to ->prealloc_buf (when that exists). | ||
296 | */ | 306 | */ |
297 | mutex_lock(&of->mutex); | 307 | mutex_lock(&of->mutex); |
298 | if (!kernfs_get_active(of->kn)) { | 308 | if (!kernfs_get_active(of->kn)) { |
@@ -301,26 +311,22 @@ static ssize_t kernfs_fop_write(struct file *file, const char __user *user_buf, | |||
301 | goto out_free; | 311 | goto out_free; |
302 | } | 312 | } |
303 | 313 | ||
304 | if (copy_from_user(buf, user_buf, len)) { | ||
305 | len = -EFAULT; | ||
306 | goto out_unlock; | ||
307 | } | ||
308 | buf[len] = '\0'; /* guarantee string termination */ | ||
309 | |||
310 | ops = kernfs_ops(of->kn); | 314 | ops = kernfs_ops(of->kn); |
311 | if (ops->write) | 315 | if (ops->write) |
312 | len = ops->write(of, buf, len, *ppos); | 316 | len = ops->write(of, buf, len, *ppos); |
313 | else | 317 | else |
314 | len = -EINVAL; | 318 | len = -EINVAL; |
315 | 319 | ||
320 | kernfs_put_active(of->kn); | ||
321 | mutex_unlock(&of->mutex); | ||
322 | |||
316 | if (len > 0) | 323 | if (len > 0) |
317 | *ppos += len; | 324 | *ppos += len; |
318 | 325 | ||
319 | out_unlock: | ||
320 | kernfs_put_active(of->kn); | ||
321 | mutex_unlock(&of->mutex); | ||
322 | out_free: | 326 | out_free: |
323 | if (buf != of->prealloc_buf) | 327 | if (buf == of->prealloc_buf) |
328 | mutex_unlock(&of->prealloc_mutex); | ||
329 | else | ||
324 | kfree(buf); | 330 | kfree(buf); |
325 | return len; | 331 | return len; |
326 | } | 332 | } |
@@ -687,6 +693,7 @@ static int kernfs_fop_open(struct inode *inode, struct file *file) | |||
687 | error = -ENOMEM; | 693 | error = -ENOMEM; |
688 | if (!of->prealloc_buf) | 694 | if (!of->prealloc_buf) |
689 | goto err_free; | 695 | goto err_free; |
696 | mutex_init(&of->prealloc_mutex); | ||
690 | } | 697 | } |
691 | 698 | ||
692 | /* | 699 | /* |
diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c index b5247226732b..1719649d7ad7 100644 --- a/fs/kernfs/inode.c +++ b/fs/kernfs/inode.c | |||
@@ -54,7 +54,10 @@ static struct kernfs_iattrs *kernfs_iattrs(struct kernfs_node *kn) | |||
54 | iattrs->ia_mode = kn->mode; | 54 | iattrs->ia_mode = kn->mode; |
55 | iattrs->ia_uid = GLOBAL_ROOT_UID; | 55 | iattrs->ia_uid = GLOBAL_ROOT_UID; |
56 | iattrs->ia_gid = GLOBAL_ROOT_GID; | 56 | iattrs->ia_gid = GLOBAL_ROOT_GID; |
57 | iattrs->ia_atime = iattrs->ia_mtime = iattrs->ia_ctime = CURRENT_TIME; | 57 | |
58 | ktime_get_real_ts(&iattrs->ia_atime); | ||
59 | iattrs->ia_mtime = iattrs->ia_atime; | ||
60 | iattrs->ia_ctime = iattrs->ia_atime; | ||
58 | 61 | ||
59 | simple_xattrs_init(&kn->iattr->xattrs); | 62 | simple_xattrs_init(&kn->iattr->xattrs); |
60 | out_unlock: | 63 | out_unlock: |
@@ -236,16 +239,18 @@ ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size) | |||
236 | static inline void set_default_inode_attr(struct inode *inode, umode_t mode) | 239 | static inline void set_default_inode_attr(struct inode *inode, umode_t mode) |
237 | { | 240 | { |
238 | inode->i_mode = mode; | 241 | inode->i_mode = mode; |
239 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; | 242 | inode->i_atime = inode->i_mtime = |
243 | inode->i_ctime = current_fs_time(inode->i_sb); | ||
240 | } | 244 | } |
241 | 245 | ||
242 | static inline void set_inode_attr(struct inode *inode, struct iattr *iattr) | 246 | static inline void set_inode_attr(struct inode *inode, struct iattr *iattr) |
243 | { | 247 | { |
248 | struct super_block *sb = inode->i_sb; | ||
244 | inode->i_uid = iattr->ia_uid; | 249 | inode->i_uid = iattr->ia_uid; |
245 | inode->i_gid = iattr->ia_gid; | 250 | inode->i_gid = iattr->ia_gid; |
246 | inode->i_atime = iattr->ia_atime; | 251 | inode->i_atime = timespec_trunc(iattr->ia_atime, sb->s_time_gran); |
247 | inode->i_mtime = iattr->ia_mtime; | 252 | inode->i_mtime = timespec_trunc(iattr->ia_mtime, sb->s_time_gran); |
248 | inode->i_ctime = iattr->ia_ctime; | 253 | inode->i_ctime = timespec_trunc(iattr->ia_ctime, sb->s_time_gran); |
249 | } | 254 | } |
250 | 255 | ||
251 | static void kernfs_refresh_inode(struct kernfs_node *kn, struct inode *inode) | 256 | static void kernfs_refresh_inode(struct kernfs_node *kn, struct inode *inode) |
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h index 981e53ab84e8..1438e2322d5c 100644 --- a/include/linux/debugfs.h +++ b/include/linux/debugfs.h | |||
@@ -19,9 +19,11 @@ | |||
19 | #include <linux/seq_file.h> | 19 | #include <linux/seq_file.h> |
20 | 20 | ||
21 | #include <linux/types.h> | 21 | #include <linux/types.h> |
22 | #include <linux/compiler.h> | ||
22 | 23 | ||
23 | struct device; | 24 | struct device; |
24 | struct file_operations; | 25 | struct file_operations; |
26 | struct srcu_struct; | ||
25 | 27 | ||
26 | struct debugfs_blob_wrapper { | 28 | struct debugfs_blob_wrapper { |
27 | void *data; | 29 | void *data; |
@@ -41,14 +43,16 @@ struct debugfs_regset32 { | |||
41 | 43 | ||
42 | extern struct dentry *arch_debugfs_dir; | 44 | extern struct dentry *arch_debugfs_dir; |
43 | 45 | ||
44 | #if defined(CONFIG_DEBUG_FS) | 46 | extern struct srcu_struct debugfs_srcu; |
45 | 47 | ||
46 | /* declared over in file.c */ | 48 | #if defined(CONFIG_DEBUG_FS) |
47 | extern const struct file_operations debugfs_file_operations; | ||
48 | 49 | ||
49 | struct dentry *debugfs_create_file(const char *name, umode_t mode, | 50 | struct dentry *debugfs_create_file(const char *name, umode_t mode, |
50 | struct dentry *parent, void *data, | 51 | struct dentry *parent, void *data, |
51 | const struct file_operations *fops); | 52 | const struct file_operations *fops); |
53 | struct dentry *debugfs_create_file_unsafe(const char *name, umode_t mode, | ||
54 | struct dentry *parent, void *data, | ||
55 | const struct file_operations *fops); | ||
52 | 56 | ||
53 | struct dentry *debugfs_create_file_size(const char *name, umode_t mode, | 57 | struct dentry *debugfs_create_file_size(const char *name, umode_t mode, |
54 | struct dentry *parent, void *data, | 58 | struct dentry *parent, void *data, |
@@ -68,6 +72,31 @@ struct dentry *debugfs_create_automount(const char *name, | |||
68 | void debugfs_remove(struct dentry *dentry); | 72 | void debugfs_remove(struct dentry *dentry); |
69 | void debugfs_remove_recursive(struct dentry *dentry); | 73 | void debugfs_remove_recursive(struct dentry *dentry); |
70 | 74 | ||
75 | int debugfs_use_file_start(const struct dentry *dentry, int *srcu_idx) | ||
76 | __acquires(&debugfs_srcu); | ||
77 | |||
78 | void debugfs_use_file_finish(int srcu_idx) __releases(&debugfs_srcu); | ||
79 | |||
80 | ssize_t debugfs_attr_read(struct file *file, char __user *buf, | ||
81 | size_t len, loff_t *ppos); | ||
82 | ssize_t debugfs_attr_write(struct file *file, const char __user *buf, | ||
83 | size_t len, loff_t *ppos); | ||
84 | |||
85 | #define DEFINE_DEBUGFS_ATTRIBUTE(__fops, __get, __set, __fmt) \ | ||
86 | static int __fops ## _open(struct inode *inode, struct file *file) \ | ||
87 | { \ | ||
88 | __simple_attr_check_format(__fmt, 0ull); \ | ||
89 | return simple_attr_open(inode, file, __get, __set, __fmt); \ | ||
90 | } \ | ||
91 | static const struct file_operations __fops = { \ | ||
92 | .owner = THIS_MODULE, \ | ||
93 | .open = __fops ## _open, \ | ||
94 | .release = simple_attr_release, \ | ||
95 | .read = debugfs_attr_read, \ | ||
96 | .write = debugfs_attr_write, \ | ||
97 | .llseek = generic_file_llseek, \ | ||
98 | } | ||
99 | |||
71 | struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry, | 100 | struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry, |
72 | struct dentry *new_dir, const char *new_name); | 101 | struct dentry *new_dir, const char *new_name); |
73 | 102 | ||
@@ -176,6 +205,20 @@ static inline void debugfs_remove(struct dentry *dentry) | |||
176 | static inline void debugfs_remove_recursive(struct dentry *dentry) | 205 | static inline void debugfs_remove_recursive(struct dentry *dentry) |
177 | { } | 206 | { } |
178 | 207 | ||
208 | static inline int debugfs_use_file_start(const struct dentry *dentry, | ||
209 | int *srcu_idx) | ||
210 | __acquires(&debugfs_srcu) | ||
211 | { | ||
212 | return 0; | ||
213 | } | ||
214 | |||
215 | static inline void debugfs_use_file_finish(int srcu_idx) | ||
216 | __releases(&debugfs_srcu) | ||
217 | { } | ||
218 | |||
219 | #define DEFINE_DEBUGFS_ATTRIBUTE(__fops, __get, __set, __fmt) \ | ||
220 | static const struct file_operations __fops = { 0 } | ||
221 | |||
179 | static inline struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry, | 222 | static inline struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry, |
180 | struct dentry *new_dir, char *new_name) | 223 | struct dentry *new_dir, char *new_name) |
181 | { | 224 | { |
diff --git a/include/linux/devcoredump.h b/include/linux/devcoredump.h index c0a360e99f64..269521f143ac 100644 --- a/include/linux/devcoredump.h +++ b/include/linux/devcoredump.h | |||
@@ -1,3 +1,22 @@ | |||
1 | /* | ||
2 | * This file is provided under the GPLv2 license. | ||
3 | * | ||
4 | * GPL LICENSE SUMMARY | ||
5 | * | ||
6 | * Copyright(c) 2015 Intel Deutschland GmbH | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of version 2 of the GNU General Public License as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * The full GNU General Public License is included in this distribution | ||
18 | * in the file called COPYING. | ||
19 | */ | ||
1 | #ifndef __DEVCOREDUMP_H | 20 | #ifndef __DEVCOREDUMP_H |
2 | #define __DEVCOREDUMP_H | 21 | #define __DEVCOREDUMP_H |
3 | 22 | ||
@@ -5,17 +24,62 @@ | |||
5 | #include <linux/module.h> | 24 | #include <linux/module.h> |
6 | #include <linux/vmalloc.h> | 25 | #include <linux/vmalloc.h> |
7 | 26 | ||
27 | #include <linux/scatterlist.h> | ||
28 | #include <linux/slab.h> | ||
29 | |||
30 | /* | ||
31 | * _devcd_free_sgtable - free all the memory of the given scatterlist table | ||
32 | * (i.e. both pages and scatterlist instances) | ||
33 | * NOTE: if two tables allocated and chained using the sg_chain function then | ||
34 | * this function should be called only once on the first table | ||
35 | * @table: pointer to sg_table to free | ||
36 | */ | ||
37 | static inline void _devcd_free_sgtable(struct scatterlist *table) | ||
38 | { | ||
39 | int i; | ||
40 | struct page *page; | ||
41 | struct scatterlist *iter; | ||
42 | struct scatterlist *delete_iter; | ||
43 | |||
44 | /* free pages */ | ||
45 | iter = table; | ||
46 | for_each_sg(table, iter, sg_nents(table), i) { | ||
47 | page = sg_page(iter); | ||
48 | if (page) | ||
49 | __free_page(page); | ||
50 | } | ||
51 | |||
52 | /* then free all chained tables */ | ||
53 | iter = table; | ||
54 | delete_iter = table; /* always points on a head of a table */ | ||
55 | while (!sg_is_last(iter)) { | ||
56 | iter++; | ||
57 | if (sg_is_chain(iter)) { | ||
58 | iter = sg_chain_ptr(iter); | ||
59 | kfree(delete_iter); | ||
60 | delete_iter = iter; | ||
61 | } | ||
62 | } | ||
63 | |||
64 | /* free the last table */ | ||
65 | kfree(delete_iter); | ||
66 | } | ||
67 | |||
68 | |||
8 | #ifdef CONFIG_DEV_COREDUMP | 69 | #ifdef CONFIG_DEV_COREDUMP |
9 | void dev_coredumpv(struct device *dev, const void *data, size_t datalen, | 70 | void dev_coredumpv(struct device *dev, void *data, size_t datalen, |
10 | gfp_t gfp); | 71 | gfp_t gfp); |
11 | 72 | ||
12 | void dev_coredumpm(struct device *dev, struct module *owner, | 73 | void dev_coredumpm(struct device *dev, struct module *owner, |
13 | const void *data, size_t datalen, gfp_t gfp, | 74 | void *data, size_t datalen, gfp_t gfp, |
14 | ssize_t (*read)(char *buffer, loff_t offset, size_t count, | 75 | ssize_t (*read)(char *buffer, loff_t offset, size_t count, |
15 | const void *data, size_t datalen), | 76 | void *data, size_t datalen), |
16 | void (*free)(const void *data)); | 77 | void (*free)(void *data)); |
78 | |||
79 | void dev_coredumpsg(struct device *dev, struct scatterlist *table, | ||
80 | size_t datalen, gfp_t gfp); | ||
17 | #else | 81 | #else |
18 | static inline void dev_coredumpv(struct device *dev, const void *data, | 82 | static inline void dev_coredumpv(struct device *dev, void *data, |
19 | size_t datalen, gfp_t gfp) | 83 | size_t datalen, gfp_t gfp) |
20 | { | 84 | { |
21 | vfree(data); | 85 | vfree(data); |
@@ -23,13 +87,19 @@ static inline void dev_coredumpv(struct device *dev, const void *data, | |||
23 | 87 | ||
24 | static inline void | 88 | static inline void |
25 | dev_coredumpm(struct device *dev, struct module *owner, | 89 | dev_coredumpm(struct device *dev, struct module *owner, |
26 | const void *data, size_t datalen, gfp_t gfp, | 90 | void *data, size_t datalen, gfp_t gfp, |
27 | ssize_t (*read)(char *buffer, loff_t offset, size_t count, | 91 | ssize_t (*read)(char *buffer, loff_t offset, size_t count, |
28 | const void *data, size_t datalen), | 92 | void *data, size_t datalen), |
29 | void (*free)(const void *data)) | 93 | void (*free)(void *data)) |
30 | { | 94 | { |
31 | free(data); | 95 | free(data); |
32 | } | 96 | } |
97 | |||
98 | static inline void dev_coredumpsg(struct device *dev, struct scatterlist *table, | ||
99 | size_t datalen, gfp_t gfp) | ||
100 | { | ||
101 | _devcd_free_sgtable(table); | ||
102 | } | ||
33 | #endif /* CONFIG_DEV_COREDUMP */ | 103 | #endif /* CONFIG_DEV_COREDUMP */ |
34 | 104 | ||
35 | #endif /* __DEVCOREDUMP_H */ | 105 | #endif /* __DEVCOREDUMP_H */ |
diff --git a/include/linux/device.h b/include/linux/device.h index ca90ad8bcd61..38f02814d53a 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
@@ -1288,8 +1288,11 @@ do { \ | |||
1288 | dev_printk(KERN_DEBUG, dev, fmt, ##__VA_ARGS__); \ | 1288 | dev_printk(KERN_DEBUG, dev, fmt, ##__VA_ARGS__); \ |
1289 | } while (0) | 1289 | } while (0) |
1290 | #else | 1290 | #else |
1291 | #define dev_dbg_ratelimited(dev, fmt, ...) \ | 1291 | #define dev_dbg_ratelimited(dev, fmt, ...) \ |
1292 | no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__) | 1292 | do { \ |
1293 | if (0) \ | ||
1294 | dev_printk(KERN_DEBUG, dev, fmt, ##__VA_ARGS__); \ | ||
1295 | } while (0) | ||
1293 | #endif | 1296 | #endif |
1294 | 1297 | ||
1295 | #ifdef VERBOSE_DEBUG | 1298 | #ifdef VERBOSE_DEBUG |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 10d3d8f8a65b..b8b3c72c2aae 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -2427,6 +2427,8 @@ static inline void bd_unlink_disk_holder(struct block_device *bdev, | |||
2427 | 2427 | ||
2428 | /* fs/char_dev.c */ | 2428 | /* fs/char_dev.c */ |
2429 | #define CHRDEV_MAJOR_HASH_SIZE 255 | 2429 | #define CHRDEV_MAJOR_HASH_SIZE 255 |
2430 | /* Marks the bottom of the first segment of free char majors */ | ||
2431 | #define CHRDEV_MAJOR_DYN_END 234 | ||
2430 | extern int alloc_chrdev_region(dev_t *, unsigned, unsigned, const char *); | 2432 | extern int alloc_chrdev_region(dev_t *, unsigned, unsigned, const char *); |
2431 | extern int register_chrdev_region(dev_t, unsigned, const char *); | 2433 | extern int register_chrdev_region(dev_t, unsigned, const char *); |
2432 | extern int __register_chrdev(unsigned int major, unsigned int baseminor, | 2434 | extern int __register_chrdev(unsigned int major, unsigned int baseminor, |
diff --git a/include/linux/isa.h b/include/linux/isa.h index b0270e3814c8..5ab85281230b 100644 --- a/include/linux/isa.h +++ b/include/linux/isa.h | |||
@@ -36,4 +36,36 @@ static inline void isa_unregister_driver(struct isa_driver *d) | |||
36 | } | 36 | } |
37 | #endif | 37 | #endif |
38 | 38 | ||
39 | /** | ||
40 | * module_isa_driver() - Helper macro for registering a ISA driver | ||
41 | * @__isa_driver: isa_driver struct | ||
42 | * @__num_isa_dev: number of devices to register | ||
43 | * | ||
44 | * Helper macro for ISA drivers which do not do anything special in module | ||
45 | * init/exit. This eliminates a lot of boilerplate code. Each module may only | ||
46 | * use this macro once, and calling it replaces module_init and module_exit. | ||
47 | */ | ||
48 | #define module_isa_driver(__isa_driver, __num_isa_dev) \ | ||
49 | static int __init __isa_driver##_init(void) \ | ||
50 | { \ | ||
51 | return isa_register_driver(&(__isa_driver), __num_isa_dev); \ | ||
52 | } \ | ||
53 | module_init(__isa_driver##_init); \ | ||
54 | static void __exit __isa_driver##_exit(void) \ | ||
55 | { \ | ||
56 | isa_unregister_driver(&(__isa_driver)); \ | ||
57 | } \ | ||
58 | module_exit(__isa_driver##_exit); | ||
59 | |||
60 | /** | ||
61 | * max_num_isa_dev() - Maximum possible number registered of an ISA device | ||
62 | * @__ida_dev_ext: ISA device address extent | ||
63 | * | ||
64 | * The highest base address possible for an ISA device is 0x3FF; this results in | ||
65 | * 1024 possible base addresses. Dividing the number of possible base addresses | ||
66 | * by the address extent taken by each device results in the maximum number of | ||
67 | * devices on a system. | ||
68 | */ | ||
69 | #define max_num_isa_dev(__isa_dev_ext) (1024 / __isa_dev_ext) | ||
70 | |||
39 | #endif /* __LINUX_ISA_H */ | 71 | #endif /* __LINUX_ISA_H */ |
diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h index 30f089ebe0a4..96356ef012de 100644 --- a/include/linux/kernfs.h +++ b/include/linux/kernfs.h | |||
@@ -179,6 +179,7 @@ struct kernfs_open_file { | |||
179 | 179 | ||
180 | /* private fields, do not use outside kernfs proper */ | 180 | /* private fields, do not use outside kernfs proper */ |
181 | struct mutex mutex; | 181 | struct mutex mutex; |
182 | struct mutex prealloc_mutex; | ||
182 | int event; | 183 | int event; |
183 | struct list_head list; | 184 | struct list_head list; |
184 | char *prealloc_buf; | 185 | char *prealloc_buf; |
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index f4b797a690ba..e707ab3e1991 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug | |||
@@ -257,6 +257,7 @@ config PAGE_OWNER | |||
257 | 257 | ||
258 | config DEBUG_FS | 258 | config DEBUG_FS |
259 | bool "Debug Filesystem" | 259 | bool "Debug Filesystem" |
260 | select SRCU | ||
260 | help | 261 | help |
261 | debugfs is a virtual file system that kernel developers use to put | 262 | debugfs is a virtual file system that kernel developers use to put |
262 | debugging files into. Enable this option to be able to read and | 263 | debugging files into. Enable this option to be able to read and |
diff --git a/scripts/coccinelle/api/debugfs/debugfs_simple_attr.cocci b/scripts/coccinelle/api/debugfs/debugfs_simple_attr.cocci new file mode 100644 index 000000000000..85cf5408d378 --- /dev/null +++ b/scripts/coccinelle/api/debugfs/debugfs_simple_attr.cocci | |||
@@ -0,0 +1,67 @@ | |||
1 | /// Use DEFINE_DEBUGFS_ATTRIBUTE rather than DEFINE_SIMPLE_ATTRIBUTE | ||
2 | /// for debugfs files. | ||
3 | /// | ||
4 | //# Rationale: DEFINE_SIMPLE_ATTRIBUTE + debugfs_create_file() | ||
5 | //# imposes some significant overhead as compared to | ||
6 | //# DEFINE_DEBUGFS_ATTRIBUTE + debugfs_create_file_unsafe(). | ||
7 | // | ||
8 | // Copyright (C): 2016 Nicolai Stange | ||
9 | // Options: --no-includes | ||
10 | // | ||
11 | |||
12 | virtual context | ||
13 | virtual patch | ||
14 | virtual org | ||
15 | virtual report | ||
16 | |||
17 | @dsa@ | ||
18 | declarer name DEFINE_SIMPLE_ATTRIBUTE; | ||
19 | identifier dsa_fops; | ||
20 | expression dsa_get, dsa_set, dsa_fmt; | ||
21 | position p; | ||
22 | @@ | ||
23 | DEFINE_SIMPLE_ATTRIBUTE@p(dsa_fops, dsa_get, dsa_set, dsa_fmt); | ||
24 | |||
25 | @dcf@ | ||
26 | expression name, mode, parent, data; | ||
27 | identifier dsa.dsa_fops; | ||
28 | @@ | ||
29 | debugfs_create_file(name, mode, parent, data, &dsa_fops) | ||
30 | |||
31 | |||
32 | @context_dsa depends on context && dcf@ | ||
33 | declarer name DEFINE_DEBUGFS_ATTRIBUTE; | ||
34 | identifier dsa.dsa_fops; | ||
35 | expression dsa.dsa_get, dsa.dsa_set, dsa.dsa_fmt; | ||
36 | @@ | ||
37 | * DEFINE_SIMPLE_ATTRIBUTE(dsa_fops, dsa_get, dsa_set, dsa_fmt); | ||
38 | |||
39 | |||
40 | @patch_dcf depends on patch expression@ | ||
41 | expression name, mode, parent, data; | ||
42 | identifier dsa.dsa_fops; | ||
43 | @@ | ||
44 | - debugfs_create_file(name, mode, parent, data, &dsa_fops) | ||
45 | + debugfs_create_file_unsafe(name, mode, parent, data, &dsa_fops) | ||
46 | |||
47 | @patch_dsa depends on patch_dcf && patch@ | ||
48 | identifier dsa.dsa_fops; | ||
49 | expression dsa.dsa_get, dsa.dsa_set, dsa.dsa_fmt; | ||
50 | @@ | ||
51 | - DEFINE_SIMPLE_ATTRIBUTE(dsa_fops, dsa_get, dsa_set, dsa_fmt); | ||
52 | + DEFINE_DEBUGFS_ATTRIBUTE(dsa_fops, dsa_get, dsa_set, dsa_fmt); | ||
53 | |||
54 | |||
55 | @script:python depends on org && dcf@ | ||
56 | fops << dsa.dsa_fops; | ||
57 | p << dsa.p; | ||
58 | @@ | ||
59 | msg="%s should be defined with DEFINE_DEBUGFS_ATTRIBUTE" % (fops) | ||
60 | coccilib.org.print_todo(p[0], msg) | ||
61 | |||
62 | @script:python depends on report && dcf@ | ||
63 | fops << dsa.dsa_fops; | ||
64 | p << dsa.p; | ||
65 | @@ | ||
66 | msg="WARNING: %s should be defined with DEFINE_DEBUGFS_ATTRIBUTE" % (fops) | ||
67 | coccilib.report.print_report(p[0], msg) | ||