driver core patches for .39
Subsystems (14)
PATCH 1/1 driver core patches for .39
Here's the "big" driver core merge for the .39 tree.
Not much for the driver core itself, but there is some firmware driver work, and a new UIO driver as well. Also some Documentation updates and a new translation added.
Please pull from:
master.kernel.org:/pub/scm/linux/kernel/git/gregkh/driver-core-2.6.git/ driver-core-next
All of these patches have been in the linux-next and mm trees for a while now.
The patches will be sent as a follow-on to this message to lkml for people to see.
thanks,
greg k-h
------------
Documentation/ABI/stable/sysfs-firmware-efi-vars | 75 +++ Documentation/ABI/testing/sysfs-firmware-dmi | 110 ++++ Documentation/ABI/testing/sysfs-platform-kim | 48 ++ Documentation/dynamic-debug-howto.txt | 12 +- Documentation/filesystems/sysfs.txt | 16 +- Documentation/kref.txt | 2 +- Documentation/memory-hotplug.txt | 47 +- Documentation/zh_CN/SecurityBugs | 50 ++ Documentation/zh_CN/SubmitChecklist | 109 ++++ Documentation/zh_CN/SubmittingPatches | 4 +- Documentation/zh_CN/magic-number.txt | 167 ++++++ arch/powerpc/platforms/pseries/hotplug-memory.c | 66 ++- arch/x86/mm/init_64.c | 14 + drivers/base/core.c | 34 +- drivers/base/firmware_class.c | 7 +- drivers/base/memory.c | 197 +++++-- drivers/base/node.c | 12 +- drivers/base/sys.c | 65 ++- drivers/firmware/Kconfig | 11 + drivers/firmware/Makefile | 1 + drivers/firmware/dmi-sysfs.c | 696 ++++++++++++++++++++++ drivers/firmware/efivars.c | 343 +++++++----- drivers/misc/Kconfig | 7 +- drivers/misc/pch_phub.c | 69 ++- drivers/misc/ti-st/st_core.c | 419 +++++--------- drivers/misc/ti-st/st_kim.c | 491 ++++++++-------- drivers/misc/ti-st/st_ll.c | 10 +- drivers/uio/Kconfig | 17 + drivers/uio/Makefile | 1 + drivers/uio/uio_pruss.c | 247 ++++++++ fs/debugfs/inode.c | 26 +- include/linux/dmi.h | 47 ++ include/linux/dynamic_debug.h | 8 +- include/linux/efi.h | 37 ++ include/linux/firmware.h | 4 +- include/linux/kobject.h | 10 +- include/linux/memory.h | 3 +- include/linux/node.h | 6 +- include/linux/platform_data/uio_pruss.h | 25 + include/linux/platform_device.h | 11 +- include/linux/ti_wilink_st.h | 76 ++- init/Kconfig | 4 +- kernel/printk.c | 138 ++++- lib/dynamic_debug.c | 61 ++- 44 files changed, 2890 insertions(+), 913 deletions(-) create mode 100644 Documentation/ABI/stable/sysfs-firmware-efi-vars create mode 100644 Documentation/ABI/testing/sysfs-firmware-dmi create mode 100644 Documentation/ABI/testing/sysfs-platform-kim create mode 100644 Documentation/zh_CN/SecurityBugs create mode 100644 Documentation/zh_CN/SubmitChecklist create mode 100644 Documentation/zh_CN/magic-number.txt create mode 100644 drivers/firmware/dmi-sysfs.c create mode 100644 drivers/uio/uio_pruss.c create mode 100644 include/linux/platform_data/uio_pruss.h
---------------
Amerigo Wang (1):
debugfs: remove module_exit()
Bart Van Assche (4):
docs/sysfs: Update directory/kobject documentation. docs/sysfs: show() methods should use scnprintf().
kobject: Add missing format attribute specifications Dynamic debug: Add more flags
Bob Liu (1):
firmware_classs: change val uevent's type to bool
Borislav Petkov (2):
sysdev: Fixup warning message
sysdev: Do not register with sysdev when erroring on add
Ferenc Wagner (2):
driver core: Replace the dangerous to_root_device macro with an inline function
sysfs: Capitalize description of SYSFS_DEPRECATED{_V2} options
Greg Kroah-Hartman (1):
dynamic_debug: add #include <linux/sched.h>
Harry Wei (4):
Translate Documentation/SecurityBugs into Chinese
Fix a mistake Chinese character in Documentation/zh_CN/SubmittingPatches Translat Documentation/SubmittingChecklist into Chinese Translate linux-2.6/Documentation/magic-number.txt into Chinese
Jan Kara (1):
debugfs: Fix filesystem reference counting on debugfs_remove() failure
Javi Merino (1):
kref: Fix typo in kref documentation
Kay Sievers (1):
printk: do not mangle valid userspace syslog prefixes
Marc Kleine-Budde (1):
Driver core: convert platform_{get,set}_drvdata to static inline functions
Mike Waychison (13):
firmware: Add DMI entry types to the headers
firmware: Basic dmi-sysfs support
firmware: Break out system_event_log in dmi-sysfs
firmware: Expose DMI type 15 System Event Log
firmware: Add documentation for /sys/firmware/dmi
firmware: Fix unaligned memory accesses in dmi-sysfs
efivars: move efivars globals into struct efivars
efivars: Make efivars bin_attributes dynamic
efivars: parameterize efivars
efivars: Split out variable registration
efivars: Parameterize operations.
efivars: Expose efivars functionality to external drivers.
efivars: Add Documentation
Nathan Fontenot (5):
memory hotplug: Allow memory blocks to span multiple memory sections memory hotplug: Update phys_index to [start|end]_section_nr memory hotplug: Define memory_block_size_bytes for powerpc/pseries memory hotplug: Define memory_block_size_bytes for x86_64 with CONFIG_X86_UV memory hotplug: sysfs probe routine should add all memory sections
Pavan Savoy (8):
drivers:misc: ti-st: register with channel IDs drivers:misc: ti-st: move from rfkill to sysfs drivers:misc: ti-st: fix error codes drivers:misc: ti-st: set right debug levels for logs drivers:misc: ti-st: firmware download optimization drivers:misc: ti-st: fix hci-ll on wake_ind collision drivers:misc: ti-st: remove multiple gpio handling drivers:misc: ti-st: fix debugging code
Pratheesh Gangadhar (1):
UIO: add PRUSS UIO driver support
Randy Dunlap (1):
kobject.h: fix build when CONFIG_HOTPLUG is disabled
Timur Tabi (1):
driver-core: document restrictions on device_rename()
Tomoya MORINAGA (1):
pch_phub: add new device ML7213
Xiaochen Wang (1):
Fix spelling mistakes in Documentation/zh_CN/SubmittingPatches
PATCH 1/50 driver-core: document restrictions on device_rename()
From: Timur Tabi <[email protected]>
Add text, courtesy of Kay Sievers, that provides some background on device_rename() and why it shouldn't be used.
--- drivers/base/core.c | 29 ++++++++++++++++++++++++++++- 1 files changed, 28 insertions(+), 1 deletions(-)
drivers/base/core.c +28 -1
@@ -1551,7 +1551,34 @@ EXPORT_SYMBOL_GPL(device_destroy);* on the same device to ensure that new_name is valid and * won't conflict with other devices. * -* "Never use this function, bad things will happen" - gregkh +* Note: Don't call this function. Currently, the networking layer calls this +* function, but that will change. The following text from Kay Sievers offers +* some insight: +* +* Renaming devices is racy at many levels, symlinks and other stuff are not +* replaced atomically, and you get a "move" uevent, but it's not easy to +* connect the event to the old and new device. Device nodes are not renamed at +* all, there isn't even support for that in the kernel now. +* +* In the meantime, during renaming, your target name might be taken by another +* driver, creating conflicts. Or the old name is taken directly after you +* renamed it -- then you get events for the same DEVPATH, before you even see +* the "move" event. It's just a mess, and nothing new should ever rely on +* kernel device renaming. Besides that, it's not even implemented now for +* other things than (driver-core wise very simple) network devices. +* +* We are currently about to change network renaming in udev to completely +* disallow renaming of devices in the same namespace as the kernel uses, +* because we can't solve the problems properly, that arise with swapping names +* of multiple interfaces without races. Means, renaming of eth[0-9]* will only +* be allowed to some other name than eth[0-9]*, for the aforementioned +* reasons. +* +* Make up a "real" name in the driver before you register anything, or add +* some other attributes for userspace to find the device, or use udev to add +* symlinks -- but never rename kernel devices later, it's a complete mess. We +* don't even want to get into that and try to implement the missing pieces in +* the core. We really have other pieces to fix in the driver core mess. :) */ int device_rename (struct device *dev,const char *new_name) {
Signature · 1 line
1.7.4.1
PATCH 2/50 docs/sysfs: Update directory/kobject documentation.
From: Bart Van Assche <[email protected]>
Some time ago the way how sysfs stores a pointer to a kobject corresponding to a directory was modified. This patch brings the documentation again in sync with the implementation.
--- Documentation/filesystems/sysfs.txt | 10 ++++++---- 1 files changed, 6 insertions(+), 4 deletions(-)
Documentation/filesystems/sysfs.txt +6 -4
@@ -39,10 +39,12 @@ userspace. Top-level directories in sysfs represent the common ancestors of object hierarchies; i.e. the subsystems the objects belong to. -Sysfs internally stores the kobject that owns the directory in the -->d_fsdata pointer of the directory's dentry. This allows sysfs to do -reference counting directly on the kobject when the file is opened and -closed. +Sysfs internally stores a pointer to the kobject that implements a +directory in the sysfs_dirent object associated with the directory. In +the past this kobject pointer has been used by sysfs to do reference +counting directly on the kobject whenever the file is opened or closed. +With the current sysfs implementation the kobject reference count is +only modified directly by the function sysfs_schedule_callback(). Attributes
Signature · 1 line
1.7.4.1
PATCH 3/50 docs/sysfs: show() methods should use scnprintf().
In reply to Greg Kroah-HartmanFrom: Bart Van Assche <[email protected]>
Since snprintf() may return a value that exceeds its second argument, show() methods should use scnprintf() instead of snprintf(). This patch updates the example in the sysfs documentation accordingly.
--- Documentation/filesystems/sysfs.txt | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-)
Documentation/filesystems/sysfs.txt +3 -3
@@ -210,9 +210,9 @@ Other notes: is 4096. - show() methods should return the number of bytes printed into the - buffer. This is the return value of snprintf(). + buffer. This is the return value of scnprintf(). -- show() should always use snprintf(). +- show() should always use scnprintf(). - store() should return the number of bytes used from the buffer. If the entire buffer has been used, just return the count argument.
@@ -231,7 +231,7 @@ A very simple (and naive) implementation of a device attribute is: static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf) { - return snprintf(buf, PAGE_SIZE, "%s\n", dev->name); + return scnprintf(buf, PAGE_SIZE, "%s\n", dev->name); } static ssize_t store_name(struct device *dev, struct device_attribute *attr,
Signature · 1 line
1.7.4.1
PATCH 4/50 kobject: Add missing format attribute specifications
In reply to Greg Kroah-HartmanFrom: Bart Van Assche <[email protected]>
Several functions in <linux/kobject.h> accept printf-style arguments. Some of these functions have been annotated with a format attribute declaration while others have not been annotated. Add a format attribute specification where it is missing.
--- include/linux/kobject.h | 7 +++++-- 1 files changed, 5 insertions(+), 2 deletions(-)
include/linux/kobject.h +5 -2
@@ -85,11 +85,13 @@ static inline const char *kobject_name(const struct kobject *kobj)extern void kobject_init (struct kobject *kobj,struct kobj_type *ktype);extern int __must_check kobject_add (struct kobject *kobj,struct kobject *parent, -const char *fmt, ...); +const char *fmt, ...) + __attribute__((format (printf,3 ,4 )));extern int __must_check kobject_init_and_add (struct kobject *kobj,struct kobj_type *ktype,struct kobject *parent, -const char *fmt, ...); +const char *fmt, ...) + __attribute__((format (printf,4 ,5 )));extern void kobject_del (struct kobject *kobj);
@@ -226,6 +228,7 @@ static inline int kobject_uevent_env(struct kobject *kobj,static inline int add_uevent_var (struct kobj_uevent_env *env,const char *format, ...) + __attribute__((format (printf,2 ,3 ))) {return 0 ; } static inline int kobject_action_type(const char *buf, size_t count,
Signature · 1 line
1.7.4.1
PATCH 5/50 Dynamic debug: Add more flags
In reply to Greg Kroah-HartmanFrom: Bart Van Assche <[email protected]>
Add flags that allow the user to specify via debugfs whether or not the module name, function name, line number and/or thread ID have to be included in the printed message.
--- Documentation/dynamic-debug-howto.txt | 12 +++++- include/linux/dynamic_debug.h | 8 ++++- lib/dynamic_debug.c | 60 ++++++++++++++++++++++++++++----- 3 files changed, 68 insertions(+), 12 deletions(-)
Documentation/dynamic-debug-howto.txt +10 -2
@@ -205,12 +205,20 @@ of the characters: The flags are: +f + Include the function name in the printed message +l + Include line number in the printed message +m + Include module name in the printed message p Causes a printk() message to be emitted to dmesg +t + Include thread ID in messages not generated from interrupt context -Note the regexp ^[-+=][scp]+$ matches a flags specification. +Note the regexp ^[-+=][flmpt]+$ matches a flags specification. Note also that there is no convenient syntax to remove all -the flags at once, you need to use "-psc". +the flags at once, you need to use "-flmpt". Debug messages during boot process
include/linux/dynamic_debug.h +7 -1
@@ -31,6 +31,10 @@ struct _ddebug {* writes commands to <debugfs>/dynamic_debug/control */ #define _DPRINTK_FLAGS_PRINT (1<<0)/* printk() a message using the format */ +#define _DPRINTK_FLAGS_INCL_MODNAME (1<<1) +#define _DPRINTK_FLAGS_INCL_FUNCNAME (1<<2) +#define _DPRINTK_FLAGS_INCL_LINENO (1<<3) +#define _DPRINTK_FLAGS_INCL_TID (1<<4)#define _DPRINTK_FLAGS_DEFAULT 0 unsigned int flags:8;char enabled;
@@ -42,6 +46,8 @@ int ddebug_add_module(struct _ddebug *tab, unsigned int n,#if defined(CONFIG_DYNAMIC_DEBUG )extern int ddebug_remove_module (const char *mod_name); +extern int __dynamic_pr_debug (struct _ddebug *descriptor,const char *fmt, ...) + __attribute__ ((format (printf,2 ,3 )));#define dynamic_pr_debug (fmt, ...) do { \ static struct _ddebug descriptor \
@@ -50,7 +56,7 @@ extern int ddebug_remove_module(const char *mod_name); {KBUILD_MODNAME , __func__, __FILE__, fmt, __LINE__, \ _DPRINTK_FLAGS_DEFAULT }; \if (unlikely (descriptor.enabled)) \ - printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); \ + __dynamic_pr_debug(&descriptor, pr_fmt(fmt), ##__VA_ARGS__); \ }while (0 )
lib/dynamic_debug.c +51 -9
104 lines not on this page · raw message
Signature · 1 line
1.7.4.1
Re: [PATCH 05/50] Dynamic debug: Add more flags
Quoted 66 lines · Greg Kroah-Hartman
Add flags that allow the user to specify via debugfs whether or not the module name, function name, line number and/or thread ID have to be included in the printed message.
Signed-off-by Bart Van Assche <[email protected]>Cc Greg Banks <[email protected]>Cc Konrad Rzeszutek Wilk <[email protected]>Signed-off-by Greg Kroah-Hartman <[email protected]>--- Documentation/dynamic-debug-howto.txt | 12 +++++- include/linux/dynamic_debug.h | 8 ++++- lib/dynamic_debug.c | 60 ++++++++++++++++++++++++++++----- 3 files changed, 68 insertions(+), 12 deletions(-)Documentation/dynamic-debug-howto.txt +10
-2@@ -205,12 +205,20 @@ of the characters: The flags are: +f + Include the function name in the printed message +l + Include line number in the printed message +m + Include module name in the printed message p Causes a printk() message to be emitted to dmesg +t + Include thread ID in messages not generated from interrupt context -Note the regexp ^[-+=][scp]+$ matches a flags specification. +Note the regexp ^[-+=][flmpt]+$ matches a flags specification. Note also that there is no convenient syntax to remove all -the flags at once, you need to use "-psc". +the flags at once, you need to use "-flmpt". Debug messages during boot processinclude/linux/dynamic_debug.h +6
-0@@ -31,6 +31,10 @@ struct _ddebug {* writes commands to <debugfs>/dynamic_debug/control */ #define _DPRINTK_FLAGS_PRINT (1<<0)/* printk() a message using the format */ +#define _DPRINTK_FLAGS_INCL_MODNAME (1<<1) +#define _DPRINTK_FLAGS_INCL_FUNCNAME (1<<2) +#define _DPRINTK_FLAGS_INCL_LINENO (1<<3) +#define _DPRINTK_FLAGS_INCL_TID (1<<4)#define _DPRINTK_FLAGS_DEFAULT 0 unsigned int flags:8;char enabled;@@ -42,6 +46,8 @@ int ddebug_add_module(struct _ddebug *tab, unsigned int n,#if defined(CONFIG_DYNAMIC_DEBUG )extern int ddebug_remove_module (const char *mod_name); +extern int __dynamic_pr_debug (struct _ddebug *descriptor,const char *fmt, ...) + __attribute__ ((format (printf,2 ,3 )));#define dynamic_pr_debug (fmt, ...) do { \ static struct _ddebug descriptor \
include/linux/dynamic_debug.h extern int ddebug_remove_module(const char *mod_name); · line 61
Quoted 7 lines
include/linux/dynamic_debug.h +1
-1@@ -50,7 +56,7 @@ extern int ddebug_remove_module(const char *mod_name); {KBUILD_MODNAME , __func__, __FILE__, fmt, __LINE__, \ _DPRINTK_FLAGS_DEFAULT }; \if (unlikely (descriptor.enabled)) \ - printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); \ + __dynamic_pr_debug(&descriptor, pr_fmt(fmt), ##__VA_ARGS__); \ }while (0 )
This piece is going to conflict with the jump label update patches, I'm trying to get into .39. The 'if (unlikely(descriptor.enabled))' bit is
now: 'if (DDEBUG_BRANCH(descriptor.enabled))'. So its a small conflict, but they wouldn't merge together. So we need to adjust either one (and make sure they're applied in the correct orer), or drop one.
thanks,
-Jason
Re: [PATCH 05/50] Dynamic debug: Add more flags
Quoted 10 lines · Jason Baron
Quoted 3 lines · Greg Kroah-Hartman
Add flags that allow the user to specify via debugfs whether or not the module name, function name, line number and/or thread ID have to be included in the printed message.
This piece is going to conflict with the jump label update patches, I'm trying to get into .39. The 'if (unlikely(descriptor.enabled))' bit is
now: 'if (DDEBUG_BRANCH(descriptor.enabled))'. So its a small conflict, but they wouldn't merge together. So we need to adjust either one (and make sure they're applied in the correct orer), or drop one.
This has been in linux-next for months now, where were the jump label patches tested that missed this? Why wasn't your patches in linux-next before the merge window opened? That's a requirement for .39 stuff, right?
Also, this is already in Linus's tree so you will have to handle the merge issue on your side now.
thanks,
greg k-h
Re: [PATCH 05/50] Dynamic debug: Add more flags
Quoted 6 lines · Greg KH
Quoted 5 lines · Jason Baron
Quoted 3 lines · Greg Kroah-Hartman
Add flags that allow the user to specify via debugfs whether or not the module name, function name, line number and/or thread ID have to be included in the printed message.
Quoted 7 lines
Quoted 5 lines
This piece is going to conflict with the jump label update patches, I'm trying to get into .39. The 'if (unlikely(descriptor.enabled))' bit is
now: 'if (DDEBUG_BRANCH(descriptor.enabled))'. So its a small conflict, but they wouldn't merge together. So we need to adjust either one (and make sure they're applied in the correct orer), or drop one.This has been in linux-next for months now, [...]
Btw, a workflow observation, i'd have expected such a commit:
Quoted 9 lines
Signed-off-by Bart Van Assche <[email protected]>Cc Greg Banks <[email protected]>Cc Konrad Rzeszutek Wilk <[email protected]>Signed-off-by Greg Kroah-Hartman <[email protected]>--- Documentation/dynamic-debug-howto.txt | 12 +++++- include/linux/dynamic_debug.h | 8 ++++- lib/dynamic_debug.c | 60 ++++++++++++++++++++++++++++----- 3 files changed, 68 insertions(+), 12 deletions(-)
... to at least have the ack from Jason who is the author and maintainer of the dyn-printk bits. You should at least have Cc:-ed him!
Preferably it should have been merged through him. That would also have alerted him to the conflict potential and would have concentrated all changes in a single tree, as it really should happen ...
So could you *please* do such changes in a bit more organized fashion in the future? Please use the get_maintainer script:
$ scripts/get_maintainer.pl -f lib/dynamic_debug.c
Jason Baron <[email protected]> (commit_signer:6/10=60%) Thomas Renninger <[email protected]> (commit_signer:3/10=30%) Pekka Enberg <[email protected]> (commit_signer:3/10=30%) Greg Kroah-Hartman <[email protected]> (commit_signer:3/10=30%) Steven Rostedt <[email protected]> (commit_signer:2/10=20%) [email protected] (open list)
The majority of those gents were not Cc:-ed to any of the submissions and resubmissions.
To answer your question, the in-flight changes Jason is talking about have not touched linux-next yet because they went through several levels of review feedback. Had your patches gone through a similar review process they might still be in flight as well and we'd also have found out about any conflicts sooner.
Thanks,
Ingo
Re: [PATCH 05/50] Dynamic debug: Add more flags
Quoted 16 lines · Ingo Molnar
Preferably it should have been merged through him. That would also have alerted him to the conflict potential and would have concentrated all changes in a single tree, as it really should happen ...
So could you *please* do such changes in a bit more organized fashion in the future? Please use the
get_maintainerscript:$ scripts/get_maintainer.pl -f lib/dynamic_debug.cJason Baron <[email protected]> (commit_signer:6/10=60%) Thomas Renninger <[email protected]> (commit_signer:3/10=30%) Pekka Enberg <[email protected]> (commit_signer:3/10=30%) Greg Kroah-Hartman <[email protected]> (commit_signer:3/10=30%) Steven Rostedt <[email protected]> (commit_signer:2/10=20%) [email protected] (open list)
Quoted 2 lines
The majority of those gents were not Cc:-ed to any of the submissions and resubmissions.
This patch was posted for the first time a few months ago. The get_maintainer.pl script back then listed the names of Greg Banks and Konrad Rzeszutek Wilk as the first two. If the get_maintainer.pl script output had been as informative back then as it is now, the right people would have been CC-ed.
Bart.
PATCH 6/50 firmware_classs: change val uevent's type to bool
In reply to Greg Kroah-HartmanFrom: Bob Liu <[email protected]>
Some place in firmware_class.c using "int uevent" define, but others use "bool uevent".
This patch replace all int uevent define to bool.
--- drivers/base/firmware_class.c | 7 +++---- include/linux/firmware.h | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-)
drivers/base/firmware_class.c +3 -4
@@ -593,8 +593,7 @@ int request_firmware(const struct firmware **firmware_p, const char *name, struct device *device) { - int uevent = 1; -return _request_firmware (firmware_p, name, device, uevent, false); + return _request_firmware(firmware_p, name, device, true, false); }/**
@@ -618,7 +617,7 @@ struct firmware_work {struct device *device;void *context;void (*cont)(const struct firmware *fw,void *context); -int uevent; +bool uevent; };static int request_firmware_work_func (void *arg)
@@ -661,7 +660,7 @@ static int request_firmware_work_func(void *arg)**/ int request_firmware_nowait ( -struct module *module,int uevent, +struct module *module,bool uevent,const char *name,struct device *device,gfp_t gfp,void *context,void (*cont)(const struct firmware *fw,void *context)) {
include/linux/firmware.h +2 -2
@@ -39,7 +39,7 @@ struct builtin_fw {int request_firmware (const struct firmware **fw,const char *name,struct device *device);int request_firmware_nowait ( -struct module *module,int uevent, +struct module *module,bool uevent,const char *name,struct device *device,gfp_t gfp,void *context,void (*cont)(const struct firmware *fw,void *context));
@@ -52,7 +52,7 @@ static inline int request_firmware(const struct firmware **fw,return -EINVAL ; }static inline int request_firmware_nowait ( -struct module *module,int uevent, +struct module *module,bool uevent,const char *name,struct device *device,gfp_t gfp,void *context,void (*cont)(const struct firmware *fw,void *context)) {
Signature · 1 line
1.7.4.1
PATCH 7/50 sysdev: Fixup warning message
In reply to Greg Kroah-HartmanFrom: Borislav Petkov <[email protected]>
Use gcc's __func__ instead of the function name.
--- drivers/base/sys.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
drivers/base/sys.c +2 -2
@@ -181,8 +181,8 @@ int sysdev_driver_register(struct sysdev_class *cls, struct sysdev_driver *drv)int err =0 ;if (!cls) { -WARN (1 ,KERN_WARNING "sysdev: invalid class passed to " -"sysdev_driver_register!\n" ); +WARN (1 ,KERN_WARNING "sysdev: invalid class passed to %s!\n" , + __func__);return -EINVAL ; }
Signature · 1 line
1.7.4.1
PATCH 8/50 debugfs: remove module_exit()
In reply to Greg Kroah-HartmanFrom: Amerigo Wang <[email protected]>
debugfs can't be a module, so module_exit() is meaningless for it.
--- fs/debugfs/inode.c | 15 --------------- 1 files changed, 0 insertions(+), 15 deletions(-)
fs/debugfs/inode.c +0 -15
@@ -13,9 +13,6 @@* */ -/* uncomment to get debug messages from the debug filesystem, ah the irony. */ -/* #define DEBUG */ -#include <linux/module.h> #include <linux/fs.h> #include <linux/mount.h>
@@ -540,17 +537,5 @@ static int __init debugfs_init(void)return retval; } - -static void __exit debugfs_exit(void) -{ - debugfs_registered = false; - -simple_release_fs (&debugfs_mount, &debugfs_mount_count); -unregister_filesystem (&debug_fs_type); -kobject_put (debug_kobj); -} -core_initcall (debugfs_init); -module_exit (debugfs_exit); -MODULE_LICENSE ("GPL" );
Signature · 1 line
1.7.4.1
PATCH 9/50 sysdev: Do not register with sysdev when erroring on add
In reply to Greg Kroah-HartmanFrom: Borislav Petkov <[email protected]>
When encountering an error while executing the driver's ->add method, we should cancel registration and unwind what we've regged so far. The low level ->add methods do return proper error codes but those aren't looked at in sysdev_driver_register(). Fix that by sharing the unregistering code.
--- drivers/base/sys.c | 61 +++++++++++++++++++++++++++++++++++++-------------- 1 files changed, 44 insertions(+), 17 deletions(-)
drivers/base/sys.c +44 -17
@@ -166,6 +166,36 @@ EXPORT_SYMBOL_GPL(sysdev_class_unregister);static DEFINE_MUTEX (sysdev_drivers_lock); +/* +* @dev != NULL means that we're unwinding because some drv->add() +* failed for some reason. You need to grab sysdev_drivers_lock before +* calling this. +*/ +static void __sysdev_driver_remove (struct sysdev_class *cls, +struct sysdev_driver *drv, +struct sys_device *from_dev) +{ +struct sys_device *dev = from_dev; + +list_del_init (&drv->entry); +if (!cls) +return ; + +if (!drv->remove) + goto kset_put; + +if (dev) +list_for_each_entry_continue_reverse (dev, &cls->kset.list, + kobj.entry) + drv->remove (dev); +else +list_for_each_entry (dev, &cls->kset.list, kobj.entry) + drv->remove (dev); + +kset_put: +kset_put (&cls->kset); +} +/** * sysdev_driver_register - Register auxillary driver * @cls: Device class driver belongs to.
@@ -175,9 +205,9 @@ static DEFINE_MUTEX(sysdev_drivers_lock);* called on each operation on devices of that class. The refcount * of @cls is incremented. */ -int sysdev_driver_register (struct sysdev_class *cls,struct sysdev_driver *drv) { +struct sys_device *dev =NULL ;int err =0 ;if (!cls) {
@@ -198,19 +228,27 @@ int sysdev_driver_register(struct sysdev_class *cls, struct sysdev_driver *drv)/* If devices of this class already exist, tell the driver */ if (drv->add) { -struct sys_device *dev; -list_for_each_entry (dev, &cls->kset.list, kobj.entry) - drv->add (dev); +list_for_each_entry (dev, &cls->kset.list, kobj.entry) { + err = drv->add (dev); +if (err) + goto unwind; + } } }else { err = -EINVAL ;WARN (1 ,KERN_ERR "%s: invalid device class\n" , __func__); } + + goto unlock; + +unwind: +__sysdev_driver_remove (cls, drv, dev); + +unlock:mutex_unlock (&sysdev_drivers_lock);return err; } -/** * sysdev_driver_unregister - Remove an auxillary driver. * @cls: Class driver belongs to.
@@ -220,23 +258,12 @@ void sysdev_driver_unregister(struct sysdev_class *cls, struct sysdev_driver *drv) {mutex_lock (&sysdev_drivers_lock); -list_del_init (&drv->entry); -if (cls) { -if (drv->remove) { -struct sys_device *dev; -list_for_each_entry (dev, &cls->kset.list, kobj.entry) - drv->remove (dev); - } -kset_put (&cls->kset); - } +__sysdev_driver_remove (cls, drv,NULL );mutex_unlock (&sysdev_drivers_lock); } -EXPORT_SYMBOL_GPL (sysdev_driver_register);EXPORT_SYMBOL_GPL (sysdev_driver_unregister); - -/** * sysdev_register - add a system device to the tree * @sysdev: device in question
Signature · 1 line
1.7.4.1
PATCH 10/50 Translate Documentation/SecurityBugs into Chinese
In reply to Greg Kroah-HartmanFrom: Harry Wei <[email protected]>
--- Documentation/zh_CN/SecurityBugs | 50 ++++++++++++++++++++++++++++++++++++++ 1 files changed, 50 insertions(+), 0 deletions(-) create mode 100644 Documentation/zh_CN/SecurityBugs
Documentation/zh_CN/SecurityBugs new file +50 -0
@@ -0,0 +1,50 @@ +Chinese translated version of Documentation/SecurityBugs + +If you have any comment or update to the content, please contact the +original document maintainer directly. However, if you have a problem +communicating in English you can also ask the Chinese maintainer for +help. Contact the Chinese maintainer if this translation is outdated +or if there is a problem with the translation. + +Chinese maintainer: Harry Wei <[email protected]> +--------------------------------------------------------------------- +Documentation/SecurityBugs 的中文翻译 + +如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文 +交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻 +译存在问题,请联系中文版维护者。 + +中文版维护者: 贾威威 Harry Wei <[email protected]> +中文版翻译者: 贾威威 Harry Wei <[email protected]> +中文版校译者: 贾威威 Harry Wei <[email protected]> + + +以下为正文 +--------------------------------------------------------------------- +Linux内核开发者认为安全非常重要。因此,我们想要知道当一个有关于 +安全的漏洞被发现的时候,并且它可能会被尽快的修复或者公开。请把这个安全 +漏洞报告给Linux内核安全团队。 + +1) 联系 + +linux内核安全团队可以通过email<[email protected]>来联系。这是 +一组独立的安全工作人员,可以帮助改善漏洞报告并且公布和取消一个修复。安 +全团队有可能会从部分的维护者那里引进额外的帮助来了解并且修复安全漏洞。 +当遇到任何漏洞,所能提供的信息越多就越能诊断和修复。如果你不清楚什么 +是有帮助的信息,那就请重温一下REPORTING-BUGS文件中的概述过程。任 +何攻击性的代码都是非常有用的,未经报告者的同意不会被取消,除非它已经 +被公布于众。 + +2) 公开 + +Linux内核安全团队的宗旨就是和漏洞提交者一起处理漏洞的解决方案直 +到公开。我们喜欢尽快地完全公开漏洞。当一个漏洞或者修复还没有被完全地理 +解,解决方案没有通过测试或者供应商协调,可以合理地延迟公开。然而,我们 +期望这些延迟尽可能的短些,是可数的几天,而不是几个星期或者几个月。公开 +日期是通过安全团队和漏洞提供者以及供应商洽谈后的结果。公开时间表是从很 +短(特殊的,它已经被公众所知道)到几个星期。作为一个基本的默认政策,我 +们所期望通知公众的日期是7天的安排。 + +3) 保密协议 + +Linux内核安全团队不是一个正式的团体,因此不能加入任何的保密协议。
Signature · 1 line
1.7.4.1
PATCH 11/50 pch_phub: add new device ML7213
In reply to Greg Kroah-HartmanFrom: Tomoya MORINAGA <[email protected]>
Add ML7213 device information.
ML7213 is companion chip of Intel Atom E6xx series for IVI(In-Vehicle Infotainment). ML7213 is completely compatible for Intel EG20T PCH.
--- drivers/misc/Kconfig | 7 ++++- drivers/misc/pch_phub.c | 69 ++++++++++++++++++++++++++++++++--------------- 2 files changed, 53 insertions(+), 23 deletions(-)
drivers/misc/Kconfig +6 -1
@@ -441,7 +441,7 @@ config BMP085 module will be called bmp085. config PCH_PHUB - tristate "PCH Packet Hub of Intel Topcliff" + tristate "PCH Packet Hub of Intel Topcliff / OKI SEMICONDUCTOR ML7213" depends on PCI help This driver is for PCH(Platform controller Hub) PHUB(Packet Hub) of
@@ -449,6 +449,11 @@ config PCH_PHUB processor. The Topcliff has MAC address and Option ROM data in SROM. This driver can access MAC address and Option ROM data in SROM. + This driver also can be used for OKI SEMICONDUCTOR's ML7213 which is + for IVI(In-Vehicle Infotainment) use. + ML7213 is companion chip for Intel Atom E6xx series. + ML7213 is completely compatible for Intel EG20T PCH. + To compile this driver as a module, choose M here: the module will be called pch_phub.
drivers/misc/pch_phub.c +47 -22
110 lines not on this page · raw message
Signature · 1 line
1.7.4.1
PATCH 12/50 dynamic_debug: add #include <linux/sched.h>
In reply to Greg Kroah-HartmanThis fixes a build breakage caused by 8ba6ebf583f12da32036fc0f003ab4043e54692e "Dynamic debug: Add more flags"
--- lib/dynamic_debug.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
lib/dynamic_debug.c +1 -0
@@ -29,6 +29,7 @@#include <linux/slab.h> #include <linux/jump_label.h> #include <linux/hardirq.h> +#include <linux/sched.h> extern struct _ddebug __start___verbose[];extern struct _ddebug __stop___verbose[];
Signature · 1 line
1.7.4.1
PATCH 13/50 memory hotplug: Allow memory blocks to span multiple memory sections
In reply to Greg Kroah-HartmanFrom: Nathan Fontenot <[email protected]>
Update the memory sysfs code such that each sysfs memory directory is now considered a memory block that can span multiple memory sections per memory block. The default size of each memory block is SECTION_SIZE_BITS to maintain the current behavior of having a single memory section per memory block (i.e. one sysfs directory per memory section).
For architectures that want to have memory blocks span multiple memory sections they need only define their own memory_block_size_bytes() routine.
Update the memory hotplug documentation to reflect the new behaviors of memory blocks reflected in sysfs.
--- Documentation/memory-hotplug.txt | 47 ++++++++---- drivers/base/memory.c | 155 ++++++++++++++++++++++++++------------ 2 files changed, 139 insertions(+), 63 deletions(-)
Documentation/memory-hotplug.txt +31 -16
@@ -126,36 +126,51 @@ config options. -------------------------------- 4 sysfs files for memory hotplug -------------------------------- -All sections have their device information under /sys/devices/system/memory as +All sections have their device information in sysfs. Each section is part of +a memory block under /sys/devices/system/memory as /sys/devices/system/memory/memoryXXX -(XXX is section id.) +(XXX is the section id.) -Now, XXX is defined as start_address_of_section / section_size. +Now, XXX is defined as (start_address_of_section / section_size) of the first +section contained in the memory block. The files 'phys_index' and +'end_phys_index' under each directory report the beginning and end section id's +for the memory block covered by the sysfs directory. It is expected that all +memory sections in this range are present and no memory holes exist in the +range. Currently there is no way to determine if there is a memory hole, but +the existence of one should not affect the hotplug capabilities of the memory +block. For example, assume 1GiB section size. A device for a memory starting at 0x100000000 is /sys/device/system/memory/memory4 (0x100000000 / 1Gib = 4) This device covers address range [0x100000000 ... 0x140000000) -Under each section, you can see 4 files. +Under each section, you can see 4 or 5 files, the end_phys_index file being +a recent addition and not present on older kernels. -/sys/devices/system/memory/memoryXXX/phys_index +/sys/devices/system/memory/memoryXXX/start_phys_index +/sys/devices/system/memory/memoryXXX/end_phys_index /sys/devices/system/memory/memoryXXX/phys_device /sys/devices/system/memory/memoryXXX/state /sys/devices/system/memory/memoryXXX/removable -'phys_index' : read-only and contains section id, same as XXX. -'state' : read-write - at read: contains online/offline state of memory. - at write: user can specify "online", "offline" command -'phys_device': read-only: designed to show the name of physical memory device. - This is not well implemented now. -'removable' : read-only: contains an integer value indicating - whether the memory section is removable or not - removable. A value of 1 indicates that the memory - section is removable and a value of 0 indicates that - it is not removable. +'phys_index' : read-only and contains section id of the first section + in the memory block, same as XXX. +'end_phys_index' : read-only and contains section id of the last section + in the memory block. +'state' : read-write + at read: contains online/offline state of memory. + at write: user can specify "online", "offline" command + which will be performed on al sections in the block. +'phys_device' : read-only: designed to show the name of physical memory + device. This is not well implemented now. +'removable' : read-only: contains an integer value indicating + whether the memory block is removable or not + removable. A value of 1 indicates that the memory + block is removable and a value of 0 indicates that + it is not removable. A memory block is removable only if + every section in the block is removable. NOTE: These directories/files appear after physical memory hotplug phase.
drivers/base/memory.c +108 -47
329 lines not on this page · raw message
Signature · 1 line
1.7.4.1
PATCH 14/50 memory hotplug: Update phys_index to [start|end]_section_nr
In reply to Greg Kroah-HartmanFrom: Nathan Fontenot <[email protected]>
Update the 'phys_index' property of a the memory_block struct to be called start_section_nr, and add a end_section_nr property. The data tracked here is the same but the updated naming is more in line with what is stored here, namely the first and last section number that the memory block spans.
The names presented to userspace remain the same, phys_index for start_section_nr and end_phys_index for end_section_nr, to avoid breaking anything in userspace.
This also updates the node sysfs code to be aware of the new capability for a memory block to contain multiple memory sections and be aware of the memory block structure name changes (start_section_nr). This requires an additional parameter to unregister_mem_sect_under_nodes so that we know which memory section of the memory block to unregister.
--- drivers/base/memory.c | 41 +++++++++++++++++++++++++++++++---------- drivers/base/node.c | 12 ++++++++---- include/linux/memory.h | 3 ++- include/linux/node.h | 6 ++++-- 4 files changed, 45 insertions(+), 17 deletions(-)
drivers/base/memory.c +31 -10
@@ -97,7 +97,7 @@ int register_memory(struct memory_block *memory)int error; memory->sysdev.cls = &memory_sysdev_class; - memory->sysdev.id = memory->phys_index / sections_per_block; + memory->sysdev.id = memory->start_section_nr / sections_per_block; error =sysdev_register (&memory->sysdev);return error;
@@ -138,12 +138,26 @@ static unsigned long get_memory_block_size(void)* uses. */ -static ssize_t show_mem_phys_index (struct sys_device *dev, +static ssize_t show_mem_start_phys_index (struct sys_device *dev,struct sysdev_attribute *attr,char *buf) {struct memory_block *mem = container_of(dev, struct memory_block, sysdev); -return sprintf (buf,"%08lx\n" , mem->phys_index / sections_per_block); +unsigned long phys_index; + + phys_index = mem->start_section_nr / sections_per_block; +return sprintf (buf,"%08lx\n" , phys_index); +} + +static ssize_t show_mem_end_phys_index (struct sys_device *dev, +struct sysdev_attribute *attr,char *buf) +{ +struct memory_block *mem = + container_of(dev, struct memory_block, sysdev); +unsigned long phys_index; + + phys_index = mem->end_section_nr / sections_per_block; +return sprintf (buf,"%08lx\n" , phys_index); }/*
@@ -158,7 +172,7 @@ static ssize_t show_mem_removable(struct sys_device *dev, container_of(dev, struct memory_block, sysdev);for (i =0 ; i < sections_per_block; i++) { - pfn =section_nr_to_pfn (mem->phys_index + i); + pfn =section_nr_to_pfn (mem->start_section_nr + i); ret &=is_mem_section_removable (pfn,PAGES_PER_SECTION ); }
@@ -275,14 +289,15 @@ static int memory_block_change_state(struct memory_block *mem, mem->state =MEM_GOING_OFFLINE ;for (i =0 ; i < sections_per_block; i++) { - ret =memory_section_action (mem->phys_index + i, to_state); + ret =memory_section_action (mem->start_section_nr + i, + to_state);if (ret)break ; }if (ret) {for (i =0 ; i < sections_per_block; i++) -memory_section_action (mem->phys_index + i, +memory_section_action (mem->start_section_nr + i, from_state_req); mem->state = from_state_req;
@@ -330,7 +345,8 @@ static ssize_t show_phys_device(struct sys_device *dev,return sprintf (buf,"%d\n" , mem->phys_device); } -static SYSDEV_ATTR(phys_index, 0444, show_mem_phys_index, NULL); +static SYSDEV_ATTR(phys_index, 0444, show_mem_start_phys_index, NULL); +static SYSDEV_ATTR(end_phys_index, 0444, show_mem_end_phys_index, NULL); static SYSDEV_ATTR(state, 0644, show_mem_state, store_mem_state); static SYSDEV_ATTR(phys_device, 0444, show_phys_device, NULL); static SYSDEV_ATTR(removable, 0444, show_mem_removable, NULL);
@@ -522,17 +538,21 @@ static int init_memory_block(struct memory_block **memory,return -ENOMEM ; scn_nr =__section_nr (section); - mem->phys_index =base_memory_block_id (scn_nr) * sections_per_block; + mem->start_section_nr = +base_memory_block_id (scn_nr) * sections_per_block; + mem->end_section_nr = mem->start_section_nr + sections_per_block -1 ; mem->state = state; mem->section_count++;mutex_init (&mem->state_mutex); - start_pfn =section_nr_to_pfn (mem->phys_index); + start_pfn =section_nr_to_pfn (mem->start_section_nr); mem->phys_device =arch_get_memory_phys_device (start_pfn); ret =register_memory (mem);if (!ret) ret =mem_create_simple_file (mem, phys_index);if (!ret) + ret =mem_create_simple_file (mem, end_phys_index); +if (!ret) ret =mem_create_simple_file (mem, state);if (!ret) ret =mem_create_simple_file (mem, phys_device);
@@ -575,11 +595,12 @@ int remove_memory_block(unsigned long node_id, struct mem_section *section,mutex_lock (&mem_sysfs_mutex); mem =find_memory_block (section); +unregister_mem_sect_under_nodes (mem,__section_nr (section)); mem->section_count--;if (mem->section_count ==0 ) { -unregister_mem_sect_under_nodes (mem);mem_remove_simple_file (mem, phys_index); +mem_remove_simple_file (mem, end_phys_index);mem_remove_simple_file (mem, state);mem_remove_simple_file (mem, phys_device);mem_remove_simple_file (mem, removable);
drivers/base/node.c +8 -4
@@ -375,8 +375,10 @@ int register_mem_sect_under_node(struct memory_block *mem_blk, int nid)return -EFAULT ;if (!node_online (nid))return 0 ; - sect_start_pfn =section_nr_to_pfn (mem_blk->phys_index); - sect_end_pfn = sect_start_pfn +PAGES_PER_SECTION -1 ; + + sect_start_pfn =section_nr_to_pfn (mem_blk->start_section_nr); + sect_end_pfn =section_nr_to_pfn (mem_blk->end_section_nr); + sect_end_pfn +=PAGES_PER_SECTION -1 ;for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) {int page_nid;
@@ -400,7 +402,8 @@ int register_mem_sect_under_node(struct memory_block *mem_blk, int nid) }/* unregister memory section under all nodes that it spans */ -int unregister_mem_sect_under_nodes (struct memory_block *mem_blk) +int unregister_mem_sect_under_nodes (struct memory_block *mem_blk, +unsigned long phys_index) {NODEMASK_ALLOC (nodemask_t, unlinked_nodes,GFP_KERNEL );unsigned long pfn, sect_start_pfn, sect_end_pfn;
@@ -412,7 +415,8 @@ int unregister_mem_sect_under_nodes(struct memory_block *mem_blk)if (!unlinked_nodes)return -ENOMEM ;nodes_clear (*unlinked_nodes); - sect_start_pfn =section_nr_to_pfn (mem_blk->phys_index); + + sect_start_pfn =section_nr_to_pfn (phys_index); sect_end_pfn = sect_start_pfn +PAGES_PER_SECTION -1 ;for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) {int nid;
include/linux/memory.h +2 -1
@@ -21,7 +21,8 @@#include <linux/mutex.h> struct memory_block { -unsigned long phys_index; +unsigned long start_section_nr; +unsigned long end_section_nr;unsigned long state;int section_count;
include/linux/node.h +4 -2
@@ -39,7 +39,8 @@ extern int register_cpu_under_node(unsigned int cpu, unsigned int nid);extern int unregister_cpu_under_node (unsigned int cpu,unsigned int nid);extern int register_mem_sect_under_node (struct memory_block *mem_blk,int nid); -extern int unregister_mem_sect_under_nodes (struct memory_block *mem_blk); +extern int unregister_mem_sect_under_nodes (struct memory_block *mem_blk, +unsigned long phys_index);#ifdef CONFIG_HUGETLBFS extern void register_hugetlbfs_with_node(node_registration_func_t doregister,
@@ -67,7 +68,8 @@ static inline int register_mem_sect_under_node(struct memory_block *mem_blk, {return 0 ; } -static inline int unregister_mem_sect_under_nodes (struct memory_block *mem_blk) +static inline int unregister_mem_sect_under_nodes (struct memory_block *mem_blk, +unsigned long phys_index) {return 0 ; }
Signature · 1 line
1.7.4.1
PATCH 15/50 memory hotplug: Define memory_block_size_bytes for powerpc/pseries
In reply to Greg Kroah-HartmanFrom: Nathan Fontenot <[email protected]>
Define a version of memory_block_size_bytes() for powerpc/pseries such that a memory block spans an entire lmb.
--- arch/powerpc/platforms/pseries/hotplug-memory.c | 66 ++++++++++++++++++----- 1 files changed, 53 insertions(+), 13 deletions(-)
arch/powerpc/platforms/pseries/hotplug-memory.c +53 -13
@@ -17,6 +17,54 @@#include <asm/pSeries_reconfig.h> #include <asm/sparsemem.h> +static unsigned long get_memblock_size (void ) +{ +struct device_node *np; +unsigned int memblock_size =0 ; + + np =of_find_node_by_path ("/ibm,dynamic-reconfiguration-memory" ); +if (np) { +const unsigned long *size; + + size =of_get_property (np,"ibm,lmb-size" ,NULL ); + memblock_size = size ? *size :0 ; + +of_node_put (np); + }else { +unsigned int memzero_size =0 ; +const unsigned int *regs; + + np =of_find_node_by_path ("/memory@0" ); +if (np) { + regs =of_get_property (np,"reg" ,NULL ); + memzero_size = regs ? regs[3 ] :0 ; +of_node_put (np); + } + +if (memzero_size) { +/* We now know the size of memory@0, use this to find +* the first memoryblock and get its size. +*/ +char buf[64 ]; + +sprintf (buf,"/memory@%x" , memzero_size); + np =of_find_node_by_path (buf); +if (np) { + regs =of_get_property (np,"reg" ,NULL ); + memblock_size = regs ? regs[3 ] :0 ; +of_node_put (np); + } + } + } + +return memblock_size; +} + +unsigned long memory_block_size_bytes (void ) +{ +return get_memblock_size (); +} +static int pseries_remove_memblock (unsigned long base,unsigned int memblock_size) {unsigned long start, start_pfn;
@@ -127,30 +175,22 @@ static int pseries_add_memory(struct device_node *np)static int pseries_drconf_memory (unsigned long *base,unsigned int action) { -struct device_node *np; -const unsigned long *lmb_size; +unsigned long memblock_size;int rc; - np =of_find_node_by_path ("/ibm,dynamic-reconfiguration-memory" ); -if (!np) + memblock_size =get_memblock_size (); +if (!memblock_size)return -EINVAL ; - lmb_size =of_get_property (np,"ibm,lmb-size" ,NULL ); -if (!lmb_size) { -of_node_put (np); -return -EINVAL ; - } -if (action ==PSERIES_DRCONF_MEM_ADD ) { - rc =memblock_add (*base, *lmb_size); + rc =memblock_add (*base, memblock_size); rc = (rc <0 ) ? -EINVAL :0 ; }else if (action ==PSERIES_DRCONF_MEM_REMOVE ) { - rc =pseries_remove_memblock (*base, *lmb_size); + rc =pseries_remove_memblock (*base, memblock_size); }else { rc = -EINVAL ; } -of_node_put (np);return rc; }
Signature · 1 line
1.7.4.1
PATCH 16/50 memory hotplug: Define memory_block_size_bytes for x86_64 with CONFIG_X86_UV
In reply to Greg Kroah-HartmanFrom: Nathan Fontenot <[email protected]>
Define a version of memory_block_size_bytes for x86_64 when CONFIG_X86_UV is set.
--- arch/x86/mm/init_64.c | 14 ++++++++++++++ 1 files changed, 14 insertions(+), 0 deletions(-)
arch/x86/mm/init_64.c +14 -0
@@ -51,6 +51,7 @@#include <asm/numa.h> #include <asm/cacheflush.h> #include <asm/init.h> +#include <asm/uv/uv.h> static int __init parse_direct_gbpages_off (char *arg) {
@@ -908,6 +909,19 @@ const char *arch_vma_name(struct vm_area_struct *vma)return NULL ; } +#ifdef CONFIG_X86_UV +#define MIN_MEMORY_BLOCK_SIZE (1 << SECTION_SIZE_BITS) + +unsigned long memory_block_size_bytes (void ) +{ +if (is_uv_system ()) { +printk (KERN_INFO "UV: memory block size 2GB\n" ); +return 2UL *1024 *1024 *1024 ; + } +return MIN_MEMORY_BLOCK_SIZE ; +} +#endif +#ifdef CONFIG_SPARSEMEM_VMEMMAP /* * Initialise the sparsemem vmemmap using huge-pages at the PMD level.
Signature · 1 line
1.7.4.1
PATCH 17/50 memory hotplug: sysfs probe routine should add all memory sections
In reply to Greg Kroah-HartmanFrom: Nathan Fontenot <[email protected]>
As a follow-on to the recent patches I submitted that allowed for a sysfs memory block to span multiple memory sections, we should also update the probe routine to online all of the memory sections in a memory block. Without this patch the current code will only add a single memory section. I think the probe routine should add all of the memory sections in the specified memory block so that its behavior is in line with memory hotplug actions through the sysfs interfaces.
This patch applies on top of the previous sysfs memory updates to allow a sysfs directory o span multiple memory sections.
https://lkml.org/lkml/2011/1/20/245
--- drivers/base/memory.c | 13 ++++++++++--- 1 files changed, 10 insertions(+), 3 deletions(-)
drivers/base/memory.c +10 -3
@@ -387,12 +387,19 @@ memory_probe_store(struct class *class, struct class_attribute *attr, {u64 phys_addr;int nid; -int ret; +int i, ret; phys_addr =simple_strtoull (buf,NULL ,0 ); - nid =memory_add_physaddr_to_nid (phys_addr); - ret =add_memory (nid, phys_addr,PAGES_PER_SECTION <<PAGE_SHIFT ); +for (i =0 ; i < sections_per_block; i++) { + nid =memory_add_physaddr_to_nid (phys_addr); + ret =add_memory (nid, phys_addr, +PAGES_PER_SECTION <<PAGE_SHIFT ); +if (ret) +break ; + + phys_addr +=MIN_MEMORY_BLOCK_SIZE ; + }if (ret) count = ret;
Signature · 1 line
1.7.4.1
PATCH 18/50 driver core: Replace the dangerous to_root_device macro with an inline function
In reply to Greg Kroah-HartmanFrom: Ferenc Wagner <[email protected]>
The original macro worked only when applied to variables named 'dev'. While this could have been fixed by simply renaming the macro argument, a more type-safe replacement by an inline function is preferred.
--- drivers/base/core.c | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-)
drivers/base/core.c +4 -1
@@ -1320,7 +1320,10 @@ struct root_devicestruct module *owner; }; -#define to_root_device (dev) container_of(dev, struct root_device, dev) +inline struct root_device *to_root_device (struct device *d) +{ + return container_of(d, struct root_device, dev); +}static void root_device_release (struct device *dev) {
Signature · 1 line
1.7.4.1
PATCH 19/50 sysfs: Capitalize description of SYSFS_DEPRECATED{_V2} options
In reply to Greg Kroah-HartmanFrom: Ferenc Wagner <[email protected]>
--- init/Kconfig | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
init/Kconfig +2 -2
@@ -814,7 +814,7 @@ config MM_OWNER bool config SYSFS_DEPRECATED - bool "enable deprecated sysfs features to support old userspace tools" + bool "Enable deprecated sysfs features to support old userspace tools" depends on SYSFS default n help
@@ -837,7 +837,7 @@ config SYSFS_DEPRECATED need to say Y here. config SYSFS_DEPRECATED_V2 - bool "enabled deprecated sysfs features by default" + bool "Enable deprecated sysfs features by default" default n depends on SYSFS depends on SYSFS_DEPRECATED
Signature · 1 line
1.7.4.1
PATCH 20/50 Fix a mistake Chinese character in Documentation/zh_CN/SubmittingPatches
In reply to Greg Kroah-HartmanFrom: Harry Wei <[email protected]>
When i see the file linux-2.6.37/Documentation/zh_CN/SubmittingPatches , i find a mistake Chinese character in it. So i give a patch for correcting this error.
--- Documentation/zh_CN/SubmittingPatches | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
Documentation/zh_CN/SubmittingPatches +1 -1
@@ -100,7 +100,7 @@ http://userweb.kernel.org/~akpm/stuff/patch-scripts.tar.gz 将改动拆分,逻辑类似的放到同一个补丁文件里。 -例如,如果你的改动里同时有bug修正和性能优化,那么把这些改动才分到两个或 +例如,如果你的改动里同时有bug修正和性能优化,那么把这些改动拆分到两个或 者更多的补丁文件中。如果你的改动包含对API的修改,并且修改了驱动程序来适 应这些新的API,那么把这些修改分成两个补丁。
Signature · 1 line
1.7.4.1
PATCH 21/50 drivers:misc: ti-st: register with channel IDs
In reply to Greg Kroah-HartmanFrom: Pavan Savoy <[email protected]>
The architecture of shared transport had begun with individual protocols like bluetooth, fm and gps telling the shared transport what sort of protocol they are and then expecting the ST driver to parse the incoming data from chip and forward data only relevant to the protocol drivers.
This change would mean each protocol drivers would also send information to ST driver as to how to intrepret their protocol data coming out of the chip.
--- drivers/misc/ti-st/st_core.c | 355 +++++++++++++----------------------------- drivers/misc/ti-st/st_kim.c | 56 ++++---- include/linux/ti_wilink_st.h | 40 ++++-- 3 files changed, 167 insertions(+), 284 deletions(-)
drivers/misc/ti-st/st_core.c +112 -243
@@ -25,10 +25,9 @@#include <linux/init.h> #include <linux/tty.h> -/* understand BT, FM and GPS for now */ -#include <net/bluetooth/bluetooth.h> -#include <net/bluetooth/hci_core.h> -#include <net/bluetooth/hci.h> +#include <linux/seq_file.h> +#include <linux/skbuff.h> +#include <linux/ti_wilink_st.h> /* function pointer pointing to either,
@@ -38,21 +37,20 @@void (*st_recv) (void *,const unsigned char *,long );/********************************************************************/ -#if 0 -/* internal misc functions */ -bool is_protocol_list_empty (void ) +static void add_channel_to_table (struct st_data_s *st_gdata, +struct st_proto_s *new_proto) { -unsigned char i =0 ; -pr_debug (" %s " , __func__); -for (i =0 ; i <ST_MAX ; i++) { -if (st_gdata->list[i] !=NULL ) -return ST_NOTEMPTY ; -/* not empty */ - } -/* list empty */ -return ST_EMPTY ; +pr_info ("%s: id %d\n" , __func__, new_proto->chnl_id); +/* list now has the channel id as index itself */ + st_gdata->list[new_proto->chnl_id] = new_proto; +} + +static void remove_channel_from_table (struct st_data_s *st_gdata, +struct st_proto_s *proto) +{ +pr_info ("%s: id %d\n" , __func__, proto->chnl_id); + st_gdata->list[proto->chnl_id] =NULL ; } -#endif /* can be called in from * -- KIM (during fw download)
@@ -82,15 +80,15 @@ int st_int_write(struct st_data_s *st_gdata,* push the skb received to relevant * protocol stacks */ -void st_send_frame (enum proto_type protoid,struct st_data_s *st_gdata) +void st_send_frame (unsigned char chnl_id,struct st_data_s *st_gdata) { -pr_info (" %s(prot:%d) " , __func__, protoid); +pr_info (" %s(prot:%d) " , __func__, chnl_id);if (unlikely (st_gdata ==NULL || st_gdata->rx_skb ==NULL - || st_gdata->list[protoid] ==NULL )) { -pr_err ("protocol %d not registered, no data to send?" , - protoid); + || st_gdata->list[chnl_id] ==NULL )) { +pr_err ("chnl_id %d not registered, no data to send?" , + chnl_id);kfree_skb (st_gdata->rx_skb);return ; }
@@ -99,17 +97,17 @@ void st_send_frame(enum proto_type protoid, struct st_data_s *st_gdata)* - should be just skb_queue_tail for the * protocol stack driver */ -if (likely (st_gdata->list[protoid]->recv !=NULL )) { +if (likely (st_gdata->list[chnl_id]->recv !=NULL )) {if (unlikely - (st_gdata->list[protoid]->recv - (st_gdata->list[protoid]->priv_data, st_gdata->rx_skb) + (st_gdata->list[chnl_id]->recv + (st_gdata->list[chnl_id]->priv_data, st_gdata->rx_skb) !=0 )) { -pr_err (" proto stack %d's ->recv failed" , protoid); +pr_err (" proto stack %d's ->recv failed" , chnl_id);kfree_skb (st_gdata->rx_skb);return ; } }else { -pr_err (" proto stack %d's ->recv null" , protoid); +pr_err (" proto stack %d's ->recv null" , chnl_id);kfree_skb (st_gdata->rx_skb); }return ;
@@ -124,7 +122,7 @@ void st_reg_complete(struct st_data_s *st_gdata, char err) {unsigned char i =0 ;pr_info (" %s " , __func__); -for (i =0 ; i <ST_MAX ; i++) { +for (i =0 ; i <ST_MAX_CHANNELS ; i++) {if (likely (st_gdata !=NULL && st_gdata->list[i] !=NULL && st_gdata->list[i]->reg_complete_cb !=NULL )) st_gdata->list[i]->reg_complete_cb
@@ -133,7 +131,7 @@ void st_reg_complete(struct st_data_s *st_gdata, char err) }static inline int st_check_data_len (struct st_data_s *st_gdata, -int protoid,int len) +unsigned char chnl_id,int len) {int room =skb_tailroom (st_gdata->rx_skb);
@@ -144,7 +142,7 @@ static inline int st_check_data_len(struct st_data_s *st_gdata,* has zero length payload. So, ask ST CORE to * forward the packet to protocol driver (BT/FM/GPS) */ -st_send_frame (protoid, st_gdata); +st_send_frame (chnl_id, st_gdata); }else if (len > room) {/* Received packet's payload length is larger.
@@ -157,7 +155,7 @@ static inline int st_check_data_len(struct st_data_s *st_gdata,/* Packet header has non-zero payload length and * we have enough space in created skb. Lets read * payload data */ - st_gdata->rx_state =ST_BT_W4_DATA ; + st_gdata->rx_state =ST_W4_DATA ; st_gdata->rx_count = len;return len; }
@@ -167,6 +165,7 @@ static inline int st_check_data_len(struct st_data_s *st_gdata, st_gdata->rx_state =ST_W4_PACKET_TYPE ; st_gdata->rx_skb =NULL ; st_gdata->rx_count =0 ; + st_gdata->rx_chnl =0 ;return 0 ; }
@@ -208,13 +207,10 @@ void st_int_recv(void *disc_data, const unsigned char *data, long count) { char *ptr; -struct hci_event_hdr *eh; -struct hci_acl_hdr *ah; -struct hci_sco_hdr *sh; -struct fm_event_hdr *fm; -struct gps_event_hdr *gps; -int len =0 , type =0 , dlen =0 ; -static enum proto_type protoid =ST_MAX ; +struct st_proto_s *proto; +unsigned short payload_len =0 ; +int len =0 , type =0 ; +unsigned char *plen;struct st_data_s *st_gdata = (struct st_data_s *)disc_data; ptr = (char *)data;
@@ -242,64 +238,36 @@ void st_int_recv(void *disc_data,/* Check ST RX state machine , where are we? */ switch (st_gdata->rx_state) { - -/* Waiting for complete packet ? */ -case ST_BT_W4_DATA : +/* Waiting for complete packet ? */ +case ST_W4_DATA :pr_debug ("Complete pkt received" ); -/* Ask ST CORE to forward * the packet to protocol driver */ -st_send_frame (protoid, st_gdata); +st_send_frame (st_gdata->rx_chnl, st_gdata); st_gdata->rx_state =ST_W4_PACKET_TYPE ; st_gdata->rx_skb =NULL ; - protoid =ST_MAX ;/* is this required ? */ -continue ; - -/* Waiting for Bluetooth event header ? */ -case ST_BT_W4_EVENT_HDR : - eh = (struct hci_event_hdr *)st_gdata->rx_skb-> - data; - -pr_debug ("Event header: evt 0x%2.2x" -"plen %d" , eh->evt, eh->plen); - -st_check_data_len (st_gdata, protoid, eh->plen); -continue ; - -/* Waiting for Bluetooth acl header ? */ -case ST_BT_W4_ACL_HDR : - ah = (struct hci_acl_hdr *)st_gdata->rx_skb-> - data; - dlen =__le16_to_cpu (ah->dlen); - -pr_info ("ACL header: dlen %d" , dlen); - -st_check_data_len (st_gdata, protoid, dlen); -continue ; - -/* Waiting for Bluetooth sco header ? */ -case ST_BT_W4_SCO_HDR : - sh = (struct hci_sco_hdr *)st_gdata->rx_skb-> - data; - -pr_info ("SCO header: dlen %d" , sh->dlen); - -st_check_data_len (st_gdata, protoid, sh->dlen); -continue ; -case ST_FM_W4_EVENT_HDR : - fm = (struct fm_event_hdr *)st_gdata->rx_skb-> - data; -pr_info ("FM Header: " ); -st_check_data_len (st_gdata,ST_FM , fm->plen);continue ; -/* TODO : Add GPS packet machine logic here */ -case ST_GPS_W4_EVENT_HDR : -/* [0x09 pkt hdr][R/W byte][2 byte len] */ - gps = (struct gps_event_hdr *)st_gdata->rx_skb-> - data; -pr_info ("GPS Header: " ); -st_check_data_len (st_gdata,ST_GPS , gps->plen); +/* parse the header to know details */ +case ST_W4_HEADER : + proto = st_gdata->list[st_gdata->rx_chnl]; + plen = + &st_gdata->rx_skb->data + [proto->offset_len_in_hdr]; +pr_info ("plen pointing to %x\n" , *plen); +if (proto->len_size ==1 )/* 1 byte len field */ + payload_len = *(unsigned char *)plen; +else if (proto->len_size ==2 ) + payload_len = +__le16_to_cpu (*(unsigned short *)plen); +else +pr_info ("%s: invalid length " +"for id %d\n" , + __func__, proto->chnl_id); +st_check_data_len (st_gdata, proto->chnl_id, + payload_len); +pr_info ("off %d, pay len %d\n" , + proto->offset_len_in_hdr, payload_len);continue ; }/* end of switch rx_state */ }
@@ -308,51 +276,6 @@ void st_int_recv(void *disc_data,/* Check first byte of packet and identify module * owner (BT/FM/GPS) */ switch (*ptr) { - -/* Bluetooth event packet? */ -case HCI_EVENT_PKT : -pr_info ("Event packet" ); - st_gdata->rx_state =ST_BT_W4_EVENT_HDR ; - st_gdata->rx_count =HCI_EVENT_HDR_SIZE ; - type =HCI_EVENT_PKT ; - protoid =ST_BT ; -break ; - -/* Bluetooth acl packet? */ -case HCI_ACLDATA_PKT : -pr_info ("ACL packet" ); - st_gdata->rx_state =ST_BT_W4_ACL_HDR ; - st_gdata->rx_count =HCI_ACL_HDR_SIZE ; - type =HCI_ACLDATA_PKT ; - protoid =ST_BT ; -break ; - -/* Bluetooth sco packet? */ -case HCI_SCODATA_PKT : -pr_info ("SCO packet" ); - st_gdata->rx_state =ST_BT_W4_SCO_HDR ; - st_gdata->rx_count =HCI_SCO_HDR_SIZE ; - type =HCI_SCODATA_PKT ; - protoid =ST_BT ; -break ; - -/* Channel 8(FM) packet? */ -case ST_FM_CH8_PKT : -pr_info ("FM CH8 packet" ); - type =ST_FM_CH8_PKT ; - st_gdata->rx_state =ST_FM_W4_EVENT_HDR ; - st_gdata->rx_count =FM_EVENT_HDR_SIZE ; - protoid =ST_FM ; -break ; - -/* Channel 9(GPS) packet? */ -case 0x9 :/*ST_LL_GPS_CH9_PKT */ -pr_info ("GPS CH9 packet" ); - type =0x9 ;/* ST_LL_GPS_CH9_PKT; */ - protoid =ST_GPS ; - st_gdata->rx_state =ST_GPS_W4_EVENT_HDR ; - st_gdata->rx_count =3 ;/* GPS_EVENT_HDR_SIZE -1*/ -break ;case LL_SLEEP_IND :case LL_SLEEP_ACK :case LL_WAKE_UP_IND :
@@ -373,57 +296,22 @@ void st_int_recv(void *disc_data,continue ;/* Unknow packet? */ default : -pr_err ("Unknown packet type %2.2x" , (__u8) *ptr); - ptr++; - count--; -continue ; + type = *ptr; + st_gdata->rx_skb =alloc_skb ( + st_gdata->list[type]->max_frame_size, +GFP_ATOMIC ); +skb_reserve (st_gdata->rx_skb, + st_gdata->list[type]->reserve); +/* next 2 required for BT only */ + st_gdata->rx_skb->cb[0 ] = type;/*pkt_type*/ + st_gdata->rx_skb->cb[1 ] =0 ;/*incoming*/ + st_gdata->rx_chnl = *ptr; + st_gdata->rx_state =ST_W4_HEADER ; + st_gdata->rx_count = st_gdata->list[type]->hdr_len; +pr_info ("rx_count %ld\n" , st_gdata->rx_count); }; ptr++; count--; - -switch (protoid) { -case ST_BT : -/* Allocate new packet to hold received data */ - st_gdata->rx_skb = -bt_skb_alloc (HCI_MAX_FRAME_SIZE ,GFP_ATOMIC ); -if (!st_gdata->rx_skb) { -pr_err ("Can't allocate mem for new packet" ); - st_gdata->rx_state =ST_W4_PACKET_TYPE ; - st_gdata->rx_count =0 ; -return ; - } -bt_cb (st_gdata->rx_skb)->pkt_type = type; -break ; -case ST_FM :/* for FM */ - st_gdata->rx_skb = -alloc_skb (FM_MAX_FRAME_SIZE ,GFP_ATOMIC ); -if (!st_gdata->rx_skb) { -pr_err ("Can't allocate mem for new packet" ); - st_gdata->rx_state =ST_W4_PACKET_TYPE ; - st_gdata->rx_count =0 ; -return ; - } -/* place holder 0x08 */ -skb_reserve (st_gdata->rx_skb,1 ); - st_gdata->rx_skb->cb[0 ] =ST_FM_CH8_PKT ; -break ; -case ST_GPS : -/* for GPS */ - st_gdata->rx_skb = -alloc_skb (100 /*GPS_MAX_FRAME_SIZE */ ,GFP_ATOMIC ); -if (!st_gdata->rx_skb) { -pr_err ("Can't allocate mem for new packet" ); - st_gdata->rx_state =ST_W4_PACKET_TYPE ; - st_gdata->rx_count =0 ; -return ; - } -/* place holder 0x09 */ -skb_reserve (st_gdata->rx_skb,1 ); - st_gdata->rx_skb->cb[0 ] =0x09 ;/*ST_GPS_CH9_PKT; */ -break ; -case ST_MAX : -break ; - } }pr_debug ("done %s" , __func__);return ;
@@ -565,20 +453,28 @@ long st_register(struct st_proto_s *new_proto)unsigned long flags =0 ;st_kim_ref (&st_gdata,0 ); -pr_info ("%s(%d) " , __func__, new_proto->type); +pr_info ("%s(%d) " , __func__, new_proto->chnl_id);if (st_gdata ==NULL || new_proto ==NULL || new_proto->recv ==NULL || new_proto->reg_complete_cb ==NULL ) {pr_err ("gdata/new_proto/recv or reg_complete_cb not ready" ); +if (st_gdata ==NULL ) +pr_err ("error 1\n" ); +if (new_proto ==NULL ) +pr_err ("error 2\n" ); +if (new_proto->recv ==NULL ) +pr_err ("error 3\n" ); +if (new_proto->reg_complete_cb ==NULL ) +pr_err ("erro 4\n" );return -1 ; } -if (new_proto->type <ST_BT || new_proto->type >=ST_MAX ) { -pr_err ("protocol %d not supported" , new_proto->type); +if (new_proto->chnl_id >=ST_MAX_CHANNELS ) { +pr_err ("chnl_id %d not supported" , new_proto->chnl_id);return -EPROTONOSUPPORT ; } -if (st_gdata->list[new_proto->type] !=NULL ) { -pr_err ("protocol %d already registered" , new_proto->type); +if (st_gdata->list[new_proto->chnl_id] !=NULL ) { +pr_err ("chnl_id %d already registered" , new_proto->chnl_id);return -EALREADY ; }
@@ -586,11 +482,11 @@ long st_register(struct st_proto_s *new_proto)spin_lock_irqsave (&st_gdata->lock, flags);if (test_bit (ST_REG_IN_PROGRESS , &st_gdata->st_state)) { -pr_info (" ST_REG_IN_PROGRESS:%d " , new_proto->type); +pr_info (" ST_REG_IN_PROGRESS:%d " , new_proto->chnl_id);/* fw download in progress */ -st_kim_chip_toggle (new_proto->type,KIM_GPIO_ACTIVE ); +st_kim_chip_toggle (new_proto->chnl_id,KIM_GPIO_ACTIVE ); - st_gdata->list[new_proto->type] = new_proto; +add_channel_to_table (st_gdata, new_proto); st_gdata->protos_registered++; new_proto->write = st_write;
@@ -598,7 +494,7 @@ long st_register(struct st_proto_s *new_proto)spin_unlock_irqrestore (&st_gdata->lock, flags);return -EINPROGRESS ; }else if (st_gdata->protos_registered ==ST_EMPTY ) { -pr_info (" protocol list empty :%d " , new_proto->type); +pr_info (" chnl_id list empty :%d " , new_proto->chnl_id);set_bit (ST_REG_IN_PROGRESS , &st_gdata->st_state); st_recv = st_kim_recv;
@@ -622,9 +518,9 @@ long st_register(struct st_proto_s *new_proto)return -1 ; } -/* the protocol might require other gpios to be toggled +/* the chnl_id might require other gpios to be toggled */ -st_kim_chip_toggle (new_proto->type,KIM_GPIO_ACTIVE ); +st_kim_chip_toggle (new_proto->chnl_id,KIM_GPIO_ACTIVE );clear_bit (ST_REG_IN_PROGRESS , &st_gdata->st_state); st_recv = st_int_recv;
@@ -642,14 +538,14 @@ long st_register(struct st_proto_s *new_proto)/* check for already registered once more, * since the above check is old */ -if (st_gdata->list[new_proto->type] !=NULL ) { +if (st_gdata->list[new_proto->chnl_id] !=NULL ) {pr_err (" proto %d already registered " , - new_proto->type); + new_proto->chnl_id);return -EALREADY ; }spin_lock_irqsave (&st_gdata->lock, flags); - st_gdata->list[new_proto->type] = new_proto; +add_channel_to_table (st_gdata, new_proto); st_gdata->protos_registered++; new_proto->write = st_write;spin_unlock_irqrestore (&st_gdata->lock, flags);
@@ -657,22 +553,7 @@ long st_register(struct st_proto_s *new_proto) }/* if fw is already downloaded & new stack registers protocol */ else { -switch (new_proto->type) { -case ST_BT : -/* do nothing */ -break ; -case ST_FM : -case ST_GPS : -st_kim_chip_toggle (new_proto->type,KIM_GPIO_ACTIVE ); -break ; -case ST_MAX : -default : -pr_err ("%d protocol not supported" , - new_proto->type); -spin_unlock_irqrestore (&st_gdata->lock, flags); -return -EPROTONOSUPPORT ; - } - st_gdata->list[new_proto->type] = new_proto; +add_channel_to_table (st_gdata, new_proto); st_gdata->protos_registered++; new_proto->write = st_write;
@@ -680,48 +561,48 @@ long st_register(struct st_proto_s *new_proto)spin_unlock_irqrestore (&st_gdata->lock, flags);return err; } -pr_debug ("done %s(%d) " , __func__, new_proto->type); +pr_debug ("done %s(%d) " , __func__, new_proto->chnl_id); }EXPORT_SYMBOL_GPL (st_register);/* to unregister a protocol - * to be called from protocol stack driver */ -long st_unregister (enum proto_type type) +long st_unregister (struct st_proto_s *proto) {long err =0 ;unsigned long flags =0 ;struct st_data_s *st_gdata; -pr_debug ("%s: %d " , __func__, type); +pr_debug ("%s: %d " , __func__, proto->chnl_id);st_kim_ref (&st_gdata,0 ); -if (type <ST_BT || type >=ST_MAX ) { -pr_err (" protocol %d not supported" , type); +if (proto->chnl_id >=ST_MAX_CHANNELS ) { +pr_err (" chnl_id %d not supported" , proto->chnl_id);return -EPROTONOSUPPORT ; }spin_lock_irqsave (&st_gdata->lock, flags); -if (st_gdata->list[type] ==NULL ) { -pr_err (" protocol %d not registered" , type); +if (st_gdata->list[proto->chnl_id] ==NULL ) { +pr_err (" chnl_id %d not registered" , proto->chnl_id);spin_unlock_irqrestore (&st_gdata->lock, flags);return -EPROTONOSUPPORT ; } st_gdata->protos_registered--; - st_gdata->list[type] =NULL ; +remove_channel_from_table (st_gdata, proto);/* kim ignores BT in the below function * and handles the rest, BT is toggled * only in kim_start and kim_stop */ -st_kim_chip_toggle (type,KIM_GPIO_INACTIVE ); +st_kim_chip_toggle (proto->chnl_id,KIM_GPIO_INACTIVE );spin_unlock_irqrestore (&st_gdata->lock, flags);if ((st_gdata->protos_registered ==ST_EMPTY ) && (!test_bit (ST_REG_PENDING , &st_gdata->st_state))) { -pr_info (" all protocols unregistered " ); +pr_info (" all chnl_ids unregistered " );/* stop traffic on tty */ if (st_gdata->tty) {
@@ -729,7 +610,7 @@ long st_unregister(enum proto_type type)stop_tty (st_gdata->tty); } -/* all protocols now unregistered */ +/* all chnl_ids now unregistered */ st_kim_stop (st_gdata->kim_data);/* disable ST LL */ st_ll_disable (st_gdata);
@@ -745,7 +626,7 @@ long st_write(struct sk_buff *skb) {struct st_data_s *st_gdata;#ifdef DEBUG -enum proto_type protoid =ST_MAX ; +unsigned char chnl_id =ST_MAX_CHANNELS ;#endif long len;
@@ -756,22 +637,10 @@ long st_write(struct sk_buff *skb)return -1 ; }#ifdef DEBUG /* open-up skb to read the 1st byte */ -switch (skb->data[0 ]) { -case HCI_COMMAND_PKT : -case HCI_ACLDATA_PKT : -case HCI_SCODATA_PKT : - protoid =ST_BT ; -break ; -case ST_FM_CH8_PKT : - protoid =ST_FM ; -break ; -case 0x09 : - protoid =ST_GPS ; -break ; - } -if (unlikely (st_gdata->list[protoid] ==NULL )) { -pr_err (" protocol %d not registered, and writing? " , - protoid); + chnl_id = skb->data[0 ]; +if (unlikely (st_gdata->list[chnl_id] ==NULL )) { +pr_err (" chnl_id %d not registered, and writing? " , + chnl_id);return -1 ; }#endif
@@ -824,7 +693,7 @@ static int st_tty_open(struct tty_struct *tty)static void st_tty_close (struct tty_struct *tty) { -unsigned char i =ST_MAX ; +unsigned char i =ST_MAX_CHANNELS ;unsigned long flags =0 ;struct st_data_s *st_gdata = tty->disc_data;
@@ -835,7 +704,7 @@ static void st_tty_close(struct tty_struct *tty)* un-installed for some reason - what should be done ? */ spin_lock_irqsave (&st_gdata->lock, flags); -for (i =ST_BT ; i <ST_MAX ; i++) { +for (i =ST_BT ; i <ST_MAX_CHANNELS ; i++) {if (st_gdata->list[i] !=NULL )pr_err ("%d not un-registered" , i); st_gdata->list[i] =NULL ;
@@ -869,7 +738,7 @@ static void st_tty_close(struct tty_struct *tty)static void st_tty_receive (struct tty_struct *tty,const unsigned char *data,char *tty_flags,int count) { - +#define VERBOSE #ifdef VERBOSE print_hex_dump (KERN_DEBUG ,">in>" ,DUMP_PREFIX_NONE ,16 ,1 , data, count,0 );
drivers/misc/ti-st/st_kim.c +27 -29
145 lines not on this page · raw message
include/linux/ti_wilink_st.h +28 -12
@@ -42,7 +42,7 @@ enum proto_type {ST_BT ,ST_FM ,ST_GPS , - ST_MAX, + ST_MAX_CHANNELS = 16, };/**
@@ -62,6 +62,17 @@ enum proto_type {* @priv_data: privdate data holder for the protocol drivers, sent * from the protocol drivers during registration, and sent back on * reg_complete_cb and recv. +* @chnl_id: channel id the protocol driver is interested in, the channel +* id is nothing but the 1st byte of the packet in UART frame. +* @max_frame_size: size of the largest frame the protocol can receive. +* @hdr_len: length of the header structure of the protocol. +* @offset_len_in_hdr: this provides the offset of the length field in the +* header structure of the protocol header, to assist ST to know +* how much to receive, if the data is split across UART frames. +* @len_size: whether the length field inside the header is 2 bytes +* or 1 byte. +* @reserve: the number of bytes ST needs to reserve in the skb being +* prepared for the protocol driver. */ struct st_proto_s {enum proto_type type;
@@ -70,10 +81,17 @@ struct st_proto_s {void (*reg_complete_cb) (void *,char data);long (*write) (struct sk_buff *skb);void *priv_data; + +unsigned char chnl_id; +unsigned short max_frame_size; +unsigned char hdr_len; +unsigned char offset_len_in_hdr; +unsigned char len_size; +unsigned char reserve; };extern long st_register (struct st_proto_s *); -extern long st_unregister (enum proto_type ); +extern long st_unregister (struct st_proto_s *);/*
@@ -114,6 +132,7 @@ extern long st_unregister(enum proto_type);* @rx_skb: the skb where all data for a protocol gets accumulated, * since tty might not call receive when a complete event packet * is received, the states, count and the skb needs to be maintained. +* @rx_chnl: the channel ID for which the data is getting accumalated for. * @txq: the list of skbs which needs to be sent onto the TTY. * @tx_waitq: if the chip is not in AWAKE state, the skbs needs to be queued * up in here, PM(WAKEUP_IND) data needs to be sent and then the skbs
@@ -135,10 +154,11 @@ struct st_data_s {#define ST_TX_SENDING 1#define ST_TX_WAKEUP 2unsigned long tx_state; -struct st_proto_s *list[ST_MAX ]; +struct st_proto_s *list[ST_MAX_CHANNELS ];unsigned long rx_state;unsigned long rx_count;struct sk_buff *rx_skb; +unsigned char rx_chnl;struct sk_buff_head txq, tx_waitq;spinlock_t lock;unsigned char protos_registered;
@@ -243,12 +263,12 @@ struct kim_data_s {struct completion kim_rcvd, ldisc_installed;char resp_buffer[30 ];const struct firmware *fw_entry; -long gpios[ST_MAX ]; +long gpios[ST_MAX_CHANNELS ];unsigned long rx_state;unsigned long rx_count;struct sk_buff *rx_skb; -struct rfkill *rfkill[ST_MAX ]; -enum proto_type rf_protos[ST_MAX ]; +struct rfkill *rfkill[ST_MAX_CHANNELS ]; +enum proto_type rf_protos[ST_MAX_CHANNELS ];struct st_data_s *core_data;struct chip_version version; };
@@ -338,12 +358,8 @@ struct hci_command {/* ST LL receiver states */ #define ST_W4_PACKET_TYPE 0 -#define ST_BT_W4_EVENT_HDR 1 -#define ST_BT_W4_ACL_HDR 2 -#define ST_BT_W4_SCO_HDR 3 -#define ST_BT_W4_DATA 4 -#define ST_FM_W4_EVENT_HDR 5 -#define ST_GPS_W4_EVENT_HDR 6 +#define ST_W4_HEADER 1 +#define ST_W4_DATA 2/* ST LL state machines */ #define ST_LL_ASLEEP 0
Signature · 1 line
1.7.4.1
PATCH 22/50 drivers:misc: ti-st: move from rfkill to sysfs
In reply to Greg Kroah-HartmanFrom: Pavan Savoy <[email protected]>
The communication between ST KIM and UIM was interfaced over the /dev/rfkill device node.
Move the interface to a simpler less abusive sysfs entry mechanism and document it in Documentation/ABI/testing/ under sysfs-platform-kim.
Shared transport driver would now read the UART details originally received by bootloader or firmware as platform data.
The data read will be shared over sysfs entries for the user-space UIM or other n/w manager/plugins to be read, and assist the driver by opening up the UART, setting the baud-rate and installing the line discipline.
--- Documentation/ABI/testing/sysfs-platform-kim | 48 +++++ drivers/misc/ti-st/st_kim.c | 244 +++++++++++++------------- include/linux/ti_wilink_st.h | 19 ++- 3 files changed, 186 insertions(+), 125 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-platform-kim
Documentation/ABI/testing/sysfs-platform-kim new file +48 -0
@@ -0,0 +1,48 @@ +What: /sys/devices/platform/kim/dev_name +Date: January 2010 +KernelVersion: 2.6.38 +Contact: "Pavan Savoy" <[email protected]> +Description: + Name of the UART device at which the WL128x chip + is connected. example: "/dev/ttyS0". + The device name flows down to architecture specific board + initialization file from the SFI/ATAGS bootloader + firmware. The name exposed is read from the user-space + dameon and opens the device when install is requested. + +What: /sys/devices/platform/kim/baud_rate +Date: January 2010 +KernelVersion: 2.6.38 +Contact: "Pavan Savoy" <[email protected]> +Description: + The maximum reliable baud-rate the host can support. + Different platforms tend to have different high-speed + UART configurations, so the baud-rate needs to be set + locally and also sent across to the WL128x via a HCI-VS + command. The entry is read and made use by the user-space + daemon when the ldisc install is requested. + +What: /sys/devices/platform/kim/flow_cntrl +Date: January 2010 +KernelVersion: 2.6.38 +Contact: "Pavan Savoy" <[email protected]> +Description: + The WL128x makes use of flow control mechanism, and this + entry most often should be 1, the host's UART is required + to have the capability of flow-control, or else this + entry can be made use of for exceptions. + +What: /sys/devices/platform/kim/install +Date: January 2010 +KernelVersion: 2.6.38 +Contact: "Pavan Savoy" <[email protected]> +Description: + When one of the protocols Bluetooth, FM or GPS wants to make + use of the shared UART transport, it registers to the shared + transport driver, which will signal the user-space for opening, + configuring baud and install line discipline via this sysfs + entry. This entry would be polled upon by the user-space + daemon managing the UART, and is notified about the change + by the sysfs_notify. The value would be '1' when UART needs + to be opened/ldisc installed, and would be '0' when UART + is no more required and needs to be closed.
drivers/misc/ti-st/st_kim.c +121 -123
345 lines not on this page · raw message
include/linux/ti_wilink_st.h +17 -2
@@ -206,8 +206,8 @@ void gps_chrdrv_stub_init(void);/* time in msec to wait for * line discipline to be installed */ -#define LDISC_TIME 500 -#define CMD_RESP_TIME 500 +#define LDISC_TIME 1000 +#define CMD_RESP_TIME 800#define MAKEWORD (a, b) ((unsigned short)(((unsigned char)(a)) \ | ((unsigned short)((unsigned char)(b))) << 8))
@@ -230,6 +230,7 @@ struct chip_version {unsigned short maj_ver; }; +#define UART_DEV_NAME_LEN 32/** * struct kim_data_s - the KIM internal data, embedded as the * platform's drv data. One for each ST device in the system.
@@ -271,6 +272,10 @@ struct kim_data_s {enum proto_type rf_protos[ST_MAX_CHANNELS ];struct st_data_s *core_data;struct chip_version version; +unsigned char ldisc_install; +unsigned char dev_name[UART_DEV_NAME_LEN ]; +unsigned char flow_cntrl; +unsigned long baud_rate; };/**
@@ -413,4 +418,14 @@ struct gps_event_hdr {u16 plen; } __attribute__ ((packed)); +/* platform data */ +struct ti_st_plat_data { +long gpios[ST_MAX_CHANNELS ];/* BT, FM and GPS */ +unsigned char dev_name[UART_DEV_NAME_LEN ];/* uart name */ +unsigned char flow_cntrl;/* flow control flag */ +unsigned long baud_rate; +int (*suspend)(struct platform_device *,pm_message_t ); +int (*resume)(struct platform_device *); +}; +#endif /* TI_WILINK_ST_H */
Signature · 1 line
1.7.4.1
PATCH 23/50 drivers:misc: ti-st: fix error codes
In reply to Greg Kroah-HartmanFrom: Pavan Savoy <[email protected]>
set-right the error codes that the shared transport driver returns.
Instead of magic numbers like -1, return relevant codes such as ETIMEDOUT or EIO, EAGAIN when wait times out or uart write bytes don't match expected value or when registration fails and needs to be attempted again.
--- drivers/misc/ti-st/st_core.c | 31 ++++++++++++++----------------- drivers/misc/ti-st/st_kim.c | 18 +++++++++--------- drivers/misc/ti-st/st_ll.c | 2 +- 3 files changed, 24 insertions(+), 27 deletions(-)
drivers/misc/ti-st/st_core.c +14 -17
@@ -65,7 +65,7 @@ int st_int_write(struct st_data_s *st_gdata,struct tty_struct *tty;if (unlikely (st_gdata ==NULL || st_gdata->tty ==NULL )) {pr_err ("tty unavailable to perform write" ); -return -1 ; +return -EINVAL ; } tty = st_gdata->tty;#ifdef VERBOSE
@@ -124,9 +124,15 @@ void st_reg_complete(struct st_data_s *st_gdata, char err)pr_info (" %s " , __func__);for (i =0 ; i <ST_MAX_CHANNELS ; i++) {if (likely (st_gdata !=NULL && st_gdata->list[i] !=NULL && - st_gdata->list[i]->reg_complete_cb !=NULL )) + st_gdata->list[i]->reg_complete_cb !=NULL )) { st_gdata->list[i]->reg_complete_cb (st_gdata->list[i]->priv_data, err); +pr_info ("protocol %d's cb sent %d\n" , i, err); +if (err) {/* cleanup registered protocol */ + st_gdata->protos_registered--; + st_gdata->list[i] =NULL ; + } + } } }
@@ -457,15 +463,7 @@ long st_register(struct st_proto_s *new_proto)if (st_gdata ==NULL || new_proto ==NULL || new_proto->recv ==NULL || new_proto->reg_complete_cb ==NULL ) {pr_err ("gdata/new_proto/recv or reg_complete_cb not ready" ); -if (st_gdata ==NULL ) -pr_err ("error 1\n" ); -if (new_proto ==NULL ) -pr_err ("error 2\n" ); -if (new_proto->recv ==NULL ) -pr_err ("error 3\n" ); -if (new_proto->reg_complete_cb ==NULL ) -pr_err ("erro 4\n" ); -return -1 ; +return -EINVAL ; }if (new_proto->chnl_id >=ST_MAX_CHANNELS ) {
@@ -512,10 +510,9 @@ long st_register(struct st_proto_s *new_proto)if ((st_gdata->protos_registered !=ST_EMPTY ) && (test_bit (ST_REG_PENDING , &st_gdata->st_state))) {pr_err (" KIM failure complete callback " ); -st_reg_complete (st_gdata,-1 ); +st_reg_complete (st_gdata, err); } - -return -1 ; +return -EINVAL ; }/* the chnl_id might require other gpios to be toggled
@@ -634,14 +631,14 @@ long st_write(struct sk_buff *skb)if (unlikely (skb ==NULL || st_gdata ==NULL || st_gdata->tty ==NULL )) {pr_err ("data/tty unavailable to perform write" ); -return -1 ; +return -EINVAL ; }#ifdef DEBUG /* open-up skb to read the 1st byte */ chnl_id = skb->data[0 ];if (unlikely (st_gdata->list[chnl_id] ==NULL )) {pr_err (" chnl_id %d not registered, and writing? " , chnl_id); -return -1 ; +return -EINVAL ; }#endif pr_debug ("%d to be written" , skb->len);
@@ -829,7 +826,7 @@ int st_core_init(struct st_data_s **core_data) err =tty_unregister_ldisc (N_TI_WL );if (err)pr_err ("unable to un-register ldisc" ); -return -1 ; +return err; } *core_data = st_gdata;return 0 ;
drivers/misc/ti-st/st_kim.c +9 -9
@@ -201,13 +201,13 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name)INIT_COMPLETION (kim_gdata->kim_rcvd);if (4 !=st_int_write (kim_gdata->core_data, read_ver_cmd,4 )) {pr_err ("kim: couldn't write 4 bytes" ); -return -1 ; +return -EIO ; }if (!wait_for_completion_timeout (&kim_gdata->kim_rcvd,msecs_to_jiffies (CMD_RESP_TIME ))) {pr_err (" waiting for ver info- timed out " ); -return -1 ; +return -ETIMEDOUT ; } version =
@@ -257,7 +257,7 @@ static long download_firmware(struct kim_data_s *kim_gdata) (kim_gdata->fw_entry->size == 0))) {pr_err (" request_firmware failed(errno %ld) for %s" , err, bts_scr_name); -return -1 ; +return -EINVAL ; } ptr = (void *)kim_gdata->fw_entry->data; len = kim_gdata->fw_entry->size;
@@ -292,7 +292,7 @@ static long download_firmware(struct kim_data_s *kim_gdata) ((struct bts_action *)ptr)->size);if (unlikely (err <0 )) {release_firmware (kim_gdata->fw_entry); -return -1 ; +return err; }if (!wait_for_completion_timeout (&kim_gdata->kim_rcvd,
@@ -301,7 +301,7 @@ static long download_firmware(struct kim_data_s *kim_gdata) (" response timeout during fw download " );/* timed out */ release_firmware (kim_gdata->fw_entry); -return -1 ; +return -ETIMEDOUT ; }break ;case ACTION_DELAY :/* sleep */
@@ -436,7 +436,7 @@ long st_kim_start(void *kim_data)pr_info ("ldisc_install = 0" );sysfs_notify (&kim_gdata->kim_pdev->dev.kobj,NULL ,"install" ); - err =-1 ; + err = -ETIMEDOUT ;continue ; }else {/* ldisc installed now */
@@ -482,7 +482,7 @@ long st_kim_stop(void *kim_data) msecs_to_jiffies(LDISC_TIME));if (!err) {/* timeout */ pr_err (" timed out waiting for ldisc to be un-installed" ); -return -1 ; +return -ETIMEDOUT ; }/* By default configure BT nShutdown to LOW state */
@@ -642,7 +642,7 @@ static int kim_probe(struct platform_device *pdev) status =st_core_init (&kim_gdata->core_data);if (status !=0 ) {pr_err (" ST core init failed" ); -return -1 ; +return -EIO ; }/* refer to itself */ kim_gdata->core_data->kim_data = kim_gdata;
@@ -704,7 +704,7 @@ static int kim_probe(struct platform_device *pdev)if (IS_ERR (kim_debugfs_dir)) {pr_err (" debugfs entries creation failed " ); kim_debugfs_dir =NULL ; -return -1 ; +return -EIO ; } debugfs_create_file("version", S_IRUGO, kim_debugfs_dir,
drivers/misc/ti-st/st_ll.c +1 -1
@@ -130,7 +130,7 @@ unsigned long st_ll_sleep_state(struct st_data_s *st_data,break ;default :pr_err (" unknown input/state " ); -return -1 ; +return -EINVAL ; }return 0 ; }
Signature · 1 line
1.7.4.1
PATCH 24/50 drivers:misc: ti-st: set right debug levels for logs
In reply to Greg Kroah-HartmanFrom: Pavan Savoy <[email protected]>
pr_debug-ing few pr_infos from the data paths such as tty receive and write so as to reduce debugs when we have higher logging levels enabled undef VERBOSE in receive to avoid huge logs when log level 8 is set.
--- drivers/misc/ti-st/st_core.c | 19 +++++++++---------- drivers/misc/ti-st/st_ll.c | 8 ++++---- 2 files changed, 13 insertions(+), 14 deletions(-)
drivers/misc/ti-st/st_core.c +9 -10
@@ -82,7 +82,7 @@ int st_int_write(struct st_data_s *st_gdata,*/ void st_send_frame (unsigned char chnl_id,struct st_data_s *st_gdata) { -pr_info (" %s(prot:%d) " , __func__, chnl_id); +pr_debug (" %s(prot:%d) " , __func__, chnl_id); if (unlikely (st_gdata == NULL || st_gdata->rx_skb == NULL
@@ -226,7 +226,7 @@ void st_int_recv(void *disc_data,return ; } -pr_info ("count %ld rx_state %ld" +pr_debug ("count %ld rx_state %ld" "rx_count %ld" , count, st_gdata->rx_state, st_gdata->rx_count);
@@ -260,7 +260,7 @@ void st_int_recv(void *disc_data, plen = &st_gdata->rx_skb->data [proto->offset_len_in_hdr]; -pr_info ("plen pointing to %x\n" , *plen); +pr_debug ("plen pointing to %x\n" , *plen);if (proto->len_size ==1 )/* 1 byte len field */ payload_len = *(unsigned char *)plen;else if (proto->len_size ==2 )
@@ -272,7 +272,7 @@ void st_int_recv(void *disc_data, __func__, proto->chnl_id);st_check_data_len (st_gdata, proto->chnl_id, payload_len); -pr_info ("off %d, pay len %d\n" , +pr_debug ("off %d, pay len %d\n" , proto->offset_len_in_hdr, payload_len);continue ; }/* end of switch rx_state */
@@ -285,7 +285,7 @@ void st_int_recv(void *disc_data,case LL_SLEEP_IND :case LL_SLEEP_ACK :case LL_WAKE_UP_IND : -pr_info ("PM packet" ); +pr_debug ("PM packet" );/* this takes appropriate action based on * sleep state received -- */
@@ -294,7 +294,7 @@ void st_int_recv(void *disc_data, count--;continue ;case LL_WAKE_UP_ACK : -pr_info ("PM packet" ); +pr_debug ("PM packet" );/* wake up ack received */ st_wakeup_ack (st_gdata, *ptr); ptr++;
@@ -314,7 +314,7 @@ void st_int_recv(void *disc_data, st_gdata->rx_chnl = *ptr; st_gdata->rx_state =ST_W4_HEADER ; st_gdata->rx_count = st_gdata->list[type]->hdr_len; -pr_info ("rx_count %ld\n" , st_gdata->rx_count); +pr_debug ("rx_count %ld\n" , st_gdata->rx_count); }; ptr++; count--;
@@ -360,7 +360,7 @@ void st_int_enqueue(struct st_data_s *st_gdata, struct sk_buff *skb)switch (st_ll_getstate (st_gdata)) {case ST_LL_AWAKE : -pr_info ("ST LL is AWAKE, sending normally" ); +pr_debug ("ST LL is AWAKE, sending normally" );skb_queue_tail (&st_gdata->txq, skb);break ;case ST_LL_ASLEEP_TO_AWAKE :
@@ -400,7 +400,7 @@ void st_tx_wakeup(struct st_data_s *st_data)pr_debug ("%s" , __func__);/* check for sending & set flag sending here */ if (test_and_set_bit (ST_TX_SENDING , &st_data->tx_state)) { -pr_info ("ST already sending" ); +pr_debug ("ST already sending" );/* keep sending */ set_bit (ST_TX_WAKEUP , &st_data->tx_state);return ;
@@ -735,7 +735,6 @@ static void st_tty_close(struct tty_struct *tty)static void st_tty_receive (struct tty_struct *tty,const unsigned char *data,char *tty_flags,int count) { -#define VERBOSE #ifdef VERBOSE print_hex_dump (KERN_DEBUG ,">in>" ,DUMP_PREFIX_NONE ,16 ,1 , data, count,0 );
drivers/misc/ti-st/st_ll.c +4 -4
@@ -30,7 +30,7 @@ static void send_ll_cmd(struct st_data_s *st_data, unsigned char cmd) { -pr_info ("%s: writing %x" , __func__, cmd); +pr_debug ("%s: writing %x" , __func__, cmd);st_int_write (st_data, &cmd,1 );return ; }
@@ -114,18 +114,18 @@ unsigned long st_ll_sleep_state(struct st_data_s *st_data, {switch (cmd) {case LL_SLEEP_IND :/* sleep ind */ -pr_info ("sleep indication recvd" ); +pr_debug ("sleep indication recvd" );ll_device_want_to_sleep (st_data);break ;case LL_SLEEP_ACK :/* sleep ack */ pr_err ("sleep ack rcvd: host shouldn't" );break ;case LL_WAKE_UP_IND :/* wake ind */ -pr_info ("wake indication recvd" ); +pr_debug ("wake indication recvd" );ll_device_want_to_wakeup (st_data);break ;case LL_WAKE_UP_ACK :/* wake ack */ -pr_info ("wake ack rcvd" ); +pr_debug ("wake ack rcvd" ); st_data->ll_state =ST_LL_AWAKE ;break ;default :
Signature · 1 line
1.7.4.1
PATCH 25/50 drivers:misc: ti-st: firmware download optimization
In reply to Greg Kroah-HartmanFrom: Pavan Savoy <[email protected]>
To fasten the process of firmware download, the chip allows disabling of the command complete event generation from host. In these cases, only few very essential commands would have the command complete events and hence the wait associated with them.
So now the driver would wait for a command complete event, only when it comes across a wait event during firmware parsing. This would also mean we need to skip not just the change baud rate command but also the wait for it.
--- drivers/misc/ti-st/st_core.c | 18 +++++++++ drivers/misc/ti-st/st_kim.c | 80 ++++++++++++++++++++++++++++++++++++++---- include/linux/ti_wilink_st.h | 6 +++ 3 files changed, 97 insertions(+), 7 deletions(-)
drivers/misc/ti-st/st_core.c +18 -0
@@ -52,6 +52,24 @@ static void remove_channel_from_table(struct st_data_s *st_gdata, st_gdata->list[proto->chnl_id] =NULL ; } +/* +* called from KIM during firmware download. +* +* This is a wrapper function to tty->ops->write_room. +* It returns number of free space available in +* uart tx buffer. +*/ +int st_get_uart_wr_room (struct st_data_s *st_gdata) +{ +struct tty_struct *tty; +if (unlikely (st_gdata ==NULL || st_gdata->tty ==NULL )) { +pr_err ("tty unavailable to perform write" ); +return -1 ; + } + tty = st_gdata->tty; +return tty->ops->write_room (tty); +} +/* can be called in from * -- KIM (during fw download) * -- ST Core (during st_write)
drivers/misc/ti-st/st_kim.c +73 -7
113 lines not on this page · raw message
include/linux/ti_wilink_st.h +6 -0
@@ -166,6 +166,11 @@ struct st_data_s {void *kim_data; }; +/* +* wrapper around tty->ops->write_room to check +* availability during firmware download +*/ +int st_get_uart_wr_room (struct st_data_s *st_gdata);/** * st_int_write - * point this to tty->driver->write or tty->ops->write
@@ -208,6 +213,7 @@ void gps_chrdrv_stub_init(void);*/ #define LDISC_TIME 1000#define CMD_RESP_TIME 800 +#define CMD_WR_TIME 5000#define MAKEWORD (a, b) ((unsigned short)(((unsigned char)(a)) \ | ((unsigned short)((unsigned char)(b))) << 8))
Signature · 1 line
1.7.4.1
PATCH 26/50 drivers:misc: ti-st: fix hci-ll on wake_ind collision
In reply to Greg Kroah-HartmanFrom: Pavan Savoy <[email protected]>
Where file-transfer stops/pauses in between, is
result of a HCI-LL anamoly in ST LL driver.
ST LL did not copy the contents of WaitQ into the TxQ, when a WAKEUP_IND collision happened.
Make also sure, that the copying mechanism is safe, by wrapping it around spin locks inside st_int_recv().
This was easily reproduced when the sleep timeout was reduced to 100ms for HCI-LL.
--- drivers/misc/ti-st/st_core.c | 15 +++++++++++++++ 1 files changed, 15 insertions(+), 0 deletions(-)
drivers/misc/ti-st/st_core.c +15 -0
@@ -236,6 +236,7 @@ void st_int_recv(void *disc_data,int len =0 , type =0 ;unsigned char *plen;struct st_data_s *st_gdata = (struct st_data_s *)disc_data; +unsigned long flags; ptr = (char *)data;/* tty_receive sent null ? */
@@ -248,6 +249,7 @@ void st_int_recv(void *disc_data,"rx_count %ld" , count, st_gdata->rx_state, st_gdata->rx_count); +spin_lock_irqsave (&st_gdata->lock, flags);/* Decode received bytes here */ while (count) {if (st_gdata->rx_count) {
@@ -308,13 +310,25 @@ void st_int_recv(void *disc_data,* sleep state received -- */ st_ll_sleep_state (st_gdata, *ptr); +/* if WAKEUP_IND collides copy from waitq to txq +* and assume chip awake +*/ +spin_unlock_irqrestore (&st_gdata->lock, flags); +if (st_ll_getstate (st_gdata) ==ST_LL_AWAKE ) +st_wakeup_ack (st_gdata,LL_WAKE_UP_ACK ); +spin_lock_irqsave (&st_gdata->lock, flags); + ptr++; count--;continue ;case LL_WAKE_UP_ACK :pr_debug ("PM packet" ); + +spin_unlock_irqrestore (&st_gdata->lock, flags);/* wake up ack received */ st_wakeup_ack (st_gdata, *ptr); +spin_lock_irqsave (&st_gdata->lock, flags); + ptr++; count--;continue ;
@@ -337,6 +351,7 @@ void st_int_recv(void *disc_data, ptr++; count--; } +spin_unlock_irqrestore (&st_gdata->lock, flags);pr_debug ("done %s" , __func__);return ; }
Signature · 1 line
1.7.4.1
PATCH 27/50 drivers:misc: ti-st: remove multiple gpio handling
In reply to Greg Kroah-HartmanFrom: Pavan Savoy <[email protected]>
TI shared transport driver previously intended to expose rfkill entries for each of the protocol gpio that the chip would have. However now in case such gpios exist, which requires to be enabled for a specific protocol, the responsibility lay on protocol driver. This patch removes the request/free of multiple gpios, rfkill struct references and also removes the chip_toggle function.
--- drivers/misc/ti-st/st_core.c | 11 ---- drivers/misc/ti-st/st_kim.c | 117 +++++++++--------------------------------- include/linux/ti_wilink_st.h | 19 +------ 3 files changed, 26 insertions(+), 121 deletions(-)
drivers/misc/ti-st/st_core.c +0 -11
@@ -515,7 +515,6 @@ long st_register(struct st_proto_s *new_proto)if (test_bit (ST_REG_IN_PROGRESS , &st_gdata->st_state)) {pr_info (" ST_REG_IN_PROGRESS:%d " , new_proto->chnl_id);/* fw download in progress */ -st_kim_chip_toggle (new_proto->chnl_id,KIM_GPIO_ACTIVE );add_channel_to_table (st_gdata, new_proto); st_gdata->protos_registered++;
@@ -548,10 +547,6 @@ long st_register(struct st_proto_s *new_proto)return -EINVAL ; } -/* the chnl_id might require other gpios to be toggled -*/ -st_kim_chip_toggle (new_proto->chnl_id,KIM_GPIO_ACTIVE ); -clear_bit (ST_REG_IN_PROGRESS , &st_gdata->st_state); st_recv = st_int_recv;
@@ -622,12 +617,6 @@ long st_unregister(struct st_proto_s *proto) st_gdata->protos_registered--;remove_channel_from_table (st_gdata, proto); - -/* kim ignores BT in the below function -* and handles the rest, BT is toggled -* only in kim_start and kim_stop -*/ -st_kim_chip_toggle (proto->chnl_id,KIM_GPIO_INACTIVE );spin_unlock_irqrestore (&st_gdata->lock, flags); if ((st_gdata->protos_registered == ST_EMPTY) &&
drivers/misc/ti-st/st_kim.c +24 -93
166 lines not on this page · raw message
include/linux/ti_wilink_st.h +2 -17
@@ -26,15 +26,6 @@#define TI_WILINK_ST_H /** -* enum kim_gpio_state - Few protocols such as FM have ACTIVE LOW -* gpio states for their chip/core enable gpios -*/ -enum kim_gpio_state { -KIM_GPIO_INACTIVE , -KIM_GPIO_ACTIVE , -}; - -/** * enum proto-type - The protocol on WiLink chips which share a * common physical interface like UART. */
@@ -252,14 +243,11 @@ struct chip_version {* the ldisc was properly installed. * @resp_buffer: data buffer for the .bts fw file name. * @fw_entry: firmware class struct to request/release the fw. -* @gpios: the list of core/chip enable gpios for BT, FM and GPS cores. * @rx_state: the rx state for kim's receive func during fw download. * @rx_count: the rx count for the kim's receive func during fw download. * @rx_skb: all of fw data might not come at once, and hence data storage for * whole of the fw response, only HCI_EVENTs and hence diff from ST's * response. -* @rfkill: rfkill data for each of the cores to be registered with rfkill. -* @rf_protos: proto types of the data registered with rfkill sub-system. * @core_data: ST core's data, which mainly is the tty's disc_data * @version: chip version available via a sysfs entry. *
@@ -270,12 +258,10 @@ struct kim_data_s {struct completion kim_rcvd, ldisc_installed;char resp_buffer[30 ];const struct firmware *fw_entry; -long gpios[ST_MAX_CHANNELS ]; +long nshutdown;unsigned long rx_state;unsigned long rx_count;struct sk_buff *rx_skb; -struct rfkill *rfkill[ST_MAX_CHANNELS ]; -enum proto_type rf_protos[ST_MAX_CHANNELS ];struct st_data_s *core_data;struct chip_version version;unsigned char ldisc_install;
@@ -293,7 +279,6 @@ long st_kim_start(void *);long st_kim_stop (void *);void st_kim_recv (void *,const unsigned char *,long count); -void st_kim_chip_toggle (enum proto_type ,enum kim_gpio_state );void st_kim_complete (void *);void kim_st_list_protocols (struct st_data_s *,void *);
@@ -426,7 +411,7 @@ struct gps_event_hdr {/* platform data */ struct ti_st_plat_data { -long gpios[ST_MAX_CHANNELS ];/* BT, FM and GPS */ +long nshutdown_gpio;unsigned char dev_name[UART_DEV_NAME_LEN ];/* uart name */ unsigned char flow_cntrl;/* flow control flag */ unsigned long baud_rate;
Signature · 1 line
1.7.4.1
PATCH 28/50 kobject.h: fix build when CONFIG_HOTPLUG is disabled
In reply to Greg Kroah-HartmanFrom: Randy Dunlap <[email protected]>
When CONFIG_HOTPLUG is not enabled, the inline function add_uevent_var() needs to have its __attribute__ before the function name/parameters, otherwise there are syntax errors.
linux-next-20110207/include/linux/kobject.h:232: error: expected ',' or ';' before '{' token
--- include/linux/kobject.h | 5 ++--- 1 files changed, 2 insertions(+), 3 deletions(-)
include/linux/kobject.h +2 -3
@@ -226,9 +226,8 @@ static inline int kobject_uevent_env(struct kobject *kobj, char *envp[]) {return 0 ; } -static inline int add_uevent_var (struct kobj_uevent_env *env, -const char *format, ...) - __attribute__((format (printf,2 ,3 ))) +static inline __attribute__((format (printf,2 ,3 ))) +int add_uevent_var (struct kobj_uevent_env *env,const char *format, ...) {return 0 ; } static inline int kobject_action_type(const char *buf, size_t count,
Signature · 1 line
1.7.4.1
PATCH 29/50 debugfs: Fix filesystem reference counting on debugfs_remove() failure
In reply to Greg Kroah-HartmanFrom: Jan Kara <[email protected]>
When __debugfs_remove() fails (because simple_rmdir() fails e.g. when a directory is not empty), we must not decrement use count of the filesystem as nothing was in fact deleted.
This fixes use after free caused by debugfs in some cases.
--- fs/debugfs/inode.c | 11 +++++++---- 1 files changed, 7 insertions(+), 4 deletions(-)
fs/debugfs/inode.c +7 -4
@@ -307,7 +307,7 @@ struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent, }EXPORT_SYMBOL_GPL (debugfs_create_symlink); -static void __debugfs_remove (struct dentry *dentry,struct dentry *parent) +static int __debugfs_remove (struct dentry *dentry,struct dentry *parent) {int ret =0 ;
@@ -330,6 +330,7 @@ static void __debugfs_remove(struct dentry *dentry, struct dentry *parent)dput (dentry); } } +return ret; }/**
@@ -348,7 +349,8 @@ static void __debugfs_remove(struct dentry *dentry, struct dentry *parent)void debugfs_remove (struct dentry *dentry) {struct dentry *parent; - +int ret; +if (!dentry)return ;
@@ -357,9 +359,10 @@ void debugfs_remove(struct dentry *dentry)return ;mutex_lock (&parent->d_inode->i_mutex); -__debugfs_remove (dentry, parent); + ret =__debugfs_remove (dentry, parent);mutex_unlock (&parent->d_inode->i_mutex); -simple_release_fs (&debugfs_mount, &debugfs_mount_count); +if (!ret) +simple_release_fs (&debugfs_mount, &debugfs_mount_count); }EXPORT_SYMBOL_GPL (debugfs_remove);
Signature · 1 line
1.7.4.1
PATCH 30/50 Translat Documentation/SubmittingChecklist into Chinese
In reply to Greg Kroah-HartmanFrom: Harry Wei <[email protected]>
I have translated linux-2.6/Documentation/SubmittingChecklist into Chinese. This patch can add translated file(SubmittingChecklist) under linux-2.6/Documentation/zh_CN/. Thanks.
--- Documentation/zh_CN/SubmitChecklist | 109 +++++++++++++++++++++++++++++++++++ 1 files changed, 109 insertions(+), 0 deletions(-) create mode 100644 Documentation/zh_CN/SubmitChecklist
Documentation/zh_CN/SubmitChecklist new file +109 -0
@@ -0,0 +1,109 @@ +Chinese translated version of Documentation/SubmitChecklist + +If you have any comment or update to the content, please contact the +original document maintainer directly. However, if you have a problem +communicating in English you can also ask the Chinese maintainer for +help. Contact the Chinese maintainer if this translation is outdated +or if there is a problem with the translation. + +Chinese maintainer: Harry Wei <[email protected]> +--------------------------------------------------------------------- +Documentation/SubmitChecklist �����ķ��� + +��������ۻ���±��ĵ����ݣ���ֱ����ϵԭ�ĵ���ά���ߡ������ʹ��Ӣ�� +���������ѵĻ���Ҳ���������İ�ά���������������������²���ʱ���߷� +��������⣬����ϵ���İ�ά���ߡ� + +���İ�ά���ߣ� ������ Harry Wei <[email protected]> +���İ淭���ߣ� ������ Harry Wei <[email protected]> +���İ�У���ߣ� ������ Harry Wei <[email protected]> + + +����Ϊ���� +--------------------------------------------------------------------- +Linux�ں��ύ�嵥 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +������һЩ�ں˿�����Ӧ�����Ļ������飬��������뿴���Լ����ں˲����ύ +�����ܵĸ��졣 + +��Щ���dz���Documentation/SubmittingPatches�ĵ������ṩ���Լ����� +�����ύLinux�ں˲�����˵���� + +1�������ʹ����һ��������ô��#include����/�����Ǹ����ܵ��Ǹ��ļ��� + ��Ҫ��������������붨��/�����Ǹ����ܵ�ͷ�ļ��� + +2������������û��߸���CONFIGѡ�� =y��=m������=n�� + ��Ҫ�б��뾯��/���� ��Ҫ�����Ӿ���/���� + +2b��ͨ�� allnoconfig, allmodconfig + +2c����ʹ�� 0=builddir �ɹ��ع��� + +3��ͨ��ʹ�ñ��ؽ�����빤��������һЩ�����������ڶ�CPU����Ϲ����� + +4��ppc64 ��һ���ܺõļ�齻�����Ŀ�ܣ���Ϊ�������ѡ�unsigned long�� + ��64λֵ��ʹ�á� + +5������Documentation/CodingStyle�ļ������ϸ����������㲹���������� + ʹ�ò�������������Υ��(scripts/checkpatch.pl)�����Ա�����ύ�� + ��Ӧ�õ����������㲹���е�����Υ�档 + +6���κθ��»��߸Ķ�CONFIGѡ����ܴ������ò˵��� + +7�����е�Kconfigѡ����¶�Ҫ��˵�����֡� + +8���Ѿ�������ܽ�����ص�Kconfig��ϡ����Ǻ���ͨ���������õ�--�����������½��� + +9�������м���ԡ� + +10��ʹ��'make checkstack'��'make namespacecheck'��飬Ȼ�������ҵ������⡣ + ע�⣺��ջ��鲻����ȷ�س������⣬�����κε�һ�������ڶ�ջ��ʹ�ö���512�ֽ� + ��Ҫ���ġ� + +11������kernel-doc��ȫ���ں�APIs�ļ�������Ҫ��̬�ĺ��������ǰ���Ҳ����ν���� + ʹ��'make htmldocs'����'make mandocs'�����kernel-doc��Ȼ�����κ� + ���ֵ����⡣ + +12���Ѿ�ͨ��CONFIG_PREEMPT, CONFIG_DEBUG_PREEMPT, + CONFIG_DEBUG_SLAB, CONFIG_DEBUG_PAGEALLOC, CONFIG_DEBUG_MUTEXES, + CONFIG_DEBUG_SPINLOCK, CONFIG_DEBUG_SPINLOCK_SLEEP���ԣ�����ͬʱ�� + ʹ�ܡ� + +13���Ѿ�����������ʹ�û��߲�ʹ�� CONFIG_SMP �� CONFIG_PREEMPT����ִ��ʱ�䡣 + +14���������Ӱ��IO/Disk���ȵȣ��Ѿ�ͨ��ʹ�û��߲�ʹ�� CONFIG_LBDAF ���ԡ� + +15�����е�codepaths�Ѿ���ʹ����lockdep���ù��ܡ� + +16�����е�/proc��¼���¶�Ҫ�����ļ�����Documentation/Ŀ¼�¡� + +17�����е��ں������������¶�����¼��Documentation/kernel-parameters.txt�ļ��С� + +18�����е�ģ��������¶���MODULE_PARM_DESC()��¼�� + +19�����е��û��ռ�ӿڸ��¶�����¼��Documentation/ABI/���鿴Documentation/ABI/README + ���Ի�ø������Ϣ���ı��û��ռ�ӿڵIJ���Ӧ�ñ��ʼ�����[email protected]�� + +20��������Dz��Ƕ�ͨ��`make headers_check'�� + +21���Ѿ�ͨ����������slab��page-allocationʧ�ܼ�顣�鿴Documentation/fault-injection/�� + +22���¼����Դ���Ѿ�ͨ��`gcc -W'��ʹ��"make EXTRA_CFLAGS=-W"�����롣�����������ܶෳ�գ� + ���Ƕ���Ѱ��©�������洦������:"warning: comparison between signed and unsigned"�� + +23���������ϲ���-mm���������ٲ��ԣ�����ȷ�����ǷͲ��������е���������һ�����Լ���VM��VFS + ��������ϵͳ�и����仯�� + +24�����е��ڴ�����{e.g., barrier(), rmb(), wmb()}��Ҫ��Դ�����е�һ��ע�����������Ƕ��Ǹ�ʲô�� + �Լ�ԭ�� + +25��������κ�����������ƵIJ��������ӣ�ҲҪ����Documentation/ioctl/ioctl-number.txt�� + +26�������ĸ��Ĵ�����������ʹ���κε��ں�APIs�����������kconfig�����й�ϵ�Ĺ��ܣ����Ҫ + ʹ����ص�kconfig���Źرգ� and/or =m�����ѡ���ṩ��[��ͬһʱ�䲻�����õĶ����ã����������������� + �������]�� + + CONFIG_SMP, CONFIG_SYSFS, CONFIG_PROC_FS, CONFIG_INPUT, CONFIG_PCI, + CONFIG_BLOCK, CONFIG_PM, CONFIG_HOTPLUG, CONFIG_MAGIC_SYSRQ, + CONFIG_NET, CONFIG_INET=n (��һ��ʹ�� CONFIG_NET=y)
Signature · 1 line
1.7.4.1
PATCH 31/50 Translate linux-2.6/Documentation/magic-number.txt into Chinese
In reply to Greg Kroah-HartmanFrom: Harry Wei <[email protected]>
I have translated linux-2.6/Documentation/magic-number.txt into Chinese.
--- Documentation/zh_CN/magic-number.txt | 167 ++++++++++++++++++++++++++++++++++ 1 files changed, 167 insertions(+), 0 deletions(-) create mode 100644 Documentation/zh_CN/magic-number.txt
Documentation/zh_CN/magic-number.txt new file +167 -0
@@ -0,0 +1,167 @@ +Chinese translated version of Documentation/magic-number.txt + +If you have any comment or update to the content, please post to LKML directly. +However, if you have problem communicating in English you can also ask the +Chinese maintainer for help. Contact the Chinese maintainer, if this +translation is outdated or there is problem with translation. + +Chinese maintainer: Jia Wei Wei <[email protected]> +--------------------------------------------------------------------- +Documentation/magic-number.txt的中文翻译 + +如果想评论或更新本文的内容,请直接发信到LKML。如果你使用英文交流有困难的话,也可 +以向中文版维护者求助。如果本翻译更新不及时或者翻译存在问题,请联系中文版维护者。 + +中文版维护者: 贾威威 Jia Wei Wei <[email protected]> +中文版翻译者: 贾威威 Jia Wei Wei <[email protected]> +中文版校译者: 贾威威 Jia Wei Wei <[email protected]> + +以下为正文 +--------------------------------------------------------------------- +这个文件是有关当前使用的魔术值注册表。当你给一个结构添加了一个魔术值,你也应该把这个魔术值添加到这个文件,因为我们最好把用于各种结构的魔术值统一起来。 + +使用魔术值来保护内核数据结构是一个非常好的主意。这就允许你在运行期检查(a)一个结构是否已经被攻击,或者(b)你已经给一个例行程序通过了一个错误的结构。后一种情况特别地有用---特别是当你通过一个空指针指向结构体的时候。tty源码,例如,经常通过特定驱动使用这种方法并且反复地排列特定方面的结构。 + +使用魔术值的方法是在结构的开始处声明的,如下: + +struct tty_ldisc { + int magic; + ... +}; + +当你以后给内核添加增强功能的时候,请遵守这条规则!这样就会节省数不清的调试时间,特别是一些古怪的情况,例如,数组超出范围并且重新写了超出部分。遵守这个规则,这些情况可以被快速地,安全地避免。 + + Theodore Ts'o + 31 Mar 94 + +给当前的Linux 2.1.55添加魔术表。 + + Michael Chastain + <mailto:[email protected]> + 22 Sep 1997 + +现在应该最新的Linux 2.1.112.因为在特性冻结期间,不能在2.2.x前改变任何东西。这些条目被数域所排序。 + + Krzysztof G.Baranowski + <mailto: [email protected]> + 29 Jul 1998 + +更新魔术表到Linux 2.5.45。刚好越过特性冻结,但是有可能还会有一些新的魔术值在2.6.x之前融入到内核中。 + + Petr Baudis + <[email protected]> + 03 Nov 2002 + +更新魔术表到Linux 2.5.74。 + + Fabian Frederick + <[email protected]> + 09 Jul 2003 + +魔术名 地址 结构 所在文件 +=========================================================================== +PG_MAGIC 'P' pg_{read,write}_hdr include/linux/pg.h +CMAGIC 0x0111 user include/linux/a.out.h +MKISS_DRIVER_MAGIC 0x04bf mkiss_channel drivers/net/mkiss.h +RISCOM8_MAGIC 0x0907 riscom_port drivers/char/riscom8.h +SPECIALIX_MAGIC 0x0907 specialix_port drivers/char/specialix_io8.h +HDLC_MAGIC 0x239e n_hdlc drivers/char/n_hdlc.c +APM_BIOS_MAGIC 0x4101 apm_user arch/i386/kernel/apm.c +CYCLADES_MAGIC 0x4359 cyclades_port include/linux/cyclades.h +DB_MAGIC 0x4442 fc_info drivers/net/iph5526_novram.c +DL_MAGIC 0x444d fc_info drivers/net/iph5526_novram.c +FASYNC_MAGIC 0x4601 fasync_struct include/linux/fs.h +FF_MAGIC 0x4646 fc_info drivers/net/iph5526_novram.c +ISICOM_MAGIC 0x4d54 isi_port include/linux/isicom.h +PTY_MAGIC 0x5001 drivers/char/pty.c +PPP_MAGIC 0x5002 ppp include/linux/if_pppvar.h +SERIAL_MAGIC 0x5301 async_struct include/linux/serial.h +SSTATE_MAGIC 0x5302 serial_state include/linux/serial.h +SLIP_MAGIC 0x5302 slip drivers/net/slip.h +STRIP_MAGIC 0x5303 strip drivers/net/strip.c +X25_ASY_MAGIC 0x5303 x25_asy drivers/net/x25_asy.h +SIXPACK_MAGIC 0x5304 sixpack drivers/net/hamradio/6pack.h +AX25_MAGIC 0x5316 ax_disp drivers/net/mkiss.h +ESP_MAGIC 0x53ee esp_struct drivers/char/esp.h +TTY_MAGIC 0x5401 tty_struct include/linux/tty.h +MGSL_MAGIC 0x5401 mgsl_info drivers/char/synclink.c +TTY_DRIVER_MAGIC 0x5402 tty_driver include/linux/tty_driver.h +MGSLPC_MAGIC 0x5402 mgslpc_info drivers/char/pcmcia/synclink_cs.c +TTY_LDISC_MAGIC 0x5403 tty_ldisc include/linux/tty_ldisc.h +USB_SERIAL_MAGIC 0x6702 usb_serial drivers/usb/serial/usb-serial.h +FULL_DUPLEX_MAGIC 0x6969 drivers/net/tulip/de2104x.c +USB_BLUETOOTH_MAGIC 0x6d02 usb_bluetooth drivers/usb/class/bluetty.c +RFCOMM_TTY_MAGIC 0x6d02 net/bluetooth/rfcomm/tty.c +USB_SERIAL_PORT_MAGIC 0x7301 usb_serial_port drivers/usb/serial/usb-serial.h +CG_MAGIC 0x00090255 ufs_cylinder_group include/linux/ufs_fs.h +A2232_MAGIC 0x000a2232 gs_port drivers/char/ser_a2232.h +RPORT_MAGIC 0x00525001 r_port drivers/char/rocket_int.h +LSEMAGIC 0x05091998 lse drivers/fc4/fc.c +GDTIOCTL_MAGIC 0x06030f07 gdth_iowr_str drivers/scsi/gdth_ioctl.h +RIEBL_MAGIC 0x09051990 drivers/net/atarilance.c +RIO_MAGIC 0x12345678 gs_port drivers/char/rio/rio_linux.c +SX_MAGIC 0x12345678 gs_port drivers/char/sx.h +NBD_REQUEST_MAGIC 0x12560953 nbd_request include/linux/nbd.h +RED_MAGIC2 0x170fc2a5 (any) mm/slab.c +BAYCOM_MAGIC 0x19730510 baycom_state drivers/net/baycom_epp.c +ISDN_X25IFACE_MAGIC 0x1e75a2b9 isdn_x25iface_proto_data + drivers/isdn/isdn_x25iface.h +ECP_MAGIC 0x21504345 cdkecpsig include/linux/cdk.h +LSOMAGIC 0x27091997 lso drivers/fc4/fc.c +LSMAGIC 0x2a3b4d2a ls drivers/fc4/fc.c +WANPIPE_MAGIC 0x414C4453 sdla_{dump,exec} include/linux/wanpipe.h +CS_CARD_MAGIC 0x43525553 cs_card sound/oss/cs46xx.c +LABELCL_MAGIC 0x4857434c labelcl_info_s include/asm/ia64/sn/labelcl.h +ISDN_ASYNC_MAGIC 0x49344C01 modem_info include/linux/isdn.h +CTC_ASYNC_MAGIC 0x49344C01 ctc_tty_info drivers/s390/net/ctctty.c +ISDN_NET_MAGIC 0x49344C02 isdn_net_local_s drivers/isdn/i4l/isdn_net_lib.h +SAVEKMSG_MAGIC2 0x4B4D5347 savekmsg arch/*/amiga/config.c +STLI_BOARDMAGIC 0x4bc6c825 stlibrd include/linux/istallion.h +CS_STATE_MAGIC 0x4c4f4749 cs_state sound/oss/cs46xx.c +SLAB_C_MAGIC 0x4f17a36d kmem_cache mm/slab.c +COW_MAGIC 0x4f4f4f4d cow_header_v1 arch/um/drivers/ubd_user.c +I810_CARD_MAGIC 0x5072696E i810_card sound/oss/i810_audio.c +TRIDENT_CARD_MAGIC 0x5072696E trident_card sound/oss/trident.c +ROUTER_MAGIC 0x524d4157 wan_device include/linux/wanrouter.h +SCC_MAGIC 0x52696368 gs_port drivers/char/scc.h +SAVEKMSG_MAGIC1 0x53415645 savekmsg arch/*/amiga/config.c +GDA_MAGIC 0x58464552 gda arch/mips/include/asm/sn/gda.h +RED_MAGIC1 0x5a2cf071 (any) mm/slab.c +STL_PORTMAGIC 0x5a7182c9 stlport include/linux/stallion.h +EEPROM_MAGIC_VALUE 0x5ab478d2 lanai_dev drivers/atm/lanai.c +HDLCDRV_MAGIC 0x5ac6e778 hdlcdrv_state include/linux/hdlcdrv.h +EPCA_MAGIC 0x5c6df104 channel include/linux/epca.h +PCXX_MAGIC 0x5c6df104 channel drivers/char/pcxx.h +KV_MAGIC 0x5f4b565f kernel_vars_s arch/mips/include/asm/sn/klkernvars.h +I810_STATE_MAGIC 0x63657373 i810_state sound/oss/i810_audio.c +TRIDENT_STATE_MAGIC 0x63657373 trient_state sound/oss/trident.c +M3_CARD_MAGIC 0x646e6f50 m3_card sound/oss/maestro3.c +FW_HEADER_MAGIC 0x65726F66 fw_header drivers/atm/fore200e.h +SLOT_MAGIC 0x67267321 slot drivers/hotplug/cpqphp.h +SLOT_MAGIC 0x67267322 slot drivers/hotplug/acpiphp.h +LO_MAGIC 0x68797548 nbd_device include/linux/nbd.h +OPROFILE_MAGIC 0x6f70726f super_block drivers/oprofile/oprofilefs.h +M3_STATE_MAGIC 0x734d724d m3_state sound/oss/maestro3.c +STL_PANELMAGIC 0x7ef621a1 stlpanel include/linux/stallion.h +VMALLOC_MAGIC 0x87654320 snd_alloc_track sound/core/memory.c +KMALLOC_MAGIC 0x87654321 snd_alloc_track sound/core/memory.c +PWC_MAGIC 0x89DC10AB pwc_device drivers/usb/media/pwc.h +NBD_REPLY_MAGIC 0x96744668 nbd_reply include/linux/nbd.h +STL_BOARDMAGIC 0xa2267f52 stlbrd include/linux/stallion.h +ENI155_MAGIC 0xa54b872d midway_eprom drivers/atm/eni.h +SCI_MAGIC 0xbabeface gs_port drivers/char/sh-sci.h +CODA_MAGIC 0xC0DAC0DA coda_file_info include/linux/coda_fs_i.h +DPMEM_MAGIC 0xc0ffee11 gdt_pci_sram drivers/scsi/gdth.h +STLI_PORTMAGIC 0xe671c7a1 stliport include/linux/istallion.h +YAM_MAGIC 0xF10A7654 yam_port drivers/net/hamradio/yam.c +CCB_MAGIC 0xf2691ad2 ccb drivers/scsi/ncr53c8xx.c +QUEUE_MAGIC_FREE 0xf7e1c9a3 queue_entry drivers/scsi/arm/queue.c +QUEUE_MAGIC_USED 0xf7e1cc33 queue_entry drivers/scsi/arm/queue.c +HTB_CMAGIC 0xFEFAFEF1 htb_class net/sched/sch_htb.c +NMI_MAGIC 0x48414d4d455201 nmi_s arch/mips/include/asm/sn/nmi.h + +请注意,在声音记忆管理中仍然有每一些被定义的驱动魔术值。查看include/sound/sndmagic.h来获取他们完整的列表信息。很多OSS声音驱动拥有自己从声卡PCI ID构建的魔术值-他们也没有被列在这里。 + +IrDA子系统也使用了大量的自己的魔术值,查看include/net/irda/irda.h来获取他们完整的信息。 + +HFS是另外一个比较大的使用魔术值的文件系统-你可以在fs/hfs/hfs.h中找到他们。
Signature · 1 line
1.7.4.1
PATCH 32/50 Driver core: convert platform_{get,set}_drvdata to static inline functions
In reply to Greg Kroah-HartmanFrom: Marc Kleine-Budde <[email protected]>
This patch converts the macros for platform_{get,set}_drvdata to static inline functions to add typechecking.
--- include/linux/platform_device.h | 11 +++++++++-- 1 files changed, 9 insertions(+), 2 deletions(-)
include/linux/platform_device.h +9 -2
@@ -130,8 +130,15 @@ extern void platform_driver_unregister(struct platform_driver *);extern int platform_driver_probe (struct platform_driver *driver,int (*probe)(struct platform_device *)); -#define platform_get_drvdata (_dev) dev_get_drvdata(&(_dev)->dev) -#define platform_set_drvdata (_dev,data) dev_set_drvdata(&(_dev)->dev, (data)) +static inline void *platform_get_drvdata (const struct platform_device *pdev) +{ +return dev_get_drvdata (&pdev->dev); +} + +static inline void platform_set_drvdata (struct platform_device *pdev,void *data) +{ +dev_set_drvdata (&pdev->dev, data); +} extern struct platform_device *platform_create_bundle(struct platform_driver *driver, int (*probe)(struct platform_device *),
Signature · 1 line
1.7.4.1
PATCH 33/50 firmware: Add DMI entry types to the headers
In reply to Greg Kroah-HartmanFrom: Mike Waychison <[email protected]>
In preparation for the upcoming commits, introduce the DMI entry types to the headers. These type names are based on those specified in the DMTF SMBIOS specification version 2.7.1.
--- include/linux/dmi.h | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 47 insertions(+), 0 deletions(-)
include/linux/dmi.h +47 -0
@@ -23,6 +23,53 @@ enum dmi_device_type { DMI_DEV_TYPE_DEV_ONBOARD = -3, }; +enum dmi_entry_type { +DMI_ENTRY_BIOS =0 , +DMI_ENTRY_SYSTEM , +DMI_ENTRY_BASEBOARD , +DMI_ENTRY_CHASSIS , +DMI_ENTRY_PROCESSOR , +DMI_ENTRY_MEM_CONTROLLER , +DMI_ENTRY_MEM_MODULE , +DMI_ENTRY_CACHE , +DMI_ENTRY_PORT_CONNECTOR , +DMI_ENTRY_SYSTEM_SLOT , +DMI_ENTRY_ONBOARD_DEVICE , +DMI_ENTRY_OEMSTRINGS , +DMI_ENTRY_SYSCONF , +DMI_ENTRY_BIOS_LANG , +DMI_ENTRY_GROUP_ASSOC , +DMI_ENTRY_SYSTEM_EVENT_LOG , +DMI_ENTRY_PHYS_MEM_ARRAY , +DMI_ENTRY_MEM_DEVICE , +DMI_ENTRY_32_MEM_ERROR , +DMI_ENTRY_MEM_ARRAY_MAPPED_ADDR , +DMI_ENTRY_MEM_DEV_MAPPED_ADDR , +DMI_ENTRY_BUILTIN_POINTING_DEV , +DMI_ENTRY_PORTABLE_BATTERY , +DMI_ENTRY_SYSTEM_RESET , +DMI_ENTRY_HW_SECURITY , +DMI_ENTRY_SYSTEM_POWER_CONTROLS , +DMI_ENTRY_VOLTAGE_PROBE , +DMI_ENTRY_COOLING_DEV , +DMI_ENTRY_TEMP_PROBE , +DMI_ENTRY_ELECTRICAL_CURRENT_PROBE , +DMI_ENTRY_OOB_REMOTE_ACCESS , +DMI_ENTRY_BIS_ENTRY , +DMI_ENTRY_SYSTEM_BOOT , +DMI_ENTRY_MGMT_DEV , +DMI_ENTRY_MGMT_DEV_COMPONENT , +DMI_ENTRY_MGMT_DEV_THRES , +DMI_ENTRY_MEM_CHANNEL , +DMI_ENTRY_IPMI_DEV , +DMI_ENTRY_SYS_POWER_SUPPLY , +DMI_ENTRY_ADDITIONAL , +DMI_ENTRY_ONBOARD_DEV_EXT , +DMI_ENTRY_MGMT_CONTROLLER_HOST , +DMI_ENTRY_INACTIVE =126 , +DMI_ENTRY_END_OF_TABLE =127 , +}; +struct dmi_header {u8 type;u8 length;
Signature · 1 line
1.7.4.1
PATCH 34/50 firmware: Basic dmi-sysfs support
In reply to Greg Kroah-HartmanFrom: Mike Waychison <[email protected]>
Introduce a new module "dmi-sysfs" that exports the broken out entries of the DMI table through sysfs.
Entries are enumerated via dmi_walk() on module load, and are populated as kobjects rooted at /sys/firmware/dmi/entries.
Entries are named "<type>-<instance>", where:
<type> : is the type of the entry, and
<instance> : is the ordinal count within the DMI table of that
entry type. This instance is used in lieu the DMI entry's handle as no assurances are made by the kernel that handles are unique.
All entries export the following attributes:
length : The length of the formatted portion of the entry
handle : The handle given to this entry by the firmware
raw : The raw bytes of the entire entry, including the
formatted portion, the unformatted (strings) portion, and the two terminating nul characters.
type : The DMI entry type
instance : The ordinal instance of this entry given its type.
position : The position ordinal of the entry within the table in
its entirety.
Entries in dmi-sysfs are kobject backed members called "struct dmi_sysfs_entry" and belong to dmi_kset. They are threaded through entry_list (protected by entry_list_lock) so that we can find them at cleanup time.
--- drivers/firmware/Kconfig | 11 ++ drivers/firmware/Makefile | 1 + drivers/firmware/dmi-sysfs.c | 396 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 408 insertions(+), 0 deletions(-) create mode 100644 drivers/firmware/dmi-sysfs.c
drivers/firmware/Kconfig +11 -0
@@ -113,6 +113,17 @@ config DMIID information from userspace through /sys/class/dmi/id/ or if you want DMI-based module auto-loading. +config DMI_SYSFS + tristate "DMI table support in sysfs" + depends on SYSFS && DMI + default n + help + Say Y or M here to enable the exporting of the raw DMI table + data via sysfs. This is useful for consuming the data without + requiring any access to /dev/mem at all. Tables are found + under /sys/firmware/dmi when this option is enabled and + loaded. + config ISCSI_IBFT_FIND bool "iSCSI Boot Firmware Table Attributes" depends on X86
drivers/firmware/Makefile +1 -0
@@ -2,6 +2,7 @@ # Makefile for the linux kernel. # obj-$(CONFIG_DMI) += dmi_scan.o +obj-$(CONFIG_DMI_SYSFS) += dmi-sysfs.o obj-$(CONFIG_EDD) += edd.o obj-$(CONFIG_EFI_VARS) += efivars.o obj-$(CONFIG_EFI_PCDP) += pcdp.o
drivers/firmware/dmi-sysfs.c new file +396 -0
396 lines not on this page · raw message
Signature · 1 line
1.7.4.1
PATCH 35/50 firmware: Break out system_event_log in dmi-sysfs
In reply to Greg Kroah-HartmanFrom: Mike Waychison <[email protected]>
The optional type 15 entry of the DMI table describes a non-volatile storage-backed system event log.
In preparation for the next commit which exposes the raw bits of the event log to userland, create a new sub-directory within the dmi entry called "system_event_log" and expose attribute files that describe the event log itself.
Currently, only a single child object is permitted within a dmi_sysfs_entry. We simply point at this child from the dmi_sysfs_entry if it exists.
--- drivers/firmware/dmi-sysfs.c | 159 ++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 159 insertions(+), 0 deletions(-)
drivers/firmware/dmi-sysfs.c +159 -0
@@ -35,6 +35,7 @@ struct dmi_sysfs_entry {int instance;int position;struct list_head list; +struct kobject *child; };/*
@@ -77,6 +78,10 @@ struct dmi_sysfs_mapped_attribute dmi_sysfs_attr_##_entry##_##_name = { \/************************************************* * Generic DMI entry support. *************************************************/ +static void dmi_entry_free (struct kobject *kobj) +{ +kfree (kobj); +}static struct dmi_sysfs_entry *to_entry (struct kobject *kobj) {
@@ -186,6 +191,146 @@ static size_t dmi_entry_length(const struct dmi_header *dh) }/************************************************* +* Support bits for specialized DMI entry support +*************************************************/ +struct dmi_entry_attr_show_data { +struct attribute *attr; +char *buf; +}; + +static ssize_t dmi_entry_attr_show_helper (struct dmi_sysfs_entry *entry, +const struct dmi_header *dh, +void *_data) +{ +struct dmi_entry_attr_show_data *data = _data; +struct dmi_sysfs_mapped_attribute *attr; + + attr =container_of (data->attr, + struct dmi_sysfs_mapped_attribute, attr); +return attr->show (entry, dh, data->buf); +} + +static ssize_t dmi_entry_attr_show (struct kobject *kobj, +struct attribute *attr, +char *buf) +{ +struct dmi_entry_attr_show_data data = { + .attr = attr, + .buf = buf, + }; +/* Find the entry according to our parent and call the +* normalized show method hanging off of the attribute */ +return find_dmi_entry (to_entry (kobj->parent), + dmi_entry_attr_show_helper, &data); +} + +static const struct sysfs_ops dmi_sysfs_specialize_attr_ops = { + .show = dmi_entry_attr_show, +}; + +/************************************************* +* Specialized DMI entry support. +*************************************************/ + +/*** Type 15 - System Event Table ***/ + +#define DMI_SEL_ACCESS_METHOD_IO8 0x00 +#define DMI_SEL_ACCESS_METHOD_IO2x8 0x01 +#define DMI_SEL_ACCESS_METHOD_IO16 0x02 +#define DMI_SEL_ACCESS_METHOD_PHYS32 0x03 +#define DMI_SEL_ACCESS_METHOD_GPNV 0x04 + +struct dmi_system_event_log { +struct dmi_header header; +u16 area_length; +u16 header_start_offset; +u16 data_start_offset; +u8 access_method; +u8 status; +u32 change_token; +union { +struct { +u16 index_addr; +u16 data_addr; + } io; +u32 phys_addr32; +u16 gpnv_handle; +u32 access_method_address; + }; +u8 header_format; +u8 type_descriptors_supported_count; +u8 per_log_type_descriptor_length; +u8 supported_log_type_descriptos[0 ]; +} __packed; + +static const struct dmi_system_event_log *to_sel (const struct dmi_header *dh) +{ +return (const struct dmi_system_event_log *)dh; +} + +#define DMI_SYSFS_SEL_FIELD (_field) \ +static ssize_t dmi_sysfs_sel_##_field(struct dmi_sysfs_entry *entry, \ + const struct dmi_header *dh, \ + char *buf) \ +{ \ + const struct dmi_system_event_log *sel = to_sel(dh); \ + if (sizeof(*sel) > dmi_entry_length(dh)) \ + return -EIO; \ + return sprintf(buf, "%u\n", sel->_field); \ +} \ +static DMI_SYSFS_MAPPED_ATTR(sel, _field) + +DMI_SYSFS_SEL_FIELD (area_length); +DMI_SYSFS_SEL_FIELD (header_start_offset); +DMI_SYSFS_SEL_FIELD (data_start_offset); +DMI_SYSFS_SEL_FIELD (access_method); +DMI_SYSFS_SEL_FIELD (status); +DMI_SYSFS_SEL_FIELD (change_token); +DMI_SYSFS_SEL_FIELD (access_method_address); +DMI_SYSFS_SEL_FIELD (header_format); +DMI_SYSFS_SEL_FIELD (type_descriptors_supported_count); +DMI_SYSFS_SEL_FIELD (per_log_type_descriptor_length); + +static struct attribute *dmi_sysfs_sel_attrs[] = { + &dmi_sysfs_attr_sel_area_length.attr, + &dmi_sysfs_attr_sel_header_start_offset.attr, + &dmi_sysfs_attr_sel_data_start_offset.attr, + &dmi_sysfs_attr_sel_access_method.attr, + &dmi_sysfs_attr_sel_status.attr, + &dmi_sysfs_attr_sel_change_token.attr, + &dmi_sysfs_attr_sel_access_method_address.attr, + &dmi_sysfs_attr_sel_header_format.attr, + &dmi_sysfs_attr_sel_type_descriptors_supported_count.attr, + &dmi_sysfs_attr_sel_per_log_type_descriptor_length.attr, +NULL , +}; + + +static struct kobj_type dmi_system_event_log_ktype = { + .release = dmi_entry_free, + .sysfs_ops = &dmi_sysfs_specialize_attr_ops, + .default_attrs = dmi_sysfs_sel_attrs, +}; + +static int dmi_system_event_log (struct dmi_sysfs_entry *entry) +{ +int ret; + + entry->child =kzalloc (sizeof (*entry->child),GFP_KERNEL ); +if (!entry->child) +return -ENOMEM ; + ret =kobject_init_and_add (entry->child, + &dmi_system_event_log_ktype, + &entry->kobj, +"system_event_log" ); +if (ret) + goto out_free; +out_free: +kfree (entry->child); +return ret; +} + +/************************************************* * Generic DMI entry support. *************************************************/
@@ -325,6 +470,18 @@ static void __init dmi_sysfs_register_handle(const struct dmi_header *dh,list_add_tail (&entry->list, &entry_list);spin_unlock (&entry_list_lock); +/* Handle specializations by type */ +switch (dh->type) { +case DMI_ENTRY_SYSTEM_EVENT_LOG : + *ret =dmi_system_event_log (entry); +break ; +default : +/* No specialization */ +break ; + } +if (*ret) + goto out_err; +/* Create the raw binary file to access the entry */ *ret =sysfs_create_bin_file (&entry->kobj, &dmi_entry_raw_attr);if (*ret)
@@ -332,6 +489,7 @@ static void __init dmi_sysfs_register_handle(const struct dmi_header *dh,return ; out_err: +kobject_put (entry->child);kobject_put (&entry->kobj);return ; }
@@ -342,6 +500,7 @@ static void cleanup_entry_list(void)/* No locks, we are on our way out */ list_for_each_entry_safe (entry, next, &entry_list, list) { +kobject_put (entry->child);kobject_put (&entry->kobj); } }
Signature · 1 line
1.7.4.1
PATCH 36/50 firmware: Expose DMI type 15 System Event Log
In reply to Greg Kroah-HartmanFrom: Mike Waychison <[email protected]>
The System Event Log described by DMI entry type 15 may be backed by either memory or may be indirectly accessed via an IO index/data register pair.
In order to get read access to this log, expose it in the "system_event_log" sub-directory of type 15 DMI entries, ie:/sys/firmware/dmi/entries/15-0/system_event_log/raw_event_log.
This commit handles both IO accessed and memory access system event logs. OEM specific access and GPNV support is explicitly not handled and we error out in the logs when we do not recognize the access method.
--- drivers/firmware/dmi-sysfs.c | 143 ++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 143 insertions(+), 0 deletions(-)
drivers/firmware/dmi-sysfs.c +143 -0
@@ -312,6 +312,140 @@ static struct kobj_type dmi_system_event_log_ktype = { .default_attrs = dmi_sysfs_sel_attrs, }; +typedef u8 (*sel_io_reader )(const struct dmi_system_event_log *sel, +loff_t offset); + +static DEFINE_MUTEX (io_port_lock); + +static u8 read_sel_8bit_indexed_io (const struct dmi_system_event_log *sel, +loff_t offset) +{ +u8 ret; + +mutex_lock (&io_port_lock); +outb ((u8 )offset, sel->io.index_addr); + ret =inb (sel->io.data_addr); +mutex_unlock (&io_port_lock); +return ret; +} + +static u8 read_sel_2x8bit_indexed_io (const struct dmi_system_event_log *sel, +loff_t offset) +{ +u8 ret; + +mutex_lock (&io_port_lock); +outb ((u8 )offset, sel->io.index_addr); +outb ((u8)(offset >>8 ), sel->io.index_addr +1 ); + ret =inb (sel->io.data_addr); +mutex_unlock (&io_port_lock); +return ret; +} + +static u8 read_sel_16bit_indexed_io (const struct dmi_system_event_log *sel, +loff_t offset) +{ +u8 ret; + +mutex_lock (&io_port_lock); +outw ((u16 )offset, sel->io.index_addr); + ret =inb (sel->io.data_addr); +mutex_unlock (&io_port_lock); +return ret; +} + +static sel_io_reader sel_io_readers[] = { + [DMI_SEL_ACCESS_METHOD_IO8 ] = read_sel_8bit_indexed_io, + [DMI_SEL_ACCESS_METHOD_IO2x8] = read_sel_2x8bit_indexed_io, + [DMI_SEL_ACCESS_METHOD_IO16 ] = read_sel_16bit_indexed_io, +}; + +static ssize_t dmi_sel_raw_read_io (struct dmi_sysfs_entry *entry, +const struct dmi_system_event_log *sel, +char *buf,loff_t pos,size_t count) +{ +ssize_t wrote =0 ; + +sel_io_reader io_reader = sel_io_readers[sel->access_method]; + +while (count && pos < sel->area_length) { + count--; + *(buf++) =io_reader (sel, pos++); + wrote++; + } + +return wrote; +} + +static ssize_t dmi_sel_raw_read_phys32 (struct dmi_sysfs_entry *entry, +const struct dmi_system_event_log *sel, +char *buf,loff_t pos,size_t count) +{ +u8 __iomem *mapped; +ssize_t wrote =0 ; + + mapped =ioremap (sel->access_method_address, sel->area_length); +if (!mapped) +return -EIO ; + +while (count && pos < sel->area_length) { + count--; + *(buf++) =readb (mapped + pos++); + wrote++; + } + +iounmap (mapped); +return wrote; +} + +static ssize_t dmi_sel_raw_read_helper (struct dmi_sysfs_entry *entry, +const struct dmi_header *dh, +void *_state) +{ +struct dmi_read_state *state = _state; +const struct dmi_system_event_log *sel =to_sel (dh); + +if (sizeof (*sel) >dmi_entry_length (dh)) +return -EIO ; + +switch (sel->access_method) { +case DMI_SEL_ACCESS_METHOD_IO8 : +case DMI_SEL_ACCESS_METHOD_IO2x8: +case DMI_SEL_ACCESS_METHOD_IO16 : +return dmi_sel_raw_read_io (entry, sel, state->buf, + state->pos, state->count); +case DMI_SEL_ACCESS_METHOD_PHYS32 : +return dmi_sel_raw_read_phys32 (entry, sel, state->buf, + state->pos, state->count); +case DMI_SEL_ACCESS_METHOD_GPNV : +pr_info ("dmi-sysfs: GPNV support missing.\n" ); +return -EIO ; +default : +pr_info ("dmi-sysfs: Unknown access method %02x\n" , + sel->access_method); +return -EIO ; + } +} + +static ssize_t dmi_sel_raw_read (struct file *filp,struct kobject *kobj, +struct bin_attribute *bin_attr, +char *buf,loff_t pos,size_t count) +{ +struct dmi_sysfs_entry *entry =to_entry (kobj->parent); +struct dmi_read_state state = { + .buf = buf, + .pos = pos, + .count = count, + }; + +return find_dmi_entry (entry, dmi_sel_raw_read_helper, &state); +} + +static struct bin_attribute dmi_sel_raw_attr = { + .attr = {.name ="raw_event_log" , .mode =0400 }, + .read = dmi_sel_raw_read, +}; +static int dmi_system_event_log (struct dmi_sysfs_entry *entry) {int ret;
@@ -325,6 +459,15 @@ static int dmi_system_event_log(struct dmi_sysfs_entry *entry) "system_event_log");if (ret) goto out_free; + + ret =sysfs_create_bin_file (entry->child, &dmi_sel_raw_attr); +if (ret) + goto out_del; + +return 0 ; + +out_del: +kobject_del (entry->child); out_free:kfree (entry->child);return ret;
Signature · 1 line
1.7.4.1
PATCH 37/50 firmware: Add documentation for /sys/firmware/dmi
In reply to Greg Kroah-HartmanFrom: Mike Waychison <[email protected]>
Document the new ABI added by the dmi-sysfs module.
--- Documentation/ABI/testing/sysfs-firmware-dmi | 110 ++++++++++++++++++++++++++ 1 files changed, 110 insertions(+), 0 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-firmware-dmi
Documentation/ABI/testing/sysfs-firmware-dmi new file +110 -0
@@ -0,0 +1,110 @@ +What: /sys/firmware/dmi/ +Date: February 2011 +Contact: Mike Waychison <[email protected]> +Description: + Many machines' firmware (x86 and ia64) export DMI / + SMBIOS tables to the operating system. Getting at this + information is often valuable to userland, especially in + cases where there are OEM extensions used. + + The kernel itself does not rely on the majority of the + information in these tables being correct. It equally + cannot ensure that the data as exported to userland is + without error either. + + DMI is structured as a large table of entries, where + each entry has a common header indicating the type and + length of the entry, as well as 'handle' that is + supposed to be unique amongst all entries. + + Some entries are required by the specification, but many + others are optional. In general though, users should + never expect to find a specific entry type on their + system unless they know for certain what their firmware + is doing. Machine to machine will vary. + + Multiple entries of the same type are allowed. In order + to handle these duplicate entry types, each entry is + assigned by the operating system an 'instance', which is + derived from an entry type's ordinal position. That is + to say, if there are 'N' multiple entries with the same type + 'T' in the DMI tables (adjacent or spread apart, it + doesn't matter), they will be represented in sysfs as + entries "T-0" through "T-(N-1)": + + Example entry directories: + + /sys/firmware/dmi/entries/17-0 + /sys/firmware/dmi/entries/17-1 + /sys/firmware/dmi/entries/17-2 + /sys/firmware/dmi/entries/17-3 + ... + + Instance numbers are used in lieu of the firmware + assigned entry handles as the kernel itself makes no + guarantees that handles as exported are unique, and + there are likely firmware images that get this wrong in + the wild. + + Each DMI entry in sysfs has the common header values + exported as attributes: + + handle : The 16bit 'handle' that is assigned to this + entry by the firmware. This handle may be + referred to by other entries. + length : The length of the entry, as presented in the + entry itself. Note that this is _not the + total count of bytes associated with the + entry_. This value represents the length of + the "formatted" portion of the entry. This + "formatted" region is sometimes followed by + the "unformatted" region composed of nul + terminated strings, with termination signalled + by a two nul characters in series. + raw : The raw bytes of the entry. This includes the + "formatted" portion of the entry, the + "unformatted" strings portion of the entry, + and the two terminating nul characters. + type : The type of the entry. This value is the same + as found in the directory name. It indicates + how the rest of the entry should be + interpreted. + instance: The instance ordinal of the entry for the + given type. This value is the same as found + in the parent directory name. + position: The position of the entry within the entirety + of the entirety. + + === Entry Specialization === + + Some entry types may have other information available in + sysfs. + + --- Type 15 - System Event Log --- + + This entry allows the firmware to export a log of + events the system has taken. This information is + typically backed by nvram, but the implementation + details are abstracted by this table. This entries data + is exported in the directory: + + /sys/firmware/dmi/entries/15-0/system_event_log + + and has the following attributes (documented in the + SMBIOS / DMI specification under "System Event Log (Type 15)": + + area_length + header_start_offset + data_start_offset + access_method + status + change_token + access_method_address + header_format + per_log_type_descriptor_length + type_descriptors_supported_count + + As well, the kernel exports the binary attribute: + + raw_event_log : The raw binary bits of the event log + as described by the DMI entry.
Signature · 1 line
1.7.4.1
Re: [PATCH 37/50] firmware: Add documentation for /sys/firmware/dmi
Documentation/ABI/testing/sysfs-firmware-dmi line 76
Quoted 6 lines · Greg Kroah-Hartman
From: Mike Waychison <[email protected]>
Document the new ABI added by the dmi-sysfs module.
Documentation/ABI/testing/sysfs-firmware-dmi new file +2
-0+ position: The position of the entry within the entirety + of the entirety.
Say what? :)
PATCH 1/1 firmware: Fix grammar in sysfs-firmware-dmi doc
Fix the grammar in describing the position attribute of DMI entries in the dmi-sysfs module. While here, make a couple other small clarifying fixups to the docs.
--- Documentation/ABI/testing/sysfs-firmware-dmi | 18 +++++++++--------- 1 files changed, 9 insertions(+), 9 deletions(-)
Documentation/ABI/testing/sysfs-firmware-dmi +9 -9
@@ -14,14 +14,15 @@ Description: DMI is structured as a large table of entries, where each entry has a common header indicating the type and - length of the entry, as well as 'handle' that is - supposed to be unique amongst all entries. + length of the entry, as well as a firmware-provided + 'handle' that is supposed to be unique amongst all + entries. Some entries are required by the specification, but many others are optional. In general though, users should never expect to find a specific entry type on their system unless they know for certain what their firmware - is doing. Machine to machine will vary. + is doing. Machine to machine experiences will vary. Multiple entries of the same type are allowed. In order to handle these duplicate entry types, each entry is
@@ -67,25 +68,24 @@ Description: and the two terminating nul characters. type : The type of the entry. This value is the same as found in the directory name. It indicates - how the rest of the entry should be - interpreted. + how the rest of the entry should be interpreted. instance: The instance ordinal of the entry for the given type. This value is the same as found in the parent directory name. - position: The position of the entry within the entirety - of the entirety. + position: The ordinal position (zero-based) of the entry + within the entirety of the DMI entry table. === Entry Specialization === Some entry types may have other information available in - sysfs. + sysfs. Not all types are specialized. --- Type 15 - System Event Log --- This entry allows the firmware to export a log of events the system has taken. This information is typically backed by nvram, but the implementation - details are abstracted by this table. This entries data + details are abstracted by this table. This entry's data is exported in the directory: /sys/firmware/dmi/entries/15-0/system_event_log
Signature · 1 line
1.7.3.1
PATCH 38/50 firmware: Fix unaligned memory accesses in dmi-sysfs
In reply to Greg Kroah-HartmanFrom: Mike Waychison <[email protected]>
DMI entries are arranged in memory back to back with no alignment guarantees. This means that the struct dmi_header passed to callbacks from dmi_walk() itself isn't byte aligned. This causes problems on architectures that expect aligned data, such as IA64.
The dmi-sysfs patchset introduced structure member accesses through this passed in dmi_header. Fix this by memcpy()ing the structures to temporary locations on stack when inspecting/copying them.
--- drivers/firmware/dmi-sysfs.c | 28 +++++++++++++--------------- 1 files changed, 13 insertions(+), 15 deletions(-)
drivers/firmware/dmi-sysfs.c +13 -15
@@ -263,20 +263,16 @@ struct dmi_system_event_log {u8 supported_log_type_descriptos[0 ]; } __packed; -static const struct dmi_system_event_log *to_sel (const struct dmi_header *dh) -{ -return (const struct dmi_system_event_log *)dh; -} -#define DMI_SYSFS_SEL_FIELD (_field) \ static ssize_t dmi_sysfs_sel_##_field(struct dmi_sysfs_entry *entry, \ const struct dmi_header *dh, \ char *buf) \ { \ - const struct dmi_system_event_log *sel = to_sel(dh); \ - if (sizeof(*sel) > dmi_entry_length(dh)) \ + struct dmi_system_event_log sel; \ + if (sizeof(sel) > dmi_entry_length(dh)) \ return -EIO; \ - return sprintf(buf, "%u\n", sel->_field); \ + memcpy(&sel, dh, sizeof(sel)); \ + return sprintf(buf, "%u\n", sel._field); \ } \ static DMI_SYSFS_MAPPED_ATTR(sel, _field)
@@ -403,26 +399,28 @@ static ssize_t dmi_sel_raw_read_helper(struct dmi_sysfs_entry *entry, void *_state) {struct dmi_read_state *state = _state; -const struct dmi_system_event_log *sel =to_sel (dh); +struct dmi_system_event_log sel; -if (sizeof (*sel) >dmi_entry_length (dh)) +if (sizeof (sel) >dmi_entry_length (dh))return -EIO ; -switch (sel->access_method) { +memcpy (&sel, dh,sizeof (sel)); + +switch (sel.access_method) {case DMI_SEL_ACCESS_METHOD_IO8 :case DMI_SEL_ACCESS_METHOD_IO2x8:case DMI_SEL_ACCESS_METHOD_IO16 : -return dmi_sel_raw_read_io (entry, sel, state->buf, +return dmi_sel_raw_read_io (entry, &sel, state->buf, state->pos, state->count);case DMI_SEL_ACCESS_METHOD_PHYS32 : -return dmi_sel_raw_read_phys32 (entry, sel, state->buf, +return dmi_sel_raw_read_phys32 (entry, &sel, state->buf, state->pos, state->count);case DMI_SEL_ACCESS_METHOD_GPNV :pr_info ("dmi-sysfs: GPNV support missing.\n" );return -EIO ;default :pr_info ("dmi-sysfs: Unknown access method %02x\n" , - sel->access_method); + sel.access_method);return -EIO ; } }
@@ -595,7 +593,7 @@ static void __init dmi_sysfs_register_handle(const struct dmi_header *dh, }/* Set the key */ - entry->dh = *dh; +memcpy (&entry->dh, dh,sizeof (*dh)); entry->instance = instance_counts[dh->type]++; entry->position = position_count++;
Signature · 1 line
1.7.4.1
PATCH 39/50 Fix spelling mistakes in Documentation/zh_CN/SubmittingPatches
In reply to Greg Kroah-HartmanFrom: Xiaochen Wang <[email protected]>
This patch fixes a spelling mistake in Documentation/zh_CN/SubmittingPatches.
--- Documentation/zh_CN/SubmittingPatches | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
Documentation/zh_CN/SubmittingPatches +1 -1
@@ -230,7 +230,7 @@ pref("mailnews.display.disable_format_flowed_support", true); 些原因,修正错误,重新提交更新后的改动,是你自己的工作。 Linus不给出任何评论就“丢弃”你的补丁是常见的事情。在系统中这样的事情很 -平常。如果他没有接受你的补丁,也许是由于以下原本: +平常。如果他没有接受你的补丁,也许是由于以下原因: * 你的补丁不能在最新版本的内核上干净的打上。 * 你的补丁在 linux-kernel 邮件列表中没有得到充分的讨论。 * 风格问题(参照第2小节)
Signature · 1 line
1.7.4.1
PATCH 40/50 UIO: add PRUSS UIO driver support
In reply to Greg Kroah-HartmanFrom: Pratheesh Gangadhar <[email protected]>
This patch implements PRUSS (Programmable Real-time Unit Sub System) UIO driver which exports SOC resources associated with PRUSS like I/O, memories and IRQs to user space. PRUSS is dual 32-bit RISC processors which is efficient in performing embedded tasks that require manipulation of packed memory mapped data structures and handling system events that have tight real time constraints. This driver is currently supported on Texas Instruments DA850, AM18xx and OMAP-L138 devices.
For example, PRUSS runs firmware for real-time critical industrial communication data link layer and communicates with application stack running in user space via shared memory and IRQs.
--- drivers/uio/Kconfig | 17 ++ drivers/uio/Makefile | 1 + drivers/uio/uio_pruss.c | 247 +++++++++++++++++++++++++++++++ include/linux/platform_data/uio_pruss.h | 25 +++ 4 files changed, 290 insertions(+), 0 deletions(-) create mode 100644 drivers/uio/uio_pruss.c create mode 100644 include/linux/platform_data/uio_pruss.h
drivers/uio/Kconfig +17 -0
@@ -94,4 +94,21 @@ config UIO_NETX To compile this driver as a module, choose M here; the module will be called uio_netx. +config UIO_PRUSS + tristate "Texas Instruments PRUSS driver" + depends on ARCH_DAVINCI_DA850 + help + PRUSS driver for OMAPL138/DA850/AM18XX devices + PRUSS driver requires user space components, examples and user space + driver is available from below SVN repo - you may use anonymous login + + https://gforge.ti.com/gf/project/pru_sw/ + + More info on API is available at below wiki + + http://processors.wiki.ti.com/index.php/PRU_Linux_Application_Loader + + To compile this driver as a module, choose M here: the module + will be called uio_pruss. + endif
drivers/uio/Makefile +1 -0
@@ -6,3 +6,4 @@ obj-$(CONFIG_UIO_AEC) += uio_aec.o obj-$(CONFIG_UIO_SERCOS3) += uio_sercos3.o obj-$(CONFIG_UIO_PCI_GENERIC) += uio_pci_generic.o obj-$(CONFIG_UIO_NETX) += uio_netx.o +obj-$(CONFIG_UIO_PRUSS) += uio_pruss.o
drivers/uio/uio_pruss.c new file +247 -0
247 lines not on this page · raw message
include/linux/platform_data/uio_pruss.h new file +25 -0
@@ -0,0 +1,25 @@ +/* +* include/linux/platform_data/uio_pruss.h +* +* Platform data for uio_pruss driver +* +* Copyright (C) 2010-11 Texas Instruments Incorporated - http://www.ti.com/ +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation version 2. +* +* This program is distributed "as is" WITHOUT ANY WARRANTY of any +* kind, whether express or implied; without even the implied warranty +* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#ifndef _UIO_PRUSS_H_ +#define _UIO_PRUSS_H_ + +/* To configure the PRUSS INTC base offset for UIO driver */ +struct uio_pruss_pdata { +u32 pintc_base; +}; +#endif /* _UIO_PRUSS_H_ */
Signature · 1 line
1.7.4.1
PATCH 41/50 kref: Fix typo in kref documentation
In reply to Greg Kroah-HartmanFrom: Javi Merino <[email protected]>
container_of() should refer to the struct created in the example.
--- Documentation/kref.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
Documentation/kref.txt +1 -1
@@ -156,7 +156,7 @@ static struct my_data *get_entry() struct my_data *entry = NULL; mutex_lock(&mutex); if (!list_empty(&q)) { - entry = container_of(q.next, struct my_q_entry, link); + entry = container_of(q.next, struct my_data, link); kref_get(&entry->refcount); } mutex_unlock(&mutex);
Signature · 1 line
1.7.4.1
PATCH 42/50 drivers:misc: ti-st: fix debugging code
In reply to Greg Kroah-HartmanFrom: Pavan Savoy <[email protected]>
debug code in TI-ST driver can be enabled by #defining DEBUG in the first line of the code and in case debugfs is mounted, the 2 entries in /sys/kernel/debug/ti-st/ will also provide useful information.
These 2 were broken because of the recent changes to the parsing logic and the registration mechanism of the protocol drivers, this patch fixes them.
--- drivers/misc/ti-st/st_core.c | 18 ++++-------------- 1 files changed, 4 insertions(+), 14 deletions(-)
drivers/misc/ti-st/st_core.c +4 -14
@@ -475,9 +475,9 @@ void kim_st_list_protocols(struct st_data_s *st_gdata, void *buf) {seq_printf (buf,"[%d]\nBT=%c\nFM=%c\nGPS=%c\n" , st_gdata->protos_registered, - st_gdata->list[ST_BT ] !=NULL ?'R' :'U' , - st_gdata->list[ST_FM ] !=NULL ?'R' :'U' , - st_gdata->list[ST_GPS ] !=NULL ?'R' :'U' ); + st_gdata->list[0x04 ] !=NULL ?'R' :'U' , + st_gdata->list[0x08 ] !=NULL ?'R' :'U' , + st_gdata->list[0x09 ] !=NULL ?'R' :'U' ); }/********************************************************************/
@@ -644,9 +644,6 @@ long st_unregister(struct st_proto_s *proto)long st_write (struct sk_buff *skb) {struct st_data_s *st_gdata; -#ifdef DEBUG -unsigned char chnl_id =ST_MAX_CHANNELS ; -#endif long len;st_kim_ref (&st_gdata,0 );
@@ -655,14 +652,7 @@ long st_write(struct sk_buff *skb)pr_err ("data/tty unavailable to perform write" );return -EINVAL ; } -#ifdef DEBUG /* open-up skb to read the 1st byte */ - chnl_id = skb->data[0 ]; -if (unlikely (st_gdata->list[chnl_id] ==NULL )) { -pr_err (" chnl_id %d not registered, and writing? " , - chnl_id); -return -EINVAL ; - } -#endif +pr_debug ("%d to be written" , skb->len); len = skb->len;
Signature · 1 line
1.7.4.1
PATCH 43/50 efivars: move efivars globals into struct efivars
In reply to Greg Kroah-HartmanFrom: Mike Waychison <[email protected]>
In preparation for abstracting out efivars to be usable by other similar variable services, move the global lock, list and kset into a structure. Later patches will change the scope of 'efivars' and have it be passed by function argument.
--- drivers/firmware/efivars.c | 86 +++++++++++++++++++++++-------------------- 1 files changed, 46 insertions(+), 40 deletions(-)
drivers/firmware/efivars.c +46 -40
@@ -89,16 +89,21 @@ MODULE_DESCRIPTION("sysfs interface to EFI Variables");MODULE_LICENSE ("GPL" );MODULE_VERSION (EFIVARS_VERSION ); -/* -* efivars_lock protects two things: -* 1) efivar_list - adds, removals, reads, writes -* 2) efi.[gs]et_variable() calls. -* It must not be held when creating sysfs entries or calling kmalloc. -* efi.get_next_variable() is only called from efivars_init(), -* which is protected by the BKL, so that path is safe. -*/ -static DEFINE_SPINLOCK (efivars_lock); -static LIST_HEAD (efivar_list); +struct efivars { +/* +* ->lock protects two things: +* 1) ->list - adds, removals, reads, writes +* 2) efi.[gs]et_variable() calls. +* It must not be held when creating sysfs entries or calling kmalloc. +* efi.get_next_variable() is only called from efivars_init(), +* which is protected by the BKL, so that path is safe. +*/ +spinlock_t lock; +struct list_head list; +struct kset *kset; +}; +static struct efivars __efivars; +static struct efivars *efivars = &__efivars;/* * The maximum size of VariableName + Data = 1024
@@ -174,14 +179,14 @@ get_var_data(struct efi_variable *var) {efi_status_t status; -spin_lock (&efivars_lock); +spin_lock (&efivars->lock); var->DataSize =1024 ; status = efi.get_variable (var->VariableName, &var->VendorGuid, &var->Attributes, &var->DataSize, var->Data); -spin_unlock (&efivars_lock); +spin_unlock (&efivars->lock);if (status !=EFI_SUCCESS ) {printk (KERN_WARNING "efivars: get_variable() failed 0x%lx!\n" , status);
@@ -291,14 +296,14 @@ efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count)return -EINVAL ; } -spin_lock (&efivars_lock); +spin_lock (&efivars->lock); status = efi.set_variable (new_var->VariableName, &new_var->VendorGuid, new_var->Attributes, new_var->DataSize, new_var->Data); -spin_unlock (&efivars_lock); +spin_unlock (&efivars->lock);if (status !=EFI_SUCCESS ) { printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n",
@@ -415,12 +420,12 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj,if (!capable (CAP_SYS_ADMIN ))return -EACCES ; -spin_lock (&efivars_lock); +spin_lock (&efivars->lock);/* * Does this variable already exist? */ -list_for_each_entry_safe (search_efivar, n, &efivar_list, list) { +list_for_each_entry_safe (search_efivar, n, &efivars->list, list) { strsize1 =utf8_strsize (search_efivar->var.VariableName,1024 ); strsize2 =utf8_strsize (new_var->VariableName,1024 ); if (strsize1 == strsize2 &&
@@ -433,7 +438,7 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj, } }if (found) { -spin_unlock (&efivars_lock); +spin_unlock (&efivars->lock);return -EINVAL ; }
@@ -447,10 +452,10 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj,if (status !=EFI_SUCCESS ) {printk (KERN_WARNING "efivars: set_variable() failed: status=%lx\n" , status); -spin_unlock (&efivars_lock); +spin_unlock (&efivars->lock);return -EIO ; } -spin_unlock (&efivars_lock); +spin_unlock (&efivars->lock);/* Create the entry in sysfs. Locking is not required here */ status = efivar_create_sysfs_entry(utf8_strsize(new_var->VariableName,
@@ -474,12 +479,12 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj,if (!capable (CAP_SYS_ADMIN ))return -EACCES ; -spin_lock (&efivars_lock); +spin_lock (&efivars->lock);/* * Does this variable already exist? */ -list_for_each_entry_safe (search_efivar, n, &efivar_list, list) { +list_for_each_entry_safe (search_efivar, n, &efivars->list, list) { strsize1 =utf8_strsize (search_efivar->var.VariableName,1024 ); strsize2 =utf8_strsize (del_var->VariableName,1024 ); if (strsize1 == strsize2 &&
@@ -492,7 +497,7 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj, } }if (!found) { -spin_unlock (&efivars_lock); +spin_unlock (&efivars->lock);return -EINVAL ; }/* force the Attributes/DataSize to 0 to ensure deletion */
@@ -508,12 +513,12 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj,if (status !=EFI_SUCCESS ) {printk (KERN_WARNING "efivars: set_variable() failed: status=%lx\n" , status); -spin_unlock (&efivars_lock); +spin_unlock (&efivars->lock);return -EIO ; }list_del (&search_efivar->list);/* We need to release this lock before unregistering. */ -spin_unlock (&efivars_lock); +spin_unlock (&efivars->lock);efivar_unregister (search_efivar);/* It's dead Jim.... */
@@ -572,8 +577,6 @@ static struct attribute_group efi_subsys_attr_group = { .attrs = efi_subsys_attrs, }; - -static struct kset *vars_kset;static struct kobject *efi_kobj;/*
@@ -582,7 +585,7 @@ static struct kobject *efi_kobj;* variable_name_size = number of bytes required to hold * variable_name (not counting the NULL * character at the end. -* efivars_lock is not held on entry or exit. +* efivars->lock is not held on entry or exit. * Returns 1 on failure, 0 on success */ static int
@@ -618,7 +621,7 @@ efivar_create_sysfs_entry(unsigned long variable_name_size, *(short_name +strlen (short_name)) ='-' ;efi_guid_unparse (vendor_guid, short_name +strlen (short_name)); - new_efivar->kobj.kset = vars_kset; + new_efivar->kobj.kset = efivars->kset; i =kobject_init_and_add (&new_efivar->kobj, &efivar_ktype,NULL ,"%s" , short_name);if (i) {
@@ -631,9 +634,9 @@ efivar_create_sysfs_entry(unsigned long variable_name_size,kfree (short_name); short_name =NULL ; -spin_lock (&efivars_lock); -list_add (&new_efivar->list, &efivar_list); -spin_unlock (&efivars_lock); +spin_lock (&efivars->lock); +list_add (&new_efivar->list, &efivars->list); +spin_unlock (&efivars->lock);return 0 ; }
@@ -674,8 +677,11 @@ efivars_init(void) goto out_free; } - vars_kset =kset_create_and_add ("vars" ,NULL , efi_kobj); -if (!vars_kset) { +spin_lock_init (&efivars->lock); +INIT_LIST_HEAD (&efivars->list); + + efivars->kset =kset_create_and_add ("vars" ,NULL , efi_kobj); +if (!efivars->kset) {printk (KERN_ERR "efivars: Subsystem registration failed.\n" ); error = -ENOMEM ; goto out_firmware_unregister;
@@ -712,12 +718,12 @@ efivars_init(void)* Now add attributes to allow creation of new vars * and deletion of existing ones... */ - error =sysfs_create_bin_file (&vars_kset->kobj, + error =sysfs_create_bin_file (&efivars->kset->kobj, &var_subsys_attr_new_var);if (error)printk (KERN_ERR "efivars: unable to create new_var sysfs file" " due to error %d\n" , error); - error =sysfs_create_bin_file (&vars_kset->kobj, + error =sysfs_create_bin_file (&efivars->kset->kobj, &var_subsys_attr_del_var);if (error) printk(KERN_ERR "efivars: unable to create del_var sysfs file"
@@ -730,7 +736,7 @@ efivars_init(void)else goto out_free; -kset_unregister (vars_kset); +kset_unregister (efivars->kset); out_firmware_unregister:kobject_put (efi_kobj);
@@ -746,14 +752,14 @@ efivars_exit(void) {struct efivar_entry *entry, *n; -list_for_each_entry_safe (entry, n, &efivar_list, list) { -spin_lock (&efivars_lock); +list_for_each_entry_safe (entry, n, &efivars->list, list) { +spin_lock (&efivars->lock);list_del (&entry->list); -spin_unlock (&efivars_lock); +spin_unlock (&efivars->lock);efivar_unregister (entry); } -kset_unregister (vars_kset); +kset_unregister (efivars->kset);kobject_put (efi_kobj); }
Signature · 1 line
1.7.4.1
PATCH 44/50 efivars: Make efivars bin_attributes dynamic
In reply to Greg Kroah-HartmanFrom: Mike Waychison <[email protected]>
In preparation for encapsulating efivars, we need to have the bin_attributes be dynamically allocated so that we can use their ->private fields to get back to the struct efivars structure.
--- drivers/firmware/efivars.c | 93 ++++++++++++++++++++++++++++++++------------ 1 files changed, 68 insertions(+), 25 deletions(-)
drivers/firmware/efivars.c +68 -25
@@ -101,6 +101,7 @@ struct efivars {spinlock_t lock;struct list_head list;struct kset *kset; +struct bin_attribute *new_var, *del_var; };static struct efivars __efivars;static struct efivars *efivars = &__efivars;
@@ -525,16 +526,6 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj,return count; } -static struct bin_attribute var_subsys_attr_new_var = { - .attr = {.name ="new_var" , .mode =0200 }, - .write = efivar_create, -}; - -static struct bin_attribute var_subsys_attr_del_var = { - .attr = {.name ="del_var" , .mode =0200 }, - .write = efivar_delete, -}; -/* * Let's not leave out systab information that snuck into * the efivars driver
@@ -640,6 +631,66 @@ efivar_create_sysfs_entry(unsigned long variable_name_size,return 0 ; } + +static int +create_efivars_bin_attributes (struct efivars *efivars) +{ +struct bin_attribute *attr; +int error; + +/* new_var */ + attr =kzalloc (sizeof (*attr),GFP_KERNEL ); +if (!attr) +return -ENOMEM ; + + attr->attr.name ="new_var" ; + attr->attr.mode =0200 ; + attr->write = efivar_create; + attr->private = efivars; + efivars->new_var = attr; + +/* del_var */ + attr =kzalloc (sizeof (*attr),GFP_KERNEL ); +if (!attr) { + error = -ENOMEM ; + goto out_free; + } + attr->attr.name ="del_var" ; + attr->attr.mode =0200 ; + attr->write = efivar_delete; + attr->private = efivars; + efivars->del_var = attr; + +sysfs_bin_attr_init (efivars->new_var); +sysfs_bin_attr_init (efivars->del_var); + +/* Register */ + error =sysfs_create_bin_file (&efivars->kset->kobj, + efivars->new_var); +if (error) { +printk (KERN_ERR "efivars: unable to create new_var sysfs file" +" due to error %d\n" , error); + goto out_free; + } + error =sysfs_create_bin_file (&efivars->kset->kobj, + efivars->del_var); +if (error) { +printk (KERN_ERR "efivars: unable to create del_var sysfs file" +" due to error %d\n" , error); +sysfs_remove_bin_file (&efivars->kset->kobj, + efivars->new_var); + goto out_free; + } + +return 0 ; +out_free: +kfree (efivars->new_var); + efivars->new_var =NULL ; +kfree (efivars->new_var); + efivars->new_var =NULL ; +return error; +} +/* * For now we register the efi subsystem with the firmware subsystem * and the vars subsystem with the efi subsystem. In the future, it
@@ -714,20 +765,7 @@ efivars_init(void) } }while (status !=EFI_NOT_FOUND ); -/* -* Now add attributes to allow creation of new vars -* and deletion of existing ones... -*/ - error =sysfs_create_bin_file (&efivars->kset->kobj, - &var_subsys_attr_new_var); -if (error) -printk (KERN_ERR "efivars: unable to create new_var sysfs file" -" due to error %d\n" , error); - error =sysfs_create_bin_file (&efivars->kset->kobj, - &var_subsys_attr_del_var); -if (error) -printk (KERN_ERR "efivars: unable to create del_var sysfs file" -" due to error %d\n" , error); + error =create_efivars_bin_attributes (efivars);/* Don't forget the systab entry */ error =sysfs_create_group (efi_kobj, &efi_subsys_attr_group);
@@ -758,7 +796,12 @@ efivars_exit(void)spin_unlock (&efivars->lock);efivar_unregister (entry); } - +if (efivars->new_var) +sysfs_remove_bin_file (&efivars->kset->kobj, efivars->new_var); +if (efivars->del_var) +sysfs_remove_bin_file (&efivars->kset->kobj, efivars->del_var); +kfree (efivars->new_var); +kfree (efivars->del_var);kset_unregister (efivars->kset);kobject_put (efi_kobj); }
Signature · 1 line
1.7.4.1
PATCH 45/50 efivars: parameterize efivars
In reply to Greg Kroah-HartmanFrom: Mike Waychison <[email protected]>
Now that we all global variable state is encapsulated by struct efivars, parameterize all functions to the efivars local to the control flow rather than at file scope. We do this by removing the variable "efivars" at file scope and move its storage down to the end of the file.
Variables get at efivars by storing the efivars pointer within each efivar_entry. The "new_var" and "del_var" binary attribute files get at the efivars through the private pointer.
--- drivers/firmware/efivars.c | 49 +++++++++++++++++++++++++++---------------- 1 files changed, 31 insertions(+), 18 deletions(-)
drivers/firmware/efivars.c +31 -18
@@ -103,8 +103,6 @@ struct efivars {struct kset *kset;struct bin_attribute *new_var, *del_var; }; -static struct efivars __efivars; -static struct efivars *efivars = &__efivars;/* * The maximum size of VariableName + Data = 1024
@@ -124,6 +122,7 @@ struct efi_variable {struct efivar_entry { +struct efivars *efivars;struct efi_variable var;struct list_head list;struct kobject kobj;
@@ -150,9 +149,10 @@ struct efivar_attribute efivar_attr_##_name = { \* Prototype for sysfs creation function */ static int -efivar_create_sysfs_entry (unsigned long variable_name_size, -efi_char16_t *variable_name, -efi_guid_t *vendor_guid); +efivar_create_sysfs_entry (struct efivars *efivars, +unsigned long variable_name_size, +efi_char16_t *variable_name, +efi_guid_t *vendor_guid);/* Return the number of unicode characters in data */ static unsigned long
@@ -176,7 +176,7 @@ utf8_strsize(efi_char16_t *data, unsigned long maxlength) }static efi_status_t -get_var_data (struct efi_variable *var) +get_var_data (struct efivars *efivars,struct efi_variable *var) {efi_status_t status;
@@ -221,7 +221,7 @@ efivar_attr_read(struct efivar_entry *entry, char *buf)if (!entry || !buf)return -EINVAL ; - status =get_var_data (var); + status =get_var_data (entry->efivars, var);if (status !=EFI_SUCCESS )return -EIO ;
@@ -244,7 +244,7 @@ efivar_size_read(struct efivar_entry *entry, char *buf)if (!entry || !buf)return -EINVAL ; - status =get_var_data (var); + status =get_var_data (entry->efivars, var);if (status !=EFI_SUCCESS )return -EIO ;
@@ -261,7 +261,7 @@ efivar_data_read(struct efivar_entry *entry, char *buf)if (!entry || !buf)return -EINVAL ; - status =get_var_data (var); + status =get_var_data (entry->efivars, var);if (status !=EFI_SUCCESS )return -EIO ;
@@ -276,6 +276,7 @@ static ssize_t efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count) { struct efi_variable *new_var, *var = &entry->var; +struct efivars *efivars = entry->efivars;efi_status_t status =EFI_NOT_FOUND ;if (count !=sizeof (struct efi_variable ))
@@ -325,7 +326,7 @@ efivar_show_raw(struct efivar_entry *entry, char *buf)if (!entry || !buf)return 0 ; - status =get_var_data (var); + status =get_var_data (entry->efivars, var);if (status !=EFI_SUCCESS )return -EIO ;
@@ -413,6 +414,7 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj, char *buf, loff_t pos, size_t count) {struct efi_variable *new_var = (struct efi_variable *)buf; +struct efivars *efivars = bin_attr->private;struct efivar_entry *search_efivar, *n;unsigned long strsize1, strsize2;efi_status_t status =EFI_NOT_FOUND ;
@@ -459,8 +461,11 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj,spin_unlock (&efivars->lock);/* Create the entry in sysfs. Locking is not required here */ - status =efivar_create_sysfs_entry (utf8_strsize (new_var->VariableName, -1024 ), new_var->VariableName, &new_var->VendorGuid); + status =efivar_create_sysfs_entry (efivars, +utf8_strsize (new_var->VariableName, +1024 ), + new_var->VariableName, + &new_var->VendorGuid);if (status) {printk (KERN_WARNING "efivars: variable created, but sysfs entry wasn't.\n" ); }
@@ -472,6 +477,7 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj, char *buf, loff_t pos, size_t count) {struct efi_variable *del_var = (struct efi_variable *)buf; +struct efivars *efivars = bin_attr->private;struct efivar_entry *search_efivar, *n;unsigned long strsize1, strsize2;efi_status_t status =EFI_NOT_FOUND ;
@@ -580,9 +586,10 @@ static struct kobject *efi_kobj;* Returns 1 on failure, 0 on success */ static int -efivar_create_sysfs_entry (unsigned long variable_name_size, -efi_char16_t *variable_name, -efi_guid_t *vendor_guid) +efivar_create_sysfs_entry (struct efivars *efivars, +unsigned long variable_name_size, +efi_char16_t *variable_name, +efi_guid_t *vendor_guid) {int i, short_name_size = variable_name_size /sizeof (efi_char16_t) +38 ;char *short_name;
@@ -597,6 +604,7 @@ efivar_create_sysfs_entry(unsigned long variable_name_size,return 1 ; } + new_efivar->efivars = efivars;memcpy (new_efivar->var.VariableName, variable_name, variable_name_size);memcpy (&(new_efivar->var.VendorGuid), vendor_guid,sizeof (efi_guid_t));
@@ -691,6 +699,8 @@ out_free:return error; } +static struct efivars __efivars; +/* * For now we register the efi subsystem with the firmware subsystem * and the vars subsystem with the efi subsystem. In the future, it
@@ -706,6 +716,7 @@ efivars_init(void)efi_guid_t vendor_guid;efi_char16_t *variable_name;unsigned long variable_name_size =1024 ; +struct efivars *efivars = &__efivars;int error =0 ;if (!efi_enabled)
@@ -751,9 +762,10 @@ efivars_init(void) &vendor_guid);switch (status) {case EFI_SUCCESS : -efivar_create_sysfs_entry (variable_name_size, - variable_name, - &vendor_guid); +efivar_create_sysfs_entry (efivars, + variable_name_size, + variable_name, + &vendor_guid);break ;case EFI_NOT_FOUND :break ;
@@ -788,6 +800,7 @@ out_free: static void __exitefivars_exit (void ) { +struct efivars *efivars = &__efivars;struct efivar_entry *entry, *n;list_for_each_entry_safe (entry, n, &efivars->list, list) {
Signature · 1 line
1.7.4.1
PATCH 46/50 efivars: Split out variable registration
In reply to Greg Kroah-HartmanFrom: Mike Waychison <[email protected]>
In anticipation of re-using the variable facilities in efivars from elsewhere, split out the registration and unregistration of struct efivars from the rest of the EFI specific sysfs code.
--- drivers/firmware/efivars.c | 122 ++++++++++++++++++++++++-------------------- 1 files changed, 67 insertions(+), 55 deletions(-)
drivers/firmware/efivars.c +67 -55
@@ -95,7 +95,7 @@ struct efivars {* 1) ->list - adds, removals, reads, writes * 2) efi.[gs]et_variable() calls. * It must not be held when creating sysfs entries or calling kmalloc. -* efi.get_next_variable() is only called from efivars_init(), +* efi.get_next_variable() is only called from register_efivars(), * which is protected by the BKL, so that path is safe. */ spinlock_t lock;
@@ -699,54 +699,48 @@ out_free:return error; } -static struct efivars __efivars; +static void unregister_efivars (struct efivars *efivars) +{ +struct efivar_entry *entry, *n; -/* -* For now we register the efi subsystem with the firmware subsystem -* and the vars subsystem with the efi subsystem. In the future, it -* might make sense to split off the efi subsystem into its own -* driver, but for now only efivars will register with it, so just -* include it here. -*/ +list_for_each_entry_safe (entry, n, &efivars->list, list) { +spin_lock (&efivars->lock); +list_del (&entry->list); +spin_unlock (&efivars->lock); +efivar_unregister (entry); + } +if (efivars->new_var) +sysfs_remove_bin_file (&efivars->kset->kobj, efivars->new_var); +if (efivars->del_var) +sysfs_remove_bin_file (&efivars->kset->kobj, efivars->del_var); +kfree (efivars->new_var); +kfree (efivars->del_var); +kset_unregister (efivars->kset); +} -static int __init -efivars_init (void ) +static int register_efivars (struct efivars *efivars, +struct kobject *parent_kobj) {efi_status_t status =EFI_NOT_FOUND ;efi_guid_t vendor_guid;efi_char16_t *variable_name;unsigned long variable_name_size =1024 ; -struct efivars *efivars = &__efivars;int error =0 ; -if (!efi_enabled) -return -ENODEV ; - variable_name =kzalloc (variable_name_size,GFP_KERNEL );if (!variable_name) {printk (KERN_ERR "efivars: Memory allocation failed.\n" );return -ENOMEM ; } -printk (KERN_INFO "EFI Variables Facility v%s %s\n" ,EFIVARS_VERSION , -EFIVARS_DATE ); - -/* For now we'll register the efi directory at /sys/firmware/efi */ - efi_kobj =kobject_create_and_add ("efi" , firmware_kobj); -if (!efi_kobj) { -printk (KERN_ERR "efivars: Firmware registration failed.\n" ); - error = -ENOMEM ; - goto out_free; - } -spin_lock_init (&efivars->lock);INIT_LIST_HEAD (&efivars->list); - efivars->kset =kset_create_and_add ("vars" ,NULL , efi_kobj); + efivars->kset =kset_create_and_add ("vars" ,NULL , parent_kobj);if (!efivars->kset) {printk (KERN_ERR "efivars: Subsystem registration failed.\n" ); error = -ENOMEM ; - goto out_firmware_unregister; + goto out; }/*
@@ -778,21 +772,54 @@ efivars_init(void) }while (status !=EFI_NOT_FOUND ); error =create_efivars_bin_attributes (efivars); - -/* Don't forget the systab entry */ - error =sysfs_create_group (efi_kobj, &efi_subsys_attr_group);if (error) -printk (KERN_ERR "efivars: Sysfs attribute export failed with error %d.\n" , error); -else - goto out_free; +unregister_efivars (efivars); -kset_unregister (efivars->kset); +out: +kfree (variable_name); -out_firmware_unregister: -kobject_put (efi_kobj); +return error; +} -out_free: -kfree (variable_name); +static struct efivars __efivars; + +/* +* For now we register the efi subsystem with the firmware subsystem +* and the vars subsystem with the efi subsystem. In the future, it +* might make sense to split off the efi subsystem into its own +* driver, but for now only efivars will register with it, so just +* include it here. +*/ + +static int __init +efivars_init (void ) +{ +int error =0 ; + +printk (KERN_INFO "EFI Variables Facility v%s %s\n" ,EFIVARS_VERSION , +EFIVARS_DATE ); + +if (!efi_enabled) +return -ENODEV ; + +/* For now we'll register the efi directory at /sys/firmware/efi */ + efi_kobj =kobject_create_and_add ("efi" , firmware_kobj); +if (!efi_kobj) { +printk (KERN_ERR "efivars: Firmware registration failed.\n" ); +return -ENOMEM ; + } + + error =register_efivars (&__efivars, efi_kobj); + +/* Don't forget the systab entry */ + error =sysfs_create_group (efi_kobj, &efi_subsys_attr_group); +if (error) { +printk (KERN_ERR +"efivars: Sysfs attribute export failed with error %d.\n" , + error); +unregister_efivars (&__efivars); +kobject_put (efi_kobj); + }return error; }
@@ -800,22 +827,7 @@ out_free: static void __exitefivars_exit (void ) { -struct efivars *efivars = &__efivars; -struct efivar_entry *entry, *n; - -list_for_each_entry_safe (entry, n, &efivars->list, list) { -spin_lock (&efivars->lock); -list_del (&entry->list); -spin_unlock (&efivars->lock); -efivar_unregister (entry); - } -if (efivars->new_var) -sysfs_remove_bin_file (&efivars->kset->kobj, efivars->new_var); -if (efivars->del_var) -sysfs_remove_bin_file (&efivars->kset->kobj, efivars->del_var); -kfree (efivars->new_var); -kfree (efivars->del_var); -kset_unregister (efivars->kset); +unregister_efivars (&__efivars);kobject_put (efi_kobj); }
Signature · 1 line
1.7.4.1
PATCH 47/50 efivars: Parameterize operations.
In reply to Greg Kroah-HartmanFrom: Mike Waychison <[email protected]>
Instead of letting efivars access struct efi directly when dealing with variables, use an operations structure. This allows a later change to reuse the efivars logic without having to pretend to support everything in struct efi.
--- drivers/firmware/efivars.c | 61 ++++++++++++++++++++++++++----------------- 1 files changed, 37 insertions(+), 24 deletions(-)
drivers/firmware/efivars.c +37 -24
@@ -89,19 +89,26 @@ MODULE_DESCRIPTION("sysfs interface to EFI Variables");MODULE_LICENSE ("GPL" );MODULE_VERSION (EFIVARS_VERSION ); +struct efivar_operations { +efi_get_variable_t *get_variable; +efi_get_next_variable_t *get_next_variable; +efi_set_variable_t *set_variable; +}; +struct efivars {/* * ->lock protects two things: * 1) ->list - adds, removals, reads, writes -* 2) efi.[gs]et_variable() calls. +* 2) ops.[gs]et_variable() calls. * It must not be held when creating sysfs entries or calling kmalloc. -* efi.get_next_variable() is only called from register_efivars(), +* ops.get_next_variable() is only called from register_efivars(), * which is protected by the BKL, so that path is safe. */ spinlock_t lock;struct list_head list;struct kset *kset;struct bin_attribute *new_var, *del_var; +const struct efivar_operations *ops; };/*
@@ -182,11 +189,11 @@ get_var_data(struct efivars *efivars, struct efi_variable *var)spin_lock (&efivars->lock); var->DataSize =1024 ; - status = efi.get_variable (var->VariableName, - &var->VendorGuid, - &var->Attributes, - &var->DataSize, - var->Data); + status = efivars->ops->get_variable (var->VariableName, + &var->VendorGuid, + &var->Attributes, + &var->DataSize, + var->Data);spin_unlock (&efivars->lock);if (status !=EFI_SUCCESS ) { printk(KERN_WARNING "efivars: get_variable() failed 0x%lx!\n",
@@ -299,11 +306,11 @@ efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count) }spin_lock (&efivars->lock); - status = efi.set_variable (new_var->VariableName, - &new_var->VendorGuid, - new_var->Attributes, - new_var->DataSize, - new_var->Data); + status = efivars->ops->set_variable (new_var->VariableName, + &new_var->VendorGuid, + new_var->Attributes, + new_var->DataSize, + new_var->Data);spin_unlock (&efivars->lock);
@@ -446,11 +453,11 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj, }/* now *really* create the variable via EFI */ - status = efi.set_variable (new_var->VariableName, - &new_var->VendorGuid, - new_var->Attributes, - new_var->DataSize, - new_var->Data); + status = efivars->ops->set_variable (new_var->VariableName, + &new_var->VendorGuid, + new_var->Attributes, + new_var->DataSize, + new_var->Data);if (status !=EFI_SUCCESS ) { printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n",
@@ -511,11 +518,11 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj, del_var->Attributes =0 ; del_var->DataSize =0 ; - status = efi.set_variable (del_var->VariableName, - &del_var->VendorGuid, - del_var->Attributes, - del_var->DataSize, - del_var->Data); + status = efivars->ops->set_variable (del_var->VariableName, + &del_var->VendorGuid, + del_var->Attributes, + del_var->DataSize, + del_var->Data);if (status !=EFI_SUCCESS ) { printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n",
@@ -719,6 +726,7 @@ static void unregister_efivars(struct efivars *efivars) }static int register_efivars (struct efivars *efivars, +const struct efivar_operations *ops,struct kobject *parent_kobj) {efi_status_t status =EFI_NOT_FOUND ;
@@ -735,6 +743,7 @@ static int register_efivars(struct efivars *efivars,spin_lock_init (&efivars->lock);INIT_LIST_HEAD (&efivars->list); + efivars->ops = ops; efivars->kset =kset_create_and_add ("vars" ,NULL , parent_kobj);if (!efivars->kset) {
@@ -751,7 +760,7 @@ static int register_efivars(struct efivars *efivars, do { variable_name_size = 1024; - status = efi.get_next_variable(&variable_name_size, + status = ops->get_next_variable(&variable_name_size, variable_name, &vendor_guid); switch (status) {
@@ -782,6 +791,7 @@ out: }static struct efivars __efivars; +static struct efivar_operations ops;/* * For now we register the efi subsystem with the firmware subsystem
@@ -809,7 +819,10 @@ efivars_init(void)return -ENOMEM ; } - error =register_efivars (&__efivars, efi_kobj); + ops.get_variable = efi.get_variable; + ops.set_variable = efi.set_variable; + ops.get_next_variable = efi.get_next_variable; + error =register_efivars (&__efivars, &ops, efi_kobj);/* Don't forget the systab entry */ error =sysfs_create_group (efi_kobj, &efi_subsys_attr_group);
Signature · 1 line
1.7.4.1
PATCH 48/50 efivars: Expose efivars functionality to external drivers.
In reply to Greg Kroah-HartmanFrom: Mike Waychison <[email protected]>
--- drivers/firmware/efivars.c | 34 +++++++--------------------------- include/linux/efi.h | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 27 deletions(-)
drivers/firmware/efivars.c +7 -27
@@ -89,28 +89,6 @@ MODULE_DESCRIPTION("sysfs interface to EFI Variables");MODULE_LICENSE ("GPL" );MODULE_VERSION (EFIVARS_VERSION ); -struct efivar_operations { -efi_get_variable_t *get_variable; -efi_get_next_variable_t *get_next_variable; -efi_set_variable_t *set_variable; -}; - -struct efivars { -/* -* ->lock protects two things: -* 1) ->list - adds, removals, reads, writes -* 2) ops.[gs]et_variable() calls. -* It must not be held when creating sysfs entries or calling kmalloc. -* ops.get_next_variable() is only called from register_efivars(), -* which is protected by the BKL, so that path is safe. -*/ -spinlock_t lock; -struct list_head list; -struct kset *kset; -struct bin_attribute *new_var, *del_var; -const struct efivar_operations *ops; -}; -/* * The maximum size of VariableName + Data = 1024 * Therefore, it's reasonable to save that much
@@ -706,7 +684,7 @@ out_free:return error; } -static void unregister_efivars (struct efivars *efivars) +void unregister_efivars (struct efivars *efivars) {struct efivar_entry *entry, *n;
@@ -724,10 +702,11 @@ static void unregister_efivars(struct efivars *efivars)kfree (efivars->del_var);kset_unregister (efivars->kset); } +EXPORT_SYMBOL_GPL (unregister_efivars); -static int register_efivars (struct efivars *efivars, -const struct efivar_operations *ops, -struct kobject *parent_kobj) +int register_efivars (struct efivars *efivars, +const struct efivar_operations *ops, +struct kobject *parent_kobj) {efi_status_t status =EFI_NOT_FOUND ;efi_guid_t vendor_guid;
@@ -789,6 +768,7 @@ out:return error; } +EXPORT_SYMBOL_GPL (register_efivars);static struct efivars __efivars;static struct efivar_operations ops;
@@ -810,7 +790,7 @@ efivars_init(void) EFIVARS_DATE);if (!efi_enabled) -return -ENODEV ; +return 0 ;/* For now we'll register the efi directory at /sys/firmware/efi */ efi_kobj =kobject_create_and_add ("efi" , firmware_kobj);
include/linux/efi.h +37 -0
@@ -397,4 +397,41 @@ static inline void memrange_efi_to_native(u64 *addr, u64 *npages) *addr &= PAGE_MASK; } +#if defined(CONFIG_EFI_VARS ) || defined(CONFIG_EFI_VARS_MODULE ) +/* +* EFI Variable support. +* +* Different firmware drivers can expose their EFI-like variables using +* the following. +*/ + +struct efivar_operations { +efi_get_variable_t *get_variable; +efi_get_next_variable_t *get_next_variable; +efi_set_variable_t *set_variable; +}; + +struct efivars { +/* +* ->lock protects two things: +* 1) ->list - adds, removals, reads, writes +* 2) ops.[gs]et_variable() calls. +* It must not be held when creating sysfs entries or calling kmalloc. +* ops.get_next_variable() is only called from register_efivars(), +* which is protected by the BKL, so that path is safe. +*/ +spinlock_t lock; +struct list_head list; +struct kset *kset; +struct bin_attribute *new_var, *del_var; +const struct efivar_operations *ops; +}; + +int register_efivars (struct efivars *efivars, +const struct efivar_operations *ops, +struct kobject *parent_kobj); +void unregister_efivars (struct efivars *efivars); + +#endif /* CONFIG_EFI_VARS */ +#endif /* _LINUX_EFI_H */
Signature · 1 line
1.7.4.1
PATCH 49/50 efivars: Add Documentation
In reply to Greg Kroah-HartmanFrom: Mike Waychison <[email protected]>
This patch documents the interface exposed by the 'efivars' module.
--- Documentation/ABI/stable/sysfs-firmware-efi-vars | 75 ++++++++++++++++++++++ 1 files changed, 75 insertions(+), 0 deletions(-) create mode 100644 Documentation/ABI/stable/sysfs-firmware-efi-vars
Documentation/ABI/stable/sysfs-firmware-efi-vars new file +75 -0
@@ -0,0 +1,75 @@ +What: /sys/firmware/efi/vars +Date: April 2004 +Contact: Matt Domsch <[email protected]> +Description: + This directory exposes interfaces for interactive with + EFI variables. For more information on EFI variables, + see 'Variable Services' in the UEFI specification + (section 7.2 in specification version 2.3 Errata D). + + In summary, EFI variables are named, and are classified + into separate namespaces through the use of a vendor + GUID. They also have an arbitrary binary value + associated with them. + + The efivars module enumerates these variables and + creates a separate directory for each one found. Each + directory has a name of the form "<key>-<vendor guid>" + and contains the following files: + + attributes: A read-only text file enumerating the + EFI variable flags. Potential values + include: + + EFI_VARIABLE_NON_VOLATILE + EFI_VARIABLE_BOOTSERVICE_ACCESS + EFI_VARIABLE_RUNTIME_ACCESS + EFI_VARIABLE_HARDWARE_ERROR_RECORD + EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS + + See the EFI documentation for an + explanation of each of these variables. + + data: A read-only binary file that can be read + to attain the value of the EFI variable + + guid: The vendor GUID of the variable. This + should always match the GUID in the + variable's name. + + raw_var: A binary file that can be read to obtain + a structure that contains everything + there is to know about the variable. + For structure definition see "struct + efi_variable" in the kernel sources. + + This file can also be written to in + order to update the value of a variable. + For this to work however, all fields of + the "struct efi_variable" passed must + match byte for byte with the structure + read out of the file, save for the value + portion. + + **Note** the efi_variable structure + read/written with this file contains a + 'long' type that may change widths + depending on your underlying + architecture. + + size: As ASCII representation of the size of + the variable's value. + + + In addition, two other magic binary files are provided + in the top-level directory and are used for adding and + removing variables: + + new_var: Takes a "struct efi_variable" and + instructs the EFI firmware to create a + new variable. + + del_var: Takes a "struct efi_variable" and + instructs the EFI firmware to remove any + variable that has a matching vendor GUID + and variable key name.
Signature · 1 line
1.7.4.1
PATCH 50/50 printk: do not mangle valid userspace syslog prefixes
In reply to Greg Kroah-HartmanFrom: Kay Sievers <[email protected]>
printk: do not mangle valid userspace syslog prefixes with /dev/kmsg
Log messages passed to the kernel log by using /dev/kmsg or /dev/ttyprintk might contain a syslog prefix including the syslog facility value.
This makes printk to recognize these headers properly, extract the real log level from it to use, and add the prefix as a proper prefix to the log buffer, instead of wrongly printing it as the log message text.
Before:
$ echo '<14>text' > /dev/kmsg $ dmesg -r <4>[135159.594810] <14>text
After:
$ echo '<14>text' > /dev/kmsg $ dmesg -r <14>[ 50.750654] text
--- kernel/printk.c | 138 +++++++++++++++++++++++++++++++++++++++++-------------- 1 files changed, 104 insertions(+), 34 deletions(-)
kernel/printk.c +104 -34
@@ -499,6 +499,71 @@ static void _call_console_drivers(unsigned start, }/* +* Parse the syslog header <[0-9]*>. The decimal value represents 32bit, the +* lower 3 bit are the log level, the rest are the log facility. In case +* userspace passes usual userspace syslog messages to /dev/kmsg or +* /dev/ttyprintk, the log prefix might contain the facility. Printk needs +* to extract the correct log level for in-kernel processing, and not mangle +* the original value. +* +* If a prefix is found, the length of the prefix is returned. If 'level' is +* passed, it will be filled in with the log level without a possible facility +* value. If 'special' is passed, the special printk prefix chars are accepted +* and returned. If no valid header is found, 0 is returned and the passed +* variables are not touched. +*/ +static size_t log_prefix (const char *p,unsigned int *level,char *special) +{ +unsigned int lev =0 ; +char sp ='\0' ; +size_t len; + +if (p[0 ] !='<' || !p[1 ]) +return 0 ; +if (p[2 ] =='>' ) { +/* usual single digit level number or special char */ +switch (p[1 ]) { + case '0' ... '7': + lev = p[1 ] -'0' ; +break ; +case 'c' :/* KERN_CONT */ +case 'd' :/* KERN_DEFAULT */ + sp = p[1 ]; +break ; +default : +return 0 ; + } + len =3 ; + }else { +/* multi digit including the level and facility number */ +char *endp =NULL ; + +if (p[1 ] <'0' && p[1 ] >'9' ) +return 0 ; + + lev = (simple_strtoul (&p[1 ], &endp,10 ) &7 ); +if (endp ==NULL || endp[0 ] !='>' ) +return 0 ; + len = (endp +1 ) - p; + } + +/* do not accept special char if not asked for */ +if (sp && !special) +return 0 ; + +if (special) { + *special = sp; +/* return special char, do not touch level */ +if (sp) +return len; + } + +if (level) + *level = lev; +return len; +} + +/* * Call the console drivers, asking them to write out * log_buf[start] to log_buf[end - 1]. * The console_lock must be held.
@@ -513,13 +578,9 @@ static void call_console_drivers(unsigned start, unsigned end) cur_index = start; start_print = start;while (cur_index != end) { -if (msg_level <0 && ((end - cur_index) >2 ) && -LOG_BUF (cur_index +0 ) =='<' && -LOG_BUF (cur_index +1 ) >='0' && -LOG_BUF (cur_index +1 ) <='7' && -LOG_BUF (cur_index +2 ) =='>' ) { - msg_level =LOG_BUF (cur_index +1 ) -'0' ; - cur_index +=3 ; +if (msg_level <0 && ((end - cur_index) >2 )) { +/* strip log prefix */ + cur_index +=log_prefix (&LOG_BUF (cur_index), &msg_level,NULL ); start_print = cur_index; }while (cur_index != end) {
@@ -717,6 +778,8 @@ asmlinkage int vprintk(const char *fmt, va_list args)unsigned long flags;int this_cpu;char *p; +size_t plen; +char special;boot_delay_msec ();printk_delay ();
@@ -757,45 +820,52 @@ asmlinkage int vprintk(const char *fmt, va_list args) printed_len +=vscnprintf (printk_buf + printed_len,sizeof (printk_buf) - printed_len, fmt, args); - p = printk_buf; -/* Do we have a loglevel in the string? */ -if (p[0 ] =='<' ) { -unsigned char c = p[1 ]; -if (c && p[2 ] =='>' ) { -switch (c) { - case '0' ... '7': /* loglevel */ - current_log_level = c -'0' ; -/* Fallthrough - make sure we're on a new line */ -case 'd' :/* KERN_DEFAULT */ -if (!new_text_line) { -emit_log_char ('\n' ); - new_text_line =1 ; - } -/* Fallthrough - skip the loglevel */ -case 'c' :/* KERN_CONT */ - p +=3 ; -break ; +/* Read log level and handle special printk prefix */ + plen =log_prefix (p, ¤t_log_level, &special); +if (plen) { + p += plen; + +switch (special) { +case 'c' :/* Strip <c> KERN_CONT, continue line */ + plen =0 ; +break ; +case 'd' :/* Strip <d> KERN_DEFAULT, start new line */ + plen =0 ; +default : +if (!new_text_line) { +emit_log_char ('\n' ); + new_text_line =1 ; } } }/* -* Copy the output into log_buf. If the caller didn't provide -* appropriate log level tags, we insert them here +* Copy the output into log_buf. If the caller didn't provide +* the appropriate log prefix, we insert them here */ -for ( ; *p; p++) { +for (; *p; p++) {if (new_text_line) { -/* Always output the token */ -emit_log_char ('<' ); -emit_log_char (current_log_level +'0' ); -emit_log_char ('>' ); - printed_len +=3 ; new_text_line =0 ; +if (plen) { +/* Copy original log prefix */ +int i; + +for (i =0 ; i < plen; i++) +emit_log_char (printk_buf[i]); + printed_len += plen; + }else { +/* Add log prefix */ +emit_log_char ('<' ); +emit_log_char (current_log_level +'0' ); +emit_log_char ('>' ); + printed_len +=3 ; + } +if (printk_time) { -/* Follow the token with the time */ +/* Add the current time stamp */ char tbuf[50 ], *tp;unsigned tlen;unsigned long long t;
Signature · 1 line
1.7.4.1