Commit 39ab05c8e0b519ff0a04a869f065746e6e8c3d95
Exists in
master
and in
7 other branches
Merge branch 'driver-core-next' of git://git.kernel.org/pub/scm/linux/kernel/git…
…/gregkh/driver-core-2.6 * 'driver-core-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6: (44 commits) debugfs: Silence DEBUG_STRICT_USER_COPY_CHECKS=y warning sysfs: remove "last sysfs file:" line from the oops messages drivers/base/memory.c: fix warning due to "memory hotplug: Speed up add/remove when blocks are larger than PAGES_PER_SECTION" memory hotplug: Speed up add/remove when blocks are larger than PAGES_PER_SECTION SYSFS: Fix erroneous comments for sysfs_update_group(). driver core: remove the driver-model structures from the documentation driver core: Add the device driver-model structures to kerneldoc Translated Documentation/email-clients.txt RAW driver: Remove call to kobject_put(). reboot: disable usermodehelper to prevent fs access efivars: prevent oops on unload when efi is not enabled Allow setting of number of raw devices as a module parameter Introduce CONFIG_GOOGLE_FIRMWARE driver: Google Memory Console driver: Google EFI SMI x86: Better comments for get_bios_ebda() x86: get_bios_ebda_length() misc: fix ti-st build issues params.c: Use new strtobool function to process boolean inputs debugfs: move to new strtobool ... Fix up trivial conflicts in fs/debugfs/file.c due to the same patch being applied twice, and an unrelated cleanup nearby.
Showing 45 changed files Side-by-side Diff
- Documentation/ABI/testing/sysfs-firmware-dmi
- Documentation/ABI/testing/sysfs-firmware-gsmi
- Documentation/ABI/testing/sysfs-firmware-log
- Documentation/ABI/testing/sysfs-kernel-fscaps
- Documentation/DocBook/device-drivers.tmpl
- Documentation/driver-model/bus.txt
- Documentation/driver-model/class.txt
- Documentation/driver-model/device.txt
- Documentation/driver-model/driver.txt
- Documentation/ja_JP/HOWTO
- Documentation/zh_CN/email-clients.txt
- arch/arm/kernel/traps.c
- arch/powerpc/kernel/traps.c
- arch/sh/kernel/traps_32.c
- arch/unicore32/kernel/traps.c
- arch/x86/include/asm/bios_ebda.h
- arch/x86/kernel/dumpstack.c
- drivers/base/core.c
- drivers/base/dd.c
- drivers/base/memory.c
- drivers/base/platform.c
- drivers/char/Kconfig
- drivers/char/mem.c
- drivers/char/raw.c
- drivers/firmware/Kconfig
- drivers/firmware/Makefile
- drivers/firmware/efivars.c
- drivers/firmware/google/Kconfig
- drivers/firmware/google/Makefile
- drivers/firmware/google/gsmi.c
- drivers/firmware/google/memconsole.c
- drivers/misc/ti-st/Kconfig
- drivers/misc/ti-st/st_core.c
- drivers/misc/ti-st/st_kim.c
- drivers/uio/uio.c
- drivers/uio/uio_netx.c
- drivers/uio/uio_pdrv_genirq.c
- fs/debugfs/file.c
- fs/sysfs/file.c
- fs/sysfs/group.c
- include/linux/device.h
- include/linux/sysfs.h
- include/linux/ti_wilink_st.h
- kernel/ksysfs.c
- kernel/sys.c
Documentation/ABI/testing/sysfs-firmware-dmi
... | ... | @@ -14,14 +14,15 @@ |
14 | 14 | |
15 | 15 | DMI is structured as a large table of entries, where |
16 | 16 | each entry has a common header indicating the type and |
17 | - length of the entry, as well as 'handle' that is | |
18 | - supposed to be unique amongst all entries. | |
17 | + length of the entry, as well as a firmware-provided | |
18 | + 'handle' that is supposed to be unique amongst all | |
19 | + entries. | |
19 | 20 | |
20 | 21 | Some entries are required by the specification, but many |
21 | 22 | others are optional. In general though, users should |
22 | 23 | never expect to find a specific entry type on their |
23 | 24 | system unless they know for certain what their firmware |
24 | - is doing. Machine to machine will vary. | |
25 | + is doing. Machine to machine experiences will vary. | |
25 | 26 | |
26 | 27 | Multiple entries of the same type are allowed. In order |
27 | 28 | to handle these duplicate entry types, each entry is |
28 | 29 | |
29 | 30 | |
30 | 31 | |
... | ... | @@ -67,25 +68,24 @@ |
67 | 68 | and the two terminating nul characters. |
68 | 69 | type : The type of the entry. This value is the same |
69 | 70 | as found in the directory name. It indicates |
70 | - how the rest of the entry should be | |
71 | - interpreted. | |
71 | + how the rest of the entry should be interpreted. | |
72 | 72 | instance: The instance ordinal of the entry for the |
73 | 73 | given type. This value is the same as found |
74 | 74 | in the parent directory name. |
75 | - position: The position of the entry within the entirety | |
76 | - of the entirety. | |
75 | + position: The ordinal position (zero-based) of the entry | |
76 | + within the entirety of the DMI entry table. | |
77 | 77 | |
78 | 78 | === Entry Specialization === |
79 | 79 | |
80 | 80 | Some entry types may have other information available in |
81 | - sysfs. | |
81 | + sysfs. Not all types are specialized. | |
82 | 82 | |
83 | 83 | --- Type 15 - System Event Log --- |
84 | 84 | |
85 | 85 | This entry allows the firmware to export a log of |
86 | 86 | events the system has taken. This information is |
87 | 87 | typically backed by nvram, but the implementation |
88 | - details are abstracted by this table. This entries data | |
88 | + details are abstracted by this table. This entry's data | |
89 | 89 | is exported in the directory: |
90 | 90 | |
91 | 91 | /sys/firmware/dmi/entries/15-0/system_event_log |
Documentation/ABI/testing/sysfs-firmware-gsmi
1 | +What: /sys/firmware/gsmi | |
2 | +Date: March 2011 | |
3 | +Contact: Mike Waychison <mikew@google.com> | |
4 | +Description: | |
5 | + Some servers used internally at Google have firmware | |
6 | + that provides callback functionality via explicit SMI | |
7 | + triggers. Some of the callbacks are similar to those | |
8 | + provided by the EFI runtime services page, but due to | |
9 | + historical reasons this different entry-point has been | |
10 | + used. | |
11 | + | |
12 | + The gsmi driver implements the kernel's abstraction for | |
13 | + these firmware callbacks. Currently, this functionality | |
14 | + is limited to handling the system event log and getting | |
15 | + access to EFI-style variables stored in nvram. | |
16 | + | |
17 | + Layout: | |
18 | + | |
19 | + /sys/firmware/gsmi/vars: | |
20 | + | |
21 | + This directory has the same layout (and | |
22 | + underlying implementation as /sys/firmware/efi/vars. | |
23 | + See Documentation/ABI/*/sysfs-firmware-efi-vars | |
24 | + for more information on how to interact with | |
25 | + this structure. | |
26 | + | |
27 | + /sys/firmware/gsmi/append_to_eventlog - write-only: | |
28 | + | |
29 | + This file takes a binary blob and passes it onto | |
30 | + the firmware to be timestamped and appended to | |
31 | + the system eventlog. The binary format is | |
32 | + interpreted by the firmware and may change from | |
33 | + platform to platform. The only kernel-enforced | |
34 | + requirement is that the blob be prefixed with a | |
35 | + 32bit host-endian type used as part of the | |
36 | + firmware call. | |
37 | + | |
38 | + /sys/firmware/gsmi/clear_config - write-only: | |
39 | + | |
40 | + Writing any value to this file will cause the | |
41 | + entire firmware configuration to be reset to | |
42 | + "factory defaults". Callers should assume that | |
43 | + a reboot is required for the configuration to be | |
44 | + cleared. | |
45 | + | |
46 | + /sys/firmware/gsmi/clear_eventlog - write-only: | |
47 | + | |
48 | + This file is used to clear out a portion/the | |
49 | + whole of the system event log. Values written | |
50 | + should be values between 1 and 100 inclusive (in | |
51 | + ASCII) representing the fraction of the log to | |
52 | + clear. Not all platforms support fractional | |
53 | + clearing though, and this writes to this file | |
54 | + will error out if the firmware doesn't like your | |
55 | + submitted fraction. | |
56 | + | |
57 | + Callers should assume that a reboot is needed | |
58 | + for this operation to complete. |
Documentation/ABI/testing/sysfs-firmware-log
Documentation/ABI/testing/sysfs-kernel-fscaps
Documentation/DocBook/device-drivers.tmpl
... | ... | @@ -96,10 +96,10 @@ |
96 | 96 | |
97 | 97 | <chapter id="devdrivers"> |
98 | 98 | <title>Device drivers infrastructure</title> |
99 | + <sect1><title>The Basic Device Driver-Model Structures </title> | |
100 | +!Iinclude/linux/device.h | |
101 | + </sect1> | |
99 | 102 | <sect1><title>Device Drivers Base</title> |
100 | -<!-- | |
101 | -X!Iinclude/linux/device.h | |
102 | ---> | |
103 | 103 | !Edrivers/base/driver.c |
104 | 104 | !Edrivers/base/core.c |
105 | 105 | !Edrivers/base/class.c |
Documentation/driver-model/bus.txt
... | ... | @@ -3,24 +3,7 @@ |
3 | 3 | |
4 | 4 | Definition |
5 | 5 | ~~~~~~~~~~ |
6 | - | |
7 | -struct bus_type { | |
8 | - char * name; | |
9 | - | |
10 | - struct subsystem subsys; | |
11 | - struct kset drivers; | |
12 | - struct kset devices; | |
13 | - | |
14 | - struct bus_attribute * bus_attrs; | |
15 | - struct device_attribute * dev_attrs; | |
16 | - struct driver_attribute * drv_attrs; | |
17 | - | |
18 | - int (*match)(struct device * dev, struct device_driver * drv); | |
19 | - int (*hotplug) (struct device *dev, char **envp, | |
20 | - int num_envp, char *buffer, int buffer_size); | |
21 | - int (*suspend)(struct device * dev, pm_message_t state); | |
22 | - int (*resume)(struct device * dev); | |
23 | -}; | |
6 | +See the kerneldoc for the struct bus_type. | |
24 | 7 | |
25 | 8 | int bus_register(struct bus_type * bus); |
26 | 9 |
Documentation/driver-model/class.txt
... | ... | @@ -27,22 +27,7 @@ |
27 | 27 | typedef int (*devclass_add)(struct device *); |
28 | 28 | typedef void (*devclass_remove)(struct device *); |
29 | 29 | |
30 | -struct device_class { | |
31 | - char * name; | |
32 | - rwlock_t lock; | |
33 | - u32 devnum; | |
34 | - struct list_head node; | |
35 | - | |
36 | - struct list_head drivers; | |
37 | - struct list_head intf_list; | |
38 | - | |
39 | - struct driver_dir_entry dir; | |
40 | - struct driver_dir_entry device_dir; | |
41 | - struct driver_dir_entry driver_dir; | |
42 | - | |
43 | - devclass_add add_device; | |
44 | - devclass_remove remove_device; | |
45 | -}; | |
30 | +See the kerneldoc for the struct class. | |
46 | 31 | |
47 | 32 | A typical device class definition would look like: |
48 | 33 |
Documentation/driver-model/device.txt
... | ... | @@ -2,96 +2,7 @@ |
2 | 2 | The Basic Device Structure |
3 | 3 | ~~~~~~~~~~~~~~~~~~~~~~~~~~ |
4 | 4 | |
5 | -struct device { | |
6 | - struct list_head g_list; | |
7 | - struct list_head node; | |
8 | - struct list_head bus_list; | |
9 | - struct list_head driver_list; | |
10 | - struct list_head intf_list; | |
11 | - struct list_head children; | |
12 | - struct device * parent; | |
13 | - | |
14 | - char name[DEVICE_NAME_SIZE]; | |
15 | - char bus_id[BUS_ID_SIZE]; | |
16 | - | |
17 | - spinlock_t lock; | |
18 | - atomic_t refcount; | |
19 | - | |
20 | - struct bus_type * bus; | |
21 | - struct driver_dir_entry dir; | |
22 | - | |
23 | - u32 class_num; | |
24 | - | |
25 | - struct device_driver *driver; | |
26 | - void *driver_data; | |
27 | - void *platform_data; | |
28 | - | |
29 | - u32 current_state; | |
30 | - unsigned char *saved_state; | |
31 | - | |
32 | - void (*release)(struct device * dev); | |
33 | -}; | |
34 | - | |
35 | -Fields | |
36 | -~~~~~~ | |
37 | -g_list: Node in the global device list. | |
38 | - | |
39 | -node: Node in device's parent's children list. | |
40 | - | |
41 | -bus_list: Node in device's bus's devices list. | |
42 | - | |
43 | -driver_list: Node in device's driver's devices list. | |
44 | - | |
45 | -intf_list: List of intf_data. There is one structure allocated for | |
46 | - each interface that the device supports. | |
47 | - | |
48 | -children: List of child devices. | |
49 | - | |
50 | -parent: *** FIXME *** | |
51 | - | |
52 | -name: ASCII description of device. | |
53 | - Example: " 3Com Corporation 3c905 100BaseTX [Boomerang]" | |
54 | - | |
55 | -bus_id: ASCII representation of device's bus position. This | |
56 | - field should be a name unique across all devices on the | |
57 | - bus type the device belongs to. | |
58 | - | |
59 | - Example: PCI bus_ids are in the form of | |
60 | - <bus number>:<slot number>.<function number> | |
61 | - This name is unique across all PCI devices in the system. | |
62 | - | |
63 | -lock: Spinlock for the device. | |
64 | - | |
65 | -refcount: Reference count on the device. | |
66 | - | |
67 | -bus: Pointer to struct bus_type that device belongs to. | |
68 | - | |
69 | -dir: Device's sysfs directory. | |
70 | - | |
71 | -class_num: Class-enumerated value of the device. | |
72 | - | |
73 | -driver: Pointer to struct device_driver that controls the device. | |
74 | - | |
75 | -driver_data: Driver-specific data. | |
76 | - | |
77 | -platform_data: Platform data specific to the device. | |
78 | - | |
79 | - Example: for devices on custom boards, as typical of embedded | |
80 | - and SOC based hardware, Linux often uses platform_data to point | |
81 | - to board-specific structures describing devices and how they | |
82 | - are wired. That can include what ports are available, chip | |
83 | - variants, which GPIO pins act in what additional roles, and so | |
84 | - on. This shrinks the "Board Support Packages" (BSPs) and | |
85 | - minimizes board-specific #ifdefs in drivers. | |
86 | - | |
87 | -current_state: Current power state of the device. | |
88 | - | |
89 | -saved_state: Pointer to saved state of the device. This is usable by | |
90 | - the device driver controlling the device. | |
91 | - | |
92 | -release: Callback to free the device after all references have | |
93 | - gone away. This should be set by the allocator of the | |
94 | - device (i.e. the bus driver that discovered the device). | |
5 | +See the kerneldoc for the struct device. | |
95 | 6 | |
96 | 7 | |
97 | 8 | Programming Interface |
Documentation/driver-model/driver.txt
1 | 1 | |
2 | 2 | Device Drivers |
3 | 3 | |
4 | -struct device_driver { | |
5 | - char * name; | |
6 | - struct bus_type * bus; | |
7 | - | |
8 | - struct completion unloaded; | |
9 | - struct kobject kobj; | |
10 | - list_t devices; | |
11 | - | |
12 | - struct module *owner; | |
13 | - | |
14 | - int (*probe) (struct device * dev); | |
15 | - int (*remove) (struct device * dev); | |
16 | - | |
17 | - int (*suspend) (struct device * dev, pm_message_t state); | |
18 | - int (*resume) (struct device * dev); | |
19 | -}; | |
20 | - | |
4 | +See the kerneldoc for the struct device_driver. | |
21 | 5 | |
22 | 6 | |
23 | 7 | Allocation |
Documentation/ja_JP/HOWTO
... | ... | @@ -11,14 +11,14 @@ |
11 | 11 | fork. So if you have any comments or updates for this file, please try |
12 | 12 | to update the original English file first. |
13 | 13 | |
14 | -Last Updated: 2008/10/24 | |
14 | +Last Updated: 2011/03/31 | |
15 | 15 | ================================== |
16 | 16 | ใใใฏใ |
17 | -linux-2.6.28/Documentation/HOWTO | |
17 | +linux-2.6.38/Documentation/HOWTO | |
18 | 18 | ใฎๅ่จณใงใใ |
19 | 19 | |
20 | 20 | ็ฟป่จณๅฃไฝ๏ผ JF ใใญใธใงใฏใ < http://www.linux.or.jp/JF/ > |
21 | -็ฟป่จณๆฅ๏ผ 2008/10/24 | |
21 | +็ฟป่จณๆฅ๏ผ 2011/3/28 | |
22 | 22 | ็ฟป่จณ่ ๏ผ Tsugikazu Shibata <tshibata at ab dot jp dot nec dot com> |
23 | 23 | ๆ กๆญฃ่ ๏ผ ๆพๅใใ <nbh--mats at nifty dot com> |
24 | 24 | ๅฐๆ ้ ๅ ธใใ (Masanori Kobayasi) <zap03216 at nifty dot ne dot jp> |
25 | 25 | |
... | ... | @@ -256,8 +256,8 @@ |
256 | 256 | - ใกใคใณใฎ 2.6.x ใซใผใใซใใชใผ |
257 | 257 | - 2.6.x.y -stable ใซใผใใซใใชใผ |
258 | 258 | - 2.6.x -git ใซใผใใซใใใ |
259 | - - 2.6.x -mm ใซใผใใซใใใ | |
260 | 259 | - ใตใใทในใใ ๆฏใฎใซใผใใซใใชใผใจใใใ |
260 | + - ็ตฑๅใในใใฎใใใฎ 2.6.x -next ใซใผใใซใใชใผ | |
261 | 261 | |
262 | 262 | 2.6.x ใซใผใใซใใชใผ |
263 | 263 | ----------------- |
264 | 264 | |
... | ... | @@ -268,9 +268,9 @@ |
268 | 268 | |
269 | 269 | - ๆฐใใใซใผใใซใใชใชใผในใใใ็ดๅพใซใ2้ฑ้ใฎ็นๅฅๆ้ใ่จญใใใใ |
270 | 270 | ใใฎๆ้ไธญใซใใกใณใใ้ใฏ Linus ใซๅคงใใชๅทฎๅใ้ใใใจใใงใใพใใ |
271 | - ใใฎใใใชๅทฎๅใฏ้ๅธธ -mm ใซใผใใซใซๆฐ้ฑ้ๅซใพใใฆใใใใใใงใใ | |
271 | + ใใฎใใใชๅทฎๅใฏ้ๅธธ -next ใซใผใใซใซๆฐ้ฑ้ๅซใพใใฆใใใใใใงใใ | |
272 | 272 | ๅคงใใชๅคๆดใฏ git(ใซใผใใซใฎใฝใผใน็ฎก็ใใผใซใ่ฉณ็ดฐใฏ |
273 | - http://git.or.cz/ ๅ็ ง) ใไฝฟใฃใฆ้ใใฎใๅฅฝใพใใใใๆนใงใใใใใ | |
273 | + http://git-scm.com/ ๅ็ ง) ใไฝฟใฃใฆ้ใใฎใๅฅฝใพใใใใๆนใงใใใใใ | |
274 | 274 | ใใใกใคใซใฎๅฝขๅผใฎใพใพ้ใใฎใงใๅๅใงใใ |
275 | 275 | |
276 | 276 | - 2้ฑ้ๅพใ-rc1 ใซใผใใซใใชใชใผในใใใใใฎๅพใซใฏใซใผใใซๅ จไฝใฎๅฎๅฎ |
277 | 277 | |
278 | 278 | |
279 | 279 | |
280 | 280 | |
281 | 281 | |
282 | 282 | |
283 | 283 | |
... | ... | @@ -333,87 +333,45 @@ |
333 | 333 | ใใฏ -rc ใซใผใใซใจๆฏในใฆใใใใใๅคงไธๅคซใใฉใใใ็ขบ่ชใใชใใง่ชๅ็ |
334 | 334 | ใซ็ๆใใใใฎใงใใใๅฎ้จ็ใงใใ |
335 | 335 | |
336 | -2.6.x -mm ใซใผใใซใใใ | |
337 | ------------------------- | |
338 | - | |
339 | -Andrew Morton ใซใใฃใฆใชใชใผในใใใๅฎ้จ็ใชใซใผใใซใใใ็พคใงใใ | |
340 | -Andrew ใฏๅๅฅใฎใตใใทในใใ ใซใผใใซใใชใผใจใใใใๅ จใฆ้ใใฆใใฆ | |
341 | -linux-kernel ใกใผใชใณใฐใชในใใงๅ้ใใใๅคๆฐใฎใใใใจๅๆใซไธใคใซใพ | |
342 | -ใจใใพใใ | |
343 | -ใใฎใใชใผใฏๆฐๆฉ่ฝใจใใใใๆค่จผใใใๅ ดใจใชใใพใใใใๆ้ใฎ้ใใใ | |
344 | -ใ -mm ใซๅ ฅใฃใฆไพกๅคใ่จผๆใใใใใAndrew ใใตใใทในใใ ใกใณใใใใ | |
345 | -ใกใคใณใฉใคใณใธๅ ฅใใใใใซ Linus ใซใใใทใฅใใพใใ | |
346 | - | |
347 | -ใกใคใณใซใผใใซใใชใผใซๅซใใใใใซ Linus ใซ้ใๅใซใใในใฆใฎๆฐใใใใ | |
348 | -ใใ -mm ใใชใผใงใในใใใใใใจใๅผทใๆจๅฅจใใใฆใใพใใใใผใธใฆใฃใณ | |
349 | -ใใฆใ้ใๅใซ -mm ใใชใผใซ็พใใชใใฃใใใใใฏใกใคใณใฉใคใณใซใใผใธใ | |
350 | -ใใใใจใฏๅฐ้ฃใซใชใใพใใ | |
351 | - | |
352 | -ใใใใฎใซใผใใซใฏๅฎๅฎใใฆๅไฝใในใใทในใใ ใจใใฆไฝฟใใฎใซใฏ้ฉๅใงใฏใ | |
353 | -ใใพใใใใใซใผใใซใใฉใณใใฎไธญใงใใใฃใจใๅไฝใซใชในใฏใ้ซใใใฎใงใใ | |
354 | - | |
355 | -ใใใใชใใใใซใผใใซ้็บใใญใปในใฎๆฏๆดใใใใใจๆใฃใฆใใใฎใงใใใฐใ | |
356 | -ใฉใใใใใใฎใซใผใใซใชใชใผในใใในใใซไฝฟใฃใฆใฟใฆใใใใฆใใๅ้กใใ | |
357 | -ใใฐใใพใใใๅ จใฆใๆญฃใใๅไฝใใใจใใฆใใlinux-kernel ใกใผใชใณใฐใช | |
358 | -ในใใซใใฃใผใใใใฏใๆไพใใฆใใ ใใใ | |
359 | - | |
360 | -ใในใฆใฎไปใฎๅฎ้จ็ใใใใซๅ ใใฆใใใใใฎใซใผใใซใฏ้ๅธธใชใชใผในๆ็นใง | |
361 | -ใกใคใณใฉใคใณใฎ -git ใซใผใใซใซๅซใพใใๅ จใฆใฎๅคๆดใๅซใใงใใพใใ | |
362 | - | |
363 | --mm ใซใผใใซใฏๆฑบใพใฃใในใฑใธใฅใผใซใงใฏใชใชใผในใใใพใใใใใใ้ๅธธๅนพ | |
364 | -ใคใใฎ -mm ใซใผใใซ (1 ใใ 3 ใๆฎ้๏ผใๅ-rc ใซใผใใซใฎ้ใซใชใชใผในใ | |
365 | -ใใพใใ | |
366 | - | |
367 | 336 | ใตใใทในใใ ๆฏใฎใซใผใใซใใชใผใจใใใ |
368 | 337 | ------------------------------------------- |
369 | 338 | |
370 | -ใซใผใใซใฎๆงใ ใช้ ๅใงไฝใ่ตทใใฆใใใใ่ฆใใใใใใซใใใใใๅคใใฎ | |
371 | -ใซใผใใซใตใใทในใใ ้็บ่ ใฏๅฝผใใฎ้็บใใชใผใๅ ฌ้ใใฆใใพใใใใใใฎ | |
372 | -ใใชใผใฏ่ชฌๆใใใใใซ -mm ใซใผใใซใชใชใผในใซๅ ฅใ่พผใพใใพใใ | |
339 | +ใใใใใฎใซใผใใซใตใใทในใใ ใฎใกใณใใ้ใฏ --- ใใใฆๅคใใฎใซใผใใซ | |
340 | +ใตใใทในใใ ใฎ้็บ่ ้ใ --- ๅ่ชใฎๆๆฐใฎ้็บ็ถๆณใใฝใผในใชใใธใใชใซ | |
341 | +ๅ ฌ้ใใฆใใพใใใใฎใใใ่ชๅใจใฏ็ฐใชใ้ ๅใฎใซใผใใซใงไฝใ่ตทใใฆใใ | |
342 | +ใใไปใฎไบบใ่ฆใใใใใใซใชใฃใฆใใพใใ้็บใๆฉใ้ฒใใงใใ้ ๅใงใฏใ | |
343 | +้็บ่ ใฏ่ช่บซใฎๆ็จฟใใฉใฎใตใใทในใใ ใซใผใใซใใชใผใๅ ใซใใฆใใใ่ณชๅ | |
344 | +ใใใใฎใงใใใฎๆ็จฟใจใใงใซ้ฒ่กไธญใฎไปใฎไฝๆฅญใจใฎ่ก็ชใ้ฟใใใใพใใ | |
373 | 345 | |
374 | -ไปฅไธใฏใใพใใพใชใซใผใใซใใชใผใฎไธญใฎใใใคใใฎใชในใ- | |
346 | +ๅคง้จๅใฎใใใใฎใชใใธใใชใฏ git ใใชใผใงใใใใใใใฎไปใฎ SCM ใ | |
347 | +quilt ใทใชใผใบใจใใฆๅ ฌ้ใใใฆใใใใใใญใฅใผใไฝฟใใใฆใใพใใใใใ | |
348 | +ใฎใตใใทในใใ ใชใใธใใชใฎใขใใฌในใฏ MAINTAINERS ใใกใคใซใซใชในใใใ | |
349 | +ใฆใใพใใใใใใฎๅคใใฏ http://git.kernel.org/ ใงๅ็ งใใใใจใใงใใพ | |
350 | +ใใ | |
375 | 351 | |
376 | - git ใใชใผ- | |
377 | - - Kbuild ใฎ้็บใใชใผใSam Ravnborg <sam@ravnborg.org> | |
378 | - git.kernel.org:/pub/scm/linux/kernel/git/sam/kbuild.git | |
352 | +ๆๆกใใใใใใใใใฎใใใชใตใใทในใใ ใใชใผใซใณใใใใใใๅใซใใกใผ | |
353 | +ใชใณใฐใชในใใงไบๅใซใฌใใฅใผใซใใใใใพใ๏ผไปฅไธใฎๅฏพๅฟใใใปใฏใทใงใณใ | |
354 | +ๅ็ ง๏ผใใใใคใใฎใซใผใใซใตใใทในใใ ใงใฏใใใฎใฌใใฅใผใฏ patchwork | |
355 | +ใจใใใใผใซใซใใฃใฆ่ฟฝ่ทกใใใพใใPatchwork ใฏ web ใคใณใฟใผใใงใคในใซ | |
356 | +ใใฃใฆใใใๆ็จฟใฎ่กจ็คบใใใใใธใฎใณใกใณใไปใใๆน่จใชใฉใใงใใใใใฆ | |
357 | +ใกใณใใใฏใใใใซๅฏพใใฆใใฌใใฅใผไธญใๅไปๆธใฟใๆๅฆใจใใใใใชใใผใฏ | |
358 | +ใใคใใใใจใใงใใพใใๅคง้จๅใฎใใใใฎ patchwork ใฎใตใคใใฏ | |
359 | +http://patchwork.kernel.org/ ใงใชในใใใใฆใใพใใ | |
379 | 360 | |
380 | - - ACPI ใฎ้็บใใชใผใ Len Brown <len.brown@intel.com> | |
381 | - git.kernel.org:/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git | |
361 | +็ตฑๅใในใใฎใใใฎ 2.6.x -next ใซใผใใซใใชใผ | |
362 | +--------------------------------------------- | |
382 | 363 | |
383 | - - Block ใฎ้็บใใชใผใJens Axboe <axboe@suse.de> | |
384 | - git.kernel.org:/pub/scm/linux/kernel/git/axboe/linux-2.6-block.git | |
364 | +ใตใใทในใใ ใใชใผใฎๆดๆฐๅ ๅฎนใใกใคใณใฉใคใณใฎ 2.6.x ใใชใผใซใใผใธใใ | |
365 | +ใๅใซใใใใใฏ็ตฑๅใในใใใใๅฟ ่ฆใใใใพใใใใฎ็ฎ็ใฎใใใๅฎ่ณช็ | |
366 | +ใซๅ จใตใใทในใใ ใใชใผใใใปใผๆฏๆฅใใซใใใฆใงใใ็นๅฅใชใในใ็จใฎใช | |
367 | +ใใธใใชใๅญๅจใใพใ- | |
368 | + http://git.kernel.org/?p=linux/kernel/git/sfr/linux-next.git | |
369 | + http://linux.f-seidel.de/linux-next/pmwiki/ | |
385 | 370 | |
386 | - - DRM ใฎ้็บใใชใผใDave Airlie <airlied@linux.ie> | |
387 | - git.kernel.org:/pub/scm/linux/kernel/git/airlied/drm-2.6.git | |
371 | +ใใฎใใๆนใซใใฃใฆใ-next ใซใผใใซใฏๆฌกใฎใใผใธๆฉไผใงใฉใใชใใฎใใกใคใณ | |
372 | +ใฉใคใณใซใผใใซใซใใผใธใใใใใใใใพใใชใฎๅฑๆใๆไพใใพใใ-next | |
373 | +ใซใผใใซใฎๅฎ่กใในใใ่กใๅ้บๅฅฝใใชใในใฟใผใฏๅคงใใซๆญ่ฟใใใพใ | |
388 | 374 | |
389 | - - ia64 ใฎ้็บใใชใผใTony Luck <tony.luck@intel.com> | |
390 | - git.kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6.git | |
391 | - | |
392 | - - infiniband, Roland Dreier <rolandd@cisco.com> | |
393 | - git.kernel.org:/pub/scm/linux/kernel/git/roland/infiniband.git | |
394 | - | |
395 | - - libata, Jeff Garzik <jgarzik@pobox.com> | |
396 | - git.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev.git | |
397 | - | |
398 | - - ใใใใฏใผใฏใใฉใคใ, Jeff Garzik <jgarzik@pobox.com> | |
399 | - git.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6.git | |
400 | - | |
401 | - - pcmcia, Dominik Brodowski <linux@dominikbrodowski.net> | |
402 | - git.kernel.org:/pub/scm/linux/kernel/git/brodo/pcmcia-2.6.git | |
403 | - | |
404 | - - SCSI, James Bottomley <James.Bottomley@hansenpartnership.com> | |
405 | - git.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git | |
406 | - | |
407 | - - x86, Ingo Molnar <mingo@elte.hu> | |
408 | - git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86.git | |
409 | - | |
410 | - quilt ใใชใผ- | |
411 | - - USB, ใใฉใคใใณใขใจ I2C, Greg Kroah-Hartman <gregkh@suse.de> | |
412 | - kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/ | |
413 | - | |
414 | - ใใฎไปใฎใซใผใใซใใชใผใฏ http://git.kernel.org/ ใจ MAINTAINERS ใใก | |
415 | - ใคใซใซไธ่ฆง่กจใใใใพใใ | |
416 | - | |
417 | 375 | ใใฐใฌใใผใ |
418 | 376 | ------------- |
419 | 377 | |
... | ... | @@ -673,10 +631,9 @@ |
673 | 631 | ใใจใใใใในใฟใผใใใใฎใงใใใใ |
674 | 632 | |
675 | 633 | Paolo Ciarrocchi ใซๆ่ฌใๅฝผใฏๅฝผใฎๆธใใ "Development Process" |
676 | -(http://linux.tar.bz/articles/2.6-development_process)ใปใฏใทใง | |
677 | -ใณใใใฎใใญในใใฎๅๅใซใใใใจใ่จฑๅฏใใฆใใใพใใใ | |
678 | -Rundy Dunlap ใจ Gerrit Huizenga ใฏใกใผใชใณใฐใชในใใงใใในใใใจใจใใฃ | |
679 | -ใฆใฏใใใชใใใจใฎใชในใใๆไพใใฆใใใพใใใ | |
634 | +(http://lwn.net/Articles/94386/) ใปใฏใทใงใณใใใฎใใญในใใฎๅๅใซใใ | |
635 | +ใใจใ่จฑๅฏใใฆใใใพใใใRundy Dunlap ใจ Gerrit Huizenga ใฏใกใผใชใณใฐ | |
636 | +ใชในใใงใใในใใใจใจใใฃใฆใฏใใใชใใใจใฎใชในใใๆไพใใฆใใใพใใใ | |
680 | 637 | ไปฅไธใฎไบบใ ใฎใฌใใฅใผใใณใกใณใใ่ฒข็ฎใซๆ่ฌใ |
681 | 638 | Pat Mochel, Hanna Linder, Randy Dunlap, Kay Sievers, |
682 | 639 | Vojtech Pavlik, Jan Kara, Josh Boyer, Kees Cook, Andrew Morton, Andi |
Documentation/zh_CN/email-clients.txt
1 | +้?Chinese translated version of Documentation/email-clients.txt | |
2 | + | |
3 | +If you have any comment or update to the content, please contact the | |
4 | +original document maintainer directly. However, if you have a problem | |
5 | +communicating in English you can also ask the Chinese maintainer for | |
6 | +help. Contact the Chinese maintainer if this translation is outdated | |
7 | +or if there is a problem with the translation. | |
8 | + | |
9 | +Chinese maintainer: Harry Wei <harryxiyou@gmail.com> | |
10 | +--------------------------------------------------------------------- | |
11 | +Documentation/email-clients.txt ???ๆถ????็ผๆ?? | |
12 | + | |
13 | +ๆฟก??????ๅฎ ??็็????ๅญ?็???????????็น็ธ??็้ฃ?ๅญ?ใจ??็ปฏ่ฏฒ?????ๅฆ๏ฝ??็ผๅญ?ใ?????ๆฟก????ๆตฃ?ๆตฃ่ทจ?ใจ?่พจ?? | |
14 | +ๆตใ???????ไผด?ๅง??็?้?ๆถ????ๆต ใฅ??ๆถ???????็ผๅญ?ใ??ๅงน???โฟ??ๆฟก???????็ผๆ????ๅญ?้ข???????่ต?????็ผ? | |
15 | +็?็???ใฉ??ๆฃฐ?้?็็ฏ??็ปฏ่ฎณ่ ??????็ผๅญ?ใ????? | |
16 | + | |
17 | +ๆถ???????็ผๅญ?ใ??้? ็ๆง??ๆฟ? Harry Wei <harryxiyou@gmail.com> | |
18 | +ๆถ???????็ผๆ?????้? ็ๆง??ๆฟ? Harry Wei <harryxiyou@gmail.com> | |
19 | +ๆถ?????????ยค?????้? Yinglin Luan <synmyth@gmail.com> | |
20 | + Xiaochen Wang <wangxiaochen0@gmail.com> | |
21 | + yaxinsn <yaxinsn@163.com> | |
22 | + | |
23 | +ๆต ใค??ๆถ็?๏ฝ?? | |
24 | +--------------------------------------------------------------------- | |
25 | + | |
26 | +Linux???ๆต ่ทบ?ใก?้ฃ?????็ผ?ๆทโ?? | |
27 | +====================================================================== | |
28 | + | |
29 | +?????????็ผ? | |
30 | +---------------------------------------------------------------------- | |
31 | +Linux?????ๆญหๆถ???????ๆฉ????ๆต ๆฐ?????ๆตใ??้????ๆฟ่ฅ??็ใค??ๆตฃ?ๆถๆดช??ๆต ๆต????????ๅฎ?????????????ๆต?็ผๅญ?ใ?? | |
32 | +??ใฆ?ๅ ??ๆต ่ฎน??ๆตฃ???????ๆต ๅ?????็น่ง?็ ??ๆด?็ใฆ??"text/plain"?????ๆฐ??้????ๆต ๆต????????ๆถ?็ง???????้? | |
33 | +???ๆถ้ธฟ??ๆตผ?ๆตฃ่ฏหๆถ????ๅฏฎ???ใฉ?ใฅ????ใจ??็้ธฟ??็ป?ๆถ???????ๅฏฐ???ไผด?ไฟฑ?? | |
34 | + | |
35 | +??ใฆ?ใฅ?????Linux?????ๆญหๆถ???????ๆต ่ทบ?ใก?้ฃ????ใฅ?????็ใค????่ทบ??็ใฅ??ๆต?????????????ๆฟฎ???่ต?????ๆธ?ๆฟก?้? | |
36 | +ๆต ?ๆต ?ๆถ???่ฅ?็ฐ?????????????ใ ?ๆฐใ็ป???????็ป็?็กท???????่ซ????ใฆ??ๆถ?็????ๅฏฎ?ๆพถๅญ?????็ผ?็ไฟฑ?? | |
37 | + | |
38 | +ๆถ?็????ๆฉ?"format=flowed"ๅฆฏโณ????????็ใค?????ๆฉ???่??ๅฏฎ?็ง่?????ๆฃฐ????ๆต ใฅ?????็นๅด?????็???? | |
39 | + | |
40 | +ๆถ?็?็โ????????ๆต ่ทบ?ใก?้ฃ??ๆฉ?็??????ใฆ?ใฃ?????ๆฉ???่??ๆตผ???ๆ??ๆตฃ????็ใค????? | |
41 | + | |
42 | +???ๆต ่ทบ?ใก?้ฃ??ๆถ???่ฅ?็ฐ???????????็?็ป????็ผ??????็ฐ?????็??????????็ใค???????่ฅ??ASCII??????UTF-8็ผ??????็ฐ??้? | |
43 | +ๆฟก????ๆตฃ?ๆตฃ่ทจ??UTF-8็ผ??????็ฐ???????????ๆต ่ฎน????๏ฝ??ๆตฃ?็?ๆตผ???ๅฎ??ๆถ?ๆต??????่????????็?็ป???????ๆฃฐ???? | |
44 | + | |
45 | +???ๆต ่ทบ?ใก?้ฃ??ๆด?็ใฅ่ฐ???้ชๆต??ๆท???? References: ?????? In-Reply-To: ???ๆฃฐ?้???๏ฝ?? | |
46 | +???ๆต ๆฐ??ๆฃฐ?็ๅ??ๆตผ?ๆถ??????? | |
47 | + | |
48 | +ๆพถ???ๅ??็ฏ?(?????????็ๅฏธ??็ฏ?)???็ฏ้????็?ใค??็ใค??้????ๆถๅ?ๆฐใ็ป?ๆตผ?ๆ????ๆถ่นโ??็ฌบ??ๆตฃ่ทจ??xclipboard, xclip | |
49 | +??????xcutselๆถ?็็จฟ??ๆต ใฏ??ๆตฃ???????ๆฟ่ฅ??็?ๆถ?ๆถ?????????ๅฎ??ๆตฃ่ทจ?ใฅ????ๅ??็ฏ???? | |
50 | + | |
51 | +ๆถ?็???ใคๅจ???PGP/GPG็ผๆ????????ๆต ๆต่ ??????็ใค?????ๆฉ???่??ๆตฃๅฎ??ๅฏฐ?ๆพถ???????ๆถ???ๅ?่ฏฒ??????????ใค??ๆตฃ????็ใค????? | |
52 | +้?ๆฉ?ๆถ????ๆฃฐ?ๆด?็ใฆ?????ๆต ใคๆ จๆพถ????้? | |
53 | + | |
54 | +??ใง???????ๆ??ๆต ่ทบ??็ใฅ?????็ใค??ๆถ????้?็ผ????ๅฎธๅ?????ๆถ?ๆถ?็ใค?????ๆถ?ๆถ???????ๆถ็ป??้?ๆท?็???ใฆ?่ทบ?ๆฎ?? | |
55 | +???ๆต ่ฎน??็?็ใค?????'patch'??ๆๆค???ๆถ?้?ๆฟก??????????ๆต?้????็ผ??????ๆ??ๆต ่ทบ??็ใฅ???????? | |
56 | + | |
57 | + | |
58 | +ๆถ?ๆต????ๆต ่ทบ?ใก?้ฃ?????็ป? | |
59 | +---------------------------------------------------------------------- | |
60 | +ๆฉ????็ผ???่ฝฐ??ๆต?็?็ผ????MUA???็ผ????็ป็ด?????ๆต ใง?ใค??็ผ?Linux?????็จฟ?????็ใค?????ๆฉ?ๆต?้ชๆต???????่ซ?? | |
61 | +?????????ๆ?ๆต ่ทบ?????็ผ???่ค????? | |
62 | + | |
63 | +็ๅญ??้? | |
64 | +TUI = ๆต ใฆ?????ๆถๅ?่น???????ใฆ?้?ใฅ?? | |
65 | +GUI = ??ๆง่ฐ?????ใข?ใฆ?้?ใฅ?? | |
66 | + | |
67 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
68 | +Alpine (TUI) | |
69 | + | |
70 | +???็ผ????ๆคค็ธ?? | |
71 | +???"Sending Preferences"??ใฅ??้? | |
72 | + | |
73 | +- "Do Not Send Flowed Text"่น?ๆคค่ฏฒ????? | |
74 | +- "Strip Whitespace Before Sending"่น?ๆคค่ฏฒ?ๆฝ?? | |
75 | + | |
76 | +่คฐ???????ๆต ่ต?่ฎน????????ๆด?็ใฆ?ๆง?ใจหๆถ?ๆตผ???่น?ๆฎ????็?็ธ????่ทบ?????ๆถ?CTRL-R็ผ???????้?ๆตฃๆ??็น???? | |
77 | +็ใค?????ๆต ่ทบ????ใฅ?ไผด??ๆต ๆต่ ??? | |
78 | + | |
79 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
80 | +Evolution (GUI) | |
81 | + | |
82 | +ๆถ?ๆต?ๅฏฎ????????????????ๆตฃ่ทจ?ใฅ????????็ใค?? | |
83 | + | |
84 | +่คฐ??????โ ??ๆต ๅ ??ๆคค็ธ??Preformat | |
85 | + ๆต ?Format->Heading->Preformatted (Ctrl-7)??????ๅฎธใฅ?้?? | |
86 | + | |
87 | +??่ทบ??ๆตฃ่ทจ??้? | |
88 | + Insert->Text File... (Alt-n x)?????ใจหๆถ????ๆต ่บฒ?? | |
89 | + | |
90 | +ๆตฃ?ๆฉ????ๆต ?"diff -Nru old.c new.c | xclip"้???????Preformat้???่ทบ??ๆตฃ่ทจ?ใค่ ??ๆฎ??ๆฉ?็?็ปฎ?็ฏ???? | |
91 | + | |
92 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
93 | +Kmail (GUI) | |
94 | + | |
95 | +ๆถ?ๆต?ๅฏฎ????????????????ๆตฃ่ทจ?ใฅ????????็ใค????? | |
96 | + | |
97 | +ๆฆ?็ใ?ๅง็ๆถ?ๆถ?HTML??็ ??????????????้?ๆถ?็??????ใฅ????? | |
98 | + | |
99 | +่คฐ?ๆถ????ๆถ?็????ๆต ๅ????่ทบ??้???ใฉ??ๆคค้?????ๆถ?็??????โ????ใฆ?ใฃ????????ๆถ????็ผ่น?็ฐๆฐจ???ๆตฃ???ใฉ??ๆต ๆต่ ๆ???ใง??ๆต ่ฎณ???????? | |
100 | +??ๆ??ๆตผ?็??????ใฆ?ใฃ??้????ๅงใ??่น?ๆคค่ฏฒ?ใฅ?????็ใค??ๆถ?????????ใฆ?ใฃ????????็ป ?????????่ง??็่พจ???????ใจ????ใฆ?ใฃ????ใคๅ??????ๆต ่ฎน?? | |
101 | +??่ทบ?????็น?ๆท?็?ๆถ้ธฟ??็ป่ฃค??ๆถ????ๆตฃ???ใจ??็ปๅคธ่ ???ๅจโ??ๅฏฎ?็น?้?็น?ๅฎธ่ฌ????ใฉ?ใจ????ใฆ?ใฃ??ๆต?้???๏ฝ??ๆตฃ???????ๆต ๆฐ?็?่ต็ ??? | |
102 | +?????โ????ใฆ?ใฃ??้?ๆตฃ????ๆฉ?ๆถ?ๆตผ?ๆพถๅ?่ฏฒๅก???????????ใฆ?ใฃ????? | |
103 | + | |
104 | +??ใฉ??ๆต ๅ??ๆด????้??????ใจหๆถ?ๆถ????้???ๅฅ??็ฏๅฅ?ใง??็ใค??็น????็ป?้?ๆถ?ๆถ?ๆฉ?็????(---)??? | |
105 | + | |
106 | +??่ทบ?????"Message"????????๏ผ??้??????โ????ใฆ??ๆต ่ฎน????ใง????????ๆตฃ????็ใค?????ๆต ่บฒ??ๆฉ????ๆถ?ๆถ?ๆฃฐ?ๆพถ???????ๆคค็ธ??ๆตฃ????ๆต ? | |
107 | +???ๆฉ?็น????็ผ?ๆตฃ???????ๆต ่ทบ็ผ็ป?ๅฎธใฅ?้????????้?ๆฉ????ๆต ใฅ็ซๆถ?"insert file"??็ฌ????? | |
108 | + | |
109 | +ๆตฃ????ๆต ใฅ????ใฅ?ไผด??ๆฉ?GPG???็ไผด??ๆต ่ฎน??ๆตฃ???????ๅฎ?็ใค?????ๆฟๆ??็?ๆตฃ่ทจ??GPG???็ๆฟ??ๆต ????ๆตฃ?ๆถๅ??ๅฎ??????????็ปๆง??็ใค??้? | |
110 | +่คฐ?ๆต ?GPGๆถ???????7ๆตฃ?็ผ??????ๆต??ๆตฃๅคธ??ๆต ?????????ๆ??ๆพถ??????? | |
111 | + | |
112 | +ๆฟก????ๆตฃ????็?ๆต ใฉ??ๆต ๅ??่คฐใ ????????็ใค??้???๏ฝ??็ๅ?ๆฝ????็ฐ?ๅฉ??ๆต ่ฎน????่ทบ?????ๆถ?็???ั??็ป????"Suggest automatic | |
113 | +display"้?ๆฉ???ๅณฐ??ๅฎ????ๆต ่ต?ๆ?่ง??็โ?ๆ???????่ฌ?? | |
114 | + | |
115 | +่คฐ?ๆตฃ?็?ๆท?็?็?็?????????????ๅฎ???????็ใค??้?ๆตฃ????ๆต ใค??ๅจ???????็ใง????ๅฅธ????โ?????็ใค????????ๆต ่ฎน????่ทบ????ๅฒ?ๅฉ????? | |
116 | +"save as"???ๆตฃ????ๆต ใคๅจ??ใค??ๆถ?ๅจโ????ๅญ?ๅญ????????็ใค????????ๆต ่ฎน??ๆฟก????็น????ๆต ใฆ?๏ฝโ???่คฐใ ??็ผ???????่คฐ?ๆตฃ?ๅง๏ฝ????ใฅ?? | |
117 | +???ๅฎธ่พฉ??็ป???๏ฝ??ๆถ?็ต????้???๏ฝ?่ต็ ??????ๆคค็ฐ??ๆต ใค??็????ๆต ?--ๅฎธ่ฌ?????ๆถ?ๆถ?ๆฉ???้ฃ??bug็?ๅงน???ใฅ?้ข??kmail???bugzilla | |
118 | +้ชๆต??็ฏ????ๆฉ?็?ๆตผ?็?ๆพถ??????????ๆต ่ต??ๆต ใฅ?????็ต่ง??ๆถ???ใฆ?ๅณฐ??็่ฏฒ???????????็?ๆท?็????้????ๆต ใฅ?????ๆตฃ???่ซ?????ๆต ่ทบ????่ทบ?ๆฟ?ๆต????็?็ธ?? | |
119 | +ๆตฃ?ๆถ?ๅฏฐ?ๆถ????ๆต ?ๆต ????????????้่ด็ผ?????????็ฟ ?????็ๆฑ?? | |
120 | + | |
121 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
122 | +Lotus Notes (GUI) | |
123 | + | |
124 | +ๆถ?็?ๆตฃ่ทจ?ใฅ????? | |
125 | + | |
126 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
127 | +Mutt (TUI) | |
128 | + | |
129 | +ๅฏฐ?ๆพถ?Linuxๅฏฎ????ๆตๅ??ๆตฃ่ทจ??mutt็นใก?้ฃ??้????ๆต ใจ?????็น????็น?ๅฎธใค????????็ฏๅ??ๆต???? | |
130 | + | |
131 | +Muttๆถ????็ฏ?็ผ?ๆ????้????ๆต ใค??็ป โฒ??ๆตฃ่ทจ?ใค??ๆถ?็ผ?ๆ???ใฉ?ๆ??ๆด?็ใฅ็ซ????????ใฆ??็????ๆพถั????ๆฎ??ๆ???ใฉ?่็ซ??? | |
132 | +ๆถ?ๆถ?"insert file"???ๆคค็ธ??็น????ๆต ใฉ??ๆฉ?ๆถ???็ฐ?????ๆต ่ทบ??็นๅญ????็ฐ???????ใฆ??ๆต ่บฒ?? | |
133 | + | |
134 | +'vim'ๆตฃ?ๆถ?mutt???็ผ?ๆ????้? | |
135 | + set editor="vi" | |
136 | + | |
137 | + ๆฟก????ๆตฃ่ทจ??xclip้???ๆ?ใคไบๆถ???ๆๆค | |
138 | + :set paste | |
139 | + ???ๆถ????ๆถ??????????shift-insert??????ๆตฃ่ทจ?? | |
140 | + :r filename | |
141 | + | |
142 | +ๆฟก??????ๅฎ ?????็ใค??ๆตฃ?ๆถๅ??ๅฎ?????????? | |
143 | +(a)ttachๅฎธใค?????ๅฏฐ?ๆฟๆค??ๆถ?็ฏ????"set paste"??? | |
144 | + | |
145 | +???็ผ????ๆคค็ธ?? | |
146 | +็น?ๆด?็ใคไบๆฆ?็ใ?ๅง็???่คฐใ ??ๅฎธใค????? | |
147 | +??ๆฐ??้????"send_charset"็ๅง็ๆถ?"us-ascii::utf-8"ๆถ????ๆถ?ๆถ?ๆถ???????ๆถ็ป????? | |
148 | + | |
149 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
150 | +Pine (TUI) | |
151 | + | |
152 | +Pineๆฉ???็ป??ๆถ?ๆต?็ป็?็ ????????ๆฃฐ?้?ๆตฃ????ๆฉ?ๆต???ๆฟ?ใฅ??็ใฉ?ๅ??ๆท?ๆพถ?ๆต???? | |
153 | + | |
154 | +ๆฟก???????ๆต ใฏ??็่ๅจ???alpine(pine???็ผั?่ฏ??) | |
155 | + | |
156 | +???็ผ????ๆคค็ธ?? | |
157 | +- ???ๆฉ?????????????็?ๅจ???ใ??็ป??????? | |
158 | +- "no-strip-whitespace-before-send"???ๆคค้????????็??????? | |
159 | + | |
160 | + | |
161 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
162 | +Sylpheed (GUI) | |
163 | + | |
164 | +- ???ๅฎ??????????ๆต ใฅ??ๆฟ็??ๅฎธใค??้???????ๆตฃ่ทจ?ใฉ??ๆต ่ฎน????? | |
165 | +- ???็้ๅจ??ใฅ????ใง??็ผ?ๆ???ใฃ?? | |
166 | +- ็ต้?????่คฐ?ๆ?ๆพถ???ๅ ??็ฏๅ????? | |
167 | +- ๆฟก???????ๆฉ?non-SSLๆฉ???ใฏ?????ๅจ?ๆตฃ่ทจ??TLS SMTP????????? | |
168 | +- ??ใง?????็ป???๏ฝ่ ???ๆถ?ๆถ?ๅฏฐ??????ใง??ruler bar??? | |
169 | +- ็ผ???ๆฟ?????ๆถ?ๅจฃ่ฏฒ????ๆฟ??็ๅ??ๆตผ?ๅง๏ฝโ???ๆต?็๏ฝ?ๅงใ?????? | |
170 | + | |
171 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
172 | +Thunderbird (GUI) | |
173 | + | |
174 | +ๆฆ?็ใ????ๅ ธ??้?thunderbirdๅฏฐ?็น่ง??????????????้?ๆตฃ????ๆฉ????ๆถ?ๆต???่ง?????ๆต ใฅๅทฑ??่ทบ?????ๅฏฐ???ๆใฝ??? | |
175 | + | |
176 | +- ??ใง?ใฆ?ๅณฐ????็ฏ?ๅง็???้?็ผ???????็ต่ฏฒ??้?ๆถ?็???????"Compose messages in HTML format"??? | |
177 | + | |
178 | +- ็ผ?ๆ?ๆตฃ????Thunderbird???็ผ?็ๅง็??ใคๅจ็น?ๆถ?็????็?ๆตฃ่ทจ??้?user_pref("mailnews.wraplength", 0); | |
179 | + | |
180 | +- ็ผ?ๆ?ๆตฃ????Thunderbird???็ผ?็ๅง็้?ๆตฃๅฎ??ๆถ?็?ๆตฃ่ทจ??"format=flowed"??็ ??้?user_pref("mailnews. | |
181 | + send_plaintext_flowed", false); | |
182 | + | |
183 | +- ๆตฃ????็?ๆตฃ?Thunderbird???ๆถๆดช???????็ ????็ฐ??้? | |
184 | + ๆฟก????ๆฆ?็ใ????ๅ ธ??ๆตฃ?ๆถ??????????HTML??็ ??้???๏ฝ?????ๅฏฐ???ไฟฑ??ๆต ?ๆต ?ๆต ????ๆฃฐ???????ๆถ????ๅฆ?ๆถ???????"Preformat"??็ ????? | |
185 | + ๆฟก????ๆฆ?็ใ????ๅ ธ??ๆตฃ?ๆถ??????????????????็ ??้?ๆตฃ?ๆถ?ๅฏฐ????็น???้่ดHTML??็ ??้?ๆต ?ๆต ?ๆตฃ?ๆถ่ฝฐ??ๅจโ?ั ??้???ใคๅ?????ๆฎ??ๅจ????้? | |
186 | + ??่ทบ??ๅฏฎๅ?ๆตๅจ็น??????็???????็ ??้???????็น?็ๅ?????็????็?็น???ๆฟ??้???ใฅ??ๆท๏ผ????็ฌ??ๆถ?ๆตฃ่ทจ??shift?????ใคๅจ็น????ๆถ?HTML | |
187 | + ??็ ??้???่ทบ?????ๆฃฐ???????ๆถ????ๅฆ?ๆถ???????"Preformat"??็ ????? | |
188 | + | |
189 | +- ???็้ๅจ??ใฅ????ใง??็ผ?ๆ????้? | |
190 | + ???็ต?Thunderbird???็ใค?????็ป ?????????่ง??็่พจ??ๆตฃ่ทจ?ใค??ๆถ?"external editor"??โ??้???่ทบ??ๆตฃ่ทจ?ใค????????ๅจใข?? | |
191 | + $EDITOR??ใจ?่ฏฒ???????????้ชๆฐหๆถ???็?????ๆถ????็?็น???ๆฟ??้????ๆต ใค??ๆ่่ๆถ?็น?็?ๆฉ?ๆถ???โ??้???่ทบ??ๅจฃ่ฏฒ??ๆถ?ๆถ?ๆตฃ่ทจ?ใฅ????? | |
192 | + ??????View->Toolbars->Customize...??????่คฐ?ๆตฃ?ๆถ????ๆทโ???????่ทบ??ๆต ?ๆต ???็ฐ?่ฏฒ??็ๅ??ๆต ใค????? | |
193 | + | |
194 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
195 | +TkRat (GUI) | |
196 | + | |
197 | +???ๆต ใคๅจ??ใฅ?????ๆตฃ่ทจ??"Insert file..."??????ๆพถ???ใง??็ผ?ๆ???ใฃ?? | |
198 | + | |
199 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
200 | +Gmail (Web GUI) | |
201 | + | |
202 | +ๆถ?็?ๆตฃ่ทจ?ใฅ????????็ใค????? | |
203 | + | |
204 | +Gmail็ผ?ๆคค้?ใก?้ฃ???????ใฅ?็????ๆฐใ็ป?ๆ????ๆถ่นโ??็ฌบ?? | |
205 | + | |
206 | +??็?่ทบ?ๆฐใ็ป?ๆ????ๆถ่นโ??ๅฅธ??ๆฃฐ????ๆต ใจ??ๆพถ???ใง??ๆ???ใจะ??็ญน???????่ทบ??ๆฉ?ๆตผ?ๆตฃ่ทจ?ใฅ??ๆ???ใฃ?????ๅงฃ?็???????ๆถ?78ๆถ?็?็ป???? | |
207 | + | |
208 | +???ๆถ?ๆถ????ๆฃฐ????Gmailๆฉ?ๆตผ????ๆต ่ฎณ??ๆถ????ASCII???็?็ป????ๆทโ????้่ดbase64็ผ???????็น????ๆถ?็ๅฎ????????ๅจัๅบๆต่น?????็???? | |
209 | + | |
210 | + ### |
arch/arm/kernel/traps.c
... | ... | @@ -234,7 +234,6 @@ |
234 | 234 | |
235 | 235 | printk(KERN_EMERG "Internal error: %s: %x [#%d]" S_PREEMPT S_SMP "\n", |
236 | 236 | str, err, ++die_counter); |
237 | - sysfs_printk_last_file(); | |
238 | 237 | |
239 | 238 | /* trap and error numbers are mostly meaningless on ARM */ |
240 | 239 | ret = notify_die(DIE_OOPS, str, regs, err, tsk->thread.trap_no, SIGSEGV); |
arch/powerpc/kernel/traps.c
arch/sh/kernel/traps_32.c
arch/unicore32/kernel/traps.c
... | ... | @@ -192,7 +192,6 @@ |
192 | 192 | |
193 | 193 | printk(KERN_EMERG "Internal error: %s: %x [#%d]\n", |
194 | 194 | str, err, ++die_counter); |
195 | - sysfs_printk_last_file(); | |
196 | 195 | |
197 | 196 | /* trap and error numbers are mostly meaningless on UniCore */ |
198 | 197 | ret = notify_die(DIE_OOPS, str, regs, err, tsk->thread.trap_no, \ |
arch/x86/include/asm/bios_ebda.h
... | ... | @@ -4,14 +4,38 @@ |
4 | 4 | #include <asm/io.h> |
5 | 5 | |
6 | 6 | /* |
7 | - * there is a real-mode segmented pointer pointing to the | |
8 | - * 4K EBDA area at 0x40E. | |
7 | + * Returns physical address of EBDA. Returns 0 if there is no EBDA. | |
9 | 8 | */ |
10 | 9 | static inline unsigned int get_bios_ebda(void) |
11 | 10 | { |
11 | + /* | |
12 | + * There is a real-mode segmented pointer pointing to the | |
13 | + * 4K EBDA area at 0x40E. | |
14 | + */ | |
12 | 15 | unsigned int address = *(unsigned short *)phys_to_virt(0x40E); |
13 | 16 | address <<= 4; |
14 | 17 | return address; /* 0 means none */ |
18 | +} | |
19 | + | |
20 | +/* | |
21 | + * Return the sanitized length of the EBDA in bytes, if it exists. | |
22 | + */ | |
23 | +static inline unsigned int get_bios_ebda_length(void) | |
24 | +{ | |
25 | + unsigned int address; | |
26 | + unsigned int length; | |
27 | + | |
28 | + address = get_bios_ebda(); | |
29 | + if (!address) | |
30 | + return 0; | |
31 | + | |
32 | + /* EBDA length is byte 0 of the EBDA (stored in KiB) */ | |
33 | + length = *(unsigned char *)phys_to_virt(address); | |
34 | + length <<= 10; | |
35 | + | |
36 | + /* Trim the length if it extends beyond 640KiB */ | |
37 | + length = min_t(unsigned int, (640 * 1024) - address, length); | |
38 | + return length; | |
15 | 39 | } |
16 | 40 | |
17 | 41 | void reserve_ebda_region(void); |
arch/x86/kernel/dumpstack.c
drivers/base/core.c
... | ... | @@ -400,7 +400,7 @@ |
400 | 400 | static int device_add_attrs(struct device *dev) |
401 | 401 | { |
402 | 402 | struct class *class = dev->class; |
403 | - struct device_type *type = dev->type; | |
403 | + const struct device_type *type = dev->type; | |
404 | 404 | int error; |
405 | 405 | |
406 | 406 | if (class) { |
... | ... | @@ -440,7 +440,7 @@ |
440 | 440 | static void device_remove_attrs(struct device *dev) |
441 | 441 | { |
442 | 442 | struct class *class = dev->class; |
443 | - struct device_type *type = dev->type; | |
443 | + const struct device_type *type = dev->type; | |
444 | 444 | |
445 | 445 | device_remove_groups(dev, dev->groups); |
446 | 446 | |
... | ... | @@ -1314,8 +1314,7 @@ |
1314 | 1314 | EXPORT_SYMBOL_GPL(device_create_file); |
1315 | 1315 | EXPORT_SYMBOL_GPL(device_remove_file); |
1316 | 1316 | |
1317 | -struct root_device | |
1318 | -{ | |
1317 | +struct root_device { | |
1319 | 1318 | struct device dev; |
1320 | 1319 | struct module *owner; |
1321 | 1320 | }; |
drivers/base/dd.c
... | ... | @@ -245,6 +245,10 @@ |
245 | 245 | |
246 | 246 | device_lock(dev); |
247 | 247 | if (dev->driver) { |
248 | + if (klist_node_attached(&dev->p->knode_driver)) { | |
249 | + ret = 1; | |
250 | + goto out_unlock; | |
251 | + } | |
248 | 252 | ret = device_bind_driver(dev); |
249 | 253 | if (ret == 0) |
250 | 254 | ret = 1; |
... | ... | @@ -257,6 +261,7 @@ |
257 | 261 | ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach); |
258 | 262 | pm_runtime_put_sync(dev); |
259 | 263 | } |
264 | +out_unlock: | |
260 | 265 | device_unlock(dev); |
261 | 266 | return ret; |
262 | 267 | } |
263 | 268 | |
264 | 269 | |
265 | 270 | |
... | ... | @@ -408,18 +413,17 @@ |
408 | 413 | } |
409 | 414 | EXPORT_SYMBOL(dev_get_drvdata); |
410 | 415 | |
411 | -void dev_set_drvdata(struct device *dev, void *data) | |
416 | +int dev_set_drvdata(struct device *dev, void *data) | |
412 | 417 | { |
413 | 418 | int error; |
414 | 419 | |
415 | - if (!dev) | |
416 | - return; | |
417 | 420 | if (!dev->p) { |
418 | 421 | error = device_private_init(dev); |
419 | 422 | if (error) |
420 | - return; | |
423 | + return error; | |
421 | 424 | } |
422 | 425 | dev->p->driver_data = data; |
426 | + return 0; | |
423 | 427 | } |
424 | 428 | EXPORT_SYMBOL(dev_set_drvdata); |
drivers/base/memory.c
... | ... | @@ -48,7 +48,8 @@ |
48 | 48 | return MEMORY_CLASS_NAME; |
49 | 49 | } |
50 | 50 | |
51 | -static int memory_uevent(struct kset *kset, struct kobject *obj, struct kobj_uevent_env *env) | |
51 | +static int memory_uevent(struct kset *kset, struct kobject *obj, | |
52 | + struct kobj_uevent_env *env) | |
52 | 53 | { |
53 | 54 | int retval = 0; |
54 | 55 | |
55 | 56 | |
... | ... | @@ -228,10 +229,11 @@ |
228 | 229 | * OK to have direct references to sparsemem variables in here. |
229 | 230 | */ |
230 | 231 | static int |
231 | -memory_section_action(unsigned long phys_index, unsigned long action) | |
232 | +memory_block_action(unsigned long phys_index, unsigned long action) | |
232 | 233 | { |
233 | 234 | int i; |
234 | 235 | unsigned long start_pfn, start_paddr; |
236 | + unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block; | |
235 | 237 | struct page *first_page; |
236 | 238 | int ret; |
237 | 239 | |
... | ... | @@ -243,7 +245,7 @@ |
243 | 245 | * that way. |
244 | 246 | */ |
245 | 247 | if (action == MEM_ONLINE) { |
246 | - for (i = 0; i < PAGES_PER_SECTION; i++) { | |
248 | + for (i = 0; i < nr_pages; i++) { | |
247 | 249 | if (PageReserved(first_page+i)) |
248 | 250 | continue; |
249 | 251 | |
250 | 252 | |
... | ... | @@ -257,12 +259,12 @@ |
257 | 259 | switch (action) { |
258 | 260 | case MEM_ONLINE: |
259 | 261 | start_pfn = page_to_pfn(first_page); |
260 | - ret = online_pages(start_pfn, PAGES_PER_SECTION); | |
262 | + ret = online_pages(start_pfn, nr_pages); | |
261 | 263 | break; |
262 | 264 | case MEM_OFFLINE: |
263 | 265 | start_paddr = page_to_pfn(first_page) << PAGE_SHIFT; |
264 | 266 | ret = remove_memory(start_paddr, |
265 | - PAGES_PER_SECTION << PAGE_SHIFT); | |
267 | + nr_pages << PAGE_SHIFT); | |
266 | 268 | break; |
267 | 269 | default: |
268 | 270 | WARN(1, KERN_WARNING "%s(%ld, %ld) unknown action: " |
... | ... | @@ -276,7 +278,7 @@ |
276 | 278 | static int memory_block_change_state(struct memory_block *mem, |
277 | 279 | unsigned long to_state, unsigned long from_state_req) |
278 | 280 | { |
279 | - int i, ret = 0; | |
281 | + int ret = 0; | |
280 | 282 | |
281 | 283 | mutex_lock(&mem->state_mutex); |
282 | 284 | |
283 | 285 | |
284 | 286 | |
... | ... | @@ -288,20 +290,11 @@ |
288 | 290 | if (to_state == MEM_OFFLINE) |
289 | 291 | mem->state = MEM_GOING_OFFLINE; |
290 | 292 | |
291 | - for (i = 0; i < sections_per_block; i++) { | |
292 | - ret = memory_section_action(mem->start_section_nr + i, | |
293 | - to_state); | |
294 | - if (ret) | |
295 | - break; | |
296 | - } | |
293 | + ret = memory_block_action(mem->start_section_nr, to_state); | |
297 | 294 | |
298 | - if (ret) { | |
299 | - for (i = 0; i < sections_per_block; i++) | |
300 | - memory_section_action(mem->start_section_nr + i, | |
301 | - from_state_req); | |
302 | - | |
295 | + if (ret) | |
303 | 296 | mem->state = from_state_req; |
304 | - } else | |
297 | + else | |
305 | 298 | mem->state = to_state; |
306 | 299 | |
307 | 300 | out: |
drivers/base/platform.c
... | ... | @@ -192,18 +192,18 @@ |
192 | 192 | int platform_device_add_resources(struct platform_device *pdev, |
193 | 193 | const struct resource *res, unsigned int num) |
194 | 194 | { |
195 | - struct resource *r; | |
195 | + struct resource *r = NULL; | |
196 | 196 | |
197 | - if (!res) | |
198 | - return 0; | |
199 | - | |
200 | - r = kmemdup(res, sizeof(struct resource) * num, GFP_KERNEL); | |
201 | - if (r) { | |
202 | - pdev->resource = r; | |
203 | - pdev->num_resources = num; | |
204 | - return 0; | |
197 | + if (res) { | |
198 | + r = kmemdup(res, sizeof(struct resource) * num, GFP_KERNEL); | |
199 | + if (!r) | |
200 | + return -ENOMEM; | |
205 | 201 | } |
206 | - return -ENOMEM; | |
202 | + | |
203 | + kfree(pdev->resource); | |
204 | + pdev->resource = r; | |
205 | + pdev->num_resources = num; | |
206 | + return 0; | |
207 | 207 | } |
208 | 208 | EXPORT_SYMBOL_GPL(platform_device_add_resources); |
209 | 209 | |
210 | 210 | |
211 | 211 | |
... | ... | @@ -220,17 +220,17 @@ |
220 | 220 | int platform_device_add_data(struct platform_device *pdev, const void *data, |
221 | 221 | size_t size) |
222 | 222 | { |
223 | - void *d; | |
223 | + void *d = NULL; | |
224 | 224 | |
225 | - if (!data) | |
226 | - return 0; | |
227 | - | |
228 | - d = kmemdup(data, size, GFP_KERNEL); | |
229 | - if (d) { | |
230 | - pdev->dev.platform_data = d; | |
231 | - return 0; | |
225 | + if (data) { | |
226 | + d = kmemdup(data, size, GFP_KERNEL); | |
227 | + if (!d) | |
228 | + return -ENOMEM; | |
232 | 229 | } |
233 | - return -ENOMEM; | |
230 | + | |
231 | + kfree(pdev->dev.platform_data); | |
232 | + pdev->dev.platform_data = d; | |
233 | + return 0; | |
234 | 234 | } |
235 | 235 | EXPORT_SYMBOL_GPL(platform_device_add_data); |
236 | 236 |
drivers/char/Kconfig
drivers/char/mem.c
... | ... | @@ -806,29 +806,41 @@ |
806 | 806 | }; |
807 | 807 | #endif |
808 | 808 | |
809 | -static ssize_t kmsg_write(struct file *file, const char __user *buf, | |
810 | - size_t count, loff_t *ppos) | |
809 | +static ssize_t kmsg_writev(struct kiocb *iocb, const struct iovec *iv, | |
810 | + unsigned long count, loff_t pos) | |
811 | 811 | { |
812 | - char *tmp; | |
813 | - ssize_t ret; | |
812 | + char *line, *p; | |
813 | + int i; | |
814 | + ssize_t ret = -EFAULT; | |
815 | + size_t len = iov_length(iv, count); | |
814 | 816 | |
815 | - tmp = kmalloc(count + 1, GFP_KERNEL); | |
816 | - if (tmp == NULL) | |
817 | + line = kmalloc(len + 1, GFP_KERNEL); | |
818 | + if (line == NULL) | |
817 | 819 | return -ENOMEM; |
818 | - ret = -EFAULT; | |
819 | - if (!copy_from_user(tmp, buf, count)) { | |
820 | - tmp[count] = 0; | |
821 | - ret = printk("%s", tmp); | |
822 | - if (ret > count) | |
823 | - /* printk can add a prefix */ | |
824 | - ret = count; | |
820 | + | |
821 | + /* | |
822 | + * copy all vectors into a single string, to ensure we do | |
823 | + * not interleave our log line with other printk calls | |
824 | + */ | |
825 | + p = line; | |
826 | + for (i = 0; i < count; i++) { | |
827 | + if (copy_from_user(p, iv[i].iov_base, iv[i].iov_len)) | |
828 | + goto out; | |
829 | + p += iv[i].iov_len; | |
825 | 830 | } |
826 | - kfree(tmp); | |
831 | + p[0] = '\0'; | |
832 | + | |
833 | + ret = printk("%s", line); | |
834 | + /* printk can add a prefix */ | |
835 | + if (ret > len) | |
836 | + ret = len; | |
837 | +out: | |
838 | + kfree(line); | |
827 | 839 | return ret; |
828 | 840 | } |
829 | 841 | |
830 | 842 | static const struct file_operations kmsg_fops = { |
831 | - .write = kmsg_write, | |
843 | + .aio_write = kmsg_writev, | |
832 | 844 | .llseek = noop_llseek, |
833 | 845 | }; |
834 | 846 |
drivers/char/raw.c
... | ... | @@ -21,6 +21,7 @@ |
21 | 21 | #include <linux/mutex.h> |
22 | 22 | #include <linux/gfp.h> |
23 | 23 | #include <linux/compat.h> |
24 | +#include <linux/vmalloc.h> | |
24 | 25 | |
25 | 26 | #include <asm/uaccess.h> |
26 | 27 | |
27 | 28 | |
... | ... | @@ -30,10 +31,15 @@ |
30 | 31 | }; |
31 | 32 | |
32 | 33 | static struct class *raw_class; |
33 | -static struct raw_device_data raw_devices[MAX_RAW_MINORS]; | |
34 | +static struct raw_device_data *raw_devices; | |
34 | 35 | static DEFINE_MUTEX(raw_mutex); |
35 | 36 | static const struct file_operations raw_ctl_fops; /* forward declaration */ |
36 | 37 | |
38 | +static int max_raw_minors = MAX_RAW_MINORS; | |
39 | + | |
40 | +module_param(max_raw_minors, int, 0); | |
41 | +MODULE_PARM_DESC(max_raw_minors, "Maximum number of raw devices (1-65536)"); | |
42 | + | |
37 | 43 | /* |
38 | 44 | * Open/close code for raw IO. |
39 | 45 | * |
... | ... | @@ -125,7 +131,7 @@ |
125 | 131 | struct raw_device_data *rawdev; |
126 | 132 | int err = 0; |
127 | 133 | |
128 | - if (number <= 0 || number >= MAX_RAW_MINORS) | |
134 | + if (number <= 0 || number >= max_raw_minors) | |
129 | 135 | return -EINVAL; |
130 | 136 | |
131 | 137 | if (MAJOR(dev) != major || MINOR(dev) != minor) |
132 | 138 | |
133 | 139 | |
... | ... | @@ -312,14 +318,27 @@ |
312 | 318 | dev_t dev = MKDEV(RAW_MAJOR, 0); |
313 | 319 | int ret; |
314 | 320 | |
315 | - ret = register_chrdev_region(dev, MAX_RAW_MINORS, "raw"); | |
321 | + if (max_raw_minors < 1 || max_raw_minors > 65536) { | |
322 | + printk(KERN_WARNING "raw: invalid max_raw_minors (must be" | |
323 | + " between 1 and 65536), using %d\n", MAX_RAW_MINORS); | |
324 | + max_raw_minors = MAX_RAW_MINORS; | |
325 | + } | |
326 | + | |
327 | + raw_devices = vmalloc(sizeof(struct raw_device_data) * max_raw_minors); | |
328 | + if (!raw_devices) { | |
329 | + printk(KERN_ERR "Not enough memory for raw device structures\n"); | |
330 | + ret = -ENOMEM; | |
331 | + goto error; | |
332 | + } | |
333 | + memset(raw_devices, 0, sizeof(struct raw_device_data) * max_raw_minors); | |
334 | + | |
335 | + ret = register_chrdev_region(dev, max_raw_minors, "raw"); | |
316 | 336 | if (ret) |
317 | 337 | goto error; |
318 | 338 | |
319 | 339 | cdev_init(&raw_cdev, &raw_fops); |
320 | - ret = cdev_add(&raw_cdev, dev, MAX_RAW_MINORS); | |
340 | + ret = cdev_add(&raw_cdev, dev, max_raw_minors); | |
321 | 341 | if (ret) { |
322 | - kobject_put(&raw_cdev.kobj); | |
323 | 342 | goto error_region; |
324 | 343 | } |
325 | 344 | |
326 | 345 | |
... | ... | @@ -336,8 +355,9 @@ |
336 | 355 | return 0; |
337 | 356 | |
338 | 357 | error_region: |
339 | - unregister_chrdev_region(dev, MAX_RAW_MINORS); | |
358 | + unregister_chrdev_region(dev, max_raw_minors); | |
340 | 359 | error: |
360 | + vfree(raw_devices); | |
341 | 361 | return ret; |
342 | 362 | } |
343 | 363 | |
... | ... | @@ -346,7 +366,7 @@ |
346 | 366 | device_destroy(raw_class, MKDEV(RAW_MAJOR, 0)); |
347 | 367 | class_destroy(raw_class); |
348 | 368 | cdev_del(&raw_cdev); |
349 | - unregister_chrdev_region(MKDEV(RAW_MAJOR, 0), MAX_RAW_MINORS); | |
369 | + unregister_chrdev_region(MKDEV(RAW_MAJOR, 0), max_raw_minors); | |
350 | 370 | } |
351 | 371 | |
352 | 372 | module_init(raw_init); |
drivers/firmware/Kconfig
drivers/firmware/Makefile
drivers/firmware/efivars.c
... | ... | @@ -677,10 +677,10 @@ |
677 | 677 | |
678 | 678 | return 0; |
679 | 679 | out_free: |
680 | + kfree(efivars->del_var); | |
681 | + efivars->del_var = NULL; | |
680 | 682 | kfree(efivars->new_var); |
681 | 683 | efivars->new_var = NULL; |
682 | - kfree(efivars->new_var); | |
683 | - efivars->new_var = NULL; | |
684 | 684 | return error; |
685 | 685 | } |
686 | 686 | |
... | ... | @@ -803,6 +803,8 @@ |
803 | 803 | ops.set_variable = efi.set_variable; |
804 | 804 | ops.get_next_variable = efi.get_next_variable; |
805 | 805 | error = register_efivars(&__efivars, &ops, efi_kobj); |
806 | + if (error) | |
807 | + goto err_put; | |
806 | 808 | |
807 | 809 | /* Don't forget the systab entry */ |
808 | 810 | error = sysfs_create_group(efi_kobj, &efi_subsys_attr_group); |
809 | 811 | |
810 | 812 | |
... | ... | @@ -810,18 +812,25 @@ |
810 | 812 | printk(KERN_ERR |
811 | 813 | "efivars: Sysfs attribute export failed with error %d.\n", |
812 | 814 | error); |
813 | - unregister_efivars(&__efivars); | |
814 | - kobject_put(efi_kobj); | |
815 | + goto err_unregister; | |
815 | 816 | } |
816 | 817 | |
818 | + return 0; | |
819 | + | |
820 | +err_unregister: | |
821 | + unregister_efivars(&__efivars); | |
822 | +err_put: | |
823 | + kobject_put(efi_kobj); | |
817 | 824 | return error; |
818 | 825 | } |
819 | 826 | |
820 | 827 | static void __exit |
821 | 828 | efivars_exit(void) |
822 | 829 | { |
823 | - unregister_efivars(&__efivars); | |
824 | - kobject_put(efi_kobj); | |
830 | + if (efi_enabled) { | |
831 | + unregister_efivars(&__efivars); | |
832 | + kobject_put(efi_kobj); | |
833 | + } | |
825 | 834 | } |
826 | 835 | |
827 | 836 | module_init(efivars_init); |
drivers/firmware/google/Kconfig
1 | +config GOOGLE_FIRMWARE | |
2 | + bool "Google Firmware Drivers" | |
3 | + depends on X86 | |
4 | + default n | |
5 | + help | |
6 | + These firmware drivers are used by Google's servers. They are | |
7 | + only useful if you are working directly on one of their | |
8 | + proprietary servers. If in doubt, say "N". | |
9 | + | |
10 | +menu "Google Firmware Drivers" | |
11 | + depends on GOOGLE_FIRMWARE | |
12 | + | |
13 | +config GOOGLE_SMI | |
14 | + tristate "SMI interface for Google platforms" | |
15 | + depends on ACPI && DMI | |
16 | + select EFI_VARS | |
17 | + help | |
18 | + Say Y here if you want to enable SMI callbacks for Google | |
19 | + platforms. This provides an interface for writing to and | |
20 | + clearing the EFI event log and reading and writing NVRAM | |
21 | + variables. | |
22 | + | |
23 | +config GOOGLE_MEMCONSOLE | |
24 | + tristate "Firmware Memory Console" | |
25 | + depends on DMI | |
26 | + help | |
27 | + This option enables the kernel to search for a firmware log in | |
28 | + the EBDA on Google servers. If found, this log is exported to | |
29 | + userland in the file /sys/firmware/log. | |
30 | + | |
31 | +endmenu |
drivers/firmware/google/Makefile
drivers/firmware/google/gsmi.c
1 | +/* | |
2 | + * Copyright 2010 Google Inc. All Rights Reserved. | |
3 | + * Author: dlaurie@google.com (Duncan Laurie) | |
4 | + * | |
5 | + * Re-worked to expose sysfs APIs by mikew@google.com (Mike Waychison) | |
6 | + * | |
7 | + * EFI SMI interface for Google platforms | |
8 | + */ | |
9 | + | |
10 | +#include <linux/kernel.h> | |
11 | +#include <linux/init.h> | |
12 | +#include <linux/types.h> | |
13 | +#include <linux/device.h> | |
14 | +#include <linux/platform_device.h> | |
15 | +#include <linux/errno.h> | |
16 | +#include <linux/string.h> | |
17 | +#include <linux/spinlock.h> | |
18 | +#include <linux/dma-mapping.h> | |
19 | +#include <linux/dmapool.h> | |
20 | +#include <linux/fs.h> | |
21 | +#include <linux/slab.h> | |
22 | +#include <linux/ioctl.h> | |
23 | +#include <linux/acpi.h> | |
24 | +#include <linux/io.h> | |
25 | +#include <linux/uaccess.h> | |
26 | +#include <linux/dmi.h> | |
27 | +#include <linux/kdebug.h> | |
28 | +#include <linux/reboot.h> | |
29 | +#include <linux/efi.h> | |
30 | + | |
31 | +#define GSMI_SHUTDOWN_CLEAN 0 /* Clean Shutdown */ | |
32 | +/* TODO(mikew@google.com): Tie in HARDLOCKUP_DETECTOR with NMIWDT */ | |
33 | +#define GSMI_SHUTDOWN_NMIWDT 1 /* NMI Watchdog */ | |
34 | +#define GSMI_SHUTDOWN_PANIC 2 /* Panic */ | |
35 | +#define GSMI_SHUTDOWN_OOPS 3 /* Oops */ | |
36 | +#define GSMI_SHUTDOWN_DIE 4 /* Die -- No longer meaningful */ | |
37 | +#define GSMI_SHUTDOWN_MCE 5 /* Machine Check */ | |
38 | +#define GSMI_SHUTDOWN_SOFTWDT 6 /* Software Watchdog */ | |
39 | +#define GSMI_SHUTDOWN_MBE 7 /* Uncorrected ECC */ | |
40 | +#define GSMI_SHUTDOWN_TRIPLE 8 /* Triple Fault */ | |
41 | + | |
42 | +#define DRIVER_VERSION "1.0" | |
43 | +#define GSMI_GUID_SIZE 16 | |
44 | +#define GSMI_BUF_SIZE 1024 | |
45 | +#define GSMI_BUF_ALIGN sizeof(u64) | |
46 | +#define GSMI_CALLBACK 0xef | |
47 | + | |
48 | +/* SMI return codes */ | |
49 | +#define GSMI_SUCCESS 0x00 | |
50 | +#define GSMI_UNSUPPORTED2 0x03 | |
51 | +#define GSMI_LOG_FULL 0x0b | |
52 | +#define GSMI_VAR_NOT_FOUND 0x0e | |
53 | +#define GSMI_HANDSHAKE_SPIN 0x7d | |
54 | +#define GSMI_HANDSHAKE_CF 0x7e | |
55 | +#define GSMI_HANDSHAKE_NONE 0x7f | |
56 | +#define GSMI_INVALID_PARAMETER 0x82 | |
57 | +#define GSMI_UNSUPPORTED 0x83 | |
58 | +#define GSMI_BUFFER_TOO_SMALL 0x85 | |
59 | +#define GSMI_NOT_READY 0x86 | |
60 | +#define GSMI_DEVICE_ERROR 0x87 | |
61 | +#define GSMI_NOT_FOUND 0x8e | |
62 | + | |
63 | +#define QUIRKY_BOARD_HASH 0x78a30a50 | |
64 | + | |
65 | +/* Internally used commands passed to the firmware */ | |
66 | +#define GSMI_CMD_GET_NVRAM_VAR 0x01 | |
67 | +#define GSMI_CMD_GET_NEXT_VAR 0x02 | |
68 | +#define GSMI_CMD_SET_NVRAM_VAR 0x03 | |
69 | +#define GSMI_CMD_SET_EVENT_LOG 0x08 | |
70 | +#define GSMI_CMD_CLEAR_EVENT_LOG 0x09 | |
71 | +#define GSMI_CMD_CLEAR_CONFIG 0x20 | |
72 | +#define GSMI_CMD_HANDSHAKE_TYPE 0xC1 | |
73 | + | |
74 | +/* Magic entry type for kernel events */ | |
75 | +#define GSMI_LOG_ENTRY_TYPE_KERNEL 0xDEAD | |
76 | + | |
77 | +/* SMI buffers must be in 32bit physical address space */ | |
78 | +struct gsmi_buf { | |
79 | + u8 *start; /* start of buffer */ | |
80 | + size_t length; /* length of buffer */ | |
81 | + dma_addr_t handle; /* dma allocation handle */ | |
82 | + u32 address; /* physical address of buffer */ | |
83 | +}; | |
84 | + | |
85 | +struct gsmi_device { | |
86 | + struct platform_device *pdev; /* platform device */ | |
87 | + struct gsmi_buf *name_buf; /* variable name buffer */ | |
88 | + struct gsmi_buf *data_buf; /* generic data buffer */ | |
89 | + struct gsmi_buf *param_buf; /* parameter buffer */ | |
90 | + spinlock_t lock; /* serialize access to SMIs */ | |
91 | + u16 smi_cmd; /* SMI command port */ | |
92 | + int handshake_type; /* firmware handler interlock type */ | |
93 | + struct dma_pool *dma_pool; /* DMA buffer pool */ | |
94 | +} gsmi_dev; | |
95 | + | |
96 | +/* Packed structures for communicating with the firmware */ | |
97 | +struct gsmi_nvram_var_param { | |
98 | + efi_guid_t guid; | |
99 | + u32 name_ptr; | |
100 | + u32 attributes; | |
101 | + u32 data_len; | |
102 | + u32 data_ptr; | |
103 | +} __packed; | |
104 | + | |
105 | +struct gsmi_get_next_var_param { | |
106 | + u8 guid[GSMI_GUID_SIZE]; | |
107 | + u32 name_ptr; | |
108 | + u32 name_len; | |
109 | +} __packed; | |
110 | + | |
111 | +struct gsmi_set_eventlog_param { | |
112 | + u32 data_ptr; | |
113 | + u32 data_len; | |
114 | + u32 type; | |
115 | +} __packed; | |
116 | + | |
117 | +/* Event log formats */ | |
118 | +struct gsmi_log_entry_type_1 { | |
119 | + u16 type; | |
120 | + u32 instance; | |
121 | +} __packed; | |
122 | + | |
123 | + | |
124 | +/* | |
125 | + * Some platforms don't have explicit SMI handshake | |
126 | + * and need to wait for SMI to complete. | |
127 | + */ | |
128 | +#define GSMI_DEFAULT_SPINCOUNT 0x10000 | |
129 | +static unsigned int spincount = GSMI_DEFAULT_SPINCOUNT; | |
130 | +module_param(spincount, uint, 0600); | |
131 | +MODULE_PARM_DESC(spincount, | |
132 | + "The number of loop iterations to use when using the spin handshake."); | |
133 | + | |
134 | +static struct gsmi_buf *gsmi_buf_alloc(void) | |
135 | +{ | |
136 | + struct gsmi_buf *smibuf; | |
137 | + | |
138 | + smibuf = kzalloc(sizeof(*smibuf), GFP_KERNEL); | |
139 | + if (!smibuf) { | |
140 | + printk(KERN_ERR "gsmi: out of memory\n"); | |
141 | + return NULL; | |
142 | + } | |
143 | + | |
144 | + /* allocate buffer in 32bit address space */ | |
145 | + smibuf->start = dma_pool_alloc(gsmi_dev.dma_pool, GFP_KERNEL, | |
146 | + &smibuf->handle); | |
147 | + if (!smibuf->start) { | |
148 | + printk(KERN_ERR "gsmi: failed to allocate name buffer\n"); | |
149 | + kfree(smibuf); | |
150 | + return NULL; | |
151 | + } | |
152 | + | |
153 | + /* fill in the buffer handle */ | |
154 | + smibuf->length = GSMI_BUF_SIZE; | |
155 | + smibuf->address = (u32)virt_to_phys(smibuf->start); | |
156 | + | |
157 | + return smibuf; | |
158 | +} | |
159 | + | |
160 | +static void gsmi_buf_free(struct gsmi_buf *smibuf) | |
161 | +{ | |
162 | + if (smibuf) { | |
163 | + if (smibuf->start) | |
164 | + dma_pool_free(gsmi_dev.dma_pool, smibuf->start, | |
165 | + smibuf->handle); | |
166 | + kfree(smibuf); | |
167 | + } | |
168 | +} | |
169 | + | |
170 | +/* | |
171 | + * Make a call to gsmi func(sub). GSMI error codes are translated to | |
172 | + * in-kernel errnos (0 on success, -ERRNO on error). | |
173 | + */ | |
174 | +static int gsmi_exec(u8 func, u8 sub) | |
175 | +{ | |
176 | + u16 cmd = (sub << 8) | func; | |
177 | + u16 result = 0; | |
178 | + int rc = 0; | |
179 | + | |
180 | + /* | |
181 | + * AH : Subfunction number | |
182 | + * AL : Function number | |
183 | + * EBX : Parameter block address | |
184 | + * DX : SMI command port | |
185 | + * | |
186 | + * Three protocols here. See also the comment in gsmi_init(). | |
187 | + */ | |
188 | + if (gsmi_dev.handshake_type == GSMI_HANDSHAKE_CF) { | |
189 | + /* | |
190 | + * If handshake_type == HANDSHAKE_CF then set CF on the | |
191 | + * way in and wait for the handler to clear it; this avoids | |
192 | + * corrupting register state on those chipsets which have | |
193 | + * a delay between writing the SMI trigger register and | |
194 | + * entering SMM. | |
195 | + */ | |
196 | + asm volatile ( | |
197 | + "stc\n" | |
198 | + "outb %%al, %%dx\n" | |
199 | + "1: jc 1b\n" | |
200 | + : "=a" (result) | |
201 | + : "0" (cmd), | |
202 | + "d" (gsmi_dev.smi_cmd), | |
203 | + "b" (gsmi_dev.param_buf->address) | |
204 | + : "memory", "cc" | |
205 | + ); | |
206 | + } else if (gsmi_dev.handshake_type == GSMI_HANDSHAKE_SPIN) { | |
207 | + /* | |
208 | + * If handshake_type == HANDSHAKE_SPIN we spin a | |
209 | + * hundred-ish usecs to ensure the SMI has triggered. | |
210 | + */ | |
211 | + asm volatile ( | |
212 | + "outb %%al, %%dx\n" | |
213 | + "1: loop 1b\n" | |
214 | + : "=a" (result) | |
215 | + : "0" (cmd), | |
216 | + "d" (gsmi_dev.smi_cmd), | |
217 | + "b" (gsmi_dev.param_buf->address), | |
218 | + "c" (spincount) | |
219 | + : "memory", "cc" | |
220 | + ); | |
221 | + } else { | |
222 | + /* | |
223 | + * If handshake_type == HANDSHAKE_NONE we do nothing; | |
224 | + * either we don't need to or it's legacy firmware that | |
225 | + * doesn't understand the CF protocol. | |
226 | + */ | |
227 | + asm volatile ( | |
228 | + "outb %%al, %%dx\n\t" | |
229 | + : "=a" (result) | |
230 | + : "0" (cmd), | |
231 | + "d" (gsmi_dev.smi_cmd), | |
232 | + "b" (gsmi_dev.param_buf->address) | |
233 | + : "memory", "cc" | |
234 | + ); | |
235 | + } | |
236 | + | |
237 | + /* check return code from SMI handler */ | |
238 | + switch (result) { | |
239 | + case GSMI_SUCCESS: | |
240 | + break; | |
241 | + case GSMI_VAR_NOT_FOUND: | |
242 | + /* not really an error, but let the caller know */ | |
243 | + rc = 1; | |
244 | + break; | |
245 | + case GSMI_INVALID_PARAMETER: | |
246 | + printk(KERN_ERR "gsmi: exec 0x%04x: Invalid parameter\n", cmd); | |
247 | + rc = -EINVAL; | |
248 | + break; | |
249 | + case GSMI_BUFFER_TOO_SMALL: | |
250 | + printk(KERN_ERR "gsmi: exec 0x%04x: Buffer too small\n", cmd); | |
251 | + rc = -ENOMEM; | |
252 | + break; | |
253 | + case GSMI_UNSUPPORTED: | |
254 | + case GSMI_UNSUPPORTED2: | |
255 | + if (sub != GSMI_CMD_HANDSHAKE_TYPE) | |
256 | + printk(KERN_ERR "gsmi: exec 0x%04x: Not supported\n", | |
257 | + cmd); | |
258 | + rc = -ENOSYS; | |
259 | + break; | |
260 | + case GSMI_NOT_READY: | |
261 | + printk(KERN_ERR "gsmi: exec 0x%04x: Not ready\n", cmd); | |
262 | + rc = -EBUSY; | |
263 | + break; | |
264 | + case GSMI_DEVICE_ERROR: | |
265 | + printk(KERN_ERR "gsmi: exec 0x%04x: Device error\n", cmd); | |
266 | + rc = -EFAULT; | |
267 | + break; | |
268 | + case GSMI_NOT_FOUND: | |
269 | + printk(KERN_ERR "gsmi: exec 0x%04x: Data not found\n", cmd); | |
270 | + rc = -ENOENT; | |
271 | + break; | |
272 | + case GSMI_LOG_FULL: | |
273 | + printk(KERN_ERR "gsmi: exec 0x%04x: Log full\n", cmd); | |
274 | + rc = -ENOSPC; | |
275 | + break; | |
276 | + case GSMI_HANDSHAKE_CF: | |
277 | + case GSMI_HANDSHAKE_SPIN: | |
278 | + case GSMI_HANDSHAKE_NONE: | |
279 | + rc = result; | |
280 | + break; | |
281 | + default: | |
282 | + printk(KERN_ERR "gsmi: exec 0x%04x: Unknown error 0x%04x\n", | |
283 | + cmd, result); | |
284 | + rc = -ENXIO; | |
285 | + } | |
286 | + | |
287 | + return rc; | |
288 | +} | |
289 | + | |
290 | +/* Return the number of unicode characters in data */ | |
291 | +static size_t | |
292 | +utf16_strlen(efi_char16_t *data, unsigned long maxlength) | |
293 | +{ | |
294 | + unsigned long length = 0; | |
295 | + | |
296 | + while (*data++ != 0 && length < maxlength) | |
297 | + length++; | |
298 | + return length; | |
299 | +} | |
300 | + | |
301 | +static efi_status_t gsmi_get_variable(efi_char16_t *name, | |
302 | + efi_guid_t *vendor, u32 *attr, | |
303 | + unsigned long *data_size, | |
304 | + void *data) | |
305 | +{ | |
306 | + struct gsmi_nvram_var_param param = { | |
307 | + .name_ptr = gsmi_dev.name_buf->address, | |
308 | + .data_ptr = gsmi_dev.data_buf->address, | |
309 | + .data_len = (u32)*data_size, | |
310 | + }; | |
311 | + efi_status_t ret = EFI_SUCCESS; | |
312 | + unsigned long flags; | |
313 | + size_t name_len = utf16_strlen(name, GSMI_BUF_SIZE / 2); | |
314 | + int rc; | |
315 | + | |
316 | + if (name_len >= GSMI_BUF_SIZE / 2) | |
317 | + return EFI_BAD_BUFFER_SIZE; | |
318 | + | |
319 | + spin_lock_irqsave(&gsmi_dev.lock, flags); | |
320 | + | |
321 | + /* Vendor guid */ | |
322 | + memcpy(¶m.guid, vendor, sizeof(param.guid)); | |
323 | + | |
324 | + /* variable name, already in UTF-16 */ | |
325 | + memset(gsmi_dev.name_buf->start, 0, gsmi_dev.name_buf->length); | |
326 | + memcpy(gsmi_dev.name_buf->start, name, name_len * 2); | |
327 | + | |
328 | + /* data pointer */ | |
329 | + memset(gsmi_dev.data_buf->start, 0, gsmi_dev.data_buf->length); | |
330 | + | |
331 | + /* parameter buffer */ | |
332 | + memset(gsmi_dev.param_buf->start, 0, gsmi_dev.param_buf->length); | |
333 | + memcpy(gsmi_dev.param_buf->start, ¶m, sizeof(param)); | |
334 | + | |
335 | + rc = gsmi_exec(GSMI_CALLBACK, GSMI_CMD_GET_NVRAM_VAR); | |
336 | + if (rc < 0) { | |
337 | + printk(KERN_ERR "gsmi: Get Variable failed\n"); | |
338 | + ret = EFI_LOAD_ERROR; | |
339 | + } else if (rc == 1) { | |
340 | + /* variable was not found */ | |
341 | + ret = EFI_NOT_FOUND; | |
342 | + } else { | |
343 | + /* Get the arguments back */ | |
344 | + memcpy(¶m, gsmi_dev.param_buf->start, sizeof(param)); | |
345 | + | |
346 | + /* The size reported is the min of all of our buffers */ | |
347 | + *data_size = min(*data_size, gsmi_dev.data_buf->length); | |
348 | + *data_size = min_t(unsigned long, *data_size, param.data_len); | |
349 | + | |
350 | + /* Copy data back to return buffer. */ | |
351 | + memcpy(data, gsmi_dev.data_buf->start, *data_size); | |
352 | + | |
353 | + /* All variables are have the following attributes */ | |
354 | + *attr = EFI_VARIABLE_NON_VOLATILE | | |
355 | + EFI_VARIABLE_BOOTSERVICE_ACCESS | | |
356 | + EFI_VARIABLE_RUNTIME_ACCESS; | |
357 | + } | |
358 | + | |
359 | + spin_unlock_irqrestore(&gsmi_dev.lock, flags); | |
360 | + | |
361 | + return ret; | |
362 | +} | |
363 | + | |
364 | +static efi_status_t gsmi_get_next_variable(unsigned long *name_size, | |
365 | + efi_char16_t *name, | |
366 | + efi_guid_t *vendor) | |
367 | +{ | |
368 | + struct gsmi_get_next_var_param param = { | |
369 | + .name_ptr = gsmi_dev.name_buf->address, | |
370 | + .name_len = gsmi_dev.name_buf->length, | |
371 | + }; | |
372 | + efi_status_t ret = EFI_SUCCESS; | |
373 | + int rc; | |
374 | + unsigned long flags; | |
375 | + | |
376 | + /* For the moment, only support buffers that exactly match in size */ | |
377 | + if (*name_size != GSMI_BUF_SIZE) | |
378 | + return EFI_BAD_BUFFER_SIZE; | |
379 | + | |
380 | + /* Let's make sure the thing is at least null-terminated */ | |
381 | + if (utf16_strlen(name, GSMI_BUF_SIZE / 2) == GSMI_BUF_SIZE / 2) | |
382 | + return EFI_INVALID_PARAMETER; | |
383 | + | |
384 | + spin_lock_irqsave(&gsmi_dev.lock, flags); | |
385 | + | |
386 | + /* guid */ | |
387 | + memcpy(¶m.guid, vendor, sizeof(param.guid)); | |
388 | + | |
389 | + /* variable name, already in UTF-16 */ | |
390 | + memcpy(gsmi_dev.name_buf->start, name, *name_size); | |
391 | + | |
392 | + /* parameter buffer */ | |
393 | + memset(gsmi_dev.param_buf->start, 0, gsmi_dev.param_buf->length); | |
394 | + memcpy(gsmi_dev.param_buf->start, ¶m, sizeof(param)); | |
395 | + | |
396 | + rc = gsmi_exec(GSMI_CALLBACK, GSMI_CMD_GET_NEXT_VAR); | |
397 | + if (rc < 0) { | |
398 | + printk(KERN_ERR "gsmi: Get Next Variable Name failed\n"); | |
399 | + ret = EFI_LOAD_ERROR; | |
400 | + } else if (rc == 1) { | |
401 | + /* variable not found -- end of list */ | |
402 | + ret = EFI_NOT_FOUND; | |
403 | + } else { | |
404 | + /* copy variable data back to return buffer */ | |
405 | + memcpy(¶m, gsmi_dev.param_buf->start, sizeof(param)); | |
406 | + | |
407 | + /* Copy the name back */ | |
408 | + memcpy(name, gsmi_dev.name_buf->start, GSMI_BUF_SIZE); | |
409 | + *name_size = utf16_strlen(name, GSMI_BUF_SIZE / 2) * 2; | |
410 | + | |
411 | + /* copy guid to return buffer */ | |
412 | + memcpy(vendor, ¶m.guid, sizeof(param.guid)); | |
413 | + ret = EFI_SUCCESS; | |
414 | + } | |
415 | + | |
416 | + spin_unlock_irqrestore(&gsmi_dev.lock, flags); | |
417 | + | |
418 | + return ret; | |
419 | +} | |
420 | + | |
421 | +static efi_status_t gsmi_set_variable(efi_char16_t *name, | |
422 | + efi_guid_t *vendor, | |
423 | + unsigned long attr, | |
424 | + unsigned long data_size, | |
425 | + void *data) | |
426 | +{ | |
427 | + struct gsmi_nvram_var_param param = { | |
428 | + .name_ptr = gsmi_dev.name_buf->address, | |
429 | + .data_ptr = gsmi_dev.data_buf->address, | |
430 | + .data_len = (u32)data_size, | |
431 | + .attributes = EFI_VARIABLE_NON_VOLATILE | | |
432 | + EFI_VARIABLE_BOOTSERVICE_ACCESS | | |
433 | + EFI_VARIABLE_RUNTIME_ACCESS, | |
434 | + }; | |
435 | + size_t name_len = utf16_strlen(name, GSMI_BUF_SIZE / 2); | |
436 | + efi_status_t ret = EFI_SUCCESS; | |
437 | + int rc; | |
438 | + unsigned long flags; | |
439 | + | |
440 | + if (name_len >= GSMI_BUF_SIZE / 2) | |
441 | + return EFI_BAD_BUFFER_SIZE; | |
442 | + | |
443 | + spin_lock_irqsave(&gsmi_dev.lock, flags); | |
444 | + | |
445 | + /* guid */ | |
446 | + memcpy(¶m.guid, vendor, sizeof(param.guid)); | |
447 | + | |
448 | + /* variable name, already in UTF-16 */ | |
449 | + memset(gsmi_dev.name_buf->start, 0, gsmi_dev.name_buf->length); | |
450 | + memcpy(gsmi_dev.name_buf->start, name, name_len * 2); | |
451 | + | |
452 | + /* data pointer */ | |
453 | + memset(gsmi_dev.data_buf->start, 0, gsmi_dev.data_buf->length); | |
454 | + memcpy(gsmi_dev.data_buf->start, data, data_size); | |
455 | + | |
456 | + /* parameter buffer */ | |
457 | + memset(gsmi_dev.param_buf->start, 0, gsmi_dev.param_buf->length); | |
458 | + memcpy(gsmi_dev.param_buf->start, ¶m, sizeof(param)); | |
459 | + | |
460 | + rc = gsmi_exec(GSMI_CALLBACK, GSMI_CMD_SET_NVRAM_VAR); | |
461 | + if (rc < 0) { | |
462 | + printk(KERN_ERR "gsmi: Set Variable failed\n"); | |
463 | + ret = EFI_INVALID_PARAMETER; | |
464 | + } | |
465 | + | |
466 | + spin_unlock_irqrestore(&gsmi_dev.lock, flags); | |
467 | + | |
468 | + return ret; | |
469 | +} | |
470 | + | |
471 | +static const struct efivar_operations efivar_ops = { | |
472 | + .get_variable = gsmi_get_variable, | |
473 | + .set_variable = gsmi_set_variable, | |
474 | + .get_next_variable = gsmi_get_next_variable, | |
475 | +}; | |
476 | + | |
477 | +static ssize_t eventlog_write(struct file *filp, struct kobject *kobj, | |
478 | + struct bin_attribute *bin_attr, | |
479 | + char *buf, loff_t pos, size_t count) | |
480 | +{ | |
481 | + struct gsmi_set_eventlog_param param = { | |
482 | + .data_ptr = gsmi_dev.data_buf->address, | |
483 | + }; | |
484 | + int rc = 0; | |
485 | + unsigned long flags; | |
486 | + | |
487 | + /* Pull the type out */ | |
488 | + if (count < sizeof(u32)) | |
489 | + return -EINVAL; | |
490 | + param.type = *(u32 *)buf; | |
491 | + count -= sizeof(u32); | |
492 | + buf += sizeof(u32); | |
493 | + | |
494 | + /* The remaining buffer is the data payload */ | |
495 | + if (count > gsmi_dev.data_buf->length) | |
496 | + return -EINVAL; | |
497 | + param.data_len = count - sizeof(u32); | |
498 | + | |
499 | + spin_lock_irqsave(&gsmi_dev.lock, flags); | |
500 | + | |
501 | + /* data pointer */ | |
502 | + memset(gsmi_dev.data_buf->start, 0, gsmi_dev.data_buf->length); | |
503 | + memcpy(gsmi_dev.data_buf->start, buf, param.data_len); | |
504 | + | |
505 | + /* parameter buffer */ | |
506 | + memset(gsmi_dev.param_buf->start, 0, gsmi_dev.param_buf->length); | |
507 | + memcpy(gsmi_dev.param_buf->start, ¶m, sizeof(param)); | |
508 | + | |
509 | + rc = gsmi_exec(GSMI_CALLBACK, GSMI_CMD_SET_EVENT_LOG); | |
510 | + if (rc < 0) | |
511 | + printk(KERN_ERR "gsmi: Set Event Log failed\n"); | |
512 | + | |
513 | + spin_unlock_irqrestore(&gsmi_dev.lock, flags); | |
514 | + | |
515 | + return rc; | |
516 | + | |
517 | +} | |
518 | + | |
519 | +static struct bin_attribute eventlog_bin_attr = { | |
520 | + .attr = {.name = "append_to_eventlog", .mode = 0200}, | |
521 | + .write = eventlog_write, | |
522 | +}; | |
523 | + | |
524 | +static ssize_t gsmi_clear_eventlog_store(struct kobject *kobj, | |
525 | + struct kobj_attribute *attr, | |
526 | + const char *buf, size_t count) | |
527 | +{ | |
528 | + int rc; | |
529 | + unsigned long flags; | |
530 | + unsigned long val; | |
531 | + struct { | |
532 | + u32 percentage; | |
533 | + u32 data_type; | |
534 | + } param; | |
535 | + | |
536 | + rc = strict_strtoul(buf, 0, &val); | |
537 | + if (rc) | |
538 | + return rc; | |
539 | + | |
540 | + /* | |
541 | + * Value entered is a percentage, 0 through 100, anything else | |
542 | + * is invalid. | |
543 | + */ | |
544 | + if (val > 100) | |
545 | + return -EINVAL; | |
546 | + | |
547 | + /* data_type here selects the smbios event log. */ | |
548 | + param.percentage = val; | |
549 | + param.data_type = 0; | |
550 | + | |
551 | + spin_lock_irqsave(&gsmi_dev.lock, flags); | |
552 | + | |
553 | + /* parameter buffer */ | |
554 | + memset(gsmi_dev.param_buf->start, 0, gsmi_dev.param_buf->length); | |
555 | + memcpy(gsmi_dev.param_buf->start, ¶m, sizeof(param)); | |
556 | + | |
557 | + rc = gsmi_exec(GSMI_CALLBACK, GSMI_CMD_CLEAR_EVENT_LOG); | |
558 | + | |
559 | + spin_unlock_irqrestore(&gsmi_dev.lock, flags); | |
560 | + | |
561 | + if (rc) | |
562 | + return rc; | |
563 | + return count; | |
564 | +} | |
565 | + | |
566 | +static struct kobj_attribute gsmi_clear_eventlog_attr = { | |
567 | + .attr = {.name = "clear_eventlog", .mode = 0200}, | |
568 | + .store = gsmi_clear_eventlog_store, | |
569 | +}; | |
570 | + | |
571 | +static ssize_t gsmi_clear_config_store(struct kobject *kobj, | |
572 | + struct kobj_attribute *attr, | |
573 | + const char *buf, size_t count) | |
574 | +{ | |
575 | + int rc; | |
576 | + unsigned long flags; | |
577 | + | |
578 | + spin_lock_irqsave(&gsmi_dev.lock, flags); | |
579 | + | |
580 | + /* clear parameter buffer */ | |
581 | + memset(gsmi_dev.param_buf->start, 0, gsmi_dev.param_buf->length); | |
582 | + | |
583 | + rc = gsmi_exec(GSMI_CALLBACK, GSMI_CMD_CLEAR_CONFIG); | |
584 | + | |
585 | + spin_unlock_irqrestore(&gsmi_dev.lock, flags); | |
586 | + | |
587 | + if (rc) | |
588 | + return rc; | |
589 | + return count; | |
590 | +} | |
591 | + | |
592 | +static struct kobj_attribute gsmi_clear_config_attr = { | |
593 | + .attr = {.name = "clear_config", .mode = 0200}, | |
594 | + .store = gsmi_clear_config_store, | |
595 | +}; | |
596 | + | |
597 | +static const struct attribute *gsmi_attrs[] = { | |
598 | + &gsmi_clear_config_attr.attr, | |
599 | + &gsmi_clear_eventlog_attr.attr, | |
600 | + NULL, | |
601 | +}; | |
602 | + | |
603 | +static int gsmi_shutdown_reason(int reason) | |
604 | +{ | |
605 | + struct gsmi_log_entry_type_1 entry = { | |
606 | + .type = GSMI_LOG_ENTRY_TYPE_KERNEL, | |
607 | + .instance = reason, | |
608 | + }; | |
609 | + struct gsmi_set_eventlog_param param = { | |
610 | + .data_len = sizeof(entry), | |
611 | + .type = 1, | |
612 | + }; | |
613 | + static int saved_reason; | |
614 | + int rc = 0; | |
615 | + unsigned long flags; | |
616 | + | |
617 | + /* avoid duplicate entries in the log */ | |
618 | + if (saved_reason & (1 << reason)) | |
619 | + return 0; | |
620 | + | |
621 | + spin_lock_irqsave(&gsmi_dev.lock, flags); | |
622 | + | |
623 | + saved_reason |= (1 << reason); | |
624 | + | |
625 | + /* data pointer */ | |
626 | + memset(gsmi_dev.data_buf->start, 0, gsmi_dev.data_buf->length); | |
627 | + memcpy(gsmi_dev.data_buf->start, &entry, sizeof(entry)); | |
628 | + | |
629 | + /* parameter buffer */ | |
630 | + param.data_ptr = gsmi_dev.data_buf->address; | |
631 | + memset(gsmi_dev.param_buf->start, 0, gsmi_dev.param_buf->length); | |
632 | + memcpy(gsmi_dev.param_buf->start, ¶m, sizeof(param)); | |
633 | + | |
634 | + rc = gsmi_exec(GSMI_CALLBACK, GSMI_CMD_SET_EVENT_LOG); | |
635 | + | |
636 | + spin_unlock_irqrestore(&gsmi_dev.lock, flags); | |
637 | + | |
638 | + if (rc < 0) | |
639 | + printk(KERN_ERR "gsmi: Log Shutdown Reason failed\n"); | |
640 | + else | |
641 | + printk(KERN_EMERG "gsmi: Log Shutdown Reason 0x%02x\n", | |
642 | + reason); | |
643 | + | |
644 | + return rc; | |
645 | +} | |
646 | + | |
647 | +static int gsmi_reboot_callback(struct notifier_block *nb, | |
648 | + unsigned long reason, void *arg) | |
649 | +{ | |
650 | + gsmi_shutdown_reason(GSMI_SHUTDOWN_CLEAN); | |
651 | + return NOTIFY_DONE; | |
652 | +} | |
653 | + | |
654 | +static struct notifier_block gsmi_reboot_notifier = { | |
655 | + .notifier_call = gsmi_reboot_callback | |
656 | +}; | |
657 | + | |
658 | +static int gsmi_die_callback(struct notifier_block *nb, | |
659 | + unsigned long reason, void *arg) | |
660 | +{ | |
661 | + if (reason == DIE_OOPS) | |
662 | + gsmi_shutdown_reason(GSMI_SHUTDOWN_OOPS); | |
663 | + return NOTIFY_DONE; | |
664 | +} | |
665 | + | |
666 | +static struct notifier_block gsmi_die_notifier = { | |
667 | + .notifier_call = gsmi_die_callback | |
668 | +}; | |
669 | + | |
670 | +static int gsmi_panic_callback(struct notifier_block *nb, | |
671 | + unsigned long reason, void *arg) | |
672 | +{ | |
673 | + gsmi_shutdown_reason(GSMI_SHUTDOWN_PANIC); | |
674 | + return NOTIFY_DONE; | |
675 | +} | |
676 | + | |
677 | +static struct notifier_block gsmi_panic_notifier = { | |
678 | + .notifier_call = gsmi_panic_callback, | |
679 | +}; | |
680 | + | |
681 | +/* | |
682 | + * This hash function was blatantly copied from include/linux/hash.h. | |
683 | + * It is used by this driver to obfuscate a board name that requires a | |
684 | + * quirk within this driver. | |
685 | + * | |
686 | + * Please do not remove this copy of the function as any changes to the | |
687 | + * global utility hash_64() function would break this driver's ability | |
688 | + * to identify a board and provide the appropriate quirk -- mikew@google.com | |
689 | + */ | |
690 | +static u64 __init local_hash_64(u64 val, unsigned bits) | |
691 | +{ | |
692 | + u64 hash = val; | |
693 | + | |
694 | + /* Sigh, gcc can't optimise this alone like it does for 32 bits. */ | |
695 | + u64 n = hash; | |
696 | + n <<= 18; | |
697 | + hash -= n; | |
698 | + n <<= 33; | |
699 | + hash -= n; | |
700 | + n <<= 3; | |
701 | + hash += n; | |
702 | + n <<= 3; | |
703 | + hash -= n; | |
704 | + n <<= 4; | |
705 | + hash += n; | |
706 | + n <<= 2; | |
707 | + hash += n; | |
708 | + | |
709 | + /* High bits are more random, so use them. */ | |
710 | + return hash >> (64 - bits); | |
711 | +} | |
712 | + | |
713 | +static u32 __init hash_oem_table_id(char s[8]) | |
714 | +{ | |
715 | + u64 input; | |
716 | + memcpy(&input, s, 8); | |
717 | + return local_hash_64(input, 32); | |
718 | +} | |
719 | + | |
720 | +static struct dmi_system_id gsmi_dmi_table[] __initdata = { | |
721 | + { | |
722 | + .ident = "Google Board", | |
723 | + .matches = { | |
724 | + DMI_MATCH(DMI_BOARD_VENDOR, "Google, Inc."), | |
725 | + }, | |
726 | + }, | |
727 | + {} | |
728 | +}; | |
729 | +MODULE_DEVICE_TABLE(dmi, gsmi_dmi_table); | |
730 | + | |
731 | +static __init int gsmi_system_valid(void) | |
732 | +{ | |
733 | + u32 hash; | |
734 | + | |
735 | + if (!dmi_check_system(gsmi_dmi_table)) | |
736 | + return -ENODEV; | |
737 | + | |
738 | + /* | |
739 | + * Only newer firmware supports the gsmi interface. All older | |
740 | + * firmware that didn't support this interface used to plug the | |
741 | + * table name in the first four bytes of the oem_table_id field. | |
742 | + * Newer firmware doesn't do that though, so use that as the | |
743 | + * discriminant factor. We have to do this in order to | |
744 | + * whitewash our board names out of the public driver. | |
745 | + */ | |
746 | + if (!strncmp(acpi_gbl_FADT.header.oem_table_id, "FACP", 4)) { | |
747 | + printk(KERN_INFO "gsmi: Board is too old\n"); | |
748 | + return -ENODEV; | |
749 | + } | |
750 | + | |
751 | + /* Disable on board with 1.0 BIOS due to Google bug 2602657 */ | |
752 | + hash = hash_oem_table_id(acpi_gbl_FADT.header.oem_table_id); | |
753 | + if (hash == QUIRKY_BOARD_HASH) { | |
754 | + const char *bios_ver = dmi_get_system_info(DMI_BIOS_VERSION); | |
755 | + if (strncmp(bios_ver, "1.0", 3) == 0) { | |
756 | + pr_info("gsmi: disabled on this board's BIOS %s\n", | |
757 | + bios_ver); | |
758 | + return -ENODEV; | |
759 | + } | |
760 | + } | |
761 | + | |
762 | + /* check for valid SMI command port in ACPI FADT */ | |
763 | + if (acpi_gbl_FADT.smi_command == 0) { | |
764 | + pr_info("gsmi: missing smi_command\n"); | |
765 | + return -ENODEV; | |
766 | + } | |
767 | + | |
768 | + /* Found */ | |
769 | + return 0; | |
770 | +} | |
771 | + | |
772 | +static struct kobject *gsmi_kobj; | |
773 | +static struct efivars efivars; | |
774 | + | |
775 | +static __init int gsmi_init(void) | |
776 | +{ | |
777 | + unsigned long flags; | |
778 | + int ret; | |
779 | + | |
780 | + ret = gsmi_system_valid(); | |
781 | + if (ret) | |
782 | + return ret; | |
783 | + | |
784 | + gsmi_dev.smi_cmd = acpi_gbl_FADT.smi_command; | |
785 | + | |
786 | + /* register device */ | |
787 | + gsmi_dev.pdev = platform_device_register_simple("gsmi", -1, NULL, 0); | |
788 | + if (IS_ERR(gsmi_dev.pdev)) { | |
789 | + printk(KERN_ERR "gsmi: unable to register platform device\n"); | |
790 | + return PTR_ERR(gsmi_dev.pdev); | |
791 | + } | |
792 | + | |
793 | + /* SMI access needs to be serialized */ | |
794 | + spin_lock_init(&gsmi_dev.lock); | |
795 | + | |
796 | + /* SMI callbacks require 32bit addresses */ | |
797 | + gsmi_dev.pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); | |
798 | + gsmi_dev.pdev->dev.dma_mask = | |
799 | + &gsmi_dev.pdev->dev.coherent_dma_mask; | |
800 | + ret = -ENOMEM; | |
801 | + gsmi_dev.dma_pool = dma_pool_create("gsmi", &gsmi_dev.pdev->dev, | |
802 | + GSMI_BUF_SIZE, GSMI_BUF_ALIGN, 0); | |
803 | + if (!gsmi_dev.dma_pool) | |
804 | + goto out_err; | |
805 | + | |
806 | + /* | |
807 | + * pre-allocate buffers because sometimes we are called when | |
808 | + * this is not feasible: oops, panic, die, mce, etc | |
809 | + */ | |
810 | + gsmi_dev.name_buf = gsmi_buf_alloc(); | |
811 | + if (!gsmi_dev.name_buf) { | |
812 | + printk(KERN_ERR "gsmi: failed to allocate name buffer\n"); | |
813 | + goto out_err; | |
814 | + } | |
815 | + | |
816 | + gsmi_dev.data_buf = gsmi_buf_alloc(); | |
817 | + if (!gsmi_dev.data_buf) { | |
818 | + printk(KERN_ERR "gsmi: failed to allocate data buffer\n"); | |
819 | + goto out_err; | |
820 | + } | |
821 | + | |
822 | + gsmi_dev.param_buf = gsmi_buf_alloc(); | |
823 | + if (!gsmi_dev.param_buf) { | |
824 | + printk(KERN_ERR "gsmi: failed to allocate param buffer\n"); | |
825 | + goto out_err; | |
826 | + } | |
827 | + | |
828 | + /* | |
829 | + * Determine type of handshake used to serialize the SMI | |
830 | + * entry. See also gsmi_exec(). | |
831 | + * | |
832 | + * There's a "behavior" present on some chipsets where writing the | |
833 | + * SMI trigger register in the southbridge doesn't result in an | |
834 | + * immediate SMI. Rather, the processor can execute "a few" more | |
835 | + * instructions before the SMI takes effect. To ensure synchronous | |
836 | + * behavior, implement a handshake between the kernel driver and the | |
837 | + * firmware handler to spin until released. This ioctl determines | |
838 | + * the type of handshake. | |
839 | + * | |
840 | + * NONE: The firmware handler does not implement any | |
841 | + * handshake. Either it doesn't need to, or it's legacy firmware | |
842 | + * that doesn't know it needs to and never will. | |
843 | + * | |
844 | + * CF: The firmware handler will clear the CF in the saved | |
845 | + * state before returning. The driver may set the CF and test for | |
846 | + * it to clear before proceeding. | |
847 | + * | |
848 | + * SPIN: The firmware handler does not implement any handshake | |
849 | + * but the driver should spin for a hundred or so microseconds | |
850 | + * to ensure the SMI has triggered. | |
851 | + * | |
852 | + * Finally, the handler will return -ENOSYS if | |
853 | + * GSMI_CMD_HANDSHAKE_TYPE is unimplemented, which implies | |
854 | + * HANDSHAKE_NONE. | |
855 | + */ | |
856 | + spin_lock_irqsave(&gsmi_dev.lock, flags); | |
857 | + gsmi_dev.handshake_type = GSMI_HANDSHAKE_SPIN; | |
858 | + gsmi_dev.handshake_type = | |
859 | + gsmi_exec(GSMI_CALLBACK, GSMI_CMD_HANDSHAKE_TYPE); | |
860 | + if (gsmi_dev.handshake_type == -ENOSYS) | |
861 | + gsmi_dev.handshake_type = GSMI_HANDSHAKE_NONE; | |
862 | + spin_unlock_irqrestore(&gsmi_dev.lock, flags); | |
863 | + | |
864 | + /* Remove and clean up gsmi if the handshake could not complete. */ | |
865 | + if (gsmi_dev.handshake_type == -ENXIO) { | |
866 | + printk(KERN_INFO "gsmi version " DRIVER_VERSION | |
867 | + " failed to load\n"); | |
868 | + ret = -ENODEV; | |
869 | + goto out_err; | |
870 | + } | |
871 | + | |
872 | + printk(KERN_INFO "gsmi version " DRIVER_VERSION " loaded\n"); | |
873 | + | |
874 | + /* Register in the firmware directory */ | |
875 | + ret = -ENOMEM; | |
876 | + gsmi_kobj = kobject_create_and_add("gsmi", firmware_kobj); | |
877 | + if (!gsmi_kobj) { | |
878 | + printk(KERN_INFO "gsmi: Failed to create firmware kobj\n"); | |
879 | + goto out_err; | |
880 | + } | |
881 | + | |
882 | + /* Setup eventlog access */ | |
883 | + ret = sysfs_create_bin_file(gsmi_kobj, &eventlog_bin_attr); | |
884 | + if (ret) { | |
885 | + printk(KERN_INFO "gsmi: Failed to setup eventlog"); | |
886 | + goto out_err; | |
887 | + } | |
888 | + | |
889 | + /* Other attributes */ | |
890 | + ret = sysfs_create_files(gsmi_kobj, gsmi_attrs); | |
891 | + if (ret) { | |
892 | + printk(KERN_INFO "gsmi: Failed to add attrs"); | |
893 | + goto out_err; | |
894 | + } | |
895 | + | |
896 | + if (register_efivars(&efivars, &efivar_ops, gsmi_kobj)) { | |
897 | + printk(KERN_INFO "gsmi: Failed to register efivars\n"); | |
898 | + goto out_err; | |
899 | + } | |
900 | + | |
901 | + register_reboot_notifier(&gsmi_reboot_notifier); | |
902 | + register_die_notifier(&gsmi_die_notifier); | |
903 | + atomic_notifier_chain_register(&panic_notifier_list, | |
904 | + &gsmi_panic_notifier); | |
905 | + | |
906 | + return 0; | |
907 | + | |
908 | + out_err: | |
909 | + kobject_put(gsmi_kobj); | |
910 | + gsmi_buf_free(gsmi_dev.param_buf); | |
911 | + gsmi_buf_free(gsmi_dev.data_buf); | |
912 | + gsmi_buf_free(gsmi_dev.name_buf); | |
913 | + if (gsmi_dev.dma_pool) | |
914 | + dma_pool_destroy(gsmi_dev.dma_pool); | |
915 | + platform_device_unregister(gsmi_dev.pdev); | |
916 | + pr_info("gsmi: failed to load: %d\n", ret); | |
917 | + return ret; | |
918 | +} | |
919 | + | |
920 | +static void __exit gsmi_exit(void) | |
921 | +{ | |
922 | + unregister_reboot_notifier(&gsmi_reboot_notifier); | |
923 | + unregister_die_notifier(&gsmi_die_notifier); | |
924 | + atomic_notifier_chain_unregister(&panic_notifier_list, | |
925 | + &gsmi_panic_notifier); | |
926 | + unregister_efivars(&efivars); | |
927 | + | |
928 | + kobject_put(gsmi_kobj); | |
929 | + gsmi_buf_free(gsmi_dev.param_buf); | |
930 | + gsmi_buf_free(gsmi_dev.data_buf); | |
931 | + gsmi_buf_free(gsmi_dev.name_buf); | |
932 | + dma_pool_destroy(gsmi_dev.dma_pool); | |
933 | + platform_device_unregister(gsmi_dev.pdev); | |
934 | +} | |
935 | + | |
936 | +module_init(gsmi_init); | |
937 | +module_exit(gsmi_exit); | |
938 | + | |
939 | +MODULE_AUTHOR("Google, Inc."); | |
940 | +MODULE_LICENSE("GPL"); |
drivers/firmware/google/memconsole.c
1 | +/* | |
2 | + * memconsole.c | |
3 | + * | |
4 | + * Infrastructure for importing the BIOS memory based console | |
5 | + * into the kernel log ringbuffer. | |
6 | + * | |
7 | + * Copyright 2010 Google Inc. All rights reserved. | |
8 | + */ | |
9 | + | |
10 | +#include <linux/ctype.h> | |
11 | +#include <linux/init.h> | |
12 | +#include <linux/kernel.h> | |
13 | +#include <linux/string.h> | |
14 | +#include <linux/sysfs.h> | |
15 | +#include <linux/kobject.h> | |
16 | +#include <linux/module.h> | |
17 | +#include <linux/dmi.h> | |
18 | +#include <asm/bios_ebda.h> | |
19 | + | |
20 | +#define BIOS_MEMCONSOLE_V1_MAGIC 0xDEADBABE | |
21 | +#define BIOS_MEMCONSOLE_V2_MAGIC (('M')|('C'<<8)|('O'<<16)|('N'<<24)) | |
22 | + | |
23 | +struct biosmemcon_ebda { | |
24 | + u32 signature; | |
25 | + union { | |
26 | + struct { | |
27 | + u8 enabled; | |
28 | + u32 buffer_addr; | |
29 | + u16 start; | |
30 | + u16 end; | |
31 | + u16 num_chars; | |
32 | + u8 wrapped; | |
33 | + } __packed v1; | |
34 | + struct { | |
35 | + u32 buffer_addr; | |
36 | + /* Misdocumented as number of pages! */ | |
37 | + u16 num_bytes; | |
38 | + u16 start; | |
39 | + u16 end; | |
40 | + } __packed v2; | |
41 | + }; | |
42 | +} __packed; | |
43 | + | |
44 | +static char *memconsole_baseaddr; | |
45 | +static size_t memconsole_length; | |
46 | + | |
47 | +static ssize_t memconsole_read(struct file *filp, struct kobject *kobp, | |
48 | + struct bin_attribute *bin_attr, char *buf, | |
49 | + loff_t pos, size_t count) | |
50 | +{ | |
51 | + return memory_read_from_buffer(buf, count, &pos, memconsole_baseaddr, | |
52 | + memconsole_length); | |
53 | +} | |
54 | + | |
55 | +static struct bin_attribute memconsole_bin_attr = { | |
56 | + .attr = {.name = "log", .mode = 0444}, | |
57 | + .read = memconsole_read, | |
58 | +}; | |
59 | + | |
60 | + | |
61 | +static void found_v1_header(struct biosmemcon_ebda *hdr) | |
62 | +{ | |
63 | + printk(KERN_INFO "BIOS console v1 EBDA structure found at %p\n", hdr); | |
64 | + printk(KERN_INFO "BIOS console buffer at 0x%.8x, " | |
65 | + "start = %d, end = %d, num = %d\n", | |
66 | + hdr->v1.buffer_addr, hdr->v1.start, | |
67 | + hdr->v1.end, hdr->v1.num_chars); | |
68 | + | |
69 | + memconsole_length = hdr->v1.num_chars; | |
70 | + memconsole_baseaddr = phys_to_virt(hdr->v1.buffer_addr); | |
71 | +} | |
72 | + | |
73 | +static void found_v2_header(struct biosmemcon_ebda *hdr) | |
74 | +{ | |
75 | + printk(KERN_INFO "BIOS console v2 EBDA structure found at %p\n", hdr); | |
76 | + printk(KERN_INFO "BIOS console buffer at 0x%.8x, " | |
77 | + "start = %d, end = %d, num_bytes = %d\n", | |
78 | + hdr->v2.buffer_addr, hdr->v2.start, | |
79 | + hdr->v2.end, hdr->v2.num_bytes); | |
80 | + | |
81 | + memconsole_length = hdr->v2.end - hdr->v2.start; | |
82 | + memconsole_baseaddr = phys_to_virt(hdr->v2.buffer_addr | |
83 | + + hdr->v2.start); | |
84 | +} | |
85 | + | |
86 | +/* | |
87 | + * Search through the EBDA for the BIOS Memory Console, and | |
88 | + * set the global variables to point to it. Return true if found. | |
89 | + */ | |
90 | +static bool found_memconsole(void) | |
91 | +{ | |
92 | + unsigned int address; | |
93 | + size_t length, cur; | |
94 | + | |
95 | + address = get_bios_ebda(); | |
96 | + if (!address) { | |
97 | + printk(KERN_INFO "BIOS EBDA non-existent.\n"); | |
98 | + return false; | |
99 | + } | |
100 | + | |
101 | + /* EBDA length is byte 0 of EBDA (in KB) */ | |
102 | + length = *(u8 *)phys_to_virt(address); | |
103 | + length <<= 10; /* convert to bytes */ | |
104 | + | |
105 | + /* | |
106 | + * Search through EBDA for BIOS memory console structure | |
107 | + * note: signature is not necessarily dword-aligned | |
108 | + */ | |
109 | + for (cur = 0; cur < length; cur++) { | |
110 | + struct biosmemcon_ebda *hdr = phys_to_virt(address + cur); | |
111 | + | |
112 | + /* memconsole v1 */ | |
113 | + if (hdr->signature == BIOS_MEMCONSOLE_V1_MAGIC) { | |
114 | + found_v1_header(hdr); | |
115 | + return true; | |
116 | + } | |
117 | + | |
118 | + /* memconsole v2 */ | |
119 | + if (hdr->signature == BIOS_MEMCONSOLE_V2_MAGIC) { | |
120 | + found_v2_header(hdr); | |
121 | + return true; | |
122 | + } | |
123 | + } | |
124 | + | |
125 | + printk(KERN_INFO "BIOS console EBDA structure not found!\n"); | |
126 | + return false; | |
127 | +} | |
128 | + | |
129 | +static struct dmi_system_id memconsole_dmi_table[] __initdata = { | |
130 | + { | |
131 | + .ident = "Google Board", | |
132 | + .matches = { | |
133 | + DMI_MATCH(DMI_BOARD_VENDOR, "Google, Inc."), | |
134 | + }, | |
135 | + }, | |
136 | + {} | |
137 | +}; | |
138 | +MODULE_DEVICE_TABLE(dmi, memconsole_dmi_table); | |
139 | + | |
140 | +static int __init memconsole_init(void) | |
141 | +{ | |
142 | + int ret; | |
143 | + | |
144 | + if (!dmi_check_system(memconsole_dmi_table)) | |
145 | + return -ENODEV; | |
146 | + | |
147 | + if (!found_memconsole()) | |
148 | + return -ENODEV; | |
149 | + | |
150 | + memconsole_bin_attr.size = memconsole_length; | |
151 | + | |
152 | + ret = sysfs_create_bin_file(firmware_kobj, &memconsole_bin_attr); | |
153 | + | |
154 | + return ret; | |
155 | +} | |
156 | + | |
157 | +static void __exit memconsole_exit(void) | |
158 | +{ | |
159 | + sysfs_remove_bin_file(firmware_kobj, &memconsole_bin_attr); | |
160 | +} | |
161 | + | |
162 | +module_init(memconsole_init); | |
163 | +module_exit(memconsole_exit); | |
164 | + | |
165 | +MODULE_AUTHOR("Google, Inc."); | |
166 | +MODULE_LICENSE("GPL"); |
drivers/misc/ti-st/Kconfig
drivers/misc/ti-st/st_core.c
... | ... | @@ -43,13 +43,15 @@ |
43 | 43 | pr_info("%s: id %d\n", __func__, new_proto->chnl_id); |
44 | 44 | /* list now has the channel id as index itself */ |
45 | 45 | st_gdata->list[new_proto->chnl_id] = new_proto; |
46 | + st_gdata->is_registered[new_proto->chnl_id] = true; | |
46 | 47 | } |
47 | 48 | |
48 | 49 | static void remove_channel_from_table(struct st_data_s *st_gdata, |
49 | 50 | struct st_proto_s *proto) |
50 | 51 | { |
51 | 52 | pr_info("%s: id %d\n", __func__, proto->chnl_id); |
52 | - st_gdata->list[proto->chnl_id] = NULL; | |
53 | +/* st_gdata->list[proto->chnl_id] = NULL; */ | |
54 | + st_gdata->is_registered[proto->chnl_id] = false; | |
53 | 55 | } |
54 | 56 | |
55 | 57 | /* |
... | ... | @@ -104,7 +106,7 @@ |
104 | 106 | |
105 | 107 | if (unlikely |
106 | 108 | (st_gdata == NULL || st_gdata->rx_skb == NULL |
107 | - || st_gdata->list[chnl_id] == NULL)) { | |
109 | + || st_gdata->is_registered[chnl_id] == false)) { | |
108 | 110 | pr_err("chnl_id %d not registered, no data to send?", |
109 | 111 | chnl_id); |
110 | 112 | kfree_skb(st_gdata->rx_skb); |
111 | 113 | |
... | ... | @@ -141,14 +143,15 @@ |
141 | 143 | unsigned char i = 0; |
142 | 144 | pr_info(" %s ", __func__); |
143 | 145 | for (i = 0; i < ST_MAX_CHANNELS; i++) { |
144 | - if (likely(st_gdata != NULL && st_gdata->list[i] != NULL && | |
145 | - st_gdata->list[i]->reg_complete_cb != NULL)) { | |
146 | + if (likely(st_gdata != NULL && | |
147 | + st_gdata->is_registered[i] == true && | |
148 | + st_gdata->list[i]->reg_complete_cb != NULL)) { | |
146 | 149 | st_gdata->list[i]->reg_complete_cb |
147 | 150 | (st_gdata->list[i]->priv_data, err); |
148 | 151 | pr_info("protocol %d's cb sent %d\n", i, err); |
149 | 152 | if (err) { /* cleanup registered protocol */ |
150 | 153 | st_gdata->protos_registered--; |
151 | - st_gdata->list[i] = NULL; | |
154 | + st_gdata->is_registered[i] = false; | |
152 | 155 | } |
153 | 156 | } |
154 | 157 | } |
... | ... | @@ -475,9 +478,9 @@ |
475 | 478 | { |
476 | 479 | seq_printf(buf, "[%d]\nBT=%c\nFM=%c\nGPS=%c\n", |
477 | 480 | st_gdata->protos_registered, |
478 | - st_gdata->list[0x04] != NULL ? 'R' : 'U', | |
479 | - st_gdata->list[0x08] != NULL ? 'R' : 'U', | |
480 | - st_gdata->list[0x09] != NULL ? 'R' : 'U'); | |
481 | + st_gdata->is_registered[0x04] == true ? 'R' : 'U', | |
482 | + st_gdata->is_registered[0x08] == true ? 'R' : 'U', | |
483 | + st_gdata->is_registered[0x09] == true ? 'R' : 'U'); | |
481 | 484 | } |
482 | 485 | |
483 | 486 | /********************************************************************/ |
... | ... | @@ -504,7 +507,7 @@ |
504 | 507 | return -EPROTONOSUPPORT; |
505 | 508 | } |
506 | 509 | |
507 | - if (st_gdata->list[new_proto->chnl_id] != NULL) { | |
510 | + if (st_gdata->is_registered[new_proto->chnl_id] == true) { | |
508 | 511 | pr_err("chnl_id %d already registered", new_proto->chnl_id); |
509 | 512 | return -EALREADY; |
510 | 513 | } |
... | ... | @@ -563,7 +566,7 @@ |
563 | 566 | /* check for already registered once more, |
564 | 567 | * since the above check is old |
565 | 568 | */ |
566 | - if (st_gdata->list[new_proto->chnl_id] != NULL) { | |
569 | + if (st_gdata->is_registered[new_proto->chnl_id] == true) { | |
567 | 570 | pr_err(" proto %d already registered ", |
568 | 571 | new_proto->chnl_id); |
569 | 572 | return -EALREADY; |
drivers/misc/ti-st/st_kim.c
drivers/uio/uio.c
... | ... | @@ -381,7 +381,13 @@ |
381 | 381 | retval = -ENOMEM; |
382 | 382 | goto exit; |
383 | 383 | } |
384 | - idev->minor = id & MAX_ID_MASK; | |
384 | + if (id < UIO_MAX_DEVICES) { | |
385 | + idev->minor = id; | |
386 | + } else { | |
387 | + dev_err(idev->dev, "too many uio devices\n"); | |
388 | + retval = -EINVAL; | |
389 | + idr_remove(&uio_idr, id); | |
390 | + } | |
385 | 391 | exit: |
386 | 392 | mutex_unlock(&minor_lock); |
387 | 393 | return retval; |
388 | 394 | |
389 | 395 | |
... | ... | @@ -587,14 +593,12 @@ |
587 | 593 | |
588 | 594 | static int uio_find_mem_index(struct vm_area_struct *vma) |
589 | 595 | { |
590 | - int mi; | |
591 | 596 | struct uio_device *idev = vma->vm_private_data; |
592 | 597 | |
593 | - for (mi = 0; mi < MAX_UIO_MAPS; mi++) { | |
594 | - if (idev->info->mem[mi].size == 0) | |
598 | + if (vma->vm_pgoff < MAX_UIO_MAPS) { | |
599 | + if (idev->info->mem[vma->vm_pgoff].size == 0) | |
595 | 600 | return -1; |
596 | - if (vma->vm_pgoff == mi) | |
597 | - return mi; | |
601 | + return (int)vma->vm_pgoff; | |
598 | 602 | } |
599 | 603 | return -1; |
600 | 604 | } |
drivers/uio/uio_netx.c
... | ... | @@ -18,6 +18,9 @@ |
18 | 18 | |
19 | 19 | #define PCI_VENDOR_ID_HILSCHER 0x15CF |
20 | 20 | #define PCI_DEVICE_ID_HILSCHER_NETX 0x0000 |
21 | +#define PCI_DEVICE_ID_HILSCHER_NETPLC 0x0010 | |
22 | +#define PCI_SUBDEVICE_ID_NETPLC_RAM 0x0000 | |
23 | +#define PCI_SUBDEVICE_ID_NETPLC_FLASH 0x0001 | |
21 | 24 | #define PCI_SUBDEVICE_ID_NXSB_PCA 0x3235 |
22 | 25 | #define PCI_SUBDEVICE_ID_NXPCA 0x3335 |
23 | 26 | |
... | ... | @@ -66,6 +69,10 @@ |
66 | 69 | bar = 0; |
67 | 70 | info->name = "netx"; |
68 | 71 | break; |
72 | + case PCI_DEVICE_ID_HILSCHER_NETPLC: | |
73 | + bar = 0; | |
74 | + info->name = "netplc"; | |
75 | + break; | |
69 | 76 | default: |
70 | 77 | bar = 2; |
71 | 78 | info->name = "netx_plx"; |
... | ... | @@ -132,6 +139,18 @@ |
132 | 139 | .device = PCI_DEVICE_ID_HILSCHER_NETX, |
133 | 140 | .subvendor = 0, |
134 | 141 | .subdevice = 0, |
142 | + }, | |
143 | + { | |
144 | + .vendor = PCI_VENDOR_ID_HILSCHER, | |
145 | + .device = PCI_DEVICE_ID_HILSCHER_NETPLC, | |
146 | + .subvendor = PCI_VENDOR_ID_HILSCHER, | |
147 | + .subdevice = PCI_SUBDEVICE_ID_NETPLC_RAM, | |
148 | + }, | |
149 | + { | |
150 | + .vendor = PCI_VENDOR_ID_HILSCHER, | |
151 | + .device = PCI_DEVICE_ID_HILSCHER_NETPLC, | |
152 | + .subvendor = PCI_VENDOR_ID_HILSCHER, | |
153 | + .subdevice = PCI_SUBDEVICE_ID_NETPLC_FLASH, | |
135 | 154 | }, |
136 | 155 | { |
137 | 156 | .vendor = PCI_VENDOR_ID_PLX, |
drivers/uio/uio_pdrv_genirq.c
fs/debugfs/file.c
fs/sysfs/file.c
... | ... | @@ -24,13 +24,6 @@ |
24 | 24 | |
25 | 25 | #include "sysfs.h" |
26 | 26 | |
27 | -/* used in crash dumps to help with debugging */ | |
28 | -static char last_sysfs_file[PATH_MAX]; | |
29 | -void sysfs_printk_last_file(void) | |
30 | -{ | |
31 | - printk(KERN_EMERG "last sysfs file: %s\n", last_sysfs_file); | |
32 | -} | |
33 | - | |
34 | 27 | /* |
35 | 28 | * There's one sysfs_buffer for each open file and one |
36 | 29 | * sysfs_open_dirent for each sysfs_dirent with one or more open |
... | ... | @@ -337,11 +330,6 @@ |
337 | 330 | struct sysfs_buffer *buffer; |
338 | 331 | const struct sysfs_ops *ops; |
339 | 332 | int error = -EACCES; |
340 | - char *p; | |
341 | - | |
342 | - p = d_path(&file->f_path, last_sysfs_file, sizeof(last_sysfs_file)); | |
343 | - if (!IS_ERR(p)) | |
344 | - memmove(last_sysfs_file, p, strlen(p) + 1); | |
345 | 333 | |
346 | 334 | /* need attr_sd for attr and ops, its parent for kobj */ |
347 | 335 | if (!sysfs_get_active(attr_sd)) |
fs/sysfs/group.c
... | ... | @@ -101,9 +101,9 @@ |
101 | 101 | } |
102 | 102 | |
103 | 103 | /** |
104 | - * sysfs_update_group - given a directory kobject, create an attribute group | |
105 | - * @kobj: The kobject to create the group on | |
106 | - * @grp: The attribute group to create | |
104 | + * sysfs_update_group - given a directory kobject, update an attribute group | |
105 | + * @kobj: The kobject to update the group on | |
106 | + * @grp: The attribute group to update | |
107 | 107 | * |
108 | 108 | * This function updates an attribute group. Unlike |
109 | 109 | * sysfs_create_group(), it will explicitly not warn or error if any |
include/linux/device.h
... | ... | @@ -47,6 +47,38 @@ |
47 | 47 | struct bus_attribute *); |
48 | 48 | extern void bus_remove_file(struct bus_type *, struct bus_attribute *); |
49 | 49 | |
50 | +/** | |
51 | + * struct bus_type - The bus type of the device | |
52 | + * | |
53 | + * @name: The name of the bus. | |
54 | + * @bus_attrs: Default attributes of the bus. | |
55 | + * @dev_attrs: Default attributes of the devices on the bus. | |
56 | + * @drv_attrs: Default attributes of the device drivers on the bus. | |
57 | + * @match: Called, perhaps multiple times, whenever a new device or driver | |
58 | + * is added for this bus. It should return a nonzero value if the | |
59 | + * given device can be handled by the given driver. | |
60 | + * @uevent: Called when a device is added, removed, or a few other things | |
61 | + * that generate uevents to add the environment variables. | |
62 | + * @probe: Called when a new device or driver add to this bus, and callback | |
63 | + * the specific driver's probe to initial the matched device. | |
64 | + * @remove: Called when a device removed from this bus. | |
65 | + * @shutdown: Called at shut-down time to quiesce the device. | |
66 | + * @suspend: Called when a device on this bus wants to go to sleep mode. | |
67 | + * @resume: Called to bring a device on this bus out of sleep mode. | |
68 | + * @pm: Power management operations of this bus, callback the specific | |
69 | + * device driver's pm-ops. | |
70 | + * @p: The private data of the driver core, only the driver core can | |
71 | + * touch this. | |
72 | + * | |
73 | + * A bus is a channel between the processor and one or more devices. For the | |
74 | + * purposes of the device model, all devices are connected via a bus, even if | |
75 | + * it is an internal, virtual, "platform" bus. Buses can plug into each other. | |
76 | + * A USB controller is usually a PCI device, for example. The device model | |
77 | + * represents the actual connections between buses and the devices they control. | |
78 | + * A bus is represented by the bus_type structure. It contains the name, the | |
79 | + * default attributes, the bus' methods, PM operations, and the driver core's | |
80 | + * private data. | |
81 | + */ | |
50 | 82 | struct bus_type { |
51 | 83 | const char *name; |
52 | 84 | struct bus_attribute *bus_attrs; |
... | ... | @@ -119,6 +151,37 @@ |
119 | 151 | extern struct kset *bus_get_kset(struct bus_type *bus); |
120 | 152 | extern struct klist *bus_get_device_klist(struct bus_type *bus); |
121 | 153 | |
154 | +/** | |
155 | + * struct device_driver - The basic device driver structure | |
156 | + * @name: Name of the device driver. | |
157 | + * @bus: The bus which the device of this driver belongs to. | |
158 | + * @owner: The module owner. | |
159 | + * @mod_name: Used for built-in modules. | |
160 | + * @suppress_bind_attrs: Disables bind/unbind via sysfs. | |
161 | + * @of_match_table: The open firmware table. | |
162 | + * @probe: Called to query the existence of a specific device, | |
163 | + * whether this driver can work with it, and bind the driver | |
164 | + * to a specific device. | |
165 | + * @remove: Called when the device is removed from the system to | |
166 | + * unbind a device from this driver. | |
167 | + * @shutdown: Called at shut-down time to quiesce the device. | |
168 | + * @suspend: Called to put the device to sleep mode. Usually to a | |
169 | + * low power state. | |
170 | + * @resume: Called to bring a device from sleep mode. | |
171 | + * @groups: Default attributes that get created by the driver core | |
172 | + * automatically. | |
173 | + * @pm: Power management operations of the device which matched | |
174 | + * this driver. | |
175 | + * @p: Driver core's private data, no one other than the driver | |
176 | + * core can touch this. | |
177 | + * | |
178 | + * The device driver-model tracks all of the drivers known to the system. | |
179 | + * The main reason for this tracking is to enable the driver core to match | |
180 | + * up drivers with new devices. Once drivers are known objects within the | |
181 | + * system, however, a number of other things become possible. Device drivers | |
182 | + * can export information and configuration variables that are independent | |
183 | + * of any specific device. | |
184 | + */ | |
122 | 185 | struct device_driver { |
123 | 186 | const char *name; |
124 | 187 | struct bus_type *bus; |
... | ... | @@ -185,8 +248,34 @@ |
185 | 248 | struct device *start, void *data, |
186 | 249 | int (*match)(struct device *dev, void *data)); |
187 | 250 | |
188 | -/* | |
189 | - * device classes | |
251 | +/** | |
252 | + * struct class - device classes | |
253 | + * @name: Name of the class. | |
254 | + * @owner: The module owner. | |
255 | + * @class_attrs: Default attributes of this class. | |
256 | + * @dev_attrs: Default attributes of the devices belong to the class. | |
257 | + * @dev_bin_attrs: Default binary attributes of the devices belong to the class. | |
258 | + * @dev_kobj: The kobject that represents this class and links it into the hierarchy. | |
259 | + * @dev_uevent: Called when a device is added, removed from this class, or a | |
260 | + * few other things that generate uevents to add the environment | |
261 | + * variables. | |
262 | + * @devnode: Callback to provide the devtmpfs. | |
263 | + * @class_release: Called to release this class. | |
264 | + * @dev_release: Called to release the device. | |
265 | + * @suspend: Used to put the device to sleep mode, usually to a low power | |
266 | + * state. | |
267 | + * @resume: Used to bring the device from the sleep mode. | |
268 | + * @ns_type: Callbacks so sysfs can detemine namespaces. | |
269 | + * @namespace: Namespace of the device belongs to this class. | |
270 | + * @pm: The default device power management operations of this class. | |
271 | + * @p: The private data of the driver core, no one other than the | |
272 | + * driver core can touch this. | |
273 | + * | |
274 | + * A class is a higher-level view of a device that abstracts out low-level | |
275 | + * implementation details. Drivers may see a SCSI disk or an ATA disk, but, | |
276 | + * at the class level, they are all simply disks. Classes allow user space | |
277 | + * to work with devices based on what they do, rather than how they are | |
278 | + * connected or how they work. | |
190 | 279 | */ |
191 | 280 | struct class { |
192 | 281 | const char *name; |
... | ... | @@ -401,6 +490,65 @@ |
401 | 490 | unsigned long segment_boundary_mask; |
402 | 491 | }; |
403 | 492 | |
493 | +/** | |
494 | + * struct device - The basic device structure | |
495 | + * @parent: The device's "parent" device, the device to which it is attached. | |
496 | + * In most cases, a parent device is some sort of bus or host | |
497 | + * controller. If parent is NULL, the device, is a top-level device, | |
498 | + * which is not usually what you want. | |
499 | + * @p: Holds the private data of the driver core portions of the device. | |
500 | + * See the comment of the struct device_private for detail. | |
501 | + * @kobj: A top-level, abstract class from which other classes are derived. | |
502 | + * @init_name: Initial name of the device. | |
503 | + * @type: The type of device. | |
504 | + * This identifies the device type and carries type-specific | |
505 | + * information. | |
506 | + * @mutex: Mutex to synchronize calls to its driver. | |
507 | + * @bus: Type of bus device is on. | |
508 | + * @driver: Which driver has allocated this | |
509 | + * @platform_data: Platform data specific to the device. | |
510 | + * Example: For devices on custom boards, as typical of embedded | |
511 | + * and SOC based hardware, Linux often uses platform_data to point | |
512 | + * to board-specific structures describing devices and how they | |
513 | + * are wired. That can include what ports are available, chip | |
514 | + * variants, which GPIO pins act in what additional roles, and so | |
515 | + * on. This shrinks the "Board Support Packages" (BSPs) and | |
516 | + * minimizes board-specific #ifdefs in drivers. | |
517 | + * @power: For device power management. | |
518 | + * See Documentation/power/devices.txt for details. | |
519 | + * @pwr_domain: Provide callbacks that are executed during system suspend, | |
520 | + * hibernation, system resume and during runtime PM transitions | |
521 | + * along with subsystem-level and driver-level callbacks. | |
522 | + * @numa_node: NUMA node this device is close to. | |
523 | + * @dma_mask: Dma mask (if dma'ble device). | |
524 | + * @coherent_dma_mask: Like dma_mask, but for alloc_coherent mapping as not all | |
525 | + * hardware supports 64-bit addresses for consistent allocations | |
526 | + * such descriptors. | |
527 | + * @dma_parms: A low level driver may set these to teach IOMMU code about | |
528 | + * segment limitations. | |
529 | + * @dma_pools: Dma pools (if dma'ble device). | |
530 | + * @dma_mem: Internal for coherent mem override. | |
531 | + * @archdata: For arch-specific additions. | |
532 | + * @of_node: Associated device tree node. | |
533 | + * @of_match: Matching of_device_id from driver. | |
534 | + * @devt: For creating the sysfs "dev". | |
535 | + * @devres_lock: Spinlock to protect the resource of the device. | |
536 | + * @devres_head: The resources list of the device. | |
537 | + * @knode_class: The node used to add the device to the class list. | |
538 | + * @class: The class of the device. | |
539 | + * @groups: Optional attribute groups. | |
540 | + * @release: Callback to free the device after all references have | |
541 | + * gone away. This should be set by the allocator of the | |
542 | + * device (i.e. the bus driver that discovered the device). | |
543 | + * | |
544 | + * At the lowest level, every device in a Linux system is represented by an | |
545 | + * instance of struct device. The device structure contains the information | |
546 | + * that the device model core needs to model the system. Most subsystems, | |
547 | + * however, track additional information about the devices they host. As a | |
548 | + * result, it is rare for devices to be represented by bare device structures; | |
549 | + * instead, that structure, like kobject structures, is usually embedded within | |
550 | + * a higher-level representation of the device. | |
551 | + */ | |
404 | 552 | struct device { |
405 | 553 | struct device *parent; |
406 | 554 | |
... | ... | @@ -408,7 +556,7 @@ |
408 | 556 | |
409 | 557 | struct kobject kobj; |
410 | 558 | const char *init_name; /* initial name of the device */ |
411 | - struct device_type *type; | |
559 | + const struct device_type *type; | |
412 | 560 | |
413 | 561 | struct mutex mutex; /* mutex to synchronize calls to |
414 | 562 | * its driver. |
... | ... | @@ -556,7 +704,7 @@ |
556 | 704 | extern const char *device_get_devnode(struct device *dev, |
557 | 705 | mode_t *mode, const char **tmp); |
558 | 706 | extern void *dev_get_drvdata(const struct device *dev); |
559 | -extern void dev_set_drvdata(struct device *dev, void *data); | |
707 | +extern int dev_set_drvdata(struct device *dev, void *data); | |
560 | 708 | |
561 | 709 | /* |
562 | 710 | * Root device objects for grouping under /sys/devices |
... | ... | @@ -610,7 +758,7 @@ |
610 | 758 | extern int (*platform_notify_remove)(struct device *dev); |
611 | 759 | |
612 | 760 | |
613 | -/** | |
761 | +/* | |
614 | 762 | * get_device - atomically increment the reference count for the device. |
615 | 763 | * |
616 | 764 | */ |
617 | 765 | |
... | ... | @@ -734,12 +882,16 @@ |
734 | 882 | #endif |
735 | 883 | |
736 | 884 | /* |
737 | - * dev_WARN() acts like dev_printk(), but with the key difference | |
885 | + * dev_WARN*() acts like dev_printk(), but with the key difference | |
738 | 886 | * of using a WARN/WARN_ON to get the message out, including the |
739 | 887 | * file/line information and a backtrace. |
740 | 888 | */ |
741 | 889 | #define dev_WARN(dev, format, arg...) \ |
742 | 890 | WARN(1, "Device: %s\n" format, dev_driver_string(dev), ## arg); |
891 | + | |
892 | +#define dev_WARN_ONCE(dev, condition, format, arg...) \ | |
893 | + WARN_ONCE(condition, "Device %s\n" format, \ | |
894 | + dev_driver_string(dev), ## arg) | |
743 | 895 | |
744 | 896 | /* Create alias, so I can be autoloaded. */ |
745 | 897 | #define MODULE_ALIAS_CHARDEV(major,minor) \ |
include/linux/sysfs.h
... | ... | @@ -176,7 +176,6 @@ |
176 | 176 | const unsigned char *name); |
177 | 177 | struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd); |
178 | 178 | void sysfs_put(struct sysfs_dirent *sd); |
179 | -void sysfs_printk_last_file(void); | |
180 | 179 | |
181 | 180 | /* Called to clear a ns tag when it is no longer valid */ |
182 | 181 | void sysfs_exit_ns(enum kobj_ns_type type, const void *tag); |
... | ... | @@ -346,10 +345,6 @@ |
346 | 345 | static inline int __must_check sysfs_init(void) |
347 | 346 | { |
348 | 347 | return 0; |
349 | -} | |
350 | - | |
351 | -static inline void sysfs_printk_last_file(void) | |
352 | -{ | |
353 | 348 | } |
354 | 349 | |
355 | 350 | #endif /* CONFIG_SYSFS */ |
include/linux/ti_wilink_st.h
... | ... | @@ -140,12 +140,12 @@ |
140 | 140 | */ |
141 | 141 | struct st_data_s { |
142 | 142 | unsigned long st_state; |
143 | - struct tty_struct *tty; | |
144 | 143 | struct sk_buff *tx_skb; |
145 | 144 | #define ST_TX_SENDING 1 |
146 | 145 | #define ST_TX_WAKEUP 2 |
147 | 146 | unsigned long tx_state; |
148 | 147 | struct st_proto_s *list[ST_MAX_CHANNELS]; |
148 | + bool is_registered[ST_MAX_CHANNELS]; | |
149 | 149 | unsigned long rx_state; |
150 | 150 | unsigned long rx_count; |
151 | 151 | struct sk_buff *rx_skb; |
... | ... | @@ -155,6 +155,7 @@ |
155 | 155 | unsigned char protos_registered; |
156 | 156 | unsigned long ll_state; |
157 | 157 | void *kim_data; |
158 | + struct tty_struct *tty; | |
158 | 159 | }; |
159 | 160 | |
160 | 161 | /* |
kernel/ksysfs.c
... | ... | @@ -16,6 +16,7 @@ |
16 | 16 | #include <linux/kexec.h> |
17 | 17 | #include <linux/profile.h> |
18 | 18 | #include <linux/sched.h> |
19 | +#include <linux/capability.h> | |
19 | 20 | |
20 | 21 | #define KERNEL_ATTR_RO(_name) \ |
21 | 22 | static struct kobj_attribute _name##_attr = __ATTR_RO(_name) |
... | ... | @@ -131,6 +132,14 @@ |
131 | 132 | |
132 | 133 | #endif /* CONFIG_KEXEC */ |
133 | 134 | |
135 | +/* whether file capabilities are enabled */ | |
136 | +static ssize_t fscaps_show(struct kobject *kobj, | |
137 | + struct kobj_attribute *attr, char *buf) | |
138 | +{ | |
139 | + return sprintf(buf, "%d\n", file_caps_enabled); | |
140 | +} | |
141 | +KERNEL_ATTR_RO(fscaps); | |
142 | + | |
134 | 143 | /* |
135 | 144 | * Make /sys/kernel/notes give the raw contents of our kernel .notes section. |
136 | 145 | */ |
... | ... | @@ -158,6 +167,7 @@ |
158 | 167 | EXPORT_SYMBOL_GPL(kernel_kobj); |
159 | 168 | |
160 | 169 | static struct attribute * kernel_attrs[] = { |
170 | + &fscaps_attr.attr, | |
161 | 171 | #if defined(CONFIG_HOTPLUG) |
162 | 172 | &uevent_seqnum_attr.attr, |
163 | 173 | &uevent_helper_attr.attr, |
kernel/sys.c
... | ... | @@ -314,6 +314,7 @@ |
314 | 314 | { |
315 | 315 | blocking_notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd); |
316 | 316 | system_state = SYSTEM_RESTART; |
317 | + usermodehelper_disable(); | |
317 | 318 | device_shutdown(); |
318 | 319 | syscore_shutdown(); |
319 | 320 | } |
... | ... | @@ -343,6 +344,7 @@ |
343 | 344 | blocking_notifier_call_chain(&reboot_notifier_list, |
344 | 345 | (state == SYSTEM_HALT)?SYS_HALT:SYS_POWER_OFF, NULL); |
345 | 346 | system_state = state; |
347 | + usermodehelper_disable(); | |
346 | 348 | device_shutdown(); |
347 | 349 | } |
348 | 350 | /** |