Skip to contentSkip to conversation

driver core patches for .39

PATCH New Greg KH 6 participants 57 messages Mar 16, 2011 – Mar 18, 2011

Subsystems (14)
lore
Share & tools
lore

Greg KH

author
#0 lore raw

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

#1 lore raw

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
index 080e9ca..9cd3b5c 100644
@@ -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
#2 lore raw

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
index 5d1335fae..2ed95f9 100644
@@ -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
#3 lore raw

PATCH 3/50 docs/sysfs: show() methods should use scnprintf().

In reply to Greg Kroah-Hartman

From: 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
index 2ed95f9..f806e50 100644
@@ -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
#4 lore raw

PATCH 4/50 kobject: Add missing format attribute specifications

In reply to Greg Kroah-Hartman

From: 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
index 8f6d121..15e82c1 100644
@@ -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
#5 lore raw

PATCH 5/50 Dynamic debug: Add more flags

In reply to Greg Kroah-Hartman

From: 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
index 58ea64a..e6c4b75 100644
@@ -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
index 1c70028..0c9653f 100644
@@ -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
#6 lore raw

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.

---
 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
index 58ea64a..e6c4b75 100644
@@ -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 +6 -0
index 1c70028..0c9653f 100644
@@ -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

author
#7 lore raw

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

#8 lore raw

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

#9 lore raw

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_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)

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.

#10 lore raw

PATCH 6/50 firmware_classs: change val uevent's type to bool

In reply to Greg Kroah-Hartman

From: 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
index 40af43e..8c798ef 100644
@@ -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
index 53d1e6c..21b3e75 100644
@@ -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
#11 lore raw

PATCH 7/50 sysdev: Fixup warning message

In reply to Greg Kroah-Hartman

From: 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
index 1667aaf..b094e0d 100644
@@ -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
#12 lore raw

PATCH 8/50 debugfs: remove module_exit()

In reply to Greg Kroah-Hartman

From: 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
index 37a8ca7..d38c88f 100644
@@ -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
#13 lore raw

PATCH 9/50 sysdev: Do not register with sysdev when erroring on add

In reply to Greg Kroah-Hartman

From: 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
index b094e0d..f6fb547 100644
@@ -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
#14 lore raw

PATCH 10/50 Translate Documentation/SecurityBugs into Chinese

In reply to Greg Kroah-Hartman

From: 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
new file mode 100644
index 0000000..d21eb07
@@ -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
#15 lore raw

PATCH 11/50 pch_phub: add new device ML7213

In reply to Greg Kroah-Hartman

From: 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
index cc8e49d..b7d5ef2 100644
@@ -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
#16 lore raw

PATCH 12/50 dynamic_debug: add #include <linux/sched.h>

In reply to Greg Kroah-Hartman

This 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
index 863c834..75ca78f 100644
@@ -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
#17 lore raw

PATCH 13/50 memory hotplug: Allow memory blocks to span multiple memory sections

In reply to Greg Kroah-Hartman

From: 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
index 57e7e9c..8f485d7 100644
@@ -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
#18 lore raw

PATCH 14/50 memory hotplug: Update phys_index to [start|end]_section_nr

In reply to Greg Kroah-Hartman

From: 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
index 0b70400..71b4a32 100644
@@ -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
index 36b4305..b3b72d6 100644
@@ -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
index 06c1fa0..e1e3b2b 100644
@@ -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
index 1466945..92370e2 100644
@@ -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
#19 lore raw

PATCH 15/50 memory hotplug: Define memory_block_size_bytes for powerpc/pseries

In reply to Greg Kroah-Hartman

From: 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
index bc88036..33867ec 100644
@@ -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
#20 lore raw

PATCH 16/50 memory hotplug: Define memory_block_size_bytes for x86_64 with CONFIG_X86_UV

In reply to Greg Kroah-Hartman

From: 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
index 71a5929..17e90d1 100644
@@ -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
#21 lore raw

PATCH 17/50 memory hotplug: sysfs probe routine should add all memory sections

In reply to Greg Kroah-Hartman

From: 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
index 71b4a32..3da6a43 100644
@@ -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
#22 lore raw

PATCH 18/50 driver core: Replace the dangerous to_root_device macro with an inline function

In reply to Greg Kroah-Hartman

From: 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
index 9cd3b5c..81b78ed 100644
@@ -1320,7 +1320,10 @@ struct root_device
 	struct 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
#23 lore raw

PATCH 19/50 sysfs: Capitalize description of SYSFS_DEPRECATED{_V2} options

In reply to Greg Kroah-Hartman

From: Ferenc Wagner <[email protected]>

---
 init/Kconfig |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)
init/Kconfig +2 -2
index be788c0..e72fd10 100644
@@ -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
#24 lore raw

PATCH 20/50 Fix a mistake Chinese character in Documentation/zh_CN/SubmittingPatches

In reply to Greg Kroah-Hartman

From: 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
index 9a1a6e1..cc89386 100644
@@ -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
#25 lore raw

PATCH 21/50 drivers:misc: ti-st: register with channel IDs

In reply to Greg Kroah-Hartman

From: 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
index f9aad06..84d73c5 100644
@@ -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
index 4c7be22..1674ca7 100644
@@ -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	2
 	unsigned 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
#26 lore raw

PATCH 22/50 drivers:misc: ti-st: move from rfkill to sysfs

In reply to Greg Kroah-Hartman

From: 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
new file mode 100644
index 0000000..c165327
@@ -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
index 1674ca7..010cda7 100644
@@ -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
#27 lore raw

PATCH 23/50 drivers:misc: ti-st: fix error codes

In reply to Greg Kroah-Hartman

From: 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
index 84d73c5..79d2dc3 100644
@@ -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
index a7fda81..ccc46a7b 100644
@@ -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
index 2bda8de..f72de6b 100644
@@ -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
#28 lore raw

PATCH 24/50 drivers:misc: ti-st: set right debug levels for logs

In reply to Greg Kroah-Hartman

From: 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
index 79d2dc3..f7bb96f 100644
@@ -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
index f72de6b..3f24951 100644
@@ -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
#29 lore raw

PATCH 25/50 drivers:misc: ti-st: firmware download optimization

In reply to Greg Kroah-Hartman

From: 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
index f7bb96f..dd2c879 100644
@@ -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
index 010cda7..7885a77 100644
@@ -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
#30 lore raw

PATCH 26/50 drivers:misc: ti-st: fix hci-ll on wake_ind collision

In reply to Greg Kroah-Hartman

From: 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
index dd2c879..f0d24d8 100644
@@ -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
#31 lore raw

PATCH 27/50 drivers:misc: ti-st: remove multiple gpio handling

In reply to Greg Kroah-Hartman

From: 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
index f0d24d8..1847c47 100644
@@ -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
index 7885a77..7071ec5 100644
@@ -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
#32 lore raw

PATCH 28/50 kobject.h: fix build when CONFIG_HOTPLUG is disabled

In reply to Greg Kroah-Hartman

From: 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
index 15e82c1..9229b64 100644
@@ -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
#33 lore raw

PATCH 29/50 debugfs: Fix filesystem reference counting on debugfs_remove() failure

In reply to Greg Kroah-Hartman

From: 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
index d38c88f..e7a7a2f 100644
@@ -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
#34 lore raw

PATCH 30/50 Translat Documentation/SubmittingChecklist into Chinese

In reply to Greg Kroah-Hartman

From: 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
new file mode 100644
index 0000000..951415b
@@ -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
#35 lore raw

PATCH 31/50 Translate linux-2.6/Documentation/magic-number.txt into Chinese

In reply to Greg Kroah-Hartman

From: 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
new file mode 100644
index 0000000..4c4ce85
@@ -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
#36 lore raw

PATCH 32/50 Driver core: convert platform_{get,set}_drvdata to static inline functions

In reply to Greg Kroah-Hartman

From: 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
index 2e700ec..d96db98 100644
@@ -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
#37 lore raw

PATCH 33/50 firmware: Add DMI entry types to the headers

In reply to Greg Kroah-Hartman

From: 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
index 90e087f..f156cca 100644
@@ -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
#38 lore raw

PATCH 34/50 firmware: Basic dmi-sysfs support

In reply to Greg Kroah-Hartman

From: 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
index e710424..3c56afc 100644
@@ -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
index 1c3c173..20c17fc 100644
@@ -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
#39 lore raw

PATCH 35/50 firmware: Break out system_event_log in dmi-sysfs

In reply to Greg Kroah-Hartman

From: 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
index 2d8a04a..d209610 100644
@@ -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
#40 lore raw

PATCH 36/50 firmware: Expose DMI type 15 System Event Log

In reply to Greg Kroah-Hartman

From: 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
index d209610..a5afd80 100644
@@ -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
#41 lore raw

PATCH 37/50 firmware: Add documentation for /sys/firmware/dmi

In reply to Greg Kroah-Hartman

From: 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
new file mode 100644
index 0000000..ba9da95
@@ -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
#42 lore raw

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? :)

#43 lore raw

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
index ba9da95..c78f9ab 100644
@@ -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
#44 lore raw

PATCH 38/50 firmware: Fix unaligned memory accesses in dmi-sysfs

In reply to Greg Kroah-Hartman

From: 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
index a5afd80..eb26d62 100644
@@ -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
#45 lore raw

PATCH 39/50 Fix spelling mistakes in Documentation/zh_CN/SubmittingPatches

In reply to Greg Kroah-Hartman

From: 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
index cc89386..0f4385a 100644
@@ -230,7 +230,7 @@ pref("mailnews.display.disable_format_flowed_support", true);
 些原因,修正错误,重新提交更新后的改动,是你自己的工作。
 
 Linus不给出任何评论就“丢弃”你的补丁是常见的事情。在系统中这样的事情很
-平常。如果他没有接受你的补丁,也许是由于以下原本:
+平常。如果他没有接受你的补丁,也许是由于以下原因:
 * 你的补丁不能在最新版本的内核上干净的打上。
 * 你的补丁在 linux-kernel 邮件列表中没有得到充分的讨论。
 * 风格问题(参照第2小节)
Signature · 1 line
1.7.4.1
#46 lore raw

PATCH 40/50 UIO: add PRUSS UIO driver support

In reply to Greg Kroah-Hartman

From: 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
index bb44079..6f3ea9b 100644
@@ -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
index 18fd818..d4dd9a5 100644
@@ -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
new file mode 100644
index 0000000..f39140a
@@ -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
#47 lore raw

PATCH 41/50 kref: Fix typo in kref documentation

In reply to Greg Kroah-Hartman

From: 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
index ae203f9..48ba715 100644
@@ -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
#48 lore raw

PATCH 42/50 drivers:misc: ti-st: fix debugging code

In reply to Greg Kroah-Hartman

From: 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
index 1847c47..486117f 100644
@@ -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
#49 lore raw

PATCH 43/50 efivars: move efivars globals into struct efivars

In reply to Greg Kroah-Hartman

From: 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
index 2a62ec6..f10ecb6 100644
@@ -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
#50 lore raw

PATCH 44/50 efivars: Make efivars bin_attributes dynamic

In reply to Greg Kroah-Hartman

From: 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
index f10ecb6..528ce47 100644
@@ -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
#51 lore raw

PATCH 45/50 efivars: parameterize efivars

In reply to Greg Kroah-Hartman

From: 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
index 528ce47..5633018 100644
@@ -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 __exit
 efivars_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
#52 lore raw

PATCH 46/50 efivars: Split out variable registration

In reply to Greg Kroah-Hartman

From: 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
index 5633018..f22bfcf 100644
@@ -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 __exit
 efivars_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
#53 lore raw

PATCH 47/50 efivars: Parameterize operations.

In reply to Greg Kroah-Hartman

From: 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
index f22bfcf..b10b7d7 100644
@@ -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
#54 lore raw

PATCH 48/50 efivars: Expose efivars functionality to external drivers.

In reply to Greg Kroah-Hartman

From: 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
index b10b7d7..ff0c373 100644
@@ -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
index fb737bc..33fa120 100644
@@ -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
#55 lore raw

PATCH 49/50 efivars: Add Documentation

In reply to Greg Kroah-Hartman

From: 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
new file mode 100644
index 0000000..5def20b
@@ -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
#56 lore raw

PATCH 50/50 printk: do not mangle valid userspace syslog prefixes

In reply to Greg Kroah-Hartman

From: 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
index 2ddbdc7..5e3d042 100644
@@ -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, &current_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