commit
c301de20f7
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,64 @@
|
||||
From: John Johansen <john.johansen@canonical.com>
|
||||
Date: Tue, 20 Jul 2010 06:57:08 -0700
|
||||
Subject: AppArmor: Allow dfa backward compatibility with broken userspace
|
||||
Patch-mainline: 2.6.37?
|
||||
|
||||
The apparmor_parser when compiling policy could generate invalid dfas
|
||||
that did not have sufficient padding to avoid invalid references, when
|
||||
used by the kernel. The kernels check to verify the next/check table
|
||||
size was broken meaning invalid dfas were being created by userspace
|
||||
and not caught.
|
||||
|
||||
To remain compatible with old tools that are not fixed, pad the loaded
|
||||
dfas next/check table. The dfa's themselves are valid except for the
|
||||
high padding for potentially invalid transitions (high bounds error),
|
||||
which have a maximimum is 256 entries. So just allocate an extra null filled
|
||||
256 entries for the next/check tables. This will guarentee all bounds
|
||||
are good and invalid transitions go to the null (0) state.
|
||||
|
||||
Signed-off-by: John Johansen <john.johansen@canonical.com>
|
||||
Acked-by: Jeff Mahoney <jeffm@suse.com>
|
||||
---
|
||||
security/apparmor/match.c | 17 +++++++++++++++++
|
||||
1 file changed, 17 insertions(+)
|
||||
|
||||
--- a/security/apparmor/match.c
|
||||
+++ b/security/apparmor/match.c
|
||||
@@ -57,8 +57,17 @@ static struct table_header *unpack_table
|
||||
if (bsize < tsize)
|
||||
goto out;
|
||||
|
||||
+ /* Pad table allocation for next/check by 256 entries to remain
|
||||
+ * backwards compatible with old (buggy) tools and remain safe without
|
||||
+ * run time checks
|
||||
+ */
|
||||
+ if (th.td_id == YYTD_ID_NXT || th.td_id == YYTD_ID_CHK)
|
||||
+ tsize += 256 * th.td_flags;
|
||||
+
|
||||
table = kvmalloc(tsize);
|
||||
if (table) {
|
||||
+ /* ensure the pad is clear, else there will be errors */
|
||||
+ memset(table, 0, tsize);
|
||||
*table = th;
|
||||
if (th.td_flags == YYTD_DATA8)
|
||||
UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
|
||||
@@ -134,11 +143,19 @@ static int verify_dfa(struct aa_dfa *dfa
|
||||
goto out;
|
||||
|
||||
if (flags & DFA_FLAG_VERIFY_STATES) {
|
||||
+ int warning = 0;
|
||||
for (i = 0; i < state_count; i++) {
|
||||
if (DEFAULT_TABLE(dfa)[i] >= state_count)
|
||||
goto out;
|
||||
/* TODO: do check that DEF state recursion terminates */
|
||||
if (BASE_TABLE(dfa)[i] + 255 >= trans_count) {
|
||||
+ if (warning)
|
||||
+ continue;
|
||||
+ printk(KERN_WARNING "AppArmor DFA next/check "
|
||||
+ "upper bounds error fixed, upgrade "
|
||||
+ "user space tools \n");
|
||||
+ warning = 1;
|
||||
+ } else if (BASE_TABLE(dfa)[i] >= trans_count) {
|
||||
printk(KERN_ERR "AppArmor DFA next/check upper "
|
||||
"bounds error\n");
|
||||
goto out;
|
@ -0,0 +1,379 @@
|
||||
From: John Johansen <john.johansen@canonical.com>
|
||||
Date: Thu, 22 Jul 2010 02:32:02 -0700
|
||||
Subject: AppArmor: compatibility patch for v5 interface
|
||||
Patch-mainline: 2.6.37?
|
||||
|
||||
Signed-off-by: John Johansen <john.johansen@canonical.com>
|
||||
Acked-by: Jeff Mahoney <jeffm@suse.com>
|
||||
---
|
||||
security/apparmor/Kconfig | 9 +
|
||||
security/apparmor/Makefile | 2
|
||||
security/apparmor/apparmorfs-24.c | 287 +++++++++++++++++++++++++++++++++
|
||||
security/apparmor/apparmorfs.c | 18 +-
|
||||
security/apparmor/include/apparmorfs.h | 6
|
||||
5 files changed, 320 insertions(+), 2 deletions(-)
|
||||
create mode 100644 security/apparmor/apparmorfs-24.c
|
||||
|
||||
--- a/security/apparmor/Kconfig
|
||||
+++ b/security/apparmor/Kconfig
|
||||
@@ -29,3 +29,12 @@ config SECURITY_APPARMOR_BOOTPARAM_VALUE
|
||||
boot.
|
||||
|
||||
If you are unsure how to answer this question, answer 1.
|
||||
+
|
||||
+config SECURITY_APPARMOR_COMPAT_24
|
||||
+ bool "Enable AppArmor 2.4 compatability"
|
||||
+ depends on SECURITY_APPARMOR
|
||||
+ default y
|
||||
+ help
|
||||
+ This option enables compatability with AppArmor 2.4. It is
|
||||
+ recommended if compatability with older versions of AppArmor
|
||||
+ is desired.
|
||||
--- a/security/apparmor/Makefile
|
||||
+++ b/security/apparmor/Makefile
|
||||
@@ -6,6 +6,8 @@ apparmor-y := apparmorfs.o audit.o capab
|
||||
path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
|
||||
resource.o sid.o file.o net.o
|
||||
|
||||
+apparmor-$(CONFIG_SECURITY_APPARMOR_COMPAT_24) += apparmorfs-24.o
|
||||
+
|
||||
clean-files: capability_names.h af_names.h
|
||||
|
||||
quiet_cmd_make-caps = GEN $@
|
||||
--- /dev/null
|
||||
+++ b/security/apparmor/apparmorfs-24.c
|
||||
@@ -0,0 +1,287 @@
|
||||
+/*
|
||||
+ * AppArmor security module
|
||||
+ *
|
||||
+ * This file contains AppArmor /sys/kernel/secrutiy/apparmor interface functions
|
||||
+ *
|
||||
+ * Copyright (C) 1998-2008 Novell/SUSE
|
||||
+ * Copyright 2009-2010 Canonical Ltd.
|
||||
+ *
|
||||
+ * 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 of the
|
||||
+ * License.
|
||||
+ *
|
||||
+ *
|
||||
+ * This file contain functions providing an interface for <= AppArmor 2.4
|
||||
+ * compatibility. It is dependent on CONFIG_SECURITY_APPARMOR_COMPAT_24
|
||||
+ * being set (see Makefile).
|
||||
+ */
|
||||
+
|
||||
+#include <linux/security.h>
|
||||
+#include <linux/vmalloc.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/seq_file.h>
|
||||
+#include <linux/uaccess.h>
|
||||
+#include <linux/namei.h>
|
||||
+
|
||||
+#include "include/apparmor.h"
|
||||
+#include "include/audit.h"
|
||||
+#include "include/context.h"
|
||||
+#include "include/policy.h"
|
||||
+
|
||||
+
|
||||
+/* apparmor/matching */
|
||||
+static ssize_t aa_matching_read(struct file *file, char __user *buf,
|
||||
+ size_t size, loff_t *ppos)
|
||||
+{
|
||||
+ const char matching[] = "pattern=aadfa audit perms=crwxamlk/ "
|
||||
+ "user::other";
|
||||
+
|
||||
+ return simple_read_from_buffer(buf, size, ppos, matching,
|
||||
+ sizeof(matching) - 1);
|
||||
+}
|
||||
+
|
||||
+const struct file_operations aa_fs_matching_fops = {
|
||||
+ .read = aa_matching_read,
|
||||
+};
|
||||
+
|
||||
+/* apparmor/features */
|
||||
+static ssize_t aa_features_read(struct file *file, char __user *buf,
|
||||
+ size_t size, loff_t *ppos)
|
||||
+{
|
||||
+ const char features[] = "file=3.1 capability=2.0 network=1.0 "
|
||||
+ "change_hat=1.5 change_profile=1.1 " "aanamespaces=1.1 rlimit=1.1";
|
||||
+
|
||||
+ return simple_read_from_buffer(buf, size, ppos, features,
|
||||
+ sizeof(features) - 1);
|
||||
+}
|
||||
+
|
||||
+const struct file_operations aa_fs_features_fops = {
|
||||
+ .read = aa_features_read,
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * __next_namespace - find the next namespace to list
|
||||
+ * @root: root namespace to stop search at (NOT NULL)
|
||||
+ * @ns: current ns position (NOT NULL)
|
||||
+ *
|
||||
+ * Find the next namespace from @ns under @root and handle all locking needed
|
||||
+ * while switching current namespace.
|
||||
+ *
|
||||
+ * Returns: next namespace or NULL if at last namespace under @root
|
||||
+ * NOTE: will not unlock root->lock
|
||||
+ */
|
||||
+static struct aa_namespace *__next_namespace(struct aa_namespace *root,
|
||||
+ struct aa_namespace *ns)
|
||||
+{
|
||||
+ struct aa_namespace *parent;
|
||||
+
|
||||
+ /* is next namespace a child */
|
||||
+ if (!list_empty(&ns->sub_ns)) {
|
||||
+ struct aa_namespace *next;
|
||||
+ next = list_first_entry(&ns->sub_ns, typeof(*ns), base.list);
|
||||
+ read_lock(&next->lock);
|
||||
+ return next;
|
||||
+ }
|
||||
+
|
||||
+ /* check if the next ns is a sibling, parent, gp, .. */
|
||||
+ parent = ns->parent;
|
||||
+ while (parent) {
|
||||
+ read_unlock(&ns->lock);
|
||||
+ list_for_each_entry_continue(ns, &parent->sub_ns, base.list) {
|
||||
+ read_lock(&ns->lock);
|
||||
+ return ns;
|
||||
+ }
|
||||
+ if (parent == root)
|
||||
+ return NULL;
|
||||
+ ns = parent;
|
||||
+ parent = parent->parent;
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * __first_profile - find the first profile in a namespace
|
||||
+ * @root: namespace that is root of profiles being displayed (NOT NULL)
|
||||
+ * @ns: namespace to start in (NOT NULL)
|
||||
+ *
|
||||
+ * Returns: unrefcounted profile or NULL if no profile
|
||||
+ */
|
||||
+static struct aa_profile *__first_profile(struct aa_namespace *root,
|
||||
+ struct aa_namespace *ns)
|
||||
+{
|
||||
+ for ( ; ns; ns = __next_namespace(root, ns)) {
|
||||
+ if (!list_empty(&ns->base.profiles))
|
||||
+ return list_first_entry(&ns->base.profiles,
|
||||
+ struct aa_profile, base.list);
|
||||
+ }
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * __next_profile - step to the next profile in a profile tree
|
||||
+ * @profile: current profile in tree (NOT NULL)
|
||||
+ *
|
||||
+ * Perform a depth first taversal on the profile tree in a namespace
|
||||
+ *
|
||||
+ * Returns: next profile or NULL if done
|
||||
+ * Requires: profile->ns.lock to be held
|
||||
+ */
|
||||
+static struct aa_profile *__next_profile(struct aa_profile *p)
|
||||
+{
|
||||
+ struct aa_profile *parent;
|
||||
+ struct aa_namespace *ns = p->ns;
|
||||
+
|
||||
+ /* is next profile a child */
|
||||
+ if (!list_empty(&p->base.profiles))
|
||||
+ return list_first_entry(&p->base.profiles, typeof(*p),
|
||||
+ base.list);
|
||||
+
|
||||
+ /* is next profile a sibling, parent sibling, gp, subling, .. */
|
||||
+ parent = p->parent;
|
||||
+ while (parent) {
|
||||
+ list_for_each_entry_continue(p, &parent->base.profiles,
|
||||
+ base.list)
|
||||
+ return p;
|
||||
+ p = parent;
|
||||
+ parent = parent->parent;
|
||||
+ }
|
||||
+
|
||||
+ /* is next another profile in the namespace */
|
||||
+ list_for_each_entry_continue(p, &ns->base.profiles, base.list)
|
||||
+ return p;
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * next_profile - step to the next profile in where ever it may be
|
||||
+ * @root: root namespace (NOT NULL)
|
||||
+ * @profile: current profile (NOT NULL)
|
||||
+ *
|
||||
+ * Returns: next profile or NULL if there isn't one
|
||||
+ */
|
||||
+static struct aa_profile *next_profile(struct aa_namespace *root,
|
||||
+ struct aa_profile *profile)
|
||||
+{
|
||||
+ struct aa_profile *next = __next_profile(profile);
|
||||
+ if (next)
|
||||
+ return next;
|
||||
+
|
||||
+ /* finished all profiles in namespace move to next namespace */
|
||||
+ return __first_profile(root, __next_namespace(root, profile->ns));
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * p_start - start a depth first traversal of profile tree
|
||||
+ * @f: seq_file to fill
|
||||
+ * @pos: current position
|
||||
+ *
|
||||
+ * Returns: first profile under current namespace or NULL if none found
|
||||
+ *
|
||||
+ * acquires first ns->lock
|
||||
+ */
|
||||
+static void *p_start(struct seq_file *f, loff_t *pos)
|
||||
+ __acquires(root->lock)
|
||||
+{
|
||||
+ struct aa_profile *profile = NULL;
|
||||
+ struct aa_namespace *root = aa_current_profile()->ns;
|
||||
+ loff_t l = *pos;
|
||||
+ f->private = aa_get_namespace(root);
|
||||
+
|
||||
+
|
||||
+ /* find the first profile */
|
||||
+ read_lock(&root->lock);
|
||||
+ profile = __first_profile(root, root);
|
||||
+
|
||||
+ /* skip to position */
|
||||
+ for (; profile && l > 0; l--)
|
||||
+ profile = next_profile(root, profile);
|
||||
+
|
||||
+ return profile;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * p_next - read the next profile entry
|
||||
+ * @f: seq_file to fill
|
||||
+ * @p: profile previously returned
|
||||
+ * @pos: current position
|
||||
+ *
|
||||
+ * Returns: next profile after @p or NULL if none
|
||||
+ *
|
||||
+ * may acquire/release locks in namespace tree as necessary
|
||||
+ */
|
||||
+static void *p_next(struct seq_file *f, void *p, loff_t *pos)
|
||||
+{
|
||||
+ struct aa_profile *profile = p;
|
||||
+ struct aa_namespace *root = f->private;
|
||||
+ (*pos)++;
|
||||
+
|
||||
+ return next_profile(root, profile);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * p_stop - stop depth first traversal
|
||||
+ * @f: seq_file we are filling
|
||||
+ * @p: the last profile writen
|
||||
+ *
|
||||
+ * Release all locking done by p_start/p_next on namespace tree
|
||||
+ */
|
||||
+static void p_stop(struct seq_file *f, void *p)
|
||||
+ __releases(root->lock)
|
||||
+{
|
||||
+ struct aa_profile *profile = p;
|
||||
+ struct aa_namespace *root = f->private, *ns;
|
||||
+
|
||||
+ if (profile) {
|
||||
+ for (ns = profile->ns; ns && ns != root; ns = ns->parent)
|
||||
+ read_unlock(&ns->lock);
|
||||
+ }
|
||||
+ read_unlock(&root->lock);
|
||||
+ aa_put_namespace(root);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * seq_show_profile - show a profile entry
|
||||
+ * @f: seq_file to file
|
||||
+ * @p: current position (profile) (NOT NULL)
|
||||
+ *
|
||||
+ * Returns: error on failure
|
||||
+ */
|
||||
+static int seq_show_profile(struct seq_file *f, void *p)
|
||||
+{
|
||||
+ struct aa_profile *profile = (struct aa_profile *)p;
|
||||
+ struct aa_namespace *root = f->private;
|
||||
+
|
||||
+ if (profile->ns != root)
|
||||
+ seq_printf(f, ":%s://", aa_ns_name(root, profile->ns));
|
||||
+ seq_printf(f, "%s (%s)\n", profile->base.hname,
|
||||
+ COMPLAIN_MODE(profile) ? "complain" : "enforce");
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct seq_operations aa_fs_profiles_op = {
|
||||
+ .start = p_start,
|
||||
+ .next = p_next,
|
||||
+ .stop = p_stop,
|
||||
+ .show = seq_show_profile,
|
||||
+};
|
||||
+
|
||||
+static int profiles_open(struct inode *inode, struct file *file)
|
||||
+{
|
||||
+ return seq_open(file, &aa_fs_profiles_op);
|
||||
+}
|
||||
+
|
||||
+static int profiles_release(struct inode *inode, struct file *file)
|
||||
+{
|
||||
+ return seq_release(inode, file);
|
||||
+}
|
||||
+
|
||||
+const struct file_operations aa_fs_profiles_fops = {
|
||||
+ .open = profiles_open,
|
||||
+ .read = seq_read,
|
||||
+ .llseek = seq_lseek,
|
||||
+ .release = profiles_release,
|
||||
+};
|
||||
--- a/security/apparmor/apparmorfs.c
|
||||
+++ b/security/apparmor/apparmorfs.c
|
||||
@@ -182,7 +182,11 @@ void __init aa_destroy_aafs(void)
|
||||
aafs_remove(".remove");
|
||||
aafs_remove(".replace");
|
||||
aafs_remove(".load");
|
||||
-
|
||||
+#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
|
||||
+ aafs_remove("profiles");
|
||||
+ aafs_remove("matching");
|
||||
+ aafs_remove("features");
|
||||
+#endif
|
||||
securityfs_remove(aa_fs_dentry);
|
||||
aa_fs_dentry = NULL;
|
||||
}
|
||||
@@ -213,7 +217,17 @@ int __init aa_create_aafs(void)
|
||||
aa_fs_dentry = NULL;
|
||||
goto error;
|
||||
}
|
||||
-
|
||||
+#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
|
||||
+ error = aafs_create("matching", 0444, &aa_fs_matching_fops);
|
||||
+ if (error)
|
||||
+ goto error;
|
||||
+ error = aafs_create("features", 0444, &aa_fs_features_fops);
|
||||
+ if (error)
|
||||
+ goto error;
|
||||
+#endif
|
||||
+ error = aafs_create("profiles", 0440, &aa_fs_profiles_fops);
|
||||
+ if (error)
|
||||
+ goto error;
|
||||
error = aafs_create(".load", 0640, &aa_fs_profile_load);
|
||||
if (error)
|
||||
goto error;
|
||||
--- a/security/apparmor/include/apparmorfs.h
|
||||
+++ b/security/apparmor/include/apparmorfs.h
|
||||
@@ -17,4 +17,10 @@
|
||||
|
||||
extern void __init aa_destroy_aafs(void);
|
||||
|
||||
+#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
|
||||
+extern const struct file_operations aa_fs_matching_fops;
|
||||
+extern const struct file_operations aa_fs_features_fops;
|
||||
+extern const struct file_operations aa_fs_profiles_fops;
|
||||
+#endif
|
||||
+
|
||||
#endif /* __AA_APPARMORFS_H */
|
@ -0,0 +1,518 @@
|
||||
From: John Johansen <john.johansen@canonical.com>
|
||||
Date: Mon, 4 Oct 2010 15:03:36 -0700
|
||||
Subject: AppArmor: compatibility patch for v5 network control
|
||||
Patch-mainline: 2.6.37?
|
||||
|
||||
Add compatibility for v5 network rules.
|
||||
|
||||
Signed-off-by: John Johansen <john.johansen@canonical.com>
|
||||
Acked-by: Jeff Mahoney <jeffm@suse.com>
|
||||
---
|
||||
include/linux/lsm_audit.h | 4
|
||||
security/apparmor/Makefile | 6 +
|
||||
security/apparmor/include/net.h | 40 ++++++++
|
||||
security/apparmor/include/policy.h | 3
|
||||
security/apparmor/lsm.c | 112 ++++++++++++++++++++++
|
||||
security/apparmor/net.c | 170 ++++++++++++++++++++++++++++++++++
|
||||
security/apparmor/policy.c | 1
|
||||
security/apparmor/policy_unpack.c | 48 +++++++++
|
||||
8 files changed, 381 insertions(+), 2 deletions(-)
|
||||
create mode 100644 security/apparmor/include/net.h
|
||||
create mode 100644 security/apparmor/net.c
|
||||
|
||||
--- a/include/linux/lsm_audit.h
|
||||
+++ b/include/linux/lsm_audit.h
|
||||
@@ -123,6 +123,10 @@ struct common_audit_data {
|
||||
u32 denied;
|
||||
uid_t ouid;
|
||||
} fs;
|
||||
+ struct {
|
||||
+ int type, protocol;
|
||||
+ struct sock *sk;
|
||||
+ } net;
|
||||
};
|
||||
} apparmor_audit_data;
|
||||
#endif
|
||||
--- a/security/apparmor/Makefile
|
||||
+++ b/security/apparmor/Makefile
|
||||
@@ -4,17 +4,21 @@ obj-$(CONFIG_SECURITY_APPARMOR) += appar
|
||||
|
||||
apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
|
||||
path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
|
||||
- resource.o sid.o file.o
|
||||
+ resource.o sid.o file.o net.o
|
||||
|
||||
clean-files: capability_names.h af_names.h
|
||||
|
||||
quiet_cmd_make-caps = GEN $@
|
||||
cmd_make-caps = echo "static const char *capability_names[] = {" > $@ ; sed -n -e "/CAP_FS_MASK/d" -e "s/^\#define[ \\t]\\+CAP_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z >> $@ ; echo "};" >> $@
|
||||
|
||||
+quiet_cmd_make-af = GEN $@
|
||||
+cmd_make-af = echo "static const char *address_family_names[] = {" > $@ ; sed -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "s/^\#define[ \\t]\\+AF_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z >> $@ ; echo "};" >> $@
|
||||
+
|
||||
quiet_cmd_make-rlim = GEN $@
|
||||
cmd_make-rlim = echo "static const char *rlim_names[] = {" > $@ ; sed -n --e "/AF_MAX/d" -e "s/^\# \\?define[ \\t]\\+RLIMIT_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z >> $@ ; echo "};" >> $@ ; echo "static const int rlim_map[] = {" >> $@ ; sed -n -e "/AF_MAX/d" -e "s/^\# \\?define[ \\t]\\+\\(RLIMIT_[A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/\\1,/p" $< >> $@ ; echo "};" >> $@
|
||||
|
||||
$(obj)/capability.o : $(obj)/capability_names.h
|
||||
+$(obj)/net.o : $(obj)/af_names.h
|
||||
$(obj)/resource.o : $(obj)/rlim_names.h
|
||||
$(obj)/capability_names.h : $(srctree)/include/linux/capability.h
|
||||
$(call cmd,make-caps)
|
||||
--- /dev/null
|
||||
+++ b/security/apparmor/include/net.h
|
||||
@@ -0,0 +1,40 @@
|
||||
+/*
|
||||
+ * AppArmor security module
|
||||
+ *
|
||||
+ * This file contains AppArmor network mediation definitions.
|
||||
+ *
|
||||
+ * Copyright (C) 1998-2008 Novell/SUSE
|
||||
+ * Copyright 2009-2010 Canonical Ltd.
|
||||
+ *
|
||||
+ * 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 of the
|
||||
+ * License.
|
||||
+ */
|
||||
+
|
||||
+#ifndef __AA_NET_H
|
||||
+#define __AA_NET_H
|
||||
+
|
||||
+#include <net/sock.h>
|
||||
+
|
||||
+/* struct aa_net - network confinement data
|
||||
+ * @allowed: basic network families permissions
|
||||
+ * @audit_network: which network permissions to force audit
|
||||
+ * @quiet_network: which network permissions to quiet rejects
|
||||
+ */
|
||||
+struct aa_net {
|
||||
+ u16 allow[AF_MAX];
|
||||
+ u16 audit[AF_MAX];
|
||||
+ u16 quiet[AF_MAX];
|
||||
+};
|
||||
+
|
||||
+extern int aa_net_perm(int op, struct aa_profile *profile, u16 family,
|
||||
+ int type, int protocol, struct sock *sk);
|
||||
+extern int aa_revalidate_sk(int op, struct sock *sk);
|
||||
+
|
||||
+static inline void aa_free_net_rules(struct aa_net *new)
|
||||
+{
|
||||
+ /* NOP */
|
||||
+}
|
||||
+
|
||||
+#endif /* __AA_NET_H */
|
||||
--- a/security/apparmor/include/policy.h
|
||||
+++ b/security/apparmor/include/policy.h
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "capability.h"
|
||||
#include "domain.h"
|
||||
#include "file.h"
|
||||
+#include "net.h"
|
||||
#include "resource.h"
|
||||
|
||||
extern const char *profile_mode_names[];
|
||||
@@ -145,6 +146,7 @@ struct aa_namespace {
|
||||
* @size: the memory consumed by this profiles rules
|
||||
* @file: The set of rules governing basic file access and domain transitions
|
||||
* @caps: capabilities for the profile
|
||||
+ * @net: network controls for the profile
|
||||
* @rlimits: rlimits for the profile
|
||||
*
|
||||
* The AppArmor profile contains the basic confinement data. Each profile
|
||||
@@ -181,6 +183,7 @@ struct aa_profile {
|
||||
|
||||
struct aa_file_rules file;
|
||||
struct aa_caps caps;
|
||||
+ struct aa_net net;
|
||||
struct aa_rlimit rlimits;
|
||||
};
|
||||
|
||||
--- a/security/apparmor/lsm.c
|
||||
+++ b/security/apparmor/lsm.c
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "include/context.h"
|
||||
#include "include/file.h"
|
||||
#include "include/ipc.h"
|
||||
+#include "include/net.h"
|
||||
#include "include/path.h"
|
||||
#include "include/policy.h"
|
||||
#include "include/procattr.h"
|
||||
@@ -619,6 +620,104 @@ static int apparmor_task_setrlimit(struc
|
||||
return error;
|
||||
}
|
||||
|
||||
+static int apparmor_socket_create(int family, int type, int protocol, int kern)
|
||||
+{
|
||||
+ struct aa_profile *profile;
|
||||
+ int error = 0;
|
||||
+
|
||||
+ if (kern)
|
||||
+ return 0;
|
||||
+
|
||||
+ profile = __aa_current_profile();
|
||||
+ if (!unconfined(profile))
|
||||
+ error = aa_net_perm(OP_CREATE, profile, family, type, protocol,
|
||||
+ NULL);
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+static int apparmor_socket_bind(struct socket *sock,
|
||||
+ struct sockaddr *address, int addrlen)
|
||||
+{
|
||||
+ struct sock *sk = sock->sk;
|
||||
+
|
||||
+ return aa_revalidate_sk(OP_BIND, sk);
|
||||
+}
|
||||
+
|
||||
+static int apparmor_socket_connect(struct socket *sock,
|
||||
+ struct sockaddr *address, int addrlen)
|
||||
+{
|
||||
+ struct sock *sk = sock->sk;
|
||||
+
|
||||
+ return aa_revalidate_sk(OP_CONNECT, sk);
|
||||
+}
|
||||
+
|
||||
+static int apparmor_socket_listen(struct socket *sock, int backlog)
|
||||
+{
|
||||
+ struct sock *sk = sock->sk;
|
||||
+
|
||||
+ return aa_revalidate_sk(OP_LISTEN, sk);
|
||||
+}
|
||||
+
|
||||
+static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
|
||||
+{
|
||||
+ struct sock *sk = sock->sk;
|
||||
+
|
||||
+ return aa_revalidate_sk(OP_ACCEPT, sk);
|
||||
+}
|
||||
+
|
||||
+static int apparmor_socket_sendmsg(struct socket *sock,
|
||||
+ struct msghdr *msg, int size)
|
||||
+{
|
||||
+ struct sock *sk = sock->sk;
|
||||
+
|
||||
+ return aa_revalidate_sk(OP_SENDMSG, sk);
|
||||
+}
|
||||
+
|
||||
+static int apparmor_socket_recvmsg(struct socket *sock,
|
||||
+ struct msghdr *msg, int size, int flags)
|
||||
+{
|
||||
+ struct sock *sk = sock->sk;
|
||||
+
|
||||
+ return aa_revalidate_sk(OP_RECVMSG, sk);
|
||||
+}
|
||||
+
|
||||
+static int apparmor_socket_getsockname(struct socket *sock)
|
||||
+{
|
||||
+ struct sock *sk = sock->sk;
|
||||
+
|
||||
+ return aa_revalidate_sk(OP_GETSOCKNAME, sk);
|
||||
+}
|
||||
+
|
||||
+static int apparmor_socket_getpeername(struct socket *sock)
|
||||
+{
|
||||
+ struct sock *sk = sock->sk;
|
||||
+
|
||||
+ return aa_revalidate_sk(OP_GETPEERNAME, sk);
|
||||
+}
|
||||
+
|
||||
+static int apparmor_socket_getsockopt(struct socket *sock, int level,
|
||||
+ int optname)
|
||||
+{
|
||||
+ struct sock *sk = sock->sk;
|
||||
+
|
||||
+ return aa_revalidate_sk(OP_GETSOCKOPT, sk);
|
||||
+}
|
||||
+
|
||||
+static int apparmor_socket_setsockopt(struct socket *sock, int level,
|
||||
+ int optname)
|
||||
+{
|
||||
+ struct sock *sk = sock->sk;
|
||||
+
|
||||
+ return aa_revalidate_sk(OP_SETSOCKOPT, sk);
|
||||
+}
|
||||
+
|
||||
+static int apparmor_socket_shutdown(struct socket *sock, int how)
|
||||
+{
|
||||
+ struct sock *sk = sock->sk;
|
||||
+
|
||||
+ return aa_revalidate_sk(OP_SOCK_SHUTDOWN, sk);
|
||||
+}
|
||||
+
|
||||
static struct security_operations apparmor_ops = {
|
||||
.name = "apparmor",
|
||||
|
||||
@@ -650,6 +749,19 @@ static struct security_operations apparm
|
||||
.getprocattr = apparmor_getprocattr,
|
||||
.setprocattr = apparmor_setprocattr,
|
||||
|
||||
+ .socket_create = apparmor_socket_create,
|
||||
+ .socket_bind = apparmor_socket_bind,
|
||||
+ .socket_connect = apparmor_socket_connect,
|
||||
+ .socket_listen = apparmor_socket_listen,
|
||||
+ .socket_accept = apparmor_socket_accept,
|
||||
+ .socket_sendmsg = apparmor_socket_sendmsg,
|
||||
+ .socket_recvmsg = apparmor_socket_recvmsg,
|
||||
+ .socket_getsockname = apparmor_socket_getsockname,
|
||||
+ .socket_getpeername = apparmor_socket_getpeername,
|
||||
+ .socket_getsockopt = apparmor_socket_getsockopt,
|
||||
+ .socket_setsockopt = apparmor_socket_setsockopt,
|
||||
+ .socket_shutdown = apparmor_socket_shutdown,
|
||||
+
|
||||
.cred_alloc_blank = apparmor_cred_alloc_blank,
|
||||
.cred_free = apparmor_cred_free,
|
||||
.cred_prepare = apparmor_cred_prepare,
|
||||
--- /dev/null
|
||||
+++ b/security/apparmor/net.c
|
||||
@@ -0,0 +1,170 @@
|
||||
+/*
|
||||
+ * AppArmor security module
|
||||
+ *
|
||||
+ * This file contains AppArmor network mediation
|
||||
+ *
|
||||
+ * Copyright (C) 1998-2008 Novell/SUSE
|
||||
+ * Copyright 2009-2010 Canonical Ltd.
|
||||
+ *
|
||||
+ * 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 of the
|
||||
+ * License.
|
||||
+ */
|
||||
+
|
||||
+#include "include/apparmor.h"
|
||||
+#include "include/audit.h"
|
||||
+#include "include/context.h"
|
||||
+#include "include/net.h"
|
||||
+#include "include/policy.h"
|
||||
+
|
||||
+#include "af_names.h"
|
||||
+
|
||||
+static const char *sock_type_names[] = {
|
||||
+ "unknown(0)",
|
||||
+ "stream",
|
||||
+ "dgram",
|
||||
+ "raw",
|
||||
+ "rdm",
|
||||
+ "seqpacket",
|
||||
+ "dccp",
|
||||
+ "unknown(7)",
|
||||
+ "unknown(8)",
|
||||
+ "unknown(9)",
|
||||
+ "packet",
|
||||
+};
|
||||
+
|
||||
+/* audit callback for net specific fields */
|
||||
+static void audit_cb(struct audit_buffer *ab, void *va)
|
||||
+{
|
||||
+ struct common_audit_data *sa = va;
|
||||
+
|
||||
+ audit_log_format(ab, " family=");
|
||||
+ if (address_family_names[sa->u.net.family]) {
|
||||
+ audit_log_string(ab, address_family_names[sa->u.net.family]);
|
||||
+ } else {
|
||||
+ audit_log_format(ab, " \"unknown(%d)\"", sa->u.net.family);
|
||||
+ }
|
||||
+
|
||||
+ audit_log_format(ab, " sock_type=");
|
||||
+ if (sock_type_names[sa->aad.net.type]) {
|
||||
+ audit_log_string(ab, sock_type_names[sa->aad.net.type]);
|
||||
+ } else {
|
||||
+ audit_log_format(ab, "\"unknown(%d)\"", sa->aad.net.type);
|
||||
+ }
|
||||
+
|
||||
+ audit_log_format(ab, " protocol=%d", sa->aad.net.protocol);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * audit_net - audit network access
|
||||
+ * @profile: profile being enforced (NOT NULL)
|
||||
+ * @op: operation being checked
|
||||
+ * @family: network family
|
||||
+ * @type: network type
|
||||
+ * @protocol: network protocol
|
||||
+ * @sk: socket auditing is being applied to
|
||||
+ * @error: error code for failure else 0
|
||||
+ *
|
||||
+ * Returns: %0 or sa->error else other errorcode on failure
|
||||
+ */
|
||||
+static int audit_net(struct aa_profile *profile, int op, u16 family, int type,
|
||||
+ int protocol, struct sock *sk, int error)
|
||||
+{
|
||||
+ int audit_type = AUDIT_APPARMOR_AUTO;
|
||||
+ struct common_audit_data sa;
|
||||
+ if (sk) {
|
||||
+ COMMON_AUDIT_DATA_INIT(&sa, NET);
|
||||
+ } else {
|
||||
+ COMMON_AUDIT_DATA_INIT(&sa, NONE);
|
||||
+ }
|
||||
+ /* todo fill in socket addr info */
|
||||
+
|
||||
+ sa.aad.op = op,
|
||||
+ sa.u.net.family = family;
|
||||
+ sa.u.net.sk = sk;
|
||||
+ sa.aad.net.type = type;
|
||||
+ sa.aad.net.protocol = protocol;
|
||||
+ sa.aad.error = error;
|
||||
+
|
||||
+ if (likely(!sa.aad.error)) {
|
||||
+ u16 audit_mask = profile->net.audit[sa.u.net.family];
|
||||
+ if (likely((AUDIT_MODE(profile) != AUDIT_ALL) &&
|
||||
+ !(1 << sa.aad.net.type & audit_mask)))
|
||||
+ return 0;
|
||||
+ audit_type = AUDIT_APPARMOR_AUDIT;
|
||||
+ } else {
|
||||
+ u16 quiet_mask = profile->net.quiet[sa.u.net.family];
|
||||
+ u16 kill_mask = 0;
|
||||
+ u16 denied = (1 << sa.aad.net.type) & ~quiet_mask;
|
||||
+
|
||||
+ if (denied & kill_mask)
|
||||
+ audit_type = AUDIT_APPARMOR_KILL;
|
||||
+
|
||||
+ if ((denied & quiet_mask) &&
|
||||
+ AUDIT_MODE(profile) != AUDIT_NOQUIET &&
|
||||
+ AUDIT_MODE(profile) != AUDIT_ALL)
|
||||
+ return COMPLAIN_MODE(profile) ? 0 : sa.aad.error;
|
||||
+ }
|
||||
+
|
||||
+ return aa_audit(audit_type, profile, GFP_KERNEL, &sa, audit_cb);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * aa_net_perm - very course network access check
|
||||
+ * @op: operation being checked
|
||||
+ * @profile: profile being enforced (NOT NULL)
|
||||
+ * @family: network family
|
||||
+ * @type: network type
|
||||
+ * @protocol: network protocol
|
||||
+ *
|
||||
+ * Returns: %0 else error if permission denied
|
||||
+ */
|
||||
+int aa_net_perm(int op, struct aa_profile *profile, u16 family, int type,
|
||||
+ int protocol, struct sock *sk)
|
||||
+{
|
||||
+ u16 family_mask;
|
||||
+ int error;
|
||||
+
|
||||
+ if ((family < 0) || (family >= AF_MAX))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if ((type < 0) || (type >= SOCK_MAX))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ /* unix domain and netlink sockets are handled by ipc */
|
||||
+ if (family == AF_UNIX || family == AF_NETLINK)
|
||||
+ return 0;
|
||||
+
|
||||
+ family_mask = profile->net.allow[family];
|
||||
+
|
||||
+ error = (family_mask & (1 << type)) ? 0 : -EACCES;
|
||||
+
|
||||
+ return audit_net(profile, op, family, type, protocol, sk, error);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * aa_revalidate_sk - Revalidate access to a sock
|
||||
+ * @op: operation being checked
|
||||
+ * @sk: sock being revalidated (NOT NULL)
|
||||
+ *
|
||||
+ * Returns: %0 else error if permission denied
|
||||
+ */
|
||||
+int aa_revalidate_sk(int op, struct sock *sk)
|
||||
+{
|
||||
+ struct aa_profile *profile;
|
||||
+ int error = 0;
|
||||
+
|
||||
+ /* aa_revalidate_sk should not be called from interrupt context
|
||||
+ * don't mediate these calls as they are not task related
|
||||
+ */
|
||||
+ if (in_interrupt())
|
||||
+ return 0;
|
||||
+
|
||||
+ profile = __aa_current_profile();
|
||||
+ if (!unconfined(profile))
|
||||
+ error = aa_net_perm(op, profile, sk->sk_family, sk->sk_type,
|
||||
+ sk->sk_protocol, sk);
|
||||
+
|
||||
+ return error;
|
||||
+}
|
||||
--- a/security/apparmor/policy.c
|
||||
+++ b/security/apparmor/policy.c
|
||||
@@ -745,6 +745,7 @@ static void free_profile(struct aa_profi
|
||||
|
||||
aa_free_file_rules(&profile->file);
|
||||
aa_free_cap_rules(&profile->caps);
|
||||
+ aa_free_net_rules(&profile->net);
|
||||
aa_free_rlimit_rules(&profile->rlimits);
|
||||
|
||||
aa_free_sid(profile->sid);
|
||||
--- a/security/apparmor/policy_unpack.c
|
||||
+++ b/security/apparmor/policy_unpack.c
|
||||
@@ -190,6 +190,19 @@ fail:
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static bool unpack_u16(struct aa_ext *e, u16 *data, const char *name)
|
||||
+{
|
||||
+ if (unpack_nameX(e, AA_U16, name)) {
|
||||
+ if (!inbounds(e, sizeof(u16)))
|
||||
+ return 0;
|
||||
+ if (data)
|
||||
+ *data = le16_to_cpu(get_unaligned((u16 *) e->pos));
|
||||
+ e->pos += sizeof(u16);
|
||||
+ return 1;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name)
|
||||
{
|
||||
if (unpack_nameX(e, AA_U32, name)) {
|
||||
@@ -468,7 +481,8 @@ static struct aa_profile *unpack_profile
|
||||
{
|
||||
struct aa_profile *profile = NULL;
|
||||
const char *name = NULL;
|
||||
- int error = -EPROTO;
|
||||
+ size_t size = 0;
|
||||
+ int i, error = -EPROTO;
|
||||
kernel_cap_t tmpcap;
|
||||
u32 tmp;
|
||||
|
||||
@@ -559,6 +573,38 @@ static struct aa_profile *unpack_profile
|
||||
if (!unpack_rlimits(e, profile))
|
||||
goto fail;
|
||||
|
||||
+ size = unpack_array(e, "net_allowed_af");
|
||||
+ if (size) {
|
||||
+
|
||||
+ for (i = 0; i < size; i++) {
|
||||
+ /* discard extraneous rules that this kernel will
|
||||
+ * never request
|
||||
+ */
|
||||
+ if (i > AF_MAX) {
|
||||
+ u16 tmp;
|
||||
+ if (!unpack_u16(e, &tmp, NULL) ||
|
||||
+ !unpack_u16(e, &tmp, NULL) ||
|
||||
+ !unpack_u16(e, &tmp, NULL))
|
||||
+ goto fail;
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (!unpack_u16(e, &profile->net.allow[i], NULL))
|
||||
+ goto fail;
|
||||
+ if (!unpack_u16(e, &profile->net.audit[i], NULL))
|
||||
+ goto fail;
|
||||
+ if (!unpack_u16(e, &profile->net.quiet[i], NULL))
|
||||
+ goto fail;
|
||||
+ }
|
||||
+ if (!unpack_nameX(e, AA_ARRAYEND, NULL))
|
||||
+ goto fail;
|
||||
+ /*
|
||||
+ * allow unix domain and netlink sockets they are handled
|
||||
+ * by IPC
|
||||
+ */
|
||||
+ }
|
||||
+ profile->net.allow[AF_UNIX] = 0xffff;
|
||||
+ profile->net.allow[AF_NETLINK] = 0xffff;
|
||||
+
|
||||
/* get file rules */
|
||||
profile->file.dfa = unpack_dfa(e);
|
||||
if (IS_ERR(profile->file.dfa)) {
|
@ -1,69 +0,0 @@
|
||||
From: Dimitri Sivanich <sivanich@sgi.com>
|
||||
Subject: Expose the irq_desc node as /proc/irq/*/node.
|
||||
References: bnc#566745, fate#306952
|
||||
Patch-mainline: not yet
|
||||
|
||||
This file provides device hardware locality information for apps desiring
|
||||
to include hardware locality in irq mapping decisions.
|
||||
|
||||
Signed-off-by: Dimitri Sivanich <sivanich@sgi.com>
|
||||
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||||
Signed-off-by: Rafael J. Wysocki <rjw@suse.de>
|
||||
---
|
||||
|
||||
Documentation/filesystems/proc.txt | 4 ++++
|
||||
kernel/irq/proc.c | 23 +++++++++++++++++++++++
|
||||
2 files changed, 27 insertions(+)
|
||||
|
||||
--- a/Documentation/filesystems/proc.txt
|
||||
+++ b/Documentation/filesystems/proc.txt
|
||||
@@ -566,6 +566,10 @@ The default_smp_affinity mask applies to
|
||||
IRQs which have not yet been allocated/activated, and hence which lack a
|
||||
/proc/irq/[0-9]* directory.
|
||||
|
||||
+The node file on an SMP system shows the node to which the device using the IRQ
|
||||
+reports itself as being attached. This hardware locality information does not
|
||||
+include information about any possible driver locality preference.
|
||||
+
|
||||
prof_cpu_mask specifies which CPUs are to be profiled by the system wide
|
||||
profiler. Default value is ffffffff (all cpus).
|
||||
|
||||
--- a/kernel/irq/proc.c
|
||||
+++ b/kernel/irq/proc.c
|
||||
@@ -146,6 +146,26 @@ static const struct file_operations defa
|
||||
.release = single_release,
|
||||
.write = default_affinity_write,
|
||||
};
|
||||
+
|
||||
+static int irq_node_proc_show(struct seq_file *m, void *v)
|
||||
+{
|
||||
+ struct irq_desc *desc = irq_to_desc((long) m->private);
|
||||
+
|
||||
+ seq_printf(m, "%d\n", desc->node);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int irq_node_proc_open(struct inode *inode, struct file *file)
|
||||
+{
|
||||
+ return single_open(file, irq_node_proc_show, PDE(inode)->data);
|
||||
+}
|
||||
+
|
||||
+static const struct file_operations irq_node_proc_fops = {
|
||||
+ .open = irq_node_proc_open,
|
||||
+ .read = seq_read,
|
||||
+ .llseek = seq_lseek,
|
||||
+ .release = single_release,
|
||||
+};
|
||||
#endif
|
||||
|
||||
static int irq_spurious_proc_show(struct seq_file *m, void *v)
|
||||
@@ -230,6 +250,9 @@ void register_irq_proc(unsigned int irq,
|
||||
/* create /proc/irq/<irq>/smp_affinity */
|
||||
proc_create_data("smp_affinity", 0600, desc->dir,
|
||||
&irq_affinity_proc_fops, (void *)(long)irq);
|
||||
+
|
||||
+ proc_create_data("node", 0444, desc->dir,
|
||||
+ &irq_node_proc_fops, (void *)(long)irq);
|
||||
#endif
|
||||
|
||||
proc_create_data("spurious", 0444, desc->dir,
|
@ -0,0 +1,30 @@
|
||||
From: Thomas Renninger <trenn@suse.de>
|
||||
Subject: Only use 32 bit addresses if they have a valid length
|
||||
References: bug#581644
|
||||
Patch-Mainline: not yet
|
||||
|
||||
Also not sure whether it will help, but it's a fix.
|
||||
|
||||
Please remove this patch again after a while also if it's not
|
||||
mainline.
|
||||
|
||||
---
|
||||
drivers/acpi/acpica/tbfadt.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/acpi/acpica/tbfadt.c
|
||||
+++ b/drivers/acpi/acpica/tbfadt.c
|
||||
@@ -550,11 +550,12 @@ static void acpi_tb_validate_fadt(void)
|
||||
(!address64->address && length)) {
|
||||
ACPI_WARNING((AE_INFO,
|
||||
"Optional field %s has zero address or length: "
|
||||
- "0x%8.8X%8.8X/0x%X",
|
||||
+ "0x%8.8X%8.8X/0x%X - not using it",
|
||||
name,
|
||||
ACPI_FORMAT_UINT64(address64->
|
||||
address),
|
||||
length));
|
||||
+ address64->address = 0;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
From: jbeulich@novell.com
|
||||
Subject: fix unwind annotations
|
||||
Patch-mainline: queued for 2.6.39
|
||||
|
||||
--- head-2011-02-17.orig/arch/x86/lib/semaphore_32.S 2011-03-01 15:03:45.000000000 +0100
|
||||
+++ head-2011-02-17/arch/x86/lib/semaphore_32.S 2011-03-01 15:04:50.000000000 +0100
|
||||
@@ -36,7 +36,7 @@
|
||||
*/
|
||||
#ifdef CONFIG_SMP
|
||||
ENTRY(__write_lock_failed)
|
||||
- CFI_STARTPROC simple
|
||||
+ CFI_STARTPROC
|
||||
FRAME
|
||||
2: LOCK_PREFIX
|
||||
addl $ RW_LOCK_BIAS,(%eax)
|
@ -0,0 +1,32 @@
|
||||
From: Thomas Renninger <trenn@suse.de>
|
||||
Subject: Fix huge and wronge C-state drawings due to uninitialized start/end timestamps
|
||||
Patch-Mainline: not yet
|
||||
References: none
|
||||
|
||||
Signed-off-by: Thomas Renninger <trenn@suse.de>
|
||||
|
||||
---
|
||||
tools/perf/builtin-timechart.c | 9 ++++++++-
|
||||
1 file changed, 8 insertions(+), 1 deletion(-)
|
||||
|
||||
Index: linux-2.6.37-master/tools/perf/builtin-timechart.c
|
||||
===================================================================
|
||||
--- linux-2.6.37-master.orig/tools/perf/builtin-timechart.c
|
||||
+++ linux-2.6.37-master/tools/perf/builtin-timechart.c
|
||||
@@ -654,8 +654,15 @@ static void draw_c_p_states(void)
|
||||
* two pass drawing so that the P state bars are on top of the C state blocks
|
||||
*/
|
||||
while (pwr) {
|
||||
- if (pwr->type == CSTATE)
|
||||
+ if (pwr->type == CSTATE) {
|
||||
+ /* If the first event is an _end event, start timestamp is zero
|
||||
+ -> ignore these */
|
||||
+ if (pwr->start_time == 0 || pwr->end_time == 0) {
|
||||
+ pwr = pwr->next;
|
||||
+ continue;
|
||||
+ }
|
||||
svg_cstate(pwr->cpu, pwr->start_time, pwr->end_time, pwr->state);
|
||||
+ }
|
||||
pwr = pwr->next;
|
||||
}
|
||||
|
@ -1,266 +0,0 @@
|
||||
From: Borislav Petkov <borislav.petkov@amd.com>
|
||||
Date: Wed, 31 Mar 2010 19:56:42 +0000 (+0200)
|
||||
Subject: powernow-k8: Add core performance boost support
|
||||
Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-tip.git
|
||||
Git-commit: 73860c6b2fd159a35637e233d735e36887c266ad
|
||||
References: bnc#602209
|
||||
Patch-mainline: 2.6.35-rc1
|
||||
|
||||
powernow-k8: Add core performance boost support
|
||||
|
||||
Starting with F10h, revE, AMD processors add support for a dynamic
|
||||
core boosting feature called Core Performance Boost. When a specific
|
||||
condition is present, a subset of the cores on a system are boosted
|
||||
beyond their P0 operating frequency to speed up the performance of
|
||||
single-threaded applications.
|
||||
|
||||
In the normal case, the system comes out of reset with core boosting
|
||||
enabled. This patch adds a sysfs knob with which core boosting can be
|
||||
switched on or off for benchmarking purposes.
|
||||
|
||||
While at it, make the CPB code hotplug-aware so that taking cores
|
||||
offline wouldn't interfere with boosting the remaining online cores.
|
||||
Furthermore, add cpu_online_mask hotplug protection as suggested by
|
||||
Andrew.
|
||||
|
||||
Finally, cleanup the driver init codepath and update copyrights.
|
||||
|
||||
Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
|
||||
LKML-Reference: <1270065406-1814-3-git-send-email-bp@amd64.org>
|
||||
Reviewed-by: Thomas Renninger <trenn@suse.de>
|
||||
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
|
||||
Acked-by: Jeff Mahoney <jeffm@suse.com>
|
||||
---
|
||||
|
||||
arch/x86/kernel/cpu/cpufreq/powernow-k8.c | 161 ++++++++++++++++++++++++++++--
|
||||
arch/x86/kernel/cpu/cpufreq/powernow-k8.h | 2
|
||||
2 files changed, 151 insertions(+), 12 deletions(-)
|
||||
|
||||
--- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
|
||||
+++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
|
||||
@@ -1,6 +1,5 @@
|
||||
-
|
||||
/*
|
||||
- * (c) 2003-2006 Advanced Micro Devices, Inc.
|
||||
+ * (c) 2003-2010 Advanced Micro Devices, Inc.
|
||||
* Your use of this code is subject to the terms and conditions of the
|
||||
* GNU general public license version 2. See "COPYING" or
|
||||
* http://www.gnu.org/licenses/gpl.html
|
||||
@@ -54,6 +53,10 @@ static DEFINE_PER_CPU(struct powernow_k8
|
||||
|
||||
static int cpu_family = CPU_OPTERON;
|
||||
|
||||
+/* core performance boost */
|
||||
+static bool cpb_capable, cpb_enabled;
|
||||
+static struct msr *msrs;
|
||||
+
|
||||
#ifndef CONFIG_SMP
|
||||
static inline const struct cpumask *cpu_core_mask(int cpu)
|
||||
{
|
||||
@@ -1394,8 +1397,77 @@ out:
|
||||
return khz;
|
||||
}
|
||||
|
||||
+static void _cpb_toggle_msrs(bool t)
|
||||
+{
|
||||
+ int cpu;
|
||||
+
|
||||
+ get_online_cpus();
|
||||
+
|
||||
+ rdmsr_on_cpus(cpu_online_mask, MSR_K7_HWCR, msrs);
|
||||
+
|
||||
+ for_each_cpu(cpu, cpu_online_mask) {
|
||||
+ struct msr *reg = per_cpu_ptr(msrs, cpu);
|
||||
+ if (t)
|
||||
+ reg->l &= ~BIT(25);
|
||||
+ else
|
||||
+ reg->l |= BIT(25);
|
||||
+ }
|
||||
+ wrmsr_on_cpus(cpu_online_mask, MSR_K7_HWCR, msrs);
|
||||
+
|
||||
+ put_online_cpus();
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Switch on/off core performance boosting.
|
||||
+ *
|
||||
+ * 0=disable
|
||||
+ * 1=enable.
|
||||
+ */
|
||||
+static void cpb_toggle(bool t)
|
||||
+{
|
||||
+ if (!cpb_capable)
|
||||
+ return;
|
||||
+
|
||||
+ if (t && !cpb_enabled) {
|
||||
+ cpb_enabled = true;
|
||||
+ _cpb_toggle_msrs(t);
|
||||
+ printk(KERN_INFO PFX "Core Boosting enabled.\n");
|
||||
+ } else if (!t && cpb_enabled) {
|
||||
+ cpb_enabled = false;
|
||||
+ _cpb_toggle_msrs(t);
|
||||
+ printk(KERN_INFO PFX "Core Boosting disabled.\n");
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static ssize_t store_cpb(struct cpufreq_policy *policy, const char *buf,
|
||||
+ size_t count)
|
||||
+{
|
||||
+ int ret = -EINVAL;
|
||||
+ unsigned long val = 0;
|
||||
+
|
||||
+ ret = strict_strtoul(buf, 10, &val);
|
||||
+ if (!ret && (val == 0 || val == 1) && cpb_capable)
|
||||
+ cpb_toggle(val);
|
||||
+ else
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ return count;
|
||||
+}
|
||||
+
|
||||
+static ssize_t show_cpb(struct cpufreq_policy *policy, char *buf)
|
||||
+{
|
||||
+ return sprintf(buf, "%u\n", cpb_enabled);
|
||||
+}
|
||||
+
|
||||
+#define define_one_rw(_name) \
|
||||
+static struct freq_attr _name = \
|
||||
+__ATTR(_name, 0644, show_##_name, store_##_name)
|
||||
+
|
||||
+define_one_rw(cpb);
|
||||
+
|
||||
static struct freq_attr *powernow_k8_attr[] = {
|
||||
&cpufreq_freq_attr_scaling_available_freqs,
|
||||
+ &cpb,
|
||||
NULL,
|
||||
};
|
||||
|
||||
@@ -1411,10 +1483,51 @@ static struct cpufreq_driver cpufreq_amd
|
||||
.attr = powernow_k8_attr,
|
||||
};
|
||||
|
||||
+/*
|
||||
+ * Clear the boost-disable flag on the CPU_DOWN path so that this cpu
|
||||
+ * cannot block the remaining ones from boosting. On the CPU_UP path we
|
||||
+ * simply keep the boost-disable flag in sync with the current global
|
||||
+ * state.
|
||||
+ */
|
||||
+static int __cpuinit cpb_notify(struct notifier_block *nb, unsigned long action,
|
||||
+ void *hcpu)
|
||||
+{
|
||||
+ unsigned cpu = (long)hcpu;
|
||||
+ u32 lo, hi;
|
||||
+
|
||||
+ switch (action) {
|
||||
+ case CPU_UP_PREPARE:
|
||||
+ case CPU_UP_PREPARE_FROZEN:
|
||||
+
|
||||
+ if (!cpb_enabled) {
|
||||
+ rdmsr_on_cpu(cpu, MSR_K7_HWCR, &lo, &hi);
|
||||
+ lo |= BIT(25);
|
||||
+ wrmsr_on_cpu(cpu, MSR_K7_HWCR, lo, hi);
|
||||
+ }
|
||||
+ break;
|
||||
+
|
||||
+ case CPU_DOWN_PREPARE:
|
||||
+ case CPU_DOWN_PREPARE_FROZEN:
|
||||
+ rdmsr_on_cpu(cpu, MSR_K7_HWCR, &lo, &hi);
|
||||
+ lo &= ~BIT(25);
|
||||
+ wrmsr_on_cpu(cpu, MSR_K7_HWCR, lo, hi);
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return NOTIFY_OK;
|
||||
+}
|
||||
+
|
||||
+static struct notifier_block __cpuinitdata cpb_nb = {
|
||||
+ .notifier_call = cpb_notify,
|
||||
+};
|
||||
+
|
||||
/* driver entry point for init */
|
||||
static int __cpuinit powernowk8_init(void)
|
||||
{
|
||||
- unsigned int i, supported_cpus = 0;
|
||||
+ unsigned int i, supported_cpus = 0, cpu;
|
||||
|
||||
for_each_online_cpu(i) {
|
||||
int rc;
|
||||
@@ -1423,15 +1536,36 @@ static int __cpuinit powernowk8_init(voi
|
||||
supported_cpus++;
|
||||
}
|
||||
|
||||
- if (supported_cpus == num_online_cpus()) {
|
||||
- printk(KERN_INFO PFX "Found %d %s "
|
||||
- "processors (%d cpu cores) (" VERSION ")\n",
|
||||
- num_online_nodes(),
|
||||
- boot_cpu_data.x86_model_id, supported_cpus);
|
||||
- return cpufreq_register_driver(&cpufreq_amd64_driver);
|
||||
+ if (supported_cpus != num_online_cpus())
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ printk(KERN_INFO PFX "Found %d %s (%d cpu cores) (" VERSION ")\n",
|
||||
+ num_online_nodes(), boot_cpu_data.x86_model_id, supported_cpus);
|
||||
+
|
||||
+ if (boot_cpu_has(X86_FEATURE_CPB)) {
|
||||
+
|
||||
+ cpb_capable = true;
|
||||
+
|
||||
+ register_cpu_notifier(&cpb_nb);
|
||||
+
|
||||
+ msrs = msrs_alloc();
|
||||
+ if (!msrs) {
|
||||
+ printk(KERN_ERR "%s: Error allocating msrs!\n", __func__);
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ rdmsr_on_cpus(cpu_online_mask, MSR_K7_HWCR, msrs);
|
||||
+
|
||||
+ for_each_cpu(cpu, cpu_online_mask) {
|
||||
+ struct msr *reg = per_cpu_ptr(msrs, cpu);
|
||||
+ cpb_enabled |= !(!!(reg->l & BIT(25)));
|
||||
+ }
|
||||
+
|
||||
+ printk(KERN_INFO PFX "Core Performance Boosting: %s.\n",
|
||||
+ (cpb_enabled ? "on" : "off"));
|
||||
}
|
||||
|
||||
- return -ENODEV;
|
||||
+ return cpufreq_register_driver(&cpufreq_amd64_driver);
|
||||
}
|
||||
|
||||
/* driver entry point for term */
|
||||
@@ -1439,6 +1573,13 @@ static void __exit powernowk8_exit(void)
|
||||
{
|
||||
dprintk("exit\n");
|
||||
|
||||
+ if (boot_cpu_has(X86_FEATURE_CPB)) {
|
||||
+ msrs_free(msrs);
|
||||
+ msrs = NULL;
|
||||
+
|
||||
+ unregister_cpu_notifier(&cpb_nb);
|
||||
+ }
|
||||
+
|
||||
cpufreq_unregister_driver(&cpufreq_amd64_driver);
|
||||
}
|
||||
|
||||
--- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.h
|
||||
+++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.h
|
||||
@@ -5,7 +5,6 @@
|
||||
* http://www.gnu.org/licenses/gpl.html
|
||||
*/
|
||||
|
||||
-
|
||||
enum pstate {
|
||||
HW_PSTATE_INVALID = 0xff,
|
||||
HW_PSTATE_0 = 0,
|
||||
@@ -55,7 +54,6 @@ struct powernow_k8_data {
|
||||
struct cpumask *available_cores;
|
||||
};
|
||||
|
||||
-
|
||||
/* processor's cpuid instruction support */
|
||||
#define CPUID_PROCESSOR_SIGNATURE 1 /* function 1 */
|
||||
#define CPUID_XFAM 0x0ff00000 /* extended family */
|
@ -1,36 +0,0 @@
|
||||
From: Olaf Hering <olh@novell.com>
|
||||
Subject: [PATCH] poweroc: vio modalias
|
||||
Patch-mainline: not yet
|
||||
|
||||
Acked-by: Olaf Hering <olh@novell.com>
|
||||
---
|
||||
arch/powerpc/kernel/vio.c | 15 +++++++++++++++
|
||||
1 file changed, 15 insertions(+)
|
||||
|
||||
--- a/arch/powerpc/kernel/vio.c
|
||||
+++ b/arch/powerpc/kernel/vio.c
|
||||
@@ -1319,9 +1319,24 @@ static ssize_t devspec_show(struct devic
|
||||
return sprintf(buf, "%s\n", of_node ? of_node->full_name : "none");
|
||||
}
|
||||
|
||||
+static ssize_t modalias_show (struct device *dev, struct device_attribute *attr,
|
||||
+ char *buf)
|
||||
+{
|
||||
+ struct device_node *of_node = dev->archdata.of_node;
|
||||
+ const char *compat;
|
||||
+ int i = 0;
|
||||
+
|
||||
+ if (of_node) {
|
||||
+ compat = of_get_property(of_node, "compatible", &i);
|
||||
+ i = sprintf (buf, "vio:T%sS%s\n", of_node->type, compat);
|
||||
+ }
|
||||
+ return i;
|
||||
+}
|
||||
+
|
||||
static struct device_attribute vio_dev_attrs[] = {
|
||||
__ATTR_RO(name),
|
||||
__ATTR_RO(devspec),
|
||||
+ __ATTR_RO(modalias),
|
||||
__ATTR_NULL
|
||||
};
|
||||
|
@ -1,42 +0,0 @@
|
||||
Date: Thu, 9 Oct 2008 11:20:27 -0400
|
||||
From: Neil Horman <nhorman@tuxdriver.com>
|
||||
To: linux-kernel@vger.kernel.org, kexec@lists.infradead.org,
|
||||
vgoyal@redhat.com, hbabu@us.ibm.com
|
||||
Subject: [PATCH] add additional symbols to /sys/kernel/vmcoreinfo data for
|
||||
ppc(64)
|
||||
Cc: nhorman@tuxdriver.com
|
||||
Patch-mainline: not yet
|
||||
|
||||
Hey-
|
||||
The makdumpdile dump filtering program, in some modes of operation needs
|
||||
the node_data and/or contig_page_data symbols to function properly. These
|
||||
symbols are missing from the powerpc kernel. This patch adds those symbols in
|
||||
properly. Tested successfully by myself and the reporter.
|
||||
|
||||
Regards
|
||||
Neil
|
||||
|
||||
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
|
||||
Acked-by: Bernhard Walle <bwalle@suse.de>
|
||||
|
||||
arch/powerpc/kernel/machine_kexec.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
|
||||
--- a/arch/powerpc/kernel/machine_kexec.c
|
||||
+++ b/arch/powerpc/kernel/machine_kexec.c
|
||||
@@ -45,6 +45,14 @@ void machine_kexec_cleanup(struct kimage
|
||||
ppc_md.machine_kexec_cleanup(image);
|
||||
}
|
||||
|
||||
+void arch_crash_save_vmcoreinfo(void)
|
||||
+{
|
||||
+#ifdef CONFIG_NEED_MULTIPLE_NODES
|
||||
+ VMCOREINFO_SYMBOL(node_data);
|
||||
+ VMCOREINFO_LENGTH(node_data, MAX_NUMNODES);
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Do not allocate memory (or fail in any way) in machine_kexec().
|
||||
* We are past the point of no return, committed to rebooting now.
|
@ -0,0 +1,23 @@
|
||||
From: Jiri Slaby <jslaby@suse.cz>
|
||||
Subject: fix build on s390 as of 2.6.36-rc4
|
||||
Patch-mainline: never
|
||||
|
||||
This fixes patches.arch/s390-message-catalog.diff build.
|
||||
|
||||
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
|
||||
|
||||
---
|
||||
include/linux/device.h | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
--- a/include/linux/device.h
|
||||
+++ b/include/linux/device.h
|
||||
@@ -660,6 +660,8 @@ int printk_dev_hash(const char *, const
|
||||
|
||||
#endif
|
||||
|
||||
+#define dev_printk(level, dev, format, arg...) \
|
||||
+ dev_printk_hash(level , dev, format, ## arg)
|
||||
#define dev_emerg(dev, format, arg...) \
|
||||
dev_printk_hash(KERN_EMERG , dev , format , ## arg)
|
||||
#define dev_alert(dev, format, arg...) \
|
@ -1,49 +0,0 @@
|
||||
From: Borislav Petkov <borislav.petkov@amd.com>
|
||||
Date: Wed, 31 Mar 2010 19:56:41 +0000 (+0200)
|
||||
Subject: x86, cpu: Add AMD core boosting feature flag to /proc/cpuinfo
|
||||
Git-commit: 5958f1d5d722df7a9e5d129676614a8e5219bacd
|
||||
Patch-mainline: 2.6.35-rc1
|
||||
|
||||
x86, cpu: Add AMD core boosting feature flag to /proc/cpuinfo
|
||||
|
||||
By semi-popular demand, this adds the Core Performance Boost feature
|
||||
flag to /proc/cpuinfo. Possible use case for this is userspace tools
|
||||
like cpufreq-aperf, for example, so that they don't have to jump through
|
||||
hoops of accessing "/dev/cpu/%d/cpuid" in order to check for CPB hw
|
||||
support, or call cpuid from userspace.
|
||||
|
||||
Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
|
||||
LKML-Reference: <1270065406-1814-2-git-send-email-bp@amd64.org>
|
||||
Reviewed-by: Thomas Renninger <trenn@suse.de>
|
||||
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
|
||||
Acked-by: Jeff Mahoney <jeffm@suse.com>
|
||||
---
|
||||
|
||||
arch/x86/include/asm/cpufeature.h | 1 +
|
||||
arch/x86/kernel/cpu/addon_cpuid_features.c | 5 +++--
|
||||
2 files changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/arch/x86/include/asm/cpufeature.h
|
||||
+++ b/arch/x86/include/asm/cpufeature.h
|
||||
@@ -161,6 +161,7 @@
|
||||
*/
|
||||
#define X86_FEATURE_IDA (7*32+ 0) /* Intel Dynamic Acceleration */
|
||||
#define X86_FEATURE_ARAT (7*32+ 1) /* Always Running APIC Timer */
|
||||
+#define X86_FEATURE_CPB (7*32+ 2) /* AMD Core Performance Boost */
|
||||
|
||||
/* Virtualization flags: Linux defined */
|
||||
#define X86_FEATURE_TPR_SHADOW (8*32+ 0) /* Intel TPR Shadow */
|
||||
--- a/arch/x86/kernel/cpu/addon_cpuid_features.c
|
||||
+++ b/arch/x86/kernel/cpu/addon_cpuid_features.c
|
||||
@@ -30,8 +30,9 @@ void __cpuinit init_scattered_cpuid_feat
|
||||
const struct cpuid_bit *cb;
|
||||
|
||||
static const struct cpuid_bit __cpuinitconst cpuid_bits[] = {
|
||||
- { X86_FEATURE_IDA, CR_EAX, 1, 0x00000006 },
|
||||
- { X86_FEATURE_ARAT, CR_EAX, 2, 0x00000006 },
|
||||
+ { X86_FEATURE_IDA, CR_EAX, 1, 0x00000006 },
|
||||
+ { X86_FEATURE_ARAT, CR_EAX, 2, 0x00000006 },
|
||||
+ { X86_FEATURE_CPB, CR_EDX, 9, 0x80000007 },
|
||||
{ X86_FEATURE_NPT, CR_EDX, 0, 0x8000000a },
|
||||
{ X86_FEATURE_LBRV, CR_EDX, 1, 0x8000000a },
|
||||
{ X86_FEATURE_SVML, CR_EDX, 2, 0x8000000a },
|
@ -1,222 +0,0 @@
|
||||
From: Mark Langsdorf <mark.langsdorf@amd.com>
|
||||
Date: Thu, 18 Mar 2010 17:41:46 +0000 (+0100)
|
||||
Subject: x86, cpufreq: Add APERF/MPERF support for AMD processors
|
||||
Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-tip.git
|
||||
Git-commit: a2fed573f065e526bfd5cbf26e5491973d9e9aaa
|
||||
References: bnc#602209
|
||||
Patch-mainline: 2.6.35-rc1
|
||||
|
||||
x86, cpufreq: Add APERF/MPERF support for AMD processors
|
||||
|
||||
Starting with model 10 of Family 0x10, AMD processors may have
|
||||
support for APERF/MPERF. Add support for identifying it and using
|
||||
it within cpufreq. Move the APERF/MPERF functions out of the
|
||||
acpi-cpufreq code and into their own file so they can easily be
|
||||
shared.
|
||||
|
||||
Signed-off-by: Mark Langsdorf <mark.langsdorf@amd.com>
|
||||
LKML-Reference: <20100401141956.GA1930@aftab>
|
||||
Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
|
||||
Reviewed-by: Thomas Renninger <trenn@suse.de>
|
||||
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
|
||||
Acked-by: Jeff Mahoney <jeffm@suse.com>
|
||||
---
|
||||
|
||||
arch/x86/kernel/cpu/cpufreq/Makefile | 4 +-
|
||||
arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c | 44 +------------------------
|
||||
arch/x86/kernel/cpu/cpufreq/mperf.c | 51 +++++++++++++++++++++++++++++
|
||||
arch/x86/kernel/cpu/cpufreq/mperf.h | 9 +++++
|
||||
arch/x86/kernel/cpu/cpufreq/powernow-k8.c | 8 ++++
|
||||
5 files changed, 72 insertions(+), 44 deletions(-)
|
||||
|
||||
--- a/arch/x86/kernel/cpu/cpufreq/Makefile
|
||||
+++ b/arch/x86/kernel/cpu/cpufreq/Makefile
|
||||
@@ -2,8 +2,8 @@
|
||||
# K8 systems. ACPI is preferred to all other hardware-specific drivers.
|
||||
# speedstep-* is preferred over p4-clockmod.
|
||||
|
||||
-obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o
|
||||
-obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi-cpufreq.o
|
||||
+obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o mperf.o
|
||||
+obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi-cpufreq.o mperf.o
|
||||
obj-$(CONFIG_X86_PCC_CPUFREQ) += pcc-cpufreq.o
|
||||
obj-$(CONFIG_X86_POWERNOW_K6) += powernow-k6.o
|
||||
obj-$(CONFIG_X86_POWERNOW_K7) += powernow-k7.o
|
||||
--- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
|
||||
+++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
|
||||
@@ -45,6 +45,7 @@
|
||||
#include <asm/msr.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/cpufeature.h>
|
||||
+#include "mperf.h"
|
||||
|
||||
#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \
|
||||
"acpi-cpufreq", msg)
|
||||
@@ -70,8 +71,6 @@ struct acpi_cpufreq_data {
|
||||
|
||||
static DEFINE_PER_CPU(struct acpi_cpufreq_data *, acfreq_data);
|
||||
|
||||
-static DEFINE_PER_CPU(struct aperfmperf, acfreq_old_perf);
|
||||
-
|
||||
/* acpi_perf_data is a pointer to percpu data. */
|
||||
static struct acpi_processor_performance *acpi_perf_data;
|
||||
|
||||
@@ -239,45 +238,6 @@ static u32 get_cur_val(const struct cpum
|
||||
return cmd.val;
|
||||
}
|
||||
|
||||
-/* Called via smp_call_function_single(), on the target CPU */
|
||||
-static void read_measured_perf_ctrs(void *_cur)
|
||||
-{
|
||||
- struct aperfmperf *am = _cur;
|
||||
-
|
||||
- get_aperfmperf(am);
|
||||
-}
|
||||
-
|
||||
-/*
|
||||
- * Return the measured active (C0) frequency on this CPU since last call
|
||||
- * to this function.
|
||||
- * Input: cpu number
|
||||
- * Return: Average CPU frequency in terms of max frequency (zero on error)
|
||||
- *
|
||||
- * We use IA32_MPERF and IA32_APERF MSRs to get the measured performance
|
||||
- * over a period of time, while CPU is in C0 state.
|
||||
- * IA32_MPERF counts at the rate of max advertised frequency
|
||||
- * IA32_APERF counts at the rate of actual CPU frequency
|
||||
- * Only IA32_APERF/IA32_MPERF ratio is architecturally defined and
|
||||
- * no meaning should be associated with absolute values of these MSRs.
|
||||
- */
|
||||
-static unsigned int get_measured_perf(struct cpufreq_policy *policy,
|
||||
- unsigned int cpu)
|
||||
-{
|
||||
- struct aperfmperf perf;
|
||||
- unsigned long ratio;
|
||||
- unsigned int retval;
|
||||
-
|
||||
- if (smp_call_function_single(cpu, read_measured_perf_ctrs, &perf, 1))
|
||||
- return 0;
|
||||
-
|
||||
- ratio = calc_aperfmperf_ratio(&per_cpu(acfreq_old_perf, cpu), &perf);
|
||||
- per_cpu(acfreq_old_perf, cpu) = perf;
|
||||
-
|
||||
- retval = (policy->cpuinfo.max_freq * ratio) >> APERFMPERF_SHIFT;
|
||||
-
|
||||
- return retval;
|
||||
-}
|
||||
-
|
||||
static unsigned int get_cur_freq_on_cpu(unsigned int cpu)
|
||||
{
|
||||
struct acpi_cpufreq_data *data = per_cpu(acfreq_data, cpu);
|
||||
@@ -699,7 +659,7 @@ static int acpi_cpufreq_cpu_init(struct
|
||||
|
||||
/* Check for APERF/MPERF support in hardware */
|
||||
if (cpu_has(c, X86_FEATURE_APERFMPERF))
|
||||
- acpi_cpufreq_driver.getavg = get_measured_perf;
|
||||
+ acpi_cpufreq_driver.getavg = cpufreq_get_measured_perf;
|
||||
|
||||
dprintk("CPU%u - ACPI performance management activated.\n", cpu);
|
||||
for (i = 0; i < perf->state_count; i++)
|
||||
--- /dev/null
|
||||
+++ b/arch/x86/kernel/cpu/cpufreq/mperf.c
|
||||
@@ -0,0 +1,51 @@
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/smp.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/cpufreq.h>
|
||||
+#include <linux/slab.h>
|
||||
+
|
||||
+#include "mperf.h"
|
||||
+
|
||||
+static DEFINE_PER_CPU(struct aperfmperf, acfreq_old_perf);
|
||||
+
|
||||
+/* Called via smp_call_function_single(), on the target CPU */
|
||||
+static void read_measured_perf_ctrs(void *_cur)
|
||||
+{
|
||||
+ struct aperfmperf *am = _cur;
|
||||
+
|
||||
+ get_aperfmperf(am);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Return the measured active (C0) frequency on this CPU since last call
|
||||
+ * to this function.
|
||||
+ * Input: cpu number
|
||||
+ * Return: Average CPU frequency in terms of max frequency (zero on error)
|
||||
+ *
|
||||
+ * We use IA32_MPERF and IA32_APERF MSRs to get the measured performance
|
||||
+ * over a period of time, while CPU is in C0 state.
|
||||
+ * IA32_MPERF counts at the rate of max advertised frequency
|
||||
+ * IA32_APERF counts at the rate of actual CPU frequency
|
||||
+ * Only IA32_APERF/IA32_MPERF ratio is architecturally defined and
|
||||
+ * no meaning should be associated with absolute values of these MSRs.
|
||||
+ */
|
||||
+unsigned int cpufreq_get_measured_perf(struct cpufreq_policy *policy,
|
||||
+ unsigned int cpu)
|
||||
+{
|
||||
+ struct aperfmperf perf;
|
||||
+ unsigned long ratio;
|
||||
+ unsigned int retval;
|
||||
+
|
||||
+ if (smp_call_function_single(cpu, read_measured_perf_ctrs, &perf, 1))
|
||||
+ return 0;
|
||||
+
|
||||
+ ratio = calc_aperfmperf_ratio(&per_cpu(acfreq_old_perf, cpu), &perf);
|
||||
+ per_cpu(acfreq_old_perf, cpu) = perf;
|
||||
+
|
||||
+ retval = (policy->cpuinfo.max_freq * ratio) >> APERFMPERF_SHIFT;
|
||||
+
|
||||
+ return retval;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(cpufreq_get_measured_perf);
|
||||
+MODULE_LICENSE("GPL");
|
||||
--- /dev/null
|
||||
+++ b/arch/x86/kernel/cpu/cpufreq/mperf.h
|
||||
@@ -0,0 +1,9 @@
|
||||
+/*
|
||||
+ * (c) 2010 Advanced Micro Devices, Inc.
|
||||
+ * Your use of this code is subject to the terms and conditions of the
|
||||
+ * GNU general public license version 2. See "COPYING" or
|
||||
+ * http://www.gnu.org/licenses/gpl.html
|
||||
+ */
|
||||
+
|
||||
+unsigned int cpufreq_get_measured_perf(struct cpufreq_policy *policy,
|
||||
+ unsigned int cpu);
|
||||
--- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
|
||||
+++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
|
||||
@@ -45,6 +45,7 @@
|
||||
#define PFX "powernow-k8: "
|
||||
#define VERSION "version 2.20.00"
|
||||
#include "powernow-k8.h"
|
||||
+#include "mperf.h"
|
||||
|
||||
/* serialize freq changes */
|
||||
static DEFINE_MUTEX(fidvid_mutex);
|
||||
@@ -57,6 +58,8 @@ static int cpu_family = CPU_OPTERON;
|
||||
static bool cpb_capable, cpb_enabled;
|
||||
static struct msr *msrs;
|
||||
|
||||
+static struct cpufreq_driver cpufreq_amd64_driver;
|
||||
+
|
||||
#ifndef CONFIG_SMP
|
||||
static inline const struct cpumask *cpu_core_mask(int cpu)
|
||||
{
|
||||
@@ -1252,6 +1255,7 @@ static int __cpuinit powernowk8_cpu_init
|
||||
struct powernow_k8_data *data;
|
||||
struct init_on_cpu init_on_cpu;
|
||||
int rc;
|
||||
+ struct cpuinfo_x86 *c = &cpu_data(pol->cpu);
|
||||
|
||||
if (!cpu_online(pol->cpu))
|
||||
return -ENODEV;
|
||||
@@ -1326,6 +1330,10 @@ static int __cpuinit powernowk8_cpu_init
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
+ /* Check for APERF/MPERF support in hardware */
|
||||
+ if (cpu_has(c, X86_FEATURE_APERFMPERF))
|
||||
+ cpufreq_amd64_driver.getavg = cpufreq_get_measured_perf;
|
||||
+
|
||||
cpufreq_frequency_table_get_attr(data->powernow_table, pol->cpu);
|
||||
|
||||
if (cpu_family == CPU_HW_PSTATE)
|
@ -1,581 +0,0 @@
|
||||
From: Andi Kleen <andi@firstfloor.org>
|
||||
Subject: x86, mce: Xeon75xx specific interface to get corrected memory error information
|
||||
Patch-Mainline: submitted to x86-tip, added but reverted due to a minor compile issue
|
||||
which gets fixed by and incremental patch
|
||||
References: bnc#573380, fate#307738
|
||||
|
||||
http://lkml.org/lkml/2010/1/22/98
|
||||
|
||||
Xeon 75xx doesn't log physical addresses on corrected machine check
|
||||
events in the standard architectural MSRs. Instead the address has to
|
||||
be retrieved in a model specific way. This makes it impossible to do
|
||||
predictive failure analysis.
|
||||
|
||||
Implement cpu model specific code to do this in mce-xeon75xx.c using a
|
||||
new hook that is called from the generic poll code. The code retrieves
|
||||
the physical address/DIMM of the last corrected error from the
|
||||
platform and makes the address look like a standard architectural MCA
|
||||
address for further processing.
|
||||
|
||||
In addition the DIMM information is retrieved and put into two new
|
||||
aux0/aux1 fields in struct mce. These fields are specific to a given
|
||||
CPU. These fields can then be decoded by mcelog into specific DIMM
|
||||
information. The latest mcelog version has support for this.
|
||||
|
||||
Longer term this will be likely in a different output format, but
|
||||
short term that seemed like the least intrusive solution. Older mcelog
|
||||
can deal with an extended record.
|
||||
|
||||
There's no code to print this information on a panic because this only
|
||||
works for corrected errors, and corrected errors do not usually result
|
||||
in panics.
|
||||
|
||||
The act of retrieving the DIMM/PA information can take some time, so
|
||||
this code has a rate limit to avoid taking too much CPU time on a
|
||||
error flood.
|
||||
|
||||
The whole thing can be loaded as a module and has suitable PCI-IDs so
|
||||
that it can be auto-loaded by a distribution. The code also checks
|
||||
explicitely for the expected CPU model number to make sure this code
|
||||
doesn't run anywhere else.
|
||||
|
||||
Signed-off-by: Thomas Renninger <trenn@suse.de>
|
||||
|
||||
---
|
||||
arch/x86/Kconfig | 8
|
||||
arch/x86/include/asm/mce.h | 2
|
||||
arch/x86/kernel/cpu/mcheck/Makefile | 1
|
||||
arch/x86/kernel/cpu/mcheck/mce-internal.h | 1
|
||||
arch/x86/kernel/cpu/mcheck/mce-xeon75xx.c | 427 ++++++++++++++++++++++++++++++
|
||||
arch/x86/kernel/cpu/mcheck/mce.c | 11
|
||||
arch/x86/kernel/e820.c | 3
|
||||
7 files changed, 452 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/arch/x86/Kconfig
|
||||
+++ b/arch/x86/Kconfig
|
||||
@@ -919,6 +919,14 @@ config X86_MCE_INTEL
|
||||
Additional support for intel specific MCE features such as
|
||||
the thermal monitor.
|
||||
|
||||
+config X86_MCE_XEON75XX
|
||||
+ tristate "Intel Xeon 7500 series corrected memory error driver"
|
||||
+ depends on X86_MCE_INTEL
|
||||
+ ---help---
|
||||
+ Add support for a Intel Xeon 7500 series specific memory error driver.
|
||||
+ This allows to report the DIMM and physical address on a corrected
|
||||
+ memory error machine check event.
|
||||
+
|
||||
config X86_MCE_AMD
|
||||
def_bool y
|
||||
prompt "AMD MCE features"
|
||||
--- a/arch/x86/include/asm/mce.h
|
||||
+++ b/arch/x86/include/asm/mce.h
|
||||
@@ -67,6 +67,8 @@ struct mce {
|
||||
__u32 socketid; /* CPU socket ID */
|
||||
__u32 apicid; /* CPU initial apic ID */
|
||||
__u64 mcgcap; /* MCGCAP MSR: machine check capabilities of CPU */
|
||||
+ __u64 aux0; /* model specific */
|
||||
+ __u64 aux1; /* model specific */
|
||||
};
|
||||
|
||||
/*
|
||||
--- a/arch/x86/kernel/cpu/mcheck/Makefile
|
||||
+++ b/arch/x86/kernel/cpu/mcheck/Makefile
|
||||
@@ -2,6 +2,7 @@ obj-y = mce.o mce-severity.o
|
||||
|
||||
obj-$(CONFIG_X86_ANCIENT_MCE) += winchip.o p5.o
|
||||
obj-$(CONFIG_X86_MCE_INTEL) += mce_intel.o
|
||||
+obj-$(CONFIG_X86_MCE_XEON75XX) += mce-xeon75xx.o
|
||||
obj-$(CONFIG_X86_MCE_AMD) += mce_amd.o
|
||||
obj-$(CONFIG_X86_MCE_THRESHOLD) += threshold.o
|
||||
obj-$(CONFIG_X86_MCE_INJECT) += mce-inject.o
|
||||
--- a/arch/x86/kernel/cpu/mcheck/mce-internal.h
|
||||
+++ b/arch/x86/kernel/cpu/mcheck/mce-internal.h
|
||||
@@ -28,3 +28,4 @@ extern int mce_ser;
|
||||
|
||||
extern struct mce_bank *mce_banks;
|
||||
|
||||
+extern void (*cpu_specific_poll)(struct mce *);
|
||||
--- /dev/null
|
||||
+++ b/arch/x86/kernel/cpu/mcheck/mce-xeon75xx.c
|
||||
@@ -0,0 +1,427 @@
|
||||
+/*
|
||||
+ * Xeon 7500 series specific machine check support code.
|
||||
+ * Copyright 2009, 2010 Intel Corporation
|
||||
+ * Author: Andi Kleen
|
||||
+ *
|
||||
+ * 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
|
||||
+ * of the License.
|
||||
+ *
|
||||
+ * Implement Xeon 7500 series specific code to retrieve the physical address
|
||||
+ * and DIMM information for corrected memory errors.
|
||||
+ *
|
||||
+ * Interface: mce->aux0/aux1 is mapped to a struct pfa_dimm with pad
|
||||
+ * redefined to DIMM valid bits. Consumers check CPUID and bank and
|
||||
+ * then interpret aux0/aux1
|
||||
+ */
|
||||
+
|
||||
+/* #define DEBUG 1 */ /* disable for production */
|
||||
+#define pr_fmt(x) "MCE: " x
|
||||
+
|
||||
+#include <linux/moduleparam.h>
|
||||
+#include <linux/pci_ids.h>
|
||||
+#include <linux/hrtimer.h>
|
||||
+#include <linux/string.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/ktime.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/pci.h>
|
||||
+#include <asm/processor.h>
|
||||
+#include <asm/e820.h>
|
||||
+#include <asm/mce.h>
|
||||
+#include <asm/io.h>
|
||||
+
|
||||
+#include "mce-internal.h"
|
||||
+
|
||||
+#define PFA_SIG "$PFA"
|
||||
+#define PFA_SIG_LEN 4
|
||||
+
|
||||
+/* DIMM description */
|
||||
+struct aux_pfa_dimm {
|
||||
+ u8 fbd_channel_id;
|
||||
+ u8 ddr_channel_id;
|
||||
+ u8 ddr_dimm_id;
|
||||
+ u8 ddr_rank_id;
|
||||
+ u8 ddr_dimm_bank_id;
|
||||
+ u8 ddr_dimm_row_id;
|
||||
+ u8 ddr_dimm_column_id;
|
||||
+ u8 valid;
|
||||
+} __attribute__((packed));
|
||||
+
|
||||
+struct pfa_dimm {
|
||||
+ u8 fbd_channel_id;
|
||||
+ u8 ddr_channel_id;
|
||||
+ u8 ddr_dimm_id;
|
||||
+ u8 ddr_rank_id;
|
||||
+ u8 ddr_dimm_bank_id;
|
||||
+ u32 ddr_dimm_row_id;
|
||||
+ u32 ddr_dimm_column_id;
|
||||
+} __attribute__((packed));
|
||||
+
|
||||
+/* Memory translation table in memory. */
|
||||
+struct pfa_table {
|
||||
+ u8 sig[PFA_SIG_LEN]; /* Signature: '$PFA' */
|
||||
+ u16 len; /* total length */
|
||||
+ u16 revision; /* 0x11 */
|
||||
+ u8 checksum; /* 8bit sum to zero */
|
||||
+ u8 db_value; /* mailbox port command value */
|
||||
+ u8 db_port; /* mailbox port */
|
||||
+ /* end of header; end of checksum */
|
||||
+ u8 command; /* input command */
|
||||
+ u32 valid; /* valid input/output bits */
|
||||
+ u16 status; /* output status */
|
||||
+ u8 socket_id; /* input socket id*/
|
||||
+ u8 bank_id; /* input MCE bank id */
|
||||
+ u32 pad1;
|
||||
+ u64 mbox_address;
|
||||
+ u64 physical_addr; /* physical address */
|
||||
+ struct pfa_dimm dimm[2];
|
||||
+ /*
|
||||
+ * topology information follows: not used for now.
|
||||
+ */
|
||||
+} __attribute__((packed));
|
||||
+
|
||||
+/* DIMM valid bits in valid: DIMM0: 8..12; DIMM1 16..20 */
|
||||
+#define DIMM_VALID_BITS(val, num) (((val) >> (4 + (num) * 8)) & DIMM_VALID_ALL)
|
||||
+#define DIMM_SET_VALID(val, num) ((val) << (4 + (num) * 8))
|
||||
+
|
||||
+enum {
|
||||
+ MCE_BANK_MBOX0 = 8,
|
||||
+ MCE_BANK_MBOX1 = 9,
|
||||
+
|
||||
+ PFA_REVISION = 0x11, /* v1.1 */
|
||||
+
|
||||
+ /* Status bits for valid field */
|
||||
+ PFA_VALID_MA = (1 << 0),
|
||||
+ PFA_VALID_SOCKETID = (1 << 1),
|
||||
+ PFA_VALID_BANKID = (1 << 2),
|
||||
+ PFA_VALID_PA = (1 << 3),
|
||||
+
|
||||
+ /* DIMM valid bits in valid */
|
||||
+ /* use with DIMM_VALID_BITS/DIMM_SET_VALID for pfa->valid */
|
||||
+ DIMM_VALID_FBD_CHAN = (1 << 0),
|
||||
+ DIMM_VALID_DDR_CHAN = (1 << 1),
|
||||
+ DIMM_VALID_DDR_DIMM = (1 << 2),
|
||||
+ DIMM_VALID_DDR_RANK = (1 << 3),
|
||||
+ DIMM_VALID_DIMM_BANK = (1 << 4),
|
||||
+ DIMM_VALID_DIMM_ROW = (1 << 5),
|
||||
+ DIMM_VALID_DIMM_COLUMN = (1 << 6),
|
||||
+ DIMM_VALID_ALL = 0x7f,
|
||||
+
|
||||
+ PFA_DIMM_VALID_MASK = DIMM_SET_VALID(DIMM_VALID_ALL, 0)
|
||||
+ | DIMM_SET_VALID(DIMM_VALID_ALL, 1),
|
||||
+
|
||||
+ /* Values for status field */
|
||||
+ PFA_STATUS_SUCCESS = 0,
|
||||
+ PFA_STATUS_SOCKET_INVALID = (1 << 1),
|
||||
+ PFA_STATUS_MBOX_INVALID = (1 << 2),
|
||||
+ PFA_STATUS_MA_INVALID = (1 << 3),
|
||||
+ PFA_STATUS_PA_INVALID = (1 << 4),
|
||||
+
|
||||
+ /* Values for command field */
|
||||
+ PFA_CMD_GET_MEM_CORR_ERR_PA = 0,
|
||||
+ PFA_CMD_PA_TO_DIMM_ADDR = 1,
|
||||
+ PFA_CMD_DIMM_TO_PA = 2,
|
||||
+ PFA_CMD_GET_TOPOLOGY = 3,
|
||||
+
|
||||
+ /* PCI device IDs and the base register */
|
||||
+ ICH_PFA_CFG = 0x8c, /* SCRATCH4 */
|
||||
+ PCI_DEVICE_ID_BXB_ICH_LEGACY0 = 0x3422,
|
||||
+};
|
||||
+
|
||||
+static struct pfa_table *pfa_table __read_mostly;
|
||||
+static int memerr_max_conv_rate __read_mostly = 100;
|
||||
+static int memerr_min_interval __read_mostly = 500;
|
||||
+static int pfa_lost; /* for diagnosis */
|
||||
+
|
||||
+enum {
|
||||
+ RATE_LIMIT_PERIOD = USEC_PER_SEC, /* in us; period of rate limit */
|
||||
+};
|
||||
+
|
||||
+module_param(memerr_max_conv_rate, int, 0644);
|
||||
+MODULE_PARM_DESC(memerr_max_conv_rate,
|
||||
+ "Maximum number of memory error conversions each second; 0 to disable");
|
||||
+module_param(memerr_min_interval, int, 0644);
|
||||
+MODULE_PARM_DESC(memerr_min_interval,
|
||||
+ "Minimum time delta between two memory conversions; in us; default 500");
|
||||
+
|
||||
+static int notest;
|
||||
+static int nocsum;
|
||||
+module_param(notest, int, 0);
|
||||
+module_param(nocsum, int, 0);
|
||||
+
|
||||
+static u64 encode_dimm(struct pfa_dimm *d, u8 valid)
|
||||
+{
|
||||
+ union {
|
||||
+ struct aux_pfa_dimm d;
|
||||
+ u64 v;
|
||||
+ } p;
|
||||
+
|
||||
+ BUILD_BUG_ON(sizeof(struct aux_pfa_dimm) != sizeof(u64));
|
||||
+ p.d.fbd_channel_id = d->fbd_channel_id;
|
||||
+ p.d.ddr_channel_id = d->ddr_channel_id;
|
||||
+ p.d.ddr_dimm_id = d->ddr_dimm_id;
|
||||
+ p.d.ddr_rank_id = d->ddr_rank_id;
|
||||
+ p.d.ddr_dimm_bank_id = d->ddr_dimm_bank_id;
|
||||
+ p.d.ddr_dimm_row_id = d->ddr_dimm_row_id;
|
||||
+ if (p.d.ddr_dimm_row_id != d->ddr_dimm_row_id) /* truncated? */
|
||||
+ valid &= ~DIMM_VALID_DIMM_ROW;
|
||||
+ p.d.ddr_dimm_column_id = d->ddr_dimm_column_id;
|
||||
+ if (p.d.ddr_dimm_column_id != d->ddr_dimm_column_id)
|
||||
+ valid &= ~DIMM_VALID_DIMM_COLUMN;
|
||||
+ p.d.valid = valid;
|
||||
+ pr_debug("PFA fbd_ch %u ddr_ch %u dimm %u rank %u bank %u valid %x\n",
|
||||
+ d->fbd_channel_id,
|
||||
+ d->ddr_channel_id,
|
||||
+ d->ddr_dimm_id,
|
||||
+ d->ddr_rank_id,
|
||||
+ d->ddr_dimm_bank_id,
|
||||
+ valid);
|
||||
+ return p.v;
|
||||
+}
|
||||
+
|
||||
+static u8 csum(u8 *table, u16 len)
|
||||
+{
|
||||
+ u8 sum = 0;
|
||||
+ int i;
|
||||
+ for (i = 0; i < len; i++)
|
||||
+ sum += *table++;
|
||||
+ return sum;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Execute a command through the mailbox interface.
|
||||
+ */
|
||||
+static int
|
||||
+pfa_command(unsigned bank, unsigned socketid, unsigned command, unsigned valid)
|
||||
+{
|
||||
+ pfa_table->bank_id = bank;
|
||||
+ pfa_table->socket_id = socketid;
|
||||
+ pfa_table->valid = valid | PFA_VALID_SOCKETID;
|
||||
+ pfa_table->command = command;
|
||||
+
|
||||
+ outb(pfa_table->db_value, pfa_table->db_port);
|
||||
+
|
||||
+ mb(); /* Reread fields after they got changed */
|
||||
+
|
||||
+ if (pfa_table->status != PFA_STATUS_SUCCESS) {
|
||||
+ pr_debug("Memory PFA command %d failed: socket:%d bank:%d status:%x\n",
|
||||
+ command, socketid, bank, pfa_table->status);
|
||||
+ return -pfa_table->status;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Retrieve physical address and DIMMs.
|
||||
+ */
|
||||
+static int translate_memory_error(struct mce *m)
|
||||
+{
|
||||
+ struct pfa_table *pfa = pfa_table;
|
||||
+ u64 status;
|
||||
+ int ret;
|
||||
+ u32 valid;
|
||||
+ int cpu = smp_processor_id();
|
||||
+
|
||||
+ /* Make sure our structures match the specification */
|
||||
+ BUILD_BUG_ON(offsetof(struct pfa_table, physical_addr) != 0x20);
|
||||
+ BUILD_BUG_ON(offsetof(struct pfa_table, status) != 0x10);
|
||||
+ BUILD_BUG_ON(offsetof(struct pfa_table, physical_addr) != 0x20);
|
||||
+ BUILD_BUG_ON(offsetof(struct pfa_table, dimm[1].ddr_dimm_column_id) !=
|
||||
+ 0x3e);
|
||||
+
|
||||
+ /* Ask for PA/DIMMs of last error */
|
||||
+ if (pfa_command(m->bank, m->socketid,
|
||||
+ PFA_CMD_GET_MEM_CORR_ERR_PA, PFA_VALID_BANKID) < 0)
|
||||
+ return -1;
|
||||
+
|
||||
+ /*
|
||||
+ * Recheck machine check bank. If the overflow bit was set
|
||||
+ * there was a race. Don't use the information in this case.
|
||||
+ */
|
||||
+ rdmsrl(MSR_IA32_MCx_STATUS(m->bank), status);
|
||||
+ if (status & MCI_STATUS_OVER) {
|
||||
+ pr_debug("%d: overflow race on bank %d\n", cpu, m->bank);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ ret = -1;
|
||||
+ valid = pfa->valid;
|
||||
+ if (valid & PFA_VALID_PA) {
|
||||
+ m->status |= MCI_STATUS_ADDRV;
|
||||
+ m->addr = pfa_table->physical_addr;
|
||||
+ pr_debug("%d: got physical address %llx valid %x\n",
|
||||
+ cpu, m->addr, valid);
|
||||
+ ret = 0;
|
||||
+ }
|
||||
+
|
||||
+ /* When DIMM information was supplied pass it out */
|
||||
+ if (valid & PFA_DIMM_VALID_MASK) {
|
||||
+ m->aux0 = encode_dimm(&pfa->dimm[0], DIMM_VALID_BITS(valid, 0));
|
||||
+ m->aux1 = encode_dimm(&pfa->dimm[1], DIMM_VALID_BITS(valid, 1));
|
||||
+ ret = 0;
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Xeon 75xx specific mce poll method to retrieve the physical address
|
||||
+ * and DIMM information.
|
||||
+ */
|
||||
+static void xeon75xx_mce_poll(struct mce *m)
|
||||
+{
|
||||
+ static DEFINE_SPINLOCK(convert_lock); /* Protect table and static */
|
||||
+ static unsigned long cperm;
|
||||
+ static ktime_t last, last_int;
|
||||
+ unsigned long flags;
|
||||
+ ktime_t now;
|
||||
+ s64 delta;
|
||||
+
|
||||
+ /* Memory error? */
|
||||
+ if (m->bank != MCE_BANK_MBOX0 && m->bank != MCE_BANK_MBOX1)
|
||||
+ return;
|
||||
+ if (m->status & MCI_STATUS_OVER)
|
||||
+ return;
|
||||
+ if (memerr_max_conv_rate == 0)
|
||||
+ return;
|
||||
+
|
||||
+ spin_lock_irqsave(&convert_lock, flags);
|
||||
+ /*
|
||||
+ * Rate limit conversions. The conversion takes some time,
|
||||
+ * but it's not good to use all the CPU time during a error
|
||||
+ * flood.
|
||||
+ * Enforce maximum number per second and minimum interval.
|
||||
+ * The ktime call should use TSC on this machine and be fast.
|
||||
+ */
|
||||
+ now = ktime_get();
|
||||
+ delta = ktime_us_delta(now, last);
|
||||
+ if (delta >= RATE_LIMIT_PERIOD) {
|
||||
+ cperm = 0;
|
||||
+ last = now;
|
||||
+ }
|
||||
+ if (ktime_us_delta(now, last_int) >= memerr_min_interval &&
|
||||
+ ++cperm <= memerr_max_conv_rate) {
|
||||
+ if (translate_memory_error(m) < 0) {
|
||||
+ /* On error stop converting for the next second */
|
||||
+ cperm = memerr_max_conv_rate;
|
||||
+ pr_debug("PFA translation failed\n");
|
||||
+ }
|
||||
+ } else
|
||||
+ pfa_lost++;
|
||||
+ last_int = now;
|
||||
+ spin_unlock_irqrestore(&convert_lock, flags);
|
||||
+}
|
||||
+
|
||||
+static struct pci_device_id bxb_mce_pciids[] = {
|
||||
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_BXB_ICH_LEGACY0) },
|
||||
+ {}
|
||||
+};
|
||||
+
|
||||
+static int __init xeon75xx_mce_init(void)
|
||||
+{
|
||||
+ u32 addr = 0;
|
||||
+ struct pci_dev *dev;
|
||||
+
|
||||
+ if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ||
|
||||
+ boot_cpu_data.x86 != 6 ||
|
||||
+ boot_cpu_data.x86_model != 0x2e)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ /*
|
||||
+ * Get table address from register in IOH.
|
||||
+ * This just looks up the device, because we don't want to "own" it.
|
||||
+ */
|
||||
+ dev = NULL;
|
||||
+ while ((dev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, dev))
|
||||
+ != NULL) {
|
||||
+ if (!pci_match_id(bxb_mce_pciids, dev))
|
||||
+ continue;
|
||||
+ pci_read_config_dword(dev, ICH_PFA_CFG, &addr);
|
||||
+ if (addr)
|
||||
+ break;
|
||||
+ }
|
||||
+ pci_dev_put(dev);
|
||||
+ if (!addr)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ if (!e820_all_mapped(addr, addr + PAGE_SIZE, E820_RESERVED)) {
|
||||
+ pr_info("PFA table at %x not e820 reserved\n", addr);
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ pfa_table = (__force struct pfa_table *)ioremap_cache(addr, PAGE_SIZE);
|
||||
+ if (!pfa_table) {
|
||||
+ pr_err("Cannot map PFA table at %x\n", addr);
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+
|
||||
+ if (memcmp(&pfa_table->sig, PFA_SIG, PFA_SIG_LEN) ||
|
||||
+ pfa_table->len < sizeof(struct pfa_table) ||
|
||||
+ /* assume newer versions are compatible */
|
||||
+ pfa_table->revision < PFA_REVISION) {
|
||||
+ pr_info("PFA table at %x invalid\n", addr);
|
||||
+ goto error_unmap;
|
||||
+ }
|
||||
+
|
||||
+ if (!nocsum && csum((u8 *)pfa_table,
|
||||
+ offsetof(struct pfa_table, command))) {
|
||||
+ pr_info("PFA table at %x length %u has invalid checksum\n",
|
||||
+ addr, pfa_table->len);
|
||||
+ goto error_unmap;
|
||||
+ }
|
||||
+
|
||||
+ /* Not strictly needed today */
|
||||
+ if (pfa_table->len > PAGE_SIZE) {
|
||||
+ unsigned len = roundup(pfa_table->len, PAGE_SIZE);
|
||||
+ iounmap(pfa_table);
|
||||
+ pfa_table = (__force void *)ioremap_cache(addr, len);
|
||||
+ if (!pfa_table) {
|
||||
+ pr_err("Cannot remap %u bytes PFA table at %x\n",
|
||||
+ len, addr);
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!notest) {
|
||||
+ int status = pfa_command(0, 0, PFA_CMD_GET_TOPOLOGY, 0);
|
||||
+ if (status < 0) {
|
||||
+ pr_err("Test of PFA table failed: %x\n", -status);
|
||||
+ goto error_unmap;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ pr_info("Found Xeon75xx PFA memory error translation table at %x\n",
|
||||
+ addr);
|
||||
+ mb();
|
||||
+ cpu_specific_poll = xeon75xx_mce_poll;
|
||||
+ return 0;
|
||||
+
|
||||
+error_unmap:
|
||||
+ iounmap(pfa_table);
|
||||
+ return -ENODEV;
|
||||
+}
|
||||
+
|
||||
+MODULE_DEVICE_TABLE(pci, bxb_mce_pciids);
|
||||
+MODULE_LICENSE("GPL v2");
|
||||
+MODULE_AUTHOR("Andi Kleen");
|
||||
+MODULE_DESCRIPTION("Intel Xeon 75xx specific DIMM error reporting");
|
||||
+
|
||||
+#ifdef CONFIG_MODULE
|
||||
+static void __exit xeon75xx_mce_exit(void)
|
||||
+{
|
||||
+ cpu_specific_poll = NULL;
|
||||
+ wmb();
|
||||
+ /* Wait for all machine checks to finish before really unloading */
|
||||
+ synchronize_rcu();
|
||||
+ iounmap(pfa_table);
|
||||
+}
|
||||
+
|
||||
+module_init(xeon75xx_mce_init);
|
||||
+module_exit(xeon75xx_mce_exit);
|
||||
+#else
|
||||
+/* When built-in run as soon as the PCI subsystem is up */
|
||||
+fs_initcall(xeon75xx_mce_init);
|
||||
+#endif
|
||||
--- a/arch/x86/kernel/cpu/mcheck/mce.c
|
||||
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
|
||||
@@ -94,6 +94,8 @@ static char *mce_helper_argv[2] = { mc
|
||||
static DECLARE_WAIT_QUEUE_HEAD(mce_wait);
|
||||
static DEFINE_PER_CPU(struct mce, mces_seen);
|
||||
static int cpu_missing;
|
||||
+void (*cpu_specific_poll)(struct mce *);
|
||||
+EXPORT_SYMBOL_GPL(cpu_specific_poll);
|
||||
|
||||
/*
|
||||
* CPU/chipset specific EDAC code can register a notifier call here to print
|
||||
@@ -371,6 +373,11 @@ static void mce_wrmsrl(u32 msr, u64 v)
|
||||
wrmsrl(msr, v);
|
||||
}
|
||||
|
||||
+static int under_injection(void)
|
||||
+{
|
||||
+ return __get_cpu_var(injectm).finished;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Simple lockless ring to communicate PFNs from the exception handler with the
|
||||
* process context work function. This is vastly simplified because there's
|
||||
@@ -574,6 +581,10 @@ void machine_check_poll(enum mcp_flags f
|
||||
|
||||
if (!(flags & MCP_TIMESTAMP))
|
||||
m.tsc = 0;
|
||||
+
|
||||
+ if (cpu_specific_poll && !under_injection() && !mce_dont_log_ce)
|
||||
+ cpu_specific_poll(&m);
|
||||
+
|
||||
/*
|
||||
* Don't get the IP here because it's unlikely to
|
||||
* have anything to do with the actual error location.
|
||||
--- a/arch/x86/kernel/e820.c
|
||||
+++ b/arch/x86/kernel/e820.c
|
||||
@@ -71,7 +71,7 @@ EXPORT_SYMBOL_GPL(e820_any_mapped);
|
||||
* Note: this function only works correct if the e820 table is sorted and
|
||||
* not-overlapping, which is the case
|
||||
*/
|
||||
-int __init e820_all_mapped(u64 start, u64 end, unsigned type)
|
||||
+int e820_all_mapped(u64 start, u64 end, unsigned type)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -98,6 +98,7 @@ int __init e820_all_mapped(u64 start, u6
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(e820_all_mapped);
|
||||
|
||||
/*
|
||||
* Add a memory region to the kernel e820 map.
|
@ -1,25 +0,0 @@
|
||||
From: Andi Kleen <andi@firstfloor.org>
|
||||
Subject: x86, mce: Xeon75xx specific interface to get corrected memory error information
|
||||
Patch-Mainline: submitted to x86-tip, added but reverted due to a minor compile issue
|
||||
which gets fixed by this patch
|
||||
References: bnc#573380, fate#307738
|
||||
|
||||
http://lkml.org/lkml/2010/1/23/50
|
||||
|
||||
Signed-off-by: Thomas Renninger <trenn@suse.de>
|
||||
|
||||
---
|
||||
arch/x86/Kconfig | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/arch/x86/Kconfig
|
||||
+++ b/arch/x86/Kconfig
|
||||
@@ -921,7 +921,7 @@ config X86_MCE_INTEL
|
||||
|
||||
config X86_MCE_XEON75XX
|
||||
tristate "Intel Xeon 7500 series corrected memory error driver"
|
||||
- depends on X86_MCE_INTEL
|
||||
+ depends on X86_MCE_INTEL && PCI
|
||||
---help---
|
||||
Add support for a Intel Xeon 7500 series specific memory error driver.
|
||||
This allows to report the DIMM and physical address on a corrected
|
@ -1,72 +0,0 @@
|
||||
From: H. Peter Anvin <hpa@zytor.com>
|
||||
Subject: x86, mce: Rename cpu_specific_poll to mce_cpu_specific_poll
|
||||
Patch-Mainline: submitted to x86-tip, added but reverted due to a minor compile issue
|
||||
which gets fixed by and incremental patch
|
||||
References: bnc#573380, fate#307738
|
||||
|
||||
http://lkml.org/lkml/2010/1/22/99
|
||||
|
||||
cpu_specific_poll is a global variable, and it should have a global
|
||||
namespace name. Since it is MCE-specific (it takes a struct mce *),
|
||||
rename it mce_cpu_specific_poll.
|
||||
|
||||
Signed-off-by: Thomas Renninger <trenn@suse.de>
|
||||
|
||||
---
|
||||
arch/x86/kernel/cpu/mcheck/mce-internal.h | 2 +-
|
||||
arch/x86/kernel/cpu/mcheck/mce-xeon75xx.c | 4 ++--
|
||||
arch/x86/kernel/cpu/mcheck/mce.c | 8 ++++----
|
||||
3 files changed, 7 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/arch/x86/kernel/cpu/mcheck/mce-internal.h
|
||||
+++ b/arch/x86/kernel/cpu/mcheck/mce-internal.h
|
||||
@@ -28,4 +28,4 @@ extern int mce_ser;
|
||||
|
||||
extern struct mce_bank *mce_banks;
|
||||
|
||||
-extern void (*cpu_specific_poll)(struct mce *);
|
||||
+extern void (*mce_cpu_specific_poll)(struct mce *);
|
||||
--- a/arch/x86/kernel/cpu/mcheck/mce-xeon75xx.c
|
||||
+++ b/arch/x86/kernel/cpu/mcheck/mce-xeon75xx.c
|
||||
@@ -396,7 +396,7 @@ static int __init xeon75xx_mce_init(void
|
||||
pr_info("Found Xeon75xx PFA memory error translation table at %x\n",
|
||||
addr);
|
||||
mb();
|
||||
- cpu_specific_poll = xeon75xx_mce_poll;
|
||||
+ mce_cpu_specific_poll = xeon75xx_mce_poll;
|
||||
return 0;
|
||||
|
||||
error_unmap:
|
||||
@@ -412,7 +412,7 @@ MODULE_DESCRIPTION("Intel Xeon 75xx spec
|
||||
#ifdef CONFIG_MODULE
|
||||
static void __exit xeon75xx_mce_exit(void)
|
||||
{
|
||||
- cpu_specific_poll = NULL;
|
||||
+ mce_cpu_specific_poll = NULL;
|
||||
wmb();
|
||||
/* Wait for all machine checks to finish before really unloading */
|
||||
synchronize_rcu();
|
||||
--- a/arch/x86/kernel/cpu/mcheck/mce.c
|
||||
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
|
||||
@@ -94,8 +94,8 @@ static char *mce_helper_argv[2] = { mc
|
||||
static DECLARE_WAIT_QUEUE_HEAD(mce_wait);
|
||||
static DEFINE_PER_CPU(struct mce, mces_seen);
|
||||
static int cpu_missing;
|
||||
-void (*cpu_specific_poll)(struct mce *);
|
||||
-EXPORT_SYMBOL_GPL(cpu_specific_poll);
|
||||
+void (*mce_cpu_specific_poll)(struct mce *);
|
||||
+EXPORT_SYMBOL_GPL(mce_cpu_specific_poll);
|
||||
|
||||
/*
|
||||
* CPU/chipset specific EDAC code can register a notifier call here to print
|
||||
@@ -582,8 +582,8 @@ void machine_check_poll(enum mcp_flags f
|
||||
if (!(flags & MCP_TIMESTAMP))
|
||||
m.tsc = 0;
|
||||
|
||||
- if (cpu_specific_poll && !under_injection() && !mce_dont_log_ce)
|
||||
- cpu_specific_poll(&m);
|
||||
+ if (mce_cpu_specific_poll && !under_injection() && !mce_dont_log_ce)
|
||||
+ mce_cpu_specific_poll(&m);
|
||||
|
||||
/*
|
||||
* Don't get the IP here because it's unlikely to
|
@ -1,77 +0,0 @@
|
||||
From 9286a0bc63de32c66d894b45dcf048a072a84cd7 Mon Sep 17 00:00:00 2001
|
||||
From: Adam Jackson <ajax@redhat.com>
|
||||
Date: Mon, 19 Apr 2010 15:57:25 -0400
|
||||
Subject: [PATCH 1/4] drm/i915: Use spatio-temporal dithering on PCH
|
||||
|
||||
Spatial dither is better than nothing, but ST is even better.
|
||||
|
||||
(from ajax's followup message:)
|
||||
I noticed this with:
|
||||
|
||||
http://ajax.fedorapeople.org/YellowFlower.jpg
|
||||
|
||||
set as my desktop background in Gnome on a 1280x800 machine (in
|
||||
particular, a Sony Vaio VPCB1 with 6-bit panel and a rather bright black
|
||||
level). Easiest way to test this is by poking at PIPEACONF with
|
||||
intel_reg_write directly:
|
||||
|
||||
% sudo intel_reg_write 0x70008 0xc0000040 # no dither
|
||||
% sudo intel_reg_write 0x70008 0xc0000050 # spatial
|
||||
% sudo intel_reg_write 0x70008 0xc0000054 # ST
|
||||
|
||||
I notice it especially strongly in the relatively flat dark area in the
|
||||
top left. Closer than about 18" I can see a noticeable checkerboard
|
||||
pattern with plain spatial dithering. ST smooths that out; I can still
|
||||
tell that it's lacking color precision, but it's not offensive.
|
||||
|
||||
Signed-off-by: Adam Jackson <ajax@redhat.com>
|
||||
Signed-off-by: Eric Anholt <eric@anholt.net>
|
||||
---
|
||||
drivers/gpu/drm/i915/i915_reg.h | 5 ++++-
|
||||
drivers/gpu/drm/i915/intel_display.c | 10 ++++++----
|
||||
2 files changed, 10 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
|
||||
index 4cbc521..89b6efc 100644
|
||||
--- a/drivers/gpu/drm/i915/i915_reg.h
|
||||
+++ b/drivers/gpu/drm/i915/i915_reg.h
|
||||
@@ -1924,7 +1924,10 @@
|
||||
/* Display & cursor control */
|
||||
|
||||
/* dithering flag on Ironlake */
|
||||
-#define PIPE_ENABLE_DITHER (1 << 4)
|
||||
+#define PIPE_ENABLE_DITHER (1 << 4)
|
||||
+#define PIPE_DITHER_TYPE_MASK (3 << 2)
|
||||
+#define PIPE_DITHER_TYPE_SPATIAL (0 << 2)
|
||||
+#define PIPE_DITHER_TYPE_ST01 (1 << 2)
|
||||
/* Pipe A */
|
||||
#define PIPEADSL 0x70000
|
||||
#define PIPEACONF 0x70008
|
||||
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
|
||||
index c7502b6..f1a37d9 100644
|
||||
--- a/drivers/gpu/drm/i915/intel_display.c
|
||||
+++ b/drivers/gpu/drm/i915/intel_display.c
|
||||
@@ -3321,14 +3321,16 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||
/* set the dithering flag */
|
||||
if (IS_I965G(dev)) {
|
||||
if (dev_priv->lvds_dither) {
|
||||
- if (HAS_PCH_SPLIT(dev))
|
||||
+ if (HAS_PCH_SPLIT(dev)) {
|
||||
pipeconf |= PIPE_ENABLE_DITHER;
|
||||
- else
|
||||
+ pipeconf |= PIPE_DITHER_TYPE_ST01;
|
||||
+ } else
|
||||
lvds |= LVDS_ENABLE_DITHER;
|
||||
} else {
|
||||
- if (HAS_PCH_SPLIT(dev))
|
||||
+ if (HAS_PCH_SPLIT(dev)) {
|
||||
pipeconf &= ~PIPE_ENABLE_DITHER;
|
||||
- else
|
||||
+ pipeconf &= ~PIPE_DITHER_TYPE_MASK;
|
||||
+ } else
|
||||
lvds &= ~LVDS_ENABLE_DITHER;
|
||||
}
|
||||
}
|
||||
--
|
||||
1.7.0.1
|
||||
|
@ -1,37 +0,0 @@
|
||||
From 7f588d4ca94f4efd146b47cdcb6483edda4886f4 Mon Sep 17 00:00:00 2001
|
||||
From: Adam Jackson <ajax@redhat.com>
|
||||
Date: Fri, 28 May 2010 17:17:37 -0400
|
||||
Subject: [PATCH 2/4] drm/i915: Honor sync polarity from VBT panel timing descriptors
|
||||
|
||||
I'm actually kind of shocked that it works at all otherwise.
|
||||
|
||||
Signed-off-by: Adam Jackson <ajax@redhat.com>
|
||||
Signed-off-by: Eric Anholt <eric@anholt.net>
|
||||
---
|
||||
drivers/gpu/drm/i915/intel_bios.c | 10 ++++++++++
|
||||
1 files changed, 10 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
|
||||
index f9ba452..8905070 100644
|
||||
--- a/drivers/gpu/drm/i915/intel_bios.c
|
||||
+++ b/drivers/gpu/drm/i915/intel_bios.c
|
||||
@@ -95,6 +95,16 @@ fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
|
||||
panel_fixed_mode->clock = dvo_timing->clock * 10;
|
||||
panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED;
|
||||
|
||||
+ if (dvo_timing->hsync_positive)
|
||||
+ panel_fixed_mode->flags |= DRM_MODE_FLAG_PHSYNC;
|
||||
+ else
|
||||
+ panel_fixed_mode->flags |= DRM_MODE_FLAG_NHSYNC;
|
||||
+
|
||||
+ if (dvo_timing->vsync_positive)
|
||||
+ panel_fixed_mode->flags |= DRM_MODE_FLAG_PVSYNC;
|
||||
+ else
|
||||
+ panel_fixed_mode->flags |= DRM_MODE_FLAG_NVSYNC;
|
||||
+
|
||||
/* Some VBTs have bogus h/vtotal values */
|
||||
if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal)
|
||||
panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1;
|
||||
--
|
||||
1.7.0.1
|
||||
|
@ -1,266 +0,0 @@
|
||||
From 2fb8b53110fdf163eae9e8a506bf769449e2ee4b Mon Sep 17 00:00:00 2001
|
||||
From: Joanna Rutkowska <joanna@invisiblethingslab.com>
|
||||
Date: Tue, 29 Jun 2010 08:34:37 +0200
|
||||
Subject: [PATCH 3/4] drm/i915: Add the support of eDP on DP-D for Ibex/CPT
|
||||
|
||||
On some machines the eDP is connected on the PCH DP-D instead of DP-A.
|
||||
|
||||
Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
|
||||
|
||||
Conflicts:
|
||||
|
||||
drivers/gpu/drm/i915/intel_dp.c
|
||||
---
|
||||
drivers/gpu/drm/i915/intel_display.c | 2 +-
|
||||
drivers/gpu/drm/i915/intel_dp.c | 99 ++++++++++++++++++++++++++++++---
|
||||
drivers/gpu/drm/i915/intel_drv.h | 1 +
|
||||
3 files changed, 92 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
|
||||
index f1a37d9..32ae849 100644
|
||||
--- a/drivers/gpu/drm/i915/intel_display.c
|
||||
+++ b/drivers/gpu/drm/i915/intel_display.c
|
||||
@@ -3073,7 +3073,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||
temp |= PIPE_8BPC;
|
||||
else
|
||||
temp |= PIPE_6BPC;
|
||||
- } else if (is_edp) {
|
||||
+ } else if (is_edp || intel_edp_is_pch(crtc)) {
|
||||
switch (dev_priv->edp_bpp/3) {
|
||||
case 8:
|
||||
temp |= PIPE_8BPC;
|
||||
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
|
||||
index 77e40cf..c13c3bf 100644
|
||||
--- a/drivers/gpu/drm/i915/intel_dp.c
|
||||
+++ b/drivers/gpu/drm/i915/intel_dp.c
|
||||
@@ -43,6 +43,7 @@
|
||||
#define DP_LINK_CONFIGURATION_SIZE 9
|
||||
|
||||
#define IS_eDP(i) ((i)->type == INTEL_OUTPUT_EDP)
|
||||
+#define IS_PCH_eDP(dp_priv) ((dp_priv)->is_edpd)
|
||||
|
||||
struct intel_dp_priv {
|
||||
uint32_t output_reg;
|
||||
@@ -58,6 +59,7 @@ struct intel_dp_priv {
|
||||
struct intel_encoder *intel_encoder;
|
||||
struct i2c_adapter adapter;
|
||||
struct i2c_algo_dp_aux_data algo;
|
||||
+ bool is_edpd;
|
||||
};
|
||||
|
||||
static void
|
||||
@@ -130,8 +132,9 @@ intel_dp_link_required(struct drm_device *dev,
|
||||
struct intel_encoder *intel_encoder, int pixel_clock)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
+ struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
||||
|
||||
- if (IS_eDP(intel_encoder))
|
||||
+ if (IS_eDP(intel_encoder) || IS_PCH_eDP(dp_priv))
|
||||
return (pixel_clock * dev_priv->edp_bpp) / 8;
|
||||
else
|
||||
return pixel_clock * 3;
|
||||
@@ -534,14 +537,14 @@ intel_reduce_ratio(uint32_t *num, uint32_t *den)
|
||||
}
|
||||
|
||||
static void
|
||||
-intel_dp_compute_m_n(int bytes_per_pixel,
|
||||
+intel_dp_compute_m_n(int bpp,
|
||||
int nlanes,
|
||||
int pixel_clock,
|
||||
int link_clock,
|
||||
struct intel_dp_m_n *m_n)
|
||||
{
|
||||
m_n->tu = 64;
|
||||
- m_n->gmch_m = pixel_clock * bytes_per_pixel;
|
||||
+ m_n->gmch_m = (pixel_clock * bpp) >> 3;
|
||||
m_n->gmch_n = link_clock * nlanes;
|
||||
intel_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n);
|
||||
m_n->link_m = pixel_clock;
|
||||
@@ -549,6 +552,31 @@ intel_dp_compute_m_n(int bytes_per_pixel,
|
||||
intel_reduce_ratio(&m_n->link_m, &m_n->link_n);
|
||||
}
|
||||
|
||||
+bool intel_edp_is_pch(struct drm_crtc *crtc)
|
||||
+{
|
||||
+ struct drm_device *dev = crtc->dev;
|
||||
+ struct drm_mode_config *mode_config = &dev->mode_config;
|
||||
+ struct drm_encoder *encoder;
|
||||
+ bool ret = false;
|
||||
+
|
||||
+ list_for_each_entry(encoder, &mode_config->encoder_list, head) {
|
||||
+ struct intel_encoder *intel_encoder;
|
||||
+ struct intel_dp_priv *dp_priv;
|
||||
+
|
||||
+ if (!encoder || encoder->crtc != crtc)
|
||||
+ continue;
|
||||
+
|
||||
+ intel_encoder = enc_to_intel_encoder(encoder);
|
||||
+ dp_priv = intel_encoder->dev_priv;
|
||||
+
|
||||
+ if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT) {
|
||||
+ ret = IS_PCH_eDP(dp_priv);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
void
|
||||
intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
@@ -558,7 +586,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
|
||||
struct drm_connector *connector;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
- int lane_count = 4;
|
||||
+ int lane_count = 4, bpp = 24;
|
||||
struct intel_dp_m_n m_n;
|
||||
|
||||
/*
|
||||
@@ -573,6 +601,8 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
|
||||
|
||||
if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT) {
|
||||
lane_count = dp_priv->lane_count;
|
||||
+ if (IS_PCH_eDP(dp_priv))
|
||||
+ bpp = dev_priv->edp_bpp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -582,7 +612,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
|
||||
* the number of bytes_per_pixel post-LUT, which we always
|
||||
* set up for 8-bits of R/G/B, or 3 bytes total.
|
||||
*/
|
||||
- intel_dp_compute_m_n(3, lane_count,
|
||||
+ intel_dp_compute_m_n(bpp, lane_count,
|
||||
mode->clock, adjusted_mode->clock, &m_n);
|
||||
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
@@ -711,13 +741,13 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
|
||||
if (mode != DRM_MODE_DPMS_ON) {
|
||||
if (dp_reg & DP_PORT_EN) {
|
||||
intel_dp_link_down(intel_encoder, dp_priv->DP);
|
||||
- if (IS_eDP(intel_encoder))
|
||||
+ if (IS_eDP(intel_encoder) || IS_PCH_eDP(dp_priv))
|
||||
ironlake_edp_backlight_off(dev);
|
||||
}
|
||||
} else {
|
||||
if (!(dp_reg & DP_PORT_EN)) {
|
||||
intel_dp_link_train(intel_encoder, dp_priv->DP, dp_priv->link_configuration);
|
||||
- if (IS_eDP(intel_encoder))
|
||||
+ if (IS_eDP(intel_encoder) || IS_PCH_eDP(dp_priv))
|
||||
ironlake_edp_backlight_on(dev);
|
||||
}
|
||||
}
|
||||
@@ -1225,6 +1255,7 @@ static int intel_dp_get_modes(struct drm_connector *connector)
|
||||
struct intel_encoder *intel_encoder = to_intel_encoder(connector);
|
||||
struct drm_device *dev = intel_encoder->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
+ struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
||||
int ret;
|
||||
|
||||
/* We should parse the EDID data and find out if it has an audio sink
|
||||
@@ -1235,7 +1266,7 @@ static int intel_dp_get_modes(struct drm_connector *connector)
|
||||
return ret;
|
||||
|
||||
/* if eDP has no EDID, try to use fixed panel mode from VBT */
|
||||
- if (IS_eDP(intel_encoder)) {
|
||||
+ if (IS_eDP(intel_encoder) || IS_PCH_eDP(dp_priv)) {
|
||||
if (dev_priv->panel_fixed_mode != NULL) {
|
||||
struct drm_display_mode *mode;
|
||||
mode = drm_mode_duplicate(dev, dev_priv->panel_fixed_mode);
|
||||
@@ -1299,6 +1330,50 @@ intel_dp_hot_plug(struct intel_encoder *intel_encoder)
|
||||
intel_dp_check_link_status(intel_encoder);
|
||||
}
|
||||
|
||||
+/* Return which DP Port should be selected for Transcoder DP control */
|
||||
+int
|
||||
+intel_trans_dp_port_sel (struct drm_crtc *crtc)
|
||||
+{
|
||||
+ struct drm_device *dev = crtc->dev;
|
||||
+ struct drm_mode_config *mode_config = &dev->mode_config;
|
||||
+ struct drm_encoder *encoder;
|
||||
+ struct intel_encoder *intel_encoder = NULL;
|
||||
+
|
||||
+ list_for_each_entry(encoder, &mode_config->encoder_list, head) {
|
||||
+ if (encoder->crtc != crtc)
|
||||
+ continue;
|
||||
+
|
||||
+ intel_encoder = enc_to_intel_encoder(encoder);
|
||||
+ if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT) {
|
||||
+ struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
||||
+ return dp_priv->output_reg;
|
||||
+ }
|
||||
+ }
|
||||
+ return -1;
|
||||
+}
|
||||
+
|
||||
+static bool intel_dpd_is_edp(struct drm_device *dev)
|
||||
+{
|
||||
+ struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
+ struct child_device_config *p_child;
|
||||
+ int i, ret = false;
|
||||
+
|
||||
+ if (!dev_priv->child_dev_num)
|
||||
+ return false;
|
||||
+
|
||||
+ for (i = 0; i < dev_priv->child_dev_num; i++) {
|
||||
+ p_child = dev_priv->child_dev + i;
|
||||
+ if (p_child->device_type != DEVICE_TYPE_eDP)
|
||||
+ continue;
|
||||
+
|
||||
+ if (p_child->dvo_port == PORT_IDPD) {
|
||||
+ ret = true;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
void
|
||||
intel_dp_init(struct drm_device *dev, int output_reg)
|
||||
{
|
||||
@@ -1320,6 +1395,7 @@ intel_dp_init(struct drm_device *dev, int output_reg)
|
||||
DRM_MODE_CONNECTOR_DisplayPort);
|
||||
drm_connector_helper_add(connector, &intel_dp_connector_helper_funcs);
|
||||
|
||||
+ dp_priv->is_edpd = false;
|
||||
if (output_reg == DP_A)
|
||||
intel_encoder->type = INTEL_OUTPUT_EDP;
|
||||
else
|
||||
@@ -1335,6 +1411,11 @@ intel_dp_init(struct drm_device *dev, int output_reg)
|
||||
if (IS_eDP(intel_encoder))
|
||||
intel_encoder->clone_mask = (1 << INTEL_EDP_CLONE_BIT);
|
||||
|
||||
+ if (HAS_PCH_SPLIT(dev) && (output_reg == PCH_DP_D)) {
|
||||
+ if (intel_dpd_is_edp(dev))
|
||||
+ dp_priv->is_edpd = true;
|
||||
+ }
|
||||
+
|
||||
intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
|
||||
connector->interlace_allowed = true;
|
||||
connector->doublescan_allowed = 0;
|
||||
@@ -1383,7 +1464,7 @@ intel_dp_init(struct drm_device *dev, int output_reg)
|
||||
intel_encoder->ddc_bus = &dp_priv->adapter;
|
||||
intel_encoder->hot_plug = intel_dp_hot_plug;
|
||||
|
||||
- if (output_reg == DP_A) {
|
||||
+ if ((output_reg == DP_A) || IS_PCH_eDP(dp_priv)) {
|
||||
/* initialize panel mode from VBT if available for eDP */
|
||||
if (dev_priv->lfp_lvds_vbt_mode) {
|
||||
dev_priv->panel_fixed_mode =
|
||||
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
|
||||
index e302537..0858a17 100644
|
||||
--- a/drivers/gpu/drm/i915/intel_drv.h
|
||||
+++ b/drivers/gpu/drm/i915/intel_drv.h
|
||||
@@ -175,6 +175,7 @@ extern void intel_dp_init(struct drm_device *dev, int dp_reg);
|
||||
void
|
||||
intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode);
|
||||
+extern bool intel_edp_is_pch(struct drm_crtc *crtc);
|
||||
extern void intel_edp_link_config (struct intel_encoder *, int *, int *);
|
||||
|
||||
|
||||
--
|
||||
1.7.0.1
|
||||
|
@ -1,38 +0,0 @@
|
||||
From 46e3e699294d3fe4fecb08d697bb29addab29576 Mon Sep 17 00:00:00 2001
|
||||
From: Zhao Yakui <yakui.zhao@intel.com>
|
||||
Date: Fri, 28 May 2010 20:28:41 +0800
|
||||
Subject: [PATCH 4/4] drm/i915: Configure the PIPECONF dither correctly for eDP
|
||||
|
||||
The non-8 BPC can be used for the eDP output device that is connected through
|
||||
DP-A or DP-D on PCH. In such case we should set the PIPECONF dither correctly.
|
||||
|
||||
Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
|
||||
---
|
||||
drivers/gpu/drm/i915/intel_display.c | 11 +++++++++++
|
||||
1 files changed, 11 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
|
||||
index 32ae849..49c9663 100644
|
||||
--- a/drivers/gpu/drm/i915/intel_display.c
|
||||
+++ b/drivers/gpu/drm/i915/intel_display.c
|
||||
@@ -3239,6 +3239,17 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||
/* setup pipeconf */
|
||||
pipeconf = I915_READ(pipeconf_reg);
|
||||
|
||||
+ if (HAS_PCH_SPLIT(dev) && (is_edp || intel_edp_is_pch(crtc))) {
|
||||
+ /* configure the dither correctly for eDP */
|
||||
+ pipeconf &= ~PIPE_DITHER_TYPE_MASK;
|
||||
+ if ((pipeconf & PIPE_BPC_MASK) != PIPE_8BPC) {
|
||||
+ pipeconf |= PIPE_ENABLE_DITHER;
|
||||
+ pipeconf |= PIPE_DITHER_TYPE_ST01;
|
||||
+ } else {
|
||||
+ pipeconf &= ~PIPE_ENABLE_DITHER;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
/* Set up the display plane register */
|
||||
dspcntr = DISPPLANE_GAMMA_ENABLE;
|
||||
|
||||
--
|
||||
1.7.0.1
|
||||
|
@ -0,0 +1,35 @@
|
||||
From 4a122c10fbfe9020df469f0f669da129c5757671 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Rosenberg <drosenberg@vsecurity.com>
|
||||
Date: Thu, 17 Mar 2011 18:32:24 -0400
|
||||
Subject: [PATCH] ALSA: sound/pci/asihpi: check adapter index in hpi_ioctl
|
||||
Git-commit: 4a122c10fbfe9020df469f0f669da129c5757671
|
||||
Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6.git
|
||||
Patch-mainline: 2.6.39-rc1
|
||||
References: bnc#680816
|
||||
|
||||
The user-supplied index into the adapters array needs to be checked, or
|
||||
an out-of-bounds kernel pointer could be accessed and used, leading to
|
||||
potentially exploitable memory corruption.
|
||||
|
||||
Signed-off-by: Dan Rosenberg <drosenberg@vsecurity.com>
|
||||
Cc: <stable@kernel.org>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
|
||||
---
|
||||
sound/pci/asihpi/hpioctl.c | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
--- a/sound/pci/asihpi/hpioctl.c
|
||||
+++ b/sound/pci/asihpi/hpioctl.c
|
||||
@@ -155,6 +155,11 @@
|
||||
goto out;
|
||||
}
|
||||
|
||||
+ if (hm->h.adapter_index >= HPI_MAX_ADAPTERS) {
|
||||
+ err = -EINVAL;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
pa = &adapters[hm->h.adapter_index];
|
||||
hr->h.size = 0;
|
||||
if (hm->h.object == HPI_OBJ_SUBSYSTEM) {
|
@ -0,0 +1,96 @@
|
||||
From c6b358748e19ce7e230b0926ac42696bc485a562 Mon Sep 17 00:00:00 2001
|
||||
From: Takashi Iwai <tiwai@suse.de>
|
||||
Date: Mon, 28 Mar 2011 12:05:31 +0200
|
||||
Subject: [PATCH] ALSA: hda - Fix pin-config of Gigabyte mobo
|
||||
Git-commit: c6b358748e19ce7e230b0926ac42696bc485a562
|
||||
Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6.git
|
||||
Patch-mainline: (to be) 2.6.39-rc2
|
||||
References: bnc#677256
|
||||
|
||||
Use pin-fix instead of the static quirk for Gigabyte mobos 1458:a002.
|
||||
|
||||
Bugzilla: https://bugzilla.novell.com/show_bug.cgi?id=677256
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
|
||||
---
|
||||
sound/pci/hda/patch_realtek.c | 21 ++++++++++++++++++---
|
||||
1 file changed, 18 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/sound/pci/hda/patch_realtek.c
|
||||
+++ b/sound/pci/hda/patch_realtek.c
|
||||
@@ -9932,7 +9932,6 @@ static struct snd_pci_quirk alc882_cfg_t
|
||||
SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC883_LAPTOP_EAPD),
|
||||
SND_PCI_QUIRK(0x10f1, 0x2350, "TYAN-S2350", ALC888_6ST_DELL),
|
||||
SND_PCI_QUIRK(0x108e, 0x534d, NULL, ALC883_3ST_6ch),
|
||||
- SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte P35 DS3R", ALC882_6ST_DIG),
|
||||
|
||||
SND_PCI_QUIRK(0x1462, 0x0349, "MSI", ALC883_TARGA_2ch_DIG),
|
||||
SND_PCI_QUIRK(0x1462, 0x040d, "MSI", ALC883_TARGA_2ch_DIG),
|
||||
@@ -10769,6 +10768,7 @@ enum {
|
||||
PINFIX_LENOVO_Y530,
|
||||
PINFIX_PB_M5210,
|
||||
PINFIX_ACER_ASPIRE_7736,
|
||||
+ PINFIX_GIGABYTE_880GM,
|
||||
};
|
||||
|
||||
static const struct alc_fixup alc882_fixups[] = {
|
||||
@@ -10800,6 +10800,13 @@ static const struct alc_fixup alc882_fix
|
||||
.type = ALC_FIXUP_SKU,
|
||||
.v.sku = ALC_FIXUP_SKU_IGNORE,
|
||||
},
|
||||
+ [PINFIX_GIGABYTE_880GM] = {
|
||||
+ .type = ALC_FIXUP_PINS,
|
||||
+ .v.pins = (const struct alc_pincfg[]) {
|
||||
+ { 0x14, 0x1114410 }, /* set as speaker */
|
||||
+ { }
|
||||
+ }
|
||||
+ },
|
||||
};
|
||||
|
||||
static struct snd_pci_quirk alc882_fixup_tbl[] = {
|
||||
@@ -10807,6 +10814,7 @@ static struct snd_pci_quirk alc882_fixup
|
||||
SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", PINFIX_LENOVO_Y530),
|
||||
SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX),
|
||||
SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", PINFIX_ACER_ASPIRE_7736),
|
||||
+ SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte", PINFIX_GIGABYTE_880GM),
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -18851,8 +18859,6 @@ static struct snd_pci_quirk alc662_cfg_t
|
||||
ALC662_3ST_6ch_DIG),
|
||||
SND_PCI_QUIRK(0x1179, 0xff6e, "Toshiba NB20x", ALC662_AUTO),
|
||||
SND_PCI_QUIRK(0x144d, 0xca00, "Samsung NC10", ALC272_SAMSUNG_NC10),
|
||||
- SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L",
|
||||
- ALC662_3ST_6ch_DIG),
|
||||
SND_PCI_QUIRK(0x152d, 0x2304, "Quanta WH1", ALC663_ASUS_H13),
|
||||
SND_PCI_QUIRK(0x1565, 0x820f, "Biostar TA780G M2+", ALC662_3ST_6ch_DIG),
|
||||
SND_PCI_QUIRK(0x1631, 0xc10c, "PB RS65", ALC663_ASUS_M51VA),
|
||||
@@ -19526,6 +19532,7 @@ enum {
|
||||
ALC662_FIXUP_IDEAPAD,
|
||||
ALC272_FIXUP_MARIO,
|
||||
ALC662_FIXUP_CZC_P10T,
|
||||
+ ALC662_FIXUP_GIGABYTE,
|
||||
};
|
||||
|
||||
static const struct alc_fixup alc662_fixups[] = {
|
||||
@@ -19554,12 +19561,20 @@ static const struct alc_fixup alc662_fix
|
||||
{}
|
||||
}
|
||||
},
|
||||
+ [ALC662_FIXUP_GIGABYTE] = {
|
||||
+ .type = ALC_FIXUP_PINS,
|
||||
+ .v.pins = (const struct alc_pincfg[]) {
|
||||
+ { 0x14, 0x1114410 }, /* set as speaker */
|
||||
+ { }
|
||||
+ }
|
||||
+ },
|
||||
};
|
||||
|
||||
static struct snd_pci_quirk alc662_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE),
|
||||
SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
|
||||
SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
|
||||
+ SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte", ALC662_FIXUP_GIGABYTE),
|
||||
SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
|
||||
SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T),
|
@ -0,0 +1,22 @@
|
||||
From: Takashi Iwai <tiwai@suse.de>
|
||||
Subject: ALSA: hda - Increase the default buffer size
|
||||
Patch-mainline: Never
|
||||
References: 682725
|
||||
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
|
||||
---
|
||||
sound/pci/hda/hda_intel.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/sound/pci/hda/hda_intel.c
|
||||
+++ b/sound/pci/hda/hda_intel.c
|
||||
@@ -2057,7 +2057,7 @@
|
||||
/* buffer pre-allocation */
|
||||
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
|
||||
snd_dma_pci_data(chip->pci),
|
||||
- 1024 * 64, 32 * 1024 * 1024);
|
||||
+ 1024 * 1024, 32 * 1024 * 1024);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,178 +0,0 @@
|
||||
From 578454ff7eab61d13a26b568f99a89a2c9edc881 Mon Sep 17 00:00:00 2001
|
||||
From: Kay Sievers <kay.sievers@vrfy.org>
|
||||
Date: Thu, 20 May 2010 18:07:20 +0200
|
||||
Subject: driver core: add devname module aliases to allow module on-demand auto-loading
|
||||
Patch-mainline: 2.6.35
|
||||
|
||||
From: Kay Sievers <kay.sievers@vrfy.org>
|
||||
|
||||
commit 578454ff7eab61d13a26b568f99a89a2c9edc881 upstream.
|
||||
|
||||
This adds:
|
||||
alias: devname:<name>
|
||||
to some common kernel modules, which will allow the on-demand loading
|
||||
of the kernel module when the device node is accessed.
|
||||
|
||||
Ideally all these modules would be compiled-in, but distros seems too
|
||||
much in love with their modularization that we need to cover the common
|
||||
cases with this new facility. It will allow us to remove a bunch of pretty
|
||||
useless init scripts and modprobes from init scripts.
|
||||
|
||||
The static device node aliases will be carried in the module itself. The
|
||||
program depmod will extract this information to a file in the module directory:
|
||||
$ cat /lib/modules/2.6.34-00650-g537b60d-dirty/modules.devname
|
||||
# Device nodes to trigger on-demand module loading.
|
||||
microcode cpu/microcode c10:184
|
||||
fuse fuse c10:229
|
||||
ppp_generic ppp c108:0
|
||||
tun net/tun c10:200
|
||||
dm_mod mapper/control c10:235
|
||||
|
||||
Udev will pick up the depmod created file on startup and create all the
|
||||
static device nodes which the kernel modules specify, so that these modules
|
||||
get automatically loaded when the device node is accessed:
|
||||
$ /sbin/udevd --debug
|
||||
...
|
||||
static_dev_create_from_modules: mknod '/dev/cpu/microcode' c10:184
|
||||
static_dev_create_from_modules: mknod '/dev/fuse' c10:229
|
||||
static_dev_create_from_modules: mknod '/dev/ppp' c108:0
|
||||
static_dev_create_from_modules: mknod '/dev/net/tun' c10:200
|
||||
static_dev_create_from_modules: mknod '/dev/mapper/control' c10:235
|
||||
udev_rules_apply_static_dev_perms: chmod '/dev/net/tun' 0666
|
||||
udev_rules_apply_static_dev_perms: chmod '/dev/fuse' 0666
|
||||
|
||||
A few device nodes are switched to statically allocated numbers, to allow
|
||||
the static nodes to work. This might also useful for systems which still run
|
||||
a plain static /dev, which is completely unsafe to use with any dynamic minor
|
||||
numbers.
|
||||
|
||||
Note:
|
||||
The devname aliases must be limited to the *common* and *single*instance*
|
||||
device nodes, like the misc devices, and never be used for conceptually limited
|
||||
systems like the loop devices, which should rather get fixed properly and get a
|
||||
control node for losetup to talk to, instead of creating a random number of
|
||||
device nodes in advance, regardless if they are ever used.
|
||||
|
||||
This facility is to hide the mess distros are creating with too modualized
|
||||
kernels, and just to hide that these modules are not compiled-in, and not to
|
||||
paper-over broken concepts. Thanks! :)
|
||||
|
||||
Cc: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
Cc: David S. Miller <davem@davemloft.net>
|
||||
Cc: Miklos Szeredi <miklos@szeredi.hu>
|
||||
Cc: Chris Mason <chris.mason@oracle.com>
|
||||
Cc: Alasdair G Kergon <agk@redhat.com>
|
||||
Cc: Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
|
||||
Cc: Ian Kent <raven@themaw.net>
|
||||
Signed-Off-By: Kay Sievers <kay.sievers@vrfy.org>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
|
||||
--- a/Documentation/devices.txt
|
||||
+++ b/Documentation/devices.txt
|
||||
@@ -443,6 +443,8 @@ Your cooperation is appreciated.
|
||||
231 = /dev/snapshot System memory snapshot device
|
||||
232 = /dev/kvm Kernel-based virtual machine (hardware virtualization extensions)
|
||||
233 = /dev/kmview View-OS A process with a view
|
||||
+ 234 = /dev/btrfs-control Btrfs control device
|
||||
+ 235 = /dev/autofs Autofs control device
|
||||
240-254 Reserved for local use
|
||||
255 Reserved for MISC_DYNAMIC_MINOR
|
||||
|
||||
diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c
|
||||
index 2cd8c54..fa6551d 100644
|
||||
--- a/arch/x86/kernel/microcode_core.c
|
||||
+++ b/arch/x86/kernel/microcode_core.c
|
||||
@@ -260,6 +260,7 @@ static void microcode_dev_exit(void)
|
||||
}
|
||||
|
||||
MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);
|
||||
+MODULE_ALIAS("devname:cpu/microcode");
|
||||
#else
|
||||
#define microcode_dev_init() 0
|
||||
#define microcode_dev_exit() do { } while (0)
|
||||
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
|
||||
index 5441688..c5f8eb1 100644
|
||||
--- a/drivers/net/ppp_generic.c
|
||||
+++ b/drivers/net/ppp_generic.c
|
||||
@@ -2926,5 +2926,5 @@ EXPORT_SYMBOL(ppp_output_wakeup);
|
||||
EXPORT_SYMBOL(ppp_register_compressor);
|
||||
EXPORT_SYMBOL(ppp_unregister_compressor);
|
||||
MODULE_LICENSE("GPL");
|
||||
-MODULE_ALIAS_CHARDEV_MAJOR(PPP_MAJOR);
|
||||
-MODULE_ALIAS("/dev/ppp");
|
||||
+MODULE_ALIAS_CHARDEV(PPP_MAJOR, 0);
|
||||
+MODULE_ALIAS("devname:ppp");
|
||||
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
|
||||
index 97b2553..005cad6 100644
|
||||
--- a/drivers/net/tun.c
|
||||
+++ b/drivers/net/tun.c
|
||||
@@ -1649,3 +1649,4 @@ MODULE_DESCRIPTION(DRV_DESCRIPTION);
|
||||
MODULE_AUTHOR(DRV_COPYRIGHT);
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS_MISCDEV(TUN_MINOR);
|
||||
+MODULE_ALIAS("devname:net/tun");
|
||||
diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c
|
||||
index d29b7f6..d832062 100644
|
||||
--- a/fs/autofs4/dev-ioctl.c
|
||||
+++ b/fs/autofs4/dev-ioctl.c
|
||||
@@ -736,11 +736,14 @@ static const struct file_operations _dev_ioctl_fops = {
|
||||
};
|
||||
|
||||
static struct miscdevice _autofs_dev_ioctl_misc = {
|
||||
- .minor = MISC_DYNAMIC_MINOR,
|
||||
+ .minor = AUTOFS_MINOR,
|
||||
.name = AUTOFS_DEVICE_NAME,
|
||||
.fops = &_dev_ioctl_fops
|
||||
};
|
||||
|
||||
+MODULE_ALIAS_MISCDEV(AUTOFS_MINOR);
|
||||
+MODULE_ALIAS("devname:autofs");
|
||||
+
|
||||
/* Register/deregister misc character device */
|
||||
int autofs_dev_ioctl_init(void)
|
||||
{
|
||||
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
|
||||
index 1866dff..2909a03 100644
|
||||
--- a/fs/btrfs/super.c
|
||||
+++ b/fs/btrfs/super.c
|
||||
@@ -832,11 +832,14 @@ static const struct file_operations btrfs_ctl_fops = {
|
||||
};
|
||||
|
||||
static struct miscdevice btrfs_misc = {
|
||||
- .minor = MISC_DYNAMIC_MINOR,
|
||||
+ .minor = BTRFS_MINOR,
|
||||
.name = "btrfs-control",
|
||||
.fops = &btrfs_ctl_fops
|
||||
};
|
||||
|
||||
+MODULE_ALIAS_MISCDEV(BTRFS_MINOR);
|
||||
+MODULE_ALIAS("devname:btrfs-control");
|
||||
+
|
||||
static int btrfs_interface_init(void)
|
||||
{
|
||||
return misc_register(&btrfs_misc);
|
||||
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
|
||||
index eb7e942..e53df5e 100644
|
||||
--- a/fs/fuse/dev.c
|
||||
+++ b/fs/fuse/dev.c
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <linux/slab.h>
|
||||
|
||||
MODULE_ALIAS_MISCDEV(FUSE_MINOR);
|
||||
+MODULE_ALIAS("devname:fuse");
|
||||
|
||||
static struct kmem_cache *fuse_req_cachep;
|
||||
|
||||
diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h
|
||||
index 8b5f7cc..b631c46 100644
|
||||
--- a/include/linux/miscdevice.h
|
||||
+++ b/include/linux/miscdevice.h
|
||||
@@ -31,6 +31,8 @@
|
||||
#define FUSE_MINOR 229
|
||||
#define KVM_MINOR 232
|
||||
#define VHOST_NET_MINOR 233
|
||||
+#define BTRFS_MINOR 234
|
||||
+#define AUTOFS_MINOR 235
|
||||
#define MISC_DYNAMIC_MINOR 255
|
||||
|
||||
struct device;
|
@ -1,35 +0,0 @@
|
||||
From feacc14de65224ccda1d8fae5140cdf043a151b0 Mon Sep 17 00:00:00 2001
|
||||
From: Francisco Jerez <currojerez@riseup.net>
|
||||
Date: Thu, 17 Jun 2010 12:42:14 +0200
|
||||
Subject: [PATCH] drm/nouveau: Don't clear AGPCMD completely on INIT_RESET.
|
||||
|
||||
We just need to clear the SBA and ENABLE bits to reset the AGP
|
||||
controller: If the AGP bridge was configured to use "fast writes",
|
||||
clearing the FW bit would break the subsequent MMIO writes and
|
||||
eventually end with a lockup.
|
||||
|
||||
Note that all the BIOSes I've seen do the same as we did (it works for
|
||||
them because they don't use MMIO), OTOH the blob leaves FW untouched.
|
||||
|
||||
Signed-off-by: Francisco Jerez <currojerez@riseup.net>
|
||||
---
|
||||
drivers/gpu/drm/nouveau/nouveau_bios.c | 3 ++-
|
||||
1 files changed, 2 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
|
||||
index abc382a..7c983d8 100644
|
||||
--- a/drivers/gpu/drm/nouveau/nouveau_bios.c
|
||||
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
|
||||
@@ -1910,7 +1910,8 @@ init_reset(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
|
||||
/* no iexec->execute check by design */
|
||||
|
||||
pci_nv_19 = bios_rd32(bios, NV_PBUS_PCI_NV_19);
|
||||
- bios_wr32(bios, NV_PBUS_PCI_NV_19, 0);
|
||||
+ bios_wr32(bios, NV_PBUS_PCI_NV_19, pci_nv_19 & ~0xf00);
|
||||
+
|
||||
bios_wr32(bios, reg, value1);
|
||||
|
||||
udelay(10);
|
||||
--
|
||||
1.7.0.1
|
||||
|
@ -1,110 +0,0 @@
|
||||
From d83809c6fdb908ba708382c9a506f6647d1fa86d Mon Sep 17 00:00:00 2001
|
||||
From: Maarten Maathuis <madman2003@gmail.com>
|
||||
Date: Sun, 9 May 2010 14:49:52 +0200
|
||||
Subject: [PATCH] drm/nouveau: allow cursor image and position to survive suspend
|
||||
|
||||
- This isn't triggered yet on a normal kernel, because it still does a VT
|
||||
switch, but it seemed like a good idea to fix this now.
|
||||
|
||||
Tested-by: Maxim Levitsky <maximlevitsky@gmail.com>
|
||||
Signed-off-by: Maarten Maathuis <madman2003@gmail.com>
|
||||
---
|
||||
drivers/gpu/drm/nouveau/nouveau_crtc.h | 2 ++
|
||||
drivers/gpu/drm/nouveau/nouveau_drv.c | 29 +++++++++++++++++++++++++++++
|
||||
drivers/gpu/drm/nouveau/nv04_cursor.c | 1 +
|
||||
drivers/gpu/drm/nouveau/nv50_cursor.c | 1 +
|
||||
4 files changed, 33 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/nouveau/nouveau_crtc.h b/drivers/gpu/drm/nouveau/nouveau_crtc.h
|
||||
index 49fa7b2..cb1ce2a 100644
|
||||
--- a/drivers/gpu/drm/nouveau/nouveau_crtc.h
|
||||
+++ b/drivers/gpu/drm/nouveau/nouveau_crtc.h
|
||||
@@ -40,6 +40,8 @@ struct nouveau_crtc {
|
||||
int sharpness;
|
||||
int last_dpms;
|
||||
|
||||
+ int cursor_saved_x, cursor_saved_y;
|
||||
+
|
||||
struct {
|
||||
int cpp;
|
||||
bool blanked;
|
||||
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c
|
||||
index 1de974a..4bccba3 100644
|
||||
--- a/drivers/gpu/drm/nouveau/nouveau_drv.c
|
||||
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.c
|
||||
@@ -177,6 +177,13 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state)
|
||||
nouveau_bo_unpin(nouveau_fb->nvbo);
|
||||
}
|
||||
|
||||
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
|
||||
+
|
||||
+ nouveau_bo_unmap(nv_crtc->cursor.nvbo);
|
||||
+ nouveau_bo_unpin(nv_crtc->cursor.nvbo);
|
||||
+ }
|
||||
+
|
||||
NV_INFO(dev, "Evicting buffers...\n");
|
||||
ttm_bo_evict_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM);
|
||||
|
||||
@@ -318,12 +325,34 @@ nouveau_pci_resume(struct pci_dev *pdev)
|
||||
nouveau_bo_pin(nouveau_fb->nvbo, TTM_PL_FLAG_VRAM);
|
||||
}
|
||||
|
||||
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM);
|
||||
+ if (!ret)
|
||||
+ ret = nouveau_bo_map(nv_crtc->cursor.nvbo);
|
||||
+ if (ret)
|
||||
+ NV_ERROR(dev, "Could not pin/map cursor.\n");
|
||||
+ }
|
||||
+
|
||||
if (dev_priv->card_type < NV_50) {
|
||||
nv04_display_restore(dev);
|
||||
NVLockVgaCrtcs(dev, false);
|
||||
} else
|
||||
nv50_display_init(dev);
|
||||
|
||||
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
|
||||
+
|
||||
+ nv_crtc->cursor.set_offset(nv_crtc,
|
||||
+ nv_crtc->cursor.nvbo->bo.offset -
|
||||
+ dev_priv->vm_vram_base);
|
||||
+
|
||||
+ nv_crtc->cursor.set_pos(nv_crtc, nv_crtc->cursor_saved_x,
|
||||
+ nv_crtc->cursor_saved_y);
|
||||
+ }
|
||||
+
|
||||
/* Force CLUT to get re-loaded during modeset */
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
|
||||
diff --git a/drivers/gpu/drm/nouveau/nv04_cursor.c b/drivers/gpu/drm/nouveau/nv04_cursor.c
|
||||
index 89a91b9..aaf3de3 100644
|
||||
--- a/drivers/gpu/drm/nouveau/nv04_cursor.c
|
||||
+++ b/drivers/gpu/drm/nouveau/nv04_cursor.c
|
||||
@@ -20,6 +20,7 @@ nv04_cursor_hide(struct nouveau_crtc *nv_crtc, bool update)
|
||||
static void
|
||||
nv04_cursor_set_pos(struct nouveau_crtc *nv_crtc, int x, int y)
|
||||
{
|
||||
+ nv_crtc->cursor_saved_x = x; nv_crtc->cursor_saved_y = y;
|
||||
NVWriteRAMDAC(nv_crtc->base.dev, nv_crtc->index,
|
||||
NV_PRAMDAC_CU_START_POS,
|
||||
XLATE(y, 0, NV_PRAMDAC_CU_START_POS_Y) |
|
||||
diff --git a/drivers/gpu/drm/nouveau/nv50_cursor.c b/drivers/gpu/drm/nouveau/nv50_cursor.c
|
||||
index 753e723..03ad7ab 100644
|
||||
--- a/drivers/gpu/drm/nouveau/nv50_cursor.c
|
||||
+++ b/drivers/gpu/drm/nouveau/nv50_cursor.c
|
||||
@@ -107,6 +107,7 @@ nv50_cursor_set_pos(struct nouveau_crtc *nv_crtc, int x, int y)
|
||||
{
|
||||
struct drm_device *dev = nv_crtc->base.dev;
|
||||
|
||||
+ nv_crtc->cursor_saved_x = x; nv_crtc->cursor_saved_y = y;
|
||||
nv_wr32(dev, NV50_PDISPLAY_CURSOR_USER_POS(nv_crtc->index),
|
||||
((y & 0xFFFF) << 16) | (x & 0xFFFF));
|
||||
/* Needed to make the cursor move. */
|
||||
--
|
||||
1.7.0.1
|
||||
|
@ -1,68 +0,0 @@
|
||||
From: Brandeburg, Jesse <jesse.brandeburg@intel.com>
|
||||
Subject: [PATCH] e1000: enhance frame fragment detection
|
||||
References: bnc#567376, CVE-2009-4536
|
||||
Patch-Mainline: Yes
|
||||
|
||||
A security discussion was recently given:
|
||||
http://events.ccc.de/congress/2009/Fahrplan//events/3596.en.html And a patch
|
||||
that I submitted awhile back was brought up. Apparently some of their testing
|
||||
revealed that they were able to force a buffer fragment in e1000 in which the
|
||||
trailing fragment was greater than 4 bytes. As a result the fragment check I
|
||||
introduced failed to detect the fragement and a partial invalid frame was
|
||||
passed up into the network stack. I've written this patch to correct it. I'm
|
||||
in the process of testing it now, but it makes good logical sense to me.
|
||||
Effectively it maintains a per-adapter state variable which detects a non-EOP
|
||||
frame, and discards it and subsequent non-EOP frames leading up to _and_
|
||||
_including_ the next positive-EOP frame (as it is by definition the last
|
||||
fragment). This should prevent any and all partial frames from entering the
|
||||
network stack from e1000.
|
||||
|
||||
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
|
||||
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
|
||||
Signed-off-by: Brandon Philips <bphilips@suse.de>
|
||||
|
||||
---
|
||||
|
||||
drivers/net/e1000/e1000.h | 2 ++
|
||||
drivers/net/e1000/e1000_main.c | 13 +++++++++++--
|
||||
2 files changed, 13 insertions(+), 2 deletions(-)
|
||||
|
||||
|
||||
--- a/drivers/net/e1000/e1000.h
|
||||
+++ b/drivers/net/e1000/e1000.h
|
||||
@@ -326,6 +326,8 @@ struct e1000_adapter {
|
||||
/* for ioport free */
|
||||
int bars;
|
||||
int need_ioport;
|
||||
+
|
||||
+ bool discarding;
|
||||
};
|
||||
|
||||
enum e1000_state_t {
|
||||
--- a/drivers/net/e1000/e1000_main.c
|
||||
+++ b/drivers/net/e1000/e1000_main.c
|
||||
@@ -3834,13 +3834,22 @@ static bool e1000_clean_rx_irq(struct e1
|
||||
|
||||
length = le16_to_cpu(rx_desc->length);
|
||||
/* !EOP means multiple descriptors were used to store a single
|
||||
- * packet, also make sure the frame isn't just CRC only */
|
||||
- if (unlikely(!(status & E1000_RXD_STAT_EOP) || (length <= 4))) {
|
||||
+ * packet, if thats the case we need to toss it. In fact, we
|
||||
+ * to toss every packet with the EOP bit clear and the next
|
||||
+ * frame that _does_ have the EOP bit set, as it is by
|
||||
+ * definition only a frame fragment
|
||||
+ */
|
||||
+ if (unlikely(!(status & E1000_RXD_STAT_EOP)))
|
||||
+ adapter->discarding = true;
|
||||
+
|
||||
+ if (adapter->discarding) {
|
||||
/* All receives must fit into a single buffer */
|
||||
E1000_DBG("%s: Receive packet consumed multiple"
|
||||
" buffers\n", netdev->name);
|
||||
/* recycle */
|
||||
buffer_info->skb = skb;
|
||||
+ if (status & E1000_RXD_STAT_EOP)
|
||||
+ adapter->discarding = false;
|
||||
goto next_desc;
|
||||
}
|
||||
|
@ -1,142 +0,0 @@
|
||||
From: Neil Horman <nhorman@tuxdriver.com>
|
||||
Subject: [PATCH] e1000e: enhance frame fragment detection
|
||||
References: bnc#567376, CVE-2009-4538
|
||||
|
||||
A security discussion was recently given:
|
||||
http://events.ccc.de/congress/2009/Fahrplan//events/3596.en.html And a patch
|
||||
that I submitted awhile back was brought up. Apparently some of their testing
|
||||
revealed that they were able to force a buffer fragment in e1000e in which the
|
||||
trailing fragment was greater than 4 bytes. As a result the fragment check I
|
||||
introduced failed to detect the fragement and a partial invalid frame was
|
||||
passed up into the network stack. I've written this patch to correct it. I'm
|
||||
in the process of testing it now, but it makes good logical sense to me.
|
||||
Effectively it maintains a per-adapter state variable which detects a non-EOP
|
||||
frame, and discards it and subsequent non-EOP frames leading up to _and_
|
||||
_including_ the next positive-EOP frame (as it is by definition the last
|
||||
fragment). This should prevent any and all partial frames from entering the
|
||||
network stack from e1000e
|
||||
|
||||
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
|
||||
Signed-off-by: Brandon Philips <bphilips@suse.de>
|
||||
---
|
||||
drivers/net/e1000e/e1000.h | 3 ++-
|
||||
drivers/net/e1000e/netdev.c | 13 +++++++++++--
|
||||
2 files changed, 13 insertions(+), 3 deletions(-)
|
||||
|
||||
Index: linux-2.6.31-openSUSE-11.2/drivers/net/e1000e/e1000.h
|
||||
===================================================================
|
||||
--- linux-2.6.31-openSUSE-11.2.orig/drivers/net/e1000e/e1000.h
|
||||
+++ linux-2.6.31-openSUSE-11.2/drivers/net/e1000e/e1000.h
|
||||
@@ -412,7 +412,8 @@ struct e1000_info {
|
||||
enum e1000_state_t {
|
||||
__E1000_TESTING,
|
||||
__E1000_RESETTING,
|
||||
- __E1000_DOWN
|
||||
+ __E1000_DOWN,
|
||||
+ __E1000_DISCARDING
|
||||
};
|
||||
|
||||
enum latency_range {
|
||||
Index: linux-2.6.31-openSUSE-11.2/drivers/net/e1000e/netdev.c
|
||||
===================================================================
|
||||
--- linux-2.6.31-openSUSE-11.2.orig/drivers/net/e1000e/netdev.c
|
||||
+++ linux-2.6.31-openSUSE-11.2/drivers/net/e1000e/netdev.c
|
||||
@@ -483,12 +483,21 @@ static bool e1000_clean_rx_irq(struct e1
|
||||
length = le16_to_cpu(rx_desc->length);
|
||||
|
||||
/* !EOP means multiple descriptors were used to store a single
|
||||
- * packet, also make sure the frame isn't just CRC only */
|
||||
- if (!(status & E1000_RXD_STAT_EOP) || (length <= 4)) {
|
||||
+ * packet, if thats the case we need to toss it. In fact, we
|
||||
+ * to toss every packet with the EOP bit clear and the next
|
||||
+ * frame that _does_ have the EOP bit set, as it is by
|
||||
+ * definition only a frame fragment
|
||||
+ */
|
||||
+ if (unlikely(!(status & E1000_RXD_STAT_EOP)))
|
||||
+ set_bit(__E1000_DISCARDING, &adapter->state);
|
||||
+
|
||||
+ if (test_bit(__E1000_DISCARDING, &adapter->state)) {
|
||||
/* All receives must fit into a single buffer */
|
||||
e_dbg("Receive packet consumed multiple buffers\n");
|
||||
/* recycle */
|
||||
buffer_info->skb = skb;
|
||||
+ if (status & E1000_RXD_STAT_EOP)
|
||||
+ clear_bit(__E1000_DISCARDING, &adapter->state);
|
||||
goto next_desc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,35 +0,0 @@
|
||||
From: Tejun Heo <teheo@suse.de>
|
||||
Date: Wed, 7 Feb 2007 12:37:41 -0800
|
||||
Subject: [PATCH] libata: add waits for GoVault
|
||||
References: 246451
|
||||
Patch-mainline: not yet
|
||||
|
||||
Iomega GoVault drives need specific waits here and there. Upstream
|
||||
approach hasn't been determined yet. This is temp solution from Gary
|
||||
Hade. Read the following thread for details.
|
||||
|
||||
http://thread.gmane.org/gmane.linux.ide/14545/focus=14663
|
||||
|
||||
With recent changes in the reset sequence (ATA_TMOUT_FF_WAIT and
|
||||
prefer-hardreset), the only thing which needs adjustment is
|
||||
ATA_TMOUT_FF_WAIT (the prereset wait part is unnecessary as the wait
|
||||
is necessary only for softreset when SCR registers are accessible and
|
||||
in those cases libata now always uses hardreset which doesn't require
|
||||
such wait).
|
||||
|
||||
Signed-off-by: Tejun Heo <teheo@suse.de>
|
||||
---
|
||||
include/linux/libata.h | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/include/linux/libata.h
|
||||
+++ b/include/linux/libata.h
|
||||
@@ -260,7 +260,7 @@ enum {
|
||||
* HHD424020F7SV00. Increase to 2secs when parallel probing
|
||||
* is in place.
|
||||
*/
|
||||
- ATA_TMOUT_FF_WAIT = 800,
|
||||
+ ATA_TMOUT_FF_WAIT = 2000,
|
||||
|
||||
/* Spec mandates to wait for ">= 2ms" before checking status
|
||||
* after reset. We wait 150ms, because that was the magic
|
@ -1,30 +0,0 @@
|
||||
From: Tejun Heo <tj@kernel.org>
|
||||
Subject: [PATCH] pci: disable MSI on VIA K8M800
|
||||
References: bnc#599508
|
||||
Patch-Mainline: Pending for 2.6.35 and -stable
|
||||
|
||||
MSI delivery from on-board ahci controller doesn't work on K8M800. At
|
||||
this point, it's unclear whether the culprit is with the ahci
|
||||
controller or the host bridge. Given the track record and considering
|
||||
the rather minimal impact of MSI, disabling it seems reasonable.
|
||||
|
||||
Signed-off-by: Tejun Heo <tj@kernel.org>
|
||||
Reported-by: Rainer Hurtado Navarro <publio.escipion.el.africano@gmail.com>
|
||||
Cc: stable@kernel.org
|
||||
Signed-off-by: Tejun Heo <teheo@suse.de>
|
||||
---
|
||||
drivers/pci/quirks.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
Index: linux-2.6.34-master/drivers/pci/quirks.c
|
||||
===================================================================
|
||||
--- linux-2.6.34-master.orig/drivers/pci/quirks.c
|
||||
+++ linux-2.6.34-master/drivers/pci/quirks.c
|
||||
@@ -2112,6 +2112,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AT
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3336, quirk_disable_all_msi);
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3351, quirk_disable_all_msi);
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3364, quirk_disable_all_msi);
|
||||
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8380_0, quirk_disable_all_msi);
|
||||
|
||||
/* Disable MSI on chipsets that are known to not support it */
|
||||
static void __devinit quirk_disable_msi(struct pci_dev *dev)
|
@ -0,0 +1,707 @@
|
||||
From foo@baz Wed Feb 9 13:35:10 PST 2011
|
||||
Date: Wed, 09 Feb 2011 13:35:10 -0800
|
||||
To: Greg KH <greg@kroah.com>
|
||||
From: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
Subject: Staging: samsung-laptop: add support for lots of laptops
|
||||
References: bnc#661682
|
||||
Patch-mainline: 2.6.39
|
||||
|
||||
This is a backport of the upstream version of the driver that added support for
|
||||
all samsung laptop devices.
|
||||
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
|
||||
diff --git a/drivers/staging/samsung-laptop/samsung-laptop.c b/drivers/staging/samsung-laptop/samsung-laptop.c
|
||||
index 701e8d5..51ec621 100644
|
||||
--- a/drivers/staging/samsung-laptop/samsung-laptop.c
|
||||
+++ b/drivers/staging/samsung-laptop/samsung-laptop.c
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
- * Samsung N130 Laptop driver
|
||||
+ * Samsung Laptop driver
|
||||
*
|
||||
* Copyright (C) 2009 Greg Kroah-Hartman (gregkh@suse.de)
|
||||
* Copyright (C) 2009 Novell Inc.
|
||||
@@ -33,51 +33,6 @@
|
||||
*/
|
||||
#define MAX_BRIGHT 0x07
|
||||
|
||||
-/* Brightness is 0 - 8, as described above. Value 0 is for the BIOS to use */
|
||||
-#define GET_BRIGHTNESS 0x00
|
||||
-#define SET_BRIGHTNESS 0x01
|
||||
-
|
||||
-/* first byte:
|
||||
- * 0x00 - wireless is off
|
||||
- * 0x01 - wireless is on
|
||||
- * second byte:
|
||||
- * 0x02 - 3G is off
|
||||
- * 0x03 - 3G is on
|
||||
- * TODO, verify 3G is correct, that doesn't seem right...
|
||||
- */
|
||||
-#define GET_WIRELESS_BUTTON 0x02
|
||||
-#define SET_WIRELESS_BUTTON 0x03
|
||||
-
|
||||
-/* 0 is off, 1 is on */
|
||||
-#define GET_BACKLIGHT 0x04
|
||||
-#define SET_BACKLIGHT 0x05
|
||||
-
|
||||
-/*
|
||||
- * 0x80 or 0x00 - no action
|
||||
- * 0x81 - recovery key pressed
|
||||
- */
|
||||
-#define GET_RECOVERY_METHOD 0x06
|
||||
-#define SET_RECOVERY_METHOD 0x07
|
||||
-
|
||||
-/* 0 is low, 1 is high */
|
||||
-#define GET_PERFORMANCE_LEVEL 0x08
|
||||
-#define SET_PERFORMANCE_LEVEL 0x09
|
||||
-
|
||||
-/*
|
||||
- * Tell the BIOS that Linux is running on this machine.
|
||||
- * 81 is on, 80 is off
|
||||
- */
|
||||
-#define SET_LINUX 0x0a
|
||||
-
|
||||
-
|
||||
-#define MAIN_FUNCTION 0x4c49
|
||||
-
|
||||
-#define SABI_HEADER_PORT 0x00
|
||||
-#define SABI_HEADER_RE_MEM 0x02
|
||||
-#define SABI_HEADER_IFACEFUNC 0x03
|
||||
-#define SABI_HEADER_EN_MEM 0x04
|
||||
-#define SABI_HEADER_DATA_OFFSET 0x05
|
||||
-#define SABI_HEADER_DATA_SEGMENT 0x07
|
||||
|
||||
#define SABI_IFACE_MAIN 0x00
|
||||
#define SABI_IFACE_SUB 0x02
|
||||
@@ -89,6 +44,173 @@ struct sabi_retval {
|
||||
u8 retval[20];
|
||||
};
|
||||
|
||||
+struct sabi_header_offsets {
|
||||
+ u8 port;
|
||||
+ u8 re_mem;
|
||||
+ u8 iface_func;
|
||||
+ u8 en_mem;
|
||||
+ u8 data_offset;
|
||||
+ u8 data_segment;
|
||||
+};
|
||||
+
|
||||
+struct sabi_commands {
|
||||
+ /*
|
||||
+ * Brightness is 0 - 8, as described above.
|
||||
+ * Value 0 is for the BIOS to use
|
||||
+ */
|
||||
+ u8 get_brightness;
|
||||
+ u8 set_brightness;
|
||||
+
|
||||
+ /*
|
||||
+ * first byte:
|
||||
+ * 0x00 - wireless is off
|
||||
+ * 0x01 - wireless is on
|
||||
+ * second byte:
|
||||
+ * 0x02 - 3G is off
|
||||
+ * 0x03 - 3G is on
|
||||
+ * TODO, verify 3G is correct, that doesn't seem right...
|
||||
+ */
|
||||
+ u8 get_wireless_button;
|
||||
+ u8 set_wireless_button;
|
||||
+
|
||||
+ /* 0 is off, 1 is on */
|
||||
+ u8 get_backlight;
|
||||
+ u8 set_backlight;
|
||||
+
|
||||
+ /*
|
||||
+ * 0x80 or 0x00 - no action
|
||||
+ * 0x81 - recovery key pressed
|
||||
+ */
|
||||
+ u8 get_recovery_mode;
|
||||
+ u8 set_recovery_mode;
|
||||
+
|
||||
+ /*
|
||||
+ * on seclinux: 0 is low, 1 is high,
|
||||
+ * on swsmi: 0 is normal, 1 is silent, 2 is turbo
|
||||
+ */
|
||||
+ u8 get_performance_level;
|
||||
+ u8 set_performance_level;
|
||||
+
|
||||
+ /*
|
||||
+ * Tell the BIOS that Linux is running on this machine.
|
||||
+ * 81 is on, 80 is off
|
||||
+ */
|
||||
+ u8 set_linux;
|
||||
+};
|
||||
+
|
||||
+struct sabi_performance_level {
|
||||
+ const char *name;
|
||||
+ u8 value;
|
||||
+};
|
||||
+
|
||||
+struct sabi_config {
|
||||
+ const char *test_string;
|
||||
+ u16 main_function;
|
||||
+ struct sabi_header_offsets header_offsets;
|
||||
+ struct sabi_commands commands;
|
||||
+ struct sabi_performance_level performance_levels[4];
|
||||
+};
|
||||
+
|
||||
+static struct sabi_config sabi_configs[] = {
|
||||
+ {
|
||||
+ .test_string = "SECLINUX",
|
||||
+
|
||||
+ .main_function = 0x4c59,
|
||||
+
|
||||
+ .header_offsets = {
|
||||
+ .port = 0x00,
|
||||
+ .re_mem = 0x02,
|
||||
+ .iface_func = 0x03,
|
||||
+ .en_mem = 0x04,
|
||||
+ .data_offset = 0x05,
|
||||
+ .data_segment = 0x07,
|
||||
+ },
|
||||
+
|
||||
+ .commands = {
|
||||
+ .get_brightness = 0x00,
|
||||
+ .set_brightness = 0x01,
|
||||
+
|
||||
+ .get_wireless_button = 0x02,
|
||||
+ .set_wireless_button = 0x03,
|
||||
+
|
||||
+ .get_backlight = 0x04,
|
||||
+ .set_backlight = 0x05,
|
||||
+
|
||||
+ .get_recovery_mode = 0x06,
|
||||
+ .set_recovery_mode = 0x07,
|
||||
+
|
||||
+ .get_performance_level = 0x08,
|
||||
+ .set_performance_level = 0x09,
|
||||
+
|
||||
+ .set_linux = 0x0a,
|
||||
+ },
|
||||
+
|
||||
+ .performance_levels = {
|
||||
+ {
|
||||
+ .name = "silent",
|
||||
+ .value = 0,
|
||||
+ },
|
||||
+ {
|
||||
+ .name = "normal",
|
||||
+ .value = 1,
|
||||
+ },
|
||||
+ { },
|
||||
+ },
|
||||
+ },
|
||||
+ {
|
||||
+ .test_string = "SwSmi@",
|
||||
+
|
||||
+ .main_function = 0x5843,
|
||||
+
|
||||
+ .header_offsets = {
|
||||
+ .port = 0x00,
|
||||
+ .re_mem = 0x04,
|
||||
+ .iface_func = 0x02,
|
||||
+ .en_mem = 0x03,
|
||||
+ .data_offset = 0x05,
|
||||
+ .data_segment = 0x07,
|
||||
+ },
|
||||
+
|
||||
+ .commands = {
|
||||
+ .get_brightness = 0x10,
|
||||
+ .set_brightness = 0x11,
|
||||
+
|
||||
+ .get_wireless_button = 0x12,
|
||||
+ .set_wireless_button = 0x13,
|
||||
+
|
||||
+ .get_backlight = 0x2d,
|
||||
+ .set_backlight = 0x2e,
|
||||
+
|
||||
+ .get_recovery_mode = 0xff,
|
||||
+ .set_recovery_mode = 0xff,
|
||||
+
|
||||
+ .get_performance_level = 0x31,
|
||||
+ .set_performance_level = 0x32,
|
||||
+
|
||||
+ .set_linux = 0xff,
|
||||
+ },
|
||||
+
|
||||
+ .performance_levels = {
|
||||
+ {
|
||||
+ .name = "normal",
|
||||
+ .value = 0,
|
||||
+ },
|
||||
+ {
|
||||
+ .name = "silent",
|
||||
+ .value = 1,
|
||||
+ },
|
||||
+ {
|
||||
+ .name = "overclock",
|
||||
+ .value = 2,
|
||||
+ },
|
||||
+ { },
|
||||
+ },
|
||||
+ },
|
||||
+ { },
|
||||
+};
|
||||
+
|
||||
+static struct sabi_config *sabi_config;
|
||||
+
|
||||
static void __iomem *sabi;
|
||||
static void __iomem *sabi_iface;
|
||||
static void __iomem *f0000_segment;
|
||||
@@ -109,21 +231,21 @@ MODULE_PARM_DESC(debug, "Debug enabled or not");
|
||||
static int sabi_get_command(u8 command, struct sabi_retval *sretval)
|
||||
{
|
||||
int retval = 0;
|
||||
- u16 port = readw(sabi + SABI_HEADER_PORT);
|
||||
+ u16 port = readw(sabi + sabi_config->header_offsets.port);
|
||||
|
||||
mutex_lock(&sabi_mutex);
|
||||
|
||||
/* enable memory to be able to write to it */
|
||||
- outb(readb(sabi + SABI_HEADER_EN_MEM), port);
|
||||
+ outb(readb(sabi + sabi_config->header_offsets.en_mem), port);
|
||||
|
||||
/* write out the command */
|
||||
- writew(MAIN_FUNCTION, sabi_iface + SABI_IFACE_MAIN);
|
||||
+ writew(sabi_config->main_function, sabi_iface + SABI_IFACE_MAIN);
|
||||
writew(command, sabi_iface + SABI_IFACE_SUB);
|
||||
writeb(0, sabi_iface + SABI_IFACE_COMPLETE);
|
||||
- outb(readb(sabi + SABI_HEADER_IFACEFUNC), port);
|
||||
+ outb(readb(sabi + sabi_config->header_offsets.iface_func), port);
|
||||
|
||||
/* write protect memory to make it safe */
|
||||
- outb(readb(sabi + SABI_HEADER_RE_MEM), port);
|
||||
+ outb(readb(sabi + sabi_config->header_offsets.re_mem), port);
|
||||
|
||||
/* see if the command actually succeeded */
|
||||
if (readb(sabi_iface + SABI_IFACE_COMPLETE) == 0xaa &&
|
||||
@@ -156,22 +278,22 @@ exit:
|
||||
static int sabi_set_command(u8 command, u8 data)
|
||||
{
|
||||
int retval = 0;
|
||||
- u16 port = readw(sabi + SABI_HEADER_PORT);
|
||||
+ u16 port = readw(sabi + sabi_config->header_offsets.port);
|
||||
|
||||
mutex_lock(&sabi_mutex);
|
||||
|
||||
/* enable memory to be able to write to it */
|
||||
- outb(readb(sabi + SABI_HEADER_EN_MEM), port);
|
||||
+ outb(readb(sabi + sabi_config->header_offsets.en_mem), port);
|
||||
|
||||
/* write out the command */
|
||||
- writew(MAIN_FUNCTION, sabi_iface + SABI_IFACE_MAIN);
|
||||
+ writew(sabi_config->main_function, sabi_iface + SABI_IFACE_MAIN);
|
||||
writew(command, sabi_iface + SABI_IFACE_SUB);
|
||||
writeb(0, sabi_iface + SABI_IFACE_COMPLETE);
|
||||
writeb(data, sabi_iface + SABI_IFACE_DATA);
|
||||
- outb(readb(sabi + SABI_HEADER_IFACEFUNC), port);
|
||||
+ outb(readb(sabi + sabi_config->header_offsets.iface_func), port);
|
||||
|
||||
/* write protect memory to make it safe */
|
||||
- outb(readb(sabi + SABI_HEADER_RE_MEM), port);
|
||||
+ outb(readb(sabi + sabi_config->header_offsets.re_mem), port);
|
||||
|
||||
/* see if the command actually succeeded */
|
||||
if (readb(sabi_iface + SABI_IFACE_COMPLETE) == 0xaa &&
|
||||
@@ -194,21 +316,21 @@ static void test_backlight(void)
|
||||
{
|
||||
struct sabi_retval sretval;
|
||||
|
||||
- sabi_get_command(GET_BACKLIGHT, &sretval);
|
||||
+ sabi_get_command(sabi_config->commands.get_backlight, &sretval);
|
||||
printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]);
|
||||
|
||||
- sabi_set_command(SET_BACKLIGHT, 0);
|
||||
+ sabi_set_command(sabi_config->commands.set_backlight, 0);
|
||||
printk(KERN_DEBUG "backlight should be off\n");
|
||||
|
||||
- sabi_get_command(GET_BACKLIGHT, &sretval);
|
||||
+ sabi_get_command(sabi_config->commands.get_backlight, &sretval);
|
||||
printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]);
|
||||
|
||||
msleep(1000);
|
||||
|
||||
- sabi_set_command(SET_BACKLIGHT, 1);
|
||||
+ sabi_set_command(sabi_config->commands.set_backlight, 1);
|
||||
printk(KERN_DEBUG "backlight should be on\n");
|
||||
|
||||
- sabi_get_command(GET_BACKLIGHT, &sretval);
|
||||
+ sabi_get_command(sabi_config->commands.get_backlight, &sretval);
|
||||
printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]);
|
||||
}
|
||||
|
||||
@@ -216,21 +338,21 @@ static void test_wireless(void)
|
||||
{
|
||||
struct sabi_retval sretval;
|
||||
|
||||
- sabi_get_command(GET_WIRELESS_BUTTON, &sretval);
|
||||
+ sabi_get_command(sabi_config->commands.get_wireless_button, &sretval);
|
||||
printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]);
|
||||
|
||||
- sabi_set_command(SET_WIRELESS_BUTTON, 0);
|
||||
+ sabi_set_command(sabi_config->commands.set_wireless_button, 0);
|
||||
printk(KERN_DEBUG "wireless led should be off\n");
|
||||
|
||||
- sabi_get_command(GET_WIRELESS_BUTTON, &sretval);
|
||||
+ sabi_get_command(sabi_config->commands.get_wireless_button, &sretval);
|
||||
printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]);
|
||||
|
||||
msleep(1000);
|
||||
|
||||
- sabi_set_command(SET_WIRELESS_BUTTON, 1);
|
||||
+ sabi_set_command(sabi_config->commands.set_wireless_button, 1);
|
||||
printk(KERN_DEBUG "wireless led should be on\n");
|
||||
|
||||
- sabi_get_command(GET_WIRELESS_BUTTON, &sretval);
|
||||
+ sabi_get_command(sabi_config->commands.get_wireless_button, &sretval);
|
||||
printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]);
|
||||
}
|
||||
|
||||
@@ -240,7 +362,8 @@ static u8 read_brightness(void)
|
||||
int user_brightness = 0;
|
||||
int retval;
|
||||
|
||||
- retval = sabi_get_command(GET_BRIGHTNESS, &sretval);
|
||||
+ retval = sabi_get_command(sabi_config->commands.get_brightness,
|
||||
+ &sretval);
|
||||
if (!retval)
|
||||
user_brightness = sretval.retval[0];
|
||||
if (user_brightness != 0)
|
||||
@@ -250,7 +373,8 @@ static u8 read_brightness(void)
|
||||
|
||||
static void set_brightness(u8 user_brightness)
|
||||
{
|
||||
- sabi_set_command(SET_BRIGHTNESS, user_brightness + 1);
|
||||
+ sabi_set_command(sabi_config->commands.set_brightness,
|
||||
+ user_brightness + 1);
|
||||
}
|
||||
|
||||
static int get_brightness(struct backlight_device *bd)
|
||||
@@ -263,9 +387,9 @@ static int update_status(struct backlight_device *bd)
|
||||
set_brightness(bd->props.brightness);
|
||||
|
||||
if (bd->props.power == FB_BLANK_UNBLANK)
|
||||
- sabi_set_command(SET_BACKLIGHT, 1);
|
||||
+ sabi_set_command(sabi_config->commands.set_backlight, 1);
|
||||
else
|
||||
- sabi_set_command(SET_BACKLIGHT, 0);
|
||||
+ sabi_set_command(sabi_config->commands.set_backlight, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -282,9 +406,9 @@ static int rfkill_set(void *data, bool blocked)
|
||||
* blocked == true is off
|
||||
*/
|
||||
if (blocked)
|
||||
- sabi_set_command(SET_WIRELESS_BUTTON, 0);
|
||||
+ sabi_set_command(sabi_config->commands.set_wireless_button, 0);
|
||||
else
|
||||
- sabi_set_command(SET_WIRELESS_BUTTON, 1);
|
||||
+ sabi_set_command(sabi_config->commands.set_wireless_button, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -317,47 +441,49 @@ static void destroy_wireless(void)
|
||||
rfkill_destroy(rfk);
|
||||
}
|
||||
|
||||
-static ssize_t get_silent_state(struct device *dev,
|
||||
- struct device_attribute *attr, char *buf)
|
||||
+static ssize_t get_performance_level(struct device *dev,
|
||||
+ struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct sabi_retval sretval;
|
||||
int retval;
|
||||
+ int i;
|
||||
|
||||
/* Read the state */
|
||||
- retval = sabi_get_command(GET_PERFORMANCE_LEVEL, &sretval);
|
||||
+ retval = sabi_get_command(sabi_config->commands.get_performance_level,
|
||||
+ &sretval);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
/* The logic is backwards, yeah, lots of fun... */
|
||||
- if (sretval.retval[0] == 0)
|
||||
- retval = 1;
|
||||
- else
|
||||
- retval = 0;
|
||||
- return sprintf(buf, "%d\n", retval);
|
||||
+ for (i = 0; sabi_config->performance_levels[i].name; ++i) {
|
||||
+ if (sretval.retval[0] == sabi_config->performance_levels[i].value)
|
||||
+ return sprintf(buf, "%s\n", sabi_config->performance_levels[i].name);
|
||||
+ }
|
||||
+ return sprintf(buf, "%s\n", "unknown");
|
||||
}
|
||||
|
||||
-static ssize_t set_silent_state(struct device *dev,
|
||||
+static ssize_t set_performance_level(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
- char value;
|
||||
-
|
||||
if (count >= 1) {
|
||||
- value = buf[0];
|
||||
- if ((value == '0') || (value == 'n') || (value == 'N')) {
|
||||
- /* Turn speed up */
|
||||
- sabi_set_command(SET_PERFORMANCE_LEVEL, 0x01);
|
||||
- } else if ((value == '1') || (value == 'y') || (value == 'Y')) {
|
||||
- /* Turn speed down */
|
||||
- sabi_set_command(SET_PERFORMANCE_LEVEL, 0x00);
|
||||
- } else {
|
||||
- return -EINVAL;
|
||||
+ int i;
|
||||
+ for (i = 0; sabi_config->performance_levels[i].name; ++i) {
|
||||
+ struct sabi_performance_level *level =
|
||||
+ &sabi_config->performance_levels[i];
|
||||
+ if (!strncasecmp(level->name, buf, strlen(level->name))) {
|
||||
+ sabi_set_command(sabi_config->commands.set_performance_level,
|
||||
+ level->value);
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
+ if (!sabi_config->performance_levels[i].name)
|
||||
+ return -EINVAL;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
-static DEVICE_ATTR(silent, S_IWUSR | S_IRUGO,
|
||||
- get_silent_state, set_silent_state);
|
||||
+static DEVICE_ATTR(performance_level, S_IWUSR | S_IRUGO,
|
||||
+ get_performance_level, set_performance_level);
|
||||
|
||||
|
||||
static int __init dmi_check_cb(const struct dmi_system_id *id)
|
||||
@@ -388,18 +514,113 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = {
|
||||
},
|
||||
.callback = dmi_check_cb,
|
||||
},
|
||||
+ {
|
||||
+ .ident = "X125",
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_SYS_VENDOR,
|
||||
+ "SAMSUNG ELECTRONICS CO., LTD."),
|
||||
+ DMI_MATCH(DMI_PRODUCT_NAME, "X125"),
|
||||
+ DMI_MATCH(DMI_BOARD_NAME, "X125"),
|
||||
+ },
|
||||
+ .callback = dmi_check_cb,
|
||||
+ },
|
||||
+ {
|
||||
+ .ident = "NC10",
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_SYS_VENDOR,
|
||||
+ "SAMSUNG ELECTRONICS CO., LTD."),
|
||||
+ DMI_MATCH(DMI_PRODUCT_NAME, "NC10"),
|
||||
+ DMI_MATCH(DMI_BOARD_NAME, "NC10"),
|
||||
+ },
|
||||
+ .callback = dmi_check_cb,
|
||||
+ },
|
||||
+ {
|
||||
+ .ident = "NP-Q45",
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_SYS_VENDOR,
|
||||
+ "SAMSUNG ELECTRONICS CO., LTD."),
|
||||
+ DMI_MATCH(DMI_PRODUCT_NAME, "SQ45S70S"),
|
||||
+ DMI_MATCH(DMI_BOARD_NAME, "SQ45S70S"),
|
||||
+ },
|
||||
+ .callback = dmi_check_cb,
|
||||
+ },
|
||||
+ {
|
||||
+ .ident = "X360",
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_SYS_VENDOR,
|
||||
+ "SAMSUNG ELECTRONICS CO., LTD."),
|
||||
+ DMI_MATCH(DMI_PRODUCT_NAME, "X360"),
|
||||
+ DMI_MATCH(DMI_BOARD_NAME, "X360"),
|
||||
+ },
|
||||
+ .callback = dmi_check_cb,
|
||||
+ },
|
||||
+ {
|
||||
+ .ident = "R518",
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_SYS_VENDOR,
|
||||
+ "SAMSUNG ELECTRONICS CO., LTD."),
|
||||
+ DMI_MATCH(DMI_PRODUCT_NAME, "R518"),
|
||||
+ DMI_MATCH(DMI_BOARD_NAME, "R518"),
|
||||
+ },
|
||||
+ .callback = dmi_check_cb,
|
||||
+ },
|
||||
+ {
|
||||
+ .ident = "N150/N210/N220",
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_SYS_VENDOR,
|
||||
+ "SAMSUNG ELECTRONICS CO., LTD."),
|
||||
+ DMI_MATCH(DMI_PRODUCT_NAME, "N150/N210/N220"),
|
||||
+ DMI_MATCH(DMI_BOARD_NAME, "N150/N210/N220"),
|
||||
+ },
|
||||
+ .callback = dmi_check_cb,
|
||||
+ },
|
||||
+ {
|
||||
+ .ident = "R530/R730",
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
|
||||
+ DMI_MATCH(DMI_PRODUCT_NAME, "R530/R730"),
|
||||
+ DMI_MATCH(DMI_BOARD_NAME, "R530/R730"),
|
||||
+ },
|
||||
+ .callback = dmi_check_cb,
|
||||
+ },
|
||||
+ {
|
||||
+ .ident = "NF110/NF210/NF310",
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
|
||||
+ DMI_MATCH(DMI_PRODUCT_NAME, "NF110/NF210/NF310"),
|
||||
+ DMI_MATCH(DMI_BOARD_NAME, "NF110/NF210/NF310"),
|
||||
+ },
|
||||
+ .callback = dmi_check_cb,
|
||||
+ },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(dmi, samsung_dmi_table);
|
||||
|
||||
+static int find_signature(void __iomem *memcheck, const char *testStr)
|
||||
+{
|
||||
+ int i = 0;
|
||||
+ int loca;
|
||||
+
|
||||
+ for (loca = 0; loca < 0xffff; loca++) {
|
||||
+ char temp = readb(memcheck + loca);
|
||||
+
|
||||
+ if (temp == testStr[i]) {
|
||||
+ if (i == strlen(testStr)-1)
|
||||
+ break;
|
||||
+ ++i;
|
||||
+ } else {
|
||||
+ i = 0;
|
||||
+ }
|
||||
+ }
|
||||
+ return loca;
|
||||
+}
|
||||
+
|
||||
static int __init samsung_init(void)
|
||||
{
|
||||
struct backlight_properties props;
|
||||
struct sabi_retval sretval;
|
||||
- const char *testStr = "SECLINUX";
|
||||
- void __iomem *memcheck;
|
||||
unsigned int ifaceP;
|
||||
- int pStr;
|
||||
+ int i;
|
||||
int loca;
|
||||
int retval;
|
||||
|
||||
@@ -414,50 +635,44 @@ static int __init samsung_init(void)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
- /* Try to find the signature "SECLINUX" in memory to find the header */
|
||||
- pStr = 0;
|
||||
- memcheck = f0000_segment;
|
||||
- for (loca = 0; loca < 0xffff; loca++) {
|
||||
- char temp = readb(memcheck + loca);
|
||||
-
|
||||
- if (temp == testStr[pStr]) {
|
||||
- if (pStr == strlen(testStr)-1)
|
||||
- break;
|
||||
- ++pStr;
|
||||
- } else {
|
||||
- pStr = 0;
|
||||
- }
|
||||
+ /* Try to find one of the signatures in memory to find the header */
|
||||
+ for (i = 0; sabi_configs[i].test_string != 0; ++i) {
|
||||
+ sabi_config = &sabi_configs[i];
|
||||
+ loca = find_signature(f0000_segment, sabi_config->test_string);
|
||||
+ if (loca != 0xffff)
|
||||
+ break;
|
||||
}
|
||||
+
|
||||
if (loca == 0xffff) {
|
||||
printk(KERN_ERR "This computer does not support SABI\n");
|
||||
goto error_no_signature;
|
||||
- }
|
||||
+ }
|
||||
|
||||
/* point to the SMI port Number */
|
||||
loca += 1;
|
||||
- sabi = (memcheck + loca);
|
||||
+ sabi = (f0000_segment + loca);
|
||||
|
||||
if (debug) {
|
||||
printk(KERN_DEBUG "This computer supports SABI==%x\n",
|
||||
loca + 0xf0000 - 6);
|
||||
printk(KERN_DEBUG "SABI header:\n");
|
||||
printk(KERN_DEBUG " SMI Port Number = 0x%04x\n",
|
||||
- readw(sabi + SABI_HEADER_PORT));
|
||||
+ readw(sabi + sabi_config->header_offsets.port));
|
||||
printk(KERN_DEBUG " SMI Interface Function = 0x%02x\n",
|
||||
- readb(sabi + SABI_HEADER_IFACEFUNC));
|
||||
+ readb(sabi + sabi_config->header_offsets.iface_func));
|
||||
printk(KERN_DEBUG " SMI enable memory buffer = 0x%02x\n",
|
||||
- readb(sabi + SABI_HEADER_EN_MEM));
|
||||
+ readb(sabi + sabi_config->header_offsets.en_mem));
|
||||
printk(KERN_DEBUG " SMI restore memory buffer = 0x%02x\n",
|
||||
- readb(sabi + SABI_HEADER_RE_MEM));
|
||||
+ readb(sabi + sabi_config->header_offsets.re_mem));
|
||||
printk(KERN_DEBUG " SABI data offset = 0x%04x\n",
|
||||
- readw(sabi + SABI_HEADER_DATA_OFFSET));
|
||||
+ readw(sabi + sabi_config->header_offsets.data_offset));
|
||||
printk(KERN_DEBUG " SABI data segment = 0x%04x\n",
|
||||
- readw(sabi + SABI_HEADER_DATA_SEGMENT));
|
||||
+ readw(sabi + sabi_config->header_offsets.data_segment));
|
||||
}
|
||||
|
||||
/* Get a pointer to the SABI Interface */
|
||||
- ifaceP = (readw(sabi + SABI_HEADER_DATA_SEGMENT) & 0x0ffff) << 4;
|
||||
- ifaceP += readw(sabi + SABI_HEADER_DATA_OFFSET) & 0x0ffff;
|
||||
+ ifaceP = (readw(sabi + sabi_config->header_offsets.data_segment) & 0x0ffff) << 4;
|
||||
+ ifaceP += readw(sabi + sabi_config->header_offsets.data_offset) & 0x0ffff;
|
||||
sabi_iface = ioremap(ifaceP, 16);
|
||||
if (!sabi_iface) {
|
||||
printk(KERN_ERR "Can't remap %x\n", ifaceP);
|
||||
@@ -470,15 +685,19 @@ static int __init samsung_init(void)
|
||||
test_backlight();
|
||||
test_wireless();
|
||||
|
||||
- retval = sabi_get_command(GET_BRIGHTNESS, &sretval);
|
||||
+ retval = sabi_get_command(sabi_config->commands.get_brightness,
|
||||
+ &sretval);
|
||||
printk(KERN_DEBUG "brightness = 0x%02x\n", sretval.retval[0]);
|
||||
}
|
||||
|
||||
/* Turn on "Linux" mode in the BIOS */
|
||||
- retval = sabi_set_command(SET_LINUX, 0x81);
|
||||
- if (retval) {
|
||||
- printk(KERN_ERR KBUILD_MODNAME ": Linux mode was not set!\n");
|
||||
- goto error_no_platform;
|
||||
+ if (sabi_config->commands.set_linux != 0xff) {
|
||||
+ retval = sabi_set_command(sabi_config->commands.set_linux,
|
||||
+ 0x81);
|
||||
+ if (retval) {
|
||||
+ printk(KERN_ERR KBUILD_MODNAME ": Linux mode was not set!\n");
|
||||
+ goto error_no_platform;
|
||||
+ }
|
||||
}
|
||||
|
||||
/* knock up a platform device to hang stuff off of */
|
||||
@@ -503,7 +722,7 @@ static int __init samsung_init(void)
|
||||
if (retval)
|
||||
goto error_no_rfk;
|
||||
|
||||
- retval = device_create_file(&sdev->dev, &dev_attr_silent);
|
||||
+ retval = device_create_file(&sdev->dev, &dev_attr_performance_level);
|
||||
if (retval)
|
||||
goto error_file_create;
|
||||
|
||||
@@ -530,9 +749,10 @@ error_no_signature:
|
||||
static void __exit samsung_exit(void)
|
||||
{
|
||||
/* Turn off "Linux" mode in the BIOS */
|
||||
- sabi_set_command(SET_LINUX, 0x80);
|
||||
+ if (sabi_config->commands.set_linux != 0xff)
|
||||
+ sabi_set_command(sabi_config->commands.set_linux, 0x80);
|
||||
|
||||
- device_remove_file(&sdev->dev, &dev_attr_silent);
|
||||
+ device_remove_file(&sdev->dev, &dev_attr_performance_level);
|
||||
backlight_device_unregister(backlight_device);
|
||||
destroy_wireless();
|
||||
iounmap(sabi_iface);
|
@ -1,40 +0,0 @@
|
||||
From: Thomas Renninger <trenn@suse.de>
|
||||
Subject: acpi-cpufreq: Fix CPU_ANY CPUFREQ_{PRE,POST}CHANGE notification
|
||||
Patch-Mainline: submitted - please revert after 2.6.35
|
||||
References: none
|
||||
|
||||
Signed-off-by: Thomas Renninger <trenn@suse.de>
|
||||
CC: venki@google.com
|
||||
CC: davej@redhat.com
|
||||
CC: arjan@infradead.org
|
||||
CC: davej@redhat.com
|
||||
CC: linux-kernel@vger.kernel.org
|
||||
---
|
||||
arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c | 4 ++--
|
||||
1 files changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
|
||||
index 4591680..c6de3a9 100644
|
||||
--- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
|
||||
+++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
|
||||
@@ -391,7 +391,7 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
|
||||
|
||||
freqs.old = perf->states[perf->state].core_frequency * 1000;
|
||||
freqs.new = data->freq_table[next_state].frequency;
|
||||
- for_each_cpu(i, cmd.mask) {
|
||||
+ for_each_cpu(i, policy->cpus) {
|
||||
freqs.cpu = i;
|
||||
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
|
||||
}
|
||||
@@ -407,7 +407,7 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
|
||||
}
|
||||
}
|
||||
|
||||
- for_each_cpu(i, cmd.mask) {
|
||||
+ for_each_cpu(i, policy->cpus) {
|
||||
freqs.cpu = i;
|
||||
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||
}
|
||||
--
|
||||
1.6.3
|
||||
|
@ -0,0 +1,78 @@
|
||||
From: Vasiliy Kulikov <segooon@gmail.com>
|
||||
Subject: acpi: ec_sys: access user space with get_user()/put_user()
|
||||
Patch-Mainline: hopefully still 2.6.36
|
||||
References: none
|
||||
|
||||
User space pointer may not be dereferenced. Use get_user()/put_user()
|
||||
instead and check their return codes.
|
||||
|
||||
Signed-off-by: Vasiliy Kulikov <segooon@gmail.com>
|
||||
Signed-off-by: Thomas Renninger <trenn@suse.de>
|
||||
---
|
||||
Compile tested.
|
||||
|
||||
drivers/acpi/ec_sys.c | 18 ++++++++++++++----
|
||||
1 files changed, 14 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/drivers/acpi/ec_sys.c b/drivers/acpi/ec_sys.c
|
||||
index 0e869b3..cc007d8 100644
|
||||
--- a/drivers/acpi/ec_sys.c
|
||||
+++ b/drivers/acpi/ec_sys.c
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/debugfs.h>
|
||||
+#include <linux/uaccess.h>
|
||||
#include "internal.h"
|
||||
|
||||
MODULE_AUTHOR("Thomas Renninger <trenn@suse.de>");
|
||||
@@ -43,7 +44,6 @@ static ssize_t acpi_ec_read_io(struct file *f, char __user *buf,
|
||||
* struct acpi_ec *ec = ((struct seq_file *)f->private_data)->private;
|
||||
*/
|
||||
unsigned int size = EC_SPACE_SIZE;
|
||||
- u8 *data = (u8 *) buf;
|
||||
loff_t init_off = *off;
|
||||
int err = 0;
|
||||
|
||||
@@ -56,9 +56,15 @@ static ssize_t acpi_ec_read_io(struct file *f, char __user *buf,
|
||||
size = count;
|
||||
|
||||
while (size) {
|
||||
- err = ec_read(*off, &data[*off - init_off]);
|
||||
+ u8 byte_read;
|
||||
+ err = ec_read(*off, &byte_read);
|
||||
if (err)
|
||||
return err;
|
||||
+ if (put_user(byte_read, buf + *off - init_off)) {
|
||||
+ if (*off - init_off)
|
||||
+ return *off - init_off; /* partial read */
|
||||
+ return -EFAULT;
|
||||
+ }
|
||||
*off += 1;
|
||||
size--;
|
||||
}
|
||||
@@ -74,7 +80,6 @@ static ssize_t acpi_ec_write_io(struct file *f, const char __user *buf,
|
||||
|
||||
unsigned int size = count;
|
||||
loff_t init_off = *off;
|
||||
- u8 *data = (u8 *) buf;
|
||||
int err = 0;
|
||||
|
||||
if (*off >= EC_SPACE_SIZE)
|
||||
@@ -85,7 +90,12 @@ static ssize_t acpi_ec_write_io(struct file *f, const char __user *buf,
|
||||
}
|
||||
|
||||
while (size) {
|
||||
- u8 byte_write = data[*off - init_off];
|
||||
+ u8 byte_write;
|
||||
+ if (get_user(byte_write, buf + *off - init_off)) {
|
||||
+ if (*off - init_off)
|
||||
+ return *off - init_off; /* partial write */
|
||||
+ return -EFAULT;
|
||||
+ }
|
||||
err = ec_write(*off, byte_write);
|
||||
if (err)
|
||||
return err;
|
||||
--
|
||||
1.7.0.4
|
||||
|
@ -1,42 +0,0 @@
|
||||
From: Thomas Renninger <trenn@suse.de>
|
||||
Subject: Do not try to set up acpi processor stuff on cores exceeding maxcpus=
|
||||
References: bnc#601520
|
||||
Patch-Mainline: Not yet
|
||||
|
||||
Signed-off-by: Thomas Renninger <trenn@suse.de>
|
||||
|
||||
---
|
||||
drivers/acpi/processor_driver.c | 5 +++++
|
||||
init/main.c | 3 ++-
|
||||
2 files changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
Index: linux-2.6.34-master/init/main.c
|
||||
===================================================================
|
||||
--- linux-2.6.34-master.orig/init/main.c
|
||||
+++ linux-2.6.34-master/init/main.c
|
||||
@@ -124,7 +124,8 @@ static char *ramdisk_execute_command;
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/* Setup configured maximum number of CPUs to activate */
|
||||
-unsigned int __initdata setup_max_cpus = NR_CPUS;
|
||||
+unsigned int setup_max_cpus = NR_CPUS;
|
||||
+EXPORT_SYMBOL(setup_max_cpus);
|
||||
|
||||
/*
|
||||
* Setup routine for controlling SMP activation
|
||||
Index: linux-2.6.34-master/drivers/acpi/processor_driver.c
|
||||
===================================================================
|
||||
--- linux-2.6.34-master.orig/drivers/acpi/processor_driver.c
|
||||
+++ linux-2.6.34-master/drivers/acpi/processor_driver.c
|
||||
@@ -581,6 +581,11 @@ static int __cpuinit acpi_processor_add(
|
||||
return 0;
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_SMP
|
||||
+ if (pr->id >= setup_max_cpus && pr->id != 0)
|
||||
+ return 0;
|
||||
+#endif
|
||||
+
|
||||
BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0));
|
||||
|
||||
/*
|
@ -0,0 +1,61 @@
|
||||
From fd0e435b0fe85622f167b84432552885a4856ac8 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Oester <kernel@linuxace.com>
|
||||
Date: Mon, 14 Mar 2011 06:22:04 +0000
|
||||
Subject: [PATCH] bonding: Incorrect TX queue offset
|
||||
Git-commit: fd0e435b0fe85622f167b84432552885a4856ac8
|
||||
Patch-mainline: v2.6.39-rc1~468^2~15
|
||||
Reference: bnc#687116, CVE-2011-1581
|
||||
|
||||
When packets come in from a device with >= 16 receive queues
|
||||
headed out a bonding interface, syslog gets filled with this:
|
||||
|
||||
kernel: bond0 selects TX queue 16, but real number of TX queues is 16
|
||||
|
||||
because queue_mapping is offset by 1. Adjust return value
|
||||
to account for the offset.
|
||||
|
||||
This is a revision of my earlier patch (which did not use the
|
||||
skb_rx_queue_* helpers - thanks to Ben for the suggestion).
|
||||
Andy submitted a similar patch which emits a pr_warning on
|
||||
invalid queue selection, but I believe the log spew is
|
||||
not useful. We can revisit that question in the future,
|
||||
but in the interim I believe fixing the core problem is
|
||||
worthwhile.
|
||||
|
||||
Signed-off-by: Phil Oester <kernel@linuxace.com>
|
||||
Signed-off-by: Andy Gospodarek <andy@greyhouse.net>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
Signed-off-by: Brandon Philips <bphilips@suse.de>
|
||||
|
||||
---
|
||||
drivers/net/bonding/bond_main.c | 11 +++++++++--
|
||||
1 files changed, 9 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
|
||||
index 3ad4f50..a93d941 100644
|
||||
--- a/drivers/net/bonding/bond_main.c
|
||||
+++ b/drivers/net/bonding/bond_main.c
|
||||
@@ -4341,11 +4341,18 @@ static u16 bond_select_queue(struct net_device *dev, struct sk_buff *skb)
|
||||
{
|
||||
/*
|
||||
* This helper function exists to help dev_pick_tx get the correct
|
||||
- * destination queue. Using a helper function skips the a call to
|
||||
+ * destination queue. Using a helper function skips a call to
|
||||
* skb_tx_hash and will put the skbs in the queue we expect on their
|
||||
* way down to the bonding driver.
|
||||
*/
|
||||
- return skb->queue_mapping;
|
||||
+ u16 txq = skb_rx_queue_recorded(skb) ? skb_get_rx_queue(skb) : 0;
|
||||
+
|
||||
+ if (unlikely(txq >= dev->real_num_tx_queues)) {
|
||||
+ do
|
||||
+ txq -= dev->real_num_tx_queues;
|
||||
+ while (txq >= dev->real_num_tx_queues);
|
||||
+ }
|
||||
+ return txq;
|
||||
}
|
||||
|
||||
static netdev_tx_t bond_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
--
|
||||
1.7.3.4
|
||||
|
@ -0,0 +1,74 @@
|
||||
From 468c3f924f043cad7a04f4f4d5224a2c9bc886c1 Mon Sep 17 00:00:00 2001
|
||||
From: Jiri Slaby <jslaby@suse.cz>
|
||||
Date: Sun, 13 Mar 2011 06:54:31 +0000
|
||||
Subject: NET: cdc-phonet, handle empty phonet header
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Git-commit: 468c3f924f043cad7a04f4f4d5224a2c9bc886c1
|
||||
Patch-mainline: yes
|
||||
References: bnc#673992
|
||||
|
||||
Currently, for N 5800 XM I get:
|
||||
cdc_phonet: probe of 1-6:1.10 failed with error -22
|
||||
|
||||
It's because phonet_header is empty. Extra altsetting looks like
|
||||
there:
|
||||
E 05 24 00 01 10 03 24 ab 05 24 06 0a 0b 04 24 fd .$....$..$....$.
|
||||
E 00 .
|
||||
|
||||
I don't see the header used anywhere so just check if the phonet
|
||||
descriptor is there, not the structure itself.
|
||||
|
||||
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
|
||||
Cc: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
|
||||
Cc: David S. Miller <davem@davemloft.net>
|
||||
Acked-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/usb/cdc-phonet.c | 9 +++------
|
||||
1 files changed, 3 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/usb/cdc-phonet.c b/drivers/net/usb/cdc-phonet.c
|
||||
index 4cf4e36..f967913 100644
|
||||
--- a/drivers/net/usb/cdc-phonet.c
|
||||
+++ b/drivers/net/usb/cdc-phonet.c
|
||||
@@ -328,13 +328,13 @@ int usbpn_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
||||
{
|
||||
static const char ifname[] = "usbpn%d";
|
||||
const struct usb_cdc_union_desc *union_header = NULL;
|
||||
- const struct usb_cdc_header_desc *phonet_header = NULL;
|
||||
const struct usb_host_interface *data_desc;
|
||||
struct usb_interface *data_intf;
|
||||
struct usb_device *usbdev = interface_to_usbdev(intf);
|
||||
struct net_device *dev;
|
||||
struct usbpn_dev *pnd;
|
||||
u8 *data;
|
||||
+ int phonet = 0;
|
||||
int len, err;
|
||||
|
||||
data = intf->altsetting->extra;
|
||||
@@ -355,10 +355,7 @@ int usbpn_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
||||
(struct usb_cdc_union_desc *)data;
|
||||
break;
|
||||
case 0xAB:
|
||||
- if (phonet_header || dlen < 5)
|
||||
- break;
|
||||
- phonet_header =
|
||||
- (struct usb_cdc_header_desc *)data;
|
||||
+ phonet = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -366,7 +363,7 @@ int usbpn_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
||||
len -= dlen;
|
||||
}
|
||||
|
||||
- if (!union_header || !phonet_header)
|
||||
+ if (!union_header || !phonet)
|
||||
return -EINVAL;
|
||||
|
||||
data_intf = usb_ifnum_to_if(usbdev, union_header->bSlaveInterface0);
|
||||
--
|
||||
1.7.4.1
|
||||
|
@ -1,136 +0,0 @@
|
||||
From: Steve French <sfrench@us.ibm.com>
|
||||
Subject: [CIFS] Allow null nd (as nfs server uses) on create
|
||||
References: bnc#593940
|
||||
Patch-mainline: queued (in cifs devel git)
|
||||
|
||||
commit fa588e0c57048b3d4bfcd772d80dc0615f83fd35 in cifs-2.6.git
|
||||
|
||||
While creating a file on a server which supports unix extensions
|
||||
such as Samba, if a file is being created which does not supply
|
||||
nameidata (i.e. nd is null), cifs client can oops when calling
|
||||
cifs_posix_open.
|
||||
|
||||
Signed-off-by: Shirish Pargaonkar <shirishp@us.ibm.com>
|
||||
Signed-off-by: Steve French <sfrench@us.ibm.com>
|
||||
Acked-by: Suresh Jayaraman <sjayaraman@suse.de>
|
||||
---
|
||||
fs/cifs/cifsproto.h | 6 ++++--
|
||||
fs/cifs/dir.c | 20 ++++++++++++--------
|
||||
fs/cifs/file.c | 11 +++++++----
|
||||
3 files changed, 23 insertions(+), 14 deletions(-)
|
||||
|
||||
Index: linux-2.6.33-master/fs/cifs/cifsproto.h
|
||||
===================================================================
|
||||
--- linux-2.6.33-master.orig/fs/cifs/cifsproto.h
|
||||
+++ linux-2.6.33-master/fs/cifs/cifsproto.h
|
||||
@@ -95,8 +95,10 @@ extern struct cifsFileInfo *cifs_new_fil
|
||||
__u16 fileHandle, struct file *file,
|
||||
struct vfsmount *mnt, unsigned int oflags);
|
||||
extern int cifs_posix_open(char *full_path, struct inode **pinode,
|
||||
- struct vfsmount *mnt, int mode, int oflags,
|
||||
- __u32 *poplock, __u16 *pnetfid, int xid);
|
||||
+ struct vfsmount *mnt,
|
||||
+ struct super_block *sb,
|
||||
+ int mode, int oflags,
|
||||
+ __u32 *poplock, __u16 *pnetfid, int xid);
|
||||
extern void cifs_unix_basic_to_fattr(struct cifs_fattr *fattr,
|
||||
FILE_UNIX_BASIC_INFO *info,
|
||||
struct cifs_sb_info *cifs_sb);
|
||||
Index: linux-2.6.33-master/fs/cifs/dir.c
|
||||
===================================================================
|
||||
--- linux-2.6.33-master.orig/fs/cifs/dir.c
|
||||
+++ linux-2.6.33-master/fs/cifs/dir.c
|
||||
@@ -183,13 +183,14 @@ cifs_new_fileinfo(struct inode *newinode
|
||||
}
|
||||
|
||||
int cifs_posix_open(char *full_path, struct inode **pinode,
|
||||
- struct vfsmount *mnt, int mode, int oflags,
|
||||
- __u32 *poplock, __u16 *pnetfid, int xid)
|
||||
+ struct vfsmount *mnt, struct super_block *sb,
|
||||
+ int mode, int oflags,
|
||||
+ __u32 *poplock, __u16 *pnetfid, int xid)
|
||||
{
|
||||
int rc;
|
||||
FILE_UNIX_BASIC_INFO *presp_data;
|
||||
__u32 posix_flags = 0;
|
||||
- struct cifs_sb_info *cifs_sb = CIFS_SB(mnt->mnt_sb);
|
||||
+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
|
||||
struct cifs_fattr fattr;
|
||||
|
||||
cFYI(1, ("posix open %s", full_path));
|
||||
@@ -242,7 +243,7 @@ int cifs_posix_open(char *full_path, str
|
||||
|
||||
/* get new inode and set it up */
|
||||
if (*pinode == NULL) {
|
||||
- *pinode = cifs_iget(mnt->mnt_sb, &fattr);
|
||||
+ *pinode = cifs_iget(sb, &fattr);
|
||||
if (!*pinode) {
|
||||
rc = -ENOMEM;
|
||||
goto posix_open_ret;
|
||||
@@ -251,7 +252,8 @@ int cifs_posix_open(char *full_path, str
|
||||
cifs_fattr_to_inode(*pinode, &fattr);
|
||||
}
|
||||
|
||||
- cifs_new_fileinfo(*pinode, *pnetfid, NULL, mnt, oflags);
|
||||
+ if (mnt)
|
||||
+ cifs_new_fileinfo(*pinode, *pnetfid, NULL, mnt, oflags);
|
||||
|
||||
posix_open_ret:
|
||||
kfree(presp_data);
|
||||
@@ -315,13 +317,14 @@ cifs_create(struct inode *inode, struct
|
||||
if (nd && (nd->flags & LOOKUP_OPEN))
|
||||
oflags = nd->intent.open.flags;
|
||||
else
|
||||
- oflags = FMODE_READ;
|
||||
+ oflags = FMODE_READ | SMB_O_CREAT;
|
||||
|
||||
if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
|
||||
(CIFS_UNIX_POSIX_PATH_OPS_CAP &
|
||||
le64_to_cpu(tcon->fsUnixInfo.Capability))) {
|
||||
- rc = cifs_posix_open(full_path, &newinode, nd->path.mnt,
|
||||
- mode, oflags, &oplock, &fileHandle, xid);
|
||||
+ rc = cifs_posix_open(full_path, &newinode,
|
||||
+ nd ? nd->path.mnt : NULL,
|
||||
+ inode->i_sb, mode, oflags, &oplock, &fileHandle, xid);
|
||||
/* EIO could indicate that (posix open) operation is not
|
||||
supported, despite what server claimed in capability
|
||||
negotation. EREMOTE indicates DFS junction, which is not
|
||||
@@ -678,6 +681,7 @@ cifs_lookup(struct inode *parent_dir_ino
|
||||
(nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open &&
|
||||
(nd->intent.open.flags & O_CREAT)) {
|
||||
rc = cifs_posix_open(full_path, &newInode, nd->path.mnt,
|
||||
+ parent_dir_inode->i_sb,
|
||||
nd->intent.open.create_mode,
|
||||
nd->intent.open.flags, &oplock,
|
||||
&fileHandle, xid);
|
||||
Index: linux-2.6.33-master/fs/cifs/file.c
|
||||
===================================================================
|
||||
--- linux-2.6.33-master.orig/fs/cifs/file.c
|
||||
+++ linux-2.6.33-master/fs/cifs/file.c
|
||||
@@ -298,10 +298,12 @@ int cifs_open(struct inode *inode, struc
|
||||
(CIFS_UNIX_POSIX_PATH_OPS_CAP &
|
||||
le64_to_cpu(tcon->fsUnixInfo.Capability))) {
|
||||
int oflags = (int) cifs_posix_convert_flags(file->f_flags);
|
||||
+ oflags |= SMB_O_CREAT;
|
||||
/* can not refresh inode info since size could be stale */
|
||||
rc = cifs_posix_open(full_path, &inode, file->f_path.mnt,
|
||||
- cifs_sb->mnt_file_mode /* ignored */,
|
||||
- oflags, &oplock, &netfid, xid);
|
||||
+ inode->i_sb,
|
||||
+ cifs_sb->mnt_file_mode /* ignored */,
|
||||
+ oflags, &oplock, &netfid, xid);
|
||||
if (rc == 0) {
|
||||
cFYI(1, ("posix open succeeded"));
|
||||
/* no need for special case handling of setting mode
|
||||
@@ -513,8 +515,9 @@ reopen_error_exit:
|
||||
int oflags = (int) cifs_posix_convert_flags(file->f_flags);
|
||||
/* can not refresh inode info since size could be stale */
|
||||
rc = cifs_posix_open(full_path, NULL, file->f_path.mnt,
|
||||
- cifs_sb->mnt_file_mode /* ignored */,
|
||||
- oflags, &oplock, &netfid, xid);
|
||||
+ inode->i_sb,
|
||||
+ cifs_sb->mnt_file_mode /* ignored */,
|
||||
+ oflags, &oplock, &netfid, xid);
|
||||
if (rc == 0) {
|
||||
cFYI(1, ("posix reopen succeeded"));
|
||||
goto reopen_success;
|
@ -1,175 +0,0 @@
|
||||
From: H. Peter Anvin <hpa@linux.intel.com>
|
||||
Date: Tue, 7 Sep 2010 23:16:18 +0000 (-0700)
|
||||
Subject: compat: Make compat_alloc_user_space() incorporate the access_ok()
|
||||
Git-commit: c41d68a513c71e35a14f66d71782d27a79a81ea6
|
||||
References: CVE-2010-3081 bnc#639709
|
||||
Patch-mainline: 2.6.36
|
||||
Introduced-by: Prior to 2.6.5
|
||||
|
||||
compat: Make compat_alloc_user_space() incorporate the access_ok()
|
||||
|
||||
compat_alloc_user_space() expects the caller to independently call
|
||||
access_ok() to verify the returned area. A missing call could
|
||||
introduce problems on some architectures.
|
||||
|
||||
This patch incorporates the access_ok() check into
|
||||
compat_alloc_user_space() and also adds a sanity check on the length.
|
||||
The existing compat_alloc_user_space() implementations are renamed
|
||||
arch_compat_alloc_user_space() and are used as part of the
|
||||
implementation of the new global function.
|
||||
|
||||
This patch assumes NULL will cause __get_user()/__put_user() to either
|
||||
fail or access userspace on all architectures. This should be
|
||||
followed by checking the return value of compat_access_user_space()
|
||||
for NULL in the callers, at which time the access_ok() in the callers
|
||||
can also be removed.
|
||||
|
||||
Reported-by: Ben Hawkes <hawkes@sota.gen.nz>
|
||||
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
|
||||
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
|
||||
Acked-by: Chris Metcalf <cmetcalf@tilera.com>
|
||||
Acked-by: David S. Miller <davem@davemloft.net>
|
||||
Acked-by: Ingo Molnar <mingo@elte.hu>
|
||||
Acked-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
Acked-by: Tony Luck <tony.luck@intel.com>
|
||||
Cc: Andrew Morton <akpm@linux-foundation.org>
|
||||
Cc: Arnd Bergmann <arnd@arndb.de>
|
||||
Cc: Fenghua Yu <fenghua.yu@intel.com>
|
||||
Cc: H. Peter Anvin <hpa@zytor.com>
|
||||
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
|
||||
Cc: Helge Deller <deller@gmx.de>
|
||||
Cc: James Bottomley <jejb@parisc-linux.org>
|
||||
Cc: Kyle McMartin <kyle@mcmartin.ca>
|
||||
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
|
||||
Cc: Paul Mackerras <paulus@samba.org>
|
||||
Cc: Ralf Baechle <ralf@linux-mips.org>
|
||||
Cc: <stable@kernel.org>
|
||||
Acked-by: Jeff Mahoney <jeffm@suse.com>
|
||||
---
|
||||
|
||||
arch/ia64/include/asm/compat.h | 2 +-
|
||||
arch/mips/include/asm/compat.h | 2 +-
|
||||
arch/parisc/include/asm/compat.h | 2 +-
|
||||
arch/powerpc/include/asm/compat.h | 2 +-
|
||||
arch/s390/include/asm/compat.h | 2 +-
|
||||
arch/sparc/include/asm/compat.h | 2 +-
|
||||
arch/x86/include/asm/compat.h | 2 +-
|
||||
include/linux/compat.h | 3 +++
|
||||
kernel/compat.c | 21 +++++++++++++++++++++
|
||||
9 files changed, 31 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/arch/ia64/include/asm/compat.h
|
||||
+++ b/arch/ia64/include/asm/compat.h
|
||||
@@ -199,7 +199,7 @@ ptr_to_compat(void __user *uptr)
|
||||
}
|
||||
|
||||
static __inline__ void __user *
|
||||
-compat_alloc_user_space (long len)
|
||||
+arch_compat_alloc_user_space (long len)
|
||||
{
|
||||
struct pt_regs *regs = task_pt_regs(current);
|
||||
return (void __user *) (((regs->r12 & 0xffffffff) & -16) - len);
|
||||
--- a/arch/mips/include/asm/compat.h
|
||||
+++ b/arch/mips/include/asm/compat.h
|
||||
@@ -145,7 +145,7 @@ static inline compat_uptr_t ptr_to_compa
|
||||
return (u32)(unsigned long)uptr;
|
||||
}
|
||||
|
||||
-static inline void __user *compat_alloc_user_space(long len)
|
||||
+static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = (struct pt_regs *)
|
||||
((unsigned long) current_thread_info() + THREAD_SIZE - 32) - 1;
|
||||
--- a/arch/parisc/include/asm/compat.h
|
||||
+++ b/arch/parisc/include/asm/compat.h
|
||||
@@ -147,7 +147,7 @@ static inline compat_uptr_t ptr_to_compa
|
||||
return (u32)(unsigned long)uptr;
|
||||
}
|
||||
|
||||
-static __inline__ void __user *compat_alloc_user_space(long len)
|
||||
+static __inline__ void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = ¤t->thread.regs;
|
||||
return (void __user *)regs->gr[30];
|
||||
--- a/arch/powerpc/include/asm/compat.h
|
||||
+++ b/arch/powerpc/include/asm/compat.h
|
||||
@@ -134,7 +134,7 @@ static inline compat_uptr_t ptr_to_compa
|
||||
return (u32)(unsigned long)uptr;
|
||||
}
|
||||
|
||||
-static inline void __user *compat_alloc_user_space(long len)
|
||||
+static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = current->thread.regs;
|
||||
unsigned long usp = regs->gpr[1];
|
||||
--- a/arch/s390/include/asm/compat.h
|
||||
+++ b/arch/s390/include/asm/compat.h
|
||||
@@ -181,7 +181,7 @@ static inline int is_compat_task(void)
|
||||
|
||||
#endif
|
||||
|
||||
-static inline void __user *compat_alloc_user_space(long len)
|
||||
+static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
unsigned long stack;
|
||||
|
||||
--- a/arch/sparc/include/asm/compat.h
|
||||
+++ b/arch/sparc/include/asm/compat.h
|
||||
@@ -167,7 +167,7 @@ static inline compat_uptr_t ptr_to_compa
|
||||
return (u32)(unsigned long)uptr;
|
||||
}
|
||||
|
||||
-static inline void __user *compat_alloc_user_space(long len)
|
||||
+static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = current_thread_info()->kregs;
|
||||
unsigned long usp = regs->u_regs[UREG_I6];
|
||||
--- a/arch/x86/include/asm/compat.h
|
||||
+++ b/arch/x86/include/asm/compat.h
|
||||
@@ -205,7 +205,7 @@ static inline compat_uptr_t ptr_to_compa
|
||||
return (u32)(unsigned long)uptr;
|
||||
}
|
||||
|
||||
-static inline void __user *compat_alloc_user_space(long len)
|
||||
+static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = task_pt_regs(current);
|
||||
return (void __user *)regs->sp - len;
|
||||
--- a/include/linux/compat.h
|
||||
+++ b/include/linux/compat.h
|
||||
@@ -360,5 +360,8 @@ extern ssize_t compat_rw_copy_check_uvec
|
||||
const struct compat_iovec __user *uvector, unsigned long nr_segs,
|
||||
unsigned long fast_segs, struct iovec *fast_pointer,
|
||||
struct iovec **ret_pointer);
|
||||
+
|
||||
+extern void __user *compat_alloc_user_space(unsigned long len);
|
||||
+
|
||||
#endif /* CONFIG_COMPAT */
|
||||
#endif /* _LINUX_COMPAT_H */
|
||||
--- a/kernel/compat.c
|
||||
+++ b/kernel/compat.c
|
||||
@@ -1137,3 +1137,24 @@ compat_sys_sysinfo(struct compat_sysinfo
|
||||
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
+/*
|
||||
+ * Allocate user-space memory for the duration of a single system call,
|
||||
+ * in order to marshall parameters inside a compat thunk.
|
||||
+ */
|
||||
+void __user *compat_alloc_user_space(unsigned long len)
|
||||
+{
|
||||
+ void __user *ptr;
|
||||
+
|
||||
+ /* If len would occupy more than half of the entire compat space... */
|
||||
+ if (unlikely(len > (((compat_uptr_t)~0) >> 1)))
|
||||
+ return NULL;
|
||||
+
|
||||
+ ptr = arch_compat_alloc_user_space(len);
|
||||
+
|
||||
+ if (unlikely(!access_ok(VERIFY_WRITE, ptr, len)))
|
||||
+ return NULL;
|
||||
+
|
||||
+ return ptr;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(compat_alloc_user_space);
|
@ -1,25 +0,0 @@
|
||||
From: Jeff Mahoney <jeffm@suse.com>
|
||||
Subject: dmar: Fix oops with no DMAR table
|
||||
References: bnc#548108
|
||||
Patch-mainline: submitted 17 Mar 2010
|
||||
|
||||
On systems without a DMAR table and with DMAR enabled, we will oops
|
||||
in dmar_ir_supported. This patch makes sure we actually have a DMAR
|
||||
table before checking it.
|
||||
|
||||
|
||||
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
|
||||
---
|
||||
|
||||
drivers/pci/dmar.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/pci/dmar.c
|
||||
+++ b/drivers/pci/dmar.c
|
||||
@@ -1460,5 +1460,5 @@ int __init dmar_ir_support(void)
|
||||
{
|
||||
struct acpi_table_dmar *dmar;
|
||||
dmar = (struct acpi_table_dmar *)dmar_tbl;
|
||||
- return dmar->flags & 0x1;
|
||||
+ return dmar && dmar->flags & 0x1;
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
From: Roland McGrath <roland@redhat.com>
|
||||
Date: Wed, 8 Sep 2010 02:36:28 +0000 (-0700)
|
||||
Subject: execve: improve interactivity with large arguments
|
||||
Git-commit: 7993bc1f4663c0db67bb8f0d98e6678145b387cd
|
||||
Patch-mainline: 2.6.36-rc4
|
||||
References: bnc#635425
|
||||
Introduced-by: 2.6.23
|
||||
|
||||
execve: improve interactivity with large arguments
|
||||
|
||||
This adds a preemption point during the copying of the argument and
|
||||
environment strings for execve, in copy_strings(). There is already
|
||||
a preemption point in the count() loop, so this doesn't add any new
|
||||
points in the abstract sense.
|
||||
|
||||
When the total argument+environment strings are very large, the time
|
||||
spent copying them can be much more than a normal user time slice.
|
||||
So this change improves the interactivity of the rest of the system
|
||||
when one process is doing an execve with very large arguments.
|
||||
|
||||
Signed-off-by: Roland McGrath <roland@redhat.com>
|
||||
Reviewed-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
|
||||
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
Acked-by: Jeff Mahoney <jeffm@suse.com>
|
||||
---
|
||||
|
||||
fs/exec.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/fs/exec.c b/fs/exec.c
|
||||
index 1b63237..6f2d777 100644
|
||||
--- a/fs/exec.c
|
||||
+++ b/fs/exec.c
|
||||
@@ -419,6 +419,8 @@ static int copy_strings(int argc, const char __user *const __user *argv,
|
||||
while (len > 0) {
|
||||
int offset, bytes_to_copy;
|
||||
|
||||
+ cond_resched();
|
||||
+
|
||||
offset = pos % PAGE_SIZE;
|
||||
if (offset == 0)
|
||||
offset = PAGE_SIZE;
|
@ -1,57 +0,0 @@
|
||||
From: Roland McGrath <roland@redhat.com>
|
||||
Date: Wed, 8 Sep 2010 02:37:06 +0000 (-0700)
|
||||
Subject: execve: make responsive to SIGKILL with large arguments
|
||||
Git-commit: 9aea5a65aa7a1af9a4236dfaeb0088f1624f9919
|
||||
Patch-mainline: 2.6.36-rc4
|
||||
References: bnc#635425
|
||||
Introduced-by: 2.6.23
|
||||
|
||||
execve: make responsive to SIGKILL with large arguments
|
||||
|
||||
An execve with a very large total of argument/environment strings
|
||||
can take a really long time in the execve system call. It runs
|
||||
uninterruptibly to count and copy all the strings. This change
|
||||
makes it abort the exec quickly if sent a SIGKILL.
|
||||
|
||||
Note that this is the conservative change, to interrupt only for
|
||||
SIGKILL, by using fatal_signal_pending(). It would be perfectly
|
||||
correct semantics to let any signal interrupt the string-copying in
|
||||
execve, i.e. use signal_pending() instead of fatal_signal_pending().
|
||||
We'll save that change for later, since it could have user-visible
|
||||
consequences, such as having a timer set too quickly make it so that
|
||||
an execve can never complete, though it always happened to work before.
|
||||
|
||||
Signed-off-by: Roland McGrath <roland@redhat.com>
|
||||
Reviewed-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
|
||||
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
Acked-by: Jeff Mahoney <jeffm@suse.com>
|
||||
---
|
||||
|
||||
fs/exec.c | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
diff --git a/fs/exec.c b/fs/exec.c
|
||||
index 6f2d777..828dd24 100644
|
||||
--- a/fs/exec.c
|
||||
+++ b/fs/exec.c
|
||||
@@ -376,6 +376,9 @@ static int count(const char __user * const __user * argv, int max)
|
||||
argv++;
|
||||
if (i++ >= max)
|
||||
return -E2BIG;
|
||||
+
|
||||
+ if (fatal_signal_pending(current))
|
||||
+ return -ERESTARTNOHAND;
|
||||
cond_resched();
|
||||
}
|
||||
}
|
||||
@@ -419,6 +422,10 @@ static int copy_strings(int argc, const char __user *const __user *argv,
|
||||
while (len > 0) {
|
||||
int offset, bytes_to_copy;
|
||||
|
||||
+ if (fatal_signal_pending(current)) {
|
||||
+ ret = -ERESTARTNOHAND;
|
||||
+ goto out;
|
||||
+ }
|
||||
cond_resched();
|
||||
|
||||
offset = pos % PAGE_SIZE;
|
@ -1,41 +0,0 @@
|
||||
From: Jeff Mahoney <jeffm@suse.com>
|
||||
Subject: [PATCH] ext3: always mark super uptodate before dirty
|
||||
References: bnc#457043
|
||||
Patch-mainline: not yet
|
||||
|
||||
The superblock's bh is something of an exception. It is only read
|
||||
during mount and is only released during unmount. The in-memory
|
||||
copy is invariably the most recent one.
|
||||
|
||||
If a write error occurs while syncing the superblock, it will be marked
|
||||
!uptodate. When another error occurs, ext3_error will invoke
|
||||
ext3_commit_super, which will mark the superblock dirty and try to
|
||||
sync it out again. If the buffer is !uptodate, then mark_buffer_dirty
|
||||
will issue a warning, but continue anyway.
|
||||
|
||||
This patch marks it uptodate before writing it out. This doesn't really
|
||||
change anything other than silencing the warning in mark_buffer_dirty.
|
||||
If the write succeeds, good. Otherwise, it will just have uptodate
|
||||
cleared again.
|
||||
|
||||
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
|
||||
---
|
||||
fs/ext3/super.c | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
--- a/fs/ext3/super.c
|
||||
+++ b/fs/ext3/super.c
|
||||
@@ -2382,6 +2382,13 @@ static int ext3_commit_super(struct supe
|
||||
es->s_free_blocks_count = cpu_to_le32(ext3_count_free_blocks(sb));
|
||||
es->s_free_inodes_count = cpu_to_le32(ext3_count_free_inodes(sb));
|
||||
BUFFER_TRACE(sbh, "marking dirty");
|
||||
+
|
||||
+ /* We only read the superblock once. The in-memory version is
|
||||
+ * always the most recent. If ext3_error is called after a
|
||||
+ * superblock write failure, it will be !uptodate. This write
|
||||
+ * will likely fail also, but it avoids the WARN_ON in
|
||||
+ * mark_buffer_dirty. */
|
||||
+ set_buffer_uptodate(sbh);
|
||||
mark_buffer_dirty(sbh);
|
||||
if (sync)
|
||||
error = sync_dirty_buffer(sbh);
|
@ -1,36 +0,0 @@
|
||||
It doesn't like pattern and explicit rules to be on the same line,
|
||||
and it seems to be more picky when matching file (or really directory)
|
||||
names with different numbers of trailing slashes.
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich [at] novell>
|
||||
Acked-by: Sam Ravnborg <sam [at] ravnborg>
|
||||
|
||||
---
|
||||
firmware/Makefile | 2 +-
|
||||
scripts/mkmakefile | 4 +++-
|
||||
2 files changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
--- linux-2.6.36-rc1/firmware/Makefile
|
||||
+++ 2.6.36-rc1-make-3.82-fixes/firmware/Makefile
|
||||
@@ -142,7 +142,7 @@ fw-shipped-$(CONFIG_YAM) += yam/1200.bin
|
||||
fw-shipped-all := $(fw-shipped-y) $(fw-shipped-m) $(fw-shipped-)
|
||||
|
||||
# Directories which we _might_ need to create, so we have a rule for them.
|
||||
-firmware-dirs := $(sort $(patsubst %,$(objtree)/$(obj)/%/,$(dir $(fw-external-y) $(fw-shipped-all))))
|
||||
+firmware-dirs := $(sort $(addprefix $(objtree)/$(obj)/,$(dir $(fw-external-y) $(fw-shipped-all))))
|
||||
|
||||
quiet_cmd_mkdir = MKDIR $(patsubst $(objtree)/%,%,$@)
|
||||
cmd_mkdir = mkdir -p $@
|
||||
--- linux-2.6.36-rc1/scripts/mkmakefile
|
||||
+++ 2.6.36-rc1-make-3.82-fixes/scripts/mkmakefile
|
||||
@@ -44,7 +44,9 @@ all:
|
||||
|
||||
Makefile:;
|
||||
|
||||
-\$(all) %/: all
|
||||
+\$(all): all
|
||||
@:
|
||||
|
||||
+%/: all
|
||||
+ @:
|
||||
EOF
|
@ -0,0 +1,43 @@
|
||||
From: Kyle McMartin <kyle@dreadnought.i.jkkm.org>
|
||||
Subject: flexcop: fix registering braindead stupid names
|
||||
References: brc#575873 bnc#661429
|
||||
Patch-mainline: Unsubmitted by author
|
||||
|
||||
This patch fixes an issue where the flexcop driver passes DRIVER_NAME to
|
||||
request_irq, which ultimately sets up proc files. The invalid name
|
||||
contains slashes so the proc file creation fails and we get a WARN_ON.
|
||||
|
||||
Acked-by: Jeff Mahoney <jeffm@suse.com>
|
||||
---
|
||||
|
||||
drivers/media/dvb/b2c2/flexcop-pci.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/media/dvb/b2c2/flexcop-pci.c
|
||||
+++ b/drivers/media/dvb/b2c2/flexcop-pci.c
|
||||
@@ -39,6 +39,7 @@ MODULE_PARM_DESC(debug,
|
||||
|
||||
#define DRIVER_VERSION "0.1"
|
||||
#define DRIVER_NAME "Technisat/B2C2 FlexCop II/IIb/III Digital TV PCI Driver"
|
||||
+#define FLEXCOP_MODULE_NAME "b2c2-flexcop"
|
||||
#define DRIVER_AUTHOR "Patrick Boettcher <patrick.boettcher@desy.de>"
|
||||
|
||||
struct flexcop_pci {
|
||||
@@ -299,7 +300,7 @@ static int flexcop_pci_init(struct flexc
|
||||
return ret;
|
||||
pci_set_master(fc_pci->pdev);
|
||||
|
||||
- if ((ret = pci_request_regions(fc_pci->pdev, DRIVER_NAME)) != 0)
|
||||
+ if ((ret = pci_request_regions(fc_pci->pdev, FLEXCOP_MODULE_NAME)) != 0)
|
||||
goto err_pci_disable_device;
|
||||
|
||||
fc_pci->io_mem = pci_iomap(fc_pci->pdev, 0, 0x800);
|
||||
@@ -313,7 +314,7 @@ static int flexcop_pci_init(struct flexc
|
||||
pci_set_drvdata(fc_pci->pdev, fc_pci);
|
||||
spin_lock_init(&fc_pci->irq_lock);
|
||||
if ((ret = request_irq(fc_pci->pdev->irq, flexcop_pci_isr,
|
||||
- IRQF_SHARED, DRIVER_NAME, fc_pci)) != 0)
|
||||
+ IRQF_SHARED, FLEXCOP_MODULE_NAME, fc_pci)) != 0)
|
||||
goto err_pci_iounmap;
|
||||
|
||||
fc_pci->init_state |= FC_PCI_INIT;
|
@ -0,0 +1,54 @@
|
||||
From: Timo Warns <Warns@pre-sense.de>
|
||||
Subject: fs/partitions/efi.c: corrupted GUID partition tables can cause kernel oops
|
||||
References: bnc#687113 CVE-2011-1577
|
||||
Patch-mainline: Probably 2.6.39; In -mm already
|
||||
|
||||
The kernel automatically evaluates partition tables of storage devices.
|
||||
The code for evaluating GUID partitions (in fs/partitions/efi.c) contains
|
||||
a bug that causes a kernel oops on certain corrupted GUID partition
|
||||
tables.
|
||||
|
||||
This bug has security impacts, because it allows, for example, to
|
||||
prepare a storage device that crashes a kernel subsystem upon connecting
|
||||
the device (e.g., a "USB Stick of (Partial) Death").
|
||||
|
||||
crc = efi_crc32((const unsigned char *) (*gpt), le32_to_cpu((*gpt)->header_size));
|
||||
|
||||
computes a CRC32 checksum over gpt covering (*gpt)->header_size bytes.
|
||||
There is no validation of (*gpt)->header_size before the efi_crc32 call.
|
||||
|
||||
A corrupted partition table may have large values for (*gpt)->header_size.
|
||||
In this case, the CRC32 computation access memory beyond the memory
|
||||
allocated for gpt, which may cause a kernel heap overflow.
|
||||
|
||||
Validate value of GUID partition table header size.
|
||||
|
||||
Signed-off-by: Timo Warns <warns@pre-sense.de>
|
||||
Cc: Matt Domsch <Matt_Domsch@dell.com>
|
||||
Cc: Eugene Teo <eugeneteo@kernel.sg>
|
||||
Cc: Dave Jones <davej@codemonkey.org.uk>
|
||||
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||||
Acked-by: Jeff Mahoney <jeffm@suse.com>
|
||||
---
|
||||
|
||||
fs/partitions/efi.c | 9 +++++++++
|
||||
1 file changed, 9 insertions(+)
|
||||
|
||||
--- a/fs/partitions/efi.c
|
||||
+++ b/fs/partitions/efi.c
|
||||
@@ -310,6 +310,15 @@ static int is_gpt_valid(struct parsed_pa
|
||||
goto fail;
|
||||
}
|
||||
|
||||
+ /* Check the GUID Partition Table header size */
|
||||
+ if (le32_to_cpu((*gpt)->header_size) >
|
||||
+ bdev_logical_block_size(state->bdev)) {
|
||||
+ pr_debug("GUID Partition Table Header size is wrong: %u > %u\n",
|
||||
+ le32_to_cpu((*gpt)->header_size),
|
||||
+ bdev_logical_block_size(state->bdev));
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
/* Check the GUID Partition Table CRC */
|
||||
origcrc = le32_to_cpu((*gpt)->header_crc32);
|
||||
(*gpt)->header_crc32 = 0;
|
@ -0,0 +1,30 @@
|
||||
From: Jeff Mahoney <jeffm@suse.com>
|
||||
Subject: hfs: avoid crash in hfs_bnode_create
|
||||
Patch-mainline: not yet
|
||||
References: bnc#552250
|
||||
|
||||
Commit 634725a92938b0f282b17cec0b007dca77adebd2 removed the BUG_ON
|
||||
in hfs_bnode_create in hfsplus. This patch removes it from the hfs
|
||||
version and avoids an fsfuzzer crash.
|
||||
|
||||
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
|
||||
Acked-by: Jeff Mahoney <jeffm@suse.com>
|
||||
---
|
||||
fs/hfs/bnode.c | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/fs/hfs/bnode.c
|
||||
+++ b/fs/hfs/bnode.c
|
||||
@@ -413,7 +413,11 @@ struct hfs_bnode *hfs_bnode_create(struc
|
||||
spin_lock(&tree->hash_lock);
|
||||
node = hfs_bnode_findhash(tree, num);
|
||||
spin_unlock(&tree->hash_lock);
|
||||
- BUG_ON(node);
|
||||
+ if (node) {
|
||||
+ printk(KERN_CRIT "new node %u already hashed?\n", num);
|
||||
+ WARN_ON(1);
|
||||
+ return node;
|
||||
+ }
|
||||
node = __hfs_bnode_create(tree, num);
|
||||
if (!node)
|
||||
return ERR_PTR(-ENOMEM);
|
@ -0,0 +1,102 @@
|
||||
From: Jiri Kosina <jkosina@suse.cz>
|
||||
Subject: [PATCH] HID: add support for Skycable 0x3f07 wireless presenter
|
||||
References: bnc#681297
|
||||
Patch-mainline: not yet, queued in subsystem tree
|
||||
|
||||
This device contains the very same bug in report descriptor as the
|
||||
Ortek ones do (i.e. LogicalMinimum == 1, which is wrong for the key
|
||||
array).
|
||||
|
||||
As we have more reports for the Ortek devices, we are keeping the driver
|
||||
name for now. Apparently there is a chip producer which sells chip with
|
||||
this buggy descriptor to multiple vendors. Thus if such reports start
|
||||
to come at highger frequency, we'll either have to rename the driver
|
||||
accordingly, or come up with more generic workaround.
|
||||
|
||||
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
|
||||
---
|
||||
drivers/hid/Kconfig | 9 +++++++--
|
||||
drivers/hid/hid-core.c | 1 +
|
||||
drivers/hid/hid-ids.h | 3 +++
|
||||
drivers/hid/hid-ortek.c | 15 +++++++++++----
|
||||
4 files changed, 22 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/drivers/hid/Kconfig
|
||||
+++ b/drivers/hid/Kconfig
|
||||
@@ -325,10 +325,15 @@ config HID_NTRIG
|
||||
Support for N-Trig touch screen.
|
||||
|
||||
config HID_ORTEK
|
||||
- tristate "Ortek PKB-1700/WKB-2000 wireless keyboard and mouse trackpad"
|
||||
+ tristate "Ortek WKB-2000/Skycable wireless keyboard and mouse trackpad"
|
||||
depends on USB_HID
|
||||
---help---
|
||||
- Support for Ortek PKB-1700/WKB-2000 wireless keyboard + mouse trackpad.
|
||||
+ There are certain devices which have LogicalMaximum wrong in the keyboard
|
||||
+ usage page of their report descriptor. The most prevailing ones so far
|
||||
+ are manufactured by Ortek, thus the name of the driver. Currently
|
||||
+ supported devices by this driver are
|
||||
+ - Ortek WKB-2000
|
||||
+ - Skycable wireless presenter
|
||||
|
||||
config HID_PANTHERLORD
|
||||
tristate "Pantherlord/GreenAsia game controller"
|
||||
--- a/drivers/hid/hid-core.c
|
||||
+++ b/drivers/hid/hid-core.c
|
||||
@@ -1411,6 +1411,7 @@ static const struct hid_device_id hid_ha
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) },
|
||||
+ { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) },
|
||||
--- a/drivers/hid/hid-ids.h
|
||||
+++ b/drivers/hid/hid-ids.h
|
||||
@@ -514,6 +514,9 @@
|
||||
#define USB_DEVICE_ID_SAMSUNG_IR_REMOTE 0x0001
|
||||
#define USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE 0x0600
|
||||
|
||||
+#define USB_VENDOR_ID_SKYCABLE 0x1223
|
||||
+#define USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER 0x3F07
|
||||
+
|
||||
#define USB_VENDOR_ID_SONY 0x054c
|
||||
#define USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE 0x024b
|
||||
#define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268
|
||||
--- a/drivers/hid/hid-ortek.c
|
||||
+++ b/drivers/hid/hid-ortek.c
|
||||
@@ -1,9 +1,12 @@
|
||||
-/*
|
||||
- * HID driver for Ortek PKB-1700/WKB-2000 (wireless keyboard + mouse trackpad).
|
||||
- * Fixes LogicalMaximum error in USB report description, see
|
||||
- * http://bugzilla.kernel.org/show_bug.cgi?id=14787
|
||||
+/* HID driver for various devices which are apparently based on the same chipset
|
||||
+ * from certain vendor which produces chips that contain wrong LogicalMaximum
|
||||
+ * value in their HID report descriptor. Currently supported devices are:
|
||||
+ *
|
||||
+ * Ortek WKB-2000
|
||||
+ * Skycable wireless presenter
|
||||
*
|
||||
* Copyright (c) 2010 Johnathon Harris <jmharris@gmail.com>
|
||||
+ * Copyright (c) 2011 Jiri Kosina
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -25,6 +28,9 @@ static __u8 *ortek_report_fixup(struct h
|
||||
if (*rsize >= 56 && rdesc[54] == 0x25 && rdesc[55] == 0x01) {
|
||||
hid_info(hdev, "Fixing up Ortek WKB-2000 report descriptor\n");
|
||||
rdesc[55] = 0x92;
|
||||
+ } else if (*rsize >= 54 && rdesc[52] == 0x25 && rdesc[53] == 0x01) {
|
||||
+ hid_info(hdev, "Fixing up logical minimum in report descriptor (Skycable)\n");
|
||||
+ rdesc[53] = 0x65;
|
||||
}
|
||||
return rdesc;
|
||||
}
|
||||
@@ -32,6 +38,7 @@ static __u8 *ortek_report_fixup(struct h
|
||||
static const struct hid_device_id ortek_devices[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_PKB1700) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) },
|
||||
+ { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(hid, ortek_devices);
|
@ -1,110 +0,0 @@
|
||||
From: Thomas Renninger <trenn@suse.de>
|
||||
Subject: x86 platform drivers: hp-wmi Reorder event id processing
|
||||
References: bnc#598059
|
||||
Patch-Mainline: submitted
|
||||
|
||||
Event id 0x4 defines the hotkey event.
|
||||
No need (or even wrong) to query HPWMI_HOTKEY_QUERY if event id is != 0x4.
|
||||
|
||||
Reorder the eventcode conditionals and use switch case instead of if/else.
|
||||
Use an enum for the event ids cases.
|
||||
|
||||
|
||||
Signed-off-by: Thomas Renninger <trenn@suse.de>
|
||||
CC: mjg@redhat.com
|
||||
CC: linux-acpi@vger.kernel.org
|
||||
|
||||
---
|
||||
drivers/platform/x86/hp-wmi.c | 51 ++++++++++++++++++++++++++----------------
|
||||
1 file changed, 32 insertions(+), 19 deletions(-)
|
||||
|
||||
Index: linux-2.6.33-master/drivers/platform/x86/hp-wmi.c
|
||||
===================================================================
|
||||
--- linux-2.6.33-master.orig/drivers/platform/x86/hp-wmi.c
|
||||
+++ linux-2.6.33-master/drivers/platform/x86/hp-wmi.c
|
||||
@@ -58,6 +58,12 @@ enum hp_wmi_radio {
|
||||
HPWMI_WWAN = 2,
|
||||
};
|
||||
|
||||
+enum hp_wmi_event_ids {
|
||||
+ HPWMI_DOCK_EVENT = 1,
|
||||
+ HPWMI_BEZEL_BUTTON = 4,
|
||||
+ HPWMI_WIRELESS = 5,
|
||||
+};
|
||||
+
|
||||
static int __devinit hp_wmi_bios_setup(struct platform_device *device);
|
||||
static int __exit hp_wmi_bios_remove(struct platform_device *device);
|
||||
static int hp_wmi_resume_handler(struct device *device);
|
||||
@@ -338,7 +344,7 @@ static void hp_wmi_notify(u32 value, voi
|
||||
struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
static struct key_entry *key;
|
||||
union acpi_object *obj;
|
||||
- int eventcode;
|
||||
+ int eventcode, key_code;
|
||||
acpi_status status;
|
||||
|
||||
status = wmi_get_event_data(value, &response);
|
||||
@@ -357,28 +363,32 @@ static void hp_wmi_notify(u32 value, voi
|
||||
|
||||
eventcode = *((u8 *) obj->buffer.pointer);
|
||||
kfree(obj);
|
||||
- if (eventcode == 0x4)
|
||||
- eventcode = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0,
|
||||
- 0);
|
||||
- key = hp_wmi_get_entry_by_scancode(eventcode);
|
||||
- if (key) {
|
||||
- switch (key->type) {
|
||||
- case KE_KEY:
|
||||
- input_report_key(hp_wmi_input_dev,
|
||||
- key->keycode, 1);
|
||||
- input_sync(hp_wmi_input_dev);
|
||||
- input_report_key(hp_wmi_input_dev,
|
||||
- key->keycode, 0);
|
||||
- input_sync(hp_wmi_input_dev);
|
||||
- break;
|
||||
- }
|
||||
- } else if (eventcode == 0x1) {
|
||||
+ switch (eventcode) {
|
||||
+ case HPWMI_DOCK_EVENT:
|
||||
input_report_switch(hp_wmi_input_dev, SW_DOCK,
|
||||
hp_wmi_dock_state());
|
||||
input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE,
|
||||
hp_wmi_tablet_state());
|
||||
input_sync(hp_wmi_input_dev);
|
||||
- } else if (eventcode == 0x5) {
|
||||
+ break;
|
||||
+ case HPWMI_BEZEL_BUTTON:
|
||||
+ key_code = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0,
|
||||
+ 0);
|
||||
+ key = hp_wmi_get_entry_by_scancode(key_code);
|
||||
+ if (key) {
|
||||
+ switch (key->type) {
|
||||
+ case KE_KEY:
|
||||
+ input_report_key(hp_wmi_input_dev,
|
||||
+ key->keycode, 1);
|
||||
+ input_sync(hp_wmi_input_dev);
|
||||
+ input_report_key(hp_wmi_input_dev,
|
||||
+ key->keycode, 0);
|
||||
+ input_sync(hp_wmi_input_dev);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ break;
|
||||
+ case HPWMI_WIRELESS:
|
||||
if (wifi_rfkill)
|
||||
rfkill_set_states(wifi_rfkill,
|
||||
hp_wmi_get_sw_state(HPWMI_WIFI),
|
||||
@@ -391,9 +401,12 @@ static void hp_wmi_notify(u32 value, voi
|
||||
rfkill_set_states(wwan_rfkill,
|
||||
hp_wmi_get_sw_state(HPWMI_WWAN),
|
||||
hp_wmi_get_hw_state(HPWMI_WWAN));
|
||||
- } else
|
||||
+ break;
|
||||
+ default:
|
||||
printk(KERN_INFO "HP WMI: Unknown key pressed - %x\n",
|
||||
eventcode);
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
|
||||
static int __init hp_wmi_input_setup(void)
|
@ -1,25 +0,0 @@
|
||||
From: Thomas Renninger <trenn@suse.de>
|
||||
Subject: x86 platform drivers: hp-wmi Add media key 0x20e8
|
||||
References: bnc#598059
|
||||
Patch-Mainline: submitted
|
||||
|
||||
Signed-off-by: Thomas Renninger <trenn@suse.de>
|
||||
CC: mjg@redhat.com
|
||||
CC: linux-acpi@vger.kernel.org
|
||||
|
||||
---
|
||||
drivers/platform/x86/hp-wmi.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
Index: linux-2.6.33-master/drivers/platform/x86/hp-wmi.c
|
||||
===================================================================
|
||||
--- linux-2.6.33-master.orig/drivers/platform/x86/hp-wmi.c
|
||||
+++ linux-2.6.33-master/drivers/platform/x86/hp-wmi.c
|
||||
@@ -96,6 +96,7 @@ static struct key_entry hp_wmi_keymap[]
|
||||
{KE_KEY, 0x02, KEY_BRIGHTNESSUP},
|
||||
{KE_KEY, 0x03, KEY_BRIGHTNESSDOWN},
|
||||
{KE_KEY, 0x20e6, KEY_PROG1},
|
||||
+ {KE_KEY, 0x20e8, KEY_MEDIA},
|
||||
{KE_KEY, 0x2142, KEY_MEDIA},
|
||||
{KE_KEY, 0x213b, KEY_INFO},
|
||||
{KE_KEY, 0x2169, KEY_DIRECTION},
|
@ -1,39 +0,0 @@
|
||||
From: Thomas Renninger <trenn@suse.de>
|
||||
Subject: x86 platform drivers: hp-wmi Catch and log unkown event and key codes correctly
|
||||
References: bnc#598059
|
||||
Patch-Mainline: submitted
|
||||
|
||||
Signed-off-by: Thomas Renninger <trenn@suse.de>
|
||||
CC: mjg@redhat.com
|
||||
CC: linux-acpi@vger.kernel.org
|
||||
|
||||
---
|
||||
drivers/platform/x86/hp-wmi.c | 8 +++++---
|
||||
1 file changed, 5 insertions(+), 3 deletions(-)
|
||||
|
||||
Index: linux-2.6.33-master/drivers/platform/x86/hp-wmi.c
|
||||
===================================================================
|
||||
--- linux-2.6.33-master.orig/drivers/platform/x86/hp-wmi.c
|
||||
+++ linux-2.6.33-master/drivers/platform/x86/hp-wmi.c
|
||||
@@ -386,7 +386,9 @@ static void hp_wmi_notify(u32 value, voi
|
||||
input_sync(hp_wmi_input_dev);
|
||||
break;
|
||||
}
|
||||
- }
|
||||
+ } else
|
||||
+ printk(KERN_INFO "HP WMI: Unknown key code - 0x%x\n",
|
||||
+ key_code);
|
||||
break;
|
||||
case HPWMI_WIRELESS:
|
||||
if (wifi_rfkill)
|
||||
@@ -403,8 +405,8 @@ static void hp_wmi_notify(u32 value, voi
|
||||
hp_wmi_get_hw_state(HPWMI_WWAN));
|
||||
break;
|
||||
default:
|
||||
- printk(KERN_INFO "HP WMI: Unknown key pressed - %x\n",
|
||||
- eventcode);
|
||||
+ printk(KERN_INFO "HP WMI: Unknown eventcode - %d\n",
|
||||
+ eventcode);
|
||||
break;
|
||||
}
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
From: Thomas Renninger <trenn@suse.de>
|
||||
Subject: x86 platform drivers: hp-wmi Use consistent prefix string for messages.
|
||||
References: bnc#598059
|
||||
Patch-Mainline: submitted
|
||||
|
||||
Signed-off-by: Thomas Renninger <trenn@suse.de>
|
||||
CC: mjg@redhat.com
|
||||
CC: linux-acpi@vger.kernel.org
|
||||
|
||||
---
|
||||
drivers/platform/x86/hp-wmi.c | 10 ++++++----
|
||||
1 file changed, 6 insertions(+), 4 deletions(-)
|
||||
|
||||
Index: linux-2.6.33-master/drivers/platform/x86/hp-wmi.c
|
||||
===================================================================
|
||||
--- linux-2.6.33-master.orig/drivers/platform/x86/hp-wmi.c
|
||||
+++ linux-2.6.33-master/drivers/platform/x86/hp-wmi.c
|
||||
@@ -52,6 +52,8 @@ MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE9
|
||||
#define HPWMI_WIRELESS_QUERY 0x5
|
||||
#define HPWMI_HOTKEY_QUERY 0xc
|
||||
|
||||
+#define PREFIX "HP WMI: "
|
||||
+
|
||||
enum hp_wmi_radio {
|
||||
HPWMI_WIFI = 0,
|
||||
HPWMI_BLUETOOTH = 1,
|
||||
@@ -349,14 +351,14 @@ static void hp_wmi_notify(u32 value, voi
|
||||
|
||||
status = wmi_get_event_data(value, &response);
|
||||
if (status != AE_OK) {
|
||||
- printk(KERN_INFO "hp-wmi: bad event status 0x%x\n", status);
|
||||
+ printk(KERN_INFO PREFIX "bad event status 0x%x\n", status);
|
||||
return;
|
||||
}
|
||||
|
||||
obj = (union acpi_object *)response.pointer;
|
||||
|
||||
if (!obj || obj->type != ACPI_TYPE_BUFFER || obj->buffer.length != 8) {
|
||||
- printk(KERN_INFO "HP WMI: Unknown response received\n");
|
||||
+ printk(KERN_INFO PREFIX "Unknown response received\n");
|
||||
kfree(obj);
|
||||
return;
|
||||
}
|
||||
@@ -387,7 +389,7 @@ static void hp_wmi_notify(u32 value, voi
|
||||
break;
|
||||
}
|
||||
} else
|
||||
- printk(KERN_INFO "HP WMI: Unknown key code - 0x%x\n",
|
||||
+ printk(KERN_INFO PREFIX "Unknown key code - 0x%x\n",
|
||||
key_code);
|
||||
break;
|
||||
case HPWMI_WIRELESS:
|
||||
@@ -405,7 +407,7 @@ static void hp_wmi_notify(u32 value, voi
|
||||
hp_wmi_get_hw_state(HPWMI_WWAN));
|
||||
break;
|
||||
default:
|
||||
- printk(KERN_INFO "HP WMI: Unknown eventcode - %d\n",
|
||||
+ printk(KERN_INFO PREFIX "Unknown eventcode - %d\n",
|
||||
eventcode);
|
||||
break;
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
From: unknown@suse.de
|
||||
Subject: some unknown ieee1394 patch
|
||||
Patch-mainline: not yet
|
||||
|
||||
make the long format the default because its also the default in the
|
||||
new firewire stack.
|
||||
Maybe it simplifies migration for new 10.3 installs to 11.0 or later.
|
||||
Maybe it is bad for existing 10.3 and earlier installs.
|
||||
|
||||
modprobe -v sbp2 sbp2_long_sysfs_ieee1394_id=0 to get the old short name
|
||||
modprobe -v sbp2 sbp2_long_sysfs_ieee1394_id=1 to get the new long name
|
||||
|
||||
---
|
||||
drivers/ieee1394/sbp2.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/ieee1394/sbp2.c
|
||||
+++ b/drivers/ieee1394/sbp2.c
|
||||
@@ -225,7 +225,7 @@ MODULE_PARM_DESC(workarounds, "Work arou
|
||||
* independent of the implementation of the ieee1394 nodemgr, the longer format
|
||||
* is recommended for future use.
|
||||
*/
|
||||
-static int sbp2_long_sysfs_ieee1394_id;
|
||||
+static int sbp2_long_sysfs_ieee1394_id = 1;
|
||||
module_param_named(long_ieee1394_id, sbp2_long_sysfs_ieee1394_id, bool, 0644);
|
||||
MODULE_PARM_DESC(long_ieee1394_id, "8+3+2 bytes format of ieee1394_id in sysfs "
|
||||
"(default = backwards-compatible = N, SAM-conforming = Y)");
|
@ -0,0 +1,60 @@
|
||||
From: Reinette Chatre <reinette.chatre@intel.com>
|
||||
Date: Tue, 29 Jun 2010 14:24:51 -0700
|
||||
Subject: [PATCH] iwlwifi: fix TX power configuration on 3945 and 4965 devices
|
||||
Patch-mainline: Probably 2.6.35
|
||||
References: bnc#619440 bnc#610421
|
||||
|
||||
When receiving a TX power change request from mac80211 the functions
|
||||
servicing these requests for 3945 and 4965 uses information in the active
|
||||
RXON. In iwl_mac_config the staging RXON is prepared based on various
|
||||
directions from mac80211 and only at the end is the staging RXON committed
|
||||
to the device and the active RXON updated.
|
||||
|
||||
By servicing the TX power change request while servicing the other requests
|
||||
that modify the staging RXON we loose the new information provided by mac80211.
|
||||
|
||||
Fix this by servicing the TX power change request after the RXON has been committed
|
||||
to the device and active RXON thus contains accurate information.
|
||||
|
||||
|
||||
21 Jan 2011 jeffm:
|
||||
This patch may have been superced by 2295c66b68ae160dde2e6e2dc4f3061105153bfc
|
||||
but needs review.
|
||||
|
||||
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
|
||||
Acked-by: Jeff Mahoney <jeffm@suse.com>
|
||||
---
|
||||
drivers/net/wireless/iwlwifi/iwl-core.c | 15 ++++++++-------
|
||||
1 file changed, 8 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
|
||||
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
|
||||
@@ -2160,13 +2160,6 @@ int iwl_mac_config(struct ieee80211_hw *
|
||||
IWL_DEBUG_MAC80211(priv, "Error setting sleep level\n");
|
||||
}
|
||||
|
||||
- if (changed & IEEE80211_CONF_CHANGE_POWER) {
|
||||
- IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n",
|
||||
- priv->tx_power_user_lmt, conf->power_level);
|
||||
-
|
||||
- iwl_set_tx_power(priv, conf->power_level, false);
|
||||
- }
|
||||
-
|
||||
if (!iwl_is_ready(priv)) {
|
||||
IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
|
||||
goto out;
|
||||
@@ -2181,6 +2174,14 @@ int iwl_mac_config(struct ieee80211_hw *
|
||||
"Not re-sending same RXON configuration.\n");
|
||||
}
|
||||
|
||||
+ if (changed & IEEE80211_CONF_CHANGE_POWER) {
|
||||
+ IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n",
|
||||
+ priv->tx_power_user_lmt, conf->power_level);
|
||||
+
|
||||
+ iwl_set_tx_power(priv, conf->power_level, false);
|
||||
+ }
|
||||
+
|
||||
+
|
||||
out:
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
mutex_unlock(&priv->mutex);
|
@ -1,28 +0,0 @@
|
||||
Subject: kbuild: fix generating of *.symtypes files
|
||||
From: Michal Marek <mmarek@suse.cz>
|
||||
Patch-mainline: submitted 2009-06-29
|
||||
|
||||
Commit 37a8d9f ("kbuild: simplify use of genksyms") broke generating of
|
||||
*.symtypes files during build (with KBUILD_SYMTYPES set). This patch
|
||||
fixes it.
|
||||
|
||||
Signed-off-by: Michal Marek <mmarek@suse.cz>
|
||||
|
||||
---
|
||||
scripts/Makefile.build | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/scripts/Makefile.build
|
||||
+++ b/scripts/Makefile.build
|
||||
@@ -156,9 +156,9 @@ $(obj)/%.i: $(src)/%.c FORCE
|
||||
|
||||
cmd_gensymtypes = \
|
||||
$(CPP) -D__GENKSYMS__ $(c_flags) $< | \
|
||||
- $(GENKSYMS) -T $@ -a $(ARCH) \
|
||||
+ $(GENKSYMS) $(if $(strip $(1)), -T $(@:.o=.symtypes)) -a $(ARCH) \
|
||||
$(if $(KBUILD_PRESERVE),-p) \
|
||||
- $(if $(1),-r $(firstword $(wildcard $(@:.symtypes=.symref) /dev/null)))
|
||||
+ -r $(firstword $(wildcard $(basename $@).symref /dev/null))
|
||||
|
||||
quiet_cmd_cc_symtypes_c = SYM $(quiet_modtag) $@
|
||||
cmd_cc_symtypes_c = \
|
@ -1,56 +0,0 @@
|
||||
From: David Howells <dhowells@redhat.com>
|
||||
Date: Fri, 10 Sep 2010 08:59:51 +0000 (+0100)
|
||||
Subject: KEYS: Fix bug in keyctl_session_to_parent() if parent has no session
|
||||
keyring
|
||||
Git-commit: 3d96406c7da1ed5811ea52a3b0905f4f0e295376
|
||||
Patch-mainline: 2.6.36-rc4
|
||||
References: CVE-2010-2960 bnc#634637
|
||||
Introduced-by: 2.6.32
|
||||
|
||||
KEYS: Fix bug in keyctl_session_to_parent() if parent has no session keyring
|
||||
|
||||
Fix a bug in keyctl_session_to_parent() whereby it tries to check the ownership
|
||||
of the parent process's session keyring whether or not the parent has a session
|
||||
keyring [CVE-2010-2960].
|
||||
|
||||
This results in the following oops:
|
||||
|
||||
BUG: unable to handle kernel NULL pointer dereference at 00000000000000a0
|
||||
IP: [<ffffffff811ae4dd>] keyctl_session_to_parent+0x251/0x443
|
||||
...
|
||||
Call Trace:
|
||||
[<ffffffff811ae2f3>] ? keyctl_session_to_parent+0x67/0x443
|
||||
[<ffffffff8109d286>] ? __do_fault+0x24b/0x3d0
|
||||
[<ffffffff811af98c>] sys_keyctl+0xb4/0xb8
|
||||
[<ffffffff81001eab>] system_call_fastpath+0x16/0x1b
|
||||
|
||||
if the parent process has no session keyring.
|
||||
|
||||
If the system is using pam_keyinit then it mostly protected against this as all
|
||||
processes derived from a login will have inherited the session keyring created
|
||||
by pam_keyinit during the log in procedure.
|
||||
|
||||
To test this, pam_keyinit calls need to be commented out in /etc/pam.d/.
|
||||
|
||||
Reported-by: Tavis Ormandy <taviso@cmpxchg8b.com>
|
||||
Signed-off-by: David Howells <dhowells@redhat.com>
|
||||
Acked-by: Tavis Ormandy <taviso@cmpxchg8b.com>
|
||||
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
Acked-by: Jeff Mahoney <jeffm@suse.com>
|
||||
---
|
||||
|
||||
security/keys/keyctl.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/security/keys/keyctl.c
|
||||
+++ b/security/keys/keyctl.c
|
||||
@@ -1292,7 +1292,8 @@ long keyctl_session_to_parent(void)
|
||||
goto not_permitted;
|
||||
|
||||
/* the keyrings must have the same UID */
|
||||
- if (pcred ->tgcred->session_keyring->uid != mycred->euid ||
|
||||
+ if ((pcred->tgcred->session_keyring &&
|
||||
+ pcred->tgcred->session_keyring->uid != mycred->euid) ||
|
||||
mycred->tgcred->session_keyring->uid != mycred->euid)
|
||||
goto not_permitted;
|
||||
|
@ -1,69 +0,0 @@
|
||||
From: David Howells <dhowells@redhat.com>
|
||||
Date: Fri, 10 Sep 2010 08:59:46 +0000 (+0100)
|
||||
Subject: KEYS: Fix RCU no-lock warning in keyctl_session_to_parent()
|
||||
Git-commit: 9d1ac65a9698513d00e5608d93fca0c53f536c14
|
||||
Patch-mainline: 2.6.36-rc4
|
||||
References: CVE-2010-2960 bnc#634637
|
||||
Introduced-by: 2.6.32
|
||||
|
||||
KEYS: Fix RCU no-lock warning in keyctl_session_to_parent()
|
||||
|
||||
There's an protected access to the parent process's credentials in the middle
|
||||
of keyctl_session_to_parent(). This results in the following RCU warning:
|
||||
|
||||
===================================================
|
||||
[ INFO: suspicious rcu_dereference_check() usage. ]
|
||||
---------------------------------------------------
|
||||
security/keys/keyctl.c:1291 invoked rcu_dereference_check() without protection!
|
||||
|
||||
other info that might help us debug this:
|
||||
|
||||
rcu_scheduler_active = 1, debug_locks = 0
|
||||
1 lock held by keyctl-session-/2137:
|
||||
#0: (tasklist_lock){.+.+..}, at: [<ffffffff811ae2ec>] keyctl_session_to_parent+0x60/0x236
|
||||
|
||||
stack backtrace:
|
||||
Pid: 2137, comm: keyctl-session- Not tainted 2.6.36-rc2-cachefs+ #1
|
||||
Call Trace:
|
||||
[<ffffffff8105606a>] lockdep_rcu_dereference+0xaa/0xb3
|
||||
[<ffffffff811ae379>] keyctl_session_to_parent+0xed/0x236
|
||||
[<ffffffff811af77e>] sys_keyctl+0xb4/0xb6
|
||||
[<ffffffff81001eab>] system_call_fastpath+0x16/0x1b
|
||||
|
||||
The code should take the RCU read lock to make sure the parents credentials
|
||||
don't go away, even though it's holding a spinlock and has IRQ disabled.
|
||||
|
||||
Signed-off-by: David Howells <dhowells@redhat.com>
|
||||
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
Acked-by: Jeff Mahoney <jeffm@suse.com>
|
||||
---
|
||||
|
||||
security/keys/keyctl.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
--- a/security/keys/keyctl.c
|
||||
+++ b/security/keys/keyctl.c
|
||||
@@ -1259,6 +1259,7 @@ long keyctl_session_to_parent(void)
|
||||
keyring_r = NULL;
|
||||
|
||||
me = current;
|
||||
+ rcu_read_lock();
|
||||
write_lock_irq(&tasklist_lock);
|
||||
|
||||
parent = me->real_parent;
|
||||
@@ -1313,6 +1314,7 @@ long keyctl_session_to_parent(void)
|
||||
set_ti_thread_flag(task_thread_info(parent), TIF_NOTIFY_RESUME);
|
||||
|
||||
write_unlock_irq(&tasklist_lock);
|
||||
+ rcu_read_unlock();
|
||||
if (oldcred)
|
||||
put_cred(oldcred);
|
||||
return 0;
|
||||
@@ -1321,6 +1323,7 @@ already_same:
|
||||
ret = 0;
|
||||
not_permitted:
|
||||
write_unlock_irq(&tasklist_lock);
|
||||
+ rcu_read_unlock();
|
||||
put_cred(cred);
|
||||
return ret;
|
||||
|
@ -1,193 +0,0 @@
|
||||
From: Bernhard Walle <bwalle@suse.de>
|
||||
Subject: Fix performance regression on large IA64 systems
|
||||
References: bnc #469589
|
||||
Patch-mainline: no (and never will)
|
||||
|
||||
This patch tries to address a performance regression discovered by SGI.
|
||||
|
||||
Patch b60c1f6ffd88850079ae419aa933ab0eddbd5535 removes the call
|
||||
to note_interrupt() in __do_IRQ(). Patch d85a60d85ea5b7c597508c1510c88e657773d378
|
||||
adds it again. Because it's needed for irqpoll.
|
||||
|
||||
That patch now introduces a new parameter 'only_fixup' for note_interrupt().
|
||||
This parameter determines two cases:
|
||||
|
||||
TRUE => The function should be only executed when irqfixup is set.
|
||||
Either 'irqpoll' or 'irqfixup' directly set that.
|
||||
|
||||
FALSE => Just the behaviour as note_interrupt() always had.
|
||||
|
||||
Now the patch converts all calls of note_interrupt() to only_fixup=FALSE,
|
||||
except the call that has been removed by b60c1f6ffd88850079ae419aa933ab0eddbd5535.
|
||||
So that call is always done, but the body is only executed when either
|
||||
'irqpoll' or 'irqfixup' are specified.
|
||||
|
||||
This patch is not meant for mainline inclusion in the first run!
|
||||
|
||||
|
||||
Signed-off-by: Bernhard Walle <bwalle@suse.de>
|
||||
|
||||
---
|
||||
arch/arm/mach-ns9xxx/irq.c | 2 +-
|
||||
arch/powerpc/platforms/cell/interrupt.c | 2 +-
|
||||
drivers/mfd/ezx-pcap.c | 3 ++-
|
||||
drivers/mfd/twl4030-irq.c | 2 +-
|
||||
include/linux/irq.h | 2 +-
|
||||
kernel/irq/chip.c | 12 ++++++------
|
||||
kernel/irq/handle.c | 4 ++--
|
||||
kernel/irq/spurious.c | 10 +++++++++-
|
||||
8 files changed, 23 insertions(+), 14 deletions(-)
|
||||
|
||||
--- a/arch/arm/mach-ns9xxx/irq.c
|
||||
+++ b/arch/arm/mach-ns9xxx/irq.c
|
||||
@@ -85,7 +85,7 @@ static void handle_prio_irq(unsigned int
|
||||
/* XXX: There is no direct way to access noirqdebug, so check
|
||||
* unconditionally for spurious irqs...
|
||||
* Maybe this function should go to kernel/irq/chip.c? */
|
||||
- note_interrupt(irq, desc, action_ret);
|
||||
+ note_interrupt(irq, desc, action_ret, false);
|
||||
|
||||
raw_spin_lock(&desc->lock);
|
||||
desc->status &= ~IRQ_INPROGRESS;
|
||||
--- a/arch/powerpc/platforms/cell/interrupt.c
|
||||
+++ b/arch/powerpc/platforms/cell/interrupt.c
|
||||
@@ -268,7 +268,7 @@ static void handle_iic_irq(unsigned int
|
||||
raw_spin_unlock(&desc->lock);
|
||||
action_ret = handle_IRQ_event(irq, action);
|
||||
if (!noirqdebug)
|
||||
- note_interrupt(irq, desc, action_ret);
|
||||
+ note_interrupt(irq, desc, action_ret, false);
|
||||
raw_spin_lock(&desc->lock);
|
||||
|
||||
} while ((desc->status & (IRQ_PENDING | IRQ_DISABLED)) == IRQ_PENDING);
|
||||
--- a/drivers/mfd/ezx-pcap.c
|
||||
+++ b/drivers/mfd/ezx-pcap.c
|
||||
@@ -203,7 +203,8 @@ static void pcap_isr_work(struct work_st
|
||||
break;
|
||||
|
||||
if (desc->status & IRQ_DISABLED)
|
||||
- note_interrupt(irq, desc, IRQ_NONE);
|
||||
+ note_interrupt(irq, desc, IRQ_NONE,
|
||||
+ false);
|
||||
else
|
||||
desc->handle_irq(irq, desc);
|
||||
}
|
||||
--- a/drivers/mfd/twl4030-irq.c
|
||||
+++ b/drivers/mfd/twl4030-irq.c
|
||||
@@ -330,7 +330,7 @@ static int twl4030_irq_thread(void *data
|
||||
*/
|
||||
if (d->status & IRQ_DISABLED)
|
||||
note_interrupt(module_irq, d,
|
||||
- IRQ_NONE);
|
||||
+ IRQ_NONE, false);
|
||||
else
|
||||
d->handle_irq(module_irq, d);
|
||||
}
|
||||
--- a/include/linux/irq.h
|
||||
+++ b/include/linux/irq.h
|
||||
@@ -324,7 +324,7 @@ static inline void generic_handle_irq(un
|
||||
|
||||
/* Handling of unhandled and spurious interrupts: */
|
||||
extern void note_interrupt(unsigned int irq, struct irq_desc *desc,
|
||||
- irqreturn_t action_ret);
|
||||
+ irqreturn_t action_ret, bool only_fixup);
|
||||
|
||||
/* Resending of interrupts :*/
|
||||
void check_irq_resend(struct irq_desc *desc, unsigned int irq);
|
||||
--- a/kernel/irq/chip.c
|
||||
+++ b/kernel/irq/chip.c
|
||||
@@ -390,7 +390,7 @@ void handle_nested_irq(unsigned int irq)
|
||||
|
||||
action_ret = action->thread_fn(action->irq, action->dev_id);
|
||||
if (!noirqdebug)
|
||||
- note_interrupt(irq, desc, action_ret);
|
||||
+ note_interrupt(irq, desc, action_ret, false);
|
||||
|
||||
raw_spin_lock_irq(&desc->lock);
|
||||
desc->status &= ~IRQ_INPROGRESS;
|
||||
@@ -434,7 +434,7 @@ handle_simple_irq(unsigned int irq, stru
|
||||
|
||||
action_ret = handle_IRQ_event(irq, action);
|
||||
if (!noirqdebug)
|
||||
- note_interrupt(irq, desc, action_ret);
|
||||
+ note_interrupt(irq, desc, action_ret, false);
|
||||
|
||||
raw_spin_lock(&desc->lock);
|
||||
desc->status &= ~IRQ_INPROGRESS;
|
||||
@@ -479,7 +479,7 @@ handle_level_irq(unsigned int irq, struc
|
||||
|
||||
action_ret = handle_IRQ_event(irq, action);
|
||||
if (!noirqdebug)
|
||||
- note_interrupt(irq, desc, action_ret);
|
||||
+ note_interrupt(irq, desc, action_ret, false);
|
||||
|
||||
raw_spin_lock(&desc->lock);
|
||||
desc->status &= ~IRQ_INPROGRESS;
|
||||
@@ -535,7 +535,7 @@ handle_fasteoi_irq(unsigned int irq, str
|
||||
|
||||
action_ret = handle_IRQ_event(irq, action);
|
||||
if (!noirqdebug)
|
||||
- note_interrupt(irq, desc, action_ret);
|
||||
+ note_interrupt(irq, desc, action_ret, false);
|
||||
|
||||
raw_spin_lock(&desc->lock);
|
||||
desc->status &= ~IRQ_INPROGRESS;
|
||||
@@ -613,7 +613,7 @@ handle_edge_irq(unsigned int irq, struct
|
||||
raw_spin_unlock(&desc->lock);
|
||||
action_ret = handle_IRQ_event(irq, action);
|
||||
if (!noirqdebug)
|
||||
- note_interrupt(irq, desc, action_ret);
|
||||
+ note_interrupt(irq, desc, action_ret, false);
|
||||
raw_spin_lock(&desc->lock);
|
||||
|
||||
} while ((desc->status & (IRQ_PENDING | IRQ_DISABLED)) == IRQ_PENDING);
|
||||
@@ -642,7 +642,7 @@ handle_percpu_irq(unsigned int irq, stru
|
||||
|
||||
action_ret = handle_IRQ_event(irq, desc->action);
|
||||
if (!noirqdebug)
|
||||
- note_interrupt(irq, desc, action_ret);
|
||||
+ note_interrupt(irq, desc, action_ret, false);
|
||||
|
||||
if (desc->chip->eoi)
|
||||
desc->chip->eoi(irq);
|
||||
--- a/kernel/irq/handle.c
|
||||
+++ b/kernel/irq/handle.c
|
||||
@@ -465,7 +465,7 @@ unsigned int __do_IRQ(unsigned int irq)
|
||||
if (likely(!(desc->status & IRQ_DISABLED))) {
|
||||
action_ret = handle_IRQ_event(irq, desc->action);
|
||||
if (!noirqdebug)
|
||||
- note_interrupt(irq, desc, action_ret);
|
||||
+ note_interrupt(irq, desc, action_ret, true);
|
||||
}
|
||||
desc->chip->end(irq);
|
||||
return 1;
|
||||
@@ -519,7 +519,7 @@ unsigned int __do_IRQ(unsigned int irq)
|
||||
|
||||
action_ret = handle_IRQ_event(irq, action);
|
||||
if (!noirqdebug)
|
||||
- note_interrupt(irq, desc, action_ret);
|
||||
+ note_interrupt(irq, desc, action_ret, false);
|
||||
|
||||
raw_spin_lock(&desc->lock);
|
||||
if (likely(!(desc->status & IRQ_PENDING)))
|
||||
--- a/kernel/irq/spurious.c
|
||||
+++ b/kernel/irq/spurious.c
|
||||
@@ -213,9 +213,17 @@ try_misrouted_irq(unsigned int irq, stru
|
||||
return action && (action->flags & IRQF_IRQPOLL);
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * The parameter "only_fixup" means that the function should be only executed
|
||||
+ * if this parameter is set either to false or to true simultaneously with
|
||||
+ * irqfixup enabled.
|
||||
+ */
|
||||
void note_interrupt(unsigned int irq, struct irq_desc *desc,
|
||||
- irqreturn_t action_ret)
|
||||
+ irqreturn_t action_ret, bool only_fixup)
|
||||
{
|
||||
+ if (only_fixup && irqfixup == 0)
|
||||
+ return;
|
||||
+
|
||||
if (unlikely(action_ret != IRQ_HANDLED)) {
|
||||
/*
|
||||
* If we are seeing only the odd spurious IRQ caused by
|
@ -0,0 +1,37 @@
|
||||
From: Vasiliy Kulikov <segoon@openwall.com>
|
||||
Date: Fri, 4 Feb 2011 09:23:33 -0300
|
||||
Subject: [media] video: sn9c102: world-wirtable sysfs files
|
||||
Patch-mainline: v2.6.39-rc2
|
||||
Git-commit: 14ddc3188d50855ae2a419a6aced995e2834e5d4
|
||||
Introduced-by: v2.6.8-rc2
|
||||
References: bnc#673934
|
||||
|
||||
Don't allow everybody to change video settings.
|
||||
|
||||
Signed-off-by: Vasiliy Kulikov <segoon@openwall.com>
|
||||
Acked-by: Mauro Carvalho Chehab <mchehab@redhat.com>
|
||||
Acked-by: Luca Risolia <luca.risolia@studio.unibo.it>
|
||||
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
|
||||
Acked-by: Jeff Mahoney <jeffm@suse.com>
|
||||
---
|
||||
drivers/media/video/sn9c102/sn9c102_core.c | 6 +++---
|
||||
1 files changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c
|
||||
index 84984f6..ce56a1c 100644
|
||||
--- a/drivers/media/video/sn9c102/sn9c102_core.c
|
||||
+++ b/drivers/media/video/sn9c102/sn9c102_core.c
|
||||
@@ -1430,9 +1430,9 @@ static DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR,
|
||||
sn9c102_show_i2c_reg, sn9c102_store_i2c_reg);
|
||||
static DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR,
|
||||
sn9c102_show_i2c_val, sn9c102_store_i2c_val);
|
||||
-static DEVICE_ATTR(green, S_IWUGO, NULL, sn9c102_store_green);
|
||||
-static DEVICE_ATTR(blue, S_IWUGO, NULL, sn9c102_store_blue);
|
||||
-static DEVICE_ATTR(red, S_IWUGO, NULL, sn9c102_store_red);
|
||||
+static DEVICE_ATTR(green, S_IWUSR, NULL, sn9c102_store_green);
|
||||
+static DEVICE_ATTR(blue, S_IWUSR, NULL, sn9c102_store_blue);
|
||||
+static DEVICE_ATTR(red, S_IWUSR, NULL, sn9c102_store_red);
|
||||
static DEVICE_ATTR(frame_header, S_IRUGO, sn9c102_show_frame_header, NULL);
|
||||
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue