nuke xenlinux kernel files
We've completly migrated to upstream kernel with pvops xen support.
This commit is contained in:
parent
ba8e92cb88
commit
65d700f5bb
4
Makefile
4
Makefile
@ -11,9 +11,7 @@ SOURCEDIR := $(WORKDIR)
|
||||
|
||||
NO_OF_CPUS := $(shell grep -c ^processor /proc/cpuinfo)
|
||||
|
||||
ifndef BUILD_FLAVOR
|
||||
$(error "Add BUILD_FLAVOR=pvops or BUILD_FLAVOR=xenlinux to make cmdline")
|
||||
endif
|
||||
BUILD_FLAVOR := pvops
|
||||
|
||||
RPM_DEFINES := --define "_sourcedir $(SOURCEDIR)" \
|
||||
--define "_specdir $(SPECDIR)" \
|
||||
|
5371
config-xenlinux
5371
config-xenlinux
File diff suppressed because it is too large
Load Diff
@ -1 +0,0 @@
|
||||
fa296255b40c9191589c0e35c2e11606a57751d3 linux-2.6.38.3.tar.bz2
|
@ -1,8 +0,0 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GnuPG v1.4.11 (GNU/Linux)
|
||||
Comment: See http://www.kernel.org/signature.html for info
|
||||
|
||||
iD8DBQBNp1wdyGugalF9Dw4RAg5cAJ4hXA7sV09J6xM9UhJ8iPz19FJQRQCgkHwx
|
||||
G/W+0jNvIVjd11rG2GPYddc=
|
||||
=kOWG
|
||||
-----END PGP SIGNATURE-----
|
@ -1,64 +0,0 @@
|
||||
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;
|
@ -1,379 +0,0 @@
|
||||
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 */
|
@ -1,518 +0,0 @@
|
||||
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,50 +0,0 @@
|
||||
From b134eac05adf33188616bf53ea38dc6c7ee487e8 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel J Blueman <daniel.blueman@gmail.com>
|
||||
Date: Wed, 18 May 2011 16:31:31 -0700
|
||||
Subject: [PATCH] x86, ioapic: Fix potential resume deadlock
|
||||
|
||||
commit b64ce24daffb634b5b3133a2e411bd4de50654e8 upstream.
|
||||
|
||||
Fix a potential deadlock when resuming; here the calling
|
||||
function has disabled interrupts, so we cannot sleep.
|
||||
|
||||
Change the memory allocation flag from GFP_KERNEL to GFP_ATOMIC.
|
||||
|
||||
TODO: We can do away with this memory allocation during resume
|
||||
by reusing the ioapic suspend/resume code that uses boot time
|
||||
allocated buffers, but we want to keep this -stable patch
|
||||
simple.
|
||||
|
||||
Signed-off-by: Daniel J Blueman <daniel.blueman@gmail.com>
|
||||
Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
|
||||
Link: http://lkml.kernel.org/r/20110518233157.385970138@sbsiddha-MOBL3.sc.intel.com
|
||||
Signed-off-by: Ingo Molnar <mingo@elte.hu>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
---
|
||||
arch/x86/kernel/apic/io_apic.c | 4 ++--
|
||||
1 files changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
|
||||
index ca9e2a35..e437778 100644
|
||||
--- a/arch/x86/kernel/apic/io_apic.c
|
||||
+++ b/arch/x86/kernel/apic/io_apic.c
|
||||
@@ -615,14 +615,14 @@ struct IO_APIC_route_entry **alloc_ioapic_entries(void)
|
||||
struct IO_APIC_route_entry **ioapic_entries;
|
||||
|
||||
ioapic_entries = kzalloc(sizeof(*ioapic_entries) * nr_ioapics,
|
||||
- GFP_KERNEL);
|
||||
+ GFP_ATOMIC);
|
||||
if (!ioapic_entries)
|
||||
return 0;
|
||||
|
||||
for (apic = 0; apic < nr_ioapics; apic++) {
|
||||
ioapic_entries[apic] =
|
||||
kzalloc(sizeof(struct IO_APIC_route_entry) *
|
||||
- nr_ioapic_registers[apic], GFP_KERNEL);
|
||||
+ nr_ioapic_registers[apic], GFP_ATOMIC);
|
||||
if (!ioapic_entries[apic])
|
||||
goto nomem;
|
||||
}
|
||||
--
|
||||
1.7.6.5
|
||||
|
@ -1,24 +0,0 @@
|
||||
From: Jeff Mahoney <jeffm@suse.com>
|
||||
Subject: acpi: export acpi_os_hotplug_execute
|
||||
Patch-mainline: not yet
|
||||
|
||||
The ACPI dock driver changes require acpi_os_hotplug_execute,
|
||||
which wasn't exported.
|
||||
|
||||
This patch exports it.
|
||||
|
||||
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
|
||||
---
|
||||
drivers/acpi/osl.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/drivers/acpi/osl.c
|
||||
+++ b/drivers/acpi/osl.c
|
||||
@@ -941,6 +941,7 @@ acpi_status acpi_os_hotplug_execute(acpi
|
||||
{
|
||||
return __acpi_os_execute(0, function, context, 1);
|
||||
}
|
||||
+EXPORT_SYMBOL(acpi_os_hotplug_execute);
|
||||
|
||||
void acpi_os_wait_events_complete(void *context)
|
||||
{
|
@ -1,67 +0,0 @@
|
||||
From: Alexey Starikovskiy <astarikovskiy@suse.de>
|
||||
Subject: ACPI: EC: Don't degrade to poll mode at storm automatically.
|
||||
References: bnc#446142
|
||||
Patch-Mainline: no
|
||||
|
||||
Signed-off-by: Thomas Renninger <trenn@suse.de>
|
||||
|
||||
Not all users of semi-broken EC devices want to degrade to poll mode, so
|
||||
give them right to choose.
|
||||
|
||||
Signed-off-by: Alexey Starikovskiy <astarikovskiy@suse.de>
|
||||
---
|
||||
|
||||
Documentation/kernel-parameters.txt | 5 +++++
|
||||
drivers/acpi/ec.c | 15 +++++++++++++++
|
||||
2 files changed, 20 insertions(+)
|
||||
|
||||
|
||||
--- a/Documentation/kernel-parameters.txt
|
||||
+++ b/Documentation/kernel-parameters.txt
|
||||
@@ -691,6 +691,11 @@ and is between 256 and 4096 characters.
|
||||
|
||||
eata= [HW,SCSI]
|
||||
|
||||
+ ec_intr= [HW,ACPI] ACPI Embedded Controller interrupt mode
|
||||
+ Format: <int>
|
||||
+ 0: polling mode
|
||||
+ non-0: interrupt mode (default)
|
||||
+
|
||||
edd= [EDD]
|
||||
Format: {"off" | "on" | "skip[mbr]"}
|
||||
|
||||
--- a/drivers/acpi/ec.c
|
||||
+++ b/drivers/acpi/ec.c
|
||||
@@ -118,6 +118,8 @@ static struct acpi_ec {
|
||||
spinlock_t curr_lock;
|
||||
} *boot_ec, *first_ec;
|
||||
|
||||
+int acpi_ec_intr = 1; /* Default is interrupt mode */
|
||||
+
|
||||
static int EC_FLAGS_MSI; /* Out-of-spec MSI controller */
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
@@ -754,6 +756,8 @@ static int ec_install_handlers(struct ac
|
||||
&acpi_ec_gpe_handler, ec);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -ENODEV;
|
||||
+ if (!acpi_ec_intr)
|
||||
+ set_bit(EC_FLAGS_NO_GPE, &ec->flags);
|
||||
acpi_set_gpe_type(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME);
|
||||
acpi_enable_gpe(NULL, ec->gpe);
|
||||
status = acpi_install_address_space_handler(ec->handle,
|
||||
@@ -1034,3 +1038,14 @@ static void __exit acpi_ec_exit(void)
|
||||
return;
|
||||
}
|
||||
#endif /* 0 */
|
||||
+
|
||||
+static int __init acpi_ec_set_intr_mode(char *str)
|
||||
+{
|
||||
+ if (!get_option(&str, &acpi_ec_intr)) {
|
||||
+ acpi_ec_intr = 0;
|
||||
+ return 0;
|
||||
+ }
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+__setup("ec_intr=", acpi_ec_set_intr_mode);
|
@ -1,30 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
From: Kurt Garloff <garloff@suse.de>
|
||||
Subject: Use SRAT table rev to use 8bit or 16/32bit PXM fields (ia64)
|
||||
References: bnc#503038
|
||||
Patch-mainline: not yet
|
||||
|
||||
In SRAT v1, we had 8bit proximity domain (PXM) fields; SRAT v2 provides
|
||||
32bits for these. The new fields were reserved before.
|
||||
According to the ACPI spec, the OS must disregrard reserved fields.
|
||||
|
||||
ia64 did handle the PXM fields almost consistently, but depending on
|
||||
sgi's sn2 platform. This patch leaves the sn2 logic in, but does also
|
||||
use 16/32 bits for PXM if the SRAT has rev 2 or higher.
|
||||
|
||||
The patch also adds __init to the two pxm accessor functions, as they
|
||||
access __initdata now and are called from an __init function only anyway.
|
||||
|
||||
Note that the code only uses 16 bits for the PXM field in the processor
|
||||
proximity field; the patch does not address this as 16 bits are more than
|
||||
enough.
|
||||
|
||||
This is patch 3/3.
|
||||
|
||||
Signed-off-by: Kurt Garloff <garloff@suse.de>
|
||||
|
||||
---
|
||||
arch/ia64/kernel/acpi.c | 10 ++++++----
|
||||
1 file changed, 6 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/arch/ia64/kernel/acpi.c
|
||||
+++ b/arch/ia64/kernel/acpi.c
|
||||
@@ -429,22 +429,24 @@ static u32 __devinitdata pxm_flag[PXM_FL
|
||||
static struct acpi_table_slit __initdata *slit_table;
|
||||
cpumask_t early_cpu_possible_map = CPU_MASK_NONE;
|
||||
|
||||
-static int get_processor_proximity_domain(struct acpi_srat_cpu_affinity *pa)
|
||||
+static int __init
|
||||
+get_processor_proximity_domain(struct acpi_srat_cpu_affinity *pa)
|
||||
{
|
||||
int pxm;
|
||||
|
||||
pxm = pa->proximity_domain_lo;
|
||||
- if (ia64_platform_is("sn2"))
|
||||
+ if (ia64_platform_is("sn2") || acpi_srat_revision >= 2)
|
||||
pxm += pa->proximity_domain_hi[0] << 8;
|
||||
return pxm;
|
||||
}
|
||||
|
||||
-static int get_memory_proximity_domain(struct acpi_srat_mem_affinity *ma)
|
||||
+static int __init
|
||||
+get_memory_proximity_domain(struct acpi_srat_mem_affinity *ma)
|
||||
{
|
||||
int pxm;
|
||||
|
||||
pxm = ma->proximity_domain;
|
||||
- if (!ia64_platform_is("sn2"))
|
||||
+ if (!ia64_platform_is("sn2") && acpi_srat_revision <= 1)
|
||||
pxm &= 0xff;
|
||||
|
||||
return pxm;
|
@ -1,52 +0,0 @@
|
||||
From: Kurt Garloff <garloff@suse.de>
|
||||
Subject: Store SRAT table revision
|
||||
References: bnc#503038
|
||||
Patch-mainline: not yet
|
||||
|
||||
In SRAT v1, we had 8bit proximity domain (PXM) fields; SRAT v2 provides
|
||||
32bits for these. The new fields were reserved before.
|
||||
According to the ACPI spec, the OS must disregrard reserved fields.
|
||||
In order to know whether or not, we must know what version the SRAT
|
||||
table has.
|
||||
|
||||
This patch stores the SRAT table revision for later consumption
|
||||
by arch specific __init functions.
|
||||
|
||||
This is patch 1/3.
|
||||
|
||||
Signed-off-by: Kurt Garloff <garloff@suse.de>
|
||||
|
||||
---
|
||||
drivers/acpi/numa.c | 3 +++
|
||||
include/acpi/acpi_numa.h | 1 +
|
||||
2 files changed, 4 insertions(+)
|
||||
|
||||
--- a/drivers/acpi/numa.c
|
||||
+++ b/drivers/acpi/numa.c
|
||||
@@ -45,6 +45,8 @@ static int pxm_to_node_map[MAX_PXM_DOMAI
|
||||
static int node_to_pxm_map[MAX_NUMNODES]
|
||||
= { [0 ... MAX_NUMNODES - 1] = PXM_INVAL };
|
||||
|
||||
+unsigned char acpi_srat_revision __initdata;
|
||||
+
|
||||
int pxm_to_node(int pxm)
|
||||
{
|
||||
if (pxm < 0)
|
||||
@@ -259,6 +261,7 @@ static int __init acpi_parse_srat(struct
|
||||
return -EINVAL;
|
||||
|
||||
/* Real work done in acpi_table_parse_srat below. */
|
||||
+ acpi_srat_revision = table->revision;
|
||||
|
||||
return 0;
|
||||
}
|
||||
--- a/include/acpi/acpi_numa.h
|
||||
+++ b/include/acpi/acpi_numa.h
|
||||
@@ -15,6 +15,7 @@ extern int pxm_to_node(int);
|
||||
extern int node_to_pxm(int);
|
||||
extern void __acpi_map_pxm_to_node(int, int);
|
||||
extern int acpi_map_pxm_to_node(int);
|
||||
+extern unsigned char acpi_srat_revision;
|
||||
|
||||
#endif /* CONFIG_ACPI_NUMA */
|
||||
#endif /* __ACP_NUMA_H */
|
@ -1,42 +0,0 @@
|
||||
From: Kurt Garloff <garloff@suse.de>
|
||||
Subject: Use SRAT table rev to use 8bit or 32bit PXM fields (x86-64)
|
||||
References: bnc#503038
|
||||
Patch-mainline: not yet
|
||||
|
||||
In SRAT v1, we had 8bit proximity domain (PXM) fields; SRAT v2 provides
|
||||
32bits for these. The new fields were reserved before.
|
||||
According to the ACPI spec, the OS must disregrard reserved fields.
|
||||
|
||||
x86-64 was rather inconsistent prior to this patch; it used 8 bits
|
||||
for the pxm field in cpu_affinity, but 32 bits in mem_affinity.
|
||||
This patch makes it consistent: Either use 8 bits consistently (SRAT
|
||||
rev 1 or lower) or 32 bits (SRAT rev 2 or higher).
|
||||
|
||||
This is patch 2/3.
|
||||
|
||||
Signed-off-by: Kurt Garloff <garloff@suse.de>
|
||||
|
||||
---
|
||||
arch/x86/mm/srat_64.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
--- a/arch/x86/mm/srat_64.c
|
||||
+++ b/arch/x86/mm/srat_64.c
|
||||
@@ -156,6 +156,8 @@ acpi_numa_processor_affinity_init(struct
|
||||
if ((pa->flags & ACPI_SRAT_CPU_ENABLED) == 0)
|
||||
return;
|
||||
pxm = pa->proximity_domain_lo;
|
||||
+ if (acpi_srat_revision >= 2)
|
||||
+ pxm |= *((unsigned int*)pa->proximity_domain_hi) << 8;
|
||||
node = setup_node(pxm);
|
||||
if (node < 0) {
|
||||
printk(KERN_ERR "SRAT: Too many proximity domains %x\n", pxm);
|
||||
@@ -259,6 +261,8 @@ acpi_numa_memory_affinity_init(struct ac
|
||||
start = ma->base_address;
|
||||
end = start + ma->length;
|
||||
pxm = ma->proximity_domain;
|
||||
+ if (acpi_srat_revision <= 1)
|
||||
+ pxm &= 0xff;
|
||||
node = setup_node(pxm);
|
||||
if (node < 0) {
|
||||
printk(KERN_ERR "SRAT: Too many proximity domains.\n");
|
@ -1,125 +0,0 @@
|
||||
From: Thomas Renninger <trenn@suse.de>
|
||||
Subject: Avoid critical temp shutdowns on specific ThinkPad T4x(p) and R40
|
||||
References: https://bugzilla.novell.com/show_bug.cgi?id=333043
|
||||
Patch-mainline: not yet
|
||||
|
||||
---
|
||||
drivers/acpi/thermal.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 93 insertions(+)
|
||||
|
||||
--- a/drivers/acpi/thermal.c
|
||||
+++ b/drivers/acpi/thermal.c
|
||||
@@ -41,6 +41,7 @@
|
||||
#include <linux/kmod.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/device.h>
|
||||
+#include <linux/dmi.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/thermal.h>
|
||||
#include <acpi/acpi_bus.h>
|
||||
@@ -984,6 +985,86 @@ static void acpi_thermal_guess_offset(st
|
||||
tz->kelvin_offset = 2732;
|
||||
}
|
||||
|
||||
+static struct dmi_system_id thermal_psv_dmi_table[] = {
|
||||
+ {
|
||||
+ .ident = "IBM ThinkPad T41",
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
|
||||
+ DMI_MATCH(DMI_PRODUCT_VERSION,"ThinkPad T41"),
|
||||
+ },
|
||||
+ },
|
||||
+ {
|
||||
+ .ident = "IBM ThinkPad T42",
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
|
||||
+ DMI_MATCH(DMI_PRODUCT_VERSION,"ThinkPad T42"),
|
||||
+ },
|
||||
+ },
|
||||
+ {
|
||||
+ .ident = "IBM ThinkPad T43",
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
|
||||
+ DMI_MATCH(DMI_PRODUCT_VERSION,"ThinkPad T43"),
|
||||
+ },
|
||||
+ },
|
||||
+ {
|
||||
+ .ident = "IBM ThinkPad T41p",
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
|
||||
+ DMI_MATCH(DMI_PRODUCT_VERSION,"ThinkPad T41p"),
|
||||
+ },
|
||||
+ },
|
||||
+ {
|
||||
+ .ident = "IBM ThinkPad T42p",
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
|
||||
+ DMI_MATCH(DMI_PRODUCT_VERSION,"ThinkPad T42p"),
|
||||
+ },
|
||||
+ },
|
||||
+ {
|
||||
+ .ident = "IBM ThinkPad T43p",
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
|
||||
+ DMI_MATCH(DMI_PRODUCT_VERSION,"ThinkPad T43p"),
|
||||
+ },
|
||||
+ },
|
||||
+ {
|
||||
+ .ident = "IBM ThinkPad R40",
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
|
||||
+ DMI_MATCH(DMI_PRODUCT_VERSION,"ThinkPad R40"),
|
||||
+ },
|
||||
+ },
|
||||
+ {
|
||||
+ .ident = "IBM ThinkPad R50p",
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
|
||||
+ DMI_MATCH(DMI_PRODUCT_VERSION,"ThinkPad R50p"),
|
||||
+ },
|
||||
+ },
|
||||
+ {},
|
||||
+};
|
||||
+
|
||||
+static int acpi_thermal_set_polling(struct acpi_thermal *tz, int seconds)
|
||||
+{
|
||||
+ if (!tz)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ /* Convert value to deci-seconds */
|
||||
+ tz->polling_frequency = seconds * 10;
|
||||
+
|
||||
+ tz->thermal_zone->polling_delay = seconds * 1000;
|
||||
+
|
||||
+ if (tz->tz_enabled)
|
||||
+ thermal_zone_device_update(tz->thermal_zone);
|
||||
+
|
||||
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
+ "Polling frequency set to %lu seconds\n",
|
||||
+ tz->polling_frequency/10));
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int acpi_thermal_add(struct acpi_device *device)
|
||||
{
|
||||
int result = 0;
|
||||
@@ -1015,6 +1096,18 @@ static int acpi_thermal_add(struct acpi_
|
||||
if (result)
|
||||
goto free_memory;
|
||||
|
||||
+ if (dmi_check_system(thermal_psv_dmi_table)) {
|
||||
+ if (tz->trips.passive.flags.valid &&
|
||||
+ tz->trips.passive.temperature > CELSIUS_TO_KELVIN(85)) {
|
||||
+ printk (KERN_INFO "Adjust passive trip point from %lu"
|
||||
+ " to %lu\n",
|
||||
+ KELVIN_TO_CELSIUS(tz->trips.passive.temperature),
|
||||
+ KELVIN_TO_CELSIUS(tz->trips.passive.temperature - 150));
|
||||
+ tz->trips.passive.temperature -= 150;
|
||||
+ acpi_thermal_set_polling(tz, 5);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
printk(KERN_INFO PREFIX "%s [%s] (%ld C)\n",
|
||||
acpi_device_name(device), acpi_device_bid(device),
|
||||
KELVIN_TO_CELSIUS(tz->temperature));
|
@ -1,118 +0,0 @@
|
||||
From: Thomas Renninger <trenn@suse.de>
|
||||
Subject: Introduce acpi_root_table=rsdt boot param and dmi list to force rsdt
|
||||
Patch-mainline: not yet
|
||||
References: http://bugzilla.kernel.org/show_bug.cgi?id=8246
|
||||
|
||||
This one is part of a patch series:
|
||||
acpi_thinkpad_introduce_acpi_root_table_boot_param.patch
|
||||
acpi_thinkpad_introduce_acpica_rsdt_global_variable.patch
|
||||
acpi_thinkpad_remove_R40e_c-state_blacklist.patch
|
||||
|
||||
Blacklist R40e, R51e and T40, T40p, T41, T41p, T42, T42p, R50 and R50p
|
||||
ThinkPads to use the RSDT instead of the XSDT.
|
||||
|
||||
Update: Jan 12 2009 jeffm
|
||||
* 2.6.29-rc1 introduced acpi_rsdt_forced. I've updated the patch to issue
|
||||
a warning that acpi=rsdt is the prefered method of forcing.
|
||||
* Moved the dmi table stuff to the main dmi table in x86/kernel/acpi/boot.
|
||||
|
||||
Update: Apr 10 2009 jeffm
|
||||
* Removed documentation, since it's deprecated.
|
||||
|
||||
Signed-off-by: Thomas Renninger <trenn@suse.de>
|
||||
Tested-by: Mark Doughty <me@markdoughty.co.uk>
|
||||
CC: Yakui Zhao <yakui.zhao@intel.com>
|
||||
|
||||
---
|
||||
arch/x86/kernel/acpi/boot.c | 53 ++++++++++++++++++++++++++++++++++++++++++++
|
||||
drivers/acpi/tables.c | 3 ++
|
||||
2 files changed, 56 insertions(+)
|
||||
|
||||
--- a/arch/x86/kernel/acpi/boot.c
|
||||
+++ b/arch/x86/kernel/acpi/boot.c
|
||||
@@ -1350,6 +1350,21 @@ static int __init dmi_ignore_irq0_timer_
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int __init force_acpi_rsdt(const struct dmi_system_id *d)
|
||||
+{
|
||||
+ if (!acpi_force) {
|
||||
+ printk(KERN_NOTICE "%s detected: force use of acpi=rsdt\n",
|
||||
+ d->ident);
|
||||
+ acpi_rsdt_forced = 1;
|
||||
+ } else {
|
||||
+ printk(KERN_NOTICE
|
||||
+ "Warning: acpi=force overrules DMI blacklist: "
|
||||
+ "acpi=rsdt\n");
|
||||
+ }
|
||||
+ return 0;
|
||||
+
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* If your system is blacklisted here, but you find that acpi=force
|
||||
* works for you, please contact linux-acpi@vger.kernel.org
|
||||
@@ -1425,6 +1440,32 @@ static struct dmi_system_id __initdata a
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
|
||||
},
|
||||
},
|
||||
+
|
||||
+ /*
|
||||
+ * Boxes that need RSDT as ACPI root table
|
||||
+ */
|
||||
+ {
|
||||
+ .callback = force_acpi_rsdt,
|
||||
+ .ident = "ThinkPad ", /* R40e, broken C-states */
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_BIOS_VENDOR, "IBM"),
|
||||
+ DMI_MATCH(DMI_BIOS_VERSION, "1SET")},
|
||||
+ },
|
||||
+ {
|
||||
+ .callback = force_acpi_rsdt,
|
||||
+ .ident = "ThinkPad ", /* R50e, slow booting */
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_BIOS_VENDOR, "IBM"),
|
||||
+ DMI_MATCH(DMI_BIOS_VERSION, "1WET")},
|
||||
+ },
|
||||
+ {
|
||||
+ .callback = force_acpi_rsdt,
|
||||
+ .ident = "ThinkPad ", /* T40, T40p, T41, T41p, T42, T42p
|
||||
+ R50, R50p */
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_BIOS_VENDOR, "IBM"),
|
||||
+ DMI_MATCH(DMI_BIOS_VERSION, "1RET")},
|
||||
+ },
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -1612,6 +1653,18 @@ static int __init parse_acpi(char *arg)
|
||||
}
|
||||
early_param("acpi", parse_acpi);
|
||||
|
||||
+/* Alias for acpi=rsdt for compatibility with openSUSE 11.1 and SLE11 */
|
||||
+static int __init parse_acpi_root_table(char *opt)
|
||||
+{
|
||||
+ if (!strcmp(opt, "rsdt")) {
|
||||
+ acpi_rsdt_forced = 1;
|
||||
+ printk(KERN_WARNING "acpi_root_table=rsdt is deprecated. "
|
||||
+ "Please use acpi=rsdt instead.\n");
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+early_param("acpi_root_table", parse_acpi_root_table);
|
||||
+
|
||||
/* FIXME: Using pci= for an ACPI parameter is a travesty. */
|
||||
static int __init parse_pci(char *arg)
|
||||
{
|
||||
--- a/drivers/acpi/tables.c
|
||||
+++ b/drivers/acpi/tables.c
|
||||
@@ -339,6 +339,9 @@ int __init acpi_table_init(void)
|
||||
{
|
||||
acpi_status status;
|
||||
|
||||
+ if (acpi_rsdt_forced)
|
||||
+ printk(KERN_INFO "Using RSDT as ACPI root table\n");
|
||||
+
|
||||
status = acpi_initialize_tables(initial_tables, ACPI_MAX_TABLES, 0);
|
||||
if (ACPI_FAILURE(status))
|
||||
return 1;
|
@ -1,15 +0,0 @@
|
||||
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)
|
@ -1,603 +0,0 @@
|
||||
From: Russ Anderson <rja@sgi.com>
|
||||
Subject: ia64: Call migration code on correctable errors v8
|
||||
References: 415829
|
||||
Acked-by: schwab@suse.de
|
||||
Patch-mainline: not yet
|
||||
|
||||
Migrate data off pages with correctable memory errors. This patch is the
|
||||
ia64 specific piece. It connects the CPE handler to the page migration
|
||||
code. It is implemented as a kernel loadable module, similar to the mca
|
||||
recovery code (mca_recovery.ko). This allows the feature to be turned off
|
||||
by uninstalling the module.
|
||||
|
||||
Update Jan 19 2009 jeffm:
|
||||
- isolate_lru_page doesn't put the page on a list anymore
|
||||
|
||||
|
||||
Signed-off-by: Russ Anderson <rja@sgi.com>
|
||||
|
||||
---
|
||||
arch/ia64/Kconfig | 9
|
||||
arch/ia64/include/asm/mca.h | 6
|
||||
arch/ia64/include/asm/page.h | 1
|
||||
arch/ia64/kernel/Makefile | 1
|
||||
arch/ia64/kernel/cpe_migrate.c | 434 +++++++++++++++++++++++++++++++++++++++++
|
||||
arch/ia64/kernel/mca.c | 37 +++
|
||||
6 files changed, 487 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/arch/ia64/Kconfig
|
||||
+++ b/arch/ia64/Kconfig
|
||||
@@ -511,6 +511,15 @@ config ARCH_PROC_KCORE_TEXT
|
||||
config IA64_MCA_RECOVERY
|
||||
tristate "MCA recovery from errors other than TLB."
|
||||
|
||||
+config IA64_CPE_MIGRATE
|
||||
+ tristate "Migrate data off pages with correctable errors"
|
||||
+ default m
|
||||
+ help
|
||||
+ Migrate data off pages with correctable memory errors. Selecting
|
||||
+ Y will build this functionality into the kernel. Selecting M will
|
||||
+ build this functionality as a kernel loadable module. Installing
|
||||
+ the module will turn on the functionality.
|
||||
+
|
||||
config PERFMON
|
||||
bool "Performance monitor support"
|
||||
help
|
||||
--- a/arch/ia64/include/asm/mca.h
|
||||
+++ b/arch/ia64/include/asm/mca.h
|
||||
@@ -142,6 +142,7 @@ extern unsigned long __per_cpu_mca[NR_CP
|
||||
|
||||
extern int cpe_vector;
|
||||
extern int ia64_cpe_irq;
|
||||
+extern int cpe_poll_enabled;
|
||||
extern void ia64_mca_init(void);
|
||||
extern void ia64_mca_cpu_init(void *);
|
||||
extern void ia64_os_mca_dispatch(void);
|
||||
@@ -156,11 +157,16 @@ extern void ia64_slave_init_handler(void
|
||||
extern void ia64_mca_cmc_vector_setup(void);
|
||||
extern int ia64_reg_MCA_extension(int (*fn)(void *, struct ia64_sal_os_state *));
|
||||
extern void ia64_unreg_MCA_extension(void);
|
||||
+extern int ia64_reg_CE_extension(int (*fn)(void *));
|
||||
+extern void ia64_unreg_CE_extension(void);
|
||||
extern unsigned long ia64_get_rnat(unsigned long *);
|
||||
extern void ia64_set_psr_mc(void);
|
||||
extern void ia64_mca_printk(const char * fmt, ...)
|
||||
__attribute__ ((format (printf, 1, 2)));
|
||||
|
||||
+extern struct list_head badpagelist;
|
||||
+extern unsigned int total_badpages;
|
||||
+
|
||||
struct ia64_mca_notify_die {
|
||||
struct ia64_sal_os_state *sos;
|
||||
int *monarch_cpu;
|
||||
--- a/arch/ia64/include/asm/page.h
|
||||
+++ b/arch/ia64/include/asm/page.h
|
||||
@@ -121,6 +121,7 @@ extern unsigned long max_low_pfn;
|
||||
#endif
|
||||
|
||||
#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
|
||||
+#define phys_to_page(kaddr) (pfn_to_page(kaddr >> PAGE_SHIFT))
|
||||
#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
|
||||
#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
|
||||
|
||||
--- a/arch/ia64/kernel/Makefile
|
||||
+++ b/arch/ia64/kernel/Makefile
|
||||
@@ -25,6 +25,7 @@ obj-$(CONFIG_PERFMON) += perfmon_defaul
|
||||
obj-$(CONFIG_IA64_CYCLONE) += cyclone.o
|
||||
obj-$(CONFIG_CPU_FREQ) += cpufreq/
|
||||
obj-$(CONFIG_IA64_MCA_RECOVERY) += mca_recovery.o
|
||||
+obj-$(CONFIG_IA64_CPE_MIGRATE) += cpe_migrate.o
|
||||
obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o
|
||||
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
|
||||
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o crash.o
|
||||
--- /dev/null
|
||||
+++ b/arch/ia64/kernel/cpe_migrate.c
|
||||
@@ -0,0 +1,434 @@
|
||||
+/*
|
||||
+ * File: cpe_migrate.c
|
||||
+ * Purpose: Migrate data from physical pages with excessive correctable
|
||||
+ * errors to new physical pages. Keep the old pages on a discard
|
||||
+ * list.
|
||||
+ *
|
||||
+ * Copyright (C) 2008 SGI - Silicon Graphics Inc.
|
||||
+ * Copyright (C) 2008 Russ Anderson <rja@sgi.com>
|
||||
+ */
|
||||
+
|
||||
+#include <linux/sysdev.h>
|
||||
+#include <linux/types.h>
|
||||
+#include <linux/sched.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/smp.h>
|
||||
+#include <linux/workqueue.h>
|
||||
+#include <linux/mm.h>
|
||||
+#include <linux/swap.h>
|
||||
+#include <linux/vmalloc.h>
|
||||
+#include <linux/migrate.h>
|
||||
+#include <linux/page-isolation.h>
|
||||
+#include <linux/memcontrol.h>
|
||||
+#include <linux/kobject.h>
|
||||
+
|
||||
+#include <asm/page.h>
|
||||
+#include <asm/system.h>
|
||||
+#include <asm/sn/sn_cpuid.h>
|
||||
+#include <asm/mca.h>
|
||||
+
|
||||
+#define BADRAM_BASENAME "badram"
|
||||
+#define CE_HISTORY_LENGTH 30
|
||||
+
|
||||
+struct cpe_info {
|
||||
+ u64 paddr;
|
||||
+ u16 node;
|
||||
+};
|
||||
+static struct cpe_info cpe[CE_HISTORY_LENGTH];
|
||||
+
|
||||
+static int cpe_polling_enabled = 1;
|
||||
+static int cpe_head;
|
||||
+static int cpe_tail;
|
||||
+static int work_scheduled;
|
||||
+static int mstat_cannot_isolate;
|
||||
+static int mstat_failed_to_discard;
|
||||
+static int mstat_already_marked;
|
||||
+static int mstat_already_on_list;
|
||||
+
|
||||
+DEFINE_SPINLOCK(cpe_migrate_lock);
|
||||
+
|
||||
+static void
|
||||
+get_physical_address(void *buffer, u64 *paddr, u16 *node)
|
||||
+{
|
||||
+ sal_log_record_header_t *rh;
|
||||
+ sal_log_mem_dev_err_info_t *mdei;
|
||||
+ ia64_err_rec_t *err_rec;
|
||||
+ sal_log_platform_err_info_t *plat_err;
|
||||
+ efi_guid_t guid;
|
||||
+
|
||||
+ err_rec = buffer;
|
||||
+ rh = &err_rec->sal_elog_header;
|
||||
+ *paddr = 0;
|
||||
+ *node = 0;
|
||||
+
|
||||
+ /*
|
||||
+ * Make sure it is a corrected error.
|
||||
+ */
|
||||
+ if (rh->severity != sal_log_severity_corrected)
|
||||
+ return;
|
||||
+
|
||||
+ plat_err = (sal_log_platform_err_info_t *)&err_rec->proc_err;
|
||||
+
|
||||
+ guid = plat_err->mem_dev_err.header.guid;
|
||||
+ if (efi_guidcmp(guid, SAL_PLAT_MEM_DEV_ERR_SECT_GUID) == 0) {
|
||||
+ /*
|
||||
+ * Memory cpe
|
||||
+ */
|
||||
+ mdei = &plat_err->mem_dev_err;
|
||||
+ if (mdei->valid.oem_data) {
|
||||
+ if (mdei->valid.physical_addr)
|
||||
+ *paddr = mdei->physical_addr;
|
||||
+
|
||||
+ if (mdei->valid.node) {
|
||||
+ if (ia64_platform_is("sn2"))
|
||||
+ *node = nasid_to_cnodeid(mdei->node);
|
||||
+ else
|
||||
+ *node = mdei->node;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static struct page *
|
||||
+alloc_migrate_page(struct page *ignored, unsigned long node, int **x)
|
||||
+{
|
||||
+
|
||||
+ return alloc_pages_node(node, GFP_HIGHUSER_MOVABLE, 0);
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+validate_paddr_page(u64 paddr)
|
||||
+{
|
||||
+ struct page *page;
|
||||
+
|
||||
+ if (!paddr)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (!ia64_phys_addr_valid(paddr))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (!pfn_valid(paddr >> PAGE_SHIFT))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ page = phys_to_page(paddr);
|
||||
+ if (PageMemError(page))
|
||||
+ mstat_already_marked++;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+extern int isolate_lru_page(struct page *);
|
||||
+static int
|
||||
+ia64_mca_cpe_move_page(u64 paddr, u32 node)
|
||||
+{
|
||||
+ LIST_HEAD(pagelist);
|
||||
+ struct page *page;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = validate_paddr_page(paddr);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ /*
|
||||
+ * convert physical address to page number
|
||||
+ */
|
||||
+ page = phys_to_page(paddr);
|
||||
+
|
||||
+ migrate_prep();
|
||||
+ ret = isolate_lru_page(page);
|
||||
+ if (ret) {
|
||||
+ mstat_cannot_isolate++;
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ list_add(&page->lru, &pagelist);
|
||||
+ ret = migrate_pages(&pagelist, alloc_migrate_page, node, 0, true);
|
||||
+ if (ret == 0) {
|
||||
+ total_badpages++;
|
||||
+ list_add_tail(&page->lru, &badpagelist);
|
||||
+ } else {
|
||||
+ mstat_failed_to_discard++;
|
||||
+ /*
|
||||
+ * The page failed to migrate and is not on the bad page list.
|
||||
+ * Clearing the error bit will allow another attempt to migrate
|
||||
+ * if it gets another correctable error.
|
||||
+ */
|
||||
+ ClearPageMemError(page);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * ia64_mca_cpe_migrate
|
||||
+ * The worker that does the actual migration. It pulls a
|
||||
+ * physical address off the list and calls the migration code.
|
||||
+ */
|
||||
+static void
|
||||
+ia64_mca_cpe_migrate(struct work_struct *unused)
|
||||
+{
|
||||
+ int ret;
|
||||
+ u64 paddr;
|
||||
+ u16 node;
|
||||
+
|
||||
+ do {
|
||||
+ paddr = cpe[cpe_tail].paddr;
|
||||
+ if (paddr) {
|
||||
+ /*
|
||||
+ * There is a valid entry that needs processing.
|
||||
+ */
|
||||
+ node = cpe[cpe_tail].node;
|
||||
+
|
||||
+ ret = ia64_mca_cpe_move_page(paddr, node);
|
||||
+ if (ret <= 0)
|
||||
+ /*
|
||||
+ * Even though the return status is negative,
|
||||
+ * clear the entry. If the same address has
|
||||
+ * another CPE it will be re-added to the list.
|
||||
+ */
|
||||
+ cpe[cpe_tail].paddr = 0;
|
||||
+
|
||||
+ }
|
||||
+ if (++cpe_tail >= CE_HISTORY_LENGTH)
|
||||
+ cpe_tail = 0;
|
||||
+
|
||||
+ } while (cpe_tail != cpe_head);
|
||||
+ work_scheduled = 0;
|
||||
+}
|
||||
+
|
||||
+static DECLARE_WORK(cpe_enable_work, ia64_mca_cpe_migrate);
|
||||
+DEFINE_SPINLOCK(cpe_list_lock);
|
||||
+
|
||||
+/*
|
||||
+ * cpe_setup_migrate
|
||||
+ * Get the physical address out of the CPE record, add it
|
||||
+ * to the list of addresses to migrate (if not already on),
|
||||
+ * and schedule the back end worker task. This is called
|
||||
+ * in interrupt context so cannot directly call the migration
|
||||
+ * code.
|
||||
+ *
|
||||
+ * Inputs
|
||||
+ * rec The CPE record
|
||||
+ * Outputs
|
||||
+ * 1 on Success, -1 on failure
|
||||
+ */
|
||||
+static int
|
||||
+cpe_setup_migrate(void *rec)
|
||||
+{
|
||||
+ u64 paddr;
|
||||
+ u16 node;
|
||||
+ /* int head, tail; */
|
||||
+ int i, ret;
|
||||
+
|
||||
+ if (!rec)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ get_physical_address(rec, &paddr, &node);
|
||||
+ ret = validate_paddr_page(paddr);
|
||||
+ if (ret < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if ((cpe_head != cpe_tail) || (cpe[cpe_head].paddr != 0))
|
||||
+ /*
|
||||
+ * List not empty
|
||||
+ */
|
||||
+ for (i = 0; i < CE_HISTORY_LENGTH; i++) {
|
||||
+ if (PAGE_ALIGN(cpe[i].paddr) == PAGE_ALIGN(paddr)) {
|
||||
+ mstat_already_on_list++;
|
||||
+ return 1; /* already on the list */
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!spin_trylock(&cpe_list_lock)) {
|
||||
+ /*
|
||||
+ * Someone else has the lock. To avoid spinning in interrupt
|
||||
+ * handler context, bail.
|
||||
+ */
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ if (cpe[cpe_head].paddr == 0) {
|
||||
+ cpe[cpe_head].node = node;
|
||||
+ cpe[cpe_head].paddr = paddr;
|
||||
+
|
||||
+ if (++cpe_head >= CE_HISTORY_LENGTH)
|
||||
+ cpe_head = 0;
|
||||
+ }
|
||||
+ spin_unlock(&cpe_list_lock);
|
||||
+
|
||||
+ if (!work_scheduled) {
|
||||
+ work_scheduled = 1;
|
||||
+ schedule_work(&cpe_enable_work);
|
||||
+ }
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * =============================================================================
|
||||
+ */
|
||||
+
|
||||
+/*
|
||||
+ * free_one_bad_page
|
||||
+ * Free one page from the list of bad pages.
|
||||
+ */
|
||||
+static int
|
||||
+free_one_bad_page(unsigned long paddr)
|
||||
+{
|
||||
+ LIST_HEAD(pagelist);
|
||||
+ struct page *page, *page2, *target;
|
||||
+
|
||||
+ /*
|
||||
+ * Verify page address
|
||||
+ */
|
||||
+ target = phys_to_page(paddr);
|
||||
+ list_for_each_entry_safe(page, page2, &badpagelist, lru) {
|
||||
+ if (page != target)
|
||||
+ continue;
|
||||
+
|
||||
+ ClearPageMemError(page); /* Mark the page as good */
|
||||
+ total_badpages--;
|
||||
+ list_move_tail(&page->lru, &pagelist);
|
||||
+ putback_lru_pages(&pagelist);
|
||||
+ break;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * free_all_bad_pages
|
||||
+ * Free all of the pages on the bad pages list.
|
||||
+ */
|
||||
+static int
|
||||
+free_all_bad_pages(void)
|
||||
+{
|
||||
+ struct page *page, *page2;
|
||||
+
|
||||
+ list_for_each_entry_safe(page, page2, &badpagelist, lru) {
|
||||
+ ClearPageMemError(page); /* Mark the page as good */
|
||||
+ total_badpages--;
|
||||
+ }
|
||||
+ putback_lru_pages(&badpagelist);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#define OPT_LEN 16
|
||||
+
|
||||
+static ssize_t
|
||||
+badpage_store(struct kobject *kobj,
|
||||
+ struct kobj_attribute *attr, const char *buf, size_t count)
|
||||
+{
|
||||
+ char optstr[OPT_LEN];
|
||||
+ unsigned long opt;
|
||||
+ int len = OPT_LEN;
|
||||
+ int err;
|
||||
+
|
||||
+ if (count < len)
|
||||
+ len = count;
|
||||
+
|
||||
+ strlcpy(optstr, buf, len);
|
||||
+
|
||||
+ err = strict_strtoul(optstr, 16, &opt);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ if (opt == 0)
|
||||
+ free_all_bad_pages();
|
||||
+ else
|
||||
+ free_one_bad_page(opt);
|
||||
+
|
||||
+ return count;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * badpage_show
|
||||
+ * Display the number, size, and addresses of all the pages on the
|
||||
+ * bad page list.
|
||||
+ *
|
||||
+ * Note that sysfs provides buf of PAGE_SIZE length. bufend tracks
|
||||
+ * the remaining space in buf to avoid overflowing.
|
||||
+ */
|
||||
+static ssize_t
|
||||
+badpage_show(struct kobject *kobj,
|
||||
+ struct kobj_attribute *attr, char *buf)
|
||||
+
|
||||
+{
|
||||
+ struct page *page, *page2;
|
||||
+ int i = 0, cnt = 0;
|
||||
+ char *bufend = buf + PAGE_SIZE;
|
||||
+
|
||||
+ cnt = snprintf(buf, bufend - (buf + cnt),
|
||||
+ "Memory marked bad: %d kB\n"
|
||||
+ "Pages marked bad: %d\n"
|
||||
+ "Unable to isolate on LRU: %d\n"
|
||||
+ "Unable to migrate: %d\n"
|
||||
+ "Already marked bad: %d\n"
|
||||
+ "Already on list: %d\n"
|
||||
+ "List of bad physical pages\n",
|
||||
+ total_badpages << (PAGE_SHIFT - 10), total_badpages,
|
||||
+ mstat_cannot_isolate, mstat_failed_to_discard,
|
||||
+ mstat_already_marked, mstat_already_on_list
|
||||
+ );
|
||||
+
|
||||
+ list_for_each_entry_safe(page, page2, &badpagelist, lru) {
|
||||
+ if (bufend - (buf + cnt) < 20)
|
||||
+ break; /* Avoid overflowing the buffer */
|
||||
+ cnt += snprintf(buf + cnt, bufend - (buf + cnt),
|
||||
+ " 0x%011lx", page_to_phys(page));
|
||||
+ if (!(++i % 5))
|
||||
+ cnt += snprintf(buf + cnt, bufend - (buf + cnt), "\n");
|
||||
+ }
|
||||
+ cnt += snprintf(buf + cnt, bufend - (buf + cnt), "\n");
|
||||
+
|
||||
+ return cnt;
|
||||
+}
|
||||
+
|
||||
+static struct kobj_attribute badram_attr = {
|
||||
+ .attr = {
|
||||
+ .name = "badram",
|
||||
+ .mode = S_IWUSR | S_IRUGO,
|
||||
+ },
|
||||
+ .show = badpage_show,
|
||||
+ .store = badpage_store,
|
||||
+};
|
||||
+
|
||||
+static int __init
|
||||
+cpe_migrate_external_handler_init(void)
|
||||
+{
|
||||
+ int error;
|
||||
+
|
||||
+ error = sysfs_create_file(kernel_kobj, &badram_attr.attr);
|
||||
+ if (error)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ /*
|
||||
+ * register external ce handler
|
||||
+ */
|
||||
+ if (ia64_reg_CE_extension(cpe_setup_migrate)) {
|
||||
+ printk(KERN_ERR "ia64_reg_CE_extension failed.\n");
|
||||
+ return -EFAULT;
|
||||
+ }
|
||||
+ cpe_poll_enabled = cpe_polling_enabled;
|
||||
+
|
||||
+ printk(KERN_INFO "Registered badram Driver\n");
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void __exit
|
||||
+cpe_migrate_external_handler_exit(void)
|
||||
+{
|
||||
+ /* unregister external mca handlers */
|
||||
+ ia64_unreg_CE_extension();
|
||||
+
|
||||
+ sysfs_remove_file(kernel_kobj, &badram_attr.attr);
|
||||
+}
|
||||
+
|
||||
+module_init(cpe_migrate_external_handler_init);
|
||||
+module_exit(cpe_migrate_external_handler_exit);
|
||||
+
|
||||
+module_param(cpe_polling_enabled, int, 0644);
|
||||
+MODULE_PARM_DESC(cpe_polling_enabled,
|
||||
+ "Enable polling with migration");
|
||||
+
|
||||
+MODULE_AUTHOR("Russ Anderson <rja@sgi.com>");
|
||||
+MODULE_DESCRIPTION("ia64 Corrected Error page migration driver");
|
||||
--- a/arch/ia64/kernel/mca.c
|
||||
+++ b/arch/ia64/kernel/mca.c
|
||||
@@ -68,6 +68,9 @@
|
||||
*
|
||||
* 2007-04-27 Russ Anderson <rja@sgi.com>
|
||||
* Support multiple cpus going through OS_MCA in the same event.
|
||||
+ *
|
||||
+ * 2008-04-22 Russ Anderson <rja@sgi.com>
|
||||
+ * Migrate data off pages with correctable memory errors.
|
||||
*/
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/types.h>
|
||||
@@ -164,7 +167,14 @@ static int cmc_polling_enabled = 1;
|
||||
* but encounters problems retrieving CPE logs. This should only be
|
||||
* necessary for debugging.
|
||||
*/
|
||||
-static int cpe_poll_enabled = 1;
|
||||
+int cpe_poll_enabled = 1;
|
||||
+EXPORT_SYMBOL(cpe_poll_enabled);
|
||||
+
|
||||
+unsigned int total_badpages;
|
||||
+EXPORT_SYMBOL(total_badpages);
|
||||
+
|
||||
+LIST_HEAD(badpagelist);
|
||||
+EXPORT_SYMBOL(badpagelist);
|
||||
|
||||
extern void salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe);
|
||||
|
||||
@@ -524,6 +534,28 @@ int mca_recover_range(unsigned long addr
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mca_recover_range);
|
||||
|
||||
+/* Function pointer to Corrected Error memory migration driver */
|
||||
+int (*ia64_mca_ce_extension)(void *);
|
||||
+
|
||||
+int
|
||||
+ia64_reg_CE_extension(int (*fn)(void *))
|
||||
+{
|
||||
+ if (ia64_mca_ce_extension)
|
||||
+ return 1;
|
||||
+
|
||||
+ ia64_mca_ce_extension = fn;
|
||||
+ return 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL(ia64_reg_CE_extension);
|
||||
+
|
||||
+void
|
||||
+ia64_unreg_CE_extension(void)
|
||||
+{
|
||||
+ if (ia64_mca_ce_extension)
|
||||
+ ia64_mca_ce_extension = NULL;
|
||||
+}
|
||||
+EXPORT_SYMBOL(ia64_unreg_CE_extension);
|
||||
+
|
||||
#ifdef CONFIG_ACPI
|
||||
|
||||
int cpe_vector = -1;
|
||||
@@ -535,6 +567,7 @@ ia64_mca_cpe_int_handler (int cpe_irq, v
|
||||
static unsigned long cpe_history[CPE_HISTORY_LENGTH];
|
||||
static int index;
|
||||
static DEFINE_SPINLOCK(cpe_history_lock);
|
||||
+ int recover;
|
||||
|
||||
IA64_MCA_DEBUG("%s: received interrupt vector = %#x on CPU %d\n",
|
||||
__func__, cpe_irq, smp_processor_id());
|
||||
@@ -581,6 +614,8 @@ ia64_mca_cpe_int_handler (int cpe_irq, v
|
||||
out:
|
||||
/* Get the CPE error record and log it */
|
||||
ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CPE);
|
||||
+ recover = (ia64_mca_ce_extension && ia64_mca_ce_extension(
|
||||
+ IA64_LOG_CURR_BUFFER(SAL_INFO_TYPE_CPE)));
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
@ -1,159 +0,0 @@
|
||||
From: Russ Anderson <rja@sgi.com>
|
||||
Subject: ia64: cpe_migrate.ko causes deadlock.
|
||||
References: bnc#464676
|
||||
Patch-mainline: not yet, depends on patches.arch/ia64-page-migration
|
||||
|
||||
schedule_on_each_cpu() deadlocks when called from an event thread.
|
||||
Change cpe_migrate to use a kthread to avoid the problem.
|
||||
|
||||
Signed-off-by: Russ Anderson <rja@sgi.com>
|
||||
Acked-by: Raymund Will <rw@suse.de>
|
||||
|
||||
---
|
||||
arch/ia64/kernel/cpe_migrate.c | 72 +++++++++++++++++++++++++++++++----------
|
||||
1 file changed, 56 insertions(+), 16 deletions(-)
|
||||
|
||||
--- a/arch/ia64/kernel/cpe_migrate.c
|
||||
+++ b/arch/ia64/kernel/cpe_migrate.c
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <linux/page-isolation.h>
|
||||
#include <linux/memcontrol.h>
|
||||
#include <linux/kobject.h>
|
||||
+#include <linux/kthread.h>
|
||||
|
||||
#include <asm/page.h>
|
||||
#include <asm/system.h>
|
||||
@@ -40,12 +41,15 @@ static struct cpe_info cpe[CE_HISTORY_LE
|
||||
static int cpe_polling_enabled = 1;
|
||||
static int cpe_head;
|
||||
static int cpe_tail;
|
||||
-static int work_scheduled;
|
||||
static int mstat_cannot_isolate;
|
||||
static int mstat_failed_to_discard;
|
||||
static int mstat_already_marked;
|
||||
static int mstat_already_on_list;
|
||||
|
||||
+/* IRQ handler notifies this wait queue on receipt of an IRQ */
|
||||
+DECLARE_WAIT_QUEUE_HEAD(cpe_activate_IRQ_wq);
|
||||
+static DECLARE_COMPLETION(kthread_cpe_migrated_exited);
|
||||
+int cpe_active;
|
||||
DEFINE_SPINLOCK(cpe_migrate_lock);
|
||||
|
||||
static void
|
||||
@@ -160,12 +164,12 @@ ia64_mca_cpe_move_page(u64 paddr, u32 no
|
||||
}
|
||||
|
||||
/*
|
||||
- * ia64_mca_cpe_migrate
|
||||
- * The worker that does the actual migration. It pulls a
|
||||
- * physical address off the list and calls the migration code.
|
||||
+ * cpe_process_queue
|
||||
+ * Pulls the physical address off the list and calls the migration code.
|
||||
+ * Will process all the addresses on the list.
|
||||
*/
|
||||
-static void
|
||||
-ia64_mca_cpe_migrate(struct work_struct *unused)
|
||||
+void
|
||||
+cpe_process_queue(void)
|
||||
{
|
||||
int ret;
|
||||
u64 paddr;
|
||||
@@ -193,10 +197,36 @@ ia64_mca_cpe_migrate(struct work_struct
|
||||
cpe_tail = 0;
|
||||
|
||||
} while (cpe_tail != cpe_head);
|
||||
- work_scheduled = 0;
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
+inline int
|
||||
+cpe_list_empty(void)
|
||||
+{
|
||||
+ return (cpe_head == cpe_tail) && (!cpe[cpe_head].paddr);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * kthread_cpe_migrate
|
||||
+ * kthread_cpe_migrate is created at module load time and lives
|
||||
+ * until the module is removed. When not active, it will sleep.
|
||||
+ */
|
||||
+static int
|
||||
+kthread_cpe_migrate(void *ignore)
|
||||
+{
|
||||
+ while (cpe_active) {
|
||||
+ /*
|
||||
+ * wait for work
|
||||
+ */
|
||||
+ (void)wait_event_interruptible(cpe_activate_IRQ_wq,
|
||||
+ (!cpe_list_empty() ||
|
||||
+ !cpe_active));
|
||||
+ cpe_process_queue(); /* process work */
|
||||
+ }
|
||||
+ complete(&kthread_cpe_migrated_exited);
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
-static DECLARE_WORK(cpe_enable_work, ia64_mca_cpe_migrate);
|
||||
DEFINE_SPINLOCK(cpe_list_lock);
|
||||
|
||||
/*
|
||||
@@ -228,10 +258,7 @@ cpe_setup_migrate(void *rec)
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
|
||||
- if ((cpe_head != cpe_tail) || (cpe[cpe_head].paddr != 0))
|
||||
- /*
|
||||
- * List not empty
|
||||
- */
|
||||
+ if (!cpe_list_empty())
|
||||
for (i = 0; i < CE_HISTORY_LENGTH; i++) {
|
||||
if (PAGE_ALIGN(cpe[i].paddr) == PAGE_ALIGN(paddr)) {
|
||||
mstat_already_on_list++;
|
||||
@@ -256,10 +283,7 @@ cpe_setup_migrate(void *rec)
|
||||
}
|
||||
spin_unlock(&cpe_list_lock);
|
||||
|
||||
- if (!work_scheduled) {
|
||||
- work_scheduled = 1;
|
||||
- schedule_work(&cpe_enable_work);
|
||||
- }
|
||||
+ wake_up_interruptible(&cpe_activate_IRQ_wq);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -396,12 +420,23 @@ static int __init
|
||||
cpe_migrate_external_handler_init(void)
|
||||
{
|
||||
int error;
|
||||
+ struct task_struct *kthread;
|
||||
|
||||
error = sysfs_create_file(kernel_kobj, &badram_attr.attr);
|
||||
if (error)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
+ * set up the kthread
|
||||
+ */
|
||||
+ cpe_active = 1;
|
||||
+ kthread = kthread_run(kthread_cpe_migrate, NULL, "cpe_migrate");
|
||||
+ if (IS_ERR(kthread)) {
|
||||
+ complete(&kthread_cpe_migrated_exited);
|
||||
+ return -EFAULT;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
* register external ce handler
|
||||
*/
|
||||
if (ia64_reg_CE_extension(cpe_setup_migrate)) {
|
||||
@@ -420,6 +455,11 @@ cpe_migrate_external_handler_exit(void)
|
||||
/* unregister external mca handlers */
|
||||
ia64_unreg_CE_extension();
|
||||
|
||||
+ /* Stop kthread */
|
||||
+ cpe_active = 0; /* tell kthread_cpe_migrate to exit */
|
||||
+ wake_up_interruptible(&cpe_activate_IRQ_wq);
|
||||
+ wait_for_completion(&kthread_cpe_migrated_exited);
|
||||
+
|
||||
sysfs_remove_file(kernel_kobj, &badram_attr.attr);
|
||||
}
|
||||
|
@ -1,54 +0,0 @@
|
||||
From: Jeff Mahoney <jeffm@suse.com>
|
||||
Subject: kmsg: Fix parameter limitations
|
||||
Patch-mainline: Whenever kmsg is upstream
|
||||
|
||||
The kmsg infrastructure, currently only employed on s/390, has limitations
|
||||
with the parameters it can handle due to the way it assembles the
|
||||
magic string for parsing with scripts/kmsg-doc.
|
||||
|
||||
cpp expects the result to be a valid expression and exits with an error
|
||||
if it is not.
|
||||
|
||||
The netfilter ipvs code causes this error, though there are more examples:
|
||||
error: pasting "_ARGS_" and "&" does not give a valid preprocessing token
|
||||
|
||||
This stems from an otherwise valid expression:
|
||||
pr_info("Registered protocols (%s)\n", &protocols[2]);
|
||||
|
||||
It tries to concatenate _ARGS_ and &protocols[2] and fails.
|
||||
|
||||
This patch fixes the issue by stringifying the entire parameter list
|
||||
and allowing kmsg-doc to unquote the resultant expression.
|
||||
|
||||
The dev_* expressions that evaluate to __KMSG_DEV are unaffected because
|
||||
the insertion of the "dev, " between _ARGS_ and the parameter list ends
|
||||
up creating a valid expression.
|
||||
|
||||
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
|
||||
---
|
||||
include/linux/printk.h | 2 +-
|
||||
scripts/kmsg-doc | 2 +-
|
||||
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/include/linux/printk.h
|
||||
+++ b/include/linux/printk.h
|
||||
@@ -416,7 +416,7 @@ extern int hex_to_bin(char ch);
|
||||
|
||||
/* generate magic string for scripts/kmsg-doc to parse */
|
||||
#define pr_printk_hash(level, format, ...) \
|
||||
- __KMSG_PRINT(level _FMT_ format _ARGS_ ##__VA_ARGS__ _END_)
|
||||
+ __KMSG_PRINT(level _FMT_ format _ARGS_ #__VA_ARGS__ _END_)
|
||||
|
||||
#elif defined(CONFIG_KMSG_IDS) && defined(KMSG_COMPONENT)
|
||||
|
||||
--- a/scripts/kmsg-doc
|
||||
+++ b/scripts/kmsg-doc
|
||||
@@ -307,7 +307,7 @@ sub process_cpp_file($$$$)
|
||||
|
||||
while (<FD>) {
|
||||
chomp;
|
||||
- if (/.*__KMSG_PRINT\(\s*(\S*)\s*_FMT_(.*)_ARGS_\s*(.*)?_END_\s*\)/o) {
|
||||
+ if (/.*__KMSG_PRINT\(\s*(\S*)\s*_FMT_(.*)_ARGS_\s*"(.*)"\s*_END_\s*\)/o) {
|
||||
if ($component ne "") {
|
||||
add_kmsg_print($component, $1, $2, $3);
|
||||
} else {
|
@ -1,139 +0,0 @@
|
||||
From: Alexander Graf <agraf@suse.de>
|
||||
Date: Wed, 18 Nov 2009 00:39:12 +0100
|
||||
Subject: Only export selected pv-ops feature structs
|
||||
References: bnc#556135, FATE#306453
|
||||
Patch-Mainline: Submitted to virtualization list
|
||||
|
||||
To really check for sure that we're not using any pv-ops code by accident,
|
||||
we should make sure that we don't even export the structures used to access
|
||||
pv-ops exported functions.
|
||||
|
||||
So let's surround the pv-ops structs by #ifdefs.
|
||||
|
||||
Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
---
|
||||
arch/x86/kernel/paravirt.c | 35 +++++++++++++++++++++++++++++------
|
||||
1 file changed, 29 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/arch/x86/kernel/paravirt.c
|
||||
+++ b/arch/x86/kernel/paravirt.c
|
||||
@@ -124,11 +124,21 @@ static void *get_call_destination(u8 typ
|
||||
{
|
||||
struct paravirt_patch_template tmpl = {
|
||||
.pv_init_ops = pv_init_ops,
|
||||
+#ifdef CONFIG_PARAVIRT_TIME
|
||||
.pv_time_ops = pv_time_ops,
|
||||
+#endif
|
||||
+#ifdef CONFIG_PARAVIRT_CPU
|
||||
.pv_cpu_ops = pv_cpu_ops,
|
||||
+#endif
|
||||
+#ifdef CONFIG_PARAVIRT_IRQ
|
||||
.pv_irq_ops = pv_irq_ops,
|
||||
+#endif
|
||||
+#ifdef CONFIG_PARAVIRT_APIC
|
||||
.pv_apic_ops = pv_apic_ops,
|
||||
+#endif
|
||||
+#ifdef CONFIG_PARAVIRT_MMU
|
||||
.pv_mmu_ops = pv_mmu_ops,
|
||||
+#endif
|
||||
#ifdef CONFIG_PARAVIRT_SPINLOCKS
|
||||
.pv_lock_ops = pv_lock_ops,
|
||||
#endif
|
||||
@@ -185,6 +195,7 @@ unsigned paravirt_patch_insns(void *insn
|
||||
return insn_len;
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_PARAVIRT_MMU
|
||||
static void native_flush_tlb(void)
|
||||
{
|
||||
__native_flush_tlb();
|
||||
@@ -203,6 +214,7 @@ static void native_flush_tlb_single(unsi
|
||||
{
|
||||
__native_flush_tlb_single(addr);
|
||||
}
|
||||
+#endif /* CONFIG_PARAVIRT_MMU */
|
||||
|
||||
/* These are in entry.S */
|
||||
extern void native_iret(void);
|
||||
@@ -284,6 +296,7 @@ enum paravirt_lazy_mode paravirt_get_laz
|
||||
return percpu_read(paravirt_lazy_mode);
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_PARAVIRT_MMU
|
||||
void arch_flush_lazy_mmu_mode(void)
|
||||
{
|
||||
preempt_disable();
|
||||
@@ -295,6 +308,7 @@ void arch_flush_lazy_mmu_mode(void)
|
||||
|
||||
preempt_enable();
|
||||
}
|
||||
+#endif /* CONFIG_PARAVIRT_MMU */
|
||||
|
||||
struct pv_info pv_info = {
|
||||
.name = "bare hardware",
|
||||
@@ -306,11 +320,16 @@ struct pv_info pv_info = {
|
||||
struct pv_init_ops pv_init_ops = {
|
||||
.patch = native_patch,
|
||||
};
|
||||
+EXPORT_SYMBOL_GPL(pv_info);
|
||||
|
||||
+#ifdef CONFIG_PARAVIRT_TIME
|
||||
struct pv_time_ops pv_time_ops = {
|
||||
.sched_clock = native_sched_clock,
|
||||
};
|
||||
+EXPORT_SYMBOL_GPL(pv_time_ops);
|
||||
+#endif
|
||||
|
||||
+#ifdef CONFIG_PARAVIRT_IRQ
|
||||
struct pv_irq_ops pv_irq_ops = {
|
||||
.save_fl = __PV_IS_CALLEE_SAVE(native_save_fl),
|
||||
.restore_fl = __PV_IS_CALLEE_SAVE(native_restore_fl),
|
||||
@@ -322,7 +341,10 @@ struct pv_irq_ops pv_irq_ops = {
|
||||
.adjust_exception_frame = paravirt_nop,
|
||||
#endif
|
||||
};
|
||||
+EXPORT_SYMBOL (pv_irq_ops);
|
||||
+#endif
|
||||
|
||||
+#ifdef CONFIG_PARAVIRT_CPU
|
||||
struct pv_cpu_ops pv_cpu_ops = {
|
||||
.cpuid = native_cpuid,
|
||||
.get_debugreg = native_get_debugreg,
|
||||
@@ -383,12 +405,17 @@ struct pv_cpu_ops pv_cpu_ops = {
|
||||
.start_context_switch = paravirt_nop,
|
||||
.end_context_switch = paravirt_nop,
|
||||
};
|
||||
+EXPORT_SYMBOL (pv_cpu_ops);
|
||||
+#endif
|
||||
|
||||
+#ifdef CONFIG_PARAVIRT_APIC
|
||||
struct pv_apic_ops pv_apic_ops = {
|
||||
#ifdef CONFIG_X86_LOCAL_APIC
|
||||
.startup_ipi_hook = paravirt_nop,
|
||||
#endif
|
||||
};
|
||||
+EXPORT_SYMBOL_GPL(pv_apic_ops);
|
||||
+#endif
|
||||
|
||||
#if defined(CONFIG_X86_32) && !defined(CONFIG_X86_PAE)
|
||||
/* 32-bit pagetable entries */
|
||||
@@ -398,6 +425,7 @@ struct pv_apic_ops pv_apic_ops = {
|
||||
#define PTE_IDENT __PV_IS_CALLEE_SAVE(_paravirt_ident_64)
|
||||
#endif
|
||||
|
||||
+#ifdef CONFIG_PARAVIRT_MMU
|
||||
struct pv_mmu_ops pv_mmu_ops = {
|
||||
|
||||
.read_cr2 = native_read_cr2,
|
||||
@@ -466,10 +494,5 @@ struct pv_mmu_ops pv_mmu_ops = {
|
||||
|
||||
.set_fixmap = native_set_fixmap,
|
||||
};
|
||||
-
|
||||
-EXPORT_SYMBOL_GPL(pv_time_ops);
|
||||
-EXPORT_SYMBOL (pv_cpu_ops);
|
||||
EXPORT_SYMBOL (pv_mmu_ops);
|
||||
-EXPORT_SYMBOL_GPL(pv_apic_ops);
|
||||
-EXPORT_SYMBOL_GPL(pv_info);
|
||||
-EXPORT_SYMBOL (pv_irq_ops);
|
||||
+#endif
|
@ -1,80 +0,0 @@
|
||||
From: Alexander Graf <agraf@suse.de>
|
||||
Date: Wed, 18 Nov 2009 12:58:00 +0100
|
||||
Subject: Replace kvm io delay pv-ops with linux magic
|
||||
References: bnc#556135, FATE#306453
|
||||
Patch-Mainline: Submitted to virtualization list
|
||||
|
||||
Currently we use pv-ops to tell linux not to do anything on io_delay.
|
||||
|
||||
While the basic idea is good IMHO, I don't see why we would need pv-ops
|
||||
for that. The io delay function already has a switch that can do nothing
|
||||
if you're so inclined.
|
||||
|
||||
So here's a patch (stacked on top of the previous pv-ops series) that
|
||||
removes the io delay pv-ops hook and just sets the native io delay
|
||||
variable instead.
|
||||
|
||||
Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
---
|
||||
arch/x86/Kconfig | 14 --------------
|
||||
arch/x86/kernel/kvm.c | 16 +++-------------
|
||||
2 files changed, 3 insertions(+), 27 deletions(-)
|
||||
|
||||
--- a/arch/x86/Kconfig
|
||||
+++ b/arch/x86/Kconfig
|
||||
@@ -548,20 +548,6 @@ config KVM_GUEST
|
||||
This option enables various optimizations for running under the KVM
|
||||
hypervisor.
|
||||
|
||||
-config KVM_IODELAY
|
||||
- bool "KVM IO-delay support"
|
||||
- depends on KVM_GUEST
|
||||
- select PARAVIRT_CPU
|
||||
- ---help---
|
||||
- Usually we wait for PIO access to complete. When inside KVM there's
|
||||
- no need to do that, as we know that we're not going through a bus,
|
||||
- but process PIO requests instantly.
|
||||
-
|
||||
- This option disables PIO waits, but drags in CPU-bound pv-ops. Thus
|
||||
- you will probably get more speed loss than speedup using this option.
|
||||
-
|
||||
- If in doubt, say N.
|
||||
-
|
||||
config KVM_MMU
|
||||
bool "KVM PV MMU support"
|
||||
depends on KVM_GUEST
|
||||
--- a/arch/x86/kernel/kvm.c
|
||||
+++ b/arch/x86/kernel/kvm.c
|
||||
@@ -29,15 +29,6 @@
|
||||
#include <asm/desc.h>
|
||||
#include <asm/tlbflush.h>
|
||||
|
||||
-#ifdef CONFIG_KVM_IODELAY
|
||||
-/*
|
||||
- * No need for any "IO delay" on KVM
|
||||
- */
|
||||
-static void kvm_io_delay(void)
|
||||
-{
|
||||
-}
|
||||
-#endif /* CONFIG_KVM_IODELAY */
|
||||
-
|
||||
#ifdef CONFIG_KVM_MMU
|
||||
#define MMU_QUEUE_SIZE 1024
|
||||
|
||||
@@ -201,13 +192,12 @@ static void kvm_leave_lazy_mmu(void)
|
||||
|
||||
static void __init paravirt_ops_setup(void)
|
||||
{
|
||||
+ extern int io_delay_type;
|
||||
pv_info.name = "KVM";
|
||||
pv_info.paravirt_enabled = 1;
|
||||
|
||||
-#ifdef CONFIG_KVM_IODELAY
|
||||
- if (kvm_para_has_feature(KVM_FEATURE_NOP_IO_DELAY))
|
||||
- pv_cpu_ops.io_delay = kvm_io_delay;
|
||||
-#endif
|
||||
+ /* Disable IO delay */
|
||||
+ io_delay_type = CONFIG_IO_DELAY_TYPE_NONE;
|
||||
|
||||
#ifdef CONFIG_KVM_MMU
|
||||
if (kvm_para_has_feature(KVM_FEATURE_MMU_OP)) {
|
@ -1,728 +0,0 @@
|
||||
From: Alexander Graf <agraf@suse.de>
|
||||
Date: Wed, 18 Nov 2009 00:27:59 +0100
|
||||
Subject: Split paravirt ops by functionality
|
||||
References: bnc#556135, FATE#306453
|
||||
Patch-Mainline: Submitted to virtualization list
|
||||
|
||||
Currently when using paravirt ops it's an all-or-nothing option. We can either
|
||||
use pv-ops for CPU, MMU, timing, etc. or not at all.
|
||||
|
||||
Now there are some use cases where we don't need the full feature set, but only
|
||||
a small chunk of it. KVM is a pretty prominent example for this.
|
||||
|
||||
So let's make everything a bit more fine-grained. We already have a splitting
|
||||
by function groups, namely "cpu", "mmu", "time", "irq", "apic" and "spinlock".
|
||||
|
||||
Taking that existing splitting and extending it to only compile in the PV
|
||||
capable bits sounded like a natural fit. That way we don't get performance hits
|
||||
in MMU code from using the KVM PV clock which only needs the TIME parts of
|
||||
pv-ops.
|
||||
|
||||
We define a new CONFIG_PARAVIRT_ALL option that basically does the same thing
|
||||
the CONFIG_PARAVIRT did before this splitting. We move all users of
|
||||
CONFIG_PARAVIRT to CONFIG_PARAVIRT_ALL, so they behave the same way they did
|
||||
before.
|
||||
|
||||
So here it is - the splitting! I would have made the patch smaller, but this
|
||||
was the closest I could get to atomic (for bisect) while staying sane.
|
||||
|
||||
Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
---
|
||||
arch/x86/Kconfig | 41 +++++++++++++++++++++++---
|
||||
arch/x86/include/asm/apic.h | 2 -
|
||||
arch/x86/include/asm/desc.h | 4 +-
|
||||
arch/x86/include/asm/fixmap.h | 2 -
|
||||
arch/x86/include/asm/io.h | 2 -
|
||||
arch/x86/include/asm/irqflags.h | 21 ++++++++++---
|
||||
arch/x86/include/asm/mmu_context.h | 4 +-
|
||||
arch/x86/include/asm/msr.h | 4 +-
|
||||
arch/x86/include/asm/paravirt.h | 44 ++++++++++++++++++++++++++--
|
||||
arch/x86/include/asm/paravirt_types.h | 12 +++++++
|
||||
arch/x86/include/asm/pgalloc.h | 2 -
|
||||
arch/x86/include/asm/pgtable-3level_types.h | 2 -
|
||||
arch/x86/include/asm/pgtable.h | 2 -
|
||||
arch/x86/include/asm/processor.h | 2 -
|
||||
arch/x86/include/asm/required-features.h | 2 -
|
||||
arch/x86/include/asm/smp.h | 2 -
|
||||
arch/x86/include/asm/system.h | 13 +++++---
|
||||
arch/x86/include/asm/tlbflush.h | 4 +-
|
||||
arch/x86/kernel/head_64.S | 2 -
|
||||
arch/x86/kernel/paravirt.c | 2 +
|
||||
arch/x86/kernel/tsc.c | 2 -
|
||||
arch/x86/kernel/vsmp_64.c | 2 -
|
||||
arch/x86/kernel/x8664_ksyms_64.c | 2 -
|
||||
arch/x86/xen/Kconfig | 2 -
|
||||
24 files changed, 140 insertions(+), 37 deletions(-)
|
||||
|
||||
--- a/arch/x86/Kconfig
|
||||
+++ b/arch/x86/Kconfig
|
||||
@@ -367,7 +367,7 @@ endif
|
||||
config X86_VSMP
|
||||
bool "ScaleMP vSMP"
|
||||
select PARAVIRT_GUEST
|
||||
- select PARAVIRT
|
||||
+ select PARAVIRT_ALL
|
||||
depends on X86_64 && PCI
|
||||
depends on X86_EXTENDED_PLATFORM
|
||||
---help---
|
||||
@@ -533,7 +533,6 @@ config VMI
|
||||
|
||||
config KVM_CLOCK
|
||||
bool "KVM paravirtualized clock"
|
||||
- select PARAVIRT
|
||||
select PARAVIRT_CLOCK
|
||||
---help---
|
||||
Turning on this option will allow you to run a paravirtualized clock
|
||||
@@ -544,7 +543,7 @@ config KVM_CLOCK
|
||||
|
||||
config KVM_GUEST
|
||||
bool "KVM Guest support"
|
||||
- select PARAVIRT
|
||||
+ select PARAVIRT_ALL
|
||||
---help---
|
||||
This option enables various optimizations for running under the KVM
|
||||
hypervisor.
|
||||
@@ -572,8 +571,42 @@ config PARAVIRT_SPINLOCKS
|
||||
|
||||
If you are unsure how to answer this question, answer N.
|
||||
|
||||
+config PARAVIRT_CPU
|
||||
+ bool
|
||||
+ select PARAVIRT
|
||||
+
|
||||
+config PARAVIRT_TIME
|
||||
+ bool
|
||||
+ select PARAVIRT
|
||||
+
|
||||
+config PARAVIRT_IRQ
|
||||
+ bool
|
||||
+ select PARAVIRT
|
||||
+
|
||||
+config PARAVIRT_APIC
|
||||
+ bool
|
||||
+ select PARAVIRT
|
||||
+
|
||||
+config PARAVIRT_MMU
|
||||
+ bool
|
||||
+ select PARAVIRT
|
||||
+
|
||||
+#
|
||||
+# This is a placeholder to activate the old "include all pv-ops functionality"
|
||||
+# behavior. If you're using this I'd recommend looking through your code to see
|
||||
+# if you can be more specific. It probably saves you a few cycles!
|
||||
+#
|
||||
+config PARAVIRT_ALL
|
||||
+ bool
|
||||
+ select PARAVIRT_CPU
|
||||
+ select PARAVIRT_TIME
|
||||
+ select PARAVIRT_IRQ
|
||||
+ select PARAVIRT_APIC
|
||||
+ select PARAVIRT_MMU
|
||||
+
|
||||
config PARAVIRT_CLOCK
|
||||
bool
|
||||
+ select PARAVIRT_TIME
|
||||
|
||||
endif
|
||||
|
||||
--- a/arch/x86/include/asm/apic.h
|
||||
+++ b/arch/x86/include/asm/apic.h
|
||||
@@ -81,7 +81,7 @@ static inline bool apic_from_smp_config(
|
||||
/*
|
||||
* Basic functions accessing APICs.
|
||||
*/
|
||||
-#ifdef CONFIG_PARAVIRT
|
||||
+#ifdef CONFIG_PARAVIRT_APIC
|
||||
#include <asm/paravirt.h>
|
||||
#endif
|
||||
|
||||
--- a/arch/x86/include/asm/desc.h
|
||||
+++ b/arch/x86/include/asm/desc.h
|
||||
@@ -78,7 +78,7 @@ static inline int desc_empty(const void
|
||||
return !(desc[0] | desc[1]);
|
||||
}
|
||||
|
||||
-#ifdef CONFIG_PARAVIRT
|
||||
+#ifdef CONFIG_PARAVIRT_CPU
|
||||
#include <asm/paravirt.h>
|
||||
#else
|
||||
#define load_TR_desc() native_load_tr_desc()
|
||||
@@ -108,7 +108,7 @@ static inline void paravirt_alloc_ldt(st
|
||||
static inline void paravirt_free_ldt(struct desc_struct *ldt, unsigned entries)
|
||||
{
|
||||
}
|
||||
-#endif /* CONFIG_PARAVIRT */
|
||||
+#endif /* CONFIG_PARAVIRT_CPU */
|
||||
|
||||
#define store_ldt(ldt) asm("sldt %0" : "=m"(ldt))
|
||||
|
||||
--- a/arch/x86/include/asm/fixmap.h
|
||||
+++ b/arch/x86/include/asm/fixmap.h
|
||||
@@ -162,7 +162,7 @@ void __native_set_fixmap(enum fixed_addr
|
||||
void native_set_fixmap(enum fixed_addresses idx,
|
||||
phys_addr_t phys, pgprot_t flags);
|
||||
|
||||
-#ifndef CONFIG_PARAVIRT
|
||||
+#ifndef CONFIG_PARAVIRT_MMU
|
||||
static inline void __set_fixmap(enum fixed_addresses idx,
|
||||
phys_addr_t phys, pgprot_t flags)
|
||||
{
|
||||
--- a/arch/x86/include/asm/io.h
|
||||
+++ b/arch/x86/include/asm/io.h
|
||||
@@ -268,7 +268,7 @@ extern void native_io_delay(void);
|
||||
extern int io_delay_type;
|
||||
extern void io_delay_init(void);
|
||||
|
||||
-#if defined(CONFIG_PARAVIRT)
|
||||
+#if defined(CONFIG_PARAVIRT_CPU)
|
||||
#include <asm/paravirt.h>
|
||||
#else
|
||||
|
||||
--- a/arch/x86/include/asm/irqflags.h
|
||||
+++ b/arch/x86/include/asm/irqflags.h
|
||||
@@ -58,9 +58,11 @@ static inline void native_halt(void)
|
||||
|
||||
#ifdef CONFIG_PARAVIRT
|
||||
#include <asm/paravirt.h>
|
||||
-#else
|
||||
+#endif
|
||||
+
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
+#ifndef CONFIG_PARAVIRT_IRQ
|
||||
static inline unsigned long arch_local_save_flags(void)
|
||||
{
|
||||
return native_save_fl();
|
||||
@@ -110,12 +112,17 @@ static inline unsigned long __raw_local_
|
||||
arch_local_irq_disable();
|
||||
return flags;
|
||||
}
|
||||
-#else
|
||||
+#endif /* CONFIG_PARAVIRT_IRQ */
|
||||
+
|
||||
+#else /* __ASSEMBLY__ */
|
||||
|
||||
+#ifndef CONFIG_PARAVIRT_IRQ
|
||||
#define ENABLE_INTERRUPTS(x) sti
|
||||
#define DISABLE_INTERRUPTS(x) cli
|
||||
+#endif /* !CONFIG_PARAVIRT_IRQ */
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
+#ifndef CONFIG_PARAVIRT_CPU
|
||||
#define SWAPGS swapgs
|
||||
/*
|
||||
* Currently paravirt can't handle swapgs nicely when we
|
||||
@@ -128,8 +135,6 @@ static inline unsigned long __raw_local_
|
||||
*/
|
||||
#define SWAPGS_UNSAFE_STACK swapgs
|
||||
|
||||
-#define PARAVIRT_ADJUST_EXCEPTION_FRAME /* */
|
||||
-
|
||||
#define INTERRUPT_RETURN iretq
|
||||
#define USERGS_SYSRET64 \
|
||||
swapgs; \
|
||||
@@ -141,16 +146,22 @@ static inline unsigned long __raw_local_
|
||||
swapgs; \
|
||||
sti; \
|
||||
sysexit
|
||||
+#endif /* !CONFIG_PARAVIRT_CPU */
|
||||
+
|
||||
+#ifndef CONFIG_PARAVIRT_IRQ
|
||||
+#define PARAVIRT_ADJUST_EXCEPTION_FRAME /* */
|
||||
+#endif /* !CONFIG_PARAVIRT_IRQ */
|
||||
|
||||
#else
|
||||
+#ifndef CONFIG_PARAVIRT_CPU
|
||||
#define INTERRUPT_RETURN iret
|
||||
#define ENABLE_INTERRUPTS_SYSEXIT sti; sysexit
|
||||
#define GET_CR0_INTO_EAX movl %cr0, %eax
|
||||
+#endif /* !CONFIG_PARAVIRT_CPU */
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
-#endif /* CONFIG_PARAVIRT */
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
static inline int arch_irqs_disabled_flags(unsigned long flags)
|
||||
--- a/arch/x86/include/asm/mmu_context.h
|
||||
+++ b/arch/x86/include/asm/mmu_context.h
|
||||
@@ -6,14 +6,14 @@
|
||||
#include <asm/pgalloc.h>
|
||||
#include <asm/tlbflush.h>
|
||||
#include <asm/paravirt.h>
|
||||
-#ifndef CONFIG_PARAVIRT
|
||||
+#ifndef CONFIG_PARAVIRT_MMU
|
||||
#include <asm-generic/mm_hooks.h>
|
||||
|
||||
static inline void paravirt_activate_mm(struct mm_struct *prev,
|
||||
struct mm_struct *next)
|
||||
{
|
||||
}
|
||||
-#endif /* !CONFIG_PARAVIRT */
|
||||
+#endif /* !CONFIG_PARAVIRT_MMU */
|
||||
|
||||
/*
|
||||
* Used for LDT copy/destruction.
|
||||
--- a/arch/x86/include/asm/msr.h
|
||||
+++ b/arch/x86/include/asm/msr.h
|
||||
@@ -135,7 +135,7 @@ static inline unsigned long long native_
|
||||
return EAX_EDX_VAL(val, low, high);
|
||||
}
|
||||
|
||||
-#ifdef CONFIG_PARAVIRT
|
||||
+#ifdef CONFIG_PARAVIRT_CPU
|
||||
#include <asm/paravirt.h>
|
||||
#else
|
||||
#include <linux/errno.h>
|
||||
@@ -246,7 +246,7 @@ do {
|
||||
|
||||
#define rdtscpll(val, aux) (val) = native_read_tscp(&(aux))
|
||||
|
||||
-#endif /* !CONFIG_PARAVIRT */
|
||||
+#endif /* !CONFIG_PARAVIRT_CPU */
|
||||
|
||||
|
||||
#define checking_wrmsrl(msr, val) wrmsr_safe((msr), (u32)(val), \
|
||||
--- a/arch/x86/include/asm/paravirt.h
|
||||
+++ b/arch/x86/include/asm/paravirt.h
|
||||
@@ -18,6 +18,7 @@ static inline int paravirt_enabled(void)
|
||||
return pv_info.paravirt_enabled;
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_PARAVIRT_CPU
|
||||
static inline void load_sp0(struct tss_struct *tss,
|
||||
struct thread_struct *thread)
|
||||
{
|
||||
@@ -58,7 +59,9 @@ static inline void write_cr0(unsigned lo
|
||||
{
|
||||
PVOP_VCALL1(pv_cpu_ops.write_cr0, x);
|
||||
}
|
||||
+#endif /* CONFIG_PARAVIRT_CPU */
|
||||
|
||||
+#ifdef CONFIG_PARAVIRT_MMU
|
||||
static inline unsigned long read_cr2(void)
|
||||
{
|
||||
return PVOP_CALL0(unsigned long, pv_mmu_ops.read_cr2);
|
||||
@@ -78,7 +81,9 @@ static inline void write_cr3(unsigned lo
|
||||
{
|
||||
PVOP_VCALL1(pv_mmu_ops.write_cr3, x);
|
||||
}
|
||||
+#endif /* CONFIG_PARAVIRT_MMU */
|
||||
|
||||
+#ifdef CONFIG_PARAVIRT_CPU
|
||||
static inline unsigned long read_cr4(void)
|
||||
{
|
||||
return PVOP_CALL0(unsigned long, pv_cpu_ops.read_cr4);
|
||||
@@ -92,8 +97,9 @@ static inline void write_cr4(unsigned lo
|
||||
{
|
||||
PVOP_VCALL1(pv_cpu_ops.write_cr4, x);
|
||||
}
|
||||
+#endif /* CONFIG_PARAVIRT_CPU */
|
||||
|
||||
-#ifdef CONFIG_X86_64
|
||||
+#if defined(CONFIG_X86_64) && defined(CONFIG_PARAVIRT_CPU)
|
||||
static inline unsigned long read_cr8(void)
|
||||
{
|
||||
return PVOP_CALL0(unsigned long, pv_cpu_ops.read_cr8);
|
||||
@@ -105,6 +111,7 @@ static inline void write_cr8(unsigned lo
|
||||
}
|
||||
#endif
|
||||
|
||||
+#ifdef CONFIG_PARAVIRT_IRQ
|
||||
static inline void arch_safe_halt(void)
|
||||
{
|
||||
PVOP_VCALL0(pv_irq_ops.safe_halt);
|
||||
@@ -114,14 +121,18 @@ static inline void halt(void)
|
||||
{
|
||||
PVOP_VCALL0(pv_irq_ops.halt);
|
||||
}
|
||||
+#endif /* CONFIG_PARAVIRT_IRQ */
|
||||
|
||||
+#ifdef CONFIG_PARAVIRT_CPU
|
||||
static inline void wbinvd(void)
|
||||
{
|
||||
PVOP_VCALL0(pv_cpu_ops.wbinvd);
|
||||
}
|
||||
+#endif
|
||||
|
||||
#define get_kernel_rpl() (pv_info.kernel_rpl)
|
||||
|
||||
+#ifdef CONFIG_PARAVIRT_CPU
|
||||
static inline u64 paravirt_read_msr(unsigned msr, int *err)
|
||||
{
|
||||
return PVOP_CALL2(u64, pv_cpu_ops.read_msr, msr, err);
|
||||
@@ -224,12 +235,16 @@ do { \
|
||||
} while (0)
|
||||
|
||||
#define rdtscll(val) (val = paravirt_read_tsc())
|
||||
+#endif /* CONFIG_PARAVIRT_CPU */
|
||||
|
||||
+#ifdef CONFIG_PARAVIRT_TIME
|
||||
static inline unsigned long long paravirt_sched_clock(void)
|
||||
{
|
||||
return PVOP_CALL0(unsigned long long, pv_time_ops.sched_clock);
|
||||
}
|
||||
+#endif /* CONFIG_PARAVIRT_TIME */
|
||||
|
||||
+#ifdef CONFIG_PARAVIRT_CPU
|
||||
static inline unsigned long long paravirt_read_pmc(int counter)
|
||||
{
|
||||
return PVOP_CALL1(u64, pv_cpu_ops.read_pmc, counter);
|
||||
@@ -345,8 +360,9 @@ static inline void slow_down_io(void)
|
||||
pv_cpu_ops.io_delay();
|
||||
#endif
|
||||
}
|
||||
+#endif /* CONFIG_PARAVIRT_CPU */
|
||||
|
||||
-#ifdef CONFIG_SMP
|
||||
+#if defined(CONFIG_SMP) && defined(CONFIG_PARAVIRT_APIC)
|
||||
static inline void startup_ipi_hook(int phys_apicid, unsigned long start_eip,
|
||||
unsigned long start_esp)
|
||||
{
|
||||
@@ -355,6 +371,7 @@ static inline void startup_ipi_hook(int
|
||||
}
|
||||
#endif
|
||||
|
||||
+#ifdef CONFIG_PARAVIRT_MMU
|
||||
static inline void paravirt_activate_mm(struct mm_struct *prev,
|
||||
struct mm_struct *next)
|
||||
{
|
||||
@@ -689,7 +706,9 @@ static inline void pmd_clear(pmd_t *pmdp
|
||||
set_pmd(pmdp, __pmd(0));
|
||||
}
|
||||
#endif /* CONFIG_X86_PAE */
|
||||
+#endif /* CONFIG_PARAVIRT_MMU */
|
||||
|
||||
+#ifdef CONFIG_PARAVIRT_CPU
|
||||
#define __HAVE_ARCH_START_CONTEXT_SWITCH
|
||||
static inline void arch_start_context_switch(struct task_struct *prev)
|
||||
{
|
||||
@@ -700,7 +719,9 @@ static inline void arch_end_context_swit
|
||||
{
|
||||
PVOP_VCALL1(pv_cpu_ops.end_context_switch, next);
|
||||
}
|
||||
+#endif /* CONFIG_PARAVIRT_CPU */
|
||||
|
||||
+#ifdef CONFIG_PARAVIRT_MMU
|
||||
#define __HAVE_ARCH_ENTER_LAZY_MMU_MODE
|
||||
static inline void arch_enter_lazy_mmu_mode(void)
|
||||
{
|
||||
@@ -719,6 +740,7 @@ static inline void __set_fixmap(unsigned
|
||||
{
|
||||
pv_mmu_ops.set_fixmap(idx, phys, flags);
|
||||
}
|
||||
+#endif /* CONFIG_PARAVIRT_MMU */
|
||||
|
||||
#if defined(CONFIG_SMP) && defined(CONFIG_PARAVIRT_SPINLOCKS)
|
||||
|
||||
@@ -829,6 +851,7 @@ static __always_inline void arch_spin_un
|
||||
#define __PV_IS_CALLEE_SAVE(func) \
|
||||
((struct paravirt_callee_save) { func })
|
||||
|
||||
+#ifdef CONFIG_PARAVIRT_IRQ
|
||||
static inline notrace unsigned long arch_local_save_flags(void)
|
||||
{
|
||||
return PVOP_CALLEE0(unsigned long, pv_irq_ops.save_fl);
|
||||
@@ -857,6 +880,7 @@ static inline unsigned long __raw_local_
|
||||
arch_local_irq_disable();
|
||||
return f;
|
||||
}
|
||||
+#endif /* CONFIG_PARAVIRT_IRQ */
|
||||
|
||||
|
||||
/* Make sure as little as possible of this mess escapes. */
|
||||
@@ -939,10 +963,13 @@ extern void default_banner(void);
|
||||
#define PARA_INDIRECT(addr) *%cs:addr
|
||||
#endif
|
||||
|
||||
+#ifdef CONFIG_PARAVIRT_CPU
|
||||
#define INTERRUPT_RETURN \
|
||||
PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_iret), CLBR_NONE, \
|
||||
jmp PARA_INDIRECT(pv_cpu_ops+PV_CPU_iret))
|
||||
+#endif /* CONFIG_PARAVIRT_CPU */
|
||||
|
||||
+#ifdef CONFIG_PARAVIRT_IRQ
|
||||
#define DISABLE_INTERRUPTS(clobbers) \
|
||||
PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_irq_disable), clobbers, \
|
||||
PV_SAVE_REGS(clobbers | CLBR_CALLEE_SAVE); \
|
||||
@@ -954,13 +981,17 @@ extern void default_banner(void);
|
||||
PV_SAVE_REGS(clobbers | CLBR_CALLEE_SAVE); \
|
||||
call PARA_INDIRECT(pv_irq_ops+PV_IRQ_irq_enable); \
|
||||
PV_RESTORE_REGS(clobbers | CLBR_CALLEE_SAVE);)
|
||||
+#endif /* CONFIG_PARAVIRT_IRQ */
|
||||
|
||||
+#ifdef CONFIG_PARAVIRT_CPU
|
||||
#define USERGS_SYSRET32 \
|
||||
PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_usergs_sysret32), \
|
||||
CLBR_NONE, \
|
||||
jmp PARA_INDIRECT(pv_cpu_ops+PV_CPU_usergs_sysret32))
|
||||
+#endif /* CONFIG_PARAVIRT_CPU */
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
+#ifdef CONFIG_PARAVIRT_CPU
|
||||
#define GET_CR0_INTO_EAX \
|
||||
push %ecx; push %edx; \
|
||||
call PARA_INDIRECT(pv_cpu_ops+PV_CPU_read_cr0); \
|
||||
@@ -970,10 +1001,12 @@ extern void default_banner(void);
|
||||
PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_irq_enable_sysexit), \
|
||||
CLBR_NONE, \
|
||||
jmp PARA_INDIRECT(pv_cpu_ops+PV_CPU_irq_enable_sysexit))
|
||||
+#endif /* CONFIG_PARAVIRT_CPU */
|
||||
|
||||
|
||||
#else /* !CONFIG_X86_32 */
|
||||
|
||||
+#ifdef CONFIG_PARAVIRT_CPU
|
||||
/*
|
||||
* If swapgs is used while the userspace stack is still current,
|
||||
* there's no way to call a pvop. The PV replacement *must* be
|
||||
@@ -993,17 +1026,23 @@ extern void default_banner(void);
|
||||
PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_swapgs), CLBR_NONE, \
|
||||
call PARA_INDIRECT(pv_cpu_ops+PV_CPU_swapgs) \
|
||||
)
|
||||
+#endif /* CONFIG_PARAVIRT_CPU */
|
||||
|
||||
+#ifdef CONFIG_PARAVIRT_MMU
|
||||
#define GET_CR2_INTO_RCX \
|
||||
call PARA_INDIRECT(pv_mmu_ops+PV_MMU_read_cr2); \
|
||||
movq %rax, %rcx; \
|
||||
xorq %rax, %rax;
|
||||
+#endif /* CONFIG_PARAVIRT_MMU */
|
||||
|
||||
+#ifdef CONFIG_PARAVIRT_IRQ
|
||||
#define PARAVIRT_ADJUST_EXCEPTION_FRAME \
|
||||
PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_adjust_exception_frame), \
|
||||
CLBR_NONE, \
|
||||
call PARA_INDIRECT(pv_irq_ops+PV_IRQ_adjust_exception_frame))
|
||||
+#endif /* CONFIG_PARAVIRT_IRQ */
|
||||
|
||||
+#ifdef CONFIG_PARAVIRT_CPU
|
||||
#define USERGS_SYSRET64 \
|
||||
PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_usergs_sysret64), \
|
||||
CLBR_NONE, \
|
||||
@@ -1013,6 +1052,7 @@ extern void default_banner(void);
|
||||
PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_irq_enable_sysexit), \
|
||||
CLBR_NONE, \
|
||||
jmp PARA_INDIRECT(pv_cpu_ops+PV_CPU_irq_enable_sysexit))
|
||||
+#endif /* CONFIG_PARAVIRT_CPU */
|
||||
#endif /* CONFIG_X86_32 */
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
--- a/arch/x86/include/asm/paravirt_types.h
|
||||
+++ b/arch/x86/include/asm/paravirt_types.h
|
||||
@@ -339,12 +339,24 @@ struct paravirt_patch_template {
|
||||
|
||||
extern struct pv_info pv_info;
|
||||
extern struct pv_init_ops pv_init_ops;
|
||||
+#ifdef CONFIG_PARAVIRT_TIME
|
||||
extern struct pv_time_ops pv_time_ops;
|
||||
+#endif
|
||||
+#ifdef CONFIG_PARAVIRT_CPU
|
||||
extern struct pv_cpu_ops pv_cpu_ops;
|
||||
+#endif
|
||||
+#ifdef CONFIG_PARAVIRT_IRQ
|
||||
extern struct pv_irq_ops pv_irq_ops;
|
||||
+#endif
|
||||
+#ifdef CONFIG_PARAVIRT_APIC
|
||||
extern struct pv_apic_ops pv_apic_ops;
|
||||
+#endif
|
||||
+#ifdef CONFIG_PARAVIRT_MMU
|
||||
extern struct pv_mmu_ops pv_mmu_ops;
|
||||
+#endif
|
||||
+#ifdef CONFIG_PARAVIRT_SPINLOCKS
|
||||
extern struct pv_lock_ops pv_lock_ops;
|
||||
+#endif
|
||||
|
||||
#define PARAVIRT_PATCH(x) \
|
||||
(offsetof(struct paravirt_patch_template, x) / sizeof(void *))
|
||||
--- a/arch/x86/include/asm/pgalloc.h
|
||||
+++ b/arch/x86/include/asm/pgalloc.h
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
static inline int __paravirt_pgd_alloc(struct mm_struct *mm) { return 0; }
|
||||
|
||||
-#ifdef CONFIG_PARAVIRT
|
||||
+#ifdef CONFIG_PARAVIRT_MMU
|
||||
#include <asm/paravirt.h>
|
||||
#else
|
||||
#define paravirt_pgd_alloc(mm) __paravirt_pgd_alloc(mm)
|
||||
--- a/arch/x86/include/asm/pgtable-3level_types.h
|
||||
+++ b/arch/x86/include/asm/pgtable-3level_types.h
|
||||
@@ -18,7 +18,7 @@ typedef union {
|
||||
} pte_t;
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
-#ifdef CONFIG_PARAVIRT
|
||||
+#ifdef CONFIG_PARAVIRT_MMU
|
||||
#define SHARED_KERNEL_PMD (pv_info.shared_kernel_pmd)
|
||||
#else
|
||||
#define SHARED_KERNEL_PMD 1
|
||||
--- a/arch/x86/include/asm/pgtable.h
|
||||
+++ b/arch/x86/include/asm/pgtable.h
|
||||
@@ -28,7 +28,7 @@ extern unsigned long empty_zero_page[PAG
|
||||
|
||||
extern struct mm_struct *pgd_page_get_mm(struct page *page);
|
||||
|
||||
-#ifdef CONFIG_PARAVIRT
|
||||
+#ifdef CONFIG_PARAVIRT_MMU
|
||||
#include <asm/paravirt.h>
|
||||
#else /* !CONFIG_PARAVIRT */
|
||||
#define set_pte(ptep, pte) native_set_pte(ptep, pte)
|
||||
--- a/arch/x86/include/asm/processor.h
|
||||
+++ b/arch/x86/include/asm/processor.h
|
||||
@@ -569,7 +569,7 @@ static inline void native_swapgs(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
-#ifdef CONFIG_PARAVIRT
|
||||
+#ifdef CONFIG_PARAVIRT_CPU
|
||||
#include <asm/paravirt.h>
|
||||
#else
|
||||
#define __cpuid native_cpuid
|
||||
--- a/arch/x86/include/asm/required-features.h
|
||||
+++ b/arch/x86/include/asm/required-features.h
|
||||
@@ -48,7 +48,7 @@
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
-#ifdef CONFIG_PARAVIRT
|
||||
+#ifdef CONFIG_PARAVIRT_MMU
|
||||
/* Paravirtualized systems may not have PSE or PGE available */
|
||||
#define NEED_PSE 0
|
||||
#define NEED_PGE 0
|
||||
--- a/arch/x86/include/asm/smp.h
|
||||
+++ b/arch/x86/include/asm/smp.h
|
||||
@@ -66,7 +66,7 @@ struct smp_ops {
|
||||
extern void set_cpu_sibling_map(int cpu);
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
-#ifndef CONFIG_PARAVIRT
|
||||
+#ifndef CONFIG_PARAVIRT_APIC
|
||||
#define startup_ipi_hook(phys_apicid, start_eip, start_esp) do { } while (0)
|
||||
#endif
|
||||
extern struct smp_ops smp_ops;
|
||||
--- a/arch/x86/include/asm/system.h
|
||||
+++ b/arch/x86/include/asm/system.h
|
||||
@@ -304,13 +304,18 @@ static inline void native_wbinvd(void)
|
||||
|
||||
#ifdef CONFIG_PARAVIRT
|
||||
#include <asm/paravirt.h>
|
||||
-#else
|
||||
-#define read_cr0() (native_read_cr0())
|
||||
-#define write_cr0(x) (native_write_cr0(x))
|
||||
+#endif/* CONFIG_PARAVIRT */
|
||||
+
|
||||
+#ifndef CONFIG_PARAVIRT_MMU
|
||||
#define read_cr2() (native_read_cr2())
|
||||
#define write_cr2(x) (native_write_cr2(x))
|
||||
#define read_cr3() (native_read_cr3())
|
||||
#define write_cr3(x) (native_write_cr3(x))
|
||||
+#endif /* CONFIG_PARAVIRT_MMU */
|
||||
+
|
||||
+#ifndef CONFIG_PARAVIRT_CPU
|
||||
+#define read_cr0() (native_read_cr0())
|
||||
+#define write_cr0(x) (native_write_cr0(x))
|
||||
#define read_cr4() (native_read_cr4())
|
||||
#define read_cr4_safe() (native_read_cr4_safe())
|
||||
#define write_cr4(x) (native_write_cr4(x))
|
||||
@@ -324,7 +329,7 @@ static inline void native_wbinvd(void)
|
||||
/* Clear the 'TS' bit */
|
||||
#define clts() (native_clts())
|
||||
|
||||
-#endif/* CONFIG_PARAVIRT */
|
||||
+#endif /* CONFIG_PARAVIRT_CPU */
|
||||
|
||||
#define stts() write_cr0(read_cr0() | X86_CR0_TS)
|
||||
|
||||
--- a/arch/x86/include/asm/tlbflush.h
|
||||
+++ b/arch/x86/include/asm/tlbflush.h
|
||||
@@ -7,7 +7,7 @@
|
||||
#include <asm/processor.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
-#ifdef CONFIG_PARAVIRT
|
||||
+#ifdef CONFIG_PARAVIRT_MMU
|
||||
#include <asm/paravirt.h>
|
||||
#else
|
||||
#define __flush_tlb() __native_flush_tlb()
|
||||
@@ -162,7 +162,7 @@ static inline void reset_lazy_tlbstate(v
|
||||
|
||||
#endif /* SMP */
|
||||
|
||||
-#ifndef CONFIG_PARAVIRT
|
||||
+#ifndef CONFIG_PARAVIRT_MMU
|
||||
#define flush_tlb_others(mask, mm, va) native_flush_tlb_others(mask, mm, va)
|
||||
#endif
|
||||
|
||||
--- a/arch/x86/kernel/head_64.S
|
||||
+++ b/arch/x86/kernel/head_64.S
|
||||
@@ -20,7 +20,7 @@
|
||||
#include <asm/processor-flags.h>
|
||||
#include <asm/percpu.h>
|
||||
|
||||
-#ifdef CONFIG_PARAVIRT
|
||||
+#ifdef CONFIG_PARAVIRT_MMU
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/paravirt.h>
|
||||
#else
|
||||
--- a/arch/x86/kernel/paravirt.c
|
||||
+++ b/arch/x86/kernel/paravirt.c
|
||||
@@ -155,12 +155,14 @@ unsigned paravirt_patch_default(u8 type,
|
||||
else if (opfunc == _paravirt_ident_64)
|
||||
ret = paravirt_patch_ident_64(insnbuf, len);
|
||||
|
||||
+#ifdef CONFIG_PARAVIRT_CPU
|
||||
else if (type == PARAVIRT_PATCH(pv_cpu_ops.iret) ||
|
||||
type == PARAVIRT_PATCH(pv_cpu_ops.irq_enable_sysexit) ||
|
||||
type == PARAVIRT_PATCH(pv_cpu_ops.usergs_sysret32) ||
|
||||
type == PARAVIRT_PATCH(pv_cpu_ops.usergs_sysret64))
|
||||
/* If operation requires a jmp, then jmp */
|
||||
ret = paravirt_patch_jmp(insnbuf, opfunc, addr, len);
|
||||
+#endif
|
||||
else
|
||||
/* Otherwise call the function; assume target could
|
||||
clobber any caller-save reg */
|
||||
--- a/arch/x86/kernel/tsc.c
|
||||
+++ b/arch/x86/kernel/tsc.c
|
||||
@@ -66,7 +66,7 @@ u64 native_sched_clock(void)
|
||||
|
||||
/* We need to define a real function for sched_clock, to override the
|
||||
weak default version */
|
||||
-#ifdef CONFIG_PARAVIRT
|
||||
+#ifdef CONFIG_PARAVIRT_TIME
|
||||
unsigned long long sched_clock(void)
|
||||
{
|
||||
return paravirt_sched_clock();
|
||||
--- a/arch/x86/kernel/vsmp_64.c
|
||||
+++ b/arch/x86/kernel/vsmp_64.c
|
||||
@@ -22,7 +22,7 @@
|
||||
#include <asm/paravirt.h>
|
||||
#include <asm/setup.h>
|
||||
|
||||
-#if defined CONFIG_PCI && defined CONFIG_PARAVIRT
|
||||
+#if defined CONFIG_PCI && defined CONFIG_PARAVIRT_IRQ
|
||||
/*
|
||||
* Interrupt control on vSMPowered systems:
|
||||
* ~AC is a shadow of IF. If IF is 'on' AC should be 'off'
|
||||
--- a/arch/x86/kernel/x8664_ksyms_64.c
|
||||
+++ b/arch/x86/kernel/x8664_ksyms_64.c
|
||||
@@ -54,6 +54,6 @@ EXPORT_SYMBOL(memcpy);
|
||||
EXPORT_SYMBOL(__memcpy);
|
||||
|
||||
EXPORT_SYMBOL(empty_zero_page);
|
||||
-#ifndef CONFIG_PARAVIRT
|
||||
+#ifndef CONFIG_PARAVIRT_CPU
|
||||
EXPORT_SYMBOL(native_load_gs_index);
|
||||
#endif
|
||||
--- a/arch/x86/xen/Kconfig
|
||||
+++ b/arch/x86/xen/Kconfig
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
config XEN
|
||||
bool "Xen guest support"
|
||||
- select PARAVIRT
|
||||
+ select PARAVIRT_ALL
|
||||
select PARAVIRT_CLOCK
|
||||
depends on X86_64 || (X86_32 && X86_PAE && !X86_VISWS)
|
||||
depends on X86_CMPXCHG && X86_TSC
|
@ -1,125 +0,0 @@
|
||||
From: Alexander Graf <agraf@suse.de>
|
||||
Date: Wed, 18 Nov 2009 00:45:10 +0100
|
||||
Subject: Split the KVM pv-ops support by feature
|
||||
References: bnc#556135, FATE#306453
|
||||
Patch-Mainline: Submitted to virtualization list
|
||||
|
||||
Currently selecting KVM guest support enabled multiple features at once that
|
||||
not everyone necessarily wants to have, namely:
|
||||
|
||||
- PV MMU
|
||||
- zero io delay
|
||||
- apic detection workaround
|
||||
|
||||
Let's split them off so we don't drag in the full pv-ops framework just to
|
||||
detect we're running on KVM. That gives us more chances to tweak performance!
|
||||
|
||||
Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
---
|
||||
arch/x86/Kconfig | 29 ++++++++++++++++++++++++++++-
|
||||
arch/x86/kernel/kvm.c | 22 +++++++++++++++-------
|
||||
2 files changed, 43 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/arch/x86/Kconfig
|
||||
+++ b/arch/x86/Kconfig
|
||||
@@ -543,11 +543,38 @@ config KVM_CLOCK
|
||||
|
||||
config KVM_GUEST
|
||||
bool "KVM Guest support"
|
||||
- select PARAVIRT_ALL
|
||||
+ select PARAVIRT
|
||||
---help---
|
||||
This option enables various optimizations for running under the KVM
|
||||
hypervisor.
|
||||
|
||||
+config KVM_IODELAY
|
||||
+ bool "KVM IO-delay support"
|
||||
+ depends on KVM_GUEST
|
||||
+ select PARAVIRT_CPU
|
||||
+ ---help---
|
||||
+ Usually we wait for PIO access to complete. When inside KVM there's
|
||||
+ no need to do that, as we know that we're not going through a bus,
|
||||
+ but process PIO requests instantly.
|
||||
+
|
||||
+ This option disables PIO waits, but drags in CPU-bound pv-ops. Thus
|
||||
+ you will probably get more speed loss than speedup using this option.
|
||||
+
|
||||
+ If in doubt, say N.
|
||||
+
|
||||
+config KVM_MMU
|
||||
+ bool "KVM PV MMU support"
|
||||
+ depends on KVM_GUEST
|
||||
+ select PARAVIRT_MMU
|
||||
+ ---help---
|
||||
+ This option enables the paravirtualized MMU for KVM. In most cases
|
||||
+ it's pretty useless and shouldn't be used.
|
||||
+
|
||||
+ It will only cost you performance, because it drags in pv-ops for
|
||||
+ memory management.
|
||||
+
|
||||
+ If in doubt, say N.
|
||||
+
|
||||
source "arch/x86/lguest/Kconfig"
|
||||
|
||||
config PARAVIRT
|
||||
--- a/arch/x86/kernel/kvm.c
|
||||
+++ b/arch/x86/kernel/kvm.c
|
||||
@@ -29,6 +29,16 @@
|
||||
#include <asm/desc.h>
|
||||
#include <asm/tlbflush.h>
|
||||
|
||||
+#ifdef CONFIG_KVM_IODELAY
|
||||
+/*
|
||||
+ * No need for any "IO delay" on KVM
|
||||
+ */
|
||||
+static void kvm_io_delay(void)
|
||||
+{
|
||||
+}
|
||||
+#endif /* CONFIG_KVM_IODELAY */
|
||||
+
|
||||
+#ifdef CONFIG_KVM_MMU
|
||||
#define MMU_QUEUE_SIZE 1024
|
||||
|
||||
static int kvmapf = 1;
|
||||
@@ -43,13 +53,6 @@ static struct kvm_para_state *kvm_para_s
|
||||
return &per_cpu(para_state, raw_smp_processor_id());
|
||||
}
|
||||
|
||||
-/*
|
||||
- * No need for any "IO delay" on KVM
|
||||
- */
|
||||
-static void kvm_io_delay(void)
|
||||
-{
|
||||
-}
|
||||
-
|
||||
#define KVM_TASK_SLEEP_HASHBITS 8
|
||||
#define KVM_TASK_SLEEP_HASHSIZE (1<<KVM_TASK_SLEEP_HASHBITS)
|
||||
|
||||
@@ -194,15 +197,19 @@ static void kvm_leave_lazy_mmu(void)
|
||||
mmu_queue_flush(state);
|
||||
paravirt_leave_lazy_mmu();
|
||||
}
|
||||
+#endif /* CONFIG_KVM_MMU */
|
||||
|
||||
static void __init paravirt_ops_setup(void)
|
||||
{
|
||||
pv_info.name = "KVM";
|
||||
pv_info.paravirt_enabled = 1;
|
||||
|
||||
+#ifdef CONFIG_KVM_IODELAY
|
||||
if (kvm_para_has_feature(KVM_FEATURE_NOP_IO_DELAY))
|
||||
pv_cpu_ops.io_delay = kvm_io_delay;
|
||||
+#endif
|
||||
|
||||
+#ifdef CONFIG_KVM_MMU
|
||||
if (kvm_para_has_feature(KVM_FEATURE_MMU_OP)) {
|
||||
pv_mmu_ops.set_pte = kvm_set_pte;
|
||||
pv_mmu_ops.set_pte_at = kvm_set_pte_at;
|
||||
@@ -226,6 +233,7 @@ static void __init paravirt_ops_setup(vo
|
||||
pv_mmu_ops.lazy_mode.enter = kvm_enter_lazy_mmu;
|
||||
pv_mmu_ops.lazy_mode.leave = kvm_leave_lazy_mmu;
|
||||
}
|
||||
+#endif /* CONFIG_KVM_MMU */
|
||||
#ifdef CONFIG_X86_IO_APIC
|
||||
no_timer_check = 1;
|
||||
#endif
|
@ -1,148 +0,0 @@
|
||||
From: Russ Anderson <rja@sgi.com>
|
||||
Subject: mm: Avoid putting a bad page back on the LRU v8
|
||||
References: 415829
|
||||
Acked-by: schwab@suse.de
|
||||
Patch-mainline: not yet
|
||||
|
||||
Prevent a page with a physical memory error from being placed back
|
||||
on the LRU. A new page flag (PG_memerror) is added if
|
||||
CONFIG_PAGEFLAGS_EXTENDED is defined.
|
||||
|
||||
Version 8 change: Removed hot path check for pages with memory
|
||||
errors on the free list.
|
||||
|
||||
Signed-off-by: Russ Anderson <rja@sgi.com>
|
||||
Reviewed-by: Christoph Lameter <cl@linux-foundation.org>
|
||||
|
||||
---
|
||||
include/linux/page-flags.h | 16 +++++++++++++++-
|
||||
mm/migrate.c | 33 +++++++++++++++++++++++++++++++++
|
||||
mm/vmscan.c | 1 +
|
||||
3 files changed, 49 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/include/linux/page-flags.h
|
||||
+++ b/include/linux/page-flags.h
|
||||
@@ -88,6 +88,7 @@ enum pageflags {
|
||||
PG_private_2, /* If pagecache, has fs aux data */
|
||||
PG_writeback, /* Page is under writeback */
|
||||
#ifdef CONFIG_PAGEFLAGS_EXTENDED
|
||||
+ PG_memerror, /* Page has a physical memory error */
|
||||
PG_head, /* A head page */
|
||||
PG_tail, /* A tail page */
|
||||
#else
|
||||
@@ -167,14 +168,21 @@ static inline int TestClearPage##uname(s
|
||||
static inline int __TestClearPage##uname(struct page *page) \
|
||||
{ return __test_and_clear_bit(PG_##lname, &page->flags); }
|
||||
|
||||
+#define PAGEFLAGMASK(uname, lname) \
|
||||
+static inline int PAGEMASK_##uname(void) \
|
||||
+ { return (1 << PG_##lname); }
|
||||
+
|
||||
#define PAGEFLAG(uname, lname) TESTPAGEFLAG(uname, lname) \
|
||||
- SETPAGEFLAG(uname, lname) CLEARPAGEFLAG(uname, lname)
|
||||
+ SETPAGEFLAG(uname, lname) CLEARPAGEFLAG(uname, lname) \
|
||||
+ PAGEFLAGMASK(uname, lname)
|
||||
|
||||
#define __PAGEFLAG(uname, lname) TESTPAGEFLAG(uname, lname) \
|
||||
__SETPAGEFLAG(uname, lname) __CLEARPAGEFLAG(uname, lname)
|
||||
|
||||
#define PAGEFLAG_FALSE(uname) \
|
||||
static inline int Page##uname(struct page *page) \
|
||||
+ { return 0; } \
|
||||
+static inline int PAGEMASK_##uname(void) \
|
||||
{ return 0; }
|
||||
|
||||
#define TESTSCFLAG(uname, lname) \
|
||||
@@ -391,6 +399,12 @@ static inline void __ClearPageTail(struc
|
||||
|
||||
#endif /* !PAGEFLAGS_EXTENDED */
|
||||
|
||||
+#ifdef CONFIG_PAGEFLAGS_EXTENDED
|
||||
+PAGEFLAG(MemError, memerror)
|
||||
+#else
|
||||
+PAGEFLAG_FALSE(MemError)
|
||||
+#endif
|
||||
+
|
||||
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
||||
/*
|
||||
* PageHuge() only returns true for hugetlbfs pages, but not for
|
||||
--- a/mm/migrate.c
|
||||
+++ b/mm/migrate.c
|
||||
@@ -63,6 +63,7 @@ int migrate_prep_local(void)
|
||||
|
||||
return 0;
|
||||
}
|
||||
+EXPORT_SYMBOL(migrate_prep);
|
||||
|
||||
/*
|
||||
* Add isolated pages on the list back to the LRU under page lock
|
||||
@@ -80,6 +81,7 @@ void putback_lru_pages(struct list_head
|
||||
putback_lru_page(page);
|
||||
}
|
||||
}
|
||||
+EXPORT_SYMBOL(putback_lru_pages);
|
||||
|
||||
/*
|
||||
* Restore a potential migration pte to a working pte entry
|
||||
@@ -701,6 +703,25 @@ unlock:
|
||||
* restored.
|
||||
*/
|
||||
list_del(&page->lru);
|
||||
+ if (PageMemError(page)) {
|
||||
+ if (rc == 0)
|
||||
+ /*
|
||||
+ * A page with a memory error that has
|
||||
+ * been migrated will not be moved to
|
||||
+ * the LRU.
|
||||
+ */
|
||||
+ goto move_newpage;
|
||||
+ else
|
||||
+ /*
|
||||
+ * The page failed to migrate and will not
|
||||
+ * be added to the bad page list. Clearing
|
||||
+ * the error bit will allow another attempt
|
||||
+ * to migrate if it gets another correctable
|
||||
+ * error.
|
||||
+ */
|
||||
+ ClearPageMemError(page);
|
||||
+ }
|
||||
+
|
||||
dec_zone_page_state(page, NR_ISOLATED_ANON +
|
||||
page_is_file_cache(page));
|
||||
putback_lru_page(page);
|
||||
@@ -775,6 +796,17 @@ int migrate_pages(struct list_head *from
|
||||
}
|
||||
}
|
||||
}
|
||||
+
|
||||
+ if (rc != 0)
|
||||
+ list_for_each_entry_safe(page, page2, from, lru)
|
||||
+ if (PageMemError(page))
|
||||
+ /*
|
||||
+ * The page failed to migrate. Clearing
|
||||
+ * the error bit will allow another attempt
|
||||
+ * to migrate if it gets another correctable
|
||||
+ * error.
|
||||
+ */
|
||||
+ ClearPageMemError(page);
|
||||
rc = 0;
|
||||
out:
|
||||
if (!swapwrite)
|
||||
@@ -787,6 +819,7 @@ out:
|
||||
|
||||
return nr_failed + retry;
|
||||
}
|
||||
+EXPORT_SYMBOL(migrate_pages);
|
||||
|
||||
#ifdef CONFIG_NUMA
|
||||
/*
|
||||
--- a/mm/vmscan.c
|
||||
+++ b/mm/vmscan.c
|
||||
@@ -1127,6 +1127,7 @@ int isolate_lru_page(struct page *page)
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
+EXPORT_SYMBOL(isolate_lru_page);
|
||||
|
||||
/*
|
||||
* Are there way too many processes in the direct reclaim path already?
|
@ -1,32 +0,0 @@
|
||||
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,33 +0,0 @@
|
||||
From: Takashi Iwai <tiwai@suse.de>
|
||||
Subject: [PATCH] Fix build_error without CONFIG_PPC_83xx
|
||||
Patch-mainline:
|
||||
References:
|
||||
|
||||
fsl_deep_sleep() is defined only with CONFIG_PPC_83xx although
|
||||
CONFIG_IPIC is set for CONFIG_PPC_MPC512x, too.
|
||||
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
|
||||
---
|
||||
---
|
||||
arch/powerpc/sysdev/ipic.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
--- a/arch/powerpc/sysdev/ipic.c
|
||||
+++ b/arch/powerpc/sysdev/ipic.c
|
||||
@@ -921,6 +921,7 @@ static int ipic_suspend(struct sys_devic
|
||||
ipic_saved_state.sermr = ipic_read(ipic->regs, IPIC_SERMR);
|
||||
ipic_saved_state.sercr = ipic_read(ipic->regs, IPIC_SERCR);
|
||||
|
||||
+#ifdef CONFIG_PPC_83xx
|
||||
if (fsl_deep_sleep()) {
|
||||
/* In deep sleep, make sure there can be no
|
||||
* pending interrupts, as this can cause
|
||||
@@ -931,6 +932,7 @@ static int ipic_suspend(struct sys_devic
|
||||
ipic_write(ipic->regs, IPIC_SEMSR, 0);
|
||||
ipic_write(ipic->regs, IPIC_SERMR, 0);
|
||||
}
|
||||
+#endif
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
From: olh@suse.de
|
||||
Subject: force speed to fix autodetection on pegasos2
|
||||
Patch-mainline: never
|
||||
|
||||
---
|
||||
arch/powerpc/platforms/chrp/setup.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/arch/powerpc/platforms/chrp/setup.c
|
||||
+++ b/arch/powerpc/platforms/chrp/setup.c
|
||||
@@ -293,7 +293,7 @@ static void chrp_init_early(void)
|
||||
if (!property)
|
||||
goto out_put;
|
||||
if (!strcmp(property, "failsafe") || !strcmp(property, "serial"))
|
||||
- add_preferred_console("ttyS", 0, NULL);
|
||||
+ add_preferred_console("ttyS", 0, "115200");
|
||||
out_put:
|
||||
of_node_put(node);
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
From: Olaf Hering <olh@suse.de>
|
||||
Subject: new prom=nodisplay option to avoid crash in firmware on B50
|
||||
Patch-mainline: not yet
|
||||
|
||||
add prom=nodisplay
|
||||
avoid crash in firmware on IBM B50 when OF stdout is on serial.
|
||||
|
||||
0 > boot scsi/sd@4:1,yaboot |
|
||||
yaboot starting: loaded at 00200000 00222530 (0/0/00c1a078; sp: 00efffd0)
|
||||
brokenfirmware did not claim executable memory, fixed it myself
|
||||
Config file 'yaboot.cnf' read, 213 bytes
|
||||
|
||||
Welcome to yaboot version 10.1.22-r945.SuSE
|
||||
booted from '/pci@80000000/scsi@10/sd@4:1,yaboot'
|
||||
Enter "help" to get some basic usage information
|
||||
boot:
|
||||
* linux
|
||||
boot: linux 3
|
||||
Please wait, loading kernel...
|
||||
Allocated 00600000 bytes for executable @ 02000000
|
||||
Elf32 kernel loaded...
|
||||
Loading ramdisk...
|
||||
ramdisk loaded 0030e057 @ 04100000
|
||||
OF stdout device is: /pci@80000000/isa@b/serial@i3f8
|
||||
command line: root=/dev/system/root xmon=on sysrq=1 quiet panic=12 3
|
||||
memory layout at init:
|
||||
memory_limit : 00000000 (16 MB aligned)
|
||||
alloc_bottom : 0440f000
|
||||
alloc_top : 30000000
|
||||
alloc_top_hi : 40000000
|
||||
rmo_top : 30000000
|
||||
ram_top : 40000000
|
||||
Looking for displays
|
||||
found display : /pci@80000000/display@16, opening ...
|
||||
Unexpected Firmware Error:
|
||||
DEFAULT CATCH!, code=fff00300 at %SRR0: 00c18ccc %SRR1: 00003030
|
||||
ok
|
||||
0 > reset-all
|
||||
|
||||
|
||||
---
|
||||
arch/powerpc/kernel/prom_init.c | 10 ++++++++++
|
||||
1 file changed, 10 insertions(+)
|
||||
|
||||
--- a/arch/powerpc/kernel/prom_init.c
|
||||
+++ b/arch/powerpc/kernel/prom_init.c
|
||||
@@ -169,6 +169,7 @@ static unsigned long __initdata dt_strin
|
||||
|
||||
static unsigned long __initdata prom_initrd_start, prom_initrd_end;
|
||||
|
||||
+static int __initdata prom_no_display;
|
||||
#ifdef CONFIG_PPC64
|
||||
static int __initdata prom_iommu_force_on;
|
||||
static int __initdata prom_iommu_off;
|
||||
@@ -596,6 +597,14 @@ static void __init early_cmdline_parse(v
|
||||
#endif /* CONFIG_CMDLINE */
|
||||
prom_printf("command line: %s\n", RELOC(prom_cmd_line));
|
||||
|
||||
+ opt = strstr(RELOC(prom_cmd_line), RELOC("prom="));
|
||||
+ if (opt) {
|
||||
+ opt += 5;
|
||||
+ while (*opt && *opt == ' ')
|
||||
+ opt++;
|
||||
+ if (!strncmp(opt, RELOC("nodisplay"), 9))
|
||||
+ RELOC(prom_no_display) = 1;
|
||||
+ }
|
||||
#ifdef CONFIG_PPC64
|
||||
opt = strstr(RELOC(prom_cmd_line), RELOC("iommu="));
|
||||
if (opt) {
|
||||
@@ -2570,6 +2579,7 @@ unsigned long __init prom_init(unsigned
|
||||
/*
|
||||
* Initialize display devices
|
||||
*/
|
||||
+ if (RELOC(prom_no_display) == 0)
|
||||
prom_check_displays();
|
||||
|
||||
#ifdef CONFIG_PPC64
|
@ -1,119 +0,0 @@
|
||||
Subject: [PATCH] add syslog printing to xmon debugger.
|
||||
From: Linas Vepstas <linas@austin.ibm.com>
|
||||
Patch-mainline: Not yet
|
||||
|
||||
|
||||
This patch 'dmesg'/printk log buffer printing to xmon. I find this
|
||||
useful because crashes are almost always preceeded by interesting
|
||||
printk's. This patch is simple & straightforward, except for one
|
||||
possibly controversial aspect: it embeds a small snippet in
|
||||
kernel/printk.c to return the location of the syslog. This is
|
||||
needed because kallsyms and even CONFIG_KALLSYMS_ALL is not enough
|
||||
to reveal the location of log_buf. This code is about 90%
|
||||
cut-n-paste of earlier code from Keith Owens.
|
||||
|
||||
Signed-off-by: Olaf Hering <olh@suse.de>
|
||||
---
|
||||
|
||||
arch/powerpc/xmon/xmon.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++
|
||||
kernel/printk.c | 2 -
|
||||
2 files changed, 58 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/arch/powerpc/xmon/xmon.c
|
||||
+++ b/arch/powerpc/xmon/xmon.c
|
||||
@@ -138,6 +138,7 @@ static struct bpt *in_breakpoint_table(u
|
||||
static int do_step(struct pt_regs *);
|
||||
static void bpt_cmds(void);
|
||||
static void cacheflush(void);
|
||||
+static void xmon_show_dmesg(void);
|
||||
static int cpu_cmd(void);
|
||||
static void csum(void);
|
||||
static void bootcmds(void);
|
||||
@@ -197,6 +198,7 @@ Commands:\n\
|
||||
#endif
|
||||
"\
|
||||
C checksum\n\
|
||||
+ D show dmesg (printk) buffer\n\
|
||||
d dump bytes\n\
|
||||
di dump instructions\n\
|
||||
df dump float values\n\
|
||||
@@ -831,6 +833,9 @@ cmds(struct pt_regs *excp)
|
||||
case 'd':
|
||||
dump();
|
||||
break;
|
||||
+ case 'D':
|
||||
+ xmon_show_dmesg();
|
||||
+ break;
|
||||
case 'l':
|
||||
symbol_lookup();
|
||||
break;
|
||||
@@ -2607,6 +2612,58 @@ static void xmon_print_symbol(unsigned l
|
||||
printf("%s", after);
|
||||
}
|
||||
|
||||
+extern void kdb_syslog_data(char *syslog_data[]);
|
||||
+#define SYSLOG_WRAP(p) if (p < syslog_data[0]) p = syslog_data[1]-1; \
|
||||
+ else if (p >= syslog_data[1]) p = syslog_data[0];
|
||||
+
|
||||
+static void xmon_show_dmesg(void)
|
||||
+{
|
||||
+ char *syslog_data[4], *start, *end, c;
|
||||
+ int logsize;
|
||||
+
|
||||
+ /* syslog_data[0,1] physical start, end+1.
|
||||
+ * syslog_data[2,3] logical start, end+1.
|
||||
+ */
|
||||
+ kdb_syslog_data(syslog_data);
|
||||
+ if (syslog_data[2] == syslog_data[3])
|
||||
+ return;
|
||||
+ logsize = syslog_data[1] - syslog_data[0];
|
||||
+ start = syslog_data[0] + (syslog_data[2] - syslog_data[0]) % logsize;
|
||||
+ end = syslog_data[0] + (syslog_data[3] - syslog_data[0]) % logsize;
|
||||
+
|
||||
+ /* Do a line at a time (max 200 chars) to reduce overhead */
|
||||
+ c = '\0';
|
||||
+ while(1) {
|
||||
+ char *p;
|
||||
+ int chars = 0;
|
||||
+ if (!*start) {
|
||||
+ while (!*start) {
|
||||
+ ++start;
|
||||
+ SYSLOG_WRAP(start);
|
||||
+ if (start == end)
|
||||
+ break;
|
||||
+ }
|
||||
+ if (start == end)
|
||||
+ break;
|
||||
+ }
|
||||
+ p = start;
|
||||
+ while (*start && chars < 200) {
|
||||
+ c = *start;
|
||||
+ ++chars;
|
||||
+ ++start;
|
||||
+ SYSLOG_WRAP(start);
|
||||
+ if (start == end || c == '\n')
|
||||
+ break;
|
||||
+ }
|
||||
+ if (chars)
|
||||
+ printf("%.*s", chars, p);
|
||||
+ if (start == end)
|
||||
+ break;
|
||||
+ }
|
||||
+ if (c != '\n')
|
||||
+ printf("\n");
|
||||
+}
|
||||
+
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
static void dump_slb(void)
|
||||
{
|
||||
--- a/kernel/printk.c
|
||||
+++ b/kernel/printk.c
|
||||
@@ -416,7 +416,7 @@ SYSCALL_DEFINE3(syslog, int, type, char
|
||||
return do_syslog(type, buf, len, SYSLOG_FROM_CALL);
|
||||
}
|
||||
|
||||
-#ifdef CONFIG_KGDB_KDB
|
||||
+#if defined(CONFIG_KGDB_KDB) || defined(CONFIG_DEBUG_KERNEL)
|
||||
/* kdb dmesg command needs access to the syslog buffer. do_syslog()
|
||||
* uses locks so it cannot be used during debugging. Just tell kdb
|
||||
* where the start and end of the physical and logical logs are. This
|
@ -1,43 +0,0 @@
|
||||
From: Jeff Mahoney <jeffm@suse.com>
|
||||
Subject: [PATCH] s390: Define FREE_PTE_NR
|
||||
Patch-mainline: Never, unless FREE_PTE_NR is used in generic code
|
||||
|
||||
Commit ba8a9229ab9e80278c28ad68b15053f65b2b0a7c from
|
||||
Martin Schwidefsky <schwidefsky@de.ibm.com> removed the
|
||||
#include <asm-generic/tlb.h> from asm-s390/tlb.h when he defined the
|
||||
s390-specific TLB operations.
|
||||
|
||||
FREE_PTR_NR is generally an internal-only value, but our unmap_vmas-lat
|
||||
patch uses it to make smarter decisions about dumping PTEs in chunks.
|
||||
|
||||
This patch restores the generic value in asm-s390/tlb.h. Since it's only
|
||||
used for an optimization, this should be safe.
|
||||
|
||||
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
|
||||
|
||||
---
|
||||
arch/s390/include/asm/tlb.h | 13 +++++++++++++
|
||||
1 file changed, 13 insertions(+)
|
||||
|
||||
--- a/arch/s390/include/asm/tlb.h
|
||||
+++ b/arch/s390/include/asm/tlb.h
|
||||
@@ -34,6 +34,19 @@
|
||||
#define TLB_NR_PTRS 508
|
||||
#endif
|
||||
|
||||
+/* Lifted from asm-generic/tlb.h; Is used by patches.suse/unmap_vmas-lat */
|
||||
+/*
|
||||
+ * For UP we don't need to worry about TLB flush
|
||||
+ * and page free order so much..
|
||||
+ */
|
||||
+#ifdef CONFIG_SMP
|
||||
+ #define FREE_PTE_NR 506
|
||||
+ #define tlb_fast_mode(tlb) ((tlb)->nr == ~0U)
|
||||
+#else
|
||||
+ #define FREE_PTE_NR 1
|
||||
+ #define tlb_fast_mode(tlb) 1
|
||||
+#endif
|
||||
+
|
||||
struct mmu_gather {
|
||||
struct mm_struct *mm;
|
||||
unsigned int fullmm;
|
@ -1,23 +0,0 @@
|
||||
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...) \
|
File diff suppressed because it is too large
Load Diff
@ -1,87 +0,0 @@
|
||||
From: IBM <lcm@us.ibm.com>
|
||||
Subject: Use apic=bigsmp on specific xseries machines
|
||||
References: bnc#440497
|
||||
Patch-Mainline: not yet
|
||||
|
||||
Signed-off-by: Thomas Renninger <trenn@suse.de>
|
||||
|
||||
|
||||
arch/x86/kernel/apic/bigsmp_32.c | 30 +++++++++++++++++++++++++++---
|
||||
arch/x86/kernel/apic/probe_32.c | 4 ++--
|
||||
2 files changed, 29 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/arch/x86/kernel/apic/bigsmp_32.c
|
||||
+++ b/arch/x86/kernel/apic/bigsmp_32.c
|
||||
@@ -156,7 +156,7 @@ static void bigsmp_send_IPI_all(int vect
|
||||
|
||||
static int dmi_bigsmp; /* can be set by dmi scanners */
|
||||
|
||||
-static int hp_ht_bigsmp(const struct dmi_system_id *d)
|
||||
+static int force_bigsmp_apic(const struct dmi_system_id *d)
|
||||
{
|
||||
printk(KERN_NOTICE "%s detected: force use of apic=bigsmp\n", d->ident);
|
||||
dmi_bigsmp = 1;
|
||||
@@ -166,17 +166,41 @@ static int hp_ht_bigsmp(const struct dmi
|
||||
|
||||
|
||||
static const struct dmi_system_id bigsmp_dmi_table[] = {
|
||||
- { hp_ht_bigsmp, "HP ProLiant DL760 G2",
|
||||
+ { force_bigsmp_apic, "HP ProLiant DL760 G2",
|
||||
{ DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
|
||||
DMI_MATCH(DMI_BIOS_VERSION, "P44-"),
|
||||
}
|
||||
},
|
||||
|
||||
- { hp_ht_bigsmp, "HP ProLiant DL740",
|
||||
+ { force_bigsmp_apic, "HP ProLiant DL740",
|
||||
{ DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
|
||||
DMI_MATCH(DMI_BIOS_VERSION, "P47-"),
|
||||
}
|
||||
},
|
||||
+
|
||||
+ { force_bigsmp_apic, "IBM x260 / x366 / x460",
|
||||
+ { DMI_MATCH(DMI_BIOS_VENDOR, "IBM"),
|
||||
+ DMI_MATCH(DMI_BIOS_VERSION, "-[ZT"),
|
||||
+ }
|
||||
+ },
|
||||
+
|
||||
+ { force_bigsmp_apic, "IBM x3800 / x3850 / x3950",
|
||||
+ { DMI_MATCH(DMI_BIOS_VENDOR, "IBM"),
|
||||
+ DMI_MATCH(DMI_BIOS_VERSION, "-[ZU"),
|
||||
+ }
|
||||
+ },
|
||||
+
|
||||
+ { force_bigsmp_apic, "IBM x3800 / x3850 / x3950",
|
||||
+ { DMI_MATCH(DMI_BIOS_VENDOR, "IBM"),
|
||||
+ DMI_MATCH(DMI_BIOS_VERSION, "-[ZS"),
|
||||
+ }
|
||||
+ },
|
||||
+
|
||||
+ { force_bigsmp_apic, "IBM x3850 M2 / x3950 M2",
|
||||
+ { DMI_MATCH(DMI_BIOS_VENDOR, "IBM"),
|
||||
+ DMI_MATCH(DMI_BIOS_VERSION, "-[A3"),
|
||||
+ }
|
||||
+ },
|
||||
{ } /* NULL entry stops DMI scanning */
|
||||
};
|
||||
|
||||
--- a/arch/x86/kernel/apic/probe_32.c
|
||||
+++ b/arch/x86/kernel/apic/probe_32.c
|
||||
@@ -267,7 +267,7 @@ generic_mps_oem_check(struct mpc_table *
|
||||
if (!apic_probe[i]->mps_oem_check(mpc, oem, productid))
|
||||
continue;
|
||||
|
||||
- if (!cmdline_apic) {
|
||||
+ if (!cmdline_apic && apic == &apic_default) {
|
||||
apic = apic_probe[i];
|
||||
printk(KERN_INFO "Switched to APIC driver `%s'.\n",
|
||||
apic->name);
|
||||
@@ -287,7 +287,7 @@ int __init default_acpi_madt_oem_check(c
|
||||
if (!apic_probe[i]->acpi_madt_oem_check(oem_id, oem_table_id))
|
||||
continue;
|
||||
|
||||
- if (!cmdline_apic) {
|
||||
+ if (!cmdline_apic && apic == &apic_default) {
|
||||
apic = apic_probe[i];
|
||||
printk(KERN_INFO "Switched to APIC driver `%s'.\n",
|
||||
apic->name);
|
@ -1,26 +0,0 @@
|
||||
From: Takashi Iwai <tiwai@suse.de>
|
||||
Subject: x86: workaround for mccreary HPET read problem
|
||||
Patch-mainline: not yet
|
||||
References: bnc#433746
|
||||
|
||||
On mccreacy platform, the read of HPET CMP register seems not updated
|
||||
immediately after the write and returns the previous value instead.
|
||||
A workaround is to read the register twice.
|
||||
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
|
||||
---
|
||||
---
|
||||
arch/x86/kernel/hpet.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/arch/x86/kernel/hpet.c
|
||||
+++ b/arch/x86/kernel/hpet.c
|
||||
@@ -386,6 +386,7 @@ static int hpet_next_event(unsigned long
|
||||
cnt += (u32) delta;
|
||||
hpet_writel(cnt, HPET_Tn_CMP(timer));
|
||||
|
||||
+ hpet_readl(HPET_Tn_CMP(timer)); /* pre-read for bnc#433746 */
|
||||
/*
|
||||
* We need to read back the CMP register on certain HPET
|
||||
* implementations (ATI chipsets) which seem to delay the
|
@ -1,38 +0,0 @@
|
||||
From: Tejun Heo <tj@kernel.org>
|
||||
Subject: x86: disallow DAC for MCP51 PCI bridge
|
||||
References: bnc#463829
|
||||
Patch-mainline: not yet
|
||||
|
||||
MCP51 corrupts DAC transfers. Disallow it. Reported by pgnet on
|
||||
bnc#463829.
|
||||
|
||||
https://bugzilla.novell.com/show_bug.cgi?id=463829
|
||||
|
||||
Signed-off-by: Tejun Heo <tj@kernel.org>
|
||||
Reported-by: pgnet <pgnet.trash@gmail.com>
|
||||
Signed-off-by: Tejun Heo <teheo@suse.de>
|
||||
---
|
||||
arch/x86/kernel/pci-dma.c | 14 ++++++++++++++
|
||||
1 file changed, 14 insertions(+)
|
||||
|
||||
--- a/arch/x86/kernel/pci-dma.c
|
||||
+++ b/arch/x86/kernel/pci-dma.c
|
||||
@@ -322,4 +322,18 @@ static __devinit void via_no_dac(struct
|
||||
}
|
||||
}
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_ANY_ID, via_no_dac);
|
||||
+
|
||||
+/*
|
||||
+ * MCP51 PCI bridge corrupts data for DAC. Disable it. Reported in
|
||||
+ * bnc#463829.
|
||||
+ */
|
||||
+static __devinit void mcp51_no_dac(struct pci_dev *dev)
|
||||
+{
|
||||
+ if (forbid_dac == 0) {
|
||||
+ printk(KERN_INFO
|
||||
+ "PCI: MCP51 PCI bridge detected. Disabling DAC.\n");
|
||||
+ forbid_dac = 1;
|
||||
+ }
|
||||
+}
|
||||
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, 0x026f, mcp51_no_dac);
|
||||
#endif
|
@ -1,223 +0,0 @@
|
||||
From: Jiri Bohac <jbohac@suse.cz>
|
||||
Subject: allow 64-bit mode for HPET Timer0
|
||||
References: bnc#456700
|
||||
|
||||
The kernel uses the HPET timers in 32-bit mode for clock-events.
|
||||
While 32 bits, with a wrap-around time of >4 minutes, is probably
|
||||
good enough for the clock-event purposes, on some chipsets this
|
||||
has a negative side-effect on the HPET main counter.
|
||||
|
||||
Unlike the original HPET specification 1.0 from 2004, which does not
|
||||
mention any side-effects of setting TN_32MODE_CNF on the
|
||||
individual timers, the ICH9 documentation, for example, says:
|
||||
|
||||
NOTE: When this bit is set to ‘1’, the hardware counter will
|
||||
do a 32-bit operation on comparator match and rollovers, thus
|
||||
the upper 32-bit of the Timer 0 Comparator Value register is
|
||||
ignored. The upper 32-bit of the main counter is not involved
|
||||
in any rollover from lower 32-bit of the main counter and
|
||||
becomes all zeros.
|
||||
|
||||
(see http://www.intel.com/assets/pdf/datasheet/316972.pdf, page
|
||||
819, section 21.1.5, Bit 8). I've seen this behaviour also on
|
||||
ICH8. I have no idea what other chipsets are affected. But I have
|
||||
seen AMD chipsets that Do The Right Thing.
|
||||
|
||||
This means, that when the kernel configures the Timer 0 to 32-bit
|
||||
mode, on these chipsets it also cripples the 64-bit main counter
|
||||
to 32 bits.
|
||||
|
||||
The HPET may be mmapped in userspace and the main counter
|
||||
accessed directly by applications, expecting a 64-bit main
|
||||
counter.
|
||||
|
||||
This patch allows the Timer0 to be configured in 64-bit mode
|
||||
on x86_64 when a hpet64 command-line option is specified.
|
||||
|
||||
Updated-by: Jeff Mahoney <jeffm@suse.com>
|
||||
Signed-off-by: Jiri Bohac <jbohac@suse.cz>
|
||||
|
||||
---
|
||||
Documentation/kernel-parameters.txt | 2
|
||||
arch/x86/kernel/hpet.c | 88 ++++++++++++++++++++++++++++++++----
|
||||
2 files changed, 81 insertions(+), 9 deletions(-)
|
||||
|
||||
--- a/Documentation/kernel-parameters.txt
|
||||
+++ b/Documentation/kernel-parameters.txt
|
||||
@@ -497,6 +497,8 @@ and is between 256 and 4096 characters.
|
||||
Range: 0 - 8192
|
||||
Default: 64
|
||||
|
||||
+ hpet64 [X86-64,HPET] enable 64-bit mode of the HPET timer (bnc#456700)
|
||||
+
|
||||
com20020= [HW,NET] ARCnet - COM20020 chipset
|
||||
Format:
|
||||
<io>[,<irq>[,<nodeID>[,<backplane>[,<ckp>[,<timeout>]]]]]
|
||||
--- a/arch/x86/kernel/hpet.c
|
||||
+++ b/arch/x86/kernel/hpet.c
|
||||
@@ -37,6 +37,7 @@ unsigned long hpet_address;
|
||||
static unsigned long hpet_num_timers;
|
||||
#endif
|
||||
static void __iomem *hpet_virt_address;
|
||||
+static int hpet_legacy_use_64_bits;
|
||||
|
||||
struct hpet_dev {
|
||||
struct clock_event_device evt;
|
||||
@@ -59,6 +60,33 @@ static inline void hpet_writel(unsigned
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
#include <asm/pgtable.h>
|
||||
+static inline unsigned long hpet_read_value(unsigned long a)
|
||||
+{
|
||||
+ if (hpet_legacy_use_64_bits)
|
||||
+ return readq(hpet_virt_address + a);
|
||||
+ else
|
||||
+ return readl(hpet_virt_address + a);
|
||||
+}
|
||||
+
|
||||
+static void hpet_write_value(unsigned long d, unsigned long a)
|
||||
+{
|
||||
+ if (hpet_legacy_use_64_bits)
|
||||
+ writeq(d, hpet_virt_address + a);
|
||||
+ else
|
||||
+ writel(d, hpet_virt_address + a);
|
||||
+}
|
||||
+
|
||||
+#else
|
||||
+
|
||||
+static inline unsigned long hpet_read_value(unsigned long a)
|
||||
+{
|
||||
+ return readl(hpet_virt_address + a);
|
||||
+}
|
||||
+
|
||||
+static void hpet_write_value(unsigned long d, unsigned long a)
|
||||
+{
|
||||
+ writel(d, hpet_virt_address + a);
|
||||
+}
|
||||
#endif
|
||||
|
||||
static inline void hpet_set_mapping(void)
|
||||
@@ -103,6 +131,17 @@ static int __init disable_hpet(char *str
|
||||
}
|
||||
__setup("nohpet", disable_hpet);
|
||||
|
||||
+#ifdef CONFIG_X86_64
|
||||
+static int hpet64 = 0;
|
||||
+static int __init hpet64_setup(char *str)
|
||||
+{
|
||||
+ hpet64 = 1;
|
||||
+ return 1;
|
||||
+}
|
||||
+__setup("hpet64", hpet64_setup);
|
||||
+#endif
|
||||
+
|
||||
+
|
||||
static inline int is_hpet_capable(void)
|
||||
{
|
||||
return !boot_hpet_disable && hpet_address;
|
||||
@@ -212,6 +251,7 @@ static void hpet_reserve_platform_timers
|
||||
* Common hpet info
|
||||
*/
|
||||
static unsigned long hpet_period;
|
||||
+static int hpet_legacy_use_64_bits; /* configure T0 in 64-bit mode? */
|
||||
|
||||
static void hpet_legacy_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt);
|
||||
@@ -278,10 +318,38 @@ static void hpet_enable_legacy_int(void)
|
||||
hpet_legacy_int_enabled = 1;
|
||||
}
|
||||
|
||||
+static int timer0_use_64_bits(void)
|
||||
+{
|
||||
+#ifndef CONFIG_X86_64
|
||||
+ /* using the HPET in 64-bit mode without atomic 64-bit
|
||||
+ * accesses is too inefficient
|
||||
+ */
|
||||
+ return 0;
|
||||
+#else
|
||||
+
|
||||
+ if (unlikely(hpet64)) {
|
||||
+ u32 id, t0_cfg;
|
||||
+ id = hpet_readl(HPET_ID);
|
||||
+ t0_cfg = hpet_readl(HPET_Tn_CFG(0));
|
||||
+
|
||||
+ if ((id & HPET_ID_64BIT) && (t0_cfg & HPET_TN_64BIT_CAP)) {
|
||||
+ printk(KERN_DEBUG "hpet timer0 configured in 64-bit mode\n");
|
||||
+ return 1;
|
||||
+ }
|
||||
+ else {
|
||||
+ printk(KERN_DEBUG "hpet timer0 does not support 64-bit mode\n");
|
||||
+ return 0;
|
||||
+ }
|
||||
+ }
|
||||
+ else return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
static void hpet_legacy_clockevent_register(void)
|
||||
{
|
||||
/* Start HPET legacy interrupts */
|
||||
hpet_enable_legacy_int();
|
||||
+ hpet_legacy_use_64_bits = timer0_use_64_bits();
|
||||
|
||||
/*
|
||||
* The mult factor is defined as (include/linux/clockchips.h)
|
||||
@@ -328,9 +396,10 @@ static void hpet_set_mode(enum clock_eve
|
||||
/* Make sure we use edge triggered interrupts */
|
||||
cfg &= ~HPET_TN_LEVEL;
|
||||
cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC |
|
||||
- HPET_TN_SETVAL | HPET_TN_32BIT;
|
||||
+ HPET_TN_SETVAL |
|
||||
+ (hpet_legacy_use_64_bits ? 0 : HPET_TN_32BIT);
|
||||
hpet_writel(cfg, HPET_Tn_CFG(timer));
|
||||
- hpet_writel(cmp, HPET_Tn_CMP(timer));
|
||||
+ hpet_write_value(cmp, HPET_Tn_CMP(timer));
|
||||
udelay(1);
|
||||
/*
|
||||
* HPET on AMD 81xx needs a second write (with HPET_TN_SETVAL
|
||||
@@ -339,7 +408,7 @@ static void hpet_set_mode(enum clock_eve
|
||||
* (See AMD-8111 HyperTransport I/O Hub Data Sheet,
|
||||
* Publication # 24674)
|
||||
*/
|
||||
- hpet_writel((unsigned long) delta, HPET_Tn_CMP(timer));
|
||||
+ hpet_write_value((unsigned long) delta, HPET_Tn_CMP(timer));
|
||||
hpet_start_counter();
|
||||
hpet_print_config();
|
||||
break;
|
||||
@@ -347,7 +416,8 @@ static void hpet_set_mode(enum clock_eve
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
cfg = hpet_readl(HPET_Tn_CFG(timer));
|
||||
cfg &= ~HPET_TN_PERIODIC;
|
||||
- cfg |= HPET_TN_ENABLE | HPET_TN_32BIT;
|
||||
+ cfg |= HPET_TN_ENABLE |
|
||||
+ (hpet_legacy_use_64_bits ? 0 : HPET_TN_32BIT);
|
||||
hpet_writel(cfg, HPET_Tn_CFG(timer));
|
||||
break;
|
||||
|
||||
@@ -376,11 +446,11 @@ static void hpet_set_mode(enum clock_eve
|
||||
static int hpet_next_event(unsigned long delta,
|
||||
struct clock_event_device *evt, int timer)
|
||||
{
|
||||
- u32 cnt;
|
||||
+ unsigned long cnt;
|
||||
|
||||
- cnt = hpet_readl(HPET_COUNTER);
|
||||
+ cnt = hpet_read_value(HPET_COUNTER);
|
||||
cnt += (u32) delta;
|
||||
- hpet_writel(cnt, HPET_Tn_CMP(timer));
|
||||
+ hpet_write_value(cnt, HPET_Tn_CMP(timer));
|
||||
|
||||
hpet_readl(HPET_Tn_CMP(timer)); /* pre-read for bnc#433746 */
|
||||
/*
|
||||
@@ -388,9 +458,9 @@ static int hpet_next_event(unsigned long
|
||||
* what we wrote hit the chip before we compare it to the
|
||||
* counter.
|
||||
*/
|
||||
- WARN_ON_ONCE((u32)hpet_readl(HPET_Tn_CMP(timer)) != cnt);
|
||||
+ WARN_ON_ONCE((u32)hpet_readl(HPET_Tn_CMP(timer)) != (u32)cnt);
|
||||
|
||||
- return (s32)((u32)hpet_readl(HPET_COUNTER) - cnt) >= 0 ? -ETIME : 0;
|
||||
+ return (s32)((u32)hpet_readl(HPET_COUNTER) - (u32)cnt) >= 0 ? -ETIME : 0;
|
||||
}
|
||||
|
||||
static void hpet_legacy_set_mode(enum clock_event_mode mode,
|
@ -1,439 +0,0 @@
|
||||
From: jbeulich@novell.com
|
||||
Subject: fix unwind annotations
|
||||
Patch-mainline: tbd
|
||||
References: bnc#472783, bnc#588458
|
||||
|
||||
---
|
||||
arch/x86/kernel/entry_64.S | 131 +++++++++++++++++++++++----------------------
|
||||
arch/x86/kernel/head_64.S | 13 ++++
|
||||
lib/rwsem_64.S | 56 ++++++++++++++---------
|
||||
3 files changed, 114 insertions(+), 84 deletions(-)
|
||||
|
||||
--- a/arch/x86/kernel/entry_64.S
|
||||
+++ b/arch/x86/kernel/entry_64.S
|
||||
@@ -234,21 +234,21 @@ ENDPROC(native_usergs_sysret64)
|
||||
/*
|
||||
* initial frame state for interrupts (and exceptions without error code)
|
||||
*/
|
||||
- .macro EMPTY_FRAME start=1 offset=0
|
||||
- .if \start
|
||||
+ .macro EMPTY_FRAME offset=0
|
||||
CFI_STARTPROC simple
|
||||
CFI_SIGNAL_FRAME
|
||||
- CFI_DEF_CFA rsp,8+\offset
|
||||
- .else
|
||||
- CFI_DEF_CFA_OFFSET 8+\offset
|
||||
- .endif
|
||||
+ CFI_DEF_CFA rsp,\offset
|
||||
.endm
|
||||
|
||||
/*
|
||||
* initial frame state for interrupts (and exceptions without error code)
|
||||
*/
|
||||
.macro INTR_FRAME start=1 offset=0
|
||||
- EMPTY_FRAME \start, SS+8+\offset-RIP
|
||||
+ .if \start
|
||||
+ EMPTY_FRAME SS+8+\offset-RIP
|
||||
+ .else
|
||||
+ CFI_DEF_CFA_OFFSET SS+8+\offset-RIP
|
||||
+ .endif
|
||||
/*CFI_REL_OFFSET ss, SS+\offset-RIP*/
|
||||
CFI_REL_OFFSET rsp, RSP+\offset-RIP
|
||||
/*CFI_REL_OFFSET rflags, EFLAGS+\offset-RIP*/
|
||||
@@ -262,14 +262,15 @@ ENDPROC(native_usergs_sysret64)
|
||||
*/
|
||||
.macro XCPT_FRAME start=1 offset=0
|
||||
INTR_FRAME \start, RIP+\offset-ORIG_RAX
|
||||
- /*CFI_REL_OFFSET orig_rax, ORIG_RAX-ORIG_RAX*/
|
||||
.endm
|
||||
|
||||
/*
|
||||
* frame that enables calling into C.
|
||||
*/
|
||||
.macro PARTIAL_FRAME start=1 offset=0
|
||||
+ .if \start >= 0
|
||||
XCPT_FRAME \start, ORIG_RAX+\offset-ARGOFFSET
|
||||
+ .endif
|
||||
CFI_REL_OFFSET rdi, RDI+\offset-ARGOFFSET
|
||||
CFI_REL_OFFSET rsi, RSI+\offset-ARGOFFSET
|
||||
CFI_REL_OFFSET rdx, RDX+\offset-ARGOFFSET
|
||||
@@ -285,7 +286,9 @@ ENDPROC(native_usergs_sysret64)
|
||||
* frame that enables passing a complete pt_regs to a C function.
|
||||
*/
|
||||
.macro DEFAULT_FRAME start=1 offset=0
|
||||
+ .if \start >= -1
|
||||
PARTIAL_FRAME \start, R11+\offset-R15
|
||||
+ .endif
|
||||
CFI_REL_OFFSET rbx, RBX+\offset
|
||||
CFI_REL_OFFSET rbp, RBP+\offset
|
||||
CFI_REL_OFFSET r12, R12+\offset
|
||||
@@ -297,25 +300,27 @@ ENDPROC(native_usergs_sysret64)
|
||||
/* save partial stack frame */
|
||||
.pushsection .kprobes.text, "ax"
|
||||
ENTRY(save_args)
|
||||
- XCPT_FRAME
|
||||
+ XCPT_FRAME offset=ORIG_RAX-RBP+8
|
||||
cld
|
||||
/*
|
||||
* start from rbp in pt_regs and jump over
|
||||
* return address.
|
||||
*/
|
||||
movq_cfi rdi, RDI+8-RBP
|
||||
- movq_cfi rsi, RSI+8-RBP
|
||||
- movq_cfi rdx, RDX+8-RBP
|
||||
- movq_cfi rcx, RCX+8-RBP
|
||||
+ movq %rsi, RSI+8-RBP(%rsp)
|
||||
+ movq %rdx, RDX+8-RBP(%rsp)
|
||||
+ movq %rcx, RCX+8-RBP(%rsp)
|
||||
movq_cfi rax, RAX+8-RBP
|
||||
- movq_cfi r8, R8+8-RBP
|
||||
- movq_cfi r9, R9+8-RBP
|
||||
- movq_cfi r10, R10+8-RBP
|
||||
- movq_cfi r11, R11+8-RBP
|
||||
+ movq %r8, R8+8-RBP(%rsp)
|
||||
+ movq %r9, R9+8-RBP(%rsp)
|
||||
+ movq %r10, R10+8-RBP(%rsp)
|
||||
+ movq %r11, R11+8-RBP(%rsp)
|
||||
|
||||
leaq -RBP+8(%rsp),%rdi /* arg1 for handler */
|
||||
movq_cfi rbp, 8 /* push %rbp */
|
||||
leaq 8(%rsp), %rbp /* mov %rsp, %ebp */
|
||||
+ CFI_DEF_CFA_REGISTER rbp
|
||||
+ CFI_ADJUST_CFA_OFFSET -8
|
||||
testl $3, CS(%rdi)
|
||||
je 1f
|
||||
SWAPGS
|
||||
@@ -327,11 +332,10 @@ ENTRY(save_args)
|
||||
*/
|
||||
1: incl PER_CPU_VAR(irq_count)
|
||||
jne 2f
|
||||
- popq_cfi %rax /* move return address... */
|
||||
+ popq %rax /* move return address... */
|
||||
mov PER_CPU_VAR(irq_stack_ptr),%rsp
|
||||
- EMPTY_FRAME 0
|
||||
- pushq_cfi %rbp /* backlink for unwinder */
|
||||
- pushq_cfi %rax /* ... to the new stack */
|
||||
+ pushq %rbp /* backlink for unwinder */
|
||||
+ pushq %rax /* ... to the new stack */
|
||||
/*
|
||||
* We entered an interrupt context - irqs are off:
|
||||
*/
|
||||
@@ -342,14 +346,14 @@ END(save_args)
|
||||
.popsection
|
||||
|
||||
ENTRY(save_rest)
|
||||
- PARTIAL_FRAME 1 REST_SKIP+8
|
||||
+ CFI_STARTPROC
|
||||
movq 5*8+16(%rsp), %r11 /* save return address */
|
||||
- movq_cfi rbx, RBX+16
|
||||
- movq_cfi rbp, RBP+16
|
||||
- movq_cfi r12, R12+16
|
||||
- movq_cfi r13, R13+16
|
||||
- movq_cfi r14, R14+16
|
||||
- movq_cfi r15, R15+16
|
||||
+ movq %rbx, RBX+16(%rsp)
|
||||
+ movq %rbp, RBP+16(%rsp)
|
||||
+ movq %r12, R12+16(%rsp)
|
||||
+ movq %r13, R13+16(%rsp)
|
||||
+ movq %r14, R14+16(%rsp)
|
||||
+ movq %r15, R15+16(%rsp)
|
||||
movq %r11, 8(%rsp) /* return address */
|
||||
FIXUP_TOP_OF_STACK %r11, 16
|
||||
ret
|
||||
@@ -359,23 +363,23 @@ END(save_rest)
|
||||
/* save complete stack frame */
|
||||
.pushsection .kprobes.text, "ax"
|
||||
ENTRY(save_paranoid)
|
||||
- XCPT_FRAME 1 RDI+8
|
||||
+ XCPT_FRAME offset=ORIG_RAX-R15+8
|
||||
cld
|
||||
- movq_cfi rdi, RDI+8
|
||||
- movq_cfi rsi, RSI+8
|
||||
+ movq %rdi, RDI+8(%rsp)
|
||||
+ movq %rsi, RSI+8(%rsp)
|
||||
movq_cfi rdx, RDX+8
|
||||
movq_cfi rcx, RCX+8
|
||||
movq_cfi rax, RAX+8
|
||||
- movq_cfi r8, R8+8
|
||||
- movq_cfi r9, R9+8
|
||||
- movq_cfi r10, R10+8
|
||||
- movq_cfi r11, R11+8
|
||||
+ movq %r8, R8+8(%rsp)
|
||||
+ movq %r9, R9+8(%rsp)
|
||||
+ movq %r10, R10+8(%rsp)
|
||||
+ movq %r11, R11+8(%rsp)
|
||||
movq_cfi rbx, RBX+8
|
||||
- movq_cfi rbp, RBP+8
|
||||
- movq_cfi r12, R12+8
|
||||
- movq_cfi r13, R13+8
|
||||
- movq_cfi r14, R14+8
|
||||
- movq_cfi r15, R15+8
|
||||
+ movq %rbp, RBP+8(%rsp)
|
||||
+ movq %r12, R12+8(%rsp)
|
||||
+ movq %r13, R13+8(%rsp)
|
||||
+ movq %r14, R14+8(%rsp)
|
||||
+ movq %r15, R15+8(%rsp)
|
||||
movl $1,%ebx
|
||||
movl $MSR_GS_BASE,%ecx
|
||||
rdmsr
|
||||
@@ -677,7 +681,7 @@ ENTRY(\label)
|
||||
subq $REST_SKIP, %rsp
|
||||
CFI_ADJUST_CFA_OFFSET REST_SKIP
|
||||
call save_rest
|
||||
- DEFAULT_FRAME 0 8 /* offset 8: return address */
|
||||
+ DEFAULT_FRAME -2 8 /* offset 8: return address */
|
||||
leaq 8(%rsp), \arg /* pt_regs pointer */
|
||||
call \func
|
||||
jmp ptregscall_common
|
||||
@@ -794,7 +798,9 @@ END(interrupt)
|
||||
subq $ORIG_RAX-RBP, %rsp
|
||||
CFI_ADJUST_CFA_OFFSET ORIG_RAX-RBP
|
||||
call save_args
|
||||
- PARTIAL_FRAME 0
|
||||
+ PARTIAL_FRAME -1 ARGOFFSET-RBP
|
||||
+ CFI_REL_OFFSET rbp, 0
|
||||
+ CFI_DEF_CFA_REGISTER rbp
|
||||
call \func
|
||||
.endm
|
||||
|
||||
@@ -813,7 +819,6 @@ ret_from_intr:
|
||||
TRACE_IRQS_OFF
|
||||
decl PER_CPU_VAR(irq_count)
|
||||
leaveq
|
||||
-
|
||||
CFI_RESTORE rbp
|
||||
CFI_DEF_CFA_REGISTER rsp
|
||||
CFI_ADJUST_CFA_OFFSET -8
|
||||
@@ -1021,7 +1026,7 @@ ENTRY(\sym)
|
||||
subq $ORIG_RAX-R15, %rsp
|
||||
CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
|
||||
call error_entry
|
||||
- DEFAULT_FRAME 0
|
||||
+ DEFAULT_FRAME -1
|
||||
movq %rsp,%rdi /* pt_regs pointer */
|
||||
xorl %esi,%esi /* no error code */
|
||||
call \do_sym
|
||||
@@ -1038,6 +1043,7 @@ ENTRY(\sym)
|
||||
subq $ORIG_RAX-R15, %rsp
|
||||
CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
|
||||
call save_paranoid
|
||||
+ DEFAULT_FRAME -1
|
||||
TRACE_IRQS_OFF
|
||||
movq %rsp,%rdi /* pt_regs pointer */
|
||||
xorl %esi,%esi /* no error code */
|
||||
@@ -1056,6 +1062,7 @@ ENTRY(\sym)
|
||||
subq $ORIG_RAX-R15, %rsp
|
||||
CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
|
||||
call save_paranoid
|
||||
+ DEFAULT_FRAME -1
|
||||
TRACE_IRQS_OFF
|
||||
movq %rsp,%rdi /* pt_regs pointer */
|
||||
xorl %esi,%esi /* no error code */
|
||||
@@ -1074,7 +1081,7 @@ ENTRY(\sym)
|
||||
subq $ORIG_RAX-R15, %rsp
|
||||
CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
|
||||
call error_entry
|
||||
- DEFAULT_FRAME 0
|
||||
+ DEFAULT_FRAME -1
|
||||
movq %rsp,%rdi /* pt_regs pointer */
|
||||
movq ORIG_RAX(%rsp),%rsi /* get error code */
|
||||
movq $-1,ORIG_RAX(%rsp) /* no syscall to restart */
|
||||
@@ -1092,7 +1099,7 @@ ENTRY(\sym)
|
||||
subq $ORIG_RAX-R15, %rsp
|
||||
CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
|
||||
call save_paranoid
|
||||
- DEFAULT_FRAME 0
|
||||
+ DEFAULT_FRAME -1
|
||||
TRACE_IRQS_OFF
|
||||
movq %rsp,%rdi /* pt_regs pointer */
|
||||
movq ORIG_RAX(%rsp),%rsi /* get error code */
|
||||
@@ -1435,25 +1442,24 @@ END(paranoid_exit)
|
||||
* returns in "no swapgs flag" in %ebx.
|
||||
*/
|
||||
ENTRY(error_entry)
|
||||
- XCPT_FRAME
|
||||
- CFI_ADJUST_CFA_OFFSET 15*8
|
||||
+ XCPT_FRAME offset=ORIG_RAX-R15+8
|
||||
/* oldrax contains error code */
|
||||
cld
|
||||
- movq_cfi rdi, RDI+8
|
||||
- movq_cfi rsi, RSI+8
|
||||
- movq_cfi rdx, RDX+8
|
||||
- movq_cfi rcx, RCX+8
|
||||
- movq_cfi rax, RAX+8
|
||||
- movq_cfi r8, R8+8
|
||||
- movq_cfi r9, R9+8
|
||||
- movq_cfi r10, R10+8
|
||||
- movq_cfi r11, R11+8
|
||||
+ movq %rdi, RDI+8(%rsp)
|
||||
+ movq %rsi, RSI+8(%rsp)
|
||||
+ movq %rdx, RDX+8(%rsp)
|
||||
+ movq %rcx, RCX+8(%rsp)
|
||||
+ movq %rax, RAX+8(%rsp)
|
||||
+ movq %r8, R8+8(%rsp)
|
||||
+ movq %r9, R9+8(%rsp)
|
||||
+ movq %r10, R10+8(%rsp)
|
||||
+ movq %r11, R11+8(%rsp)
|
||||
movq_cfi rbx, RBX+8
|
||||
- movq_cfi rbp, RBP+8
|
||||
- movq_cfi r12, R12+8
|
||||
- movq_cfi r13, R13+8
|
||||
- movq_cfi r14, R14+8
|
||||
- movq_cfi r15, R15+8
|
||||
+ movq %rbp, RBP+8(%rsp)
|
||||
+ movq %r12, R12+8(%rsp)
|
||||
+ movq %r13, R13+8(%rsp)
|
||||
+ movq %r14, R14+8(%rsp)
|
||||
+ movq %r15, R15+8(%rsp)
|
||||
xorl %ebx,%ebx
|
||||
testl $3,CS+8(%rsp)
|
||||
je error_kernelspace
|
||||
@@ -1471,6 +1477,7 @@ error_sti:
|
||||
* compat mode. Check for these here too.
|
||||
*/
|
||||
error_kernelspace:
|
||||
+ CFI_REL_OFFSET rcx, RCX+8
|
||||
incl %ebx
|
||||
leaq irq_return(%rip),%rcx
|
||||
cmpq %rcx,RIP+8(%rsp)
|
||||
@@ -1518,7 +1523,7 @@ ENTRY(nmi)
|
||||
subq $ORIG_RAX-R15, %rsp
|
||||
CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
|
||||
call save_paranoid
|
||||
- DEFAULT_FRAME 0
|
||||
+ DEFAULT_FRAME -1
|
||||
/* paranoidentry do_nmi, 0; without TRACE_IRQS_OFF */
|
||||
movq %rsp,%rdi
|
||||
movq $-1,%rsi
|
||||
--- a/arch/x86/kernel/head_64.S
|
||||
+++ b/arch/x86/kernel/head_64.S
|
||||
@@ -284,6 +284,8 @@ early_idt_handlers:
|
||||
|
||||
ENTRY(early_idt_handler)
|
||||
#ifdef CONFIG_EARLY_PRINTK
|
||||
+#include <asm/calling.h>
|
||||
+#include <asm/dwarf2.h>
|
||||
cmpl $2,early_recursion_flag(%rip)
|
||||
jz 1f
|
||||
incl early_recursion_flag(%rip)
|
||||
@@ -299,6 +301,16 @@ ENTRY(early_idt_handler)
|
||||
testl $0x27d00,%eax
|
||||
je 0f
|
||||
popq %r8 # get error code
|
||||
+
|
||||
+ CFI_STARTPROC simple
|
||||
+ CFI_SIGNAL_FRAME
|
||||
+ CFI_DEF_CFA rsp, SS+8-RIP
|
||||
+# CFI_REL_OFFSET ss, SS-RIP
|
||||
+ CFI_REL_OFFSET rsp, RSP-RIP
|
||||
+# CFI_REL_OFFSET rflags, EFLAGS-RIP
|
||||
+# CFI_REL_OFFSET cs, CS-RIP
|
||||
+ CFI_REL_OFFSET rip, RIP-RIP
|
||||
+
|
||||
0: movq 0(%rsp),%rcx # get ip
|
||||
movq 8(%rsp),%rdx # get cs
|
||||
xorl %eax,%eax
|
||||
@@ -312,6 +324,7 @@ ENTRY(early_idt_handler)
|
||||
movq 0(%rsp),%rsi # get rip again
|
||||
call __print_symbol
|
||||
#endif
|
||||
+ CFI_ENDPROC
|
||||
#endif /* EARLY_PRINTK */
|
||||
1: hlt
|
||||
jmp 1b
|
||||
--- a/arch/x86/lib/rwsem_64.S
|
||||
+++ b/arch/x86/lib/rwsem_64.S
|
||||
@@ -23,43 +23,50 @@
|
||||
#include <asm/dwarf2.h>
|
||||
|
||||
#define save_common_regs \
|
||||
- pushq %rdi; \
|
||||
- pushq %rsi; \
|
||||
- pushq %rcx; \
|
||||
- pushq %r8; \
|
||||
- pushq %r9; \
|
||||
- pushq %r10; \
|
||||
- pushq %r11
|
||||
+ pushq_cfi %rdi; CFI_REL_OFFSET rdi, 0; \
|
||||
+ pushq_cfi %rsi; CFI_REL_OFFSET rsi, 0; \
|
||||
+ pushq_cfi %rcx; CFI_REL_OFFSET rcx, 0; \
|
||||
+ pushq_cfi %r8; CFI_REL_OFFSET r8, 0; \
|
||||
+ pushq_cfi %r9; CFI_REL_OFFSET r9, 0; \
|
||||
+ pushq_cfi %r10; CFI_REL_OFFSET r10, 0; \
|
||||
+ pushq_cfi %r11; CFI_REL_OFFSET r11, 0
|
||||
|
||||
#define restore_common_regs \
|
||||
- popq %r11; \
|
||||
- popq %r10; \
|
||||
- popq %r9; \
|
||||
- popq %r8; \
|
||||
- popq %rcx; \
|
||||
- popq %rsi; \
|
||||
- popq %rdi
|
||||
+ popq_cfi %r11; CFI_RESTORE r11; \
|
||||
+ popq_cfi %r10; CFI_RESTORE r10; \
|
||||
+ popq_cfi %r9; CFI_RESTORE r9; \
|
||||
+ popq_cfi %r8; CFI_RESTORE r8; \
|
||||
+ popq_cfi %rcx; CFI_RESTORE rcx; \
|
||||
+ popq_cfi %rsi; CFI_RESTORE rsi; \
|
||||
+ popq_cfi %rdi; CFI_RESTORE rdi
|
||||
|
||||
/* Fix up special calling conventions */
|
||||
ENTRY(call_rwsem_down_read_failed)
|
||||
+ CFI_STARTPROC
|
||||
save_common_regs
|
||||
- pushq %rdx
|
||||
+ pushq_cfi %rdx
|
||||
+ CFI_REL_OFFSET rdx, 0
|
||||
movq %rax,%rdi
|
||||
call rwsem_down_read_failed
|
||||
- popq %rdx
|
||||
+ popq_cfi %rdx
|
||||
+ CFI_RESTORE rdx
|
||||
restore_common_regs
|
||||
ret
|
||||
- ENDPROC(call_rwsem_down_read_failed)
|
||||
+ CFI_ENDPROC
|
||||
+ENDPROC(call_rwsem_down_read_failed)
|
||||
|
||||
ENTRY(call_rwsem_down_write_failed)
|
||||
+ CFI_STARTPROC
|
||||
save_common_regs
|
||||
movq %rax,%rdi
|
||||
call rwsem_down_write_failed
|
||||
restore_common_regs
|
||||
ret
|
||||
- ENDPROC(call_rwsem_down_write_failed)
|
||||
+ CFI_ENDPROC
|
||||
+ENDPROC(call_rwsem_down_write_failed)
|
||||
|
||||
ENTRY(call_rwsem_wake)
|
||||
+ CFI_STARTPROC
|
||||
decl %edx /* do nothing if still outstanding active readers */
|
||||
jnz 1f
|
||||
save_common_regs
|
||||
@@ -67,15 +74,20 @@ ENTRY(call_rwsem_wake)
|
||||
call rwsem_wake
|
||||
restore_common_regs
|
||||
1: ret
|
||||
- ENDPROC(call_rwsem_wake)
|
||||
+ CFI_ENDPROC
|
||||
+ENDPROC(call_rwsem_wake)
|
||||
|
||||
/* Fix up special calling conventions */
|
||||
ENTRY(call_rwsem_downgrade_wake)
|
||||
+ CFI_STARTPROC
|
||||
save_common_regs
|
||||
- pushq %rdx
|
||||
+ pushq_cfi %rdx
|
||||
+ CFI_REL_OFFSET rdx, 0
|
||||
movq %rax,%rdi
|
||||
call rwsem_downgrade_wake
|
||||
- popq %rdx
|
||||
+ popq_cfi %rdx
|
||||
+ CFI_RESTORE rdx
|
||||
restore_common_regs
|
||||
ret
|
||||
- ENDPROC(call_rwsem_downgrade_wake)
|
||||
+ CFI_ENDPROC
|
||||
+ENDPROC(call_rwsem_downgrade_wake)
|
@ -1,74 +0,0 @@
|
||||
From: Brandon Philips <bphilips@suse.de>
|
||||
Subject: Avoid oops on G33 in 1MB stolen Mem case
|
||||
References: bnc#391261
|
||||
Patch-Mainline: soon (see bug for ref)
|
||||
|
||||
This is similar to f443675affe3f16dd428e46f0f7fd3f4d703eeab which was
|
||||
reverted because it broke with older XOrg driver. This patch only fixes
|
||||
the 1MB stolen case since it causes an oops due to a calculation
|
||||
problem.
|
||||
|
||||
This will not work with older X drivers without the accompanying patch
|
||||
but I think avoiding an oops and making it possible to work with an
|
||||
up-to-date xorg driver is reasonable.
|
||||
|
||||
Explanation of the oops:
|
||||
|
||||
> static void intel_i830_init_gtt_entries(void)
|
||||
...
|
||||
> } else if (IS_G33) {
|
||||
> /* G33's GTT size defined in gmch_ctrl */
|
||||
> switch (gmch_ctrl & G33_PGETBL_SIZE_MASK) {
|
||||
> case G33_PGETBL_SIZE_1M:
|
||||
> size = 1024;
|
||||
> break;
|
||||
...
|
||||
> size += 4;
|
||||
|
||||
size = 1028
|
||||
|
||||
Then since we have the BIOS setting 1MB for the device in the GMCH
|
||||
control we get to here:
|
||||
|
||||
> } else {
|
||||
> switch (gmch_ctrl & I855_GMCH_GMS_MASK) {
|
||||
> case I855_GMCH_GMS_STOLEN_1M:
|
||||
> gtt_entries = MB(1) - KB(size);
|
||||
> break;
|
||||
|
||||
MB(1) = 1 * 1024 * 1024
|
||||
KB(1028) = 1028 * 1024
|
||||
|
||||
MB(1) - KB(1028) = -4096
|
||||
|
||||
> gtt_entries /= KB(4);
|
||||
> intel_private.gtt_entries = gtt_entries;
|
||||
|
||||
We end up with -1 in gtt_entries.
|
||||
|
||||
This leads to intel_i915_configure reading/writing to areas outside of
|
||||
mapped memory and the oops.
|
||||
|
||||
Signed-off-by: Brandon Philips <bphilips@suse.de>
|
||||
Acked-by: Thomas Renninger <trenn@suse.de>
|
||||
|
||||
---
|
||||
drivers/char/agp/intel-gtt.c | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
--- a/drivers/char/agp/intel-gtt.c
|
||||
+++ b/drivers/char/agp/intel-gtt.c
|
||||
@@ -648,6 +648,13 @@ static void intel_i830_init_gtt_entries(
|
||||
} else {
|
||||
switch (gmch_ctrl & I855_GMCH_GMS_MASK) {
|
||||
case I855_GMCH_GMS_STOLEN_1M:
|
||||
+ if (IS_G33) {
|
||||
+ size = 0;
|
||||
+ printk(KERN_WARNING PFX
|
||||
+ "Warning: G33 chipset with 1MB"
|
||||
+ " allocated. Older X.org Intel drivers"
|
||||
+ " will not work.\n");
|
||||
+ }
|
||||
gtt_entries = MB(1) - KB(size);
|
||||
break;
|
||||
case I855_GMCH_GMS_STOLEN_4M:
|
@ -1,126 +0,0 @@
|
||||
From 3cd8c73bebbc64ab13173931012ed4a58717b446 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Wilson <chris@chris-wilson.co.uk>
|
||||
Date: Tue, 12 Apr 2011 18:06:51 +0100
|
||||
Subject: [PATCH 1/2] drm/i915: Sanitize the output registers after resume
|
||||
|
||||
commit f6e5b1603b8bb7131b6778d0d4e2e5dda120a379 upstream.
|
||||
|
||||
Similar to booting, we need to inspect the state left by the BIOS and
|
||||
remove any conflicting bits before we take over. The example reported by
|
||||
Seth Forshee is very similar to the bug we encountered with the state left
|
||||
by grub2, that the crtc pipe<->planning mapping was reversed from our
|
||||
expectations and so we failed to turn off the outputs when booting or,
|
||||
in this case, resuming. This may be in fact the same bug, but triggered
|
||||
at resume time.
|
||||
|
||||
This patch rearranges the code we already have to clear up the
|
||||
conflicting state upon init and calls it from reset (which is called
|
||||
after we have lost control of the hardware, i.e. along both the boot and
|
||||
resume paths) instead.
|
||||
|
||||
Reported-and-tested-by: Seth Forshee <seth.forshee@canonical.com>
|
||||
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=35796
|
||||
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
|
||||
Reviewed-by: Keith Packard <keithp@keithp.com>
|
||||
Signed-off-by: Keith Packard <keithp@keithp.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
---
|
||||
drivers/gpu/drm/i915/intel_display.c | 68 ++++++++++++++++++----------------
|
||||
1 files changed, 36 insertions(+), 32 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
|
||||
index cef853b..c7403e7 100644
|
||||
--- a/drivers/gpu/drm/i915/intel_display.c
|
||||
+++ b/drivers/gpu/drm/i915/intel_display.c
|
||||
@@ -5764,36 +5764,6 @@ cleanup_work:
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static void intel_crtc_reset(struct drm_crtc *crtc)
|
||||
-{
|
||||
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
-
|
||||
- /* Reset flags back to the 'unknown' status so that they
|
||||
- * will be correctly set on the initial modeset.
|
||||
- */
|
||||
- intel_crtc->dpms_mode = -1;
|
||||
-}
|
||||
-
|
||||
-static struct drm_crtc_helper_funcs intel_helper_funcs = {
|
||||
- .dpms = intel_crtc_dpms,
|
||||
- .mode_fixup = intel_crtc_mode_fixup,
|
||||
- .mode_set = intel_crtc_mode_set,
|
||||
- .mode_set_base = intel_pipe_set_base,
|
||||
- .mode_set_base_atomic = intel_pipe_set_base_atomic,
|
||||
- .load_lut = intel_crtc_load_lut,
|
||||
- .disable = intel_crtc_disable,
|
||||
-};
|
||||
-
|
||||
-static const struct drm_crtc_funcs intel_crtc_funcs = {
|
||||
- .reset = intel_crtc_reset,
|
||||
- .cursor_set = intel_crtc_cursor_set,
|
||||
- .cursor_move = intel_crtc_cursor_move,
|
||||
- .gamma_set = intel_crtc_gamma_set,
|
||||
- .set_config = drm_crtc_helper_set_config,
|
||||
- .destroy = intel_crtc_destroy,
|
||||
- .page_flip = intel_crtc_page_flip,
|
||||
-};
|
||||
-
|
||||
static void intel_sanitize_modesetting(struct drm_device *dev,
|
||||
int pipe, int plane)
|
||||
{
|
||||
@@ -5830,6 +5800,42 @@ static void intel_sanitize_modesetting(struct drm_device *dev,
|
||||
intel_disable_pipe(dev_priv, pipe);
|
||||
}
|
||||
|
||||
+static void intel_crtc_reset(struct drm_crtc *crtc)
|
||||
+{
|
||||
+ struct drm_device *dev = crtc->dev;
|
||||
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
+
|
||||
+ /* Reset flags back to the 'unknown' status so that they
|
||||
+ * will be correctly set on the initial modeset.
|
||||
+ */
|
||||
+ intel_crtc->dpms_mode = -1;
|
||||
+
|
||||
+ /* We need to fix up any BIOS configuration that conflicts with
|
||||
+ * our expectations.
|
||||
+ */
|
||||
+ intel_sanitize_modesetting(dev, intel_crtc->pipe, intel_crtc->plane);
|
||||
+}
|
||||
+
|
||||
+static struct drm_crtc_helper_funcs intel_helper_funcs = {
|
||||
+ .dpms = intel_crtc_dpms,
|
||||
+ .mode_fixup = intel_crtc_mode_fixup,
|
||||
+ .mode_set = intel_crtc_mode_set,
|
||||
+ .mode_set_base = intel_pipe_set_base,
|
||||
+ .mode_set_base_atomic = intel_pipe_set_base_atomic,
|
||||
+ .load_lut = intel_crtc_load_lut,
|
||||
+ .disable = intel_crtc_disable,
|
||||
+};
|
||||
+
|
||||
+static const struct drm_crtc_funcs intel_crtc_funcs = {
|
||||
+ .reset = intel_crtc_reset,
|
||||
+ .cursor_set = intel_crtc_cursor_set,
|
||||
+ .cursor_move = intel_crtc_cursor_move,
|
||||
+ .gamma_set = intel_crtc_gamma_set,
|
||||
+ .set_config = drm_crtc_helper_set_config,
|
||||
+ .destroy = intel_crtc_destroy,
|
||||
+ .page_flip = intel_crtc_page_flip,
|
||||
+};
|
||||
+
|
||||
static void intel_crtc_init(struct drm_device *dev, int pipe)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
@@ -5879,8 +5885,6 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
|
||||
|
||||
setup_timer(&intel_crtc->idle_timer, intel_crtc_idle_timer,
|
||||
(unsigned long)intel_crtc);
|
||||
-
|
||||
- intel_sanitize_modesetting(dev, intel_crtc->pipe, intel_crtc->plane);
|
||||
}
|
||||
|
||||
int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
|
||||
--
|
||||
1.7.6.5
|
||||
|
@ -1,64 +0,0 @@
|
||||
From 38c1a19fb78da8c2a617b1d8a3fcafb691c1409f Mon Sep 17 00:00:00 2001
|
||||
From: Chris Wilson <chris@chris-wilson.co.uk>
|
||||
Date: Sun, 16 Jan 2011 19:37:30 +0000
|
||||
Subject: [PATCH 1/3] drm/i915: Use ACPI OpRegion to determine lid status
|
||||
|
||||
Admittedly, trusting ACPI or the BIOS at all to be correct is littered
|
||||
with numerous examples where it is wrong. Maybe, just maybe, we will
|
||||
have better luck using the ACPI OpRegion lid status...
|
||||
|
||||
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
|
||||
---
|
||||
drivers/gpu/drm/i915/i915_drv.h | 1 +
|
||||
drivers/gpu/drm/i915/intel_lvds.c | 7 +++++++
|
||||
drivers/gpu/drm/i915/intel_opregion.c | 2 ++
|
||||
3 files changed, 10 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
|
||||
index 456f404..a299cc6 100644
|
||||
--- a/drivers/gpu/drm/i915/i915_drv.h
|
||||
+++ b/drivers/gpu/drm/i915/i915_drv.h
|
||||
@@ -111,6 +111,7 @@ struct intel_opregion {
|
||||
struct opregion_swsci *swsci;
|
||||
struct opregion_asle *asle;
|
||||
void *vbt;
|
||||
+ u32 __iomem *lid_state;
|
||||
};
|
||||
#define OPREGION_SIZE (8*1024)
|
||||
|
||||
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
|
||||
index bcdba7b..aa29228 100644
|
||||
--- a/drivers/gpu/drm/i915/intel_lvds.c
|
||||
+++ b/drivers/gpu/drm/i915/intel_lvds.c
|
||||
@@ -472,8 +472,15 @@ static enum drm_connector_status
|
||||
intel_lvds_detect(struct drm_connector *connector, bool force)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
+ struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
enum drm_connector_status status = connector_status_connected;
|
||||
|
||||
+ /* Assume that the BIOS does not lie through the OpRegion... */
|
||||
+ if (dev_priv->opregion.lid_state)
|
||||
+ return ioread32(dev_priv->opregion.lid_state) & 0x1 ?
|
||||
+ connector_status_connected :
|
||||
+ connector_status_disconnected;
|
||||
+
|
||||
/* ACPI lid methods were generally unreliable in this generation, so
|
||||
* don't even bother.
|
||||
*/
|
||||
diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c
|
||||
index 64fd644..9efccb9 100644
|
||||
--- a/drivers/gpu/drm/i915/intel_opregion.c
|
||||
+++ b/drivers/gpu/drm/i915/intel_opregion.c
|
||||
@@ -489,6 +489,8 @@ int intel_opregion_setup(struct drm_device *dev)
|
||||
opregion->header = base;
|
||||
opregion->vbt = base + OPREGION_VBT_OFFSET;
|
||||
|
||||
+ opregion->lid_state = base + 0x01ac;
|
||||
+
|
||||
mboxes = opregion->header->mboxes;
|
||||
if (mboxes & MBOX_ACPI) {
|
||||
DRM_DEBUG_DRIVER("Public ACPI methods supported\n");
|
||||
--
|
||||
1.7.6.5
|
||||
|
@ -1,35 +0,0 @@
|
||||
From 9e4eb0947431c5a6b55f442aee3eb505e5a334d5 Mon Sep 17 00:00:00 2001
|
||||
From: Jesse Barnes <jbarnes@virtuousgeek.org>
|
||||
Date: Tue, 4 Jan 2011 15:09:29 -0800
|
||||
Subject: [PATCH 2/3] drm/i915: don't enable plane, pipe and PLL prematurely
|
||||
|
||||
On Ironlake+ we need to enable these in a specific order.
|
||||
|
||||
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
|
||||
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
|
||||
---
|
||||
drivers/gpu/drm/i915/intel_display.c | 8 +++++---
|
||||
1 files changed, 5 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
|
||||
index 49fb54f..711beca 100644
|
||||
--- a/drivers/gpu/drm/i915/intel_display.c
|
||||
+++ b/drivers/gpu/drm/i915/intel_display.c
|
||||
@@ -4322,9 +4322,11 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||
pipeconf &= ~PIPECONF_DOUBLE_WIDE;
|
||||
}
|
||||
|
||||
- dspcntr |= DISPLAY_PLANE_ENABLE;
|
||||
- pipeconf |= PIPECONF_ENABLE;
|
||||
- dpll |= DPLL_VCO_ENABLE;
|
||||
+ if (!HAS_PCH_SPLIT(dev)) {
|
||||
+ dspcntr |= DISPLAY_PLANE_ENABLE;
|
||||
+ pipeconf |= PIPECONF_ENABLE;
|
||||
+ dpll |= DPLL_VCO_ENABLE;
|
||||
+ }
|
||||
|
||||
DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
|
||||
drm_mode_debug_printmodeline(mode);
|
||||
--
|
||||
1.7.6.5
|
||||
|
@ -1,429 +0,0 @@
|
||||
From 152d92c3e618d1c17c6a84c66aec00af227c3f0e Mon Sep 17 00:00:00 2001
|
||||
From: Jesse Barnes <jbarnes@virtuousgeek.org>
|
||||
Date: Tue, 4 Jan 2011 15:09:30 -0800
|
||||
Subject: [PATCH 3/3] drm/i915: add pipe/plane enable/disable functions
|
||||
|
||||
Add plane enable/disable functions to prevent duplicated code and allow
|
||||
us to easily check for plane enable/disable requirements (such as pipe
|
||||
enable, plane status, pll status etc).
|
||||
|
||||
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
|
||||
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
|
||||
---
|
||||
drivers/gpu/drm/i915/i915_reg.h | 5 +-
|
||||
drivers/gpu/drm/i915/intel_display.c | 308 +++++++++++++++++++++++-----------
|
||||
2 files changed, 216 insertions(+), 97 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
|
||||
index 12c547a..b0f1290 100644
|
||||
--- a/drivers/gpu/drm/i915/i915_reg.h
|
||||
+++ b/drivers/gpu/drm/i915/i915_reg.h
|
||||
@@ -2537,9 +2537,10 @@
|
||||
#define DISPPLANE_32BPP_30BIT_NO_ALPHA (0xa<<26)
|
||||
#define DISPPLANE_STEREO_ENABLE (1<<25)
|
||||
#define DISPPLANE_STEREO_DISABLE 0
|
||||
-#define DISPPLANE_SEL_PIPE_MASK (1<<24)
|
||||
+#define DISPPLANE_SEL_PIPE_SHIFT 24
|
||||
+#define DISPPLANE_SEL_PIPE_MASK (3<<DISPPLANE_SEL_PIPE_SHIFT)
|
||||
#define DISPPLANE_SEL_PIPE_A 0
|
||||
-#define DISPPLANE_SEL_PIPE_B (1<<24)
|
||||
+#define DISPPLANE_SEL_PIPE_B (1<<DISPPLANE_SEL_PIPE_SHIFT)
|
||||
#define DISPPLANE_SRC_KEY_ENABLE (1<<22)
|
||||
#define DISPPLANE_SRC_KEY_DISABLE 0
|
||||
#define DISPPLANE_LINE_DOUBLE (1<<20)
|
||||
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
|
||||
index 711beca..cef853b 100644
|
||||
--- a/drivers/gpu/drm/i915/intel_display.c
|
||||
+++ b/drivers/gpu/drm/i915/intel_display.c
|
||||
@@ -1058,6 +1058,203 @@ void intel_wait_for_pipe_off(struct drm_device *dev, int pipe)
|
||||
}
|
||||
}
|
||||
|
||||
+static const char *state_string(bool enabled)
|
||||
+{
|
||||
+ return enabled ? "on" : "off";
|
||||
+}
|
||||
+
|
||||
+/* Only for pre-ILK configs */
|
||||
+static void assert_pll(struct drm_i915_private *dev_priv,
|
||||
+ enum pipe pipe, bool state)
|
||||
+{
|
||||
+ int reg;
|
||||
+ u32 val;
|
||||
+ bool cur_state;
|
||||
+
|
||||
+ reg = DPLL(pipe);
|
||||
+ val = I915_READ(reg);
|
||||
+ cur_state = !!(val & DPLL_VCO_ENABLE);
|
||||
+ WARN(cur_state != state,
|
||||
+ "PLL state assertion failure (expected %s, current %s)\n",
|
||||
+ state_string(state), state_string(cur_state));
|
||||
+}
|
||||
+#define assert_pll_enabled(d, p) assert_pll(d, p, true)
|
||||
+#define assert_pll_disabled(d, p) assert_pll(d, p, false)
|
||||
+
|
||||
+static void assert_pipe_enabled(struct drm_i915_private *dev_priv,
|
||||
+ enum pipe pipe)
|
||||
+{
|
||||
+ int reg;
|
||||
+ u32 val;
|
||||
+
|
||||
+ reg = PIPECONF(pipe);
|
||||
+ val = I915_READ(reg);
|
||||
+ WARN(!(val & PIPECONF_ENABLE),
|
||||
+ "pipe %c assertion failure, should be active but is disabled\n",
|
||||
+ pipe ? 'B' : 'A');
|
||||
+}
|
||||
+
|
||||
+static void assert_plane_enabled(struct drm_i915_private *dev_priv,
|
||||
+ enum plane plane)
|
||||
+{
|
||||
+ int reg;
|
||||
+ u32 val;
|
||||
+
|
||||
+ reg = DSPCNTR(plane);
|
||||
+ val = I915_READ(reg);
|
||||
+ WARN(!(val & DISPLAY_PLANE_ENABLE),
|
||||
+ "plane %c assertion failure, should be active but is disabled\n",
|
||||
+ plane ? 'B' : 'A');
|
||||
+}
|
||||
+
|
||||
+static void assert_planes_disabled(struct drm_i915_private *dev_priv,
|
||||
+ enum pipe pipe)
|
||||
+{
|
||||
+ int reg, i;
|
||||
+ u32 val;
|
||||
+ int cur_pipe;
|
||||
+
|
||||
+ /* Need to check both planes against the pipe */
|
||||
+ for (i = 0; i < 2; i++) {
|
||||
+ reg = DSPCNTR(i);
|
||||
+ val = I915_READ(reg);
|
||||
+ cur_pipe = (val & DISPPLANE_SEL_PIPE_MASK) >>
|
||||
+ DISPPLANE_SEL_PIPE_SHIFT;
|
||||
+ WARN((val & DISPLAY_PLANE_ENABLE) && pipe == cur_pipe,
|
||||
+ "plane %d assertion failure, should be off on pipe %c but is still active\n",
|
||||
+ i, pipe ? 'B' : 'A');
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * intel_enable_pipe - enable a pipe, assertiing requirements
|
||||
+ * @dev_priv: i915 private structure
|
||||
+ * @pipe: pipe to enable
|
||||
+ *
|
||||
+ * Enable @pipe, making sure that various hardware specific requirements
|
||||
+ * are met, if applicable, e.g. PLL enabled, LVDS pairs enabled, etc.
|
||||
+ *
|
||||
+ * @pipe should be %PIPE_A or %PIPE_B.
|
||||
+ *
|
||||
+ * Will wait until the pipe is actually running (i.e. first vblank) before
|
||||
+ * returning.
|
||||
+ */
|
||||
+static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
|
||||
+{
|
||||
+ int reg;
|
||||
+ u32 val;
|
||||
+
|
||||
+ /*
|
||||
+ * A pipe without a PLL won't actually be able to drive bits from
|
||||
+ * a plane. On ILK+ the pipe PLLs are integrated, so we don't
|
||||
+ * need the check.
|
||||
+ */
|
||||
+ if (!HAS_PCH_SPLIT(dev_priv->dev))
|
||||
+ assert_pll_enabled(dev_priv, pipe);
|
||||
+
|
||||
+ reg = PIPECONF(pipe);
|
||||
+ val = I915_READ(reg);
|
||||
+ val |= PIPECONF_ENABLE;
|
||||
+ I915_WRITE(reg, val);
|
||||
+ POSTING_READ(reg);
|
||||
+ intel_wait_for_vblank(dev_priv->dev, pipe);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * intel_disable_pipe - disable a pipe, assertiing requirements
|
||||
+ * @dev_priv: i915 private structure
|
||||
+ * @pipe: pipe to disable
|
||||
+ *
|
||||
+ * Disable @pipe, making sure that various hardware specific requirements
|
||||
+ * are met, if applicable, e.g. plane disabled, panel fitter off, etc.
|
||||
+ *
|
||||
+ * @pipe should be %PIPE_A or %PIPE_B.
|
||||
+ *
|
||||
+ * Will wait until the pipe has shut down before returning.
|
||||
+ */
|
||||
+static void intel_disable_pipe(struct drm_i915_private *dev_priv,
|
||||
+ enum pipe pipe)
|
||||
+{
|
||||
+ int reg;
|
||||
+ u32 val;
|
||||
+
|
||||
+ /*
|
||||
+ * Make sure planes won't keep trying to pump pixels to us,
|
||||
+ * or we might hang the display.
|
||||
+ */
|
||||
+ assert_planes_disabled(dev_priv, pipe);
|
||||
+
|
||||
+ /* Don't disable pipe A or pipe A PLLs if needed */
|
||||
+ if (pipe == PIPE_A && (dev_priv->quirks & QUIRK_PIPEA_FORCE))
|
||||
+ return;
|
||||
+
|
||||
+ reg = PIPECONF(pipe);
|
||||
+ val = I915_READ(reg);
|
||||
+ val &= ~PIPECONF_ENABLE;
|
||||
+ I915_WRITE(reg, val);
|
||||
+ POSTING_READ(reg);
|
||||
+ intel_wait_for_pipe_off(dev_priv->dev, pipe);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * intel_enable_plane - enable a display plane on a given pipe
|
||||
+ * @dev_priv: i915 private structure
|
||||
+ * @plane: plane to enable
|
||||
+ * @pipe: pipe being fed
|
||||
+ *
|
||||
+ * Enable @plane on @pipe, making sure that @pipe is running first.
|
||||
+ */
|
||||
+static void intel_enable_plane(struct drm_i915_private *dev_priv,
|
||||
+ enum plane plane, enum pipe pipe)
|
||||
+{
|
||||
+ int reg;
|
||||
+ u32 val;
|
||||
+
|
||||
+ /* If the pipe isn't enabled, we can't pump pixels and may hang */
|
||||
+ assert_pipe_enabled(dev_priv, pipe);
|
||||
+
|
||||
+ reg = DSPCNTR(plane);
|
||||
+ val = I915_READ(reg);
|
||||
+ val |= DISPLAY_PLANE_ENABLE;
|
||||
+ I915_WRITE(reg, val);
|
||||
+ POSTING_READ(reg);
|
||||
+ intel_wait_for_vblank(dev_priv->dev, pipe);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Plane regs are double buffered, going from enabled->disabled needs a
|
||||
+ * trigger in order to latch. The display address reg provides this.
|
||||
+ */
|
||||
+static void intel_flush_display_plane(struct drm_i915_private *dev_priv,
|
||||
+ enum plane plane)
|
||||
+{
|
||||
+ u32 reg = DSPADDR(plane);
|
||||
+ I915_WRITE(reg, I915_READ(reg));
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * intel_disable_plane - disable a display plane
|
||||
+ * @dev_priv: i915 private structure
|
||||
+ * @plane: plane to disable
|
||||
+ * @pipe: pipe consuming the data
|
||||
+ *
|
||||
+ * Disable @plane; should be an independent operation.
|
||||
+ */
|
||||
+static void intel_disable_plane(struct drm_i915_private *dev_priv,
|
||||
+ enum plane plane, enum pipe pipe)
|
||||
+{
|
||||
+ int reg;
|
||||
+ u32 val;
|
||||
+
|
||||
+ reg = DSPCNTR(plane);
|
||||
+ val = I915_READ(reg);
|
||||
+ val &= ~DISPLAY_PLANE_ENABLE;
|
||||
+ I915_WRITE(reg, val);
|
||||
+ POSTING_READ(reg);
|
||||
+ intel_flush_display_plane(dev_priv, plane);
|
||||
+ intel_wait_for_vblank(dev_priv->dev, pipe);
|
||||
+}
|
||||
+
|
||||
static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
@@ -2003,14 +2200,6 @@ static void ironlake_fdi_enable(struct drm_crtc *crtc)
|
||||
}
|
||||
}
|
||||
|
||||
-static void intel_flush_display_plane(struct drm_device *dev,
|
||||
- int plane)
|
||||
-{
|
||||
- struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
- u32 reg = DSPADDR(plane);
|
||||
- I915_WRITE(reg, I915_READ(reg));
|
||||
-}
|
||||
-
|
||||
/*
|
||||
* When we disable a pipe, we need to clear any pending scanline wait events
|
||||
* to avoid hanging the ring, which we assume we are waiting on.
|
||||
@@ -2158,22 +2347,8 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
|
||||
dev_priv->pch_pf_size);
|
||||
}
|
||||
|
||||
- /* Enable CPU pipe */
|
||||
- reg = PIPECONF(pipe);
|
||||
- temp = I915_READ(reg);
|
||||
- if ((temp & PIPECONF_ENABLE) == 0) {
|
||||
- I915_WRITE(reg, temp | PIPECONF_ENABLE);
|
||||
- POSTING_READ(reg);
|
||||
- intel_wait_for_vblank(dev, intel_crtc->pipe);
|
||||
- }
|
||||
-
|
||||
- /* configure and enable CPU plane */
|
||||
- reg = DSPCNTR(plane);
|
||||
- temp = I915_READ(reg);
|
||||
- if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
|
||||
- I915_WRITE(reg, temp | DISPLAY_PLANE_ENABLE);
|
||||
- intel_flush_display_plane(dev, plane);
|
||||
- }
|
||||
+ intel_enable_pipe(dev_priv, pipe);
|
||||
+ intel_enable_plane(dev_priv, plane, pipe);
|
||||
|
||||
/* Skip the PCH stuff if possible */
|
||||
if (!is_pch_port)
|
||||
@@ -2285,27 +2460,13 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
|
||||
drm_vblank_off(dev, pipe);
|
||||
intel_crtc_update_cursor(crtc, false);
|
||||
|
||||
- /* Disable display plane */
|
||||
- reg = DSPCNTR(plane);
|
||||
- temp = I915_READ(reg);
|
||||
- if (temp & DISPLAY_PLANE_ENABLE) {
|
||||
- I915_WRITE(reg, temp & ~DISPLAY_PLANE_ENABLE);
|
||||
- intel_flush_display_plane(dev, plane);
|
||||
- }
|
||||
+ intel_disable_plane(dev_priv, plane, pipe);
|
||||
|
||||
if (dev_priv->cfb_plane == plane &&
|
||||
dev_priv->display.disable_fbc)
|
||||
dev_priv->display.disable_fbc(dev);
|
||||
|
||||
- /* disable cpu pipe, disable after all planes disabled */
|
||||
- reg = PIPECONF(pipe);
|
||||
- temp = I915_READ(reg);
|
||||
- if (temp & PIPECONF_ENABLE) {
|
||||
- I915_WRITE(reg, temp & ~PIPECONF_ENABLE);
|
||||
- POSTING_READ(reg);
|
||||
- /* wait for cpu pipe off, pipe state */
|
||||
- intel_wait_for_pipe_off(dev, intel_crtc->pipe);
|
||||
- }
|
||||
+ intel_disable_pipe(dev_priv, pipe);
|
||||
|
||||
/* Disable PF */
|
||||
I915_WRITE(pipe ? PFB_CTL_1 : PFA_CTL_1, 0);
|
||||
@@ -2500,19 +2661,8 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
|
||||
udelay(150);
|
||||
}
|
||||
|
||||
- /* Enable the pipe */
|
||||
- reg = PIPECONF(pipe);
|
||||
- temp = I915_READ(reg);
|
||||
- if ((temp & PIPECONF_ENABLE) == 0)
|
||||
- I915_WRITE(reg, temp | PIPECONF_ENABLE);
|
||||
-
|
||||
- /* Enable the plane */
|
||||
- reg = DSPCNTR(plane);
|
||||
- temp = I915_READ(reg);
|
||||
- if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
|
||||
- I915_WRITE(reg, temp | DISPLAY_PLANE_ENABLE);
|
||||
- intel_flush_display_plane(dev, plane);
|
||||
- }
|
||||
+ intel_enable_pipe(dev_priv, pipe);
|
||||
+ intel_enable_plane(dev_priv, plane, pipe);
|
||||
|
||||
intel_crtc_load_lut(crtc);
|
||||
intel_update_fbc(dev);
|
||||
@@ -2544,33 +2694,13 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
|
||||
dev_priv->display.disable_fbc)
|
||||
dev_priv->display.disable_fbc(dev);
|
||||
|
||||
- /* Disable display plane */
|
||||
- reg = DSPCNTR(plane);
|
||||
- temp = I915_READ(reg);
|
||||
- if (temp & DISPLAY_PLANE_ENABLE) {
|
||||
- I915_WRITE(reg, temp & ~DISPLAY_PLANE_ENABLE);
|
||||
- /* Flush the plane changes */
|
||||
- intel_flush_display_plane(dev, plane);
|
||||
-
|
||||
- /* Wait for vblank for the disable to take effect */
|
||||
- if (IS_GEN2(dev))
|
||||
- intel_wait_for_vblank(dev, pipe);
|
||||
- }
|
||||
+ intel_disable_plane(dev_priv, plane, pipe);
|
||||
|
||||
/* Don't disable pipe A or pipe A PLLs if needed */
|
||||
if (pipe == 0 && (dev_priv->quirks & QUIRK_PIPEA_FORCE))
|
||||
goto done;
|
||||
|
||||
- /* Next, disable display pipes */
|
||||
- reg = PIPECONF(pipe);
|
||||
- temp = I915_READ(reg);
|
||||
- if (temp & PIPECONF_ENABLE) {
|
||||
- I915_WRITE(reg, temp & ~PIPECONF_ENABLE);
|
||||
-
|
||||
- /* Wait for the pipe to turn off */
|
||||
- POSTING_READ(reg);
|
||||
- intel_wait_for_pipe_off(dev, pipe);
|
||||
- }
|
||||
+ intel_disable_pipe(dev_priv, pipe);
|
||||
|
||||
reg = DPLL(pipe);
|
||||
temp = I915_READ(reg);
|
||||
@@ -4322,11 +4452,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||
pipeconf &= ~PIPECONF_DOUBLE_WIDE;
|
||||
}
|
||||
|
||||
- if (!HAS_PCH_SPLIT(dev)) {
|
||||
- dspcntr |= DISPLAY_PLANE_ENABLE;
|
||||
- pipeconf |= PIPECONF_ENABLE;
|
||||
+ if (!HAS_PCH_SPLIT(dev))
|
||||
dpll |= DPLL_VCO_ENABLE;
|
||||
- }
|
||||
|
||||
DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
|
||||
drm_mode_debug_printmodeline(mode);
|
||||
@@ -4535,6 +4662,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||
|
||||
I915_WRITE(PIPECONF(pipe), pipeconf);
|
||||
POSTING_READ(PIPECONF(pipe));
|
||||
+ if (!HAS_PCH_SPLIT(dev))
|
||||
+ intel_enable_pipe(dev_priv, pipe);
|
||||
|
||||
intel_wait_for_vblank(dev, pipe);
|
||||
|
||||
@@ -4545,6 +4674,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||
}
|
||||
|
||||
I915_WRITE(DSPCNTR(plane), dspcntr);
|
||||
+ POSTING_READ(DSPCNTR(plane));
|
||||
+ if (!HAS_PCH_SPLIT(dev))
|
||||
+ intel_enable_plane(dev_priv, plane, pipe);
|
||||
|
||||
ret = intel_pipe_set_base(crtc, x, y, old_fb);
|
||||
|
||||
@@ -5694,22 +5826,8 @@ static void intel_sanitize_modesetting(struct drm_device *dev,
|
||||
pipe = !pipe;
|
||||
|
||||
/* Disable the plane and wait for it to stop reading from the pipe. */
|
||||
- I915_WRITE(reg, val & ~DISPLAY_PLANE_ENABLE);
|
||||
- intel_flush_display_plane(dev, plane);
|
||||
-
|
||||
- if (IS_GEN2(dev))
|
||||
- intel_wait_for_vblank(dev, pipe);
|
||||
-
|
||||
- if (pipe == 0 && (dev_priv->quirks & QUIRK_PIPEA_FORCE))
|
||||
- return;
|
||||
-
|
||||
- /* Switch off the pipe. */
|
||||
- reg = PIPECONF(pipe);
|
||||
- val = I915_READ(reg);
|
||||
- if (val & PIPECONF_ENABLE) {
|
||||
- I915_WRITE(reg, val & ~PIPECONF_ENABLE);
|
||||
- intel_wait_for_pipe_off(dev, pipe);
|
||||
- }
|
||||
+ intel_disable_plane(dev_priv, plane, pipe);
|
||||
+ intel_disable_pipe(dev_priv, pipe);
|
||||
}
|
||||
|
||||
static void intel_crtc_init(struct drm_device *dev, int pipe)
|
||||
--
|
||||
1.7.6.5
|
||||
|
@ -1,35 +0,0 @@
|
||||
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) {
|
@ -1,96 +0,0 @@
|
||||
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),
|
@ -1,22 +0,0 @@
|
||||
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,40 +0,0 @@
|
||||
From: Brandon Philips <bphilips@suse.de>
|
||||
Subject: [PATCH] bnx2: entropy source
|
||||
Patch-mainline: never
|
||||
References: FATE#307517
|
||||
|
||||
Current disk-less systems have no entropy source whatsoever. Therefore, the
|
||||
network drivers tg3, bnx2, e1000, e1000e, igb and ixgbe should be enabled to
|
||||
feed entropy to the kernel via the IRQF_SAMPLE_RANDOM flag when loaded. This
|
||||
option shall not be enabled by default but implemented via a module option to
|
||||
be activated by the administrator.
|
||||
|
||||
Signed-off-by: Brandon Philips <bphilips@suse.de>
|
||||
|
||||
---
|
||||
drivers/net/bnx2.c | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
--- a/drivers/net/bnx2.c
|
||||
+++ b/drivers/net/bnx2.c
|
||||
@@ -84,6 +84,10 @@ MODULE_FIRMWARE(FW_MIPS_FILE_09);
|
||||
MODULE_FIRMWARE(FW_RV2P_FILE_09);
|
||||
MODULE_FIRMWARE(FW_RV2P_FILE_09_Ax);
|
||||
|
||||
+static int entropy = 0;
|
||||
+module_param(entropy, int, 0);
|
||||
+MODULE_PARM_DESC(entropy, "Allow bnx2 to populate the /dev/random entropy pool");
|
||||
+
|
||||
static int disable_msi = 0;
|
||||
|
||||
module_param(disable_msi, int, 0);
|
||||
@@ -6116,6 +6120,9 @@ bnx2_request_irq(struct bnx2 *bp)
|
||||
else
|
||||
flags = IRQF_SHARED;
|
||||
|
||||
+ if (entropy)
|
||||
+ flags |= IRQF_SAMPLE_RANDOM;
|
||||
+
|
||||
for (i = 0; i < bp->irq_nvecs; i++) {
|
||||
irq = &bp->irq_tbl[i];
|
||||
rc = request_irq(irq->vector, irq->handler, flags, irq->name,
|
@ -1,45 +0,0 @@
|
||||
From: Xiuling Ma <xma@us.ibm.com>
|
||||
Subject: [PATCH] disable catas_reset by default to avoid problems with EEH
|
||||
References: bnc#456389
|
||||
Patch-mainline: not yet
|
||||
|
||||
PPC machines with EEH and Mellanox ib/net cards with catastrophic error
|
||||
recovery that encounter a PCI bus error can crash and become
|
||||
unresponsive.
|
||||
|
||||
Disable the card reset to avoid this.
|
||||
|
||||
NOTE: an upstream fix will come later once IBM can review a couple of
|
||||
approaches I suggested since this fix is brute force. This driver didn't have
|
||||
this reset on error feature in SLES10 so it isn't a feature removal.
|
||||
|
||||
Signed-off-by: Xiuling Ma <xma@us.ibm.com>
|
||||
Acked-by: Brandon Philips <bphilips@suse.de>
|
||||
|
||||
---
|
||||
drivers/infiniband/hw/mthca/mthca_catas.c | 2 +-
|
||||
drivers/net/mlx4/catas.c | 2 +-
|
||||
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/infiniband/hw/mthca/mthca_catas.c
|
||||
+++ b/drivers/infiniband/hw/mthca/mthca_catas.c
|
||||
@@ -51,7 +51,7 @@ static LIST_HEAD(catas_list);
|
||||
static struct workqueue_struct *catas_wq;
|
||||
static struct work_struct catas_work;
|
||||
|
||||
-static int catas_reset_disable;
|
||||
+static int catas_reset_disable = 1;
|
||||
module_param_named(catas_reset_disable, catas_reset_disable, int, 0644);
|
||||
MODULE_PARM_DESC(catas_reset_disable, "disable reset on catastrophic event if nonzero");
|
||||
|
||||
--- a/drivers/net/mlx4/catas.c
|
||||
+++ b/drivers/net/mlx4/catas.c
|
||||
@@ -44,7 +44,7 @@ static DEFINE_SPINLOCK(catas_lock);
|
||||
static LIST_HEAD(catas_list);
|
||||
static struct work_struct catas_work;
|
||||
|
||||
-static int internal_err_reset = 1;
|
||||
+static int internal_err_reset = 0;
|
||||
module_param(internal_err_reset, int, 0644);
|
||||
MODULE_PARM_DESC(internal_err_reset,
|
||||
"Reset device on internal errors if non-zero (default 1)");
|
@ -1,47 +0,0 @@
|
||||
From: Jiri Benc <jbenc@suse.cz>
|
||||
Subject: Enable e1000 as entropy source (disabled by default)
|
||||
References: FATE#307517
|
||||
Patch-mainline: never
|
||||
|
||||
Based on the patch by Oracle:
|
||||
|
||||
> e1000: Add IRQF_SAMPLE_RANDOM flag to e1000 as a module option
|
||||
>
|
||||
> This patch allows for the bnx2 to add to the /dev/random entropy pool
|
||||
> via a module parameter, entropy.
|
||||
>
|
||||
> 0 - default for EL5 - do not populate the entropy pool
|
||||
> 1 - optional - Uses IRQF_SAMPLE_RANDOM flag on request_irq calls to populate
|
||||
> the /dev/random pool
|
||||
>
|
||||
> Signed-off-by: John Sobecki <john.sobecki@oracle.com>
|
||||
|
||||
Signed-off-by: Brandon Philips <bphilips@suse.de>
|
||||
|
||||
---
|
||||
drivers/net/e1000/e1000_main.c | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
--- a/drivers/net/e1000/e1000_main.c
|
||||
+++ b/drivers/net/e1000/e1000_main.c
|
||||
@@ -213,6 +213,10 @@ static int debug = NETIF_MSG_DRV | NETIF
|
||||
module_param(debug, int, 0);
|
||||
MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
|
||||
|
||||
+static int entropy = 0;
|
||||
+module_param(entropy, int, 0);
|
||||
+MODULE_PARM_DESC(entropy, "Allow e1000 to populate the /dev/random entropy pool");
|
||||
+
|
||||
/**
|
||||
* e1000_get_hw_dev - return device
|
||||
* used by hardware layer to print debugging information
|
||||
@@ -272,6 +276,9 @@ static int e1000_request_irq(struct e100
|
||||
int irq_flags = IRQF_SHARED;
|
||||
int err;
|
||||
|
||||
+ if (entropy)
|
||||
+ irq_flags |= IRQF_SAMPLE_RANDOM;
|
||||
+
|
||||
err = request_irq(adapter->pdev->irq, handler, irq_flags, netdev->name,
|
||||
netdev);
|
||||
if (err) {
|
@ -1,86 +0,0 @@
|
||||
From: Jiri Benc <jbenc@suse.cz>
|
||||
Subject: Enable e1000e as entropy source (disabled by default)
|
||||
References: FATE#307517
|
||||
Patch-mainline: never
|
||||
|
||||
Current disk-less systems have no entropy source whatsoever. Therefore, the
|
||||
network drivers tg3, bnx2, e1000, e1000e, igb and ixgbe should be enabled to
|
||||
feed entropy to the kernel via the IRQF_SAMPLE_RANDOM flag when loaded. This
|
||||
option shall not be enabled by default but implemented via a module option to
|
||||
be activated by the administrator.
|
||||
|
||||
Signed-off-by: Brandon Philips <bphilips@suse.de>
|
||||
|
||||
---
|
||||
drivers/net/e1000e/e1000.h | 1 +
|
||||
drivers/net/e1000e/netdev.c | 14 +++++++++-----
|
||||
drivers/net/e1000e/param.c | 4 ++++
|
||||
3 files changed, 14 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/net/e1000e/e1000.h
|
||||
+++ b/drivers/net/e1000e/e1000.h
|
||||
@@ -467,6 +467,7 @@ extern void e1000e_reset_interrupt_capab
|
||||
extern void e1000e_disable_aspm(struct pci_dev *pdev, u16 state);
|
||||
|
||||
extern unsigned int copybreak;
|
||||
+extern int entropy;
|
||||
|
||||
extern char *e1000e_get_hw_dev_name(struct e1000_hw *hw);
|
||||
|
||||
--- a/drivers/net/e1000e/netdev.c
|
||||
+++ b/drivers/net/e1000e/netdev.c
|
||||
@@ -1847,8 +1847,8 @@ static int e1000_request_msix(struct e10
|
||||
else
|
||||
memcpy(adapter->rx_ring->name, netdev->name, IFNAMSIZ);
|
||||
err = request_irq(adapter->msix_entries[vector].vector,
|
||||
- e1000_intr_msix_rx, 0, adapter->rx_ring->name,
|
||||
- netdev);
|
||||
+ e1000_intr_msix_rx, entropy ? IRQF_SAMPLE_RANDOM : 0,
|
||||
+ adapter->rx_ring->name, netdev);
|
||||
if (err)
|
||||
goto out;
|
||||
adapter->rx_ring->itr_register = E1000_EITR_82574(vector);
|
||||
@@ -1889,6 +1889,7 @@ static int e1000_request_irq(struct e100
|
||||
{
|
||||
struct net_device *netdev = adapter->netdev;
|
||||
int err;
|
||||
+ int irq_flags = 0;
|
||||
|
||||
if (adapter->msix_entries) {
|
||||
err = e1000_request_msix(adapter);
|
||||
@@ -1900,7 +1901,8 @@ static int e1000_request_irq(struct e100
|
||||
e1000e_set_interrupt_capability(adapter);
|
||||
}
|
||||
if (adapter->flags & FLAG_MSI_ENABLED) {
|
||||
- err = request_irq(adapter->pdev->irq, e1000_intr_msi, 0,
|
||||
+ err = request_irq(adapter->pdev->irq, e1000_intr_msi,
|
||||
+ entropy ? IRQF_SAMPLE_RANDOM : 0,
|
||||
netdev->name, netdev);
|
||||
if (!err)
|
||||
return err;
|
||||
@@ -1910,8 +1912,10 @@ static int e1000_request_irq(struct e100
|
||||
adapter->int_mode = E1000E_INT_MODE_LEGACY;
|
||||
}
|
||||
|
||||
- err = request_irq(adapter->pdev->irq, e1000_intr, IRQF_SHARED,
|
||||
- netdev->name, netdev);
|
||||
+ if (entropy)
|
||||
+ irq_flags |= IRQF_SAMPLE_RANDOM;
|
||||
+ err = request_irq(adapter->pdev->irq, e1000_intr,
|
||||
+ irq_flags | IRQF_SHARED, netdev->name, netdev);
|
||||
if (err)
|
||||
e_err("Unable to allocate interrupt, Error: %d\n", err);
|
||||
|
||||
--- a/drivers/net/e1000e/param.c
|
||||
+++ b/drivers/net/e1000e/param.c
|
||||
@@ -31,6 +31,10 @@
|
||||
|
||||
#include "e1000.h"
|
||||
|
||||
+int entropy = 0;
|
||||
+module_param(entropy, int, 0);
|
||||
+MODULE_PARM_DESC(entropy, "Allow e1000e to populate the /dev/random entropy pool");
|
||||
+
|
||||
/*
|
||||
* This is the only thing that needs to be changed to adjust the
|
||||
* maximum number of ports that the driver can manage.
|
@ -1,43 +0,0 @@
|
||||
Subject: add alias entry for portN properties
|
||||
From: olh@suse.de
|
||||
References: 435215 - LTC48564
|
||||
Patch-mainline: not yet
|
||||
|
||||
Use separate table for alias entries in the ehea module,
|
||||
otherwise the probe() function will operate on the separate ports
|
||||
instead of the lhea-"root" entry of the device-tree
|
||||
|
||||
---
|
||||
drivers/net/ehea/ehea_main.c | 14 +++++++++++++-
|
||||
1 file changed, 13 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/ehea/ehea_main.c
|
||||
+++ b/drivers/net/ehea/ehea_main.c
|
||||
@@ -112,6 +112,19 @@ static int __devinit ehea_probe_adapter(
|
||||
|
||||
static int __devexit ehea_remove(struct platform_device *dev);
|
||||
|
||||
+static struct of_device_id ehea_module_device_table[] = {
|
||||
+ {
|
||||
+ .name = "lhea",
|
||||
+ .compatible = "IBM,lhea",
|
||||
+ },
|
||||
+ {
|
||||
+ .type = "network",
|
||||
+ .compatible = "IBM,lhea-ethernet",
|
||||
+ },
|
||||
+ {},
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, ehea_module_device_table);
|
||||
+
|
||||
static struct of_device_id ehea_device_table[] = {
|
||||
{
|
||||
.name = "lhea",
|
||||
@@ -119,7 +132,6 @@ static struct of_device_id ehea_device_t
|
||||
},
|
||||
{},
|
||||
};
|
||||
-MODULE_DEVICE_TABLE(of, ehea_device_table);
|
||||
|
||||
static struct of_platform_driver ehea_driver = {
|
||||
.driver = {
|
@ -1,380 +0,0 @@
|
||||
From: Jiri Kosina <jkosina@suse.cz>
|
||||
Subject: Elo USB touchscreen driver
|
||||
Patch-mainline: will be submitted for 2.6.28
|
||||
References: FATE#304972
|
||||
|
||||
This is a driver for Elo USB touchscreen devices.
|
||||
|
||||
Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
|
||||
Acked-by: Jiri Kosina <jkosina@suse.cz>
|
||||
|
||||
---
|
||||
drivers/hid/hid-core.c | 2
|
||||
drivers/hid/hid-ids.h | 2
|
||||
drivers/input/touchscreen/Kconfig | 12 +
|
||||
drivers/input/touchscreen/Makefile | 1
|
||||
drivers/input/touchscreen/elousb.c | 305 +++++++++++++++++++++++++++++++++++++
|
||||
5 files changed, 322 insertions(+)
|
||||
|
||||
--- a/drivers/hid/hid-core.c
|
||||
+++ b/drivers/hid/hid-core.c
|
||||
@@ -1643,6 +1643,8 @@ static const struct hid_device_id hid_ig
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, 0x0004) },
|
||||
+ { HID_USB_DEVICE(USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_4000U) },
|
||||
+ { HID_USB_DEVICE(USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_4500U) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC5UH) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC4UM) },
|
||||
--- a/drivers/hid/hid-ids.h
|
||||
+++ b/drivers/hid/hid-ids.h
|
||||
@@ -216,7 +216,9 @@
|
||||
#define USB_VENDOR_ID_DREAM_CHEEKY 0x1d34
|
||||
|
||||
#define USB_VENDOR_ID_ELO 0x04E7
|
||||
+#define USB_DEVICE_ID_ELO_4000U 0x0009
|
||||
#define USB_DEVICE_ID_ELO_TS2700 0x0020
|
||||
+#define USB_DEVICE_ID_ELO_4500U 0x0030
|
||||
|
||||
#define USB_VENDOR_ID_EMS 0x2006
|
||||
#define USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II 0x0118
|
||||
--- a/drivers/input/touchscreen/Kconfig
|
||||
+++ b/drivers/input/touchscreen/Kconfig
|
||||
@@ -214,6 +214,18 @@ config TOUCHSCREEN_ELO
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called elo.
|
||||
|
||||
+config TOUCHSCREEN_ELOUSB
|
||||
+ tristate "Elo USB touchscreens"
|
||||
+ select USB
|
||||
+ help
|
||||
+ Say Y here if you have an Elo USB touchscreen connected to
|
||||
+ your system.
|
||||
+
|
||||
+ If unsure, say N.
|
||||
+
|
||||
+ To compile this driver as a module, choose M here: the
|
||||
+ module will be called elousb.
|
||||
+
|
||||
config TOUCHSCREEN_WACOM_W8001
|
||||
tristate "Wacom W8001 penabled serial touchscreen"
|
||||
select SERIO
|
||||
--- a/drivers/input/touchscreen/Makefile
|
||||
+++ b/drivers/input/touchscreen/Makefile
|
||||
@@ -22,6 +22,7 @@ obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += h
|
||||
obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o
|
||||
+obj-$(CONFIG_TOUCHSCREEN_ELOUSB) += elousb.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/input/touchscreen/elousb.c
|
||||
@@ -0,0 +1,305 @@
|
||||
+/*
|
||||
+ * Copyright (c) 1999-2001 Vojtech Pavlik
|
||||
+ *
|
||||
+ * Elo USB touchscreen support
|
||||
+ */
|
||||
+
|
||||
+/*
|
||||
+ * 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; either version 2 of the License.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License
|
||||
+ * along with this program; if not, write to the Free Software
|
||||
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
+ *
|
||||
+ * Should you need to contact me, the author, you can do so either by
|
||||
+ * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
|
||||
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
+ */
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/usb.h>
|
||||
+#include <linux/usb/input.h>
|
||||
+#include <linux/hid.h>
|
||||
+#include <linux/input.h>
|
||||
+
|
||||
+/*
|
||||
+ * Version Information
|
||||
+ */
|
||||
+#define DRIVER_VERSION "v1.1"
|
||||
+#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@suse.cz>"
|
||||
+#define DRIVER_DESC "Elo USB touchscreen driver"
|
||||
+#define DRIVER_LICENSE "GPL"
|
||||
+
|
||||
+MODULE_AUTHOR(DRIVER_AUTHOR);
|
||||
+MODULE_DESCRIPTION(DRIVER_DESC);
|
||||
+MODULE_LICENSE(DRIVER_LICENSE);
|
||||
+
|
||||
+struct elousb {
|
||||
+ char name[128];
|
||||
+ char phys[64];
|
||||
+ struct usb_device *usbdev;
|
||||
+ struct input_dev *dev;
|
||||
+ struct urb *irq;
|
||||
+
|
||||
+ unsigned char *data;
|
||||
+ dma_addr_t data_dma;
|
||||
+};
|
||||
+
|
||||
+static void elousb_irq(struct urb *urb)
|
||||
+{
|
||||
+ struct elousb *elo = urb->context;
|
||||
+ unsigned char *data = elo->data;
|
||||
+ struct input_dev *dev = elo->dev;
|
||||
+ int status;
|
||||
+
|
||||
+ switch (urb->status) {
|
||||
+ case 0: /* success */
|
||||
+ break;
|
||||
+ case -ECONNRESET: /* unlink */
|
||||
+ case -ENOENT:
|
||||
+ case -ESHUTDOWN:
|
||||
+ return;
|
||||
+ /* -EPIPE: should clear the halt */
|
||||
+ default: /* error */
|
||||
+ goto resubmit;
|
||||
+ }
|
||||
+
|
||||
+ if (data[0] != 'T') /* Mandatory ELO packet marker */
|
||||
+ return;
|
||||
+
|
||||
+
|
||||
+ input_report_abs(dev, ABS_X, ((u32)data[3] << 8) | data[2]);
|
||||
+ input_report_abs(dev, ABS_Y, ((u32)data[5] << 8) | data[4]);
|
||||
+
|
||||
+ input_report_abs(dev, ABS_PRESSURE,
|
||||
+ (data[1] & 0x80) ? (((u32)data[7] << 8) | data[6]): 0);
|
||||
+
|
||||
+ if (data[1] & 0x03) {
|
||||
+ input_report_key(dev, BTN_TOUCH, 1);
|
||||
+ input_sync(dev);
|
||||
+ }
|
||||
+
|
||||
+ if (data[1] & 0x04)
|
||||
+ input_report_key(dev, BTN_TOUCH, 0);
|
||||
+
|
||||
+ input_sync(dev);
|
||||
+
|
||||
+resubmit:
|
||||
+ status = usb_submit_urb (urb, GFP_ATOMIC);
|
||||
+ if (status)
|
||||
+ err ("can't resubmit intr, %s-%s/input0, status %d",
|
||||
+ elo->usbdev->bus->bus_name,
|
||||
+ elo->usbdev->devpath, status);
|
||||
+}
|
||||
+
|
||||
+static int elousb_open(struct input_dev *dev)
|
||||
+{
|
||||
+ struct elousb *elo = input_get_drvdata(dev);
|
||||
+
|
||||
+ elo->irq->dev = elo->usbdev;
|
||||
+ if (usb_submit_urb(elo->irq, GFP_KERNEL))
|
||||
+ return -EIO;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void elousb_close(struct input_dev *dev)
|
||||
+{
|
||||
+ struct elousb *elo = input_get_drvdata(dev);
|
||||
+
|
||||
+ usb_kill_urb(elo->irq);
|
||||
+}
|
||||
+
|
||||
+static int elousb_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
||||
+{
|
||||
+ struct usb_device *dev = interface_to_usbdev(intf);
|
||||
+ struct usb_host_interface *interface;
|
||||
+ struct usb_endpoint_descriptor *endpoint;
|
||||
+ struct hid_descriptor *hdesc;
|
||||
+ struct elousb *elo;
|
||||
+ struct input_dev *input_dev;
|
||||
+ int pipe, i;
|
||||
+ unsigned int rsize = 0;
|
||||
+ int error = -ENOMEM;
|
||||
+ char *rdesc;
|
||||
+
|
||||
+ interface = intf->cur_altsetting;
|
||||
+
|
||||
+ if (interface->desc.bNumEndpoints != 1)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ endpoint = &interface->endpoint[0].desc;
|
||||
+ if (!(endpoint->bEndpointAddress & USB_DIR_IN))
|
||||
+ return -ENODEV;
|
||||
+ if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) &&
|
||||
+ (!interface->desc.bNumEndpoints ||
|
||||
+ usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) {
|
||||
+ err("HID class descriptor not present");
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < hdesc->bNumDescriptors; i++)
|
||||
+ if (hdesc->desc[i].bDescriptorType == HID_DT_REPORT)
|
||||
+ rsize = le16_to_cpu(hdesc->desc[i].wDescriptorLength);
|
||||
+
|
||||
+ if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) {
|
||||
+ err("weird size of report descriptor (%u)", rsize);
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
|
||||
+
|
||||
+ elo = kzalloc(sizeof(struct elousb), GFP_KERNEL);
|
||||
+ input_dev = input_allocate_device();
|
||||
+ if (!elo || !input_dev)
|
||||
+ goto fail1;
|
||||
+
|
||||
+ elo->data = usb_buffer_alloc(dev, 8, GFP_ATOMIC, &elo->data_dma);
|
||||
+ if (!elo->data)
|
||||
+ goto fail1;
|
||||
+
|
||||
+ elo->irq = usb_alloc_urb(0, GFP_KERNEL);
|
||||
+ if (!elo->irq)
|
||||
+ goto fail2;
|
||||
+
|
||||
+ if (!(rdesc = kmalloc(rsize, GFP_KERNEL)))
|
||||
+ goto fail3;
|
||||
+
|
||||
+ elo->usbdev = dev;
|
||||
+ elo->dev = input_dev;
|
||||
+
|
||||
+ if ((error = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
|
||||
+ HID_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0,
|
||||
+ interface->desc.bInterfaceNumber,
|
||||
+ NULL, 0, USB_CTRL_SET_TIMEOUT)) < 0) {
|
||||
+ err("setting HID idle timeout failed, error %d", error);
|
||||
+ error = -ENODEV;
|
||||
+ goto fail4;
|
||||
+ }
|
||||
+
|
||||
+ if ((error = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
|
||||
+ USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN,
|
||||
+ HID_DT_REPORT << 8, interface->desc.bInterfaceNumber,
|
||||
+ rdesc, rsize, USB_CTRL_GET_TIMEOUT)) < rsize) {
|
||||
+ err("reading HID report descriptor failed, error %d", error);
|
||||
+ error = -ENODEV;
|
||||
+ goto fail4;
|
||||
+ }
|
||||
+
|
||||
+ if (dev->manufacturer)
|
||||
+ strlcpy(elo->name, dev->manufacturer, sizeof(elo->name));
|
||||
+
|
||||
+ if (dev->product) {
|
||||
+ if (dev->manufacturer)
|
||||
+ strlcat(elo->name, " ", sizeof(elo->name));
|
||||
+ strlcat(elo->name, dev->product, sizeof(elo->name));
|
||||
+ }
|
||||
+
|
||||
+ if (!strlen(elo->name))
|
||||
+ snprintf(elo->name, sizeof(elo->name),
|
||||
+ "Elo touchscreen %04x:%04x",
|
||||
+ le16_to_cpu(dev->descriptor.idVendor),
|
||||
+ le16_to_cpu(dev->descriptor.idProduct));
|
||||
+
|
||||
+ usb_make_path(dev, elo->phys, sizeof(elo->phys));
|
||||
+ strlcat(elo->phys, "/input0", sizeof(elo->phys));
|
||||
+
|
||||
+ input_dev->name = elo->name;
|
||||
+ input_dev->phys = elo->phys;
|
||||
+ usb_to_input_id(dev, &input_dev->id);
|
||||
+ input_dev->dev.parent = &intf->dev;
|
||||
+
|
||||
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
|
||||
+ set_bit(BTN_TOUCH, input_dev->keybit);
|
||||
+ input_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
|
||||
+ set_bit(ABS_PRESSURE, input_dev->absbit);
|
||||
+
|
||||
+ input_set_abs_params(input_dev, ABS_X, 0, 4000, 0, 0);
|
||||
+ input_set_abs_params(input_dev, ABS_Y, 0, 3840, 0, 0);
|
||||
+ input_set_abs_params(input_dev, ABS_PRESSURE, 0, 256, 0, 0);
|
||||
+
|
||||
+ input_set_drvdata(input_dev, elo);
|
||||
+
|
||||
+ input_dev->open = elousb_open;
|
||||
+ input_dev->close = elousb_close;
|
||||
+
|
||||
+ usb_fill_int_urb(elo->irq, dev, pipe, elo->data, 8,
|
||||
+ elousb_irq, elo, endpoint->bInterval);
|
||||
+ elo->irq->transfer_dma = elo->data_dma;
|
||||
+ elo->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
|
||||
+
|
||||
+ input_register_device(elo->dev);
|
||||
+
|
||||
+ usb_set_intfdata(intf, elo);
|
||||
+ return 0;
|
||||
+
|
||||
+fail4:
|
||||
+ kfree(rdesc);
|
||||
+fail3:
|
||||
+ usb_free_urb(elo->irq);
|
||||
+fail2:
|
||||
+ usb_buffer_free(dev, 8, elo->data, elo->data_dma);
|
||||
+fail1:
|
||||
+ input_free_device(input_dev);
|
||||
+ kfree(elo);
|
||||
+ return -ENOMEM;
|
||||
+}
|
||||
+
|
||||
+static void elousb_disconnect(struct usb_interface *intf)
|
||||
+{
|
||||
+ struct elousb *elo = usb_get_intfdata (intf);
|
||||
+
|
||||
+ usb_set_intfdata(intf, NULL);
|
||||
+ if (elo) {
|
||||
+ usb_kill_urb(elo->irq);
|
||||
+ input_unregister_device(elo->dev);
|
||||
+ usb_free_urb(elo->irq);
|
||||
+ usb_buffer_free(interface_to_usbdev(intf), 8, elo->data, elo->data_dma);
|
||||
+ kfree(elo);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static struct usb_device_id elousb_id_table [] = {
|
||||
+ { USB_DEVICE(0x04e7, 0x0009) }, /* CarrolTouch 4000U */
|
||||
+ { USB_DEVICE(0x04e7, 0x0030) }, /* CarrolTouch 4500U */
|
||||
+ { } /* Terminating entry */
|
||||
+};
|
||||
+
|
||||
+MODULE_DEVICE_TABLE (usb, elousb_id_table);
|
||||
+
|
||||
+static struct usb_driver elousb_driver = {
|
||||
+ .name = "elousb",
|
||||
+ .probe = elousb_probe,
|
||||
+ .disconnect = elousb_disconnect,
|
||||
+ .id_table = elousb_id_table,
|
||||
+};
|
||||
+
|
||||
+static int __init elousb_init(void)
|
||||
+{
|
||||
+ int retval = usb_register(&elousb_driver);
|
||||
+ if (retval == 0)
|
||||
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" DRIVER_DESC);
|
||||
+ return retval;
|
||||
+}
|
||||
+
|
||||
+static void __exit elousb_exit(void)
|
||||
+{
|
||||
+ usb_deregister(&elousb_driver);
|
||||
+}
|
||||
+
|
||||
+module_init(elousb_init);
|
||||
+module_exit(elousb_exit);
|
@ -1,70 +0,0 @@
|
||||
From: Jiri Benc <jbenc@suse.cz>
|
||||
Subject: Enable igb as entropy source (disabled by default)
|
||||
References: FATE#307517
|
||||
Patch-mainline: never
|
||||
|
||||
Current disk-less systems have no entropy source whatsoever. Therefore, the
|
||||
network drivers tg3, bnx2, e1000, e1000e, igb and ixgbe should be enabled to
|
||||
feed entropy to the kernel via the IRQF_SAMPLE_RANDOM flag when loaded. This
|
||||
option shall not be enabled by default but implemented via a module option to
|
||||
be activated by the administrator.
|
||||
|
||||
Signed-off-by: Brandon Philips <bphilips@suse.de>
|
||||
|
||||
---
|
||||
drivers/net/igb/igb_main.c | 16 +++++++++++++---
|
||||
1 file changed, 13 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/net/igb/igb_main.c
|
||||
+++ b/drivers/net/igb/igb_main.c
|
||||
@@ -61,6 +61,10 @@ static const struct e1000_info *igb_info
|
||||
[board_82575] = &e1000_82575_info,
|
||||
};
|
||||
|
||||
+static int entropy = 0;
|
||||
+module_param(entropy, int, 0);
|
||||
+MODULE_PARM_DESC(entropy, "Allow igb to populate the /dev/random entropy pool");
|
||||
+
|
||||
static DEFINE_PCI_DEVICE_TABLE(igb_pci_tbl) = {
|
||||
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_COPPER), board_82575 },
|
||||
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_FIBER), board_82575 },
|
||||
@@ -897,7 +901,8 @@ static int igb_request_msix(struct igb_a
|
||||
int i, err = 0, vector = 0;
|
||||
|
||||
err = request_irq(adapter->msix_entries[vector].vector,
|
||||
- igb_msix_other, 0, netdev->name, adapter);
|
||||
+ igb_msix_other, entropy ? IRQF_SAMPLE_RANDOM : 0,
|
||||
+ netdev->name, adapter);
|
||||
if (err)
|
||||
goto out;
|
||||
vector++;
|
||||
@@ -1194,6 +1199,10 @@ static int igb_request_irq(struct igb_ad
|
||||
struct net_device *netdev = adapter->netdev;
|
||||
struct pci_dev *pdev = adapter->pdev;
|
||||
int err = 0;
|
||||
+ int irq_flags = 0;
|
||||
+
|
||||
+ if (entropy)
|
||||
+ irq_flags = IRQF_SAMPLE_RANDOM;
|
||||
|
||||
if (adapter->msix_entries) {
|
||||
err = igb_request_msix(adapter);
|
||||
@@ -1228,7 +1237,7 @@ static int igb_request_irq(struct igb_ad
|
||||
}
|
||||
|
||||
if (adapter->flags & IGB_FLAG_HAS_MSI) {
|
||||
- err = request_irq(adapter->pdev->irq, igb_intr_msi, 0,
|
||||
+ err = request_irq(adapter->pdev->irq, igb_intr_msi, irq_flags,
|
||||
netdev->name, adapter);
|
||||
if (!err)
|
||||
goto request_done;
|
||||
@@ -1238,7 +1247,8 @@ static int igb_request_irq(struct igb_ad
|
||||
adapter->flags &= ~IGB_FLAG_HAS_MSI;
|
||||
}
|
||||
|
||||
- err = request_irq(adapter->pdev->irq, igb_intr, IRQF_SHARED,
|
||||
+ irq_flags |= IRQF_SHARED;
|
||||
+ err = request_irq(adapter->pdev->irq, igb_intr, irq_flags,
|
||||
netdev->name, adapter);
|
||||
|
||||
if (err)
|
@ -1,218 +0,0 @@
|
||||
From: Takashi Iwai <tiwai@suse.de>
|
||||
Subject: [PATCH 2/2] input: Add LED support to Synaptics device
|
||||
Patch-mainline: Submitted
|
||||
References: bnc#547370,bnc#582529,bnc#589014
|
||||
|
||||
The new Synaptics devices have an LED on the top-left corner.
|
||||
This patch adds a new LED class device to control it. It's created
|
||||
dynamically upon synaptics device probing.
|
||||
|
||||
The LED is controlled via the command 0x0a with parameters 0x88 or 0x10.
|
||||
This seems only on/off control although other value might be accepted.
|
||||
|
||||
The detection of the LED isn't clear yet. It should have been the new
|
||||
capability bits that indicate the presence, but on real machines, it
|
||||
doesn't fit. So, for the time being, the driver checks the product id
|
||||
in the ext capability bits and assumes that LED exists on the known
|
||||
devices.
|
||||
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
|
||||
---
|
||||
drivers/input/mouse/Kconfig | 9 +++
|
||||
drivers/input/mouse/synaptics.c | 111 ++++++++++++++++++++++++++++++++++++++++
|
||||
drivers/input/mouse/synaptics.h | 3 +
|
||||
3 files changed, 123 insertions(+)
|
||||
|
||||
--- a/drivers/input/mouse/Kconfig
|
||||
+++ b/drivers/input/mouse/Kconfig
|
||||
@@ -19,6 +19,7 @@ config MOUSE_PS2
|
||||
select SERIO_LIBPS2
|
||||
select SERIO_I8042 if X86
|
||||
select SERIO_GSCPS2 if GSC
|
||||
+ select LEDS_CLASS if MOUSE_PS2_SYNAPICS_LED
|
||||
help
|
||||
Say Y here if you have a PS/2 mouse connected to your system. This
|
||||
includes the standard 2 or 3-button PS/2 mouse, as well as PS/2
|
||||
@@ -67,6 +68,14 @@ config MOUSE_PS2_SYNAPTICS
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
+config MOUSE_PS2_SYNAPTICS_LED
|
||||
+ bool "Support embedded LED on Synaptics devices"
|
||||
+ depends on MOUSE_PS2_SYNAPTICS
|
||||
+ select NEW_LEDS
|
||||
+ help
|
||||
+ Say Y here if you have a Synaptics device with an embedded LED.
|
||||
+ This will enable LED class driver to control the LED device.
|
||||
+
|
||||
config MOUSE_PS2_LIFEBOOK
|
||||
bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EXPERT
|
||||
default y
|
||||
--- a/drivers/input/mouse/synaptics.c
|
||||
+++ b/drivers/input/mouse/synaptics.c
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <linux/input/mt.h>
|
||||
#include <linux/serio.h>
|
||||
#include <linux/libps2.h>
|
||||
+#include <linux/leds.h>
|
||||
#include <linux/slab.h>
|
||||
#include "psmouse.h"
|
||||
#include "synaptics.h"
|
||||
@@ -353,6 +354,110 @@ static void synaptics_pt_create(struct p
|
||||
serio_register_port(serio);
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_MOUSE_PS2_SYNAPTICS_LED
|
||||
+/*
|
||||
+ * LED handling:
|
||||
+ * Some Synaptics devices have an embeded LED at the top-left corner.
|
||||
+ */
|
||||
+
|
||||
+struct synaptics_led {
|
||||
+ struct psmouse *psmouse;
|
||||
+ struct work_struct work;
|
||||
+ struct led_classdev cdev;
|
||||
+};
|
||||
+
|
||||
+static void synaptics_set_led(struct psmouse *psmouse, int on)
|
||||
+{
|
||||
+ int i;
|
||||
+ unsigned char cmd = on ? 0x88 : 0x10;
|
||||
+
|
||||
+ ps2_begin_command(&psmouse->ps2dev);
|
||||
+ if (__ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11))
|
||||
+ goto out;
|
||||
+ for (i = 6; i >= 0; i -= 2) {
|
||||
+ unsigned char d = (cmd >> i) & 3;
|
||||
+ if (__ps2_command(&psmouse->ps2dev, &d, PSMOUSE_CMD_SETRES))
|
||||
+ goto out;
|
||||
+ }
|
||||
+ cmd = 0x0a;
|
||||
+ __ps2_command(&psmouse->ps2dev, &cmd, PSMOUSE_CMD_SETRATE);
|
||||
+ out:
|
||||
+ ps2_end_command(&psmouse->ps2dev);
|
||||
+}
|
||||
+
|
||||
+static void synaptics_led_work(struct work_struct *work)
|
||||
+{
|
||||
+ struct synaptics_led *led;
|
||||
+
|
||||
+ led = container_of(work, struct synaptics_led, work);
|
||||
+ synaptics_set_led(led->psmouse, led->cdev.brightness);
|
||||
+}
|
||||
+
|
||||
+static void synaptics_led_cdev_brightness_set(struct led_classdev *cdev,
|
||||
+ enum led_brightness value)
|
||||
+{
|
||||
+ struct synaptics_led *led;
|
||||
+
|
||||
+ led = container_of(cdev, struct synaptics_led, cdev);
|
||||
+ schedule_work(&led->work);
|
||||
+}
|
||||
+
|
||||
+static void synaptics_sync_led(struct psmouse *psmouse)
|
||||
+{
|
||||
+ struct synaptics_data *priv = psmouse->private;
|
||||
+
|
||||
+ if (priv->led)
|
||||
+ synaptics_set_led(psmouse, priv->led->cdev.brightness);
|
||||
+}
|
||||
+
|
||||
+static int synaptics_init_led(struct psmouse *psmouse)
|
||||
+{
|
||||
+ struct synaptics_data *priv = psmouse->private;
|
||||
+ struct synaptics_led *led;
|
||||
+ int err;
|
||||
+
|
||||
+ /* FIXME: LED is supposedly detectable in cap0c[1] 0x20, but it seems
|
||||
+ * not working on real machines.
|
||||
+ * So we check the product id to be sure.
|
||||
+ */
|
||||
+ if (!priv->ext_cap_0c || SYN_CAP_PRODUCT_ID(priv->ext_cap) != 0xe4)
|
||||
+ return 0;
|
||||
+
|
||||
+ printk(KERN_INFO "synaptics: support LED control\n");
|
||||
+ led = kzalloc(sizeof(struct synaptics_led), GFP_KERNEL);
|
||||
+ if (!led)
|
||||
+ return -ENOMEM;
|
||||
+ led->psmouse = psmouse;
|
||||
+ INIT_WORK(&led->work, synaptics_led_work);
|
||||
+ led->cdev.name = "psmouse::synaptics";
|
||||
+ led->cdev.brightness_set = synaptics_led_cdev_brightness_set;
|
||||
+ led->cdev.flags = LED_CORE_SUSPENDRESUME;
|
||||
+ err = led_classdev_register(NULL, &led->cdev);
|
||||
+ if (err < 0) {
|
||||
+ kfree(led);
|
||||
+ return err;
|
||||
+ }
|
||||
+ priv->led = led;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void synaptics_free_led(struct psmouse *psmouse)
|
||||
+{
|
||||
+ struct synaptics_data *priv = psmouse->private;
|
||||
+
|
||||
+ if (!priv->led)
|
||||
+ return;
|
||||
+ cancel_work_sync(&priv->led->work);
|
||||
+ synaptics_set_led(psmouse, 0);
|
||||
+ led_classdev_unregister(&priv->led->cdev);
|
||||
+ kfree(priv->led);
|
||||
+}
|
||||
+#else
|
||||
+#define synaptics_init_led(ps) 0
|
||||
+#define synaptics_free_led(ps) do {} while (0)
|
||||
+#define synaptics_sync_led(ps) do {} while (0)
|
||||
+#endif
|
||||
+
|
||||
/*****************************************************************************
|
||||
* Functions to interpret the absolute mode packets
|
||||
****************************************************************************/
|
||||
@@ -647,6 +752,7 @@ static void set_input_params(struct inpu
|
||||
|
||||
static void synaptics_disconnect(struct psmouse *psmouse)
|
||||
{
|
||||
+ synaptics_free_led(psmouse);
|
||||
synaptics_reset(psmouse);
|
||||
kfree(psmouse->private);
|
||||
psmouse->private = NULL;
|
||||
@@ -678,6 +784,8 @@ static int synaptics_reconnect(struct ps
|
||||
return -1;
|
||||
}
|
||||
|
||||
+ synaptics_sync_led(psmouse);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -752,6 +860,9 @@ int synaptics_init(struct psmouse *psmou
|
||||
SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity),
|
||||
priv->model_id, priv->capabilities, priv->ext_cap, priv->ext_cap_0c);
|
||||
|
||||
+ if (synaptics_init_led(psmouse) < 0)
|
||||
+ goto init_fail;
|
||||
+
|
||||
set_input_params(psmouse->dev, priv);
|
||||
|
||||
/*
|
||||
--- a/drivers/input/mouse/synaptics.h
|
||||
+++ b/drivers/input/mouse/synaptics.h
|
||||
@@ -97,6 +97,8 @@ struct synaptics_hw_state {
|
||||
signed char scroll;
|
||||
};
|
||||
|
||||
+struct synaptics_led;
|
||||
+
|
||||
struct synaptics_data {
|
||||
/* Data read from the touchpad */
|
||||
unsigned long int model_id; /* Model-ID */
|
||||
@@ -110,6 +112,7 @@ struct synaptics_data {
|
||||
struct serio *pt_port; /* Pass-through serio port */
|
||||
|
||||
struct synaptics_hw_state mt; /* current gesture packet */
|
||||
+ struct synaptics_led *led;
|
||||
};
|
||||
|
||||
void synaptics_module_init(void);
|
@ -1,90 +0,0 @@
|
||||
From: Jiri Benc <jbenc@suse.cz>
|
||||
Subject: Enable ixgbe as entropy source (disabled by default)
|
||||
References: FATE#307517
|
||||
Patch-mainline: never
|
||||
|
||||
Current disk-less systems have no entropy source whatsoever. Therefore, the
|
||||
network drivers tg3, bnx2, e1000, e1000e, igb and ixgbe should be enabled to
|
||||
feed entropy to the kernel via the IRQF_SAMPLE_RANDOM flag when loaded. This
|
||||
option shall not be enabled by default but implemented via a module option to
|
||||
be activated by the administrator.
|
||||
|
||||
Signed-off-by: Brandon Philips <bphilips@suse.de>
|
||||
|
||||
---
|
||||
drivers/net/ixgbe/ixgbe_main.c | 22 +++++++++++++++++++---
|
||||
1 file changed, 19 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/net/ixgbe/ixgbe_main.c
|
||||
+++ b/drivers/net/ixgbe/ixgbe_main.c
|
||||
@@ -56,6 +56,11 @@ static const char ixgbe_driver_string[]
|
||||
const char ixgbe_driver_version[] = DRV_VERSION;
|
||||
static char ixgbe_copyright[] = "Copyright (c) 1999-2010 Intel Corporation.";
|
||||
|
||||
+static int entropy = 0;
|
||||
+module_param(entropy, int, 0);
|
||||
+MODULE_PARM_DESC(entropy, "Allow ixgbe to populate the /dev/random entropy pool");
|
||||
+
|
||||
+
|
||||
static const struct ixgbe_info *ixgbe_info_tbl[] = {
|
||||
[board_82598] = &ixgbe_82598_info,
|
||||
[board_82599] = &ixgbe_82599_info,
|
||||
@@ -2317,6 +2322,7 @@ static int ixgbe_request_msix_irqs(struc
|
||||
irqreturn_t (*handler)(int, void *);
|
||||
int i, vector, q_vectors, err;
|
||||
int ri = 0, ti = 0;
|
||||
+ int irq_flags;
|
||||
|
||||
/* Decrement for Other and TCP Timer vectors */
|
||||
q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
|
||||
@@ -2334,22 +2340,27 @@ static int ixgbe_request_msix_irqs(struc
|
||||
struct ixgbe_q_vector *q_vector = adapter->q_vector[vector];
|
||||
handler = SET_HANDLER(q_vector);
|
||||
|
||||
+ irq_flags = 0;
|
||||
if (handler == &ixgbe_msix_clean_rx) {
|
||||
snprintf(q_vector->name, sizeof(q_vector->name) - 1,
|
||||
"%s-%s-%d", netdev->name, "rx", ri++);
|
||||
+ if (entropy)
|
||||
+ irq_flags = IRQF_SAMPLE_RANDOM;
|
||||
} else if (handler == &ixgbe_msix_clean_tx) {
|
||||
snprintf(q_vector->name, sizeof(q_vector->name) - 1,
|
||||
"%s-%s-%d", netdev->name, "tx", ti++);
|
||||
} else if (handler == &ixgbe_msix_clean_many) {
|
||||
snprintf(q_vector->name, sizeof(q_vector->name) - 1,
|
||||
"%s-%s-%d", netdev->name, "TxRx", ri++);
|
||||
+ if (entropy)
|
||||
+ irq_flags = IRQF_SAMPLE_RANDOM;
|
||||
ti++;
|
||||
} else {
|
||||
/* skip this unused q_vector */
|
||||
continue;
|
||||
}
|
||||
err = request_irq(adapter->msix_entries[vector].vector,
|
||||
- handler, 0, q_vector->name,
|
||||
+ handler, irq_flags, q_vector->name,
|
||||
q_vector);
|
||||
if (err) {
|
||||
e_err(probe, "request_irq failed for MSIX interrupt "
|
||||
@@ -2563,14 +2574,19 @@ static int ixgbe_request_irq(struct ixgb
|
||||
{
|
||||
struct net_device *netdev = adapter->netdev;
|
||||
int err;
|
||||
+ int irq_flags = 0;
|
||||
+
|
||||
+ if (entropy)
|
||||
+ irq_flags = IRQF_SAMPLE_RANDOM;
|
||||
|
||||
if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
|
||||
err = ixgbe_request_msix_irqs(adapter);
|
||||
} else if (adapter->flags & IXGBE_FLAG_MSI_ENABLED) {
|
||||
- err = request_irq(adapter->pdev->irq, ixgbe_intr, 0,
|
||||
+ err = request_irq(adapter->pdev->irq, ixgbe_intr, irq_flags,
|
||||
netdev->name, netdev);
|
||||
} else {
|
||||
- err = request_irq(adapter->pdev->irq, ixgbe_intr, IRQF_SHARED,
|
||||
+ irq_flags |= IRQF_SHARED;
|
||||
+ err = request_irq(adapter->pdev->irq, ixgbe_intr, irq_flags,
|
||||
netdev->name, netdev);
|
||||
}
|
||||
|
@ -1,24 +0,0 @@
|
||||
From: Tejun Heo <teheo@suse.de>
|
||||
Subject: [PATCH] libata: unlock HPA by default
|
||||
References: 299267
|
||||
Patch-mainline: not yet
|
||||
|
||||
Unlock HPA by default. This is to stay compatible with the old IDE
|
||||
drivers.
|
||||
|
||||
Signed-off-by: Tejun Heo <teheo@suse.de>
|
||||
---
|
||||
drivers/ata/libata-core.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/ata/libata-core.c
|
||||
+++ b/drivers/ata/libata-core.c
|
||||
@@ -138,7 +138,7 @@ int libata_fua = 0;
|
||||
module_param_named(fua, libata_fua, int, 0444);
|
||||
MODULE_PARM_DESC(fua, "FUA support (0=off [default], 1=on)");
|
||||
|
||||
-static int ata_ignore_hpa;
|
||||
+static int ata_ignore_hpa = 1;
|
||||
module_param_named(ignore_hpa, ata_ignore_hpa, int, 0644);
|
||||
MODULE_PARM_DESC(ignore_hpa, "Ignore HPA limit (0=keep BIOS limits, 1=ignore limits, using full disk)");
|
||||
|
@ -1,70 +0,0 @@
|
||||
From: Martin Wilck <martin.wilck@fujitsu-siemens.com>
|
||||
Subject: megaraid_mbox: Oops on SG_IO
|
||||
References: bnc#475619
|
||||
Patch-mainline: not yet
|
||||
|
||||
This patch fixes an Oops in megaraid_mbox that happens when a
|
||||
MODE_SENSE command for a logical drive is started viaioctl(SG_IO).
|
||||
|
||||
The problem only occurs if the buffer specified by the user to receive
|
||||
the mode data resides in highmem and if the buffer is aligned for
|
||||
direct dma (no bounce buffer necessary). megaraid_mbox emulates
|
||||
the MODE_SENSE command and writes the data using memset() directly
|
||||
into user buffer. If the buffer is at a currently unmapped highmem
|
||||
page, this leads to an Oops.
|
||||
|
||||
Signed-off-by: Hannes Reinecke <hare@suse.de>
|
||||
|
||||
---
|
||||
drivers/scsi/megaraid/megaraid_mbox.c | 28 +++++++++++++++++++++++-----
|
||||
1 file changed, 23 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/scsi/megaraid/megaraid_mbox.c
|
||||
+++ b/drivers/scsi/megaraid/megaraid_mbox.c
|
||||
@@ -1586,13 +1586,20 @@ megaraid_mbox_build_cmd(adapter_t *adapt
|
||||
case MODE_SENSE:
|
||||
{
|
||||
struct scatterlist *sgl;
|
||||
- caddr_t vaddr;
|
||||
+ struct page *pg;
|
||||
+ unsigned char *vaddr;
|
||||
+ unsigned long flags;
|
||||
|
||||
sgl = scsi_sglist(scp);
|
||||
- if (sg_page(sgl)) {
|
||||
- vaddr = (caddr_t) sg_virt(&sgl[0]);
|
||||
+ pg = sg_page(sgl);
|
||||
+ if (pg) {
|
||||
+ local_irq_save(flags);
|
||||
+ vaddr = kmap_atomic(pg, KM_BIO_SRC_IRQ) + sgl->offset;
|
||||
|
||||
memset(vaddr, 0, scp->cmnd[4]);
|
||||
+
|
||||
+ kunmap_atomic(vaddr, KM_BIO_SRC_IRQ);
|
||||
+ local_irq_restore(flags);
|
||||
}
|
||||
else {
|
||||
con_log(CL_ANN, (KERN_WARNING
|
||||
@@ -2330,9 +2337,20 @@ megaraid_mbox_dpc(unsigned long devp)
|
||||
if (scp->cmnd[0] == INQUIRY && status == 0 && islogical == 0
|
||||
&& IS_RAID_CH(raid_dev, scb->dev_channel)) {
|
||||
|
||||
+ struct page *pg;
|
||||
+ unsigned char *vaddr;
|
||||
+ unsigned long flags;
|
||||
+
|
||||
sgl = scsi_sglist(scp);
|
||||
- if (sg_page(sgl)) {
|
||||
- c = *(unsigned char *) sg_virt(&sgl[0]);
|
||||
+ pg = sg_page(sgl);
|
||||
+ if (pg) {
|
||||
+ local_irq_save(flags);
|
||||
+ vaddr = kmap_atomic(pg, KM_BIO_SRC_IRQ) + sgl->offset;
|
||||
+
|
||||
+ c = *vaddr;
|
||||
+
|
||||
+ kunmap_atomic(vaddr, KM_BIO_SRC_IRQ);
|
||||
+ local_irq_restore(flags);
|
||||
} else {
|
||||
con_log(CL_ANN, (KERN_WARNING
|
||||
"megaraid mailbox: invalid sg:%d\n",
|
File diff suppressed because it is too large
Load Diff
@ -1,53 +0,0 @@
|
||||
From: Olaf Hering <olh@suse.de>
|
||||
Subject: enable mouse button emulation also for G5
|
||||
Patch-mainline: never
|
||||
|
||||
fix compile errors
|
||||
|
||||
drivers/macintosh/Kconfig | 2 +-
|
||||
drivers/macintosh/adb.c | 4 ++++
|
||||
drivers/macintosh/adbhid.c | 6 +++++-
|
||||
3 files changed, 10 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/macintosh/Kconfig
|
||||
+++ b/drivers/macintosh/Kconfig
|
||||
@@ -13,7 +13,7 @@ if MACINTOSH_DRIVERS
|
||||
|
||||
config ADB
|
||||
bool "Apple Desktop Bus (ADB) support"
|
||||
- depends on MAC || (PPC_PMAC && PPC32)
|
||||
+ depends on MAC || PPC_PMAC
|
||||
help
|
||||
Apple Desktop Bus (ADB) support is for support of devices which
|
||||
are connected to an ADB port. ADB devices tend to have 4 pins.
|
||||
--- a/drivers/macintosh/adb.c
|
||||
+++ b/drivers/macintosh/adb.c
|
||||
@@ -298,6 +298,10 @@ static int __init adb_init(void)
|
||||
if (!machine_is(chrp) && !machine_is(powermac))
|
||||
return 0;
|
||||
#endif
|
||||
+#ifdef CONFIG_PPC64
|
||||
+ if (!machine_is(powermac))
|
||||
+ return 0;
|
||||
+#endif
|
||||
#ifdef CONFIG_MAC
|
||||
if (!MACH_IS_MAC)
|
||||
return 0;
|
||||
--- a/drivers/macintosh/adbhid.c
|
||||
+++ b/drivers/macintosh/adbhid.c
|
||||
@@ -1264,10 +1264,14 @@ init_ms_a3(int id)
|
||||
|
||||
static int __init adbhid_init(void)
|
||||
{
|
||||
-#ifndef CONFIG_MAC
|
||||
+#ifdef CONFIG_PPC32
|
||||
if (!machine_is(chrp) && !machine_is(powermac))
|
||||
return 0;
|
||||
#endif
|
||||
+#ifdef CONFIG_PPC64
|
||||
+ if (!machine_is(powermac))
|
||||
+ return 0;
|
||||
+#endif
|
||||
|
||||
led_request.complete = 1;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,707 +0,0 @@
|
||||
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,193 +0,0 @@
|
||||
From: Matt Carlson <mcarlson@broadcom.com>
|
||||
Subject: tg3: 5785 and 57780 asic revs not working
|
||||
References: bnc#580780
|
||||
Patch-mainline: Never
|
||||
|
||||
There is a known problem with phylib that causes a lot of problems.
|
||||
Phylib does not load phy modules as it detects devices on the MDIO bus.
|
||||
If the phylib module gets loaded as a dependancy of tg3, there will be
|
||||
no opportunity to load the needed broadcom.ko module before tg3 requests
|
||||
phylib to probe the MDIO bus. The result will be that tg3 will fail to
|
||||
attach to 5785 and 57780 devices.
|
||||
|
||||
There are several known solutions to this problem. (None of these
|
||||
should go upstream. The upstream fix should be to get phylib to load
|
||||
modules for devices it encounters.) Only one of them need be applied.
|
||||
|
||||
1) Statically link in the broadcom.ko module into the kernel.
|
||||
|
||||
2) Add the following to /etc/modprobe.d/local.conf or its equivalent:
|
||||
|
||||
install tg3 /sbin/modprobe broadcom; /sbin/modprobe --ignore-install tg3
|
||||
|
||||
3) Apply the following patch:
|
||||
|
||||
Signed-off-by: Brandon Philips <bphilips@suse.de>
|
||||
|
||||
---
|
||||
drivers/net/tg3.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
drivers/net/tg3.h | 9 +++++
|
||||
2 files changed, 92 insertions(+)
|
||||
|
||||
--- a/drivers/net/tg3.c
|
||||
+++ b/drivers/net/tg3.c
|
||||
@@ -1998,6 +1998,58 @@ static int tg3_phy_reset(struct tg3 *tp)
|
||||
tg3_phy_toggle_apd(tp, false);
|
||||
|
||||
out:
|
||||
+ if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM50610 ||
|
||||
+ (tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM50610M) {
|
||||
+ u32 reg;
|
||||
+
|
||||
+ /* Enable SM_DSP clock and tx 6dB coding. */
|
||||
+ reg = MII_TG3_AUXCTL_SHDWSEL_AUXCTL |
|
||||
+ MII_TG3_AUXCTL_ACTL_SMDSP_ENA |
|
||||
+ MII_TG3_AUXCTL_ACTL_TX_6DB;
|
||||
+ tg3_writephy(tp, MII_TG3_AUX_CTRL, reg);
|
||||
+
|
||||
+ reg = MII_TG3_DSP_EXP8_REJ2MHz;
|
||||
+ tg3_phydsp_write(tp, MII_TG3_DSP_EXP8, reg);
|
||||
+
|
||||
+ /* Apply workaround to A0 revision parts only. */
|
||||
+ if (tp->phy_id == TG3_PHY_ID_BCM50610 ||
|
||||
+ tp->phy_id == TG3_PHY_ID_BCM50610M) {
|
||||
+ tg3_phydsp_write(tp, 0x001F, 0x0300);
|
||||
+ tg3_phydsp_write(tp, 0x601F, 0x0002);
|
||||
+ tg3_phydsp_write(tp, 0x0F75, 0x003C);
|
||||
+ tg3_phydsp_write(tp, 0x0F96, 0x0010);
|
||||
+ tg3_phydsp_write(tp, 0x0F97, 0x0C0C);
|
||||
+ }
|
||||
+
|
||||
+ /* Turn off SM_DSP clock. */
|
||||
+ reg = MII_TG3_AUXCTL_SHDWSEL_AUXCTL |
|
||||
+ MII_TG3_AUXCTL_ACTL_TX_6DB;
|
||||
+ tg3_writephy(tp, MII_TG3_AUX_CTRL, reg);
|
||||
+
|
||||
+ /* Clear all mode configuration bits. */
|
||||
+ reg = MII_TG3_MISC_SHDW_WREN |
|
||||
+ MII_TG3_MISC_SHDW_RGMII_SEL;
|
||||
+ tg3_writephy(tp, MII_TG3_MISC_SHDW, reg);
|
||||
+ }
|
||||
+ if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM57780) {
|
||||
+ u32 reg;
|
||||
+
|
||||
+ /* Enable SM_DSP clock and tx 6dB coding. */
|
||||
+ reg = MII_TG3_AUXCTL_SHDWSEL_AUXCTL |
|
||||
+ MII_TG3_AUXCTL_ACTL_SMDSP_ENA |
|
||||
+ MII_TG3_AUXCTL_ACTL_TX_6DB;
|
||||
+ tg3_writephy(tp, MII_TG3_AUX_CTRL, reg);
|
||||
+
|
||||
+ tg3_writephy(tp, MII_TG3_DSP_ADDRESS, MII_TG3_DSP_EXP75);
|
||||
+ tg3_readphy(tp, MII_TG3_DSP_RW_PORT, ®);
|
||||
+ reg |= MII_TG3_DSP_EXP75_SUP_CM_OSC;
|
||||
+ tg3_phydsp_write(tp, MII_TG3_DSP_EXP75, reg);
|
||||
+
|
||||
+ /* Turn off SM_DSP clock. */
|
||||
+ reg = MII_TG3_AUXCTL_SHDWSEL_AUXCTL |
|
||||
+ MII_TG3_AUXCTL_ACTL_TX_6DB;
|
||||
+ tg3_writephy(tp, MII_TG3_AUX_CTRL, reg);
|
||||
+ }
|
||||
if (tp->phy_flags & TG3_PHYFLG_ADC_BUG) {
|
||||
tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00);
|
||||
tg3_phydsp_write(tp, 0x201f, 0x2aaa);
|
||||
@@ -2054,6 +2106,22 @@ out:
|
||||
/* adjust output voltage */
|
||||
tg3_writephy(tp, MII_TG3_FET_PTEST, 0x12);
|
||||
}
|
||||
+ else if (tp->phy_flags & TG3_PHYFLG_IS_FET) {
|
||||
+ u32 brcmtest;
|
||||
+ if (!tg3_readphy(tp, MII_TG3_FET_TEST, &brcmtest) &&
|
||||
+ !tg3_writephy(tp, MII_TG3_FET_TEST,
|
||||
+ brcmtest | MII_TG3_FET_SHADOW_EN)) {
|
||||
+ u32 val, reg = MII_TG3_FET_SHDW_AUXMODE4;
|
||||
+
|
||||
+ if (!tg3_readphy(tp, reg, &val)) {
|
||||
+ val &= ~MII_TG3_FET_SHDW_AM4_LED_MASK;
|
||||
+ val |= MII_TG3_FET_SHDW_AM4_LED_MODE1;
|
||||
+ tg3_writephy(tp, reg, val);
|
||||
+ }
|
||||
+
|
||||
+ tg3_writephy(tp, MII_TG3_FET_TEST, brcmtest);
|
||||
+ }
|
||||
+ }
|
||||
|
||||
tg3_phy_toggle_automdix(tp, 1);
|
||||
tg3_phy_set_wirespeed(tp);
|
||||
@@ -3288,6 +3356,15 @@ relink:
|
||||
|
||||
tg3_phy_eee_adjust(tp, current_link_up);
|
||||
|
||||
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) {
|
||||
+ if (tp->link_config.active_speed == SPEED_10)
|
||||
+ tw32(MAC_MI_STAT,
|
||||
+ MAC_MI_STAT_10MBPS_MODE |
|
||||
+ MAC_MI_STAT_LNKSTAT_ATTN_ENAB);
|
||||
+ else
|
||||
+ tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB);
|
||||
+ }
|
||||
+
|
||||
if (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) {
|
||||
/* Polled via timer. */
|
||||
tw32_f(MAC_EVENT, 0);
|
||||
@@ -13411,9 +13488,11 @@ static int __devinit tg3_get_invariants(
|
||||
GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_BX)
|
||||
tp->coalesce_mode |= HOSTCC_MODE_32BYTE;
|
||||
|
||||
+#if 0
|
||||
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
|
||||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
|
||||
tp->tg3_flags3 |= TG3_FLG3_USE_PHYLIB;
|
||||
+#endif
|
||||
|
||||
err = tg3_mdio_init(tp);
|
||||
if (err)
|
||||
@@ -14203,6 +14282,10 @@ static char * __devinit tg3_phy_string(s
|
||||
case TG3_PHY_ID_BCM5718S: return "5718S";
|
||||
case TG3_PHY_ID_BCM57765: return "57765";
|
||||
case TG3_PHY_ID_BCM5719C: return "5719C";
|
||||
+ case TG3_PHY_ID_BCM50610: return "50610";
|
||||
+ case TG3_PHY_ID_BCM50610M: return "50610M";
|
||||
+ case TG3_PHY_ID_BCMAC131: return "AC131";
|
||||
+ case TG3_PHY_ID_BCM57780: return "57780";
|
||||
case TG3_PHY_ID_BCM8002: return "8002/serdes";
|
||||
case 0: return "serdes";
|
||||
default: return "unknown";
|
||||
--- a/drivers/net/tg3.h
|
||||
+++ b/drivers/net/tg3.h
|
||||
@@ -2072,6 +2072,7 @@
|
||||
#define MII_TG3_DSP_EXP8_REJ2MHz 0x0001
|
||||
#define MII_TG3_DSP_EXP8_AEDW 0x0200
|
||||
#define MII_TG3_DSP_EXP75 0x0f75
|
||||
+#define MII_TG3_DSP_EXP75_SUP_CM_OSC 0x0001
|
||||
#define MII_TG3_DSP_EXP96 0x0f96
|
||||
#define MII_TG3_DSP_EXP97 0x0f97
|
||||
|
||||
@@ -2127,6 +2128,8 @@
|
||||
#define MII_TG3_MISC_SHDW_SCR5_LPED 0x0010
|
||||
#define MII_TG3_MISC_SHDW_SCR5_SEL 0x1400
|
||||
|
||||
+#define MII_TG3_MISC_SHDW_RGMII_SEL 0x2c00
|
||||
+
|
||||
#define MII_TG3_TEST1 0x1e
|
||||
#define MII_TG3_TEST1_TRIM_EN 0x0010
|
||||
#define MII_TG3_TEST1_CRC_EN 0x8000
|
||||
@@ -2144,6 +2147,8 @@
|
||||
#define MII_TG3_FET_SHDW_MISCCTRL_MDIX 0x4000
|
||||
|
||||
#define MII_TG3_FET_SHDW_AUXMODE4 0x1a
|
||||
+#define MII_TG3_FET_SHDW_AM4_LED_MODE1 0x0001
|
||||
+#define MII_TG3_FET_SHDW_AM4_LED_MASK 0x0003
|
||||
#define MII_TG3_FET_SHDW_AUXMODE4_SBPD 0x0008
|
||||
|
||||
#define MII_TG3_FET_SHDW_AUXSTAT2 0x1b
|
||||
@@ -2922,6 +2927,10 @@ struct tg3 {
|
||||
#define TG3_PHY_ID_BCM5719C 0x5c0d8a20
|
||||
#define TG3_PHY_ID_BCM5906 0xdc00ac40
|
||||
#define TG3_PHY_ID_BCM8002 0x60010140
|
||||
+#define TG3_PHY_ID_BCM50610 0xbc050d60
|
||||
+#define TG3_PHY_ID_BCM50610M 0xbc050d70
|
||||
+#define TG3_PHY_ID_BCMAC131 0xbc050c70
|
||||
+#define TG3_PHY_ID_BCM57780 0x5c0d8990
|
||||
#define TG3_PHY_ID_INVALID 0xffffffff
|
||||
|
||||
#define PHY_ID_RTL8211C 0x001cc910
|
@ -1,61 +0,0 @@
|
||||
From: Brandon Philips <bphilips@suse.de>
|
||||
Subject: [PATCH] tg3: entropy source
|
||||
Patch-mainline: never
|
||||
References: FATE#307517
|
||||
|
||||
Signed-off-by: Brandon Philips <bphilips@suse.de>
|
||||
|
||||
---
|
||||
drivers/net/tg3.c | 13 +++++++++----
|
||||
1 file changed, 9 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/net/tg3.c
|
||||
+++ b/drivers/net/tg3.c
|
||||
@@ -15,7 +15,6 @@
|
||||
* notice is accompanying it.
|
||||
*/
|
||||
|
||||
-
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/stringify.h>
|
||||
@@ -67,6 +66,10 @@
|
||||
|
||||
#include "tg3.h"
|
||||
|
||||
+static int entropy = 0;
|
||||
+module_param(entropy, int, 0);
|
||||
+MODULE_PARM_DESC(entropy, "Allow tg3 to populate the /dev/random entropy pool");
|
||||
+
|
||||
#define DRV_MODULE_NAME "tg3"
|
||||
#define TG3_MAJ_NUM 3
|
||||
#define TG3_MIN_NUM 116
|
||||
@@ -8590,10 +8593,13 @@ restart_timer:
|
||||
static int tg3_request_irq(struct tg3 *tp, int irq_num)
|
||||
{
|
||||
irq_handler_t fn;
|
||||
- unsigned long flags;
|
||||
+ unsigned long flags = 0;
|
||||
char *name;
|
||||
struct tg3_napi *tnapi = &tp->napi[irq_num];
|
||||
|
||||
+ if (entropy)
|
||||
+ flags = IRQF_SAMPLE_RANDOM;
|
||||
+
|
||||
if (tp->irq_cnt == 1)
|
||||
name = tp->dev->name;
|
||||
else {
|
||||
@@ -8606,12 +8612,11 @@ static int tg3_request_irq(struct tg3 *t
|
||||
fn = tg3_msi;
|
||||
if (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI)
|
||||
fn = tg3_msi_1shot;
|
||||
- flags = IRQF_SAMPLE_RANDOM;
|
||||
} else {
|
||||
fn = tg3_interrupt;
|
||||
if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)
|
||||
fn = tg3_interrupt_tagged;
|
||||
- flags = IRQF_SHARED | IRQF_SAMPLE_RANDOM;
|
||||
+ flags |= IRQF_SHARED;
|
||||
}
|
||||
|
||||
return request_irq(tnapi->irq_vec, fn, flags, name, tnapi);
|
@ -1,78 +0,0 @@
|
||||
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,67 +0,0 @@
|
||||
From: Nick Piggin <npiggin@suse.de>
|
||||
Subject: be more aggressive with zone reclaims
|
||||
References: bnc#476525
|
||||
Patch-mainline: no
|
||||
|
||||
The zone reclaim design is not very good for parallel allocations.
|
||||
The primary problem is that only one thread is allowed to perform
|
||||
zone-reclaim at a time. If another thread needs memory from that
|
||||
zone/node, then its zone-reclaim will fail and it will be forced
|
||||
to fall back to allocating from another zone.
|
||||
|
||||
Additionally, the default zone reclaim priority is insufficient
|
||||
for massively parallel allocations. Lower ZONE_RECLAIM_PRIORITY
|
||||
to fix it. This can result in higher latency spikes, but similar
|
||||
kind of page allocation latency can often be encountered as
|
||||
normal part of page reclaim when pagecache fills memory.
|
||||
|
||||
Signed-off-by: Petr Tesarik <ptesarik@suse.cz>
|
||||
|
||||
---
|
||||
mm/vmscan.c | 13 ++++---------
|
||||
1 file changed, 4 insertions(+), 9 deletions(-)
|
||||
|
||||
--- a/mm/vmscan.c
|
||||
+++ b/mm/vmscan.c
|
||||
@@ -2515,7 +2515,7 @@ int zone_reclaim_mode __read_mostly;
|
||||
* of a node considered for each zone_reclaim. 4 scans 1/16th of
|
||||
* a zone.
|
||||
*/
|
||||
-#define ZONE_RECLAIM_PRIORITY 4
|
||||
+#define ZONE_RECLAIM_PRIORITY 0
|
||||
|
||||
/*
|
||||
* Percentage of pages in a zone that must be unmapped for zone_reclaim to
|
||||
@@ -2620,6 +2620,8 @@ static int __zone_reclaim(struct zone *z
|
||||
|
||||
slab_reclaimable = zone_page_state(zone, NR_SLAB_RECLAIMABLE);
|
||||
if (slab_reclaimable > zone->min_slab_pages) {
|
||||
+ unsigned long lru_pages = zone_reclaimable_pages(zone);
|
||||
+
|
||||
/*
|
||||
* shrink_slab() does not currently allow us to determine how
|
||||
* many pages were freed in this zone. So we take the current
|
||||
@@ -2630,10 +2632,7 @@ static int __zone_reclaim(struct zone *z
|
||||
* Note that shrink_slab will free memory on all zones and may
|
||||
* take a long time.
|
||||
*/
|
||||
- while (shrink_slab(sc.nr_scanned, gfp_mask, order) &&
|
||||
- zone_page_state(zone, NR_SLAB_RECLAIMABLE) >
|
||||
- slab_reclaimable - nr_pages)
|
||||
- ;
|
||||
+ shrink_slab(sc.nr_scanned, gfp_mask, lru_pages);
|
||||
|
||||
/*
|
||||
* Update nr_reclaimed by the number of slab pages we
|
||||
@@ -2687,11 +2686,7 @@ int zone_reclaim(struct zone *zone, gfp_
|
||||
if (node_state(node_id, N_CPU) && node_id != numa_node_id())
|
||||
return ZONE_RECLAIM_NOSCAN;
|
||||
|
||||
- if (zone_test_and_set_flag(zone, ZONE_RECLAIM_LOCKED))
|
||||
- return ZONE_RECLAIM_NOSCAN;
|
||||
-
|
||||
ret = __zone_reclaim(zone, gfp_mask, order);
|
||||
- zone_clear_flag(zone, ZONE_RECLAIM_LOCKED);
|
||||
|
||||
if (!ret)
|
||||
count_vm_event(PGSCAN_ZONE_RECLAIM_FAILED);
|
@ -1,61 +0,0 @@
|
||||
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
|
||||
|
@ -1,45 +0,0 @@
|
||||
From: jbeulich@novell.com
|
||||
Subject: Module use count must be updated as bridges are created/destroyed
|
||||
Patch-mainline: unknown
|
||||
References: 267651
|
||||
|
||||
Otherwise 'modprobe -r' on a module having a dependency on bridge will
|
||||
implicitly unload bridge, bringing down all connectivity that was using
|
||||
bridges.
|
||||
|
||||
---
|
||||
net/bridge/br_if.c | 9 +++++++++
|
||||
1 file changed, 9 insertions(+)
|
||||
|
||||
--- a/net/bridge/br_if.c
|
||||
+++ b/net/bridge/br_if.c
|
||||
@@ -291,6 +291,11 @@ int br_add_bridge(struct net *net, const
|
||||
if (!dev)
|
||||
return -ENOMEM;
|
||||
|
||||
+ if (!try_module_get(THIS_MODULE)) {
|
||||
+ free_netdev(dev);
|
||||
+ return -ENOENT;
|
||||
+ }
|
||||
+
|
||||
rtnl_lock();
|
||||
if (strchr(dev->name, '%')) {
|
||||
ret = dev_alloc_name(dev, dev->name);
|
||||
@@ -309,6 +314,8 @@ int br_add_bridge(struct net *net, const
|
||||
unregister_netdevice(dev);
|
||||
out:
|
||||
rtnl_unlock();
|
||||
+ if (ret)
|
||||
+ module_put(THIS_MODULE);
|
||||
return ret;
|
||||
|
||||
out_free:
|
||||
@@ -340,6 +347,8 @@ int br_del_bridge(struct net *net, const
|
||||
del_br(netdev_priv(dev), NULL);
|
||||
|
||||
rtnl_unlock();
|
||||
+ if (ret == 0)
|
||||
+ module_put(THIS_MODULE);
|
||||
return ret;
|
||||
}
|
||||
|
@ -1,74 +0,0 @@
|
||||
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,65 +0,0 @@
|
||||
From: Thomas Renninger <trenn@suse.de>
|
||||
Subject: CPUFREQ: ondemand: Limit default sampling rate to 300ms max.
|
||||
References: bnc#464461
|
||||
Patch-Mainline: never, SLE11 only
|
||||
|
||||
Modified for SP1 by Jiri Bohac <jbohac@suse.cz>
|
||||
|
||||
HW cpufreq drivers (e.g. all non-acpi AMD) may report too high latency values.
|
||||
The default sampling rate (how often the ondemand/conservative governor
|
||||
checks for frequency adjustments) may therefore be much too high,
|
||||
resulting in performance loss.
|
||||
|
||||
Restrict default sampling rate to 300ms. 333ms sampling rate is field
|
||||
tested with userspace governors, 300ms should be a fine maximum default
|
||||
value for the ondemand kernel governor for all HW out there.
|
||||
|
||||
Set default up_threshold to 40 on multi core systems.
|
||||
This should avoid effects where two CPU intensive threads are waiting on
|
||||
each other on separate cores. On a single core machine these would all be
|
||||
processed on one core resulting in higher utilization of the one core.
|
||||
|
||||
---
|
||||
drivers/cpufreq/cpufreq_ondemand.c | 24 ++++++++++++++++++++++++
|
||||
1 file changed, 24 insertions(+)
|
||||
|
||||
--- a/drivers/cpufreq/cpufreq_ondemand.c
|
||||
+++ b/drivers/cpufreq/cpufreq_ondemand.c
|
||||
@@ -35,6 +35,7 @@
|
||||
#define MICRO_FREQUENCY_MIN_SAMPLE_RATE (10000)
|
||||
#define MIN_FREQUENCY_UP_THRESHOLD (11)
|
||||
#define MAX_FREQUENCY_UP_THRESHOLD (100)
|
||||
+#define MAX_DEFAULT_SAMPLING_RATE (300 * 1000U)
|
||||
|
||||
/*
|
||||
* The polling frequency of this governor depends on the capability of
|
||||
@@ -736,6 +737,29 @@ static int cpufreq_governor_dbs(struct c
|
||||
dbs_tuners_ins.sampling_rate =
|
||||
max(min_sampling_rate,
|
||||
latency * LATENCY_MULTIPLIER);
|
||||
+ /*
|
||||
+ * Cut def_sampling rate to 300ms if it was above,
|
||||
+ * still consider to not set it above latency
|
||||
+ * transition * 100
|
||||
+ */
|
||||
+ if (dbs_tuners_ins.sampling_rate > MAX_DEFAULT_SAMPLING_RATE) {
|
||||
+ dbs_tuners_ins.sampling_rate =
|
||||
+ max(min_sampling_rate, MAX_DEFAULT_SAMPLING_RATE);
|
||||
+ printk(KERN_INFO "CPUFREQ: ondemand sampling "
|
||||
+ "rate set to %d ms\n",
|
||||
+ dbs_tuners_ins.sampling_rate / 1000);
|
||||
+ }
|
||||
+ /*
|
||||
+ * Be conservative in respect to performance.
|
||||
+ * If an application calculates using two threads
|
||||
+ * depending on each other, they will be run on several
|
||||
+ * CPU cores resulting on 50% load on both.
|
||||
+ * SLED might still want to prefer 80% up_threshold
|
||||
+ * by default, but we cannot differ that here.
|
||||
+ */
|
||||
+ if (num_online_cpus() > 1)
|
||||
+ dbs_tuners_ins.up_threshold =
|
||||
+ DEF_FREQUENCY_UP_THRESHOLD / 2;
|
||||
dbs_tuners_ins.io_is_busy = should_io_be_busy();
|
||||
}
|
||||
mutex_unlock(&dbs_mutex);
|
@ -1,29 +0,0 @@
|
||||
From: Hannes Reinecke <hare@suse.de>
|
||||
Subject: Reattach device handler for multipath devices
|
||||
References: bnc#435688
|
||||
Patch-mainline: not yet
|
||||
|
||||
The multipath daemon might have specified a different device_handler
|
||||
than the one a device is attached to by default.
|
||||
So we should try to re-attach with the user-specified device_handler
|
||||
and only return an error if that fails.
|
||||
And we should _not_ detach existing hardware handlers. This will
|
||||
set the path to failed during failover.
|
||||
|
||||
Signed-off-by: Hannes Reinecke <hare@suse.de
|
||||
|
||||
---
|
||||
drivers/md/dm-mpath.c | 2 --
|
||||
1 file changed, 2 deletions(-)
|
||||
|
||||
--- a/drivers/md/dm-mpath.c
|
||||
+++ b/drivers/md/dm-mpath.c
|
||||
@@ -168,8 +168,6 @@ static void free_pgpaths(struct list_hea
|
||||
|
||||
list_for_each_entry_safe(pgpath, tmp, pgpaths, list) {
|
||||
list_del(&pgpath->list);
|
||||
- if (m->hw_handler_name)
|
||||
- scsi_dh_detach(bdev_get_queue(pgpath->path.dev->bdev));
|
||||
dm_put_device(ti, pgpath->path.dev);
|
||||
free_pgpath(pgpath);
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
From: Nikanth Karthikesan <knikanth@suse.de>
|
||||
Subject: Release md->map_lock before set_disk_ro
|
||||
Patch-mainline: No
|
||||
References: bnc#556899 bnc#479784
|
||||
|
||||
Signed-off-by: Nikanth Karthikesan <knikanth@suse.de>
|
||||
|
||||
Calling set_disk_ro() with irqs disabled triggers a warning.
|
||||
|
||||
set_disk_ro() can be called outside the
|
||||
write_lock_irqsave(&md->map_lock)? And to get the
|
||||
dm_table_get_mode(md->map), we just need to hold a reference
|
||||
with dm_get_table() and dm_table_put()
|
||||
|
||||
---
|
||||
drivers/md/dm.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/md/dm.c
|
||||
+++ b/drivers/md/dm.c
|
||||
@@ -2174,12 +2174,15 @@ static struct dm_table *__bind(struct ma
|
||||
old_map = md->map;
|
||||
md->map = t;
|
||||
dm_table_set_restrictions(t, q, limits);
|
||||
+ write_unlock_irqrestore(&md->map_lock, flags);
|
||||
+
|
||||
+ dm_table_get(md->map);
|
||||
if (!(dm_table_get_mode(t) & FMODE_WRITE)) {
|
||||
set_disk_ro(md->disk, 1);
|
||||
} else {
|
||||
set_disk_ro(md->disk, 0);
|
||||
}
|
||||
- write_unlock_irqrestore(&md->map_lock, flags);
|
||||
+ dm_table_put(md->map);
|
||||
|
||||
return old_map;
|
||||
}
|
@ -1,90 +0,0 @@
|
||||
From: Hannes Reinecke <hare@suse.de>
|
||||
Subject: dm multipath devices are not getting created for readonly devices
|
||||
References: bnc#382705
|
||||
Patch-mainline: not yet
|
||||
|
||||
Currently we cannot create device-mapper tables for multipath devices
|
||||
whenever they are read-only.
|
||||
This patch modifies the device-mapper to set the 'READ-ONLY' flag
|
||||
automatically whenever a read-only is added to the table.
|
||||
|
||||
Signed-off-by: Hannes Reinecke <hare@suse.de>
|
||||
|
||||
---
|
||||
drivers/md/dm-table.c | 10 +++++++++-
|
||||
drivers/md/dm.c | 18 ++++++++++++++++--
|
||||
2 files changed, 25 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/md/dm-table.c
|
||||
+++ b/drivers/md/dm-table.c
|
||||
@@ -465,11 +465,19 @@ static int __table_get_device(struct dm_
|
||||
dd->dm_dev.mode = mode;
|
||||
dd->dm_dev.bdev = NULL;
|
||||
|
||||
- if ((r = open_dev(dd, dev, t->md))) {
|
||||
+ r = open_dev(dd, dev, t->md);
|
||||
+ if (r == -EROFS) {
|
||||
+ dd->dm_dev.mode &= ~FMODE_WRITE;
|
||||
+ r = open_dev(dd, dev, t->md);
|
||||
+ }
|
||||
+ if (r) {
|
||||
kfree(dd);
|
||||
return r;
|
||||
}
|
||||
|
||||
+ if (dd->dm_dev.mode != mode)
|
||||
+ t->mode = dd->dm_dev.mode;
|
||||
+
|
||||
format_dev_t(dd->dm_dev.name, dev);
|
||||
|
||||
atomic_set(&dd->count, 0);
|
||||
--- a/drivers/md/dm.c
|
||||
+++ b/drivers/md/dm.c
|
||||
@@ -343,16 +343,25 @@ int dm_deleting_md(struct mapped_device
|
||||
static int dm_blk_open(struct block_device *bdev, fmode_t mode)
|
||||
{
|
||||
struct mapped_device *md;
|
||||
+ int retval = 0;
|
||||
|
||||
spin_lock(&_minor_lock);
|
||||
|
||||
md = bdev->bd_disk->private_data;
|
||||
- if (!md)
|
||||
+ if (!md) {
|
||||
+ retval = -ENXIO;
|
||||
goto out;
|
||||
+ }
|
||||
|
||||
if (test_bit(DMF_FREEING, &md->flags) ||
|
||||
dm_deleting_md(md)) {
|
||||
md = NULL;
|
||||
+ retval = -ENXIO;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if (get_disk_ro(md->disk) && (mode & FMODE_WRITE)) {
|
||||
+ md = NULL;
|
||||
+ retval = -EROFS;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -364,7 +373,7 @@ out:
|
||||
out:
|
||||
spin_unlock(&_minor_lock);
|
||||
|
||||
- return md ? 0 : -ENXIO;
|
||||
+ return retval;
|
||||
}
|
||||
|
||||
static int dm_blk_close(struct gendisk *disk, fmode_t mode)
|
||||
@@ -2165,6 +2174,11 @@ static struct dm_table *__bind(struct ma
|
||||
old_map = md->map;
|
||||
md->map = t;
|
||||
dm_table_set_restrictions(t, q, limits);
|
||||
+ if (!(dm_table_get_mode(t) & FMODE_WRITE)) {
|
||||
+ set_disk_ro(md->disk, 1);
|
||||
+ } else {
|
||||
+ set_disk_ro(md->disk, 0);
|
||||
+ }
|
||||
write_unlock_irqrestore(&md->map_lock, flags);
|
||||
|
||||
return old_map;
|
@ -1,63 +0,0 @@
|
||||
From: Ludwig Nussel <lnussel@novell.com>
|
||||
Subject: make nf_conntrack_slp actually work
|
||||
References: bnc#470963
|
||||
Patch-mainline: not yet, depends on patches.suse/netfilter-ip_conntrack_slp.patch
|
||||
|
||||
Acked-by: Jeff Mahoney <jeffm@suse.com>
|
||||
---
|
||||
|
||||
net/netfilter/nf_conntrack_slp.c | 18 +++++++++++-------
|
||||
1 file changed, 11 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/net/netfilter/nf_conntrack_slp.c
|
||||
+++ b/net/netfilter/nf_conntrack_slp.c
|
||||
@@ -47,15 +47,15 @@ static int help(struct sk_buff *skb, uns
|
||||
struct nf_conn *ct, enum ip_conntrack_info ctinfo)
|
||||
{
|
||||
struct nf_conntrack_expect *exp;
|
||||
- struct iphdr *iph = ip_hdr(skb);
|
||||
struct rtable *rt = skb_rtable(skb);
|
||||
struct in_device *in_dev;
|
||||
__be32 mask = 0;
|
||||
+ __be32 src = 0;
|
||||
|
||||
/* we're only interested in locally generated packets */
|
||||
if (skb->sk == NULL)
|
||||
goto out;
|
||||
- if (rt == NULL || !(rt->rt_flags & RTCF_BROADCAST))
|
||||
+ if (rt == NULL || !(rt->rt_flags & (RTCF_MULTICAST|RTCF_BROADCAST)))
|
||||
goto out;
|
||||
if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL)
|
||||
goto out;
|
||||
@@ -64,15 +64,18 @@ static int help(struct sk_buff *skb, uns
|
||||
in_dev = __in_dev_get_rcu(rt->dst.dev);
|
||||
if (in_dev != NULL) {
|
||||
for_primary_ifa(in_dev) {
|
||||
- if (ifa->ifa_broadcast == iph->daddr) {
|
||||
- mask = ifa->ifa_mask;
|
||||
- break;
|
||||
- }
|
||||
+ /* this is a hack as slp uses multicast we can't match
|
||||
+ * the destination address to some broadcast address. So
|
||||
+ * just take the first one. Better would be to install
|
||||
+ * expectations for all addresses */
|
||||
+ mask = ifa->ifa_mask;
|
||||
+ src = ifa->ifa_broadcast;
|
||||
+ break;
|
||||
} endfor_ifa(in_dev);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
- if (mask == 0)
|
||||
+ if (mask == 0 || src == 0)
|
||||
goto out;
|
||||
|
||||
exp = nf_ct_expect_alloc(ct);
|
||||
@@ -80,6 +83,7 @@ static int help(struct sk_buff *skb, uns
|
||||
goto out;
|
||||
|
||||
exp->tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
|
||||
+ exp->tuple.src.u3.ip = src;
|
||||
exp->tuple.src.u.udp.port = htons(SLP_PORT);
|
||||
|
||||
exp->mask.src.u3.ip = mask;
|
@ -1,43 +0,0 @@
|
||||
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;
|
@ -1,54 +0,0 @@
|
||||
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;
|
@ -1,30 +0,0 @@
|
||||
From: Dean Roe <roe@sgi.com>
|
||||
Subject: Prevent NULL pointer deref in grab_swap_token
|
||||
References: 159260
|
||||
Patch-mainline: not yet
|
||||
|
||||
grab_swap_token() assumes that the current process has an mm struct,
|
||||
which is not true for kernel threads invoking get_user_pages(). Since
|
||||
this should be extremely rare, just return from grab_swap_token()
|
||||
without doing anything.
|
||||
|
||||
Signed-off-by: Dean Roe <roe@sgi.com>
|
||||
Acked-by: mason@suse.de
|
||||
Acked-by: okir@suse.de
|
||||
|
||||
|
||||
mm/thrash.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
--- a/mm/thrash.c
|
||||
+++ b/mm/thrash.c
|
||||
@@ -31,6 +31,9 @@ void grab_swap_token(struct mm_struct *m
|
||||
int current_interval;
|
||||
|
||||
global_faults++;
|
||||
+ if (mm == NULL)
|
||||
+ return;
|
||||
+
|
||||
|
||||
current_interval = global_faults - mm->faultstamp;
|
||||
|
@ -1,30 +0,0 @@
|
||||
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);
|
@ -1,102 +0,0 @@
|
||||
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,44 +0,0 @@
|
||||
Date: Tue, 6 Jan 2009 10:27:41 -0600
|
||||
From: Dimitri Sivanich <sivanich@sgi.com>
|
||||
To: linux-ia64@vger.kernel.org, Tony Luck <tony.luck@intel.com>,
|
||||
Greg KH <greg@kroah.com>
|
||||
Cc: linux-kernel@vger.kernel.org,
|
||||
Peter Zijlstra <peterz@infradead.org>,
|
||||
Gregory Haskins <ghaskins@novell.com>, Nick Piggin <npiggin@suse.de>,
|
||||
Tony Luck <tony.luck@gmail.com>, Robin Holt <holt@sgi.com>
|
||||
Subject: configure HAVE_UNSTABLE_SCHED_CLOCK for SGI_SN systems
|
||||
Patch-mainline: not yet
|
||||
|
||||
Turn on CONFIG_HAVE_UNSTABLE_SCHED_CLOCK for SGI_SN.
|
||||
|
||||
SGI Altix has unsynchronized itc clocks. This results in rq->clock
|
||||
occasionally being set to a time in the past by a remote cpu.
|
||||
|
||||
Note that it is possible that this problem may exist for other ia64
|
||||
machines as well, based on the following comment for sched_clock() in
|
||||
arch/ia64/kernel/head.S:
|
||||
|
||||
* Return a CPU-local timestamp in nano-seconds. This timestamp is
|
||||
* NOT synchronized across CPUs its return value must never be
|
||||
* compared against the values returned on another CPU. The usage in
|
||||
* kernel/sched.c ensures that.
|
||||
|
||||
|
||||
Signed-off-by: Dimitri Sivanich <sivanich@sgi.com>
|
||||
Signed-off-by: Gregory Haskins <ghaskins@novell.com>
|
||||
|
||||
---
|
||||
|
||||
arch/ia64/Kconfig | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/arch/ia64/Kconfig
|
||||
+++ b/arch/ia64/Kconfig
|
||||
@@ -548,6 +548,7 @@ config IA64_MC_ERR_INJECT
|
||||
|
||||
config SGI_SN
|
||||
def_bool y if (IA64_SGI_SN2 || IA64_GENERIC)
|
||||
+ select HAVE_UNSTABLE_SCHED_CLOCK
|
||||
|
||||
config IA64_ESI
|
||||
bool "ESI (Extensible SAL Interface) support"
|
@ -1,53 +0,0 @@
|
||||
From: Jan Blunck <jblunck@suse.de>
|
||||
Subject: ia64-kvm: fix sparse warnings
|
||||
Patch-mainline: not yet
|
||||
|
||||
This patch fixes some sparse warning about dubious one-bit signed bitfield.
|
||||
|
||||
Signed-off-by: Jan Blunck <jblunck@suse.de>
|
||||
---
|
||||
arch/ia64/kvm/vti.h | 26 +++++++++++++-------------
|
||||
1 file changed, 13 insertions(+), 13 deletions(-)
|
||||
|
||||
--- a/arch/ia64/kvm/vti.h
|
||||
+++ b/arch/ia64/kvm/vti.h
|
||||
@@ -83,13 +83,13 @@
|
||||
union vac {
|
||||
unsigned long value;
|
||||
struct {
|
||||
- int a_int:1;
|
||||
- int a_from_int_cr:1;
|
||||
- int a_to_int_cr:1;
|
||||
- int a_from_psr:1;
|
||||
- int a_from_cpuid:1;
|
||||
- int a_cover:1;
|
||||
- int a_bsw:1;
|
||||
+ unsigned int a_int:1;
|
||||
+ unsigned int a_from_int_cr:1;
|
||||
+ unsigned int a_to_int_cr:1;
|
||||
+ unsigned int a_from_psr:1;
|
||||
+ unsigned int a_from_cpuid:1;
|
||||
+ unsigned int a_cover:1;
|
||||
+ unsigned int a_bsw:1;
|
||||
long reserved:57;
|
||||
};
|
||||
};
|
||||
@@ -97,12 +97,12 @@ union vac {
|
||||
union vdc {
|
||||
unsigned long value;
|
||||
struct {
|
||||
- int d_vmsw:1;
|
||||
- int d_extint:1;
|
||||
- int d_ibr_dbr:1;
|
||||
- int d_pmc:1;
|
||||
- int d_to_pmd:1;
|
||||
- int d_itm:1;
|
||||
+ unsigned int d_vmsw:1;
|
||||
+ unsigned int d_extint:1;
|
||||
+ unsigned int d_ibr_dbr:1;
|
||||
+ unsigned int d_pmc:1;
|
||||
+ unsigned int d_to_pmd:1;
|
||||
+ unsigned int d_itm:1;
|
||||
long reserved:58;
|
||||
};
|
||||
};
|
@ -1,30 +0,0 @@
|
||||
From: Jiri Kosina <jkosina@suse.cz>
|
||||
Subject: Input: Add Acer Aspire 5710 to nomux blacklist
|
||||
References: bnc#404881
|
||||
Patch-mainline: submitted
|
||||
|
||||
Acer Aspire needs to be added to nomux blacklist, otherwise the touchpad
|
||||
misbehaves.
|
||||
|
||||
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
|
||||
|
||||
---
|
||||
drivers/input/serio/i8042-x86ia64io.h | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
--- a/drivers/input/serio/i8042-x86ia64io.h
|
||||
+++ b/drivers/input/serio/i8042-x86ia64io.h
|
||||
@@ -371,6 +371,13 @@ static const struct dmi_system_id __init
|
||||
},
|
||||
},
|
||||
{
|
||||
+ /* Acer Aspire 5710 */
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
|
||||
+ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5710"),
|
||||
+ },
|
||||
+ },
|
||||
+ {
|
||||
/* Gericom Bellagio */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Gericom"),
|
@ -1,60 +0,0 @@
|
||||
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,21 +0,0 @@
|
||||
From: agraf@suse.de
|
||||
Subject: Ignore apic polarity
|
||||
Patch-mainline: unknown
|
||||
References: bnc#556564
|
||||
|
||||
---
|
||||
virt/kvm/ioapic.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/virt/kvm/ioapic.c
|
||||
+++ b/virt/kvm/ioapic.c
|
||||
@@ -202,7 +202,8 @@ int kvm_ioapic_set_irq(struct kvm_ioapic
|
||||
old_irr = ioapic->irr;
|
||||
if (irq >= 0 && irq < IOAPIC_NUM_PINS) {
|
||||
entry = ioapic->redirtbl[irq];
|
||||
- level ^= entry.fields.polarity;
|
||||
+// polarity is always active high in qemu
|
||||
+// level ^= entry.fields.polarity;
|
||||
if (!level)
|
||||
ioapic->irr &= ~mask;
|
||||
else {
|
@ -1,73 +0,0 @@
|
||||
From: agraf@suse.de
|
||||
Subject: Implement some missing intercepts so osx doesn't blow up
|
||||
Patch-mainline: unknown
|
||||
References: bnc#556564
|
||||
|
||||
---
|
||||
arch/x86/kvm/svm.c | 20 ++++++++++++++++++--
|
||||
arch/x86/kvm/x86.c | 4 +++-
|
||||
2 files changed, 21 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/arch/x86/kvm/svm.c
|
||||
+++ b/arch/x86/kvm/svm.c
|
||||
@@ -2303,6 +2303,22 @@ static int skinit_interception(struct vc
|
||||
return 1;
|
||||
}
|
||||
|
||||
+static int monitor_interception(struct vcpu_svm *svm)
|
||||
+{
|
||||
+ svm->next_rip = kvm_rip_read(&svm->vcpu) + 3;
|
||||
+ skip_emulated_instruction(&svm->vcpu);
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+static int mwait_interception(struct vcpu_svm *svm)
|
||||
+{
|
||||
+ svm->next_rip = kvm_rip_read(&svm->vcpu) + 3;
|
||||
+ skip_emulated_instruction(&svm->vcpu);
|
||||
+
|
||||
+ return kvm_emulate_halt(&svm->vcpu);
|
||||
+}
|
||||
+
|
||||
static int invalid_op_interception(struct vcpu_svm *svm)
|
||||
{
|
||||
kvm_queue_exception(&svm->vcpu, UD_VECTOR);
|
||||
@@ -2722,8 +2738,8 @@ static int (*svm_exit_handlers[])(struct
|
||||
[SVM_EXIT_CLGI] = clgi_interception,
|
||||
[SVM_EXIT_SKINIT] = skinit_interception,
|
||||
[SVM_EXIT_WBINVD] = emulate_on_interception,
|
||||
- [SVM_EXIT_MONITOR] = invalid_op_interception,
|
||||
- [SVM_EXIT_MWAIT] = invalid_op_interception,
|
||||
+ [SVM_EXIT_MONITOR] = monitor_interception,
|
||||
+ [SVM_EXIT_MWAIT] = mwait_interception,
|
||||
[SVM_EXIT_XSETBV] = xsetbv_interception,
|
||||
[SVM_EXIT_NPF] = pf_interception,
|
||||
};
|
||||
--- a/arch/x86/kvm/x86.c
|
||||
+++ b/arch/x86/kvm/x86.c
|
||||
@@ -1254,6 +1254,7 @@ int kvm_set_msr_common(struct kvm_vcpu *
|
||||
case MSR_VM_HSAVE_PA:
|
||||
case MSR_AMD64_PATCH_LOADER:
|
||||
break;
|
||||
+ case 0xe2:
|
||||
case 0x200 ... 0x2ff:
|
||||
return set_msr_mtrr(vcpu, msr, data);
|
||||
case MSR_IA32_APICBASE:
|
||||
@@ -1512,6 +1513,7 @@ int kvm_get_msr_common(struct kvm_vcpu *
|
||||
case MSR_K8_INT_PENDING_MSG:
|
||||
case MSR_AMD64_NB_CFG:
|
||||
case MSR_FAM10H_MMIO_CONF_BASE:
|
||||
+ case 0xe2:
|
||||
data = 0;
|
||||
break;
|
||||
case MSR_MTRRcap:
|
||||
@@ -1985,7 +1987,7 @@ static void do_cpuid_ent(struct kvm_cpui
|
||||
0 /* Reserved */ | f_lm | F(3DNOWEXT) | F(3DNOW);
|
||||
/* cpuid 1.ecx */
|
||||
const u32 kvm_supported_word4_x86_features =
|
||||
- F(XMM3) | F(PCLMULQDQ) | 0 /* DTES64, MONITOR */ |
|
||||
+ F(XMM3) | F(PCLMULQDQ) | 0 /* DTES64 */ | F(MWAIT) |
|
||||
0 /* DS-CPL, VMX, SMX, EST */ |
|
||||
0 /* TM2 */ | F(SSSE3) | 0 /* CNXT-ID */ | 0 /* Reserved */ |
|
||||
0 /* Reserved */ | F(CX16) | 0 /* xTPR Update, PDCM */ |
|
@ -1,37 +0,0 @@
|
||||
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);
|
||||
|
||||
|
||||
|
@ -1,69 +0,0 @@
|
||||
From: Jeff Mahoney <jeffm@suse.com>
|
||||
Subject: [PATCH] mISDN: Add support for group membership check
|
||||
References: bnc#564423
|
||||
Patch-mainline: Unsubmitted, needs upstream consensus
|
||||
|
||||
This patch adds a module parameter to allow a group access to the
|
||||
mISDN devices. Otherwise, unpriviledged users on systems with ISDN hardware
|
||||
have the ability to dial out, potentially causing expensive bills.
|
||||
|
||||
Based on a different implementation by Patrick Koppen <isdn4linux@koppen.de>
|
||||
|
||||
Acked-by: Jeff Mahoney <jeffm@suse.com>
|
||||
---
|
||||
|
||||
drivers/isdn/mISDN/core.c | 3 +++
|
||||
drivers/isdn/mISDN/core.h | 1 +
|
||||
drivers/isdn/mISDN/socket.c | 8 ++++++++
|
||||
3 files changed, 12 insertions(+)
|
||||
|
||||
--- a/drivers/isdn/mISDN/core.c
|
||||
+++ b/drivers/isdn/mISDN/core.c
|
||||
@@ -21,10 +21,13 @@
|
||||
#include "core.h"
|
||||
|
||||
static u_int debug;
|
||||
+u_int misdn_permitted_gid;
|
||||
|
||||
MODULE_AUTHOR("Karsten Keil");
|
||||
MODULE_LICENSE("GPL");
|
||||
module_param(debug, uint, S_IRUGO | S_IWUSR);
|
||||
+module_param_named(gid, misdn_permitted_gid, uint, 0);
|
||||
+MODULE_PARM_DESC(gid, "Unix group for accessing misdn socket (default 0)");
|
||||
|
||||
static u64 device_ids;
|
||||
#define MAX_DEVICE_ID 63
|
||||
--- a/drivers/isdn/mISDN/core.h
|
||||
+++ b/drivers/isdn/mISDN/core.h
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
extern struct mISDNdevice *get_mdevice(u_int);
|
||||
extern int get_mdevice_count(void);
|
||||
+extern u_int misdn_permitted_gid;
|
||||
|
||||
/* stack status flag */
|
||||
#define mISDN_STACK_ACTION_MASK 0x0000ffff
|
||||
--- a/drivers/isdn/mISDN/socket.c
|
||||
+++ b/drivers/isdn/mISDN/socket.c
|
||||
@@ -608,6 +608,10 @@ data_sock_create(struct net *net, struct
|
||||
{
|
||||
struct sock *sk;
|
||||
|
||||
+ if(!capable(CAP_SYS_ADMIN) && (misdn_permitted_gid != current_gid())
|
||||
+ && (!in_group_p(misdn_permitted_gid)))
|
||||
+ return -EPERM;
|
||||
+
|
||||
if (sock->type != SOCK_DGRAM)
|
||||
return -ESOCKTNOSUPPORT;
|
||||
|
||||
@@ -690,6 +694,10 @@ base_sock_ioctl(struct socket *sock, uns
|
||||
case IMSETDEVNAME:
|
||||
{
|
||||
struct mISDN_devrename dn;
|
||||
+ if(!capable(CAP_SYS_ADMIN)
|
||||
+ && (misdn_permitted_gid != current_gid())
|
||||
+ && (!in_group_p(misdn_permitted_gid)))
|
||||
+ return -EPERM;
|
||||
if (copy_from_user(&dn, (void __user *)arg,
|
||||
sizeof(dn))) {
|
||||
err = -EFAULT;
|
@ -1,104 +0,0 @@
|
||||
From: Jeff Mahoney <jeffm@suse.com>
|
||||
Subject: netfilter: Implement RFC 1123 for FTP conntrack
|
||||
References: bnc#466279
|
||||
Patch-mainline: Submitted via http://bugzilla.netfilter.org/show_bug.cgi?id=574 23 Jan 2011
|
||||
|
||||
The FTP conntrack code currently only accepts the following format for
|
||||
the 227 response for PASV:
|
||||
227 Entering Passive Mode (148,100,81,40,31,161).
|
||||
|
||||
It doesn't accept the following format from an obscure server:
|
||||
227 Data transfer will passively listen to 67,218,99,134,50,144
|
||||
|
||||
From RFC 1123:
|
||||
The format of the 227 reply to a PASV command is not
|
||||
well standardized. In particular, an FTP client cannot
|
||||
assume that the parentheses shown on page 40 of RFC-959
|
||||
will be present (and in fact, Figure 3 on page 43 omits
|
||||
them). Therefore, a User-FTP program that interprets
|
||||
the PASV reply must scan the reply for the first digit
|
||||
of the host and port numbers.
|
||||
|
||||
This patch adds support for the RFC 1123 clarification by:
|
||||
- Allowing a search filter to specify NUL as the terminator so that
|
||||
try_number will return successfully if the array of numbers has been
|
||||
filled when an unexpected character is encountered.
|
||||
- Using space as the separator for the 227 reply and then scanning for
|
||||
the first digit of the number sequence. The number sequence is parsed
|
||||
out using the existing try_rfc959 but with a NUL terminator.
|
||||
|
||||
Tracked in: https://bugzilla.novell.com/show_bug.cgi?id=466279
|
||||
|
||||
Reported-by: Mark Post <mpost@novell.com>
|
||||
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
|
||||
---
|
||||
net/netfilter/nf_conntrack_ftp.c | 36 +++++++++++++++++++++++++++++++-----
|
||||
1 file changed, 31 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/net/netfilter/nf_conntrack_ftp.c
|
||||
+++ b/net/netfilter/nf_conntrack_ftp.c
|
||||
@@ -53,6 +53,7 @@ unsigned int (*nf_nat_ftp_hook)(struct s
|
||||
EXPORT_SYMBOL_GPL(nf_nat_ftp_hook);
|
||||
|
||||
static int try_rfc959(const char *, size_t, struct nf_conntrack_man *, char);
|
||||
+static int try_rfc1123(const char *, size_t, struct nf_conntrack_man *, char);
|
||||
static int try_eprt(const char *, size_t, struct nf_conntrack_man *, char);
|
||||
static int try_epsv_response(const char *, size_t, struct nf_conntrack_man *,
|
||||
char);
|
||||
@@ -87,10 +88,10 @@ static struct ftp_search {
|
||||
{
|
||||
.pattern = "227 ",
|
||||
.plen = sizeof("227 ") - 1,
|
||||
- .skip = '(',
|
||||
- .term = ')',
|
||||
+ .skip = ' ',
|
||||
+ .term = '\0',
|
||||
.ftptype = NF_CT_FTP_PASV,
|
||||
- .getnum = try_rfc959,
|
||||
+ .getnum = try_rfc1123,
|
||||
},
|
||||
{
|
||||
.pattern = "229 ",
|
||||
@@ -129,8 +130,9 @@ static int try_number(const char *data,
|
||||
i++;
|
||||
else {
|
||||
/* Unexpected character; true if it's the
|
||||
- terminator and we're finished. */
|
||||
- if (*data == term && i == array_size - 1)
|
||||
+ terminator (or we don't care about one)
|
||||
+ and we're finished. */
|
||||
+ if ((*data == term || !term) && i == array_size - 1)
|
||||
return len;
|
||||
|
||||
pr_debug("Char %u (got %u nums) `%u' unexpected\n",
|
||||
@@ -160,6 +162,30 @@ static int try_rfc959(const char *data,
|
||||
return length;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * From RFC 1123:
|
||||
+ * The format of the 227 reply to a PASV command is not
|
||||
+ * well standardized. In particular, an FTP client cannot
|
||||
+ * assume that the parentheses shown on page 40 of RFC-959
|
||||
+ * will be present (and in fact, Figure 3 on page 43 omits
|
||||
+ * them). Therefore, a User-FTP program that interprets
|
||||
+ * the PASV reply must scan the reply for the first digit
|
||||
+ * of the host and port numbers.
|
||||
+ */
|
||||
+static int try_rfc1123(const char *data, size_t dlen,
|
||||
+ struct nf_conntrack_man *cmd, char term)
|
||||
+{
|
||||
+ int i;
|
||||
+ for (i = 0; i < dlen; i++)
|
||||
+ if (isdigit(data[i]))
|
||||
+ break;
|
||||
+
|
||||
+ if (i == dlen)
|
||||
+ return 0;
|
||||
+
|
||||
+ return try_rfc959(data + i, dlen - i, cmd, 0);
|
||||
+}
|
||||
+
|
||||
/* Grab port: number up to delimiter */
|
||||
static int get_port(const char *data, int start, size_t dlen, char delim,
|
||||
__be16 *port)
|
@ -1,46 +0,0 @@
|
||||
From: Andreas Gruenbacher <agruen@suse.de>
|
||||
Subject: "No acl" entry put in client-side acl cache instead of "not cached"
|
||||
References: 171059
|
||||
|
||||
When the acl of a file is not cached and only the default acl of that
|
||||
file is requested, a NULL "no acl" entry is put in the client-side acl
|
||||
cache of nfs instead of ERR_PTR(-EAGAIN) "not cached".
|
||||
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
|
||||
Index: linux-2.6.16/fs/nfs/nfs3acl.c
|
||||
===================================================================
|
||||
--- linux-2.6.16.orig/fs/nfs/nfs3acl.c
|
||||
+++ linux-2.6.16/fs/nfs/nfs3acl.c
|
||||
@@ -172,8 +172,10 @@ static void nfs3_cache_acls(struct inode
|
||||
inode->i_ino, acl, dfacl);
|
||||
spin_lock(&inode->i_lock);
|
||||
__nfs3_forget_cached_acls(NFS_I(inode));
|
||||
- nfsi->acl_access = posix_acl_dup(acl);
|
||||
- nfsi->acl_default = posix_acl_dup(dfacl);
|
||||
+ if (!IS_ERR(acl))
|
||||
+ nfsi->acl_access = posix_acl_dup(acl);
|
||||
+ if (!IS_ERR(dfacl))
|
||||
+ nfsi->acl_default = posix_acl_dup(dfacl);
|
||||
spin_unlock(&inode->i_lock);
|
||||
}
|
||||
|
||||
@@ -250,7 +252,9 @@ struct posix_acl *nfs3_proc_getacl(struc
|
||||
res.acl_access = NULL;
|
||||
}
|
||||
}
|
||||
- nfs3_cache_acls(inode, res.acl_access, res.acl_default);
|
||||
+ nfs3_cache_acls(inode,
|
||||
+ (res.mask & NFS_ACL) ? res.acl_access : ERR_PTR(-EINVAL),
|
||||
+ (res.mask & NFS_DFACL) ? res.acl_default : ERR_PTR(-EINVAL));
|
||||
|
||||
switch(type) {
|
||||
case ACL_TYPE_ACCESS:
|
||||
@@ -321,6 +325,7 @@ static int nfs3_proc_setacls(struct inod
|
||||
switch (status) {
|
||||
case 0:
|
||||
status = nfs_refresh_inode(inode, &fattr);
|
||||
+ nfs3_cache_acls(inode, acl, dfacl);
|
||||
break;
|
||||
case -EPFNOSUPPORT:
|
||||
case -EPROTONOSUPPORT:
|
@ -1,80 +0,0 @@
|
||||
From: NeilBrown <neilb@suse.de>
|
||||
Subject: Make selection of 'readdir-plus' adapt to usage patterns.
|
||||
Patch-mainline: not yet
|
||||
References: bnc#678123
|
||||
|
||||
While the use of READDIRPLUS is significantly more efficient than
|
||||
READDIR followed by many GETATTR calls, it is still less efficient
|
||||
than just READDIR if the attributes are not required.
|
||||
|
||||
We can get a hint as to whether the application requires attr information
|
||||
by looking at whether any ->getattr calls are made between
|
||||
->readdir calls.
|
||||
If there are any, then getting the attributes seems to be worth while.
|
||||
|
||||
This patch tracks whether there have been recent getattr calls on
|
||||
children of a directory and uses that information to selectively
|
||||
disable READDIRPLUS on that directory.
|
||||
|
||||
The first 'readdir' call is always served using READDIRPLUS.
|
||||
Subsequent calls only use READDIRPLUS if there was a getattr on a child
|
||||
in the mean time.
|
||||
|
||||
The locking of ->d_parent access needs to be reviewed.
|
||||
As the bit is simply a hint, it isn't critical that it is set
|
||||
on the "correct" parent if a rename is happening, but it is
|
||||
critical that the 'set' doesn't set a bit in something that
|
||||
isn't even an inode any more.
|
||||
|
||||
Acked-by: NeilBrown <neilb@suse.de>
|
||||
Signed-off-by: Neil Brown <neilb@suse.de>
|
||||
|
||||
---
|
||||
fs/nfs/dir.c | 3 +++
|
||||
fs/nfs/inode.c | 9 +++++++++
|
||||
include/linux/nfs_fs.h | 4 ++++
|
||||
3 files changed, 16 insertions(+)
|
||||
|
||||
--- linux-2.6.37-openSUSE-11.4.orig/fs/nfs/dir.c
|
||||
+++ linux-2.6.37-openSUSE-11.4/fs/nfs/dir.c
|
||||
@@ -802,6 +802,9 @@ static int nfs_readdir(struct file *filp
|
||||
desc->dir_cookie = &nfs_file_open_context(filp)->dir_cookie;
|
||||
desc->decode = NFS_PROTO(inode)->decode_dirent;
|
||||
desc->plus = NFS_USE_READDIRPLUS(inode);
|
||||
+ if (filp->f_pos > 0 && !test_bit(NFS_INO_SEEN_GETATTR, &NFS_I(inode)->flags))
|
||||
+ desc->plus = 0;
|
||||
+ clear_bit(NFS_INO_SEEN_GETATTR, &NFS_I(inode)->flags);
|
||||
|
||||
nfs_block_sillyrename(dentry);
|
||||
res = nfs_revalidate_mapping(inode, filp->f_mapping);
|
||||
--- linux-2.6.37-openSUSE-11.4.orig/fs/nfs/inode.c
|
||||
+++ linux-2.6.37-openSUSE-11.4/fs/nfs/inode.c
|
||||
@@ -500,6 +500,15 @@ int nfs_getattr(struct vfsmount *mnt, st
|
||||
struct inode *inode = dentry->d_inode;
|
||||
int need_atime = NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATIME;
|
||||
int err;
|
||||
+ struct dentry *p;
|
||||
+ struct inode *pi;
|
||||
+
|
||||
+ rcu_read_lock();
|
||||
+ p = dentry->d_parent;
|
||||
+ pi = rcu_dereference(p)->d_inode;
|
||||
+ if (pi && !test_bit(NFS_INO_SEEN_GETATTR, &NFS_I(pi)->flags))
|
||||
+ set_bit(NFS_INO_SEEN_GETATTR, &NFS_I(pi)->flags);
|
||||
+ rcu_read_unlock();
|
||||
|
||||
/* Flush out writes to the server in order to update c/mtime. */
|
||||
if (S_ISREG(inode->i_mode)) {
|
||||
--- linux-2.6.37-openSUSE-11.4.orig/include/linux/nfs_fs.h
|
||||
+++ linux-2.6.37-openSUSE-11.4/include/linux/nfs_fs.h
|
||||
@@ -220,6 +220,10 @@ struct nfs_inode {
|
||||
#define NFS_INO_FSCACHE (5) /* inode can be cached by FS-Cache */
|
||||
#define NFS_INO_FSCACHE_LOCK (6) /* FS-Cache cookie management lock */
|
||||
#define NFS_INO_COMMIT (7) /* inode is committing unstable writes */
|
||||
+#define NFS_INO_SEEN_GETATTR (8) /* flag to track if app is calling
|
||||
+ * getattr in a directory during
|
||||
+ * readdir
|
||||
+ */
|
||||
|
||||
static inline struct nfs_inode *NFS_I(const struct inode *inode)
|
||||
{
|
@ -1,31 +0,0 @@
|
||||
From: Michal Hocko <mhocko@novell.com>
|
||||
Subject: Don't fail allocations for the slot table when mounting an NFS filesystem
|
||||
Patch-mainline: no
|
||||
References: bnc#519820
|
||||
|
||||
When the *_slot_table_entries exceeds 111, the slot_table_size
|
||||
exceeds 32K and an order-4 allocation is forced. This does not
|
||||
retry nearly as much as order-3 so failure is more likely.
|
||||
But mount and autofs in particular doesn't cope well with failure.
|
||||
So force __GFP_REPEAT - the assumption is that people will only
|
||||
set the slot_table_size sysctl large on a machine with plenty
|
||||
of memory, so this should not block indefinitely.
|
||||
|
||||
Acked-by: Neil Brown <neilb@suse.de>
|
||||
Signed-off-by: Neil Brown <neilb@suse.de>
|
||||
|
||||
---
|
||||
net/sunrpc/xprtsock.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/net/sunrpc/xprt.c
|
||||
+++ b/net/sunrpc/xprt.c
|
||||
@@ -2266,7 +2266,7 @@ static struct rpc_xprt *xs_setup_xprt(st
|
||||
kref_init(&xprt->kref);
|
||||
|
||||
xprt->max_reqs = max_req;
|
||||
- xprt->slot = kcalloc(max_req, sizeof(struct rpc_rqst), GFP_KERNEL);
|
||||
+ xprt->slot = kcalloc(max_req, sizeof(struct rpc_rqst), GFP_KERNEL | __GFP_REPEAT);
|
||||
if (xprt->slot == NULL)
|
||||
goto out_free;
|
||||
|
@ -1,127 +0,0 @@
|
||||
Patch-mainline: submitted 04aug2009
|
||||
References: bnc#498708
|
||||
From: NeilBrown <neilb@suse.de>
|
||||
Date: Tue, 4 Aug 2009 15:06:38 +1000
|
||||
Subject: [PATCH 08/12] sunrpc/cache: retry cache lookups that return -ETIMEDOUT
|
||||
|
||||
If cache_check returns -ETIMEDOUT, then the cache item is not
|
||||
up-to-date, but there is no pending upcall.
|
||||
This could mean the data is not available, or it could mean that the
|
||||
good data has been stored in a new cache item.
|
||||
|
||||
So re-do the lookup and if that returns a new item, proceed using that
|
||||
item.
|
||||
|
||||
Signed-off-by: NeilBrown <neilb@suse.de>
|
||||
|
||||
---
|
||||
fs/nfsd/export.c | 18 ++++++++++++++++++
|
||||
net/sunrpc/svcauth_unix.c | 23 ++++++++++++++++++++---
|
||||
2 files changed, 38 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/fs/nfsd/export.c
|
||||
+++ b/fs/nfsd/export.c
|
||||
@@ -794,9 +794,18 @@ exp_find_key(svc_client *clp, int fsid_t
|
||||
memcpy(key.ek_fsid, fsidv, key_len(fsid_type));
|
||||
|
||||
ek = svc_expkey_lookup(&key);
|
||||
+ again:
|
||||
if (ek == NULL)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
err = cache_check(&svc_expkey_cache, &ek->h, reqp);
|
||||
+ if (err == -ETIMEDOUT) {
|
||||
+ struct svc_expkey *prev_ek = ek;
|
||||
+ ek = svc_expkey_lookup(&key);
|
||||
+ if (ek != prev_ek)
|
||||
+ goto again;
|
||||
+ if (ek)
|
||||
+ cache_put(&ek->h, &svc_expkey_cache);
|
||||
+ }
|
||||
if (err)
|
||||
return ERR_PTR(err);
|
||||
return ek;
|
||||
@@ -866,9 +875,18 @@ static svc_export *exp_get_by_name(svc_c
|
||||
key.ex_path = *path;
|
||||
|
||||
exp = svc_export_lookup(&key);
|
||||
+ retry:
|
||||
if (exp == NULL)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
err = cache_check(&svc_export_cache, &exp->h, reqp);
|
||||
+ if (err == -ETIMEDOUT) {
|
||||
+ struct svc_export *prev_exp = exp;
|
||||
+ exp = svc_export_lookup(&key);
|
||||
+ if (exp != prev_exp)
|
||||
+ goto retry;
|
||||
+ if (exp)
|
||||
+ cache_put(&exp->h, &svc_export_cache);
|
||||
+ }
|
||||
if (err)
|
||||
return ERR_PTR(err);
|
||||
return exp;
|
||||
--- a/net/sunrpc/svcauth_unix.c
|
||||
+++ b/net/sunrpc/svcauth_unix.c
|
||||
@@ -663,13 +663,14 @@ static struct unix_gid *unix_gid_lookup(
|
||||
|
||||
static struct group_info *unix_gid_find(uid_t uid, struct svc_rqst *rqstp)
|
||||
{
|
||||
- struct unix_gid *ug;
|
||||
+ struct unix_gid *ug, *prevug;
|
||||
struct group_info *gi;
|
||||
int ret;
|
||||
|
||||
ug = unix_gid_lookup(uid);
|
||||
if (!ug)
|
||||
return ERR_PTR(-EAGAIN);
|
||||
+retry:
|
||||
ret = cache_check(&unix_gid_cache, &ug->h, &rqstp->rq_chandle);
|
||||
switch (ret) {
|
||||
case -ENOENT:
|
||||
@@ -678,6 +679,13 @@ static struct group_info *unix_gid_find(
|
||||
gi = get_group_info(ug->gi);
|
||||
cache_put(&ug->h, &unix_gid_cache);
|
||||
return gi;
|
||||
+ case -ETIMEDOUT:
|
||||
+ prevug = ug;
|
||||
+ ug = unix_gid_lookup(uid);
|
||||
+ if (ug != prevug)
|
||||
+ goto retry;
|
||||
+ if (ug)
|
||||
+ cache_put(&ug->h, &unix_gid_cache);
|
||||
default:
|
||||
return ERR_PTR(-EAGAIN);
|
||||
}
|
||||
@@ -688,7 +696,7 @@ svcauth_unix_set_client(struct svc_rqst
|
||||
{
|
||||
struct sockaddr_in *sin;
|
||||
struct sockaddr_in6 *sin6, sin6_storage;
|
||||
- struct ip_map *ipm;
|
||||
+ struct ip_map *ipm, *prev_ipm;
|
||||
struct group_info *gi;
|
||||
struct svc_cred *cred = &rqstp->rq_cred;
|
||||
|
||||
@@ -714,14 +722,23 @@ svcauth_unix_set_client(struct svc_rqst
|
||||
ipm = ip_map_lookup(rqstp->rq_server->sv_program->pg_class,
|
||||
&sin6->sin6_addr);
|
||||
|
||||
+ retry:
|
||||
if (ipm == NULL)
|
||||
return SVC_DENIED;
|
||||
|
||||
switch (cache_check(&ip_map_cache, &ipm->h, &rqstp->rq_chandle)) {
|
||||
default:
|
||||
BUG();
|
||||
- case -EAGAIN:
|
||||
case -ETIMEDOUT:
|
||||
+ prev_ipm = ipm;
|
||||
+ ipm = ip_map_lookup(rqstp->rq_server->sv_program->pg_class,
|
||||
+ &sin6->sin6_addr);
|
||||
+ if (ipm != prev_ipm)
|
||||
+ goto retry;
|
||||
+ if (ipm)
|
||||
+ cache_put(&ipm->h, &ip_map_cache);
|
||||
+
|
||||
+ case -EAGAIN:
|
||||
return SVC_DROP;
|
||||
case -ENOENT:
|
||||
return SVC_DENIED;
|
@ -1,25 +0,0 @@
|
||||
From: Sankar P <psankar@novell.com>
|
||||
Subject: fs: novfs: Initialize super-block with standard macros
|
||||
Patch-mainline: no
|
||||
|
||||
Initialize the super block's maxbytes with MAX_LFS_FILESIZE macro.
|
||||
|
||||
Signed-off-by: Sankar P <psankar@novell.com>
|
||||
Signed-off-by: Samrat Kannikar <ksamrat@novell.com>
|
||||
Acked-by: Jan Kara <jack@suse.cz>
|
||||
|
||||
---
|
||||
fs/novfs/inode.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/fs/novfs/inode.c
|
||||
+++ b/fs/novfs/inode.c
|
||||
@@ -3825,7 +3825,7 @@ int novfs_fill_super(struct super_block
|
||||
|
||||
SB->s_blocksize = PAGE_CACHE_SIZE;
|
||||
SB->s_blocksize_bits = PAGE_CACHE_SHIFT;
|
||||
- SB->s_maxbytes = 0xFFFFFFFFFFFFFFFFULL; /* Max file size */
|
||||
+ SB->s_maxbytes = MAX_LFS_FILESIZE; /* Max file size */
|
||||
SB->s_op = &novfs_ops;
|
||||
SB->s_flags |= (MS_NODIRATIME | MS_NODEV | MS_POSIXACL);
|
||||
SB->s_magic = NOVFS_MAGIC;
|
@ -1,54 +0,0 @@
|
||||
From: Sankar P <psankar@novell.com>
|
||||
Subject: novfs: backing device info initialization
|
||||
References: bnc#623472
|
||||
Patch-mainline: no
|
||||
|
||||
The patch initializes and destroys the backing device info struct
|
||||
for the novfs properly. Fixes an OOPS as well.
|
||||
|
||||
Acked-by: Jan Kara <jack@novell.com>
|
||||
Acked-by: Sankar P <psankar@novell.com>
|
||||
Signed-off-by: Anders Johansson <ajohansson@novell.com>
|
||||
|
||||
---
|
||||
fs/novfs/inode.c | 15 +++++++++++++++
|
||||
1 file changed, 15 insertions(+)
|
||||
|
||||
--- a/fs/novfs/inode.c
|
||||
+++ b/fs/novfs/inode.c
|
||||
@@ -3977,6 +3977,17 @@ int __init init_novfs(void)
|
||||
inHAX = 0;
|
||||
inHAXTime = get_nanosecond_time();
|
||||
|
||||
+ retCode = bdi_init(&novfs_backing_dev_info);
|
||||
+
|
||||
+ if(!retCode)
|
||||
+ retCode = bdi_register(&novfs_backing_dev_info, NULL, "novfs-map");
|
||||
+ if (retCode) {
|
||||
+ bdi_destroy(&novfs_backing_dev_info);
|
||||
+ goto bdi_fail;
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+
|
||||
retCode = novfs_proc_init();
|
||||
|
||||
novfs_profile_init();
|
||||
@@ -3992,6 +4003,8 @@ int __init init_novfs(void)
|
||||
novfs_scope_exit();
|
||||
}
|
||||
}
|
||||
+
|
||||
+bdi_fail:
|
||||
return (retCode);
|
||||
}
|
||||
|
||||
@@ -4007,6 +4020,8 @@ void __exit exit_novfs(void)
|
||||
kfree(novfs_current_mnt);
|
||||
novfs_current_mnt = NULL;
|
||||
}
|
||||
+
|
||||
+ bdi_destroy(&novfs_backing_dev_info);
|
||||
}
|
||||
|
||||
int novfs_lock_inode_cache(struct inode *i)
|
@ -1,46 +0,0 @@
|
||||
From: Samrat Kannikar <ksamrat@novell.com>
|
||||
Subject: novfs: Remove dcache count restricting code
|
||||
References: bnc#576026
|
||||
Patch-mainline: no
|
||||
|
||||
Attached patch removes the code which restricts the
|
||||
number of dir_cache entries, that are maintained by novfs
|
||||
|
||||
Signed-off-by: Samrat Kannikar <ksamrat@novell.com>
|
||||
Acked-by: Jan Kara <jack@suse.cz>
|
||||
|
||||
---
|
||||
fs/novfs/inode.c | 15 ---------------
|
||||
1 file changed, 15 deletions(-)
|
||||
|
||||
--- a/fs/novfs/inode.c
|
||||
+++ b/fs/novfs/inode.c
|
||||
@@ -4345,8 +4345,6 @@ int novfs_add_inode_entry(struct inode *
|
||||
struct inode_data *id;
|
||||
struct novfs_dir_cache *new;
|
||||
int retVal = -ENOMEM;
|
||||
- struct novfs_dir_cache *todel;
|
||||
- struct list_head *todeltmp;
|
||||
|
||||
//SClark
|
||||
DbgPrint("i: %p", i);
|
||||
@@ -4382,19 +4380,6 @@ int novfs_add_inode_entry(struct inode *
|
||||
memcpy(new->name, name->name, name->len);
|
||||
new->name[new->nameLen] = '\0';
|
||||
list_add(&new->list, &id->DirCache);
|
||||
-
|
||||
- if (id->cntDC > 20) {
|
||||
- todeltmp = id->DirCache.prev;
|
||||
- todel = list_entry(todeltmp, struct novfs_dir_cache, list);
|
||||
-
|
||||
- list_del(&todel->list);
|
||||
-
|
||||
- kfree(todel);
|
||||
-
|
||||
- DCCount--;
|
||||
- id->cntDC--;
|
||||
- }
|
||||
-
|
||||
}
|
||||
}
|
||||
return (retVal);
|
@ -1,34 +0,0 @@
|
||||
From: Anders Johansson <ajohansson@novell.com>
|
||||
Subject: Oops in novfs:unlink_local
|
||||
References: bnc#569071
|
||||
Patch-mainline: no
|
||||
|
||||
Signed-off-by: Anders Johansson <ajohansson@novell.com>
|
||||
Acked-by: Sankar P <psankar@novell.com>
|
||||
---
|
||||
fs/novfs/daemon.c | 12 ++++++------
|
||||
1 file changed, 6 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/fs/novfs/daemon.c
|
||||
+++ b/fs/novfs/daemon.c
|
||||
@@ -2046,14 +2046,14 @@ static long local_unlink(const char *pat
|
||||
}
|
||||
dentry = lookup_one_len(name, nd.path.dentry, strlen(name));
|
||||
error = PTR_ERR(dentry);
|
||||
- DbgPrint("dentry %p", dentry);
|
||||
- if (!(dentry->d_inode->i_mode & S_IFLNK)) {
|
||||
- DbgPrint("%s not a link", name);
|
||||
- error=-ENOENT;
|
||||
- goto exit1;
|
||||
- }
|
||||
|
||||
if (!IS_ERR(dentry)) {
|
||||
+ DbgPrint("dentry %p", dentry);
|
||||
+ if (!(dentry->d_inode->i_mode & S_IFLNK)) {
|
||||
+ DbgPrint("%s not a link", name);
|
||||
+ error=-ENOENT;
|
||||
+ goto exit1;
|
||||
+ }
|
||||
/* Why not before? Because we want correct error value */
|
||||
if (nd.last.name[nd.last.len])
|
||||
goto slashes;
|
@ -1,34 +0,0 @@
|
||||
From: Sankar P <psankar@novell.com>
|
||||
Subject: novfs: Get proper UID when looking up inode
|
||||
Patch-mainline: no
|
||||
References: bnc#486997
|
||||
|
||||
novfs is incorrectly assigning the rights in the /var/opt/novell/nclmnt
|
||||
directory. This causes nwlogin mappings to fail.
|
||||
|
||||
Patch below is ported for SLED 11 SP1 and it is already submitted for
|
||||
OES 2 service packs.
|
||||
|
||||
Ported-by: Sankar P <psankar@novell.com>
|
||||
Signed-off-by: Pary D <dpary@novell.com>
|
||||
Acked-by: Jan Kara <jack@suse.cz>
|
||||
|
||||
---
|
||||
fs/novfs/inode.c | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/fs/novfs/inode.c
|
||||
+++ b/fs/novfs/inode.c
|
||||
@@ -2760,7 +2760,11 @@ struct dentry *novfs_i_lookup(struct ino
|
||||
}
|
||||
|
||||
if (!inode && ino) {
|
||||
- uid = novfs_scope_get_uid(id->Scope);
|
||||
+ if (id && id->Scope) {
|
||||
+ uid = novfs_scope_get_uid(id->Scope);
|
||||
+ } else {
|
||||
+ uid = novfs_scope_get_uid(novfs_get_scope(dentry));
|
||||
+ }
|
||||
if (novfs_lock_inode_cache(dir)) {
|
||||
inode = novfs_get_inode (dentry->d_sb, info->mode, 0, uid, ino, &name);
|
||||
if (inode) {
|
@ -1,31 +0,0 @@
|
||||
From: Sankar P <psankar@novell.com>
|
||||
Subject: novfs: fix an oops in novfs scope-finding code
|
||||
References: bnc#588579
|
||||
Patch-mainline: no
|
||||
|
||||
This patch removes an attempt to dereference a NULL pointer,
|
||||
on failed memory allocation. The addscope boolean takes care
|
||||
of the ScopeUserName field's validity.
|
||||
|
||||
Signed-off-by: Sankar P <psankar@novell.com>
|
||||
Acked-by: Jan Kara <jack@suse.cz>
|
||||
---
|
||||
fs/novfs/scope.c | 7 +++----
|
||||
1 file changed, 3 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/fs/novfs/scope.c
|
||||
+++ b/fs/novfs/scope.c
|
||||
@@ -170,10 +170,9 @@ static struct novfs_scope_list *Scope_Fi
|
||||
kfree(scope);
|
||||
scope = NULL;
|
||||
}
|
||||
- }
|
||||
-
|
||||
- if (addscope) {
|
||||
- novfs_add_to_root(scope->ScopeUserName);
|
||||
+
|
||||
+ if (scope && addscope)
|
||||
+ novfs_add_to_root(scope->ScopeUserName);
|
||||
}
|
||||
}
|
||||
|
@ -1,26 +0,0 @@
|
||||
From: Sankar P <psankar@novell.com>
|
||||
Subject: novfs: NCP Fragments can be upto 64k in size.
|
||||
References: bnc#625965
|
||||
Patch-mainline: No
|
||||
|
||||
Increase the Maximum fragment size declaration, so as to
|
||||
avoid wrong boundary checks.
|
||||
|
||||
Signed-off-by: Sankar P <psankar@novell.com>
|
||||
|
||||
diff --git a/fs/novfs/nwcapi.h b/fs/novfs/nwcapi.h
|
||||
index 4b6fb99..8cd842a 100644
|
||||
--- a/fs/novfs/nwcapi.h
|
||||
+++ b/fs/novfs/nwcapi.h
|
||||
@@ -301,7 +301,7 @@ N_EXTERN_LIBRARY(NWRCODE)
|
||||
#define MIN_NUM_REPLIES 1
|
||||
#define MAX_NUM_REQUESTS 4096
|
||||
#define MIN_NUM_REQUESTS 1
|
||||
-#define MAX_FRAG_SIZE 4096
|
||||
+#define MAX_FRAG_SIZE 65536
|
||||
#define MIN_FRAG_SIZE 1
|
||||
#define MAX_INFO_LEN 4096
|
||||
#define MAX_DOMAIN_LEN MAX_NETWORK_NAME_LENGTH
|
||||
--
|
||||
1.7.3.2
|
||||
|
@ -1,39 +0,0 @@
|
||||
From: Sankar P <psankar@novell.com>
|
||||
Subject: novfs: novfs reports incorrect file size
|
||||
Patch-mainline: no
|
||||
References: bnc#426536
|
||||
|
||||
While updating the inode, make sure that the s_blocks member
|
||||
is updated to the number of 512 blocks units.
|
||||
|
||||
This fixes the issue of novfs reporting invalid file sizes.
|
||||
|
||||
Signed-off-by: Sankar P <psankar@novell.com>
|
||||
Acked-by: Jan Kara <jack@suse.cz>
|
||||
|
||||
---
|
||||
fs/novfs/inode.c | 13 +++++++++++--
|
||||
1 file changed, 11 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/fs/novfs/inode.c
|
||||
+++ b/fs/novfs/inode.c
|
||||
@@ -2671,8 +2671,17 @@ void update_inode(struct inode *Inode, s
|
||||
Inode->i_mtime = Info->mtime;
|
||||
|
||||
if (Inode->i_size && Inode->i_sb->s_blocksize) {
|
||||
- Inode->i_blocks =
|
||||
- (unsigned long) (Info->size >> (loff_t) Inode->i_blkbits);
|
||||
+
|
||||
+ /*
|
||||
+ * Filling number of blocks as in NSS filesystem.
|
||||
+ * The s_blocksize is initialized to PAGE_CACHE_SIZE in
|
||||
+ * the super block initialization.
|
||||
+ *
|
||||
+ * Update i_blocks to have the number of 512 blocks
|
||||
+ */
|
||||
+ Inode->i_blocks = (((loff_t)Info->size) + Inode->i_sb->s_blocksize - 1)
|
||||
+ >> (loff_t)Inode->i_blkbits;
|
||||
+ Inode->i_blocks = Inode->i_blocks << (PAGE_CACHE_SHIFT - 9);
|
||||
Inode->i_bytes = Info->size & (Inode->i_sb->s_blocksize - 1);
|
||||
|
||||
DbgPrint("i_sb->s_blocksize=%d", Inode->i_sb->s_blocksize);
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user