mirror of
https://github.com/Fishwaldo/build.git
synced 2025-03-22 06:41:23 +00:00
1145 lines
33 KiB
Diff
1145 lines
33 KiB
Diff
|
diff --git a/Documentation/filesystems/efivarfs.txt b/Documentation/filesystems/efivarfs.txt
|
||
|
index c477af086e65..686a64bba775 100644
|
||
|
--- a/Documentation/filesystems/efivarfs.txt
|
||
|
+++ b/Documentation/filesystems/efivarfs.txt
|
||
|
@@ -14,3 +14,10 @@ filesystem.
|
||
|
efivarfs is typically mounted like this,
|
||
|
|
||
|
mount -t efivarfs none /sys/firmware/efi/efivars
|
||
|
+
|
||
|
+Due to the presence of numerous firmware bugs where removing non-standard
|
||
|
+UEFI variables causes the system firmware to fail to POST, efivarfs
|
||
|
+files that are not well-known standardized variables are created
|
||
|
+as immutable files. This doesn't prevent removal - "chattr -i" will work -
|
||
|
+but it does prevent this kind of failure from being accomplished
|
||
|
+accidentally.
|
||
|
diff --git a/Makefile b/Makefile
|
||
|
index 40d4d3bf52c3..4be9e643cef0 100644
|
||
|
--- a/Makefile
|
||
|
+++ b/Makefile
|
||
|
@@ -1,6 +1,6 @@
|
||
|
VERSION = 3
|
||
|
PATCHLEVEL = 10
|
||
|
-SUBLEVEL = 100
|
||
|
+SUBLEVEL = 101
|
||
|
EXTRAVERSION =
|
||
|
NAME = TOSSUG Baby Fish
|
||
|
|
||
|
diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c
|
||
|
index 6ee59a0eb268..48b4cf6b2a24 100644
|
||
|
--- a/arch/powerpc/kernel/module_64.c
|
||
|
+++ b/arch/powerpc/kernel/module_64.c
|
||
|
@@ -192,7 +192,7 @@ static void dedotify(Elf64_Sym *syms, unsigned int numsyms, char *strtab)
|
||
|
if (syms[i].st_shndx == SHN_UNDEF) {
|
||
|
char *name = strtab + syms[i].st_name;
|
||
|
if (name[0] == '.')
|
||
|
- memmove(name, name+1, strlen(name));
|
||
|
+ syms[i].st_name++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
|
||
|
index 04cc2fa7744f..335fe70967a8 100644
|
||
|
--- a/arch/x86/kvm/vmx.c
|
||
|
+++ b/arch/x86/kvm/vmx.c
|
||
|
@@ -1487,6 +1487,13 @@ static void add_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr,
|
||
|
return;
|
||
|
}
|
||
|
break;
|
||
|
+ case MSR_IA32_PEBS_ENABLE:
|
||
|
+ /* PEBS needs a quiescent period after being disabled (to write
|
||
|
+ * a record). Disabling PEBS through VMX MSR swapping doesn't
|
||
|
+ * provide that period, so a CPU could write host's record into
|
||
|
+ * guest's memory.
|
||
|
+ */
|
||
|
+ wrmsrl(MSR_IA32_PEBS_ENABLE, 0);
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < m->nr; ++i)
|
||
|
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
|
||
|
index 41ba726c1ce2..7f2b6dec4b2b 100644
|
||
|
--- a/arch/x86/kvm/x86.c
|
||
|
+++ b/arch/x86/kvm/x86.c
|
||
|
@@ -1941,6 +1941,8 @@ static void accumulate_steal_time(struct kvm_vcpu *vcpu)
|
||
|
|
||
|
static void record_steal_time(struct kvm_vcpu *vcpu)
|
||
|
{
|
||
|
+ accumulate_steal_time(vcpu);
|
||
|
+
|
||
|
if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED))
|
||
|
return;
|
||
|
|
||
|
@@ -2074,12 +2076,6 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
|
||
|
if (!(data & KVM_MSR_ENABLED))
|
||
|
break;
|
||
|
|
||
|
- vcpu->arch.st.last_steal = current->sched_info.run_delay;
|
||
|
-
|
||
|
- preempt_disable();
|
||
|
- accumulate_steal_time(vcpu);
|
||
|
- preempt_enable();
|
||
|
-
|
||
|
kvm_make_request(KVM_REQ_STEAL_UPDATE, vcpu);
|
||
|
|
||
|
break;
|
||
|
@@ -2758,7 +2754,6 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
|
||
|
vcpu->cpu = cpu;
|
||
|
}
|
||
|
|
||
|
- accumulate_steal_time(vcpu);
|
||
|
kvm_make_request(KVM_REQ_STEAL_UPDATE, vcpu);
|
||
|
}
|
||
|
|
||
|
diff --git a/crypto/af_alg.c b/crypto/af_alg.c
|
||
|
index 0ca108f3c840..1aaa555fab56 100644
|
||
|
--- a/crypto/af_alg.c
|
||
|
+++ b/crypto/af_alg.c
|
||
|
@@ -125,23 +125,6 @@ int af_alg_release(struct socket *sock)
|
||
|
}
|
||
|
EXPORT_SYMBOL_GPL(af_alg_release);
|
||
|
|
||
|
-void af_alg_release_parent(struct sock *sk)
|
||
|
-{
|
||
|
- struct alg_sock *ask = alg_sk(sk);
|
||
|
- bool last;
|
||
|
-
|
||
|
- sk = ask->parent;
|
||
|
- ask = alg_sk(sk);
|
||
|
-
|
||
|
- lock_sock(sk);
|
||
|
- last = !--ask->refcnt;
|
||
|
- release_sock(sk);
|
||
|
-
|
||
|
- if (last)
|
||
|
- sock_put(sk);
|
||
|
-}
|
||
|
-EXPORT_SYMBOL_GPL(af_alg_release_parent);
|
||
|
-
|
||
|
static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
|
||
|
{
|
||
|
struct sock *sk = sock->sk;
|
||
|
@@ -149,7 +132,6 @@ static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
|
||
|
struct sockaddr_alg *sa = (void *)uaddr;
|
||
|
const struct af_alg_type *type;
|
||
|
void *private;
|
||
|
- int err;
|
||
|
|
||
|
if (sock->state == SS_CONNECTED)
|
||
|
return -EINVAL;
|
||
|
@@ -175,22 +157,16 @@ static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
|
||
|
return PTR_ERR(private);
|
||
|
}
|
||
|
|
||
|
- err = -EBUSY;
|
||
|
lock_sock(sk);
|
||
|
- if (ask->refcnt)
|
||
|
- goto unlock;
|
||
|
|
||
|
swap(ask->type, type);
|
||
|
swap(ask->private, private);
|
||
|
|
||
|
- err = 0;
|
||
|
-
|
||
|
-unlock:
|
||
|
release_sock(sk);
|
||
|
|
||
|
alg_do_release(type, private);
|
||
|
|
||
|
- return err;
|
||
|
+ return 0;
|
||
|
}
|
||
|
|
||
|
static int alg_setkey(struct sock *sk, char __user *ukey,
|
||
|
@@ -223,15 +199,11 @@ static int alg_setsockopt(struct socket *sock, int level, int optname,
|
||
|
struct sock *sk = sock->sk;
|
||
|
struct alg_sock *ask = alg_sk(sk);
|
||
|
const struct af_alg_type *type;
|
||
|
- int err = -EBUSY;
|
||
|
+ int err = -ENOPROTOOPT;
|
||
|
|
||
|
lock_sock(sk);
|
||
|
- if (ask->refcnt)
|
||
|
- goto unlock;
|
||
|
-
|
||
|
type = ask->type;
|
||
|
|
||
|
- err = -ENOPROTOOPT;
|
||
|
if (level != SOL_ALG || !type)
|
||
|
goto unlock;
|
||
|
|
||
|
@@ -280,8 +252,7 @@ int af_alg_accept(struct sock *sk, struct socket *newsock)
|
||
|
|
||
|
sk2->sk_family = PF_ALG;
|
||
|
|
||
|
- if (!ask->refcnt++)
|
||
|
- sock_hold(sk);
|
||
|
+ sock_hold(sk);
|
||
|
alg_sk(sk2)->parent = sk;
|
||
|
alg_sk(sk2)->type = type;
|
||
|
|
||
|
diff --git a/fs/efivarfs/file.c b/fs/efivarfs/file.c
|
||
|
index 8dd524f32284..08f105a06fbf 100644
|
||
|
--- a/fs/efivarfs/file.c
|
||
|
+++ b/fs/efivarfs/file.c
|
||
|
@@ -10,6 +10,7 @@
|
||
|
#include <linux/efi.h>
|
||
|
#include <linux/fs.h>
|
||
|
#include <linux/slab.h>
|
||
|
+#include <linux/mount.h>
|
||
|
|
||
|
#include "internal.h"
|
||
|
|
||
|
@@ -108,9 +109,79 @@ out_free:
|
||
|
return size;
|
||
|
}
|
||
|
|
||
|
+static int
|
||
|
+efivarfs_ioc_getxflags(struct file *file, void __user *arg)
|
||
|
+{
|
||
|
+ struct inode *inode = file->f_mapping->host;
|
||
|
+ unsigned int i_flags;
|
||
|
+ unsigned int flags = 0;
|
||
|
+
|
||
|
+ i_flags = inode->i_flags;
|
||
|
+ if (i_flags & S_IMMUTABLE)
|
||
|
+ flags |= FS_IMMUTABLE_FL;
|
||
|
+
|
||
|
+ if (copy_to_user(arg, &flags, sizeof(flags)))
|
||
|
+ return -EFAULT;
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int
|
||
|
+efivarfs_ioc_setxflags(struct file *file, void __user *arg)
|
||
|
+{
|
||
|
+ struct inode *inode = file->f_mapping->host;
|
||
|
+ unsigned int flags;
|
||
|
+ unsigned int i_flags = 0;
|
||
|
+ int error;
|
||
|
+
|
||
|
+ if (!inode_owner_or_capable(inode))
|
||
|
+ return -EACCES;
|
||
|
+
|
||
|
+ if (copy_from_user(&flags, arg, sizeof(flags)))
|
||
|
+ return -EFAULT;
|
||
|
+
|
||
|
+ if (flags & ~FS_IMMUTABLE_FL)
|
||
|
+ return -EOPNOTSUPP;
|
||
|
+
|
||
|
+ if (!capable(CAP_LINUX_IMMUTABLE))
|
||
|
+ return -EPERM;
|
||
|
+
|
||
|
+ if (flags & FS_IMMUTABLE_FL)
|
||
|
+ i_flags |= S_IMMUTABLE;
|
||
|
+
|
||
|
+
|
||
|
+ error = mnt_want_write_file(file);
|
||
|
+ if (error)
|
||
|
+ return error;
|
||
|
+
|
||
|
+ mutex_lock(&inode->i_mutex);
|
||
|
+ inode->i_flags &= ~S_IMMUTABLE;
|
||
|
+ inode->i_flags |= i_flags;
|
||
|
+ mutex_unlock(&inode->i_mutex);
|
||
|
+
|
||
|
+ mnt_drop_write_file(file);
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+long
|
||
|
+efivarfs_file_ioctl(struct file *file, unsigned int cmd, unsigned long p)
|
||
|
+{
|
||
|
+ void __user *arg = (void __user *)p;
|
||
|
+
|
||
|
+ switch (cmd) {
|
||
|
+ case FS_IOC_GETFLAGS:
|
||
|
+ return efivarfs_ioc_getxflags(file, arg);
|
||
|
+ case FS_IOC_SETFLAGS:
|
||
|
+ return efivarfs_ioc_setxflags(file, arg);
|
||
|
+ }
|
||
|
+
|
||
|
+ return -ENOTTY;
|
||
|
+}
|
||
|
+
|
||
|
const struct file_operations efivarfs_file_operations = {
|
||
|
.open = simple_open,
|
||
|
.read = efivarfs_file_read,
|
||
|
.write = efivarfs_file_write,
|
||
|
.llseek = no_llseek,
|
||
|
+ .unlocked_ioctl = efivarfs_file_ioctl,
|
||
|
};
|
||
|
diff --git a/fs/efivarfs/inode.c b/fs/efivarfs/inode.c
|
||
|
index 7e787fb90293..d0351bc7b533 100644
|
||
|
--- a/fs/efivarfs/inode.c
|
||
|
+++ b/fs/efivarfs/inode.c
|
||
|
@@ -15,7 +15,8 @@
|
||
|
#include "internal.h"
|
||
|
|
||
|
struct inode *efivarfs_get_inode(struct super_block *sb,
|
||
|
- const struct inode *dir, int mode, dev_t dev)
|
||
|
+ const struct inode *dir, int mode,
|
||
|
+ dev_t dev, bool is_removable)
|
||
|
{
|
||
|
struct inode *inode = new_inode(sb);
|
||
|
|
||
|
@@ -23,6 +24,7 @@ struct inode *efivarfs_get_inode(struct super_block *sb,
|
||
|
inode->i_ino = get_next_ino();
|
||
|
inode->i_mode = mode;
|
||
|
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
|
||
|
+ inode->i_flags = is_removable ? 0 : S_IMMUTABLE;
|
||
|
switch (mode & S_IFMT) {
|
||
|
case S_IFREG:
|
||
|
inode->i_fop = &efivarfs_file_operations;
|
||
|
@@ -102,22 +104,17 @@ static void efivarfs_hex_to_guid(const char *str, efi_guid_t *guid)
|
||
|
static int efivarfs_create(struct inode *dir, struct dentry *dentry,
|
||
|
umode_t mode, bool excl)
|
||
|
{
|
||
|
- struct inode *inode;
|
||
|
+ struct inode *inode = NULL;
|
||
|
struct efivar_entry *var;
|
||
|
int namelen, i = 0, err = 0;
|
||
|
+ bool is_removable = false;
|
||
|
|
||
|
if (!efivarfs_valid_name(dentry->d_name.name, dentry->d_name.len))
|
||
|
return -EINVAL;
|
||
|
|
||
|
- inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0);
|
||
|
- if (!inode)
|
||
|
- return -ENOMEM;
|
||
|
-
|
||
|
var = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL);
|
||
|
- if (!var) {
|
||
|
- err = -ENOMEM;
|
||
|
- goto out;
|
||
|
- }
|
||
|
+ if (!var)
|
||
|
+ return -ENOMEM;
|
||
|
|
||
|
/* length of the variable name itself: remove GUID and separator */
|
||
|
namelen = dentry->d_name.len - EFI_VARIABLE_GUID_LEN - 1;
|
||
|
@@ -125,6 +122,16 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry,
|
||
|
efivarfs_hex_to_guid(dentry->d_name.name + namelen + 1,
|
||
|
&var->var.VendorGuid);
|
||
|
|
||
|
+ if (efivar_variable_is_removable(var->var.VendorGuid,
|
||
|
+ dentry->d_name.name, namelen))
|
||
|
+ is_removable = true;
|
||
|
+
|
||
|
+ inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0, is_removable);
|
||
|
+ if (!inode) {
|
||
|
+ err = -ENOMEM;
|
||
|
+ goto out;
|
||
|
+ }
|
||
|
+
|
||
|
for (i = 0; i < namelen; i++)
|
||
|
var->var.VariableName[i] = dentry->d_name.name[i];
|
||
|
|
||
|
@@ -138,7 +145,8 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry,
|
||
|
out:
|
||
|
if (err) {
|
||
|
kfree(var);
|
||
|
- iput(inode);
|
||
|
+ if (inode)
|
||
|
+ iput(inode);
|
||
|
}
|
||
|
return err;
|
||
|
}
|
||
|
diff --git a/fs/efivarfs/internal.h b/fs/efivarfs/internal.h
|
||
|
index b5ff16addb7c..b4505188e799 100644
|
||
|
--- a/fs/efivarfs/internal.h
|
||
|
+++ b/fs/efivarfs/internal.h
|
||
|
@@ -15,7 +15,8 @@ extern const struct file_operations efivarfs_file_operations;
|
||
|
extern const struct inode_operations efivarfs_dir_inode_operations;
|
||
|
extern bool efivarfs_valid_name(const char *str, int len);
|
||
|
extern struct inode *efivarfs_get_inode(struct super_block *sb,
|
||
|
- const struct inode *dir, int mode, dev_t dev);
|
||
|
+ const struct inode *dir, int mode, dev_t dev,
|
||
|
+ bool is_removable);
|
||
|
|
||
|
extern struct list_head efivarfs_list;
|
||
|
|
||
|
diff --git a/fs/efivarfs/super.c b/fs/efivarfs/super.c
|
||
|
index 141aee31884f..5a3655f690d9 100644
|
||
|
--- a/fs/efivarfs/super.c
|
||
|
+++ b/fs/efivarfs/super.c
|
||
|
@@ -128,8 +128,9 @@ static int efivarfs_callback(efi_char16_t *name16, efi_guid_t vendor,
|
||
|
struct dentry *dentry, *root = sb->s_root;
|
||
|
unsigned long size = 0;
|
||
|
char *name;
|
||
|
- int len, i;
|
||
|
+ int len;
|
||
|
int err = -ENOMEM;
|
||
|
+ bool is_removable = false;
|
||
|
|
||
|
entry = kmalloc(sizeof(*entry), GFP_KERNEL);
|
||
|
if (!entry)
|
||
|
@@ -138,15 +139,17 @@ static int efivarfs_callback(efi_char16_t *name16, efi_guid_t vendor,
|
||
|
memcpy(entry->var.VariableName, name16, name_size);
|
||
|
memcpy(&(entry->var.VendorGuid), &vendor, sizeof(efi_guid_t));
|
||
|
|
||
|
- len = ucs2_strlen(entry->var.VariableName);
|
||
|
+ len = ucs2_utf8size(entry->var.VariableName);
|
||
|
|
||
|
/* name, plus '-', plus GUID, plus NUL*/
|
||
|
name = kmalloc(len + 1 + EFI_VARIABLE_GUID_LEN + 1, GFP_KERNEL);
|
||
|
if (!name)
|
||
|
goto fail;
|
||
|
|
||
|
- for (i = 0; i < len; i++)
|
||
|
- name[i] = entry->var.VariableName[i] & 0xFF;
|
||
|
+ ucs2_as_utf8(name, entry->var.VariableName, len);
|
||
|
+
|
||
|
+ if (efivar_variable_is_removable(entry->var.VendorGuid, name, len))
|
||
|
+ is_removable = true;
|
||
|
|
||
|
name[len] = '-';
|
||
|
|
||
|
@@ -154,7 +157,8 @@ static int efivarfs_callback(efi_char16_t *name16, efi_guid_t vendor,
|
||
|
|
||
|
name[len + EFI_VARIABLE_GUID_LEN+1] = '\0';
|
||
|
|
||
|
- inode = efivarfs_get_inode(sb, root->d_inode, S_IFREG | 0644, 0);
|
||
|
+ inode = efivarfs_get_inode(sb, root->d_inode, S_IFREG | 0644, 0,
|
||
|
+ is_removable);
|
||
|
if (!inode)
|
||
|
goto fail_name;
|
||
|
|
||
|
@@ -210,7 +214,7 @@ static int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
|
||
|
sb->s_d_op = &efivarfs_d_ops;
|
||
|
sb->s_time_gran = 1;
|
||
|
|
||
|
- inode = efivarfs_get_inode(sb, NULL, S_IFDIR | 0755, 0);
|
||
|
+ inode = efivarfs_get_inode(sb, NULL, S_IFDIR | 0755, 0, true);
|
||
|
if (!inode)
|
||
|
return -ENOMEM;
|
||
|
inode->i_op = &efivarfs_dir_inode_operations;
|
||
|
diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h
|
||
|
index 2f38daaab3d7..d61c11170213 100644
|
||
|
--- a/include/crypto/if_alg.h
|
||
|
+++ b/include/crypto/if_alg.h
|
||
|
@@ -30,8 +30,6 @@ struct alg_sock {
|
||
|
|
||
|
struct sock *parent;
|
||
|
|
||
|
- unsigned int refcnt;
|
||
|
-
|
||
|
const struct af_alg_type *type;
|
||
|
void *private;
|
||
|
};
|
||
|
@@ -66,7 +64,6 @@ int af_alg_register_type(const struct af_alg_type *type);
|
||
|
int af_alg_unregister_type(const struct af_alg_type *type);
|
||
|
|
||
|
int af_alg_release(struct socket *sock);
|
||
|
-void af_alg_release_parent(struct sock *sk);
|
||
|
int af_alg_accept(struct sock *sk, struct socket *newsock);
|
||
|
|
||
|
int af_alg_make_sg(struct af_alg_sgl *sgl, void __user *addr, int len,
|
||
|
@@ -83,6 +80,11 @@ static inline struct alg_sock *alg_sk(struct sock *sk)
|
||
|
return (struct alg_sock *)sk;
|
||
|
}
|
||
|
|
||
|
+static inline void af_alg_release_parent(struct sock *sk)
|
||
|
+{
|
||
|
+ sock_put(alg_sk(sk)->parent);
|
||
|
+}
|
||
|
+
|
||
|
static inline void af_alg_init_completion(struct af_alg_completion *completion)
|
||
|
{
|
||
|
init_completion(&completion->completion);
|
||
|
diff --git a/include/linux/module.h b/include/linux/module.h
|
||
|
index 46f1ea01e6f6..761dc2848ffa 100644
|
||
|
--- a/include/linux/module.h
|
||
|
+++ b/include/linux/module.h
|
||
|
@@ -220,6 +220,12 @@ struct module_ref {
|
||
|
unsigned long decs;
|
||
|
} __attribute((aligned(2 * sizeof(unsigned long))));
|
||
|
|
||
|
+struct mod_kallsyms {
|
||
|
+ Elf_Sym *symtab;
|
||
|
+ unsigned int num_symtab;
|
||
|
+ char *strtab;
|
||
|
+};
|
||
|
+
|
||
|
struct module
|
||
|
{
|
||
|
enum module_state state;
|
||
|
@@ -308,14 +314,9 @@ struct module
|
||
|
#endif
|
||
|
|
||
|
#ifdef CONFIG_KALLSYMS
|
||
|
- /*
|
||
|
- * We keep the symbol and string tables for kallsyms.
|
||
|
- * The core_* fields below are temporary, loader-only (they
|
||
|
- * could really be discarded after module init).
|
||
|
- */
|
||
|
- Elf_Sym *symtab, *core_symtab;
|
||
|
- unsigned int num_symtab, core_num_syms;
|
||
|
- char *strtab, *core_strtab;
|
||
|
+ /* Protected by RCU and/or module_mutex: use rcu_dereference() */
|
||
|
+ struct mod_kallsyms *kallsyms;
|
||
|
+ struct mod_kallsyms core_kallsyms;
|
||
|
|
||
|
/* Section attributes */
|
||
|
struct module_sect_attrs *sect_attrs;
|
||
|
diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
|
||
|
index 0b2d0cbe0bab..36e5e9998865 100644
|
||
|
--- a/include/linux/tracepoint.h
|
||
|
+++ b/include/linux/tracepoint.h
|
||
|
@@ -129,9 +129,6 @@ static inline void tracepoint_synchronize_unregister(void)
|
||
|
void *it_func; \
|
||
|
void *__data; \
|
||
|
\
|
||
|
- if (!cpu_online(raw_smp_processor_id())) \
|
||
|
- return; \
|
||
|
- \
|
||
|
if (!(cond)) \
|
||
|
return; \
|
||
|
prercu; \
|
||
|
@@ -265,15 +262,19 @@ static inline void tracepoint_synchronize_unregister(void)
|
||
|
* "void *__data, proto" as the callback prototype.
|
||
|
*/
|
||
|
#define DECLARE_TRACE_NOARGS(name) \
|
||
|
- __DECLARE_TRACE(name, void, , 1, void *__data, __data)
|
||
|
+ __DECLARE_TRACE(name, void, , \
|
||
|
+ cpu_online(raw_smp_processor_id()), \
|
||
|
+ void *__data, __data)
|
||
|
|
||
|
#define DECLARE_TRACE(name, proto, args) \
|
||
|
- __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args), 1, \
|
||
|
- PARAMS(void *__data, proto), \
|
||
|
- PARAMS(__data, args))
|
||
|
+ __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args), \
|
||
|
+ cpu_online(raw_smp_processor_id()), \
|
||
|
+ PARAMS(void *__data, proto), \
|
||
|
+ PARAMS(__data, args))
|
||
|
|
||
|
#define DECLARE_TRACE_CONDITION(name, proto, args, cond) \
|
||
|
- __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args), PARAMS(cond), \
|
||
|
+ __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args), \
|
||
|
+ cpu_online(raw_smp_processor_id()) && (PARAMS(cond)), \
|
||
|
PARAMS(void *__data, proto), \
|
||
|
PARAMS(__data, args))
|
||
|
|
||
|
diff --git a/include/linux/ucs2_string.h b/include/linux/ucs2_string.h
|
||
|
index cbb20afdbc01..bb679b48f408 100644
|
||
|
--- a/include/linux/ucs2_string.h
|
||
|
+++ b/include/linux/ucs2_string.h
|
||
|
@@ -11,4 +11,8 @@ unsigned long ucs2_strlen(const ucs2_char_t *s);
|
||
|
unsigned long ucs2_strsize(const ucs2_char_t *data, unsigned long maxlength);
|
||
|
int ucs2_strncmp(const ucs2_char_t *a, const ucs2_char_t *b, size_t len);
|
||
|
|
||
|
+unsigned long ucs2_utf8size(const ucs2_char_t *src);
|
||
|
+unsigned long ucs2_as_utf8(u8 *dest, const ucs2_char_t *src,
|
||
|
+ unsigned long maxlength);
|
||
|
+
|
||
|
#endif /* _LINUX_UCS2_STRING_H_ */
|
||
|
diff --git a/kernel/module.c b/kernel/module.c
|
||
|
index 70a4754c001f..f8a4f48b48a9 100644
|
||
|
--- a/kernel/module.c
|
||
|
+++ b/kernel/module.c
|
||
|
@@ -179,6 +179,9 @@ struct load_info {
|
||
|
struct _ddebug *debug;
|
||
|
unsigned int num_debug;
|
||
|
bool sig_ok;
|
||
|
+#ifdef CONFIG_KALLSYMS
|
||
|
+ unsigned long mod_kallsyms_init_off;
|
||
|
+#endif
|
||
|
struct {
|
||
|
unsigned int sym, str, mod, vers, info, pcpu;
|
||
|
} index;
|
||
|
@@ -2346,8 +2349,20 @@ static void layout_symtab(struct module *mod, struct load_info *info)
|
||
|
strsect->sh_entsize = get_offset(mod, &mod->init_size, strsect,
|
||
|
info->index.str) | INIT_OFFSET_MASK;
|
||
|
pr_debug("\t%s\n", info->secstrings + strsect->sh_name);
|
||
|
+
|
||
|
+ /* We'll tack temporary mod_kallsyms on the end. */
|
||
|
+ mod->init_size = ALIGN(mod->init_size,
|
||
|
+ __alignof__(struct mod_kallsyms));
|
||
|
+ info->mod_kallsyms_init_off = mod->init_size;
|
||
|
+ mod->init_size += sizeof(struct mod_kallsyms);
|
||
|
+ mod->init_size = debug_align(mod->init_size);
|
||
|
}
|
||
|
|
||
|
+/*
|
||
|
+ * We use the full symtab and strtab which layout_symtab arranged to
|
||
|
+ * be appended to the init section. Later we switch to the cut-down
|
||
|
+ * core-only ones.
|
||
|
+ */
|
||
|
static void add_kallsyms(struct module *mod, const struct load_info *info)
|
||
|
{
|
||
|
unsigned int i, ndst;
|
||
|
@@ -2356,28 +2371,33 @@ static void add_kallsyms(struct module *mod, const struct load_info *info)
|
||
|
char *s;
|
||
|
Elf_Shdr *symsec = &info->sechdrs[info->index.sym];
|
||
|
|
||
|
- mod->symtab = (void *)symsec->sh_addr;
|
||
|
- mod->num_symtab = symsec->sh_size / sizeof(Elf_Sym);
|
||
|
+ /* Set up to point into init section. */
|
||
|
+ mod->kallsyms = mod->module_init + info->mod_kallsyms_init_off;
|
||
|
+
|
||
|
+ mod->kallsyms->symtab = (void *)symsec->sh_addr;
|
||
|
+ mod->kallsyms->num_symtab = symsec->sh_size / sizeof(Elf_Sym);
|
||
|
/* Make sure we get permanent strtab: don't use info->strtab. */
|
||
|
- mod->strtab = (void *)info->sechdrs[info->index.str].sh_addr;
|
||
|
+ mod->kallsyms->strtab = (void *)info->sechdrs[info->index.str].sh_addr;
|
||
|
|
||
|
/* Set types up while we still have access to sections. */
|
||
|
- for (i = 0; i < mod->num_symtab; i++)
|
||
|
- mod->symtab[i].st_info = elf_type(&mod->symtab[i], info);
|
||
|
-
|
||
|
- mod->core_symtab = dst = mod->module_core + info->symoffs;
|
||
|
- mod->core_strtab = s = mod->module_core + info->stroffs;
|
||
|
- src = mod->symtab;
|
||
|
- for (ndst = i = 0; i < mod->num_symtab; i++) {
|
||
|
+ for (i = 0; i < mod->kallsyms->num_symtab; i++)
|
||
|
+ mod->kallsyms->symtab[i].st_info
|
||
|
+ = elf_type(&mod->kallsyms->symtab[i], info);
|
||
|
+
|
||
|
+ /* Now populate the cut down core kallsyms for after init. */
|
||
|
+ mod->core_kallsyms.symtab = dst = mod->module_core + info->symoffs;
|
||
|
+ mod->core_kallsyms.strtab = s = mod->module_core + info->stroffs;
|
||
|
+ src = mod->kallsyms->symtab;
|
||
|
+ for (ndst = i = 0; i < mod->kallsyms->num_symtab; i++) {
|
||
|
if (i == 0 ||
|
||
|
is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) {
|
||
|
dst[ndst] = src[i];
|
||
|
- dst[ndst++].st_name = s - mod->core_strtab;
|
||
|
- s += strlcpy(s, &mod->strtab[src[i].st_name],
|
||
|
+ dst[ndst++].st_name = s - mod->core_kallsyms.strtab;
|
||
|
+ s += strlcpy(s, &mod->kallsyms->strtab[src[i].st_name],
|
||
|
KSYM_NAME_LEN) + 1;
|
||
|
}
|
||
|
}
|
||
|
- mod->core_num_syms = ndst;
|
||
|
+ mod->core_kallsyms.num_symtab = ndst;
|
||
|
}
|
||
|
#else
|
||
|
static inline void layout_symtab(struct module *mod, struct load_info *info)
|
||
|
@@ -3117,9 +3137,8 @@ static int do_init_module(struct module *mod)
|
||
|
module_put(mod);
|
||
|
trim_init_extable(mod);
|
||
|
#ifdef CONFIG_KALLSYMS
|
||
|
- mod->num_symtab = mod->core_num_syms;
|
||
|
- mod->symtab = mod->core_symtab;
|
||
|
- mod->strtab = mod->core_strtab;
|
||
|
+ /* Switch to core kallsyms now init is done: kallsyms may be walking! */
|
||
|
+ rcu_assign_pointer(mod->kallsyms, &mod->core_kallsyms);
|
||
|
#endif
|
||
|
unset_module_init_ro_nx(mod);
|
||
|
module_free(mod, mod->module_init);
|
||
|
@@ -3398,9 +3417,9 @@ static inline int is_arm_mapping_symbol(const char *str)
|
||
|
&& (str[2] == '\0' || str[2] == '.');
|
||
|
}
|
||
|
|
||
|
-static const char *symname(struct module *mod, unsigned int symnum)
|
||
|
+static const char *symname(struct mod_kallsyms *kallsyms, unsigned int symnum)
|
||
|
{
|
||
|
- return mod->strtab + mod->symtab[symnum].st_name;
|
||
|
+ return kallsyms->strtab + kallsyms->symtab[symnum].st_name;
|
||
|
}
|
||
|
|
||
|
static const char *get_ksymbol(struct module *mod,
|
||
|
@@ -3410,6 +3429,7 @@ static const char *get_ksymbol(struct module *mod,
|
||
|
{
|
||
|
unsigned int i, best = 0;
|
||
|
unsigned long nextval;
|
||
|
+ struct mod_kallsyms *kallsyms = rcu_dereference_sched(mod->kallsyms);
|
||
|
|
||
|
/* At worse, next value is at end of module */
|
||
|
if (within_module_init(addr, mod))
|
||
|
@@ -3419,32 +3439,32 @@ static const char *get_ksymbol(struct module *mod,
|
||
|
|
||
|
/* Scan for closest preceding symbol, and next symbol. (ELF
|
||
|
starts real symbols at 1). */
|
||
|
- for (i = 1; i < mod->num_symtab; i++) {
|
||
|
- if (mod->symtab[i].st_shndx == SHN_UNDEF)
|
||
|
+ for (i = 1; i < kallsyms->num_symtab; i++) {
|
||
|
+ if (kallsyms->symtab[i].st_shndx == SHN_UNDEF)
|
||
|
continue;
|
||
|
|
||
|
/* We ignore unnamed symbols: they're uninformative
|
||
|
* and inserted at a whim. */
|
||
|
- if (*symname(mod, i) == '\0'
|
||
|
- || is_arm_mapping_symbol(symname(mod, i)))
|
||
|
+ if (*symname(kallsyms, i) == '\0'
|
||
|
+ || is_arm_mapping_symbol(symname(kallsyms, i)))
|
||
|
continue;
|
||
|
|
||
|
- if (mod->symtab[i].st_value <= addr
|
||
|
- && mod->symtab[i].st_value > mod->symtab[best].st_value)
|
||
|
+ if (kallsyms->symtab[i].st_value <= addr
|
||
|
+ && kallsyms->symtab[i].st_value > kallsyms->symtab[best].st_value)
|
||
|
best = i;
|
||
|
- if (mod->symtab[i].st_value > addr
|
||
|
- && mod->symtab[i].st_value < nextval)
|
||
|
- nextval = mod->symtab[i].st_value;
|
||
|
+ if (kallsyms->symtab[i].st_value > addr
|
||
|
+ && kallsyms->symtab[i].st_value < nextval)
|
||
|
+ nextval = kallsyms->symtab[i].st_value;
|
||
|
}
|
||
|
|
||
|
if (!best)
|
||
|
return NULL;
|
||
|
|
||
|
if (size)
|
||
|
- *size = nextval - mod->symtab[best].st_value;
|
||
|
+ *size = nextval - kallsyms->symtab[best].st_value;
|
||
|
if (offset)
|
||
|
- *offset = addr - mod->symtab[best].st_value;
|
||
|
- return symname(mod, best);
|
||
|
+ *offset = addr - kallsyms->symtab[best].st_value;
|
||
|
+ return symname(kallsyms, best);
|
||
|
}
|
||
|
|
||
|
/* For kallsyms to ask for address resolution. NULL means not found. Careful
|
||
|
@@ -3540,18 +3560,21 @@ int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
|
||
|
|
||
|
preempt_disable();
|
||
|
list_for_each_entry_rcu(mod, &modules, list) {
|
||
|
+ struct mod_kallsyms *kallsyms;
|
||
|
+
|
||
|
if (mod->state == MODULE_STATE_UNFORMED)
|
||
|
continue;
|
||
|
- if (symnum < mod->num_symtab) {
|
||
|
- *value = mod->symtab[symnum].st_value;
|
||
|
- *type = mod->symtab[symnum].st_info;
|
||
|
- strlcpy(name, symname(mod, symnum), KSYM_NAME_LEN);
|
||
|
+ kallsyms = rcu_dereference_sched(mod->kallsyms);
|
||
|
+ if (symnum < kallsyms->num_symtab) {
|
||
|
+ *value = kallsyms->symtab[symnum].st_value;
|
||
|
+ *type = kallsyms->symtab[symnum].st_info;
|
||
|
+ strlcpy(name, symname(kallsyms, symnum), KSYM_NAME_LEN);
|
||
|
strlcpy(module_name, mod->name, MODULE_NAME_LEN);
|
||
|
*exported = is_exported(name, *value, mod);
|
||
|
preempt_enable();
|
||
|
return 0;
|
||
|
}
|
||
|
- symnum -= mod->num_symtab;
|
||
|
+ symnum -= kallsyms->num_symtab;
|
||
|
}
|
||
|
preempt_enable();
|
||
|
return -ERANGE;
|
||
|
@@ -3560,11 +3583,12 @@ int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
|
||
|
static unsigned long mod_find_symname(struct module *mod, const char *name)
|
||
|
{
|
||
|
unsigned int i;
|
||
|
+ struct mod_kallsyms *kallsyms = rcu_dereference_sched(mod->kallsyms);
|
||
|
|
||
|
- for (i = 0; i < mod->num_symtab; i++)
|
||
|
- if (strcmp(name, symname(mod, i)) == 0 &&
|
||
|
- mod->symtab[i].st_info != 'U')
|
||
|
- return mod->symtab[i].st_value;
|
||
|
+ for (i = 0; i < kallsyms->num_symtab; i++)
|
||
|
+ if (strcmp(name, symname(kallsyms, i)) == 0 &&
|
||
|
+ kallsyms->symtab[i].st_info != 'U')
|
||
|
+ return kallsyms->symtab[i].st_value;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
@@ -3603,11 +3627,14 @@ int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *,
|
||
|
int ret;
|
||
|
|
||
|
list_for_each_entry(mod, &modules, list) {
|
||
|
+ /* We hold module_mutex: no need for rcu_dereference_sched */
|
||
|
+ struct mod_kallsyms *kallsyms = mod->kallsyms;
|
||
|
+
|
||
|
if (mod->state == MODULE_STATE_UNFORMED)
|
||
|
continue;
|
||
|
- for (i = 0; i < mod->num_symtab; i++) {
|
||
|
- ret = fn(data, symname(mod, i),
|
||
|
- mod, mod->symtab[i].st_value);
|
||
|
+ for (i = 0; i < kallsyms->num_symtab; i++) {
|
||
|
+ ret = fn(data, symname(kallsyms, i),
|
||
|
+ mod, kallsyms->symtab[i].st_value);
|
||
|
if (ret != 0)
|
||
|
return ret;
|
||
|
}
|
||
|
diff --git a/lib/ucs2_string.c b/lib/ucs2_string.c
|
||
|
index 6f500ef2301d..f0b323abb4c6 100644
|
||
|
--- a/lib/ucs2_string.c
|
||
|
+++ b/lib/ucs2_string.c
|
||
|
@@ -49,3 +49,65 @@ ucs2_strncmp(const ucs2_char_t *a, const ucs2_char_t *b, size_t len)
|
||
|
}
|
||
|
}
|
||
|
EXPORT_SYMBOL(ucs2_strncmp);
|
||
|
+
|
||
|
+unsigned long
|
||
|
+ucs2_utf8size(const ucs2_char_t *src)
|
||
|
+{
|
||
|
+ unsigned long i;
|
||
|
+ unsigned long j = 0;
|
||
|
+
|
||
|
+ for (i = 0; i < ucs2_strlen(src); i++) {
|
||
|
+ u16 c = src[i];
|
||
|
+
|
||
|
+ if (c >= 0x800)
|
||
|
+ j += 3;
|
||
|
+ else if (c >= 0x80)
|
||
|
+ j += 2;
|
||
|
+ else
|
||
|
+ j += 1;
|
||
|
+ }
|
||
|
+
|
||
|
+ return j;
|
||
|
+}
|
||
|
+EXPORT_SYMBOL(ucs2_utf8size);
|
||
|
+
|
||
|
+/*
|
||
|
+ * copy at most maxlength bytes of whole utf8 characters to dest from the
|
||
|
+ * ucs2 string src.
|
||
|
+ *
|
||
|
+ * The return value is the number of characters copied, not including the
|
||
|
+ * final NUL character.
|
||
|
+ */
|
||
|
+unsigned long
|
||
|
+ucs2_as_utf8(u8 *dest, const ucs2_char_t *src, unsigned long maxlength)
|
||
|
+{
|
||
|
+ unsigned int i;
|
||
|
+ unsigned long j = 0;
|
||
|
+ unsigned long limit = ucs2_strnlen(src, maxlength);
|
||
|
+
|
||
|
+ for (i = 0; maxlength && i < limit; i++) {
|
||
|
+ u16 c = src[i];
|
||
|
+
|
||
|
+ if (c >= 0x800) {
|
||
|
+ if (maxlength < 3)
|
||
|
+ break;
|
||
|
+ maxlength -= 3;
|
||
|
+ dest[j++] = 0xe0 | (c & 0xf000) >> 12;
|
||
|
+ dest[j++] = 0x80 | (c & 0x0fc0) >> 6;
|
||
|
+ dest[j++] = 0x80 | (c & 0x003f);
|
||
|
+ } else if (c >= 0x80) {
|
||
|
+ if (maxlength < 2)
|
||
|
+ break;
|
||
|
+ maxlength -= 2;
|
||
|
+ dest[j++] = 0xc0 | (c & 0x7c0) >> 6;
|
||
|
+ dest[j++] = 0x80 | (c & 0x03f);
|
||
|
+ } else {
|
||
|
+ maxlength -= 1;
|
||
|
+ dest[j++] = c & 0x7f;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ if (maxlength)
|
||
|
+ dest[j] = '\0';
|
||
|
+ return j;
|
||
|
+}
|
||
|
+EXPORT_SYMBOL(ucs2_as_utf8);
|
||
|
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
|
||
|
index 31bf2586fb84..864408026202 100644
|
||
|
--- a/net/mac80211/agg-rx.c
|
||
|
+++ b/net/mac80211/agg-rx.c
|
||
|
@@ -290,7 +290,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
|
||
|
}
|
||
|
|
||
|
/* prepare A-MPDU MLME for Rx aggregation */
|
||
|
- tid_agg_rx = kmalloc(sizeof(struct tid_ampdu_rx), GFP_KERNEL);
|
||
|
+ tid_agg_rx = kzalloc(sizeof(*tid_agg_rx), GFP_KERNEL);
|
||
|
if (!tid_agg_rx)
|
||
|
goto end;
|
||
|
|
||
|
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
|
||
|
index f3bbea1eb9e7..13f10aab9213 100644
|
||
|
--- a/net/mac80211/rc80211_minstrel_ht.c
|
||
|
+++ b/net/mac80211/rc80211_minstrel_ht.c
|
||
|
@@ -454,7 +454,7 @@ minstrel_aggr_check(struct ieee80211_sta *pubsta, struct sk_buff *skb)
|
||
|
if (skb_get_queue_mapping(skb) == IEEE80211_AC_VO)
|
||
|
return;
|
||
|
|
||
|
- ieee80211_start_tx_ba_session(pubsta, tid, 5000);
|
||
|
+ ieee80211_start_tx_ba_session(pubsta, tid, 0);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c
|
||
|
index c8717c1d082e..87dd619fb2e9 100644
|
||
|
--- a/net/wireless/wext-core.c
|
||
|
+++ b/net/wireless/wext-core.c
|
||
|
@@ -342,6 +342,39 @@ static const int compat_event_type_size[] = {
|
||
|
|
||
|
/* IW event code */
|
||
|
|
||
|
+static void wireless_nlevent_flush(void)
|
||
|
+{
|
||
|
+ struct sk_buff *skb;
|
||
|
+ struct net *net;
|
||
|
+
|
||
|
+ ASSERT_RTNL();
|
||
|
+
|
||
|
+ for_each_net(net) {
|
||
|
+ while ((skb = skb_dequeue(&net->wext_nlevents)))
|
||
|
+ rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL,
|
||
|
+ GFP_KERNEL);
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+static int wext_netdev_notifier_call(struct notifier_block *nb,
|
||
|
+ unsigned long state, void *ptr)
|
||
|
+{
|
||
|
+ /*
|
||
|
+ * When a netdev changes state in any way, flush all pending messages
|
||
|
+ * to avoid them going out in a strange order, e.g. RTM_NEWLINK after
|
||
|
+ * RTM_DELLINK, or with IFF_UP after without IFF_UP during dev_close()
|
||
|
+ * or similar - all of which could otherwise happen due to delays from
|
||
|
+ * schedule_work().
|
||
|
+ */
|
||
|
+ wireless_nlevent_flush();
|
||
|
+
|
||
|
+ return NOTIFY_OK;
|
||
|
+}
|
||
|
+
|
||
|
+static struct notifier_block wext_netdev_notifier = {
|
||
|
+ .notifier_call = wext_netdev_notifier_call,
|
||
|
+};
|
||
|
+
|
||
|
static int __net_init wext_pernet_init(struct net *net)
|
||
|
{
|
||
|
skb_queue_head_init(&net->wext_nlevents);
|
||
|
@@ -360,7 +393,12 @@ static struct pernet_operations wext_pernet_ops = {
|
||
|
|
||
|
static int __init wireless_nlevent_init(void)
|
||
|
{
|
||
|
- return register_pernet_subsys(&wext_pernet_ops);
|
||
|
+ int err = register_pernet_subsys(&wext_pernet_ops);
|
||
|
+
|
||
|
+ if (err)
|
||
|
+ return err;
|
||
|
+
|
||
|
+ return register_netdevice_notifier(&wext_netdev_notifier);
|
||
|
}
|
||
|
|
||
|
subsys_initcall(wireless_nlevent_init);
|
||
|
@@ -368,17 +406,8 @@ subsys_initcall(wireless_nlevent_init);
|
||
|
/* Process events generated by the wireless layer or the driver. */
|
||
|
static void wireless_nlevent_process(struct work_struct *work)
|
||
|
{
|
||
|
- struct sk_buff *skb;
|
||
|
- struct net *net;
|
||
|
-
|
||
|
rtnl_lock();
|
||
|
-
|
||
|
- for_each_net(net) {
|
||
|
- while ((skb = skb_dequeue(&net->wext_nlevents)))
|
||
|
- rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL,
|
||
|
- GFP_KERNEL);
|
||
|
- }
|
||
|
-
|
||
|
+ wireless_nlevent_flush();
|
||
|
rtnl_unlock();
|
||
|
}
|
||
|
|
||
|
diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c
|
||
|
index 754f88e1fdab..4892966fc1b8 100644
|
||
|
--- a/sound/soc/codecs/wm8958-dsp2.c
|
||
|
+++ b/sound/soc/codecs/wm8958-dsp2.c
|
||
|
@@ -459,7 +459,7 @@ static int wm8958_put_mbc_enum(struct snd_kcontrol *kcontrol,
|
||
|
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||
|
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
|
||
|
struct wm8994 *control = wm8994->wm8994;
|
||
|
- int value = ucontrol->value.integer.value[0];
|
||
|
+ int value = ucontrol->value.enumerated.item[0];
|
||
|
int reg;
|
||
|
|
||
|
/* Don't allow on the fly reconfiguration */
|
||
|
@@ -549,7 +549,7 @@ static int wm8958_put_vss_enum(struct snd_kcontrol *kcontrol,
|
||
|
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||
|
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
|
||
|
struct wm8994 *control = wm8994->wm8994;
|
||
|
- int value = ucontrol->value.integer.value[0];
|
||
|
+ int value = ucontrol->value.enumerated.item[0];
|
||
|
int reg;
|
||
|
|
||
|
/* Don't allow on the fly reconfiguration */
|
||
|
@@ -582,7 +582,7 @@ static int wm8958_put_vss_hpf_enum(struct snd_kcontrol *kcontrol,
|
||
|
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||
|
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
|
||
|
struct wm8994 *control = wm8994->wm8994;
|
||
|
- int value = ucontrol->value.integer.value[0];
|
||
|
+ int value = ucontrol->value.enumerated.item[0];
|
||
|
int reg;
|
||
|
|
||
|
/* Don't allow on the fly reconfiguration */
|
||
|
@@ -749,7 +749,7 @@ static int wm8958_put_enh_eq_enum(struct snd_kcontrol *kcontrol,
|
||
|
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||
|
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
|
||
|
struct wm8994 *control = wm8994->wm8994;
|
||
|
- int value = ucontrol->value.integer.value[0];
|
||
|
+ int value = ucontrol->value.enumerated.item[0];
|
||
|
int reg;
|
||
|
|
||
|
/* Don't allow on the fly reconfiguration */
|
||
|
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
|
||
|
index 6e746c7474bf..cda3cf23474b 100644
|
||
|
--- a/sound/soc/codecs/wm8994.c
|
||
|
+++ b/sound/soc/codecs/wm8994.c
|
||
|
@@ -361,7 +361,7 @@ static int wm8994_put_drc_enum(struct snd_kcontrol *kcontrol,
|
||
|
struct wm8994 *control = wm8994->wm8994;
|
||
|
struct wm8994_pdata *pdata = &control->pdata;
|
||
|
int drc = wm8994_get_drc(kcontrol->id.name);
|
||
|
- int value = ucontrol->value.integer.value[0];
|
||
|
+ int value = ucontrol->value.enumerated.item[0];
|
||
|
|
||
|
if (drc < 0)
|
||
|
return drc;
|
||
|
@@ -468,7 +468,7 @@ static int wm8994_put_retune_mobile_enum(struct snd_kcontrol *kcontrol,
|
||
|
struct wm8994 *control = wm8994->wm8994;
|
||
|
struct wm8994_pdata *pdata = &control->pdata;
|
||
|
int block = wm8994_get_retune_mobile_block(kcontrol->id.name);
|
||
|
- int value = ucontrol->value.integer.value[0];
|
||
|
+ int value = ucontrol->value.enumerated.item[0];
|
||
|
|
||
|
if (block < 0)
|
||
|
return block;
|
||
|
diff --git a/tools/testing/selftests/efivarfs/efivarfs.sh b/tools/testing/selftests/efivarfs/efivarfs.sh
|
||
|
index 77edcdcc016b..057278448515 100644
|
||
|
--- a/tools/testing/selftests/efivarfs/efivarfs.sh
|
||
|
+++ b/tools/testing/selftests/efivarfs/efivarfs.sh
|
||
|
@@ -88,7 +88,11 @@ test_delete()
|
||
|
exit 1
|
||
|
fi
|
||
|
|
||
|
- rm $file
|
||
|
+ rm $file 2>/dev/null
|
||
|
+ if [ $? -ne 0 ]; then
|
||
|
+ chattr -i $file
|
||
|
+ rm $file
|
||
|
+ fi
|
||
|
|
||
|
if [ -e $file ]; then
|
||
|
echo "$file couldn't be deleted" >&2
|
||
|
@@ -111,6 +115,7 @@ test_zero_size_delete()
|
||
|
exit 1
|
||
|
fi
|
||
|
|
||
|
+ chattr -i $file
|
||
|
printf "$attrs" > $file
|
||
|
|
||
|
if [ -e $file ]; then
|
||
|
@@ -141,7 +146,11 @@ test_valid_filenames()
|
||
|
echo "$file could not be created" >&2
|
||
|
ret=1
|
||
|
else
|
||
|
- rm $file
|
||
|
+ rm $file 2>/dev/null
|
||
|
+ if [ $? -ne 0 ]; then
|
||
|
+ chattr -i $file
|
||
|
+ rm $file
|
||
|
+ fi
|
||
|
fi
|
||
|
done
|
||
|
|
||
|
@@ -174,7 +183,11 @@ test_invalid_filenames()
|
||
|
|
||
|
if [ -e $file ]; then
|
||
|
echo "Creating $file should have failed" >&2
|
||
|
- rm $file
|
||
|
+ rm $file 2>/dev/null
|
||
|
+ if [ $? -ne 0 ]; then
|
||
|
+ chattr -i $file
|
||
|
+ rm $file
|
||
|
+ fi
|
||
|
ret=1
|
||
|
fi
|
||
|
done
|
||
|
diff --git a/tools/testing/selftests/efivarfs/open-unlink.c b/tools/testing/selftests/efivarfs/open-unlink.c
|
||
|
index 8c0764407b3c..4af74f733036 100644
|
||
|
--- a/tools/testing/selftests/efivarfs/open-unlink.c
|
||
|
+++ b/tools/testing/selftests/efivarfs/open-unlink.c
|
||
|
@@ -1,10 +1,68 @@
|
||
|
+#include <errno.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdint.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <unistd.h>
|
||
|
+#include <sys/ioctl.h>
|
||
|
#include <sys/types.h>
|
||
|
#include <sys/stat.h>
|
||
|
#include <fcntl.h>
|
||
|
+#include <linux/fs.h>
|
||
|
+
|
||
|
+static int set_immutable(const char *path, int immutable)
|
||
|
+{
|
||
|
+ unsigned int flags;
|
||
|
+ int fd;
|
||
|
+ int rc;
|
||
|
+ int error;
|
||
|
+
|
||
|
+ fd = open(path, O_RDONLY);
|
||
|
+ if (fd < 0)
|
||
|
+ return fd;
|
||
|
+
|
||
|
+ rc = ioctl(fd, FS_IOC_GETFLAGS, &flags);
|
||
|
+ if (rc < 0) {
|
||
|
+ error = errno;
|
||
|
+ close(fd);
|
||
|
+ errno = error;
|
||
|
+ return rc;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (immutable)
|
||
|
+ flags |= FS_IMMUTABLE_FL;
|
||
|
+ else
|
||
|
+ flags &= ~FS_IMMUTABLE_FL;
|
||
|
+
|
||
|
+ rc = ioctl(fd, FS_IOC_SETFLAGS, &flags);
|
||
|
+ error = errno;
|
||
|
+ close(fd);
|
||
|
+ errno = error;
|
||
|
+ return rc;
|
||
|
+}
|
||
|
+
|
||
|
+static int get_immutable(const char *path)
|
||
|
+{
|
||
|
+ unsigned int flags;
|
||
|
+ int fd;
|
||
|
+ int rc;
|
||
|
+ int error;
|
||
|
+
|
||
|
+ fd = open(path, O_RDONLY);
|
||
|
+ if (fd < 0)
|
||
|
+ return fd;
|
||
|
+
|
||
|
+ rc = ioctl(fd, FS_IOC_GETFLAGS, &flags);
|
||
|
+ if (rc < 0) {
|
||
|
+ error = errno;
|
||
|
+ close(fd);
|
||
|
+ errno = error;
|
||
|
+ return rc;
|
||
|
+ }
|
||
|
+ close(fd);
|
||
|
+ if (flags & FS_IMMUTABLE_FL)
|
||
|
+ return 1;
|
||
|
+ return 0;
|
||
|
+}
|
||
|
|
||
|
int main(int argc, char **argv)
|
||
|
{
|
||
|
@@ -27,7 +85,7 @@ int main(int argc, char **argv)
|
||
|
buf[4] = 0;
|
||
|
|
||
|
/* create a test variable */
|
||
|
- fd = open(path, O_WRONLY | O_CREAT);
|
||
|
+ fd = open(path, O_WRONLY | O_CREAT, 0600);
|
||
|
if (fd < 0) {
|
||
|
perror("open(O_WRONLY)");
|
||
|
return EXIT_FAILURE;
|
||
|
@@ -41,6 +99,18 @@ int main(int argc, char **argv)
|
||
|
|
||
|
close(fd);
|
||
|
|
||
|
+ rc = get_immutable(path);
|
||
|
+ if (rc < 0) {
|
||
|
+ perror("ioctl(FS_IOC_GETFLAGS)");
|
||
|
+ return EXIT_FAILURE;
|
||
|
+ } else if (rc) {
|
||
|
+ rc = set_immutable(path, 0);
|
||
|
+ if (rc < 0) {
|
||
|
+ perror("ioctl(FS_IOC_SETFLAGS)");
|
||
|
+ return EXIT_FAILURE;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
fd = open(path, O_RDONLY);
|
||
|
if (fd < 0) {
|
||
|
perror("open");
|