perf ver. bump

This commit is contained in:
Rmys
2020-04-14 00:03:24 +03:00
parent db7eb887f2
commit 5cc034956e
171 changed files with 17599 additions and 682387 deletions
+1 -1
View File
@@ -24,5 +24,5 @@ def install():
pisitools.domove("/usr/etc/bash_completion.d/perf", "/etc/bash_completion.d")
pisitools.removeDir("/usr/etc")
#pisitools.domove("/usr/lib64/libperf-gtk.so", "/usr/lib/")
pisitools.domove("/usr/lib64/libperf-gtk.so", "/usr/lib/")
pisitools.removeDir("/usr/lib64")
@@ -1,86 +0,0 @@
diff -Nuar linux-4.9.orig/fs/aufs/posix_acl.c linux-4.9/fs/aufs/posix_acl.c
--- linux-4.9.orig/fs/aufs/posix_acl.c 2017-04-09 09:33:00.155052337 +0300
+++ linux-4.9/fs/aufs/posix_acl.c 2017-04-09 09:34:03.760053849 +0300
@@ -1,5 +1,18 @@
/*
* Copyright (C) 2014-2016 Junjiro R. Okajima
+ *
+ * This program, aufs 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, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
*/
/*
@@ -36,6 +49,8 @@
/* always topmost only */
acl = get_acl(h_inode, type);
+ if (!IS_ERR_OR_NULL(acl))
+ set_cached_acl(inode, type, acl);
out:
ii_read_unlock(inode);
@@ -77,8 +92,10 @@
ssz = au_sxattr(dentry, inode, &arg);
dput(dentry);
err = ssz;
- if (ssz >= 0)
+ if (ssz >= 0) {
err = 0;
+ set_cached_acl(inode, type, acl);
+ }
out:
return err;
diff -Nuar linux-4.9.orig/fs/aufs/xattr.c linux-4.9/fs/aufs/xattr.c
--- linux-4.9.orig/fs/aufs/xattr.c 2017-04-09 09:33:00.160052337 +0300
+++ linux-4.9/fs/aufs/xattr.c 2017-04-09 09:34:08.757053967 +0300
@@ -1,11 +1,26 @@
/*
* Copyright (C) 2014-2016 Junjiro R. Okajima
+ *
+ * This program, aufs 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, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
*/
/*
* handling xattr functions
*/
+#include <linux/fs.h>
+#include <linux/posix_acl_xattr.h>
#include <linux/xattr.h>
#include "aufs.h"
@@ -309,7 +324,11 @@
};
static const struct xattr_handler *au_xattr_handlers[] = {
- &au_xattr_handler,
+#ifdef CONFIG_FS_POSIX_ACL
+ &posix_acl_access_xattr_handler,
+ &posix_acl_default_xattr_handler,
+#endif
+ &au_xattr_handler, /* must be last */
NULL
};
Binary file not shown.
@@ -1,181 +0,0 @@
3rdparty/mkbuild.pl | 92 +++++++++++++++++++++++++++++++++++++++++++++
Documentation/3rdparty.txt | 76 +++++++++++++++++++++++++++++++++++++
2 files changed, 168 insertions(+)
diff -Nurp linux-2.6.37/3rdparty/mkbuild.pl linux-2.6.37.3rdparty/3rdparty/mkbuild.pl
--- linux-2.6.37/3rdparty/mkbuild.pl 1970-01-01 02:00:00.000000000 +0200
+++ linux-2.6.37.3rdparty/3rdparty/mkbuild.pl 2004-04-23 14:59:03.000000000 +0300
@@ -0,0 +1,92 @@
+#!/usr/bin/perl -w
+#
+# Version 1.0
+#
+# Copyright 2001 Jeff Garzik <jgarzik@mandrakesoft.com>
+# Copyright 2002 Juan Quintela <quintela@mandrakesoft.com>
+# Copyright 2003 Nicolas Planel <nplanel@mandrakesoft.com>
+#
+# This software may be used and distributed according to the terms
+# of the GNU General Public License, incorporated herein by reference.
+#
+#
+# Run "mkbuild.pl"
+#
+# This program generates the following files
+# Makefile
+# Makefile.drivers
+# Config.in
+# using the information in the subdirs of this directory.
+#
+# subdirs need to have:
+# a Config.in file
+# a Makefile with a O_TARGET/L_TARGET targets
+# The config.in should set a CONFIG_<module_dir_name> to m/y.
+
+use strict;
+
+opendir(THISDIR, ".");
+# get dirs without . and .. garbage
+my (@modules) = grep(!/\.\.?$/,grep(-d, readdir(THISDIR)));
+closedir(THISDIR);
+
+generate_kconfig(@modules);
+generate_makefile(@modules);
+exit(0);
+
+##########################################################################
+
+sub generate_makefile {
+ my (@modules) = @_;
+
+ local *F;
+ open F, "> Makefile" or die "Cannot create new Makefile: $!\n";
+ print F <<'EOM';
+#
+# THIS IS AN AUTOMATICALLY GENERATED FILE. DO NOT EDIT.
+#
+
+EOM
+ printf F "obj- := 3rdparty.o # Dummy rule to force built-in.o to be made\n";
+ printf F "obj-\$(%s) += %s\n", to_CONFIG($_), $_ . '/' foreach @modules;
+}
+
+sub generate_kconfig {
+ my (@modules) = @_;
+
+ local *F;
+ open F, "> Kconfig" or die "Cannot create Kconfig: $!\n";
+ print F <<"EOM";
+#
+# THIS IS AN AUTOMATICALLY GENERATED FILE. DO NOT EDIT.
+#
+
+menu "Unofficial 3rd party kernel additions"
+
+EOM
+
+ foreach (@modules) {
+ die "No Kconfig in $_.\n" if ! -r "$_/Kconfig";
+ print F "source 3rdparty/$_/Kconfig\n";
+ }
+ print F "\n\nendmenu\n";
+}
+
+sub to_CONFIG {
+ local $_ = $_[0];
+ tr/a-z/A-Z/;
+ s/[\-\. ]/_/g;
+ "CONFIG_$_";
+}
+
+sub find_target {
+ my ($module_dir) = @_;
+
+ local *F;
+ open(F, "$module_dir/Makefile") or die "$module_dir/Makefile: $!\n";
+ while (<F>) {
+ chomp;
+ return $1 if (/[LO]_TARGET.*:=\s+(\S+)/);
+ }
+}
+
diff -Nurp linux-2.6.37/Documentation/3rdparty.txt linux-2.6.37.3rdparty/Documentation/3rdparty.txt
--- linux-2.6.37/Documentation/3rdparty.txt 1970-01-01 02:00:00.000000000 +0200
+++ linux-2.6.37.3rdparty/Documentation/3rdparty.txt 2003-11-22 01:07:26.000000000 +0200
@@ -0,0 +1,76 @@
+
+Third-Party Kernel Source Module Support, or
+an easy way to add modules to your kernel build.
+
+
+
+Vendors quite often add additional drivers and features to the kernel
+which require nothing more than modifying Kconfig, Makefile, and
+adding one or more files to a sub-directory. As a single discrete task,
+this is not a problem. However, using patches to add modules to the
+kernel very often results in patch conflicts, resulting in needless time
+wastage as developers regenerate an otherwise working kernel patch.
+
+This is designed as a solution to these problems. It is NOT designed as
+a replacement for the kernel build system, but merely as a tool for
+vendors and system administrators to ease the pain of patch management.
+
+The key feature of this system is the distinct lack of patches. Drivers
+are installed via unpacking a tarball.
+
+
+
+Adding a directory to the build (usually from a tarball)
+--------------------------------------------------------
+If a directory exists inside the 3rdparty sub-directory that contains a
+proper Makefile, it can be added to the build. It also needs a
+Kconfig file.
+
+ cd /usr/src/linux-2.4.3/3rdparty
+ bzcat /tmp/my-driver2.tar.bz2 | tar xf - # creates "my2" dir
+
+
+Limitations
+-----------
+There are some limitations to this system. This system is only
+designed to support a very common case. If you find yourself running
+into limitations (kernel build experts can spot them right off),
+then you should probably be patching the kernel instead of using
+mkbuild.pl for that particular module.
+
+FIXME: actually list the limitations
+
+
+
+Other notes
+-----------
+Link order is controlled by the order of mkbuild.pl executions.
+
+"make mrproper" will erase Makefile.meta, and empty Kconfig, Makefile,
+and Makefile.drivers.
+
+IMPORTANT NOTE: Because this feature modifies the kernel's makefiles and
+configuration system, you MUST complete all mkbuild.pl runs before
+running any "make" command.
+
+Building in the 3rdparty dir
+----------------------------
+
+If you use modules that:
+ - are contained in one subdir with the name of the module
+ - has a Makefile
+ - has a Kconfig file
+
+The system calls the ./mkbuild.pl script. It will search for
+subdirectories, and will try to build each of them as a module.
+Things to note:
+
+ The dependencies will be done in a module called:
+
+ 3rdparty/<module_dir_name>/<module_name>
+
+depending of CONFIG_<module_name_in_uppercase>.
+
+<module_name> is the value of O_TARGET/L_TARGET.
+
+
@@ -1,191 +0,0 @@
Include 3rdparty directory into the main build-system.
Original author is unknown.
(Was either Juan Quintela or Jeff Garzik)
Signed-off-by: Luiz Fernando N. Capitulino <lcapitulino@mandriva.com.br>
Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
Signed-off-by: Thomas Backlund <tmb@mageia.org>
Makefile | 2 +-
arch/alpha/Kconfig | 1 +
arch/ia64/Kconfig | 2 ++
arch/mips/Kconfig | 2 ++
arch/powerpc/Kconfig | 2 ++
arch/sparc/Kconfig | 2 ++
arch/x86/Kconfig | 2 ++
scripts/kconfig/Makefile | 33 ++++++++++++++++++---------------
8 files changed, 30 insertions(+), 16 deletions(-)
diff -Nurp linux-4.2.2/arch/alpha/Kconfig linux-4.2.2-3rd/arch/alpha/Kconfig
--- linux-4.2.2/arch/alpha/Kconfig 2015-08-30 21:34:09.000000000 +0300
+++ linux-4.2.2-3rd/arch/alpha/Kconfig 2015-09-29 23:02:44.024347272 +0300
@@ -750,3 +750,4 @@ source "crypto/Kconfig"
source "lib/Kconfig"
+source "3rdparty/Kconfig"
diff -Nurp linux-4.2.2/arch/ia64/Kconfig linux-4.2.2-3rd/arch/ia64/Kconfig
--- linux-4.2.2/arch/ia64/Kconfig 2015-08-30 21:34:09.000000000 +0300
+++ linux-4.2.2-3rd/arch/ia64/Kconfig 2015-09-29 23:02:44.024347272 +0300
@@ -613,3 +613,5 @@ source "lib/Kconfig"
config IOMMU_HELPER
def_bool (IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB || IA64_GENERIC || SWIOTLB)
+
+source "3rdparty/Kconfig"
diff -Nurp linux-4.2.2/arch/mips/Kconfig linux-4.2.2-3rd/arch/mips/Kconfig
--- linux-4.2.2/arch/mips/Kconfig 2015-08-30 21:34:09.000000000 +0300
+++ linux-4.2.2-3rd/arch/mips/Kconfig 2015-09-29 23:02:44.024347272 +0300
@@ -2944,3 +2944,5 @@ source "crypto/Kconfig"
source "lib/Kconfig"
source "arch/mips/kvm/Kconfig"
+
+source "3rdparty/Kconfig"
diff -Nurp linux-4.2.2/arch/powerpc/Kconfig linux-4.2.2-3rd/arch/powerpc/Kconfig
--- linux-4.2.2/arch/powerpc/Kconfig 2015-08-30 21:34:09.000000000 +0300
+++ linux-4.2.2-3rd/arch/powerpc/Kconfig 2015-09-29 23:02:44.025347276 +0300
@@ -1112,3 +1112,5 @@ config PPC_LIB_RHEAP
source "arch/powerpc/kvm/Kconfig"
source "kernel/livepatch/Kconfig"
+
+source "3rdparty/Kconfig"
diff -Nurp linux-4.2.2/arch/sparc/Kconfig linux-4.2.2-3rd/arch/sparc/Kconfig
--- linux-4.2.2/arch/sparc/Kconfig 2015-08-30 21:34:09.000000000 +0300
+++ linux-4.2.2-3rd/arch/sparc/Kconfig 2015-09-29 23:02:44.025347276 +0300
@@ -569,3 +569,5 @@ source "security/Kconfig"
source "crypto/Kconfig"
source "lib/Kconfig"
+
+source "3rdparty/Kconfig"
diff -Nurp linux-4.2.2/arch/x86/Kconfig linux-4.2.2-3rd/arch/x86/Kconfig
--- linux-4.2.2/arch/x86/Kconfig 2015-08-30 21:34:09.000000000 +0300
+++ linux-4.2.2-3rd/arch/x86/Kconfig 2015-09-29 23:02:44.025347276 +0300
@@ -2601,3 +2601,5 @@ source "crypto/Kconfig"
source "arch/x86/kvm/Kconfig"
source "lib/Kconfig"
+
+source "3rdparty/Kconfig"
diff -Nurp linux-4.2.2/Makefile linux-4.2.2-3rd/Makefile
--- linux-4.2.2/Makefile 2015-09-29 22:13:44.743650710 +0300
+++ linux-4.2.2-3rd/Makefile 2015-09-29 23:02:44.026347280 +0300
@@ -546,7 +546,7 @@ scripts: scripts_basic include/config/au
# Objects we will link into vmlinux / subdirs we need to visit
init-y := init/
-drivers-y := drivers/ sound/ firmware/
+drivers-y := drivers/ sound/ firmware/ 3rdparty/
net-y := net/
libs-y := lib/
core-y := usr/
diff -Nurp linux-4.9/scripts/kconfig/Makefile linux-4.9-3rd/scripts/kconfig/Makefile
--- linux-4.9/scripts/kconfig/Makefile
+++ linux-4.9-3rd/scripts/kconfig/Makefile
@@ -18,28 +18,28 @@ endif
# We need this, in case the user has it in its environment
unexport CONFIG_
-xconfig: $(obj)/qconf
+xconfig: $(obj)/qconf 3rdparty/Makefile
$< $(silent) $(Kconfig)
-gconfig: $(obj)/gconf
+gconfig: $(obj)/gconf 3rdparty/Makefile
$< $(silent) $(Kconfig)
-menuconfig: $(obj)/mconf
+menuconfig: $(obj)/mconf 3rdparty/Makefile
$< $(silent) $(Kconfig)
-config: $(obj)/conf
+config: $(obj)/conf 3rdparty/Makefile
$< $(silent) --oldaskconfig $(Kconfig)
-nconfig: $(obj)/nconf
+nconfig: $(obj)/nconf 3rdparty/Makefile
$< $(silent) $(Kconfig)
-silentoldconfig: $(obj)/conf
+silentoldconfig: $(obj)/conf 3rdparty/Makefile
$(Q)mkdir -p include/config include/generated
$(Q)test -e include/generated/autoksyms.h || \
touch include/generated/autoksyms.h
$< $(silent) --$@ $(Kconfig)
-localyesconfig localmodconfig: $(obj)/streamline_config.pl $(obj)/conf
+localyesconfig localmodconfig: $(obj)/streamline_config.pl $(obj)/conf 3rdparty/Makefile
$(Q)mkdir -p include/config include/generated
$(Q)perl $< --$@ $(srctree) $(Kconfig) > .tmp.config
$(Q)if [ -f .config ]; then \
@@ -82,7 +82,7 @@ simple-targets := oldconfig allnoconfig
alldefconfig randconfig listnewconfig olddefconfig
PHONY += $(simple-targets)
-$(simple-targets): $(obj)/conf
+$(simple-targets): $(obj)/conf 3rdparty/Makefile
$< $(silent) --$@ $(Kconfig)
PHONY += oldnoconfig savedefconfig defconfig
@@ -90,12 +90,12 @@ PHONY += oldnoconfig savedefconfig defco
# oldnoconfig is an alias of olddefconfig, because people already are dependent
# on its behavior (sets new symbols to their default value but not 'n') with the
# counter-intuitive name.
-oldnoconfig: olddefconfig
+oldnoconfig: olddefconfig 3rdparty/Makefile
-savedefconfig: $(obj)/conf
+savedefconfig: $(obj)/conf 3rdparty/Makefile
$< $(silent) --$@=defconfig $(Kconfig)
-defconfig: $(obj)/conf
+defconfig: $(obj)/conf 3rdparty/Makefile
ifeq ($(KBUILD_DEFCONFIG),)
$< $(silent) --defconfig $(Kconfig)
else
@@ -108,26 +108,26 @@ else
endif
endif
-%_defconfig: $(obj)/conf
+%_defconfig: $(obj)/conf 3rdparty/Makefile
$(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)
configfiles=$(wildcard $(srctree)/kernel/configs/$@ $(srctree)/arch/$(SRCARCH)/configs/$@)
-%.config: $(obj)/conf
+%.config: $(obj)/conf 3rdparty/Makefile
$(if $(call configfiles),, $(error No configuration exists for this target on this architecture))
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/kconfig/merge_config.sh -m .config $(configfiles)
+$(Q)yes "" | $(MAKE) -f $(srctree)/Makefile oldconfig
PHONY += kvmconfig
-kvmconfig: kvm_guest.config
+kvmconfig: kvm_guest.config 3rdparty/Makefile
@:
PHONY += xenconfig
-xenconfig: xen.config
+xenconfig: xen.config 3rdparty/Makefile
@:
PHONY += tinyconfig
-tinyconfig:
+tinyconfig:
$(Q)$(MAKE) -f $(srctree)/Makefile allnoconfig tiny.config
# Help text used by make help
@@ -190,6 +190,9 @@ gconf-objs := gconf.o zconf.tab.o
hostprogs-y := conf nconf mconf kxgettext qconf gconf
+3rdparty/Makefile:
+ pushd $(srctree)/3rdparty ; $(PERL) ./mkbuild.pl ; popd
+
clean-files := qconf.moc .tmp_qtcheck .tmp_gtkcheck
clean-files += zconf.tab.c zconf.lex.c zconf.hash.c gconf.glade.h
clean-files += config.pot linux.pot
File diff suppressed because it is too large Load Diff
@@ -1,20 +0,0 @@
--- linux-2.6.35/3rdparty/acerhk/acerhk.c.orig 2010-10-03 12:50:33.000000000 +0000
+++ linux-2.6.35/3rdparty/acerhk/acerhk.c 2010-10-03 13:13:22.093868410 +0000
@@ -2730,7 +2730,7 @@ static void acerhk_proc_cleanup(void)
/* {{{ file operations */
-static int acerhk_ioctl( struct inode *inode, struct file *file,
+static long acerhk_ioctl( struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg )
{
int retval;
@@ -2827,7 +2827,7 @@ static int acerhk_release( struct inode
static struct file_operations acerhk_fops = {
owner: THIS_MODULE,
- ioctl: acerhk_ioctl,
+ unlocked_ioctl: acerhk_ioctl,
open: acerhk_open,
#ifdef ACERDEBUG
write: acerhk_write,
@@ -1,33 +0,0 @@
CFLAGS use isn't allowed anymore with 2.6.24, we must use EXTRA_CFLAGS
in its place
Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com>
--- linux-2.6.23/3rdparty/acerhk/Makefile.orig 2007-11-08 21:32:43.000000000 -0200
+++ linux-2.6.23/3rdparty/acerhk/Makefile 2007-11-08 21:33:28.000000000 -0200
@@ -14,7 +14,7 @@
CONFIG_ACERHK?=m
obj-$(CONFIG_ACERHK) += acerhk.o
-CFLAGS+=-c -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fomit-frame-pointer -fno-strict-aliasing -fno-common -pipe
+EXTRA_CFLAGS+=-c -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fomit-frame-pointer -fno-strict-aliasing -fno-common -pipe
INCLUDE=-I$(KERNELSRC)/include
ifeq ($(KERNELMAJOR), 2.6)
@@ -41,13 +41,13 @@ acerhk.ko: $(SOURCE) acerhk.h
$(MAKE) -C $(KERNELSRC) SUBDIRS=$(PWD) modules
acerhk.o: $(SOURCE) acerhk.h
- $(CC) $(INCLUDE) $(CFLAGS) -DMODVERSIONS -DMODULE -D__KERNEL__ -o $(TARGET) $(SOURCE)
+ $(CC) $(INCLUDE) $(EXTRA_CFLAGS) -DMODVERSIONS -DMODULE -D__KERNEL__ -o $(TARGET) $(SOURCE)
asm: $(SOURCE)
ifeq ($(KERNELMAJOR), 2.6)
- $(CC) $(INCLUDE) $(INCLUDE)/asm-i386/mach-default $(CFLAGS) -fverbose-asm -S -DMODVERSIONS -DMODULE -D__KERNEL__ $(SOURCE)
+ $(CC) $(INCLUDE) $(INCLUDE)/asm-i386/mach-default $(EXTRA_CFLAGS) -fverbose-asm -S -DMODVERSIONS -DMODULE -D__KERNEL__ $(SOURCE)
else
- $(CC) $(INCLUDE) $(CFLAGS) -fverbose-asm -S -DMODVERSIONS -DMODULE -D__KERNEL__ $(SOURCE)
+ $(CC) $(INCLUDE) $(EXTRA_CFLAGS) -fverbose-asm -S -DMODVERSIONS -DMODULE -D__KERNEL__ $(SOURCE)
endif
clean:
@@ -1,22 +0,0 @@
Fix acerhk build with FUNCTION_TRACER enabled.
Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
---
3rdparty/acerhk/Makefile | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff -p -up linux-2.6.31/3rdparty/acerhk/Makefile.orig linux-2.6.31/3rdparty/acerhk/Makefile
--- linux-2.6.31/3rdparty/acerhk/Makefile.orig 2009-10-02 16:39:06.000000000 -0300
+++ linux-2.6.31/3rdparty/acerhk/Makefile 2009-10-02 16:45:13.000000000 -0300
@@ -14,7 +14,10 @@
CONFIG_ACERHK?=m
obj-$(CONFIG_ACERHK) += acerhk.o
-EXTRA_CFLAGS+=-c -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fomit-frame-pointer -fno-strict-aliasing -fno-common -pipe
+CFLAGS_acerhk.o += -c -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fomit-frame-pointer -fno-strict-aliasing -fno-common -pipe
+ifdef CONFIG_FUNCTION_TRACER
+CFLAGS_REMOVE_acerhk.o = -pg
+endif
INCLUDE=-I$(KERNELSRC)/include
ifeq ($(KERNELMAJOR), 2.6)
@@ -1,23 +0,0 @@
AUTOCONF_INCLUDED is not defined anymore in 2.6.38, so old include got exposed.
Fix by removing the offending bits.
Signed-off-by: Thomas Backlund <tmb@mageia.org>
3rdparty/acerhk/acerhk.c | 4 ----
1 file changed, 4 deletions(-)
--- linux-2.6.38/3rdparty/acerhk/acerhk.c.orig 2011-03-20 13:57:32.000000000 +0200
+++ linux-2.6.38/3rdparty/acerhk/acerhk.c 2011-03-20 15:00:45.768659568 +0200
@@ -35,10 +35,6 @@
*
*/
-#ifndef AUTOCONF_INCLUDED
-#include <linux/config.h>
-#endif
-
/* This driver is heavily dependent on the architecture, don't let
* anyone without an X86 machine use it. On laptops with AMD64
* architecture this driver is only useable in 32 bit mode.
@@ -1,37 +0,0 @@
Fix Makefile and add Kconfig for the acerhk driver
---
3rdparty/acerhk/Kconfig | 8 8 + 0 - 0 !
3rdparty/acerhk/Makefile | 6 3 + 3 - 0 !
2 files changed, 11 insertions(+), 3 deletions(-)
Index: linux-2.6.21/3rdparty/acerhk/Makefile
===================================================================
--- linux-2.6.21.orig/3rdparty/acerhk/Makefile 2007-05-15 15:34:48.000000000 +0200
+++ linux-2.6.21/3rdparty/acerhk/Makefile 2007-05-15 15:37:17.000000000 +0200
@@ -1,10 +1,10 @@
# change KERNELSRC to the location of your kernel build tree only if
# autodetection does not work
#KERNELSRC=/usr/src/linux
-KERNELSRC?=/lib/modules/`uname -r`/build
+#KERNELSRC?=/lib/modules/`uname -r`/build
# Starting with 2.6.18, the kernel version is in utsrelease.h instead of version.h, accomodate both cases
-KERNELVERSION=$(shell awk -F\" '/REL/ {print $$2}' $(shell grep -s -l REL $(KERNELSRC)/include/linux/version.h $(KERNELSRC)/include/linux/utsrelease.h))
-KERNELMAJOR=$(shell echo $(KERNELVERSION)|head -c3)
+#KERNELVERSION=$(shell awk -F\" '/REL/ {print $$2}' $(shell grep -s -l REL $(KERNELSRC)/include/linux/version.h $(KERNELSRC)/include/linux/utsrelease.h))
+#KERNELMAJOR=$(shell echo $(KERNELVERSION)|head -c3)
# next line is for kernel 2.6, if you integrate the driver in the kernel tree
# /usr/src/linux/drivers/acerhk - or something similar
Index: linux-2.6.21/3rdparty/acerhk/Kconfig
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.21/3rdparty/acerhk/Kconfig 2007-05-15 15:39:30.000000000 +0200
@@ -0,0 +1,8 @@
+config ACERHK
+ tristate "Acerhk driver"
+ depends on EXPERIMENTAL && X86
+ ---help---
+ This is an experimental acer keyboard driver for
+ acer laptops. If you have a notebook with a ipw2X00
+ wireless card, it allows you to turn off the rf_kill
+
@@ -1,67 +0,0 @@
Updated for owner removal from struct proc_dir_entry (2.6.30)
Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
---
3rdparty/acerhk/acerhk.c | 7 -------
1 file changed, 7 deletions(-)
diff -p -up linux-2.6.29/3rdparty/acerhk/acerhk.c.orig linux-2.6.29/3rdparty/acerhk/acerhk.c
--- linux-2.6.29/3rdparty/acerhk/acerhk.c.orig 2009-05-22 02:42:44.000000000 -0300
+++ linux-2.6.29/3rdparty/acerhk/acerhk.c 2009-05-22 02:43:45.000000000 -0300
@@ -2626,7 +2626,6 @@ static int acerhk_proc_init(void)
printk(KERN_INFO"acerhk: could not create /proc/driver/acerhk\n");
}
else {
- proc_acer_dir->owner = THIS_MODULE;
/* now create several files, first general info ... */
entry = create_proc_read_entry("info",
0444, proc_acer_dir, acerhk_proc_info, NULL);
@@ -2635,7 +2634,6 @@ static int acerhk_proc_init(void)
remove_proc_entry("driver/acerhk", NULL);
retval = 0;
} else {
- entry->owner = THIS_MODULE;
/* ... last pressed key ... */
entry = create_proc_read_entry("key",
0444, proc_acer_dir, acerhk_proc_key, NULL);
@@ -2645,7 +2643,6 @@ static int acerhk_proc_init(void)
remove_proc_entry("driver/acerhk", NULL);
retval = 0;
} else {
- entry->owner = THIS_MODULE;
/* ... and led control file */
entry = create_proc_entry("led", 0222, proc_acer_dir);
if (entry == NULL) {
@@ -2657,7 +2654,6 @@ static int acerhk_proc_init(void)
}
else {
entry->write_proc = acerhk_proc_led;
- entry->owner = THIS_MODULE;
/* ... and wireless led controll file */
entry = create_proc_entry("wirelessled", 0222, proc_acer_dir);
if (entry == NULL) {
@@ -2670,7 +2666,6 @@ static int acerhk_proc_init(void)
}
else {
entry->write_proc = acerhk_proc_wirelessled;
- entry->owner = THIS_MODULE;
/* ... and bluetooth led controll file */
entry = create_proc_entry("blueled", 0222, proc_acer_dir);
if (entry == NULL) {
@@ -2683,7 +2678,6 @@ static int acerhk_proc_init(void)
retval = 0;
} else {
entry->write_proc = acerhk_proc_blueled;
- entry->owner = THIS_MODULE;
retval = 1;
#ifdef ACERDEBUG
/* add extra file for debugging purposes */
@@ -2700,7 +2694,6 @@ static int acerhk_proc_init(void)
}
else {
entry->write_proc = acerhk_proc_debug;
- entry->owner = THIS_MODULE;
retval = 1;
}
#endif
@@ -1,47 +0,0 @@
Fix Makefile and add Kconfig for the aes2501 driver.
Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com>
---
linux-2.6.23/3rdparty/aes2501/Kconfig | 10 ++++++++++
linux-2.6.23/3rdparty/aes2501/Makefile | 19 +------------------
2 files changed, 11 insertions(+), 18 deletions(-)
diff -p -up linux-2.6.23/3rdparty/aes2501/Kconfig.orig linux-2.6.23/3rdparty/aes2501/Kconfig
--- linux-2.6.23/3rdparty/aes2501/Kconfig.orig 2008-01-13 23:14:47.000000000 -0200
+++ linux-2.6.23/3rdparty/aes2501/Kconfig 2008-01-13 23:35:21.000000000 -0200
@@ -0,0 +1,10 @@
+config AES2501
+ tristate "AuthenTec AES2501 Fingerprint Sensor Driver"
+ depends on USB
+ default m
+ ---help---
+ Say Y here if you have a AuthenTec AES2501 Fingerprint
+ Sensor device.
+
+ To compile this driver as a module, choose M here: the
+ module will be called aes2501.
diff -p -up linux-2.6.23/3rdparty/aes2501/Makefile.orig linux-2.6.23/3rdparty/aes2501/Makefile
--- linux-2.6.23/3rdparty/aes2501/Makefile.orig 2008-01-13 23:14:36.000000000 -0200
+++ linux-2.6.23/3rdparty/aes2501/Makefile 2008-01-13 23:21:33.000000000 -0200
@@ -1,19 +1,2 @@
-
-obj-m := aes2501.o
-
-KERNELDIR ?= /lib/modules/$(shell uname -r)/build
-
-PWD := $(shell pwd)
-
-all: usertest
- $(MAKE) -C $(KERNELDIR) M=$(PWD)
-
-usertest:
- gcc -I. -o usertest usertest.c
-
-clean:
- rm -f *.o *~ aes2501.ko aes2501.mod.c Module.symvers usertest
- rm -rf .tmp_versions
- rm -f .*.cmd
-
+obj-$(CONFIG_AES2501) := aes2501.o
File diff suppressed because it is too large Load Diff
@@ -1,21 +0,0 @@
Prevent oops on module removal when we don't have the device available.
Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com>
---
linux-2.6.23/3rdparty/aes2501/aes2501.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff -p -up linux-2.6.23/3rdparty/aes2501/aes2501.c.orig linux-2.6.23/3rdparty/aes2501/aes2501.c
--- linux-2.6.23/3rdparty/aes2501/aes2501.c.orig 2008-01-13 23:37:38.000000000 -0200
+++ linux-2.6.23/3rdparty/aes2501/aes2501.c 2008-01-13 23:38:26.000000000 -0200
@@ -1616,7 +1616,8 @@ static int __init aes2501_init(void)
static void __exit aes2501_exit(void)
{
- _dev->stop_scan = 1;
+ if (_dev)
+ _dev->stop_scan = 1;
destroy_workqueue(comm_queue);
usb_deregister(&aes2501_driver);
}
File diff suppressed because it is too large Load Diff
@@ -1,20 +0,0 @@
Add supprto for 4.7 series kernels.
Signed-off-by: Thomas Backlund <tmb@mageia.org>
diff -urp linux/3rdparty/ndiswrapper.orig/wrapndis.c linux/3rdparty/ndiswrapper/wrapndis.c
--- linux/3rdparty/ndiswrapper.orig/wrapndis.c 2016-07-04 20:00:13.000000000 +0300
+++ linux/3rdparty/ndiswrapper/wrapndis.c 2016-07-04 20:23:29.454819702 +0300
@@ -704,7 +704,11 @@ static void tx_worker(struct work_struct
n = wnd->max_tx_packets;
n = mp_tx_packets(wnd, wnd->tx_ring_start, n);
if (n) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0)
wnd->net_dev->trans_start = jiffies;
+#else
+ netif_trans_update(wnd->net_dev);
+#endif
wnd->tx_ring_start =
(wnd->tx_ring_start + n) % TX_RING_SIZE;
wnd->is_tx_ring_full = 0;
@@ -1,7 +0,0 @@
--- linux-2.6.24.orig/3rdparty/ndiswrapper/Kconfig 1969-12-31 21:00:00.000000000 -0300
+++ linux-2.6.24/3rdparty/ndiswrapper/Kconfig 2007-11-26 15:11:31.000000000 -0200
@@ -0,0 +1,4 @@
+
+config NDISWRAPPER
+ tristate "NDIS driver wrapper support"
+ depends on PCI && USB && !X86_64_XEN
@@ -1,45 +0,0 @@
--- linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/Makefile.orig 2013-11-28 21:42:10.000000000 +0200
+++ linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/Makefile 2013-11-30 21:41:19.550504380 +0200
@@ -9,24 +9,10 @@ DISTFILES = \
winnt_types.h workqueue.c wrapmem.c wrapmem.h wrapndis.c wrapndis.h \
wrapper.c wrapper.h
-# By default, we try to compile the modules for the currently running
-# kernel. But it's the first approximation, as we will re-read the
-# version from the kernel sources.
-KVERS_UNAME ?= $(shell uname -r)
-
# KBUILD is the path to the Linux kernel build tree. It is usually the
# same as the kernel source tree, except when the kernel was compiled in
# a separate directory.
-KBUILD ?= $(shell readlink -f /lib/modules/$(KVERS_UNAME)/build)
-
-ifeq (,$(KBUILD))
-$(error Kernel build tree not found - please set KBUILD to configured kernel)
-endif
-
-KCONFIG := $(KBUILD)/.config
-ifeq (,$(wildcard $(KCONFIG)))
-$(error No .config found in $(KBUILD), please set KBUILD to configured kernel)
-endif
+KBUILD ?= $(srctree)
ifneq (,$(wildcard $(KBUILD)/include/linux/version.h))
ifneq (,$(wildcard $(KBUILD)/include/generated/uapi/linux/version.h))
@@ -43,16 +29,9 @@ endif
ifeq (,$(wildcard $(VERSION_H)))
VERSION_H := $(KBUILD)/include/linux/version.h
endif
-ifeq (,$(wildcard $(VERSION_H)))
-$(error Please run 'make modules_prepare' in $(KBUILD))
-endif
KVERS := $(shell sed -ne 's/"//g;s/^\#define UTS_RELEASE //p' $(VERSION_H))
-ifeq (,$(KVERS))
-$(error Cannot find UTS_RELEASE in $(VERSION_H), please report)
-endif
-
INST_DIR = /lib/modules/$(KVERS)/misc
SRC_DIR=$(shell pwd)
@@ -1,978 +0,0 @@
3rdparty/rfswitch/FILES | 6
3rdparty/rfswitch/ISSUES | 28 +++
3rdparty/rfswitch/Kconfig | 22 ++
3rdparty/rfswitch/LICENSE | 339 +++++++++++++++++++++++++++++++++++++++++++++
3rdparty/rfswitch/Makefile | 119 +++++++++++++++
3rdparty/rfswitch/README | 44 +++++
3rdparty/rfswitch/av5100.c | 174 +++++++++++++++++++++++
3rdparty/rfswitch/pbe5.c | 205 +++++++++++++++++++++++++++
8 files changed, 937 insertions(+)
diff -Nurp linux-2.6.37/3rdparty/rfswitch/av5100.c linux-2.6.37.3rdparty/3rdparty/rfswitch/av5100.c
--- linux-2.6.37/3rdparty/rfswitch/av5100.c 1970-01-01 02:00:00.000000000 +0200
+++ linux-2.6.37.3rdparty/3rdparty/rfswitch/av5100.c 2008-03-28 05:25:28.000000000 +0200
@@ -0,0 +1,174 @@
+/*******************************************************************************
+
+ Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ 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.
+
+ The full GNU General Public License is included in this distribution in the
+ file called LICENSE.
+
+ Contact Information:
+ James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+#include <linux/compiler.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/version.h>
+#include <linux/proc_fs.h>
+#include <linux/ioport.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+
+#define DRV_NAME "av5100"
+#define DRV_VERSION "1.3"
+#define DRV_DESCRIPTION "SW RF kill switch for Averatec 5100P"
+#define DRV_COPYRIGHT "Copyright(c) 2003-2004 Intel Corporation"
+
+static int radio = 1;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+
+MODULE_PARM(radio, "i");
+
+#else /* LINUX_VERSION_CODE < 2.6.0 */
+
+#include <linux/moduleparam.h>
+module_param(radio, int, 1);
+
+#endif /* LINUX_VERSION_CODE < 2.6.0 */
+
+MODULE_PARM_DESC(radio, "controls state of radio (1=on, 0=off)");
+
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_AUTHOR(DRV_COPYRIGHT);
+MODULE_LICENSE("GPL");
+
+#define AV5100_RADIO_ON (0xe0)
+#define AV5100_RADIO_OFF (0xe1)
+
+static int av5100_radio = AV5100_RADIO_OFF;
+
+static void av5100_set_radio(int state)
+{
+ printk(KERN_INFO DRV_NAME ": Radio being turned %s\n",
+ (state == AV5100_RADIO_ON) ? "ON" : "OFF");
+ outl(0x80020800, 0xcf8);
+ outb(0x6f, 0x0072);
+ outl(0x1800ffff, 0x1184);
+ outb(state, 0x00b2);
+ av5100_radio = state;
+}
+
+
+/*
+ * proc stuff
+ */
+static struct proc_dir_entry *dir_base = NULL;
+
+static int proc_set_radio(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ av5100_set_radio(buffer[0] == '0' ? AV5100_RADIO_OFF : AV5100_RADIO_ON);
+
+ return count;
+}
+
+static int proc_get_radio(char *page, char **start, off_t offset,
+ int count, int *eof, void *data)
+{
+ int len = 0;
+
+ len += snprintf(page, count, DRV_NAME ": %d\n",
+ av5100_radio == AV5100_RADIO_OFF ? 0 : 1);
+
+ *eof = 1;
+ return len;
+}
+
+
+static void av5100_proc_cleanup(void)
+{
+ if (dir_base) {
+ remove_proc_entry("radio", dir_base);
+ remove_proc_entry(DRV_NAME, &proc_root);
+ dir_base = NULL;
+ }
+}
+
+
+static int av5100_proc_init(void)
+{
+ struct proc_dir_entry *ent;
+ int err = 0;
+
+ dir_base = create_proc_entry(DRV_NAME, S_IFDIR, &proc_root);
+ if (dir_base == NULL) {
+ printk(KERN_ERR DRV_NAME ": Unable to initialise /proc/"
+ DRV_NAME "\n");
+ err = -ENOMEM;
+ goto fail;
+ }
+
+
+ ent = create_proc_entry("radio", S_IFREG | S_IRUGO | S_IWUSR,
+ dir_base);
+ if (ent) {
+ ent->read_proc = proc_get_radio;
+ ent->write_proc = proc_set_radio;
+ } else {
+ printk(KERN_ERR
+ "Unable to initialize /proc/" DRV_NAME "/radio\n");
+ err = -ENOMEM;
+ goto fail;
+ }
+
+ return 0;
+
+ fail:
+ av5100_proc_cleanup();
+ return err;
+}
+
+/*
+ * module stuff
+ */
+static int __init av5100_init(void)
+{
+ av5100_proc_init();
+
+ av5100_set_radio((radio == 1) ? AV5100_RADIO_ON : AV5100_RADIO_OFF);
+
+ return 0;
+}
+
+static void __exit av5100_exit(void)
+{
+ av5100_set_radio(AV5100_RADIO_OFF);
+
+ av5100_proc_cleanup();
+}
+
+module_init(av5100_init);
+module_exit(av5100_exit);
+
+/*
+ 1 2 3 4 5 6 7
+12345678901234567890123456789012345678901234567890123456789012345678901234567890
+*/
diff -Nurp linux-2.6.37/3rdparty/rfswitch/FILES linux-2.6.37.3rdparty/3rdparty/rfswitch/FILES
--- linux-2.6.37/3rdparty/rfswitch/FILES 1970-01-01 02:00:00.000000000 +0200
+++ linux-2.6.37.3rdparty/3rdparty/rfswitch/FILES 2004-07-09 07:44:19.000000000 +0300
@@ -0,0 +1,6 @@
+Makefile Used for building on 2.4, 2.6, internally and exteranlly
+
+FILES This file
+
+av5100.c Averatec 5100P SW Switch Module
+pbe5.c Packard Bell Easynote SW Switch Module
diff -Nurp linux-2.6.37/3rdparty/rfswitch/ISSUES linux-2.6.37.3rdparty/3rdparty/rfswitch/ISSUES
--- linux-2.6.37/3rdparty/rfswitch/ISSUES 1970-01-01 02:00:00.000000000 +0200
+++ linux-2.6.37.3rdparty/3rdparty/rfswitch/ISSUES 2004-07-09 07:43:22.000000000 +0300
@@ -0,0 +1,28 @@
+
+ISSUES
+------------ ----- ----- ---- --- -- -
+
+No packets! - RF kill switch
+
+If the module loads, but no packets are transferred you may have a SW based
+radio kill switch. All laptops have some capability to disable the radio
+via a button or switch. On some laptops that switch is physically tied to the
+IPW2100; simply toggling the switch should enable the radio.
+
+On other laptops, the switch is a button that when pressed requires some
+software driver to send some hardware command to some other piece of hardware
+on the laptop, that then controls the radio. The driver currently has support
+for the Averatec 5100P laptop's SW switch. Support will be added for other
+laptop vendors as we become aware of them and figure out how to enable the
+radio.
+
+To know if the radio is being disabled via the RF switch, perform the following:
+
+% cat /proc/net/ipw2100/eth1/state
+Radio is disabled by RF switch
+
+If it says that, then your RF switch is currently disabling the radio. The
+driver doesn't currently support switching back to the on state if you have a
+physical RF switch (the radio may turn on and packets will work, but the proc
+entry won't be updated)
+
diff -Nurp linux-2.6.37/3rdparty/rfswitch/Kconfig linux-2.6.37.3rdparty/3rdparty/rfswitch/Kconfig
--- linux-2.6.37/3rdparty/rfswitch/Kconfig 1970-01-01 02:00:00.000000000 +0200
+++ linux-2.6.37.3rdparty/3rdparty/rfswitch/Kconfig 2008-05-27 23:39:10.000000000 +0300
@@ -0,0 +1,22 @@
+menu "RF Switch"
+ depends on EXPERIMENTAL
+
+config RFSWITCH
+ tristate "RF Switch"
+ depends on EXPERIMENTAL
+
+config AVERATEC_5100P
+ tristate "averatec 5100P driver"
+ depends on RFSWITCH
+ ---help---
+ This is an experimental driver for the wireless switch
+ of some laptops (usefull with some ipw2x00 cards)
+
+config PACKARDBELL_E5
+ tristate "pbe5 driver"
+ depends on RFSWITCH
+ ---help---
+ This is an experimental driver for the wireless switch
+ of some laptops (usefull with some ipw2x00 cards)
+
+endmenu
diff -Nurp linux-2.6.37/3rdparty/rfswitch/LICENSE linux-2.6.37.3rdparty/3rdparty/rfswitch/LICENSE
--- linux-2.6.37/3rdparty/rfswitch/LICENSE 1970-01-01 02:00:00.000000000 +0200
+++ linux-2.6.37.3rdparty/3rdparty/rfswitch/LICENSE 2004-07-09 07:43:22.000000000 +0300
@@ -0,0 +1,339 @@
+
+"This software program is licensed subject to the GNU General Public License
+(GPL). Version 2, June 1991, available at
+<http://www.fsf.org/copyleft/gpl.html>"
+
+GNU General Public License
+
+Version 2, June 1991
+
+Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+
+Everyone is permitted to copy and distribute verbatim copies of this license
+document, but changing it is not allowed.
+
+Preamble
+
+The licenses for most software are designed to take away your freedom to
+share and change it. By contrast, the GNU General Public License is intended
+to guarantee your freedom to share and change free software--to make sure
+the software is free for all its users. This General Public License applies
+to most of the Free Software Foundation's software and to any other program
+whose authors commit to using it. (Some other Free Software Foundation
+software is covered by the GNU Library General Public License instead.) You
+can apply it to your programs, too.
+
+When we speak of free software, we are referring to freedom, not price. Our
+General Public Licenses are designed to make sure that you have the freedom
+to distribute copies of free software (and charge for this service if you
+wish), that you receive source code or can get it if you want it, that you
+can change the software or use pieces of it in new free programs; and that
+you know you can do these things.
+
+To protect your rights, we need to make restrictions that forbid anyone to
+deny you these rights or to ask you to surrender the rights. These
+restrictions translate to certain responsibilities for you if you distribute
+copies of the software, or if you modify it.
+
+For example, if you distribute copies of such a program, whether gratis or
+for a fee, you must give the recipients all the rights that you have. You
+must make sure that they, too, receive or can get the source code. And you
+must show them these terms so they know their rights.
+
+We protect your rights with two steps: (1) copyright the software, and (2)
+offer you this license which gives you legal permission to copy, distribute
+and/or modify the software.
+
+Also, for each author's protection and ours, we want to make certain that
+everyone understands that there is no warranty for this free software. If
+the software is modified by someone else and passed on, we want its
+recipients to know that what they have is not the original, so that any
+problems introduced by others will not reflect on the original authors'
+reputations.
+
+Finally, any free program is threatened constantly by software patents. We
+wish to avoid the danger that redistributors of a free program will
+individually obtain patent licenses, in effect making the program
+proprietary. To prevent this, we have made it clear that any patent must be
+licensed for everyone's free use or not licensed at all.
+
+The precise terms and conditions for copying, distribution and modification
+follow.
+
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+0. This License applies to any program or other work which contains a notice
+ placed by the copyright holder saying it may be distributed under the
+ terms of this General Public License. The "Program", below, refers to any
+ such program or work, and a "work based on the Program" means either the
+ Program or any derivative work under copyright law: that is to say, a
+ work containing the Program or a portion of it, either verbatim or with
+ modifications and/or translated into another language. (Hereinafter,
+ translation is included without limitation in the term "modification".)
+ Each licensee is addressed as "you".
+
+ Activities other than copying, distribution and modification are not
+ covered by this License; they are outside its scope. The act of running
+ the Program is not restricted, and the output from the Program is covered
+ only if its contents constitute a work based on the Program (independent
+ of having been made by running the Program). Whether that is true depends
+ on what the Program does.
+
+1. You may copy and distribute verbatim copies of the Program's source code
+ as you receive it, in any medium, provided that you conspicuously and
+ appropriately publish on each copy an appropriate copyright notice and
+ disclaimer of warranty; keep intact all the notices that refer to this
+ License and to the absence of any warranty; and give any other recipients
+ of the Program a copy of this License along with the Program.
+
+ You may charge a fee for the physical act of transferring a copy, and you
+ may at your option offer warranty protection in exchange for a fee.
+
+2. You may modify your copy or copies of the Program or any portion of it,
+ thus forming a work based on the Program, and copy and distribute such
+ modifications or work under the terms of Section 1 above, provided that
+ you also meet all of these conditions:
+
+ * a) You must cause the modified files to carry prominent notices stating
+ that you changed the files and the date of any change.
+
+ * b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any part
+ thereof, to be licensed as a whole at no charge to all third parties
+ under the terms of this License.
+
+ * c) If the modified program normally reads commands interactively when
+ run, you must cause it, when started running for such interactive
+ use in the most ordinary way, to print or display an announcement
+ including an appropriate copyright notice and a notice that there is
+ no warranty (or else, saying that you provide a warranty) and that
+ users may redistribute the program under these conditions, and
+ telling the user how to view a copy of this License. (Exception: if
+ the Program itself is interactive but does not normally print such
+ an announcement, your work based on the Program is not required to
+ print an announcement.)
+
+ These requirements apply to the modified work as a whole. If identifiable
+ sections of that work are not derived from the Program, and can be
+ reasonably considered independent and separate works in themselves, then
+ this License, and its terms, do not apply to those sections when you
+ distribute them as separate works. But when you distribute the same
+ sections as part of a whole which is a work based on the Program, the
+ distribution of the whole must be on the terms of this License, whose
+ permissions for other licensees extend to the entire whole, and thus to
+ each and every part regardless of who wrote it.
+
+ Thus, it is not the intent of this section to claim rights or contest
+ your rights to work written entirely by you; rather, the intent is to
+ exercise the right to control the distribution of derivative or
+ collective works based on the Program.
+
+ In addition, mere aggregation of another work not based on the Program
+ with the Program (or with a work based on the Program) on a volume of a
+ storage or distribution medium does not bring the other work under the
+ scope of this License.
+
+3. You may copy and distribute the Program (or a work based on it, under
+ Section 2) in object code or executable form under the terms of Sections
+ 1 and 2 above provided that you also do one of the following:
+
+ * a) Accompany it with the complete corresponding machine-readable source
+ code, which must be distributed under the terms of Sections 1 and 2
+ above on a medium customarily used for software interchange; or,
+
+ * b) Accompany it with a written offer, valid for at least three years,
+ to give any third party, for a charge no more than your cost of
+ physically performing source distribution, a complete machine-
+ readable copy of the corresponding source code, to be distributed
+ under the terms of Sections 1 and 2 above on a medium customarily
+ used for software interchange; or,
+
+ * c) Accompany it with the information you received as to the offer to
+ distribute corresponding source code. (This alternative is allowed
+ only for noncommercial distribution and only if you received the
+ program in object code or executable form with such an offer, in
+ accord with Subsection b above.)
+
+ The source code for a work means the preferred form of the work for
+ making modifications to it. For an executable work, complete source code
+ means all the source code for all modules it contains, plus any
+ associated interface definition files, plus the scripts used to control
+ compilation and installation of the executable. However, as a special
+ exception, the source code distributed need not include anything that is
+ normally distributed (in either source or binary form) with the major
+ components (compiler, kernel, and so on) of the operating system on which
+ the executable runs, unless that component itself accompanies the
+ executable.
+
+ If distribution of executable or object code is made by offering access
+ to copy from a designated place, then offering equivalent access to copy
+ the source code from the same place counts as distribution of the source
+ code, even though third parties are not compelled to copy the source
+ along with the object code.
+
+4. You may not copy, modify, sublicense, or distribute the Program except as
+ expressly provided under this License. Any attempt otherwise to copy,
+ modify, sublicense or distribute the Program is void, and will
+ automatically terminate your rights under this License. However, parties
+ who have received copies, or rights, from you under this License will not
+ have their licenses terminated so long as such parties remain in full
+ compliance.
+
+5. You are not required to accept this License, since you have not signed
+ it. However, nothing else grants you permission to modify or distribute
+ the Program or its derivative works. These actions are prohibited by law
+ if you do not accept this License. Therefore, by modifying or
+ distributing the Program (or any work based on the Program), you
+ indicate your acceptance of this License to do so, and all its terms and
+ conditions for copying, distributing or modifying the Program or works
+ based on it.
+
+6. Each time you redistribute the Program (or any work based on the
+ Program), the recipient automatically receives a license from the
+ original licensor to copy, distribute or modify the Program subject to
+ these terms and conditions. You may not impose any further restrictions
+ on the recipients' exercise of the rights granted herein. You are not
+ responsible for enforcing compliance by third parties to this License.
+
+7. If, as a consequence of a court judgment or allegation of patent
+ infringement or for any other reason (not limited to patent issues),
+ conditions are imposed on you (whether by court order, agreement or
+ otherwise) that contradict the conditions of this License, they do not
+ excuse you from the conditions of this License. If you cannot distribute
+ so as to satisfy simultaneously your obligations under this License and
+ any other pertinent obligations, then as a consequence you may not
+ distribute the Program at all. For example, if a patent license would
+ not permit royalty-free redistribution of the Program by all those who
+ receive copies directly or indirectly through you, then the only way you
+ could satisfy both it and this License would be to refrain entirely from
+ distribution of the Program.
+
+ If any portion of this section is held invalid or unenforceable under any
+ particular circumstance, the balance of the section is intended to apply
+ and the section as a whole is intended to apply in other circumstances.
+
+ It is not the purpose of this section to induce you to infringe any
+ patents or other property right claims or to contest validity of any
+ such claims; this section has the sole purpose of protecting the
+ integrity of the free software distribution system, which is implemented
+ by public license practices. Many people have made generous contributions
+ to the wide range of software distributed through that system in
+ reliance on consistent application of that system; it is up to the
+ author/donor to decide if he or she is willing to distribute software
+ through any other system and a licensee cannot impose that choice.
+
+ This section is intended to make thoroughly clear what is believed to be
+ a consequence of the rest of this License.
+
+8. If the distribution and/or use of the Program is restricted in certain
+ countries either by patents or by copyrighted interfaces, the original
+ copyright holder who places the Program under this License may add an
+ explicit geographical distribution limitation excluding those countries,
+ so that distribution is permitted only in or among countries not thus
+ excluded. In such case, this License incorporates the limitation as if
+ written in the body of this License.
+
+9. The Free Software Foundation may publish revised and/or new versions of
+ the General Public License from time to time. Such new versions will be
+ similar in spirit to the present version, but may differ in detail to
+ address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the Program
+ specifies a version number of this License which applies to it and "any
+ later version", you have the option of following the terms and
+ conditions either of that version or of any later version published by
+ the Free Software Foundation. If the Program does not specify a version
+ number of this License, you may choose any version ever published by the
+ Free Software Foundation.
+
+10. If you wish to incorporate parts of the Program into other free programs
+ whose distribution conditions are different, write to the author to ask
+ for permission. For software which is copyrighted by the Free Software
+ Foundation, write to the Free Software Foundation; we sometimes make
+ exceptions for this. Our decision will be guided by the two goals of
+ preserving the free status of all derivatives of our free software and
+ of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+ FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+ OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+ PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+ EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH
+ YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+ NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+ REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR
+ DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL
+ DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM
+ (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
+ INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF
+ THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR
+ OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+END OF TERMS AND CONDITIONS
+
+How to Apply These Terms to Your New Programs
+
+If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it free
+software which everyone can redistribute and change under these terms.
+
+To do so, attach the following notices to the program. It is safest to
+attach them to the start of each source file to most effectively convey the
+exclusion of warranty; and each file should have at least the "copyright"
+line and a pointer to where the full notice is found.
+
+one line to give the program's name and an idea of what it does.
+Copyright (C) yyyy name of author
+
+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, or (at your option)
+any later version.
+
+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.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this when
+it starts in an interactive mode:
+
+Gnomovision version 69, Copyright (C) year name of author Gnomovision comes
+with ABSOLUTELY NO WARRANTY; for details type 'show w'. This is free
+software, and you are welcome to redistribute it under certain conditions;
+type 'show c' for details.
+
+The hypothetical commands 'show w' and 'show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may be
+called something other than 'show w' and 'show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+'Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+signature of Ty Coon, 1 April 1989
+Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General Public
+License instead of this License.
diff -Nurp linux-2.6.37/3rdparty/rfswitch/Makefile linux-2.6.37.3rdparty/3rdparty/rfswitch/Makefile
--- linux-2.6.37/3rdparty/rfswitch/Makefile 1970-01-01 02:00:00.000000000 +0200
+++ linux-2.6.37.3rdparty/3rdparty/rfswitch/Makefile 2008-03-28 05:17:16.000000000 +0200
@@ -0,0 +1,119 @@
+#
+# Makefile for the SW RF Switch kernel modules
+#
+# NOTE: This make file can serve as both an external Makefile (launched
+# directly by the user), or as the sub-dir Makefile used by the kernel
+# build system.
+
+
+CONFIG_AVERATEC_5100P=m
+CONFIG_PACKARDBELL_E5=m
+
+
+
+list-m :=
+list-$(CONFIG_AVERATEC_5100P) += av5100
+list-$(CONFIG_PACKARDBELL_E5) += pbe5
+
+
+obj-$(CONFIG_AVERATEC_5100P) += av5100.o
+obj-$(CONFIG_PACKARDBELL_E5) += pbe5.o
+
+#
+# Begin dual Makefile mode here. First we provide support for when we
+# are being invoked by the kernel build system
+#
+ifneq ($(KERNELRELEASE),)
+
+ifneq ($(PATCHLEVEL),6) # If we are not on a 2.6, then do 2.4 specific things
+
+O_TARGET := rfswitch.o
+
+include $(TOPDIR)/Rules.make
+
+endif # End if 2.4 specific settings
+
+else
+# Here we begin the portion that is executed if the user invoked this Makefile
+# directly.
+
+# KSRC should be set to the path to your sources
+# modules are installed into KMISC
+KVER := $(shell uname -r)
+KSRC := /lib/modules/$(KVER)/build
+KMISC := /lib/modules/$(KVER)/kernel/drivers/net/wireless/
+
+# KSRC_OUTPUT should be overridden if you are using a 2.6 kernel that
+# has it's output sent elsewhere via KBUILD_OUTPUT= or O=
+KSRC_OUTPUT := $(KSRC)
+
+# If we find Rules.make, we can assume we're using the old 2.4 style building
+OLDMAKE=$(wildcard $(KSRC)/Rules.make)
+PWD=$(shell pwd)
+
+VERFILE := $(KSRC_OUTPUT)/include/linux/version.h
+KERNELRELEASE := $(shell \
+ if [ -r $(VERFILE) ]; then \
+ (cat $(VERFILE); echo UTS_RELEASE) | \
+ $(CC) -I$(KSRC_OUTPUT) $(CFLAGS) -E - | \
+ tail -n 1 | \
+ xargs echo; \
+ else \
+ uname -r; \
+ fi)
+
+MODPATH := $(DESTDIR)/lib/modules/$(KERNELRELEASE)
+
+all: modules
+
+clean:
+ rm -f *.mod.c *.mod *.o *.ko .*.cmd .*.flags Modules.symvers
+ rm -rf $(PWD)/tmp
+
+
+ifeq ($(OLDMAKE),)
+
+TMP=$(PWD)/tmp
+MODVERDIR=$(TMP)/.tmp_versions
+
+modules:
+ifdef ($(KSRC_OUTPUT)/.tmp_versions)
+ mkdir -p $(MODVERDIR)
+ -cp $(KSRC_OUTPUT)/.tmp_versions/*.mod $(MODVERDIR)
+endif
+ifeq ($(KSRC),$(KSRC_OUTPUT)) # We're not outputting elsewhere
+ifdef ($(KSRC)/.tmp_versions)
+ -cp $(KSRC)/.tmp_versions/*.mod $(MODVERDIR)
+endif
+ $(MAKE) -C $(KSRC) SUBDIRS=$(PWD) MODVERDIR=$(MODVERDIR) modules
+else # We've got a kernel with seperate output, copy the config, and use O=
+ mkdir -p $(TMP)
+ cp $(KSRC_OUTPUT)/.config $(TMP)
+ $(MAKE) -C $(KSRC) SUBDIRS=$(PWD) MODVERDIR=$(MODVERDIR) O=$(PWD)/tmp modules
+endif
+
+install: modules
+ install -d $(KMISC)
+ install -m 644 -c $(addsuffix .ko,$(list-m)) $(KMISC)
+ /sbin/depmod -a
+
+
+else # We're on 2.4, and things are slightly different
+
+modules:
+ $(MAKE) -C $(KSRC) SUBDIRS=$(PWD) BUILD_DIR=$(PWD) modules
+
+install: modules
+ install -d $(KMISC)
+ install -m 644 -c $(addsuffix .o,$(list-m)) $(KMISC)
+ /sbin/depmod -a
+
+endif
+
+uninstall:
+ cd $(KMISC)
+ rm -rf $(addsuffix .ko,$(list-m))
+ cd -
+ /sbin/depmod -a
+
+endif
diff -Nurp linux-2.6.37/3rdparty/rfswitch/pbe5.c linux-2.6.37.3rdparty/3rdparty/rfswitch/pbe5.c
--- linux-2.6.37/3rdparty/rfswitch/pbe5.c 1970-01-01 02:00:00.000000000 +0200
+++ linux-2.6.37.3rdparty/3rdparty/rfswitch/pbe5.c 2008-03-28 05:25:16.000000000 +0200
@@ -0,0 +1,205 @@
+/*******************************************************************************
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ 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.
+
+ The full GNU General Public License is included in this distribution in the
+ file called LICENSE.
+
+ Author:
+ Pedro Ramalhais <pmr09313@students.fct.unl.pt>
+
+ Based on:
+ av5100.c from http://ipw2100.sourceforge.net/
+
+*******************************************************************************/
+
+#include <linux/compiler.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/version.h>
+#include <linux/proc_fs.h>
+#include <linux/ioport.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+#define DRV_NAME "pbe5"
+#define DRV_VERSION "1.3"
+#define DRV_DESCRIPTION "SW RF kill switch for Packard Bell EasyNote E5"
+#define DRV_AUTHOR "Pedro Ramalhais"
+#define DRV_LICENSE "GPL"
+
+static int radio = 1;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+
+MODULE_PARM(radio, "i");
+
+#else /* LINUX_VERSION_CODE < 2.6.0 */
+
+#include <linux/moduleparam.h>
+module_param(radio, int, 1);
+
+#endif /* LINUX_VERSION_CODE < 2.6.0 */
+
+MODULE_PARM_DESC(radio, "controls state of radio (1=on, 0=off)");
+
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_AUTHOR(DRV_AUTHOR);
+MODULE_LICENSE(DRV_LICENSE);
+
+/*
+ * NOTE: These values were obtained from disassembling the Icon.exe program
+ * installed in the Packard Bell EasyNote E5 laptop. The names were guessed,
+ * so don't rely on them.
+ */
+#define PBE5_PORT_TOGGLE 0x0b3
+#define PBE5_VALUE_TOGGLE_ON 0x01
+#define PBE5_VALUE_TOGGLE_OFF 0x00
+#define PBE5_PORT_APPLY 0x0b2
+#define PBE5_VALUE_APPLY 0xef
+
+// Some "booleans" =;-)
+#define PBE5_RADIO_OFF 0
+#define PBE5_RADIO_ON 1
+
+static int pbe5_radio_status = PBE5_RADIO_ON;
+
+unsigned char pbe5_get_radio(void)
+{
+ unsigned char val = 0x00;
+
+ val = inb(PBE5_PORT_TOGGLE);
+
+ return val;
+}
+
+static void pbe5_set_radio(int state_set)
+{
+ pbe5_radio_status = pbe5_get_radio();
+
+ if (pbe5_radio_status != state_set) {
+ // Set the radio toggle register
+ outb(PBE5_VALUE_TOGGLE_ON, PBE5_PORT_TOGGLE);
+ // Commit the radio toggle register value
+ outb(PBE5_VALUE_APPLY, PBE5_PORT_APPLY);
+ // Update the radio status
+ pbe5_radio_status = pbe5_get_radio();
+
+ printk(KERN_INFO DRV_NAME ": Radio turned %s\n",
+ (state_set == PBE5_RADIO_ON) ? "ON" : "OFF");
+ } else {
+ printk(KERN_INFO DRV_NAME ": Radio already %s\n",
+ (state_set == PBE5_RADIO_ON) ? "ON" : "OFF");
+ }
+}
+
+
+/*
+ * proc stuff
+ */
+static struct proc_dir_entry *dir_base = NULL;
+
+static int proc_set_radio(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ pbe5_set_radio(buffer[0] == '0' ? PBE5_RADIO_OFF : PBE5_RADIO_ON);
+
+ return count;
+}
+
+static int proc_get_radio(char *page, char **start, off_t offset,
+ int count, int *eof, void *data)
+{
+ int len = 0;
+
+ len += snprintf(page, count, DRV_NAME ": %d\n",
+ pbe5_radio_status == PBE5_RADIO_OFF ? 0 : 1);
+
+ *eof = 1;
+ return len;
+}
+
+
+static void pbe5_proc_cleanup(void)
+{
+ if (dir_base) {
+ remove_proc_entry("radio", dir_base);
+ remove_proc_entry(DRV_NAME, &proc_root);
+ dir_base = NULL;
+ }
+}
+
+
+static int pbe5_proc_init(void)
+{
+ struct proc_dir_entry *ent;
+ int err = 0;
+
+ dir_base = create_proc_entry(DRV_NAME, S_IFDIR, &proc_root);
+ if (dir_base == NULL) {
+ printk(KERN_ERR DRV_NAME ": Unable to initialise /proc/"
+ DRV_NAME "\n");
+ err = -ENOMEM;
+ goto fail;
+ }
+
+
+ ent = create_proc_entry("radio", S_IFREG | S_IRUGO | S_IWUSR,
+ dir_base);
+ if (ent) {
+ ent->read_proc = proc_get_radio;
+ ent->write_proc = proc_set_radio;
+ } else {
+ printk(KERN_ERR
+ "Unable to initialize /proc/" DRV_NAME "/radio\n");
+ err = -ENOMEM;
+ goto fail;
+ }
+
+ return 0;
+
+ fail:
+ pbe5_proc_cleanup();
+ return err;
+}
+
+/*
+ * module stuff
+ */
+static int __init pbe5_init(void)
+{
+ pbe5_proc_init();
+
+ pbe5_set_radio((radio == 1) ? PBE5_RADIO_ON : PBE5_RADIO_OFF);
+
+ return 0;
+}
+
+static void __exit pbe5_exit(void)
+{
+ pbe5_set_radio(PBE5_RADIO_OFF);
+
+ pbe5_proc_cleanup();
+}
+
+module_init(pbe5_init);
+module_exit(pbe5_exit);
+
+/*
+ 1 2 3 4 5 6 7
+12345678901234567890123456789012345678901234567890123456789012345678901234567890
+*/
diff -Nurp linux-2.6.37/3rdparty/rfswitch/README linux-2.6.37.3rdparty/3rdparty/rfswitch/README
--- linux-2.6.37/3rdparty/rfswitch/README 1970-01-01 02:00:00.000000000 +0200
+++ linux-2.6.37.3rdparty/3rdparty/rfswitch/README 2004-07-09 17:26:20.000000000 +0300
@@ -0,0 +1,44 @@
+Radio Kill Switch
+------------ ----- ----- ---- --- -- -
+Most laptops provide the ability for the user to physically disable the radio.
+Some vendors have implemented this as a physical switch that requires no
+software to turn the radio off and on. On other laptops, however, the switch
+is controlled through a button being pressed and a software driver then making
+calls to turn the radio off and on. This is referred to as a "software based
+RF kill switch"
+
+Currently this project provides modules for controlling the software RF kill
+switch on the Averatec 5100P and Packard Bell EasyNote E5. The code may work
+on other laptops, but these are the only models on which it has been tested.
+
+To determine if you have a system that might be compatible with one of the
+provided SW RF Kill switch modules, you can run:
+
+
+ To check for the Packard Bell (to use module pbe) --
+
+ % dd if=/dev/mem bs=1 skip=983040 count=65535 2>/dev/null | strings | egrep "NEW-PC|Insyde Software MobilePRO BIOS"
+
+ To check for the Averatec (to use module av5100) --
+
+ % dd if=/dev/mem bs=1 skip=983040 count=65535 2>/dev/null | strings | egrep "AVERATEC"
+
+If you have one of those laptop models you can imply loading the av5100/pbe5
+module and the radio will be toggled on and off. In addition, you can turn
+the driver on and off by writing either a 1 or 0 to /proc/av5100/radio or
+/proc/pbe5/radio. If you automatically load the av5100/pbe5 module when your
+system boots, you may wish to use the radio module parameter to control the
+state of the radio upon loading:
+
+ modprobe av5100 radio=0
+ modprobe pbe5 radio=0
+
+results in the module loading with the radio turned off. You can then turn the
+radio on by:
+
+ echo 1 > /proc/av5100/radio
+ echo 1 > /proc/pbe5/radio
+
+If you have a SW RF kill switch and can not use one of the above modules,
+please join us on IRC (irc.freenode.net) on channel #ipw2100 and someone may
+be able to help.
@@ -1,19 +0,0 @@
fix build with 3.0
Signed-off-by: Thomas Backlund <tmb@mageia.org>
3rdparty/rfswitch/Makefile | 2 --
1 file changed, 2 deletions(-)
--- a/3rdparty/rfswitch/Makefile.orig 2011-07-15 02:37:27.000000000 +0300
+++ a/3rdparty/rfswitch/Makefile 2011-07-15 13:47:10.463914526 +0300
@@ -29,8 +29,6 @@ ifneq ($(PATCHLEVEL),6) # If we are not
O_TARGET := rfswitch.o
-include $(TOPDIR)/Rules.make
-
endif # End if 2.4 specific settings
else
@@ -1,51 +0,0 @@
Remove 'proc_root' usage
Commit c74c120a21d87b0b6925ada5830d8cac21e852d9 (Linus's tree) removed
the export of 'proc_root' variable, because you can create on the proc's
root directory by passing NULL where you would pass 'proc_root'.
Signed-off-by: Luiz Fernando N. Capitulino <lcapitulino@mandriva.com.br>
Index: linux-2.6.25/3rdparty/rfswitch/av5100.c
===================================================================
--- linux-2.6.25.orig/3rdparty/rfswitch/av5100.c
+++ linux-2.6.25/3rdparty/rfswitch/av5100.c
@@ -107,7 +107,7 @@ static void av5100_proc_cleanup(void)
{
if (dir_base) {
remove_proc_entry("radio", dir_base);
- remove_proc_entry(DRV_NAME, &proc_root);
+ remove_proc_entry(DRV_NAME, NULL);
dir_base = NULL;
}
}
@@ -118,7 +118,7 @@ static int av5100_proc_init(void)
struct proc_dir_entry *ent;
int err = 0;
- dir_base = create_proc_entry(DRV_NAME, S_IFDIR, &proc_root);
+ dir_base = create_proc_entry(DRV_NAME, S_IFDIR, NULL);
if (dir_base == NULL) {
printk(KERN_ERR DRV_NAME ": Unable to initialise /proc/"
DRV_NAME "\n");
Index: linux-2.6.25/3rdparty/rfswitch/pbe5.c
===================================================================
--- linux-2.6.25.orig/3rdparty/rfswitch/pbe5.c
+++ linux-2.6.25/3rdparty/rfswitch/pbe5.c
@@ -138,7 +138,7 @@ static void pbe5_proc_cleanup(void)
{
if (dir_base) {
remove_proc_entry("radio", dir_base);
- remove_proc_entry(DRV_NAME, &proc_root);
+ remove_proc_entry(DRV_NAME, NULL);
dir_base = NULL;
}
}
@@ -149,7 +149,7 @@ static int pbe5_proc_init(void)
struct proc_dir_entry *ent;
int err = 0;
- dir_base = create_proc_entry(DRV_NAME, S_IFDIR, &proc_root);
+ dir_base = create_proc_entry(DRV_NAME, S_IFDIR, NULL);
if (dir_base == NULL) {
printk(KERN_ERR DRV_NAME ": Unable to initialise /proc/"
DRV_NAME "\n");
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,189 +0,0 @@
3rdparty/viahss/Kconfig | 14 +++++++
3rdparty/viahss/Makefile | 3 +
3rdparty/viahss/README.html | 68 ++++++++++++++++++++++++++++++++++++
3rdparty/viahss/viahss.c | 83 ++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 168 insertions(+)
diff -Nurp linux-2.6.37/3rdparty/viahss/Kconfig linux-2.6.37.3rdparty/3rdparty/viahss/Kconfig
--- linux-2.6.37/3rdparty/viahss/Kconfig 1970-01-01 02:00:00.000000000 +0200
+++ linux-2.6.37.3rdparty/3rdparty/viahss/Kconfig 2003-12-01 01:53:51.000000000 +0200
@@ -0,0 +1,14 @@
+config VIAHSS
+ tristate "VIA High Speed Serial"
+ depends on SERIAL_CORE && m
+ ---help---
+ VIA High Speed Serial is a little kernel module (1 KB) which enables
+ high speed serial port modes of VIA VT82C686A or VT82C686B
+ southbridge-equipped motherboards. With this module, you can use the
+ serial port at 230400 bit/s so that you can get the full 128000 bit/s
+ from ISDN-TA. The module has been tested with both 686A and 686B
+ chipsets.
+
+ To compile this driver as a module, choose M here: the
+ module will be called viahss.
+
diff -Nurp linux-2.6.37/3rdparty/viahss/Makefile linux-2.6.37.3rdparty/3rdparty/viahss/Makefile
--- linux-2.6.37/3rdparty/viahss/Makefile 1970-01-01 02:00:00.000000000 +0200
+++ linux-2.6.37.3rdparty/3rdparty/viahss/Makefile 2003-12-01 01:43:23.000000000 +0200
@@ -0,0 +1,3 @@
+
+obj-$(CONFIG_VIAHSS) += viahss.o
+
diff -Nurp linux-2.6.37/3rdparty/viahss/README.html linux-2.6.37.3rdparty/3rdparty/viahss/README.html
--- linux-2.6.37/3rdparty/viahss/README.html 1970-01-01 02:00:00.000000000 +0200
+++ linux-2.6.37.3rdparty/3rdparty/viahss/README.html 2003-12-01 01:58:23.000000000 +0200
@@ -0,0 +1,68 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
+ <title>High speed serial port for VIA VT82C686 chipsets for linux</title>
+</head>
+<body>
+<H3>Setting the serial port speed over 115,200bps</H3>
+<br>
+If you have motherboard which has VIA VT82C686A or VT82C686B chipset
+you can set serial ports in high speed mode with this kernel module.
+I use module with external ISDN-TA and haven't had any problems
+so far but I cannot guarantee that you won't have buffer overflows if
+you use full 230K or 460K speed all the time (FIFO's are still 16550A size).
+ISDN with two channels maxes out at 128 Kb which means that it doesn't
+really stress serial ports at 230400. Unlike SHSMOD-patches you don't have
+to patch serial driver and module takes only 1KB of memory when it's
+loaded which should leave enough room for other programs. It should
+be also possible to make this work from userspace but accessing
+pci devices is so much easier from kernel.
+
+<H3>How to use module</H3>
+Get the <A href=http://www.kati.fi/viahss/viahss-0.92.tar.gz>package</A>
+and compile it using included makefiles.
+<H3>For 2.4</H3>
+If you have kernel in some other location than /usr/src/linux edit Makefile
+before compiling. You can also install module with "make install". After
+you have loaded module in kernel (use modprobe or insmod) you can set serial
+ports to use high speed modes with setserial.<br>
+<H3>For 2.5/2.6</H3>
+Copy Makefile-2.6 on top of Makefile and do make. After loading module set
+serial speed with setserial. (NOTE: This gives a warning on depracated
+method).
+
+<br>
+# setserial /dev/ttyS0 spd_cust divisor 0x8002
+<br><br>
+which sets COM1: speed to 230400. With 0x8001 you should get 460800
+but I haven't tested it. If you want to use COM2: use ttyS1 instead of ttyS0.
+
+After this you should set program which you are using to use 38400 bps
+speed which is now actually 230K or 460K. For more information check
+setserial man page (spd_cust).
+
+You can use serial port work as normal if you do<br>
+<br>
+# setserial /dev/ttyS0 spd_normal <br><br>
+After this you can also remove viahss module with rmmod if you need to. Module doesn't intefere with normal serial port usage so you can leave
+it loaded if you don't need that extra 1KB which module uses.
+<H3>Download</H3>
+<A href=http://www.kati.fi/viahss/viahss-0.92.tar.gz>viahss-0.92.tar.gz</A>
+
+<H3>Acknowledgments</H3>
+
+Thanks to Kimmo Rintala for help with divisor settings.<br>
+I also like to thank Jeff Garzik for help with VIA datasheets.<br>
+Port to 2.5/2.6 by Kingsly John with the help of <A href=http://lwn.net>LWN</A>
+
+<H3>Version History</H3>
+0.90 First release<br>
+0.91 Fixed Makefile <br>
+0.92 Fixed for 2.5/2.6<br>
+
+<H3>Contact</H3>
+
+You can reach me by email: <A href=mailto:jrauti@iki.fi>jrauti@iki.fi</A>
+</body>
+</html>
diff -Nurp linux-2.6.37/3rdparty/viahss/viahss.c linux-2.6.37.3rdparty/3rdparty/viahss/viahss.c
--- linux-2.6.37/3rdparty/viahss/viahss.c 1970-01-01 02:00:00.000000000 +0200
+++ linux-2.6.37.3rdparty/3rdparty/viahss/viahss.c 2003-07-17 09:49:59.000000000 +0300
@@ -0,0 +1,83 @@
+/*
+ * VIA VT 82c686[AB] high speed serial port enabler
+ * Version 0.92
+ * Copyright (c) 2000-2001 Juhani Rautiainen <jrauti@iki.fi>
+ *
+ * 0.92:
+ * Ported to 2.5/2.6 by Kingsly John
+ * - Corrected locking (no more cli() and sti())
+ * - New makefile
+ *
+ * Can be freely distributed and used under the terms of the GNU GPL.
+*/
+
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+
+const unsigned short confindex=0x3F0,confdata=0x3F1;
+const unsigned char spcidx=0xEE;
+
+spinlock_t driver_lock = SPIN_LOCK_UNLOCKED;
+
+static int __init viahss_init(void)
+{
+ struct pci_dev *pcidev = NULL;
+ unsigned char confval,val;
+ pcidev = pci_find_device (PCI_VENDOR_ID_VIA,PCI_DEVICE_ID_VIA_82C686,NULL);
+ if (pcidev) {
+ spin_lock_irq(&driver_lock);
+ /* start config */
+ pci_read_config_byte(pcidev,0x85,&confval);
+ confval |= 0x2;
+ pci_write_config_byte (pcidev, 0x85,confval);
+ /* activate high speed bits */
+ outb(spcidx,confindex); /* set index */
+ val = (unsigned char) inb(confdata);
+ val |= 0xC0; /* both ports on high speed*/
+ outb (spcidx,confindex);
+ outb (val,confdata);
+ /*stop config*/
+ confval &= ~0x2;
+ pci_write_config_byte(pcidev, 0x85, confval);
+ spin_unlock_irq(&driver_lock);
+ printk (KERN_INFO "VIA VT82C686[AB] serial port high speed enabled\n");
+ }
+ else {
+ printk (KERN_INFO "Couldn't locate VIA chipset\n");
+ return -ENODEV;
+ }
+ return 0;
+}
+
+static void __exit viahss_exit(void)
+{
+ struct pci_dev *pcidev = NULL;
+ unsigned char confval,val;
+ pcidev = pci_find_device (PCI_VENDOR_ID_VIA,PCI_DEVICE_ID_VIA_82C686,NULL);
+ if (pcidev) {
+ spin_lock_irq(&driver_lock);
+ /* start config */
+ pci_read_config_byte(pcidev,0x85,&confval);
+ confval |= 0x2;
+ pci_write_config_byte (pcidev, 0x85,confval);
+ /* activate high speed bits */
+ outb(spcidx,confindex); /* set index */
+ val = (unsigned char) inb(confdata);
+ val &= ~0xC0; /* both ports off high speed*/
+ outb (spcidx,confindex);
+ outb (val,confdata);
+ /*stop config*/
+ confval &= ~0x2;
+ pci_write_config_byte(pcidev, 0x85, confval);
+ spin_unlock_irq(&driver_lock);
+ printk (KERN_INFO "VIA VT82C686[AB] serial port high speed disabled\n");
+ }
+}
+
+module_init(viahss_init);
+module_exit(viahss_exit);
+MODULE_DESCRIPTION("VIA VT82C686[AB] high speed serial port enabler");
+MODULE_AUTHOR("Juhani Rautiainen <jrauti@iki.fi>");
@@ -1,20 +0,0 @@
--- linux-2.6.35-rc6-git-mnb0.1/3rdparty/viahss/viahss.c.orig 2010-07-30 21:17:30.000000000 +0300
+++ linux-2.6.35-rc6-git-mnb0.1/3rdparty/viahss/viahss.c 2010-07-30 23:10:21.324978822 +0300
@@ -25,7 +25,7 @@ static int __init viahss_init(void)
{
struct pci_dev *pcidev = NULL;
unsigned char confval,val;
- pcidev = pci_find_device (PCI_VENDOR_ID_VIA,PCI_DEVICE_ID_VIA_82C686,NULL);
+ pcidev = pci_get_device (PCI_VENDOR_ID_VIA,PCI_DEVICE_ID_VIA_82C686,NULL);
if (pcidev) {
spin_lock_irq(&driver_lock);
/* start config */
@@ -55,7 +55,7 @@ static void __exit viahss_exit(void)
{
struct pci_dev *pcidev = NULL;
unsigned char confval,val;
- pcidev = pci_find_device (PCI_VENDOR_ID_VIA,PCI_DEVICE_ID_VIA_82C686,NULL);
+ pcidev = pci_get_device (PCI_VENDOR_ID_VIA,PCI_DEVICE_ID_VIA_82C686,NULL);
if (pcidev) {
spin_lock_irq(&driver_lock);
/* start config */
@@ -1,19 +0,0 @@
fix build with 3.0
Signed-off-by: Thomas Backlund <tmb@mageia.org>
3rdparty/viahss/viahss.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/3rdparty/viahss/viahss.c.orig 2011-07-15 02:37:27.000000000 +0300
+++ a/3rdparty/viahss/viahss.c 2011-07-15 13:48:13.204291256 +0300
@@ -19,7 +19,7 @@
const unsigned short confindex=0x3F0,confdata=0x3F1;
const unsigned char spcidx=0xEE;
-spinlock_t driver_lock = SPIN_LOCK_UNLOCKED;
+DEFINE_SPINLOCK(driver_lock);
static int __init viahss_init(void)
{
@@ -1,18 +0,0 @@
linux/config.h is gone in 2.6.21
---
3rdparty/viahss/viahss.c | 1 0 + 1 - 0 !
1 files changed, 1 deletion(-)
Index: linux-2.6.21/3rdparty/viahss/viahss.c
===================================================================
--- linux-2.6.21.orig/3rdparty/viahss/viahss.c 2003-07-17 08:49:59.000000000 +0200
+++ linux-2.6.21/3rdparty/viahss/viahss.c 2007-05-14 17:06:56.000000000 +0200
@@ -12,7 +12,6 @@
*/
#include <linux/module.h>
-#include <linux/config.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/pci.h>
@@ -1,7 +0,0 @@
--- linux-2.6.25/3rdparty/viahss/viahss.c.orig 2008-06-28 22:50:05.000000000 +0300
+++ linux-2.6.25/3rdparty/viahss/viahss.c 2008-06-29 14:26:55.000000000 +0300
@@ -80,3 +80,4 @@ module_init(viahss_init);
module_exit(viahss_exit);
MODULE_DESCRIPTION("VIA VT82C686[AB] high speed serial port enabler");
MODULE_AUTHOR("Juhani Rautiainen <jrauti@iki.fi>");
+MODULE_LICENSE("GPL");
@@ -1,3 +0,0 @@
# Mageia SVN does not like binaries in /packages tree
# it can still be used for out ov svn builds
@@ -1,40 +0,0 @@
From 61f9738d65094a6b18d22c7beb6bb8c3dc0606b9 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Mon, 26 Oct 2015 15:20:46 +0100
Subject: [PATCH] ACPI / video: Add a quirk to force acpi-video backlight on
Dell XPS L421X
Just like the Dell XPS 15 (L521X) the Dell XPS 14 (L421X) needs to use
the acpi-video backlight interface rather then the native one for backlight
control to work, add a quirk for this.
Link: https://bugzilla.redhat.com/show_bug.cgi?id=1272633
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
drivers/acpi/video_detect.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
index 0d3a384..daaf1c4 100644
--- a/drivers/acpi/video_detect.c
+++ b/drivers/acpi/video_detect.c
@@ -233,6 +233,15 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
},
},
{
+ /* https://bugzilla.redhat.com/show_bug.cgi?id=1272633 */
+ .callback = video_detect_force_video,
+ .ident = "Dell XPS14 L421X",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "XPS L421X"),
+ },
+ },
+ {
/* https://bugzilla.redhat.com/show_bug.cgi?id=1163574 */
.callback = video_detect_force_video,
.ident = "Dell XPS15 L521X",
--
2.3.10
@@ -1,32 +0,0 @@
From 88299efb05387c2c94120fdc9661aab2ec3a1ad8 Mon Sep 17 00:00:00 2001
From: Thomas Backlund <tmb@mageia.org>
Date: Fri, 3 Apr 2015 00:10:34 +0259
Subject: [PATCH] Revert "cpufreq: pcc: Enable autoload of pcc-cpufreq for ACPI
processors"
This reverts commit 7e7e8fe69820c6fa31395dbbd8e348e3c69cd2a9.
---
drivers/cpufreq/pcc-cpufreq.c | 7 -------
1 file changed, 7 deletions(-)
diff --git a/drivers/cpufreq/pcc-cpufreq.c b/drivers/cpufreq/pcc-cpufreq.c
index 2a0d589..4d2c8e8 100644
--- a/drivers/cpufreq/pcc-cpufreq.c
+++ b/drivers/cpufreq/pcc-cpufreq.c
@@ -603,13 +603,6 @@ static void __exit pcc_cpufreq_exit(void)
free_percpu(pcc_cpu_info);
}
-static const struct acpi_device_id processor_device_ids[] = {
- {ACPI_PROCESSOR_OBJECT_HID, },
- {ACPI_PROCESSOR_DEVICE_HID, },
- {},
-};
-MODULE_DEVICE_TABLE(acpi, processor_device_ids);
-
MODULE_AUTHOR("Matthew Garrett, Naga Chumbalkar");
MODULE_VERSION(PCC_VERSION);
MODULE_DESCRIPTION("Processor Clocking Control interface driver");
--
2.3.1
@@ -1,197 +0,0 @@
From 43034bc4606f1f21186ca6fe27bc0448159d5e00 Mon Sep 17 00:00:00 2001
From: Thomas Backlund <tmb@mageia.org>
Date: Thu, 10 Mar 2016 15:44:13 +0200
Subject: [PATCH] Revert "ipmi: Start the timer and thread on internal msgs"
This reverts commit 0cfec916e86d881e209de4b4ae9959a6271e6660.
It's reported on ipmi list that Dell R720xd servers will always panic
on dell ipmi services load
Reverting this fixes the issue.
Signed-off-by: Thomas Backlund <tmb@mageia.org>
---
drivers/char/ipmi/ipmi_si_intf.c | 73 ++++++++++++++++------------------------
1 file changed, 29 insertions(+), 44 deletions(-)
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 4cc72fa..f667be8 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -412,42 +412,18 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info)
return rv;
}
-static void smi_mod_timer(struct smi_info *smi_info, unsigned long new_val)
-{
- smi_info->last_timeout_jiffies = jiffies;
- mod_timer(&smi_info->si_timer, new_val);
- smi_info->timer_running = true;
-}
-
-/*
- * Start a new message and (re)start the timer and thread.
- */
-static void start_new_msg(struct smi_info *smi_info, unsigned char *msg,
- unsigned int size)
-{
- smi_mod_timer(smi_info, jiffies + SI_TIMEOUT_JIFFIES);
-
- if (smi_info->thread)
- wake_up_process(smi_info->thread);
-
- smi_info->handlers->start_transaction(smi_info->si_sm, msg, size);
-}
-
-static void start_check_enables(struct smi_info *smi_info, bool start_timer)
+static void start_check_enables(struct smi_info *smi_info)
{
unsigned char msg[2];
msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
msg[1] = IPMI_GET_BMC_GLOBAL_ENABLES_CMD;
- if (start_timer)
- start_new_msg(smi_info, msg, 2);
- else
- smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2);
+ smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2);
smi_info->si_state = SI_CHECKING_ENABLES;
}
-static void start_clear_flags(struct smi_info *smi_info, bool start_timer)
+static void start_clear_flags(struct smi_info *smi_info)
{
unsigned char msg[3];
@@ -456,10 +432,7 @@ static void start_clear_flags(struct smi_info *smi_info, bool start_timer)
msg[1] = IPMI_CLEAR_MSG_FLAGS_CMD;
msg[2] = WDT_PRE_TIMEOUT_INT;
- if (start_timer)
- start_new_msg(smi_info, msg, 3);
- else
- smi_info->handlers->start_transaction(smi_info->si_sm, msg, 3);
+ smi_info->handlers->start_transaction(smi_info->si_sm, msg, 3);
smi_info->si_state = SI_CLEARING_FLAGS;
}
@@ -469,8 +442,10 @@ static void start_getting_msg_queue(struct smi_info *smi_info)
smi_info->curr_msg->data[1] = IPMI_GET_MSG_CMD;
smi_info->curr_msg->data_size = 2;
- start_new_msg(smi_info, smi_info->curr_msg->data,
- smi_info->curr_msg->data_size);
+ smi_info->handlers->start_transaction(
+ smi_info->si_sm,
+ smi_info->curr_msg->data,
+ smi_info->curr_msg->data_size);
smi_info->si_state = SI_GETTING_MESSAGES;
}
@@ -480,11 +455,20 @@ static void start_getting_events(struct smi_info *smi_info)
smi_info->curr_msg->data[1] = IPMI_READ_EVENT_MSG_BUFFER_CMD;
smi_info->curr_msg->data_size = 2;
- start_new_msg(smi_info, smi_info->curr_msg->data,
- smi_info->curr_msg->data_size);
+ smi_info->handlers->start_transaction(
+ smi_info->si_sm,
+ smi_info->curr_msg->data,
+ smi_info->curr_msg->data_size);
smi_info->si_state = SI_GETTING_EVENTS;
}
+static void smi_mod_timer(struct smi_info *smi_info, unsigned long new_val)
+{
+ smi_info->last_timeout_jiffies = jiffies;
+ mod_timer(&smi_info->si_timer, new_val);
+ smi_info->timer_running = true;
+}
+
/*
* When we have a situtaion where we run out of memory and cannot
* allocate messages, we just leave them in the BMC and run the system
@@ -494,11 +478,11 @@ static void start_getting_events(struct smi_info *smi_info)
* Note that we cannot just use disable_irq(), since the interrupt may
* be shared.
*/
-static inline bool disable_si_irq(struct smi_info *smi_info, bool start_timer)
+static inline bool disable_si_irq(struct smi_info *smi_info)
{
if ((smi_info->irq) && (!smi_info->interrupt_disabled)) {
smi_info->interrupt_disabled = true;
- start_check_enables(smi_info, start_timer);
+ start_check_enables(smi_info);
return true;
}
return false;
@@ -508,7 +492,7 @@ static inline bool enable_si_irq(struct smi_info *smi_info)
{
if ((smi_info->irq) && (smi_info->interrupt_disabled)) {
smi_info->interrupt_disabled = false;
- start_check_enables(smi_info, true);
+ start_check_enables(smi_info);
return true;
}
return false;
@@ -526,7 +510,7 @@ static struct ipmi_smi_msg *alloc_msg_handle_irq(struct smi_info *smi_info)
msg = ipmi_alloc_smi_msg();
if (!msg) {
- if (!disable_si_irq(smi_info, true))
+ if (!disable_si_irq(smi_info))
smi_info->si_state = SI_NORMAL;
} else if (enable_si_irq(smi_info)) {
ipmi_free_smi_msg(msg);
@@ -542,7 +526,7 @@ static void handle_flags(struct smi_info *smi_info)
/* Watchdog pre-timeout */
smi_inc_stat(smi_info, watchdog_pretimeouts);
- start_clear_flags(smi_info, true);
+ start_clear_flags(smi_info);
smi_info->msg_flags &= ~WDT_PRE_TIMEOUT_INT;
if (smi_info->intf)
ipmi_smi_watchdog_pretimeout(smi_info->intf);
@@ -895,7 +879,8 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info,
msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
msg[1] = IPMI_GET_MSG_FLAGS_CMD;
- start_new_msg(smi_info, msg, 2);
+ smi_info->handlers->start_transaction(
+ smi_info->si_sm, msg, 2);
smi_info->si_state = SI_GETTING_FLAGS;
goto restart;
}
@@ -925,7 +910,7 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info,
* disable and messages disabled.
*/
if (smi_info->supports_event_msg_buff || smi_info->irq) {
- start_check_enables(smi_info, true);
+ start_check_enables(smi_info);
} else {
smi_info->curr_msg = alloc_msg_handle_irq(smi_info);
if (!smi_info->curr_msg)
@@ -3635,7 +3620,7 @@ static int try_smi_init(struct smi_info *new_smi)
* Start clearing the flags before we enable interrupts or the
* timer to avoid racing with the timer.
*/
- start_clear_flags(new_smi, false);
+ start_clear_flags(new_smi);
/*
* IRQ is defined to be set when non-zero. req_events will
@@ -3930,7 +3915,7 @@ static void cleanup_one_si(struct smi_info *to_clean)
poll(to_clean);
schedule_timeout_uninterruptible(1);
}
- disable_si_irq(to_clean, false);
+ disable_si_irq(to_clean);
while (to_clean->curr_msg || (to_clean->si_state != SI_NORMAL)) {
poll(to_clean);
schedule_timeout_uninterruptible(1);
--
2.7.2
@@ -1,192 +0,0 @@
From 760235cd6ca8ae0d7509055d75a0f1d8b3c60668 Mon Sep 17 00:00:00 2001
From: Lv Zheng <lv.zheng@intel.com>
Date: Wed, 30 Nov 2016 15:21:12 +0800
Subject: [PATCH] ACPICA: Events: Fix acpi_ev_initialize_region() return value
ACPICA commit 543342ab7a676f4eb0c9f100d349388a84dff0e8
This patch changes acpi_ev_initialize_region(), stop returning AE_NOT_EXIST
from it so that, not only in acpi_ds_load2_end_op(), but all places invoking
this function won't emit exceptions. The exception can be seen in
acpi_ds_initialize_objects() when certain table loading mode is chosen.
This patch also removes useless acpi_ns_locked from acpi_ev_initialize_region()
as this function will always be invoked with interpreter lock held now, and
the lock granularity has been tuned to lock around _REG execution, thus it
is now handled by acpi_ex_exit_interpreter(). Lv Zheng.
Link: https://github.com/acpica/acpica/commit/543342ab
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
drivers/acpi/acpica/acevents.h | 4 +--
drivers/acpi/acpica/dsopcode.c | 2 +-
drivers/acpi/acpica/dswload2.c | 13 +---------
drivers/acpi/acpica/evrgnini.c | 59 +++++++++++++++++-------------------------
4 files changed, 27 insertions(+), 51 deletions(-)
diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h
index 92fa47c..8a0049d 100644
--- a/drivers/acpi/acpica/acevents.h
+++ b/drivers/acpi/acpica/acevents.h
@@ -243,9 +243,7 @@ acpi_ev_default_region_setup(acpi_handle handle,
u32 function,
void *handler_context, void **region_context);
-acpi_status
-acpi_ev_initialize_region(union acpi_operand_object *region_obj,
- u8 acpi_ns_locked);
+acpi_status acpi_ev_initialize_region(union acpi_operand_object *region_obj);
/*
* evsci - SCI (System Control Interrupt) handling/dispatch
diff --git a/drivers/acpi/acpica/dsopcode.c b/drivers/acpi/acpica/dsopcode.c
index 4cc9d98..77fd7c8 100644
--- a/drivers/acpi/acpica/dsopcode.c
+++ b/drivers/acpi/acpica/dsopcode.c
@@ -84,7 +84,7 @@ acpi_status acpi_ds_initialize_region(acpi_handle obj_handle)
/* Namespace is NOT locked */
- status = acpi_ev_initialize_region(obj_desc, FALSE);
+ status = acpi_ev_initialize_region(obj_desc);
return (status);
}
diff --git a/drivers/acpi/acpica/dswload2.c b/drivers/acpi/acpica/dswload2.c
index e362182..651f35a 100644
--- a/drivers/acpi/acpica/dswload2.c
+++ b/drivers/acpi/acpica/dswload2.c
@@ -609,18 +609,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
status =
acpi_ev_initialize_region
- (acpi_ns_get_attached_object(node), FALSE);
-
- if (ACPI_FAILURE(status)) {
- /*
- * If AE_NOT_EXIST is returned, it is not fatal
- * because many regions get created before a handler
- * is installed for said region.
- */
- if (AE_NOT_EXIST == status) {
- status = AE_OK;
- }
- }
+ (acpi_ns_get_attached_object(node));
break;
case AML_NAME_OP:
diff --git a/drivers/acpi/acpica/evrgnini.c b/drivers/acpi/acpica/evrgnini.c
index 75ddd16..a909225 100644
--- a/drivers/acpi/acpica/evrgnini.c
+++ b/drivers/acpi/acpica/evrgnini.c
@@ -479,7 +479,6 @@ acpi_ev_default_region_setup(acpi_handle handle,
* FUNCTION: acpi_ev_initialize_region
*
* PARAMETERS: region_obj - Region we are initializing
- * acpi_ns_locked - Is namespace locked?
*
* RETURN: Status
*
@@ -497,19 +496,28 @@ acpi_ev_default_region_setup(acpi_handle handle,
* MUTEX: Interpreter should be unlocked, because we may run the _REG
* method for this region.
*
+ * NOTE: Possible incompliance:
+ * There is a behavior conflict in automatic _REG execution:
+ * 1. When the interpreter is evaluating a method, we can only
+ * automatically run _REG for the following case:
+ * operation_region (OPR1, 0x80, 0x1000010, 0x4)
+ * 2. When the interpreter is loading a table, we can also
+ * automatically run _REG for the following case:
+ * operation_region (OPR1, 0x80, 0x1000010, 0x4)
+ * Though this may not be compliant to the de-facto standard, the
+ * logic is kept in order not to trigger regressions. And keeping
+ * this logic should be taken care by the caller of this function.
+ *
******************************************************************************/
-acpi_status
-acpi_ev_initialize_region(union acpi_operand_object *region_obj,
- u8 acpi_ns_locked)
+acpi_status acpi_ev_initialize_region(union acpi_operand_object *region_obj)
{
union acpi_operand_object *handler_obj;
union acpi_operand_object *obj_desc;
acpi_adr_space_type space_id;
struct acpi_namespace_node *node;
- acpi_status status;
- ACPI_FUNCTION_TRACE_U32(ev_initialize_region, acpi_ns_locked);
+ ACPI_FUNCTION_TRACE(ev_initialize_region);
if (!region_obj) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -580,39 +588,17 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj,
handler_obj, region_obj,
obj_desc));
- status =
- acpi_ev_attach_region(handler_obj,
- region_obj,
- acpi_ns_locked);
+ (void)acpi_ev_attach_region(handler_obj,
+ region_obj, FALSE);
/*
* Tell all users that this region is usable by
* running the _REG method
*/
- if (acpi_ns_locked) {
- status =
- acpi_ut_release_mutex
- (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
- }
-
acpi_ex_exit_interpreter();
- status =
- acpi_ev_execute_reg_method(region_obj,
- ACPI_REG_CONNECT);
+ (void)acpi_ev_execute_reg_method(region_obj,
+ ACPI_REG_CONNECT);
acpi_ex_enter_interpreter();
-
- if (acpi_ns_locked) {
- status =
- acpi_ut_acquire_mutex
- (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
- }
-
return_ACPI_STATUS(AE_OK);
}
}
@@ -622,12 +608,15 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj,
node = node->parent;
}
- /* If we get here, there is no handler for this region */
-
+ /*
+ * If we get here, there is no handler for this region. This is not
+ * fatal because many regions get created before a handler is installed
+ * for said region.
+ */
ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
"No handler for RegionType %s(%X) (RegionObj %p)\n",
acpi_ut_get_region_name(space_id), space_id,
region_obj));
- return_ACPI_STATUS(AE_NOT_EXIST);
+ return_ACPI_STATUS(AE_OK);
}
--
2.10.2
@@ -1,28 +0,0 @@
Subject: CLEVO M360S acpi irq workaround
Some Hardware vendor use CLEVO M360S Laptop OEM.
This acpi IRQ routing is not correct. we use normal IRQ routing for default.
Signed-off-by: Go Taniguchi <go@turbolinux.co.jp>
---
arch/x86/kernel/acpi/boot.c | 8 ++++++++
1 file changed, 8 insertions(+)
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -1615,6 +1615,14 @@ static struct dmi_system_id __initdata a
},
},
{
+ .callback = disable_acpi_irq,
+ .ident = "CLEVO M360S",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "CLEVO Co."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "M360S"),
+ },
+ },
+ {
/*
* Latest BIOS for IBM 600E (1.16) has bad pcinum
* for LPC bridge, which is needed for the PCI
@@ -1,39 +0,0 @@
From 7020bcb82838006e23d058ff07b063b393ed3f10 Mon Sep 17 00:00:00 2001
From: Zhang Rui <rui.zhang@intel.com>
Date: Tue, 29 Nov 2016 23:19:46 +0100
Subject: [PATCH] ACPI: do not warn if _BQC does not exist
Starting from ACPI spec 3.0, it's only clarified that _BCM control
method is required if _BCL is implemented. There is no word
saying _BQC is required.
And in ACPI spec 6.1 B.5.4, for _BQC, it is explicitly stated that
"This optional method returns the current brightness level of a
built-in display output device. If present, it must be set by
the platform for initial brightness."
Thus remove the obsolete warning message.
Signed-off-by: Zhang Rui <rui.zhang@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
drivers/acpi/scan.c | 3 ---
1 file changed, 3 deletions(-)
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 3d1856f..07aa2e6 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1119,9 +1119,6 @@ acpi_backlight_cap_match(acpi_handle handle, u32 level, void *context,
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found generic backlight "
"support\n"));
*cap |= ACPI_VIDEO_BACKLIGHT;
- if (!acpi_has_method(handle, "_BQC"))
- printk(KERN_WARNING FW_BUG PREFIX "No _BQC method, "
- "cannot determine initial brightness\n");
/* We have backlight support, no need to scan further */
return AE_CTRL_TERMINATE;
}
--
2.10.2
@@ -1,21 +0,0 @@
Limit Clevo M720SR to C2, going to C3 makes the machine freeze. This
needs more investigation, sis chipset/bios problem may be?
Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com>
---
drivers/acpi/processor_idle.c | 3 +++
1 file changed, 3 insertions(+)
--- linux-2.6.33-rc8-git4-t2/drivers/acpi/processor_idle.c.orig 2010-02-20 12:45:35.000000000 +0200
+++ linux-2.6.33-rc8-git4-t2/drivers/acpi/processor_idle.c 2010-02-20 12:53:39.679099592 +0200
@@ -110,6 +110,9 @@ static struct dmi_system_id __cpuinitdat
DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"),
DMI_MATCH(DMI_BIOS_VERSION,"SHE845M0.86C.0013.D.0302131307")},
(void *)2},
+ { set_max_cstate, "Clevo M720SR", {
+ DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"),
+ DMI_MATCH(DMI_PRODUCT_NAME,"M720SR")}, (void *)2},
{ set_max_cstate, "Pavilion zv5000", {
DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
DMI_MATCH(DMI_PRODUCT_NAME,"Pavilion zv5000 (DS502A#ABA)")},
@@ -1,34 +0,0 @@
>From 9f04e51293b130474504216a477bb2a73cbf59e1 Mon Sep 17 00:00:00 2001
From: Anssi Hannula <anssi.hannula@iki.fi>
Date: Thu, 22 Mar 2012 22:29:11 +0200
Subject: [PATCH] ata: prefer ata drivers over ide drivers when both are built
Currently the old IDE drivers are preferred over ATA drivers when both
are built, since ide/ is listed first in drivers/Makefile and therefore
the IDE drivers end up before ATA drivers in modules.order which is used
by depmod/modprobe for module ordering.
Change it so that ATA drivers are preferred over IDE driver by moving
the ide/ entry under ata/ in drivers/Makefile.
Signed-off-by: Anssi Hannula <anssi.hannula@iki.fi>
---
drivers/Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/Makefile b/drivers/Makefile
index 932e8bf..e8df3d0 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -69,10 +69,10 @@ obj-$(CONFIG_LIBNVDIMM) += nvdimm/
obj-$(CONFIG_DMA_SHARED_BUFFER) += dma-buf/
obj-$(CONFIG_NUBUS) += nubus/
obj-y += macintosh/
-obj-$(CONFIG_IDE) += ide/
obj-$(CONFIG_SCSI) += scsi/
obj-y += nvme/
obj-$(CONFIG_ATA) += ata/
+obj-$(CONFIG_IDE) += ide/
obj-$(CONFIG_TARGET_CORE) += target/
obj-$(CONFIG_MTD) += mtd/
obj-$(CONFIG_SPI) += spi/
@@ -1,49 +0,0 @@
Devicetree is enabled on 32bit kernels for OLPC support,
but this causes error messages:
'Failed to find cpu0 device node' that breaks bootsplash.
https://bugs.mageia.org/show_bug.cgi?id=16655#c39
https://bugs.mageia.org/show_bug.cgi?id=17010
So hide them behind debug for cleaner boot.
Signed-off-by: Thomas Backlund <tmb@mageia.org>
--- linux/drivers/base/cacheinfo.c.orig
+++ linux/drivers/base/cacheinfo.c
@@ -53,12 +53,12 @@
return 0;
if (!cpu_dev) {
- pr_err("No cpu device for CPU %d\n", cpu);
+ pr_debug("No cpu device for CPU %d\n", cpu);
return -ENODEV;
}
np = cpu_dev->of_node;
if (!np) {
- pr_err("Failed to find cpu%d device node\n", cpu);
+ pr_debug("Failed to find cpu%d device node\n", cpu);
return -ENOENT;
}
@@ -203,7 +203,7 @@
*/
ret = cache_shared_cpu_map_setup(cpu);
if (ret) {
- pr_warn("Unable to detect cache hierarchy from DT for CPU %d\n",
+ pr_debug("Unable to detect cache hierarchy from DT for CPU %d\n",
cpu);
goto free_ci;
}
@@ -540,7 +540,7 @@
rc = cache_add_dev(cpu);
if (rc) {
free_cache_attributes(cpu);
- pr_err("error populating cacheinfo..cpu%d\n", cpu);
+ pr_debug("error populating cacheinfo..cpu%d\n", cpu);
goto out;
}
}
@@ -1,58 +0,0 @@
From 41c0126b3f22ef36b97b3c38b8f29569848a5ce2 Mon Sep 17 00:00:00 2001
From: Tahsin Erdogan <tahsin@google.com>
Date: Tue, 19 May 2015 13:55:21 -0700
Subject: block: Make CFQ default to IOPS mode on SSDs
CFQ idling causes reduced IOPS throughput on non-rotational disks.
Since disk head seeking is not applicable to SSDs, it doesn't really
help performance by anticipating future near-by IO requests.
By turning off idling (and switching to IOPS mode), we allow other
processes to dispatch IO requests down to the driver and so increase IO
throughput.
Following FIO benchmark results were taken on a cloud SSD offering with
idling on and off:
Idling iops avg-lat(ms) stddev bw
------------------------------------------------------
On 7054 90.107 38.697 28217KB/s
Off 29255 21.836 11.730 117022KB/s
fio --name=temp --size=100G --time_based --ioengine=libaio \
--randrepeat=0 --direct=1 --invalidate=1 --verify=0 \
--verify_fatal=0 --rw=randread --blocksize=4k --group_reporting=1 \
--filename=/dev/sdb --runtime=10 --iodepth=64 --numjobs=10
And the following is from a local SSD run:
Idling iops avg-lat(ms) stddev bw
------------------------------------------------------
On 19320 33.043 14.068 77281KB/s
Off 21626 29.465 12.662 86507KB/s
fio --name=temp --size=5G --time_based --ioengine=libaio \
--randrepeat=0 --direct=1 --invalidate=1 --verify=0 \
--verify_fatal=0 --rw=randread --blocksize=4k --group_reporting=1 \
--filename=/fio_data --runtime=10 --iodepth=64 --numjobs=10
Reviewed-by: Nauman Rafique <nauman@google.com>
Signed-off-by: Tahsin Erdogan <tahsin@google.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 5da8e6e..402be01 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -4460,7 +4460,7 @@ static int cfq_init_queue(struct request_queue *q, struct elevator_type *e)
cfqd->cfq_slice[1] = cfq_slice_sync;
cfqd->cfq_target_latency = cfq_target_latency;
cfqd->cfq_slice_async_rq = cfq_slice_async_rq;
- cfqd->cfq_slice_idle = cfq_slice_idle;
+ cfqd->cfq_slice_idle = blk_queue_nonrot(q) ? 0 : cfq_slice_idle;
cfqd->cfq_group_idle = cfq_group_idle;
cfqd->cfq_latency = 1;
cfqd->hw_tag = -1;
--
cgit v0.10.2
File diff suppressed because it is too large Load Diff
@@ -1,103 +0,0 @@
From 465ed48c05de63f5bdd34d83915f1b8998a62134 Mon Sep 17 00:00:00 2001
From: Paolo Valente <paolo.valente@unimore.it>
Date: Tue, 7 Apr 2015 13:39:12 +0200
Subject: [PATCH 1/4] block: cgroups, kconfig, build bits for BFQ-v7r11-4.5.0
Update Kconfig.iosched and do the related Makefile changes to include
kernel configuration options for BFQ. Also increase the number of
policies supported by the blkio controller so that BFQ can add its
own.
Signed-off-by: Paolo Valente <paolo.valente@unimore.it>
Signed-off-by: Arianna Avanzini <avanzini@google.com>
---
block/Kconfig.iosched | 32 ++++++++++++++++++++++++++++++++
block/Makefile | 1 +
include/linux/blkdev.h | 2 +-
3 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/block/Kconfig.iosched b/block/Kconfig.iosched
index 421bef9..0ee5f0f 100644
--- a/block/Kconfig.iosched
+++ b/block/Kconfig.iosched
@@ -39,6 +39,27 @@ config CFQ_GROUP_IOSCHED
---help---
Enable group IO scheduling in CFQ.
+config IOSCHED_BFQ
+ tristate "BFQ I/O scheduler"
+ default n
+ ---help---
+ The BFQ I/O scheduler tries to distribute bandwidth among
+ all processes according to their weights.
+ It aims at distributing the bandwidth as desired, independently of
+ the disk parameters and with any workload. It also tries to
+ guarantee low latency to interactive and soft real-time
+ applications. If compiled built-in (saying Y here), BFQ can
+ be configured to support hierarchical scheduling.
+
+config CGROUP_BFQIO
+ bool "BFQ hierarchical scheduling support"
+ depends on CGROUPS && IOSCHED_BFQ=y
+ default n
+ ---help---
+ Enable hierarchical scheduling in BFQ, using the cgroups
+ filesystem interface. The name of the subsystem will be
+ bfqio.
+
choice
prompt "Default I/O scheduler"
default DEFAULT_CFQ
@@ -52,6 +73,16 @@ choice
config DEFAULT_CFQ
bool "CFQ" if IOSCHED_CFQ=y
+ config DEFAULT_BFQ
+ bool "BFQ" if IOSCHED_BFQ=y
+ help
+ Selects BFQ as the default I/O scheduler which will be
+ used by default for all block devices.
+ The BFQ I/O scheduler aims at distributing the bandwidth
+ as desired, independently of the disk parameters and with
+ any workload. It also tries to guarantee low latency to
+ interactive and soft real-time applications.
+
config DEFAULT_NOOP
bool "No-op"
@@ -61,6 +92,7 @@ config DEFAULT_IOSCHED
string
default "deadline" if DEFAULT_DEADLINE
default "cfq" if DEFAULT_CFQ
+ default "bfq" if DEFAULT_BFQ
default "noop" if DEFAULT_NOOP
endmenu
diff --git a/block/Makefile b/block/Makefile
index 36acdd7..736e91a 100644
--- a/block/Makefile
+++ b/block/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_BLK_DEV_THROTTLING) += blk-throttle.o
obj-$(CONFIG_IOSCHED_NOOP) += noop-iosched.o
obj-$(CONFIG_IOSCHED_DEADLINE) += deadline-iosched.o
obj-$(CONFIG_IOSCHED_CFQ) += cfq-iosched.o
+obj-$(CONFIG_IOSCHED_BFQ) += bfq-iosched.o
obj-$(CONFIG_BLOCK_COMPAT) += compat_ioctl.o
obj-$(CONFIG_BLK_CMDLINE_PARSER) += cmdline-parser.o
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index c47c358..1047d99 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -45,7 +45,7 @@ struct pr_ops;
* Maximum number of blkcg policies allowed to be registered concurrently.
* Defined here to simplify include dependency.
*/
-#define BLKCG_MAX_POLS 2
+#define BLKCG_MAX_POLS 3
typedef void (rq_end_io_fn)(struct request *, int);
--
2.10.0
@@ -1,21 +0,0 @@
Disable floppy autoloading as it makes systems without real hw,
but that has the pnp headers hang.
See https://bugs.mageia.org/show_bug.cgi?id=4696
Signed-off-by: Thomas Backlund <tmb@mageia.org>
diff -Nurp linux-3.3.3-rc1/drivers/block/floppy.c.orig linux-3.3.3-rc1/drivers/block/floppy.c
--- linux-3.3.3-rc1/drivers/block/floppy.c.orig 2012-03-19 01:15:34.000000000 +0200
+++ linux-3.3.3-rc1/drivers/block/floppy.c 2012-04-22 02:58:10.238498303 +0300
@@ -4621,8 +4621,7 @@ static const struct pnp_device_id floppy
{"PNP0700", 0},
{}
};
-
-MODULE_DEVICE_TABLE(pnp, floppy_pnpids);
+/* MODULE_DEVICE_TABLE(pnp, floppy_pnpids); */
#else
@@ -1,34 +0,0 @@
From 124298bd03acebd9c9da29a794718aca31bec1f7 Mon Sep 17 00:00:00 2001
From: Daniel Roschka <danielroschka@phoenitydawn.de>
Date: Wed, 22 Feb 2017 15:17:29 -0700
Subject: [PATCH] nvme: detect NVMe controller in recent MacBooks
Adds support for detection of the NVMe controller found in the
following recent MacBooks:
- Retina MacBook 2016 (MacBook9,1)
- 13" MacBook Pro 2016 without Touch Bar (MacBook13,1)
- 13" MacBook Pro 2016 with Touch Bar (MacBook13,2)
Signed-off-by: Daniel Roschka <danielroschka@phoenitydawn.de>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Sagi Grimberg <sagi@grimberg.me>
Signed-off-by: Jens Axboe <axboe@fb.com>
---
drivers/nvme/host/pci.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index d38dae9..319f5c5 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -2120,6 +2120,7 @@ static const struct pci_device_id nvme_id_table[] = {
.driver_data = NVME_QUIRK_DELAY_BEFORE_CHK_RDY, },
{ PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, 0xffffff) },
{ PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2001) },
+ { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2003) },
{ 0, }
};
MODULE_DEVICE_TABLE(pci, nvme_id_table);
--
2.10.2
@@ -1,69 +0,0 @@
block/bfq-iosched.c | 4 +++-
block/bfq-sched.c | 15 ++++++++++++---
block/bfq.h | 2 +-
3 files changed, 16 insertions(+), 5 deletions(-)
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
index 96b79a0dae9f..158628392d92 100644
--- a/block/bfq-iosched.c
+++ b/block/bfq-iosched.c
@@ -4572,6 +4572,8 @@ static int bfq_set_request(struct request_queue *q, struct request *rq,
if (!bic)
goto queue_fail;
+ bfq_check_ioprio_change(bic, bio);
+
bfq_bic_update_cgroup(bic, bio);
new_queue:
@@ -5268,7 +5270,7 @@ static struct blkcg_policy blkcg_policy_bfq = {
static int __init bfq_init(void)
{
int ret;
- char msg[60] = "BFQ I/O-scheduler: v8r10";
+ char msg[60] = "BFQ I/O-scheduler: v8r11";
#ifdef CONFIG_BFQ_GROUP_IOSCHED
ret = blkcg_policy_register(&blkcg_policy_bfq);
diff --git a/block/bfq-sched.c b/block/bfq-sched.c
index 70aac56b02ef..8311bdbeceea 100644
--- a/block/bfq-sched.c
+++ b/block/bfq-sched.c
@@ -1280,14 +1280,23 @@ static bool __bfq_deactivate_entity(struct bfq_entity *entity,
bool ins_into_idle_tree)
{
struct bfq_sched_data *sd = entity->sched_data;
- struct bfq_service_tree *st = bfq_entity_service_tree(entity);
- bool is_in_service = entity == sd->in_service_entity;
+ struct bfq_service_tree *st;
+ bool is_in_service;
if (!entity->on_st) { /* entity never activated, or already inactive */
- BUG_ON(entity == entity->sched_data->in_service_entity);
+ BUG_ON(sd && entity == sd->in_service_entity);
return false;
}
+ /*
+ * If we get here, then entity is active, which implies that
+ * bfq_group_set_parent has already been invoked for the group
+ * represented by entity. Therefore, the field
+ * entity->sched_data has been set, and we can safely use it.
+ */
+ st = bfq_entity_service_tree(entity);
+ is_in_service = entity == sd->in_service_entity;
+
BUG_ON(is_in_service && entity->tree && entity->tree != &st->active);
if (is_in_service)
diff --git a/block/bfq.h b/block/bfq.h
index e3855af1211b..a521ac40cac0 100644
--- a/block/bfq.h
+++ b/block/bfq.h
@@ -1,5 +1,5 @@
/*
- * BFQ v8r10 for 4.9.0: data structures and common functions prototypes.
+ * BFQ v8r11 for 4.9.0: data structures and common functions prototypes.
*
* Based on ideas and code from CFQ:
* Copyright (C) 2003 Jens Axboe <axboe@kernel.dk>
@@ -1,729 +0,0 @@
block/bfq-cgroup.c | 12 +--
block/bfq-iosched.c | 211 +++++++++++++++++++++++++++++++---------------------
block/bfq-sched.c | 73 ++++++++++++------
block/bfq.h | 4 +-
4 files changed, 180 insertions(+), 120 deletions(-)
diff --git a/block/bfq-cgroup.c b/block/bfq-cgroup.c
index bbaecd0..a66a723 100644
--- a/block/bfq-cgroup.c
+++ b/block/bfq-cgroup.c
@@ -771,7 +771,6 @@ static void bfq_pd_offline(struct blkg_policy_data *pd)
__bfq_deactivate_entity(entity, false);
bfq_put_async_queues(bfqd, bfqg);
- BUG_ON(entity->tree);
/*
* @blkg is going offline and will be ignored by
@@ -1140,6 +1139,9 @@ static inline void bfqg_stats_update_idle_time(struct bfq_group *bfqg) { }
static inline void bfqg_stats_set_start_idle_time(struct bfq_group *bfqg) { }
static inline void bfqg_stats_update_avg_queue_size(struct bfq_group *bfqg) { }
+static void bfq_bfqq_move(struct bfq_data *bfqd, struct bfq_queue *bfqq,
+ struct bfq_group *bfqg) {}
+
static void bfq_init_entity(struct bfq_entity *entity,
struct bfq_group *bfqg)
{
@@ -1154,13 +1156,7 @@ static void bfq_init_entity(struct bfq_entity *entity,
entity->sched_data = &bfqg->sched_data;
}
-static struct bfq_group *
-bfq_bic_update_cgroup(struct bfq_io_cq *bic, struct bio *bio)
-{
- struct bfq_data *bfqd = bic_to_bfqd(bic);
-
- return bfqd->root_group;
-}
+static void bfq_bic_update_cgroup(struct bfq_io_cq *bic, struct bio *bio) {}
static void bfq_end_wr_async(struct bfq_data *bfqd)
{
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
index 78baa07..96b79a0 100644
--- a/block/bfq-iosched.c
+++ b/block/bfq-iosched.c
@@ -9,7 +9,7 @@
*
* Copyright (C) 2015 Paolo Valente <paolo.valente@unimore.it>
*
- * Copyright (C) 2016 Paolo Valente <paolo.valente@linaro.org>
+ * Copyright (C) 2017 Paolo Valente <paolo.valente@linaro.org>
*
* Licensed under the GPL-2 as detailed in the accompanying COPYING.BFQ
* file.
@@ -107,7 +107,7 @@ static const int bfq_async_charge_factor = 10;
/* Default timeout values, in jiffies, approximating CFQ defaults. */
static const int bfq_timeout = (HZ / 8);
-struct kmem_cache *bfq_pool;
+static struct kmem_cache *bfq_pool;
/* Below this threshold (in ns), we consider thinktime immediate. */
#define BFQ_MIN_TT (2 * NSEC_PER_MSEC)
@@ -483,6 +483,22 @@ static void bfq_weights_tree_add(struct bfq_data *bfqd,
entity->weight_counter = kzalloc(sizeof(struct bfq_weight_counter),
GFP_ATOMIC);
+
+ /*
+ * In the unlucky event of an allocation failure, we just
+ * exit. This will cause the weight of entity to not be
+ * considered in bfq_differentiated_weights, which, in its
+ * turn, causes the scenario to be deemed wrongly symmetric in
+ * case entity's weight would have been the only weight making
+ * the scenario asymmetric. On the bright side, no unbalance
+ * will however occur when entity becomes inactive again (the
+ * invocation of this function is triggered by an activation
+ * of entity). In fact, bfq_weights_tree_remove does nothing
+ * if !entity->weight_counter.
+ */
+ if (unlikely(!entity->weight_counter))
+ return;
+
entity->weight_counter->weight = entity->weight;
rb_link_node(&entity->weight_counter->weights_node, parent, new);
rb_insert_color(&entity->weight_counter->weights_node, root);
@@ -519,13 +535,45 @@ static void bfq_weights_tree_remove(struct bfq_data *bfqd,
entity->weight_counter = NULL;
}
+/*
+ * Return expired entry, or NULL to just start from scratch in rbtree.
+ */
+static struct request *bfq_check_fifo(struct bfq_queue *bfqq,
+ struct request *last)
+{
+ struct request *rq;
+
+ if (bfq_bfqq_fifo_expire(bfqq))
+ return NULL;
+
+ bfq_mark_bfqq_fifo_expire(bfqq);
+
+ rq = rq_entry_fifo(bfqq->fifo.next);
+
+ if (rq == last || ktime_get_ns() < rq->fifo_time)
+ return NULL;
+
+ bfq_log_bfqq(bfqq->bfqd, bfqq, "check_fifo: returned %p", rq);
+ BUG_ON(RB_EMPTY_NODE(&rq->rb_node));
+ return rq;
+}
+
static struct request *bfq_find_next_rq(struct bfq_data *bfqd,
struct bfq_queue *bfqq,
struct request *last)
{
struct rb_node *rbnext = rb_next(&last->rb_node);
struct rb_node *rbprev = rb_prev(&last->rb_node);
- struct request *next = NULL, *prev = NULL;
+ struct request *next, *prev = NULL;
+
+ BUG_ON(list_empty(&bfqq->fifo));
+
+ /* Follow expired path, else get first next available. */
+ next = bfq_check_fifo(bfqq, last);
+ if (next) {
+ BUG_ON(next == last);
+ return next;
+ }
BUG_ON(RB_EMPTY_NODE(&last->rb_node));
@@ -1359,7 +1407,6 @@ static void bfq_bfqq_handle_idle_busy_switch(struct bfq_data *bfqd,
bfq_bfqq_expire(bfqd, bfqd->in_service_queue,
false, BFQ_BFQQ_PREEMPTED);
- BUG_ON(in_serv->entity.budget < 0);
}
}
@@ -1523,12 +1570,15 @@ static void bfq_remove_request(struct request *rq)
elv_rb_del(&bfqq->sort_list, rq);
if (RB_EMPTY_ROOT(&bfqq->sort_list)) {
+ bfqq->next_rq = NULL;
+
BUG_ON(bfqq->entity.budget < 0);
if (bfq_bfqq_busy(bfqq) && bfqq != bfqd->in_service_queue) {
+ BUG_ON(bfqq->ref < 2); /* referred by rq and on tree */
bfq_del_bfqq_busy(bfqd, bfqq, false);
-
- /* bfqq emptied. In normal operation, when
+ /*
+ * bfqq emptied. In normal operation, when
* bfqq is empty, bfqq->entity.service and
* bfqq->entity.budget must contain,
* respectively, the service received and the
@@ -1537,7 +1587,8 @@ static void bfq_remove_request(struct request *rq)
* this last removal occurred while bfqq is
* not in service. To avoid inconsistencies,
* reset both bfqq->entity.service and
- * bfqq->entity.budget.
+ * bfqq->entity.budget, if bfqq has still a
+ * process that may issue I/O requests to it.
*/
bfqq->entity.budget = bfqq->entity.service = 0;
}
@@ -1868,7 +1919,7 @@ static bool bfq_may_be_close_cooperator(struct bfq_queue *bfqq,
* positives. In case bfqq is weight-raised, such false positives
* would evidently degrade latency guarantees for bfqq.
*/
-bool wr_from_too_long(struct bfq_queue *bfqq)
+static bool wr_from_too_long(struct bfq_queue *bfqq)
{
return bfqq->wr_coeff > 1 &&
time_is_before_jiffies(bfqq->last_wr_start_finish +
@@ -2029,7 +2080,8 @@ bfq_merge_bfqqs(struct bfq_data *bfqd, struct bfq_io_cq *bic,
new_bfqq->wr_coeff = bfqq->wr_coeff;
new_bfqq->wr_cur_max_time = bfqq->wr_cur_max_time;
new_bfqq->last_wr_start_finish = bfqq->last_wr_start_finish;
- new_bfqq->wr_start_at_switch_to_srt = bfqq->wr_start_at_switch_to_srt;
+ new_bfqq->wr_start_at_switch_to_srt =
+ bfqq->wr_start_at_switch_to_srt;
if (bfq_bfqq_busy(new_bfqq))
bfqd->wr_busy_queues++;
new_bfqq->entity.prio_changed = 1;
@@ -2072,6 +2124,7 @@ bfq_merge_bfqqs(struct bfq_data *bfqd, struct bfq_io_cq *bic,
*/
new_bfqq->bic = NULL;
bfqq->bic = NULL;
+ /* release process reference to bfqq */
bfq_put_queue(bfqq);
}
@@ -2298,7 +2351,7 @@ static unsigned long bfq_calc_max_budget(struct bfq_data *bfqd)
* function of the estimated peak rate. See comments on
* bfq_calc_max_budget(), and on T_slow and T_fast arrays.
*/
-void update_thr_responsiveness_params(struct bfq_data *bfqd)
+static void update_thr_responsiveness_params(struct bfq_data *bfqd)
{
int dev_type = blk_queue_nonrot(bfqd->queue);
@@ -2333,7 +2386,7 @@ void update_thr_responsiveness_params(struct bfq_data *bfqd)
BFQ_RATE_SHIFT);
}
-void bfq_reset_rate_computation(struct bfq_data *bfqd, struct request *rq)
+static void bfq_reset_rate_computation(struct bfq_data *bfqd, struct request *rq)
{
if (rq != NULL) { /* new rq dispatch now, reset accordingly */
bfqd->last_dispatch = bfqd->first_dispatch = ktime_get_ns() ;
@@ -2350,7 +2403,7 @@ void bfq_reset_rate_computation(struct bfq_data *bfqd, struct request *rq)
bfqd->tot_sectors_dispatched);
}
-void bfq_update_rate_reset(struct bfq_data *bfqd, struct request *rq)
+static void bfq_update_rate_reset(struct bfq_data *bfqd, struct request *rq)
{
u32 rate, weight, divisor;
@@ -2400,7 +2453,7 @@ void bfq_update_rate_reset(struct bfq_data *bfqd, struct request *rq)
* total, and rate is below the current estimated peak rate
* - rate is unreasonably high (> 20M sectors/sec)
*/
- if ((bfqd->peak_rate_samples > (3 * bfqd->sequential_samples)>>2 &&
+ if ((bfqd->sequential_samples < (3 * bfqd->peak_rate_samples)>>2 &&
rate <= bfqd->peak_rate) ||
rate > 20<<BFQ_RATE_SHIFT) {
bfq_log(bfqd,
@@ -2515,7 +2568,7 @@ void bfq_update_rate_reset(struct bfq_data *bfqd, struct request *rq)
* of the observed dispatch rate. The function assumes to be invoked
* on every request dispatch.
*/
-void bfq_update_peak_rate(struct bfq_data *bfqd, struct request *rq)
+static void bfq_update_peak_rate(struct bfq_data *bfqd, struct request *rq)
{
u64 now_ns = ktime_get_ns();
@@ -2616,29 +2669,6 @@ static void bfq_dispatch_insert(struct request_queue *q, struct request *rq)
elv_dispatch_sort(q, rq);
}
-/*
- * Return expired entry, or NULL to just start from scratch in rbtree.
- */
-static struct request *bfq_check_fifo(struct bfq_queue *bfqq)
-{
- struct request *rq = NULL;
-
- if (bfq_bfqq_fifo_expire(bfqq))
- return NULL;
-
- bfq_mark_bfqq_fifo_expire(bfqq);
-
- if (list_empty(&bfqq->fifo))
- return NULL;
-
- rq = rq_entry_fifo(bfqq->fifo.next);
-
- if (ktime_get_ns() < rq->fifo_time)
- return NULL;
-
- return rq;
-}
-
static void __bfq_bfqq_expire(struct bfq_data *bfqd, struct bfq_queue *bfqq)
{
BUG_ON(bfqq != bfqd->in_service_queue);
@@ -2904,8 +2934,8 @@ static bool bfq_bfqq_is_slow(struct bfq_data *bfqd, struct bfq_queue *bfqq,
delta_ktime = ktime_sub(delta_ktime, bfqd->last_budget_start);
delta_usecs = ktime_to_us(delta_ktime);
- /* don't trust short/unrealistic values. */
- if (delta_usecs < 1000 || delta_usecs >= LONG_MAX) {
+ /* don't use too short time intervals */
+ if (delta_usecs < 1000) {
if (blk_queue_nonrot(bfqd->queue))
/*
* give same worst-case guarantees as idling
@@ -2915,7 +2945,7 @@ static bool bfq_bfqq_is_slow(struct bfq_data *bfqd, struct bfq_queue *bfqq,
else /* charge at least one seek */
*delta_ms = bfq_slice_idle / NSEC_PER_MSEC;
- bfq_log(bfqd, "bfq_bfqq_is_slow: unrealistic %u", delta_usecs);
+ bfq_log(bfqd, "bfq_bfqq_is_slow: too short %u", delta_usecs);
return slow;
}
@@ -3067,6 +3097,7 @@ static void bfq_bfqq_expire(struct bfq_data *bfqd,
bool slow;
unsigned long delta = 0;
struct bfq_entity *entity = &bfqq->entity;
+ int ref;
BUG_ON(bfqq != bfqd->in_service_queue);
@@ -3174,12 +3205,15 @@ static void bfq_bfqq_expire(struct bfq_data *bfqd,
__bfq_bfqq_recalc_budget(bfqd, bfqq, reason);
BUG_ON(bfqq->next_rq == NULL &&
bfqq->entity.budget < bfqq->entity.service);
+ ref = bfqq->ref;
__bfq_bfqq_expire(bfqd, bfqq);
- BUG_ON(!bfq_bfqq_busy(bfqq) && reason == BFQ_BFQQ_BUDGET_EXHAUSTED &&
+ BUG_ON(ref > 1 &&
+ !bfq_bfqq_busy(bfqq) && reason == BFQ_BFQQ_BUDGET_EXHAUSTED &&
!bfq_class_idle(bfqq));
- if (!bfq_bfqq_busy(bfqq) &&
+ /* mark bfqq as waiting a request only if a bic still points to it */
+ if (ref > 1 && !bfq_bfqq_busy(bfqq) &&
reason != BFQ_BFQQ_BUDGET_TIMEOUT &&
reason != BFQ_BFQQ_BUDGET_EXHAUSTED)
bfq_mark_bfqq_non_blocking_wait_rq(bfqq);
@@ -3504,14 +3538,29 @@ static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd)
!bfq_bfqq_must_idle(bfqq))
goto expire;
+check_queue:
+ /*
+ * This loop is rarely executed more than once. Even when it
+ * happens, it is much more convenient to re-execute this loop
+ * than to return NULL and trigger a new dispatch to get a
+ * request served.
+ */
next_rq = bfqq->next_rq;
/*
* If bfqq has requests queued and it has enough budget left to
* serve them, keep the queue, otherwise expire it.
*/
if (next_rq) {
+ BUG_ON(RB_EMPTY_ROOT(&bfqq->sort_list));
+
if (bfq_serv_to_charge(next_rq, bfqq) >
bfq_bfqq_budget_left(bfqq)) {
+ /*
+ * Expire the queue for budget exhaustion,
+ * which makes sure that the next budget is
+ * enough to serve the next request, even if
+ * it comes from the fifo expired path.
+ */
reason = BFQ_BFQQ_BUDGET_EXHAUSTED;
goto expire;
} else {
@@ -3559,9 +3608,16 @@ static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd)
bfq_bfqq_expire(bfqd, bfqq, false, reason);
new_queue:
bfqq = bfq_set_in_service_queue(bfqd);
- bfq_log(bfqd, "select_queue: new queue %d returned",
- bfqq ? bfqq->pid : 0);
+ if (bfqq) {
+ bfq_log_bfqq(bfqd, bfqq, "select_queue: checking new queue");
+ goto check_queue;
+ }
keep_queue:
+ if (bfqq)
+ bfq_log_bfqq(bfqd, bfqq, "select_queue: returned this queue");
+ else
+ bfq_log(bfqd, "select_queue: no queue returned");
+
return bfqq;
}
@@ -3627,45 +3683,17 @@ static int bfq_dispatch_request(struct bfq_data *bfqd,
struct bfq_queue *bfqq)
{
int dispatched = 0;
- struct request *rq;
+ struct request *rq = bfqq->next_rq;
unsigned long service_to_charge;
BUG_ON(RB_EMPTY_ROOT(&bfqq->sort_list));
-
- /* Follow expired path, else get first next available. */
- rq = bfq_check_fifo(bfqq);
- if (!rq)
- rq = bfqq->next_rq;
+ BUG_ON(!rq);
service_to_charge = bfq_serv_to_charge(rq, bfqq);
- if (service_to_charge > bfq_bfqq_budget_left(bfqq)) {
- /*
- * This may happen if the next rq is chosen in fifo order
- * instead of sector order. The budget is properly
- * dimensioned to be always sufficient to serve the next
- * request only if it is chosen in sector order. The reason
- * is that it would be quite inefficient and little useful
- * to always make sure that the budget is large enough to
- * serve even the possible next rq in fifo order.
- * In fact, requests are seldom served in fifo order.
- *
- * Expire the queue for budget exhaustion, and make sure
- * that the next act_budget is enough to serve the next
- * request, even if it comes from the fifo expired path.
- */
- bfqq->next_rq = rq;
- /*
- * Since this dispatch is failed, make sure that
- * a new one will be performed
- */
- if (!bfqd->rq_in_driver)
- bfq_schedule_dispatch(bfqd);
- BUG_ON(bfqq->entity.budget < bfqq->entity.service);
- goto expire;
- }
+ BUG_ON(service_to_charge > bfq_bfqq_budget_left(bfqq));
BUG_ON(bfqq->entity.budget < bfqq->entity.service);
- /* Finally, insert request into driver dispatch list. */
+
bfq_bfqq_served(bfqq, service_to_charge);
BUG_ON(bfqq->entity.budget < bfqq->entity.service);
@@ -3805,7 +3833,8 @@ static int bfq_dispatch_requests(struct request_queue *q, int force)
* Task holds one reference to the queue, dropped when task exits. Each rq
* in-flight on this queue also holds a reference, dropped when rq is freed.
*
- * Queue lock must be held here.
+ * Queue lock must be held here. Recall not to use bfqq after calling
+ * this function on it.
*/
static void bfq_put_queue(struct bfq_queue *bfqq)
{
@@ -3874,7 +3903,7 @@ static void bfq_exit_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq)
bfq_put_cooperator(bfqq);
- bfq_put_queue(bfqq);
+ bfq_put_queue(bfqq); /* release process reference */
}
static void bfq_init_icq(struct io_cq *icq)
@@ -3973,6 +4002,7 @@ static void bfq_check_ioprio_change(struct bfq_io_cq *bic, struct bio *bio)
bfqq = bic_to_bfqq(bic, false);
if (bfqq) {
+ /* release process reference on this queue */
bfq_put_queue(bfqq);
bfqq = bfq_get_queue(bfqd, bio, BLK_RW_ASYNC, bic);
bic_set_bfqq(bic, bfqq, false);
@@ -4093,14 +4123,20 @@ static struct bfq_queue *bfq_get_queue(struct bfq_data *bfqd,
* prune it.
*/
if (async_bfqq) {
- bfqq->ref++;
+ bfqq->ref++; /*
+ * Extra group reference, w.r.t. sync
+ * queue. This extra reference is removed
+ * only if bfqq->bfqg disappears, to
+ * guarantee that this queue is not freed
+ * until its group goes away.
+ */
bfq_log_bfqq(bfqd, bfqq, "get_queue, bfqq not in async: %p, %d",
bfqq, bfqq->ref);
*async_bfqq = bfqq;
}
out:
- bfqq->ref++;
+ bfqq->ref++; /* get a process reference to this queue */
bfq_log_bfqq(bfqd, bfqq, "get_queue, at end: %p, %d", bfqq, bfqq->ref);
rcu_read_unlock();
return bfqq;
@@ -4274,10 +4310,14 @@ static void bfq_insert_request(struct request_queue *q, struct request *rq)
bfqq->allocated[rq_data_dir(rq)]--;
new_bfqq->ref++;
bfq_clear_bfqq_just_created(bfqq);
- bfq_put_queue(bfqq);
if (bic_to_bfqq(RQ_BIC(rq), 1) == bfqq)
bfq_merge_bfqqs(bfqd, RQ_BIC(rq),
bfqq, new_bfqq);
+ /*
+ * rq is about to be enqueued into new_bfqq,
+ * release rq reference on bfqq
+ */
+ bfq_put_queue(bfqq);
rq->elv.priv[1] = new_bfqq;
bfqq = new_bfqq;
}
@@ -4697,9 +4737,8 @@ static void bfq_shutdown_timer_wq(struct bfq_data *bfqd)
cancel_work_sync(&bfqd->unplug_work);
}
-#ifdef CONFIG_BFQ_GROUP_IOSCHED
static void __bfq_put_async_bfqq(struct bfq_data *bfqd,
- struct bfq_queue **bfqq_ptr)
+ struct bfq_queue **bfqq_ptr)
{
struct bfq_group *root_group = bfqd->root_group;
struct bfq_queue *bfqq = *bfqq_ptr;
@@ -4730,7 +4769,6 @@ static void bfq_put_async_queues(struct bfq_data *bfqd, struct bfq_group *bfqg)
__bfq_put_async_bfqq(bfqd, &bfqg->async_idle_bfqq);
}
-#endif
static void bfq_exit_queue(struct elevator_queue *e)
{
@@ -4755,6 +4793,7 @@ static void bfq_exit_queue(struct elevator_queue *e)
#ifdef CONFIG_BFQ_GROUP_IOSCHED
blkcg_deactivate_policy(q, &blkcg_policy_bfq);
#else
+ bfq_put_async_queues(bfqd, bfqd->root_group);
kfree(bfqd->root_group);
#endif
@@ -5229,7 +5268,7 @@ static struct blkcg_policy blkcg_policy_bfq = {
static int __init bfq_init(void)
{
int ret;
- char msg[60] = "BFQ I/O-scheduler: v8r7";
+ char msg[60] = "BFQ I/O-scheduler: v8r10";
#ifdef CONFIG_BFQ_GROUP_IOSCHED
ret = blkcg_policy_register(&blkcg_policy_bfq);
@@ -5255,7 +5294,7 @@ static int __init bfq_init(void)
* be run for a long time.
*/
T_slow[0] = msecs_to_jiffies(3500); /* actually 4 sec */
- T_slow[1] = msecs_to_jiffies(1000); /* actually 1.5 sec */
+ T_slow[1] = msecs_to_jiffies(6000); /* actually 6.5 sec */
T_fast[0] = msecs_to_jiffies(7000); /* actually 8 sec */
T_fast[1] = msecs_to_jiffies(2500); /* actually 3 sec */
diff --git a/block/bfq-sched.c b/block/bfq-sched.c
index 797bce7..70aac56 100644
--- a/block/bfq-sched.c
+++ b/block/bfq-sched.c
@@ -154,7 +154,13 @@ static bool bfq_update_next_in_service(struct bfq_sched_data *sd,
#define for_each_entity(entity) \
for (; entity ; entity = entity->parent)
-#define for_each_entity_safe(entity, parent) \
+/*
+ * For each iteration, compute parent in advance, so as to be safe if
+ * entity is deallocated during the iteration. Such a deallocation may
+ * happen as a consequence of a bfq_put_queue that frees the bfq_queue
+ * containing entity.
+ */
+#define for_each_entity_safe(entity, parent) \
for (; entity && ({ parent = entity->parent; 1; }); entity = parent)
/*
@@ -691,27 +697,31 @@ static void bfq_idle_insert(struct bfq_service_tree *st,
}
/**
- * bfq_forget_entity - remove an entity from the wfq trees.
+ * bfq_forget_entity - do not consider entity any longer for scheduling
* @st: the service tree.
* @entity: the entity being removed.
+ * @is_in_service: true if entity is currently the in-service entity.
*
- * Update the device status and forget everything about @entity, putting
- * the device reference to it, if it is a queue. Entities belonging to
- * groups are not refcounted.
+ * Forget everything about @entity. In addition, if entity represents
+ * a queue, and the latter is not in service, then release the service
+ * reference to the queue (the one taken through bfq_get_entity). In
+ * fact, in this case, there is really no more service reference to
+ * the queue, as the latter is also outside any service tree. If,
+ * instead, the queue is in service, then __bfq_bfqd_reset_in_service
+ * will take care of putting the reference when the queue finally
+ * stops being served.
*/
static void bfq_forget_entity(struct bfq_service_tree *st,
- struct bfq_entity *entity)
+ struct bfq_entity *entity,
+ bool is_in_service)
{
struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity);
- struct bfq_sched_data *sd;
-
BUG_ON(!entity->on_st);
entity->on_st = false;
st->wsum -= entity->weight;
- if (bfqq) {
- sd = entity->sched_data;
- bfq_log_bfqq(bfqq->bfqd, bfqq, "forget_entity: %p %d",
+ if (bfqq && !is_in_service) {
+ bfq_log_bfqq(bfqq->bfqd, bfqq, "forget_entity (before): %p %d",
bfqq, bfqq->ref);
bfq_put_queue(bfqq);
}
@@ -726,7 +736,8 @@ static void bfq_put_idle_entity(struct bfq_service_tree *st,
struct bfq_entity *entity)
{
bfq_idle_extract(st, entity);
- bfq_forget_entity(st, entity);
+ bfq_forget_entity(st, entity,
+ entity == entity->sched_data->in_service_entity);
}
/**
@@ -1082,6 +1093,12 @@ static void __bfq_activate_entity(struct bfq_entity *entity,
*/
entity->start = min_vstart;
st->wsum += entity->weight;
+ /*
+ * entity is about to be inserted into a service tree,
+ * and then set in service: get a reference to make
+ * sure entity does not disappear until it is no
+ * longer in service or scheduled for service.
+ */
bfq_get_entity(entity);
BUG_ON(entity->on_st && bfqq);
@@ -1264,27 +1281,27 @@ static bool __bfq_deactivate_entity(struct bfq_entity *entity,
{
struct bfq_sched_data *sd = entity->sched_data;
struct bfq_service_tree *st = bfq_entity_service_tree(entity);
- bool was_in_service = entity == sd->in_service_entity;
+ bool is_in_service = entity == sd->in_service_entity;
if (!entity->on_st) { /* entity never activated, or already inactive */
BUG_ON(entity == entity->sched_data->in_service_entity);
return false;
}
- BUG_ON(was_in_service && entity->tree && entity->tree != &st->active);
+ BUG_ON(is_in_service && entity->tree && entity->tree != &st->active);
- if (was_in_service)
+ if (is_in_service)
bfq_calc_finish(entity, entity->service);
if (entity->tree == &st->active)
bfq_active_extract(st, entity);
- else if (!was_in_service && entity->tree == &st->idle)
+ else if (!is_in_service && entity->tree == &st->idle)
bfq_idle_extract(st, entity);
else if (entity->tree)
BUG();
if (!ins_into_idle_tree || !bfq_gt(entity->finish, st->vtime))
- bfq_forget_entity(st, entity);
+ bfq_forget_entity(st, entity, is_in_service);
else
bfq_idle_insert(st, entity);
@@ -1301,7 +1318,7 @@ static void bfq_deactivate_entity(struct bfq_entity *entity,
bool expiration)
{
struct bfq_sched_data *sd;
- struct bfq_entity *parent;
+ struct bfq_entity *parent = NULL;
for_each_entity_safe(entity, parent) {
sd = entity->sched_data;
@@ -1320,8 +1337,8 @@ static void bfq_deactivate_entity(struct bfq_entity *entity,
if (!__bfq_deactivate_entity(entity, ins_into_idle_tree)) {
/*
- * Entity is not any tree any more, so, this
- * deactivation is a no-op, and there is
+ * entity is not in any tree any more, so
+ * this deactivation is a no-op, and there is
* nothing to change for upper-level entities
* (in case of expiration, this can never
* happen).
@@ -1821,14 +1838,16 @@ static struct bfq_queue *bfq_get_next_queue(struct bfq_data *bfqd)
static void __bfq_bfqd_reset_in_service(struct bfq_data *bfqd)
{
- struct bfq_entity *entity = &bfqd->in_service_queue->entity;
+ struct bfq_queue *in_serv_bfqq = bfqd->in_service_queue;
+ struct bfq_entity *in_serv_entity = &in_serv_bfqq->entity;
+ struct bfq_entity *entity = in_serv_entity;
if (bfqd->in_service_bic) {
put_io_context(bfqd->in_service_bic->icq.ioc);
bfqd->in_service_bic = NULL;
}
- bfq_clear_bfqq_wait_request(bfqd->in_service_queue);
+ bfq_clear_bfqq_wait_request(in_serv_bfqq);
hrtimer_try_to_cancel(&bfqd->idle_slice_timer);
bfqd->in_service_queue = NULL;
@@ -1840,6 +1859,14 @@ static void __bfq_bfqd_reset_in_service(struct bfq_data *bfqd)
*/
for_each_entity(entity)
entity->sched_data->in_service_entity = NULL;
+
+ /*
+ * in_serv_entity is no longer in service, so, if it is in no
+ * service tree either, then release the service reference to
+ * the queue it represents (taken with bfq_get_entity).
+ */
+ if (!in_serv_entity->on_st)
+ bfq_put_queue(in_serv_bfqq);
}
static void bfq_deactivate_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq,
@@ -1904,8 +1931,6 @@ static void bfq_del_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq,
BUG_ON(bfqq->entity.budget < 0);
bfq_deactivate_bfqq(bfqd, bfqq, true, expiration);
-
- BUG_ON(bfqq->entity.budget < 0);
}
/*
diff --git a/block/bfq.h b/block/bfq.h
index a9da002..e3855af 100644
--- a/block/bfq.h
+++ b/block/bfq.h
@@ -1,5 +1,5 @@
/*
- * BFQ v8r7 for 4.9.0: data structures and common functions prototypes.
+ * BFQ v8r10 for 4.9.0: data structures and common functions prototypes.
*
* Based on ideas and code from CFQ:
* Copyright (C) 2003 Jens Axboe <axboe@kernel.dk>
@@ -9,7 +9,7 @@
*
* Copyright (C) 2015 Paolo Valente <paolo.valente@unimore.it>
*
- * Copyright (C) 2016 Paolo Valente <paolo.valente@linaro.org>
+ * Copyright (C) 2017 Paolo Valente <paolo.valente@linaro.org>
*/
#ifndef _BFQ_H
@@ -1,35 +0,0 @@
agp/intel: add new host bridge id for Q57 system
Add new Host Bridge ID found on a Q57 based system from Positivo. I
don't know what abbreviation id for this would be best, may be Q_HB
instead of UNKNOWN currently used would be better.
Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
[ rebased for 3.8-rc3 /tmb ]
Signed-off-by: Thomas Backlund <tmb@mageia.org>
Removed the parts of the patch that are already applied in the kernel by
the commit 67384fe3fd450536342330f684ea1f7dcaef8130:
"char/agp: add another Ironlake host bridge"
Rediffed for kernel 3.10.24.
Signed-off-by: Eugene A. Shatokhin <eugene.shatokhin@rosalab.ru>
drivers/char/agp/intel-gtt.c | 2 ++
1 file changed, 2 insertions(+)
diff -Nurp linux-3.8-rc3/drivers/char/agp/intel-gtt.c linux-3.8-rc3.q57/drivers/char/agp/intel-gtt.c
--- linux-3.8-rc3/drivers/char/agp/intel-gtt.c 2013-01-10 08:17:09.690594184 +0200
+++ linux-3.8-rc3.q57/drivers/char/agp/intel-gtt.c 2013-01-10 08:38:56.649888839 +0200
@@ -1303,6 +1303,8 @@ static const struct intel_gtt_driver_des
&g4x_gtt_driver },
{ PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG,
"HD Graphics", &ironlake_gtt_driver },
+ { PCI_DEVICE_ID_INTEL_IRONLAKE_D2_HB,
+ "HD Graphics", &ironlake_gtt_driver },
{ PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG,
"HD Graphics", &ironlake_gtt_driver },
{ 0, NULL, NULL }
@@ -1,115 +0,0 @@
From bc33c5df710c0aae6db396146194108634ef6f60 Mon Sep 17 00:00:00 2001
From: "Winkler, Tomas" <tomas.winkler@intel.com>
Date: Mon, 12 Sep 2016 16:04:19 +0300
Subject: [PATCH] tmp/tpm_crb: fix Intel PTT hw bug during idle state
There is a HW bug in Skylake, and Broxton PCH Intel PTT device, where
most of the registers in the control area except START, REQUEST, CANCEL,
and LOC_CTRL lost retention when the device is in the idle state. Hence
we need to bring the device to ready state before accessing the other
registers. The fix brings device to ready state before trying to read
command and response buffer addresses in order to remap the for access.
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Tested-by: Jarkko Sakkinen <jarkko.sakkinn@linux.intel.com>
Reviewed-by: Jarkko Sakkinen <jarkko.sakkinn@linux.intel.com>
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
---
drivers/char/tpm/tpm_crb.c | 47 ++++++++++++++++++++++++++++++++++++++--------
1 file changed, 39 insertions(+), 8 deletions(-)
diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c
index 8dd0f20..ff0d505 100644
--- a/drivers/char/tpm/tpm_crb.c
+++ b/drivers/char/tpm/tpm_crb.c
@@ -315,6 +315,7 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv,
struct list_head resources;
struct resource io_res;
struct device *dev = &device->dev;
+ u32 pa_high, pa_low;
u64 cmd_pa;
u32 cmd_size;
u64 rsp_pa;
@@ -342,12 +343,27 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv,
if (IS_ERR(priv->cca))
return PTR_ERR(priv->cca);
- cmd_pa = ((u64) ioread32(&priv->cca->cmd_pa_high) << 32) |
- (u64) ioread32(&priv->cca->cmd_pa_low);
+ /*
+ * PTT HW bug w/a: wake up the device to access
+ * possibly not retained registers.
+ */
+ ret = crb_cmd_ready(dev, priv);
+ if (ret)
+ return ret;
+
+ pa_high = ioread32(&priv->cca->cmd_pa_high);
+ pa_low = ioread32(&priv->cca->cmd_pa_low);
+ cmd_pa = ((u64)pa_high << 32) | pa_low;
cmd_size = ioread32(&priv->cca->cmd_size);
+
+ dev_dbg(dev, "cmd_hi = %X cmd_low = %X cmd_size %X\n",
+ pa_high, pa_low, cmd_size);
+
priv->cmd = crb_map_res(dev, priv, &io_res, cmd_pa, cmd_size);
- if (IS_ERR(priv->cmd))
- return PTR_ERR(priv->cmd);
+ if (IS_ERR(priv->cmd)) {
+ ret = PTR_ERR(priv->cmd);
+ goto out;
+ }
memcpy_fromio(&rsp_pa, &priv->cca->rsp_pa, 8);
rsp_pa = le64_to_cpu(rsp_pa);
@@ -355,7 +371,8 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv,
if (cmd_pa != rsp_pa) {
priv->rsp = crb_map_res(dev, priv, &io_res, rsp_pa, rsp_size);
- return PTR_ERR_OR_ZERO(priv->rsp);
+ ret = PTR_ERR_OR_ZERO(priv->rsp);
+ goto out;
}
/* According to the PTP specification, overlapping command and response
@@ -363,12 +380,18 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv,
*/
if (cmd_size != rsp_size) {
dev_err(dev, FW_BUG "overlapping command and response buffer sizes are not identical");
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
+
priv->cmd_size = cmd_size;
priv->rsp = priv->cmd;
- return 0;
+
+out:
+ crb_go_idle(dev, priv);
+
+ return ret;
}
static int crb_acpi_add(struct acpi_device *device)
@@ -412,7 +435,15 @@ static int crb_acpi_add(struct acpi_device *device)
if (rc)
return rc;
- return crb_init(device, priv);
+ rc = crb_cmd_ready(dev, priv);
+ if (rc)
+ return rc;
+
+ rc = crb_init(device, priv);
+ if (rc)
+ crb_go_idle(dev, priv);
+
+ return rc;
}
static int crb_acpi_remove(struct acpi_device *device)
--
2.10.2
@@ -1,134 +0,0 @@
From e74f2f76c13770bb8e004475a933923e9c92723d Mon Sep 17 00:00:00 2001
From: "Winkler, Tomas" <tomas.winkler@intel.com>
Date: Sat, 8 Oct 2016 14:59:39 +0300
Subject: [PATCH] tmp/tpm_crb: implement runtime pm for tpm_crb
Utilize runtime_pm for driving tpm crb idle states.
The framework calls cmd_ready from the pm_runtime_resume handler
and go idle from the pm_runtime_suspend handler.
The TPM framework should wake the device before transmit and receive.
In case the runtime_pm framework is not compiled in or enabled, the device
will be in the permanent ready state.
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Tested-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
---
drivers/char/tpm/tpm-interface.c | 5 +++++
drivers/char/tpm/tpm_crb.c | 42 ++++++++++++++++++++++++++++++++++++----
2 files changed, 43 insertions(+), 4 deletions(-)
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index 3a9149c..cb0e57e 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -29,6 +29,7 @@
#include <linux/mutex.h>
#include <linux/spinlock.h>
#include <linux/freezer.h>
+#include <linux/pm_runtime.h>
#include "tpm.h"
#include "tpm_eventlog.h"
@@ -356,6 +357,8 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz,
if (!(flags & TPM_TRANSMIT_UNLOCKED))
mutex_lock(&chip->tpm_mutex);
+ pm_runtime_get_sync(chip->dev.parent);
+
rc = chip->ops->send(chip, (u8 *) buf, count);
if (rc < 0) {
dev_err(&chip->dev,
@@ -397,6 +400,8 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz,
dev_err(&chip->dev,
"tpm_transmit: tpm_recv: error %zd\n", rc);
out:
+ pm_runtime_put_sync(chip->dev.parent);
+
if (!(flags & TPM_TRANSMIT_UNLOCKED))
mutex_unlock(&chip->tpm_mutex);
return rc;
diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c
index f579f1a..717b6b4 100644
--- a/drivers/char/tpm/tpm_crb.c
+++ b/drivers/char/tpm/tpm_crb.c
@@ -19,6 +19,7 @@
#include <linux/highmem.h>
#include <linux/rculist.h>
#include <linux/module.h>
+#include <linux/pm_runtime.h>
#include "tpm.h"
#define ACPI_SIG_TPM2 "TPM2"
@@ -149,8 +150,6 @@ static int __maybe_unused crb_cmd_ready(struct device *dev,
return 0;
}
-static SIMPLE_DEV_PM_OPS(crb_pm, tpm_pm_suspend, tpm_pm_resume);
-
static u8 crb_status(struct tpm_chip *chip)
{
struct crb_priv *priv = dev_get_drvdata(&chip->dev);
@@ -433,11 +432,21 @@ static int crb_acpi_add(struct acpi_device *device)
if (rc)
return rc;
+ pm_runtime_get_noresume(dev);
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+
rc = tpm_chip_register(chip);
- if (rc)
+ if (rc) {
crb_go_idle(dev, priv);
+ pm_runtime_put_noidle(dev);
+ pm_runtime_disable(dev);
+ return rc;
+ }
- return rc;
+ pm_runtime_put(dev);
+
+ return 0;
}
static int crb_acpi_remove(struct acpi_device *device)
@@ -447,9 +456,34 @@ static int crb_acpi_remove(struct acpi_device *device)
tpm_chip_unregister(chip);
+ pm_runtime_disable(dev);
+
return 0;
}
+#ifdef CONFIG_PM
+static int crb_pm_runtime_suspend(struct device *dev)
+{
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ struct crb_priv *priv = dev_get_drvdata(&chip->dev);
+
+ return crb_go_idle(dev, priv);
+}
+
+static int crb_pm_runtime_resume(struct device *dev)
+{
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ struct crb_priv *priv = dev_get_drvdata(&chip->dev);
+
+ return crb_cmd_ready(dev, priv);
+}
+#endif /* CONFIG_PM */
+
+static const struct dev_pm_ops crb_pm = {
+ SET_SYSTEM_SLEEP_PM_OPS(tpm_pm_suspend, tpm_pm_resume)
+ SET_RUNTIME_PM_OPS(crb_pm_runtime_suspend, crb_pm_runtime_resume, NULL)
+};
+
static struct acpi_device_id crb_device_ids[] = {
{"MSFT0101", 0},
{"", 0},
--
2.10.2
@@ -1,111 +0,0 @@
From ba5287b6ef6a2ee91dc6cc0829649cecf7b70253 Mon Sep 17 00:00:00 2001
From: "Winkler, Tomas" <tomas.winkler@intel.com>
Date: Thu, 15 Sep 2016 10:27:38 +0300
Subject: [PATCH] tpm/tpm_crb: implement tpm crb idle state
The register TPM_CRB_CTRL_REQ_x contains bits goIdle and cmdReady for
SW to indicate that the device can enter or should exit the idle state.
The legacy ACPI-start (SMI + DMA) based devices do not support these
bits and the idle state management is not exposed to the host SW.
Thus, this functionality only is enabled only for a CRB start (MMIO)
based devices.
Based on Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
original patch:
'tpm_crb: implement power tpm crb power management'
To keep the implementation local to the hw we don't use wait_for_tpm_stat
for polling the TPM_CRB_CTRL_REQ.
[jarkko.sakkinen@linux.intel.com: removed cmdReady debug trace on a
success case due the heavy amount of log traffic it causes.]
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Tested-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
---
drivers/char/tpm/tpm_crb.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 66 insertions(+)
diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c
index a7c870a..8dd0f20 100644
--- a/drivers/char/tpm/tpm_crb.c
+++ b/drivers/char/tpm/tpm_crb.c
@@ -83,6 +83,72 @@ struct crb_priv {
u32 cmd_size;
};
+/**
+ * crb_go_idle - request tpm crb device to go the idle state
+ *
+ * @dev: crb device
+ * @priv: crb private data
+ *
+ * Write CRB_CTRL_REQ_GO_IDLE to TPM_CRB_CTRL_REQ
+ * The device should respond within TIMEOUT_C by clearing the bit.
+ * Anyhow, we do not wait here as a consequent CMD_READY request
+ * will be handled correctly even if idle was not completed.
+ *
+ * The function does nothing for devices with ACPI-start method.
+ *
+ * Return: 0 always
+ */
+static int __maybe_unused crb_go_idle(struct device *dev, struct crb_priv *priv)
+{
+ if (priv->flags & CRB_FL_ACPI_START)
+ return 0;
+
+ iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->cca->req);
+ /* we don't really care when this settles */
+
+ return 0;
+}
+
+/**
+ * crb_cmd_ready - request tpm crb device to enter ready state
+ *
+ * @dev: crb device
+ * @priv: crb private data
+ *
+ * Write CRB_CTRL_REQ_CMD_READY to TPM_CRB_CTRL_REQ
+ * and poll till the device acknowledge it by clearing the bit.
+ * The device should respond within TIMEOUT_C.
+ *
+ * The function does nothing for devices with ACPI-start method
+ *
+ * Return: 0 on success -ETIME on timeout;
+ */
+static int __maybe_unused crb_cmd_ready(struct device *dev,
+ struct crb_priv *priv)
+{
+ ktime_t stop, start;
+
+ if (priv->flags & CRB_FL_ACPI_START)
+ return 0;
+
+ iowrite32(CRB_CTRL_REQ_CMD_READY, &priv->cca->req);
+
+ start = ktime_get();
+ stop = ktime_add(start, ms_to_ktime(TPM2_TIMEOUT_C));
+ do {
+ if (!(ioread32(&priv->cca->req) & CRB_CTRL_REQ_CMD_READY))
+ return 0;
+ usleep_range(50, 100);
+ } while (ktime_before(ktime_get(), stop));
+
+ if (ioread32(&priv->cca->req) & CRB_CTRL_REQ_CMD_READY) {
+ dev_warn(dev, "cmdReady timed out\n");
+ return -ETIME;
+ }
+
+ return 0;
+}
+
static SIMPLE_DEV_PM_OPS(crb_pm, tpm_pm_suspend, tpm_pm_resume);
static u8 crb_status(struct tpm_chip *chip)
--
2.10.2
@@ -1,75 +0,0 @@
From c58bd34cec4c05f8e3362a79ae94de9f405c39b5 Mon Sep 17 00:00:00 2001
From: "Winkler, Tomas" <tomas.winkler@intel.com>
Date: Mon, 12 Sep 2016 16:04:20 +0300
Subject: [PATCH] tpm/tpm_crb: open code the crb_init into acpi_add
This is preparation step for implementing tpm crb
runtime pm. We need to have tpm chip allocated
and populated before we access the runtime handlers.
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Tested-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
---
drivers/char/tpm/tpm_crb.c | 26 ++++++++++----------------
1 file changed, 10 insertions(+), 16 deletions(-)
diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c
index ff0d505..f579f1a 100644
--- a/drivers/char/tpm/tpm_crb.c
+++ b/drivers/char/tpm/tpm_crb.c
@@ -262,21 +262,6 @@ static const struct tpm_class_ops tpm_crb = {
.req_complete_val = CRB_DRV_STS_COMPLETE,
};
-static int crb_init(struct acpi_device *device, struct crb_priv *priv)
-{
- struct tpm_chip *chip;
-
- chip = tpmm_chip_alloc(&device->dev, &tpm_crb);
- if (IS_ERR(chip))
- return PTR_ERR(chip);
-
- dev_set_drvdata(&chip->dev, priv);
- chip->acpi_dev_handle = device->handle;
- chip->flags = TPM_CHIP_FLAG_TPM2;
-
- return tpm_chip_register(chip);
-}
-
static int crb_check_resource(struct acpi_resource *ares, void *data)
{
struct resource *io_res = data;
@@ -398,6 +383,7 @@ static int crb_acpi_add(struct acpi_device *device)
{
struct acpi_table_tpm2 *buf;
struct crb_priv *priv;
+ struct tpm_chip *chip;
struct device *dev = &device->dev;
acpi_status status;
u32 sm;
@@ -435,11 +421,19 @@ static int crb_acpi_add(struct acpi_device *device)
if (rc)
return rc;
+ chip = tpmm_chip_alloc(dev, &tpm_crb);
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+
+ dev_set_drvdata(&chip->dev, priv);
+ chip->acpi_dev_handle = device->handle;
+ chip->flags = TPM_CHIP_FLAG_TPM2;
+
rc = crb_cmd_ready(dev, priv);
if (rc)
return rc;
- rc = crb_init(device, priv);
+ rc = tpm_chip_register(chip);
if (rc)
crb_go_idle(dev, priv);
--
2.10.2
@@ -1,21 +0,0 @@
This patch adds module aliases for matching the old dm-raid45 patch
by heinzm@redhat.com carried by kernel-tmb series in order to make
sure there is an upgrade path.
Signed-off-by: Thomas Backlund <tmb@mageia.org>
drivers/md/dm-raid.c | 2 ++
1 file changed, 2 insertions(+)
--- linux/drivers/md/dm-raid.c.orig
+++ linux/drivers/md/dm-raid.c
@@ -3689,6 +3689,8 @@ MODULE_ALIAS("dm-raid10");
MODULE_ALIAS("dm-raid4");
MODULE_ALIAS("dm-raid5");
MODULE_ALIAS("dm-raid6");
+MODULE_ALIAS("dm-raid45");
+MODULE_ALIAS("dm-raid4-5");
MODULE_AUTHOR("Neil Brown <dm-devel@redhat.com>");
MODULE_AUTHOR("Heinz Mauelshagen <dm-devel@redhat.com>");
MODULE_LICENSE("GPL");
@@ -1,29 +0,0 @@
This patch adds missing module aliases for the old ieee1394 stack
to make it easier for endusers.
Note: firewire-sbp2 and firewire-ohci already contains the needed aliases.
Signed-off-by: Thomas Backlund <tmb@mageia.org>
diff -Nurp linux-2.6.38.4/drivers/firewire/core-transaction.c linux-2.6.38.4.fw/drivers/firewire/core-transaction.c
--- linux-2.6.38.4/drivers/firewire/core-transaction.c 2011-03-15 03:20:32.000000000 +0200
+++ linux-2.6.38.4.fw/drivers/firewire/core-transaction.c 2011-04-22 16:22:28.461386738 +0300
@@ -1174,6 +1174,9 @@ static struct fw_address_handler registe
MODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>");
MODULE_DESCRIPTION("Core IEEE1394 transaction logic");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("ieee1394");
+MODULE_ALIAS("raw1394");
+MODULE_ALIAS("video1394");
static const u32 vendor_textual_descriptor[] = {
/* textual descriptor leaf () */
diff -Nurp linux-2.6.38.4/drivers/firewire/net.c linux-2.6.38.4.fw/drivers/firewire/net.c
--- linux-2.6.38.4/drivers/firewire/net.c 2011-03-15 03:20:32.000000000 +0200
+++ linux-2.6.38.4.fw/drivers/firewire/net.c 2011-04-22 16:20:34.008883920 +0300
@@ -1719,3 +1719,4 @@ MODULE_AUTHOR("Jay Fenlason <fenlason@re
MODULE_DESCRIPTION("IP over IEEE1394 as per RFC 2734/3146");
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(ieee1394, fwnet_id_table);
+MODULE_ALIAS("eth1394");
@@ -0,0 +1,39 @@
From 88ab55f16aae90e2e974eb67cc2380edb92b0661 Mon Sep 17 00:00:00 2001
From: Namjae Jeon <namjae.jeon@samsung.com>
Date: Mon, 2 Mar 2020 15:21:43 +0900
Subject: [PATCH 12/14] MAINTAINERS: add exfat filesystem
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Add myself and Sungjong Seo as exfat maintainer.
Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com>
Signed-off-by: Sungjong Seo <sj1557.seo@samsung.com>
Reviewed-by: Pali Rohár <pali.rohar@gmail.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
MAINTAINERS | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 38fe2f3f7b6f..27d912bc5ae2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6240,6 +6240,13 @@ F: include/trace/events/mdio.h
F: include/uapi/linux/mdio.h
F: include/uapi/linux/mii.h
+EXFAT FILE SYSTEM
+M: Namjae Jeon <namjae.jeon@samsung.com>
+M: Sungjong Seo <sj1557.seo@samsung.com>
+L: linux-fsdevel@vger.kernel.org
+S: Maintained
+F: fs/exfat/
+
EXT2 FILE SYSTEM
M: Jan Kara <jack@suse.com>
L: linux-ext4@vger.kernel.org
--
2.25.1
@@ -1,402 +0,0 @@
fs/aufs/Kconfig | 2 +-
fs/dcache.c | 2 ++
fs/exec.c | 1 +
fs/fcntl.c | 1 +
fs/file_table.c | 4 ++++
fs/inode.c | 1 +
fs/namespace.c | 2 ++
fs/notify/group.c | 4 ++++
fs/notify/mark.c | 4 ++++
fs/open.c | 2 ++
fs/read_write.c | 2 ++
fs/splice.c | 2 ++
fs/xattr.c | 1 +
kernel/task_work.c | 1 +
security/commoncap.c | 2 ++
security/device_cgroup.c | 2 ++
security/security.c | 10 ++++++++++
17 files changed, 42 insertions(+), 1 deletion(-)
diff -Nurp linux-4.9-aufs/fs/aufs/Kconfig linux-4.9-aufs-mod/fs/aufs/Kconfig
--- linux-4.9-aufs/fs/aufs/Kconfig 2016-12-31 00:31:52.367789380 +0200
+++ linux-4.9-aufs-mod/fs/aufs/Kconfig 2016-12-31 00:32:35.153785422 +0200
@@ -1,5 +1,5 @@
config AUFS_FS
- bool "Aufs (Advanced multi layered unification filesystem) support"
+ tristate "Aufs (Advanced multi layered unification filesystem) support"
help
Aufs is a stackable unification filesystem such as Unionfs,
which unifies several directories and provides a merged single
diff -Nurp linux-4.9-aufs/fs/dcache.c linux-4.9-aufs-mod/fs/dcache.c
--- linux-4.9-aufs/fs/dcache.c 2016-12-31 00:31:52.379789379 +0200
+++ linux-4.9-aufs-mod/fs/dcache.c 2016-12-31 01:49:12.324360147 +0200
@@ -1272,6 +1272,7 @@ rename_retry:
seq = 1;
goto again;
}
+EXPORT_SYMBOL_GPL(d_walk);
/*
* Search for at least 1 mount point in the dentry's subdirs.
@@ -2855,6 +2856,7 @@ void d_exchange(struct dentry *dentry1,
write_sequnlock(&rename_lock);
}
+EXPORT_SYMBOL_GPL(d_exchange);
/**
* d_ancestor - search for an ancestor
diff -Nurp linux-4.9-aufs/fs/exec.c linux-4.9-aufs-mod/fs/exec.c
--- linux-4.9-aufs/fs/exec.c 2016-12-11 21:17:54.000000000 +0200
+++ linux-4.9-aufs-mod/fs/exec.c 2016-12-31 00:32:35.153785422 +0200
@@ -104,6 +104,7 @@ bool path_noexec(const struct path *path
return (path->mnt->mnt_flags & MNT_NOEXEC) ||
(path->mnt->mnt_sb->s_iflags & SB_I_NOEXEC);
}
+EXPORT_SYMBOL_GPL(path_noexec);
#ifdef CONFIG_USELIB
/*
diff -Nurp linux-4.9-aufs/fs/fcntl.c linux-4.9-aufs-mod/fs/fcntl.c
--- linux-4.9-aufs/fs/fcntl.c 2016-12-31 00:31:52.379789379 +0200
+++ linux-4.9-aufs-mod/fs/fcntl.c 2016-12-31 00:32:35.154785422 +0200
@@ -82,6 +82,7 @@ int setfl(int fd, struct file * filp, un
out:
return error;
}
+EXPORT_SYMBOL_GPL(setfl);
static void f_modown(struct file *filp, struct pid *pid, enum pid_type type,
int force)
diff -Nurp linux-4.9-aufs/fs/file_table.c linux-4.9-aufs-mod/fs/file_table.c
--- linux-4.9-aufs/fs/file_table.c 2016-12-11 21:17:54.000000000 +0200
+++ linux-4.9-aufs-mod/fs/file_table.c 2016-12-31 00:32:35.154785422 +0200
@@ -147,6 +147,7 @@ over:
}
return ERR_PTR(-ENFILE);
}
+EXPORT_SYMBOL_GPL(get_empty_filp);
/**
* alloc_file - allocate and initialize a 'struct file'
@@ -258,6 +259,7 @@ void flush_delayed_fput(void)
{
delayed_fput(NULL);
}
+EXPORT_SYMBOL_GPL(flush_delayed_fput);
static DECLARE_DELAYED_WORK(delayed_fput_work, delayed_fput);
@@ -300,6 +302,7 @@ void __fput_sync(struct file *file)
}
EXPORT_SYMBOL(fput);
+EXPORT_SYMBOL_GPL(__fput_sync);
void put_filp(struct file *file)
{
@@ -308,6 +311,7 @@ void put_filp(struct file *file)
file_free(file);
}
}
+EXPORT_SYMBOL_GPL(put_filp);
void __init files_init(void)
{
diff -Nurp linux-4.9-aufs/fs/inode.c linux-4.9-aufs-mod/fs/inode.c
--- linux-4.9-aufs/fs/inode.c 2016-12-31 00:31:52.379789379 +0200
+++ linux-4.9-aufs-mod/fs/inode.c 2016-12-31 00:32:35.154785422 +0200
@@ -1651,6 +1651,7 @@ int update_time(struct inode *inode, str
return update_time(inode, time, flags);
}
+EXPORT_SYMBOL_GPL(update_time);
/**
* touch_atime - update the access time
diff -Nurp linux-4.9-aufs/fs/namespace.c linux-4.9-aufs-mod/fs/namespace.c
--- linux-4.9-aufs/fs/namespace.c 2016-12-11 21:17:54.000000000 +0200
+++ linux-4.9-aufs-mod/fs/namespace.c 2016-12-31 00:32:35.154785422 +0200
@@ -466,6 +466,7 @@ void __mnt_drop_write(struct vfsmount *m
mnt_dec_writers(real_mount(mnt));
preempt_enable();
}
+EXPORT_SYMBOL_GPL(__mnt_drop_write);
/**
* mnt_drop_write - give up write access to a mount
@@ -1823,6 +1824,7 @@ int iterate_mounts(int (*f)(struct vfsmo
}
return 0;
}
+EXPORT_SYMBOL_GPL(iterate_mounts);
static void cleanup_group_ids(struct mount *mnt, struct mount *end)
{
diff -Nurp linux-4.9-aufs/fs/notify/group.c linux-4.9-aufs-mod/fs/notify/group.c
--- linux-4.9-aufs/fs/notify/group.c 2016-12-11 21:17:54.000000000 +0200
+++ linux-4.9-aufs-mod/fs/notify/group.c 2016-12-31 00:32:35.155785422 +0200
@@ -22,6 +22,7 @@
#include <linux/srcu.h>
#include <linux/rculist.h>
#include <linux/wait.h>
+#include <linux/module.h>
#include <linux/fsnotify_backend.h>
#include "fsnotify.h"
@@ -100,6 +101,7 @@ void fsnotify_get_group(struct fsnotify_
{
atomic_inc(&group->refcnt);
}
+EXPORT_SYMBOL_GPL(fsnotify_get_group);
/*
* Drop a reference to a group. Free it if it's through.
@@ -109,6 +111,7 @@ void fsnotify_put_group(struct fsnotify_
if (atomic_dec_and_test(&group->refcnt))
fsnotify_final_destroy_group(group);
}
+EXPORT_SYMBOL_GPL(fsnotify_put_group);
/*
* Create a new fsnotify_group and hold a reference for the group returned.
@@ -137,6 +140,7 @@ struct fsnotify_group *fsnotify_alloc_gr
return group;
}
+EXPORT_SYMBOL_GPL(fsnotify_alloc_group);
int fsnotify_fasync(int fd, struct file *file, int on)
{
diff -Nurp linux-4.9-aufs/fs/notify/mark.c linux-4.9-aufs-mod/fs/notify/mark.c
--- linux-4.9-aufs/fs/notify/mark.c 2016-12-11 21:17:54.000000000 +0200
+++ linux-4.9-aufs-mod/fs/notify/mark.c 2016-12-31 00:32:35.155785422 +0200
@@ -113,6 +113,7 @@ void fsnotify_put_mark(struct fsnotify_m
mark->free_mark(mark);
}
}
+EXPORT_SYMBOL_GPL(fsnotify_put_mark);
/* Calculate mask of events for a list of marks */
u32 fsnotify_recalc_mask(struct hlist_head *head)
@@ -230,6 +231,7 @@ void fsnotify_destroy_mark(struct fsnoti
mutex_unlock(&group->mark_mutex);
fsnotify_free_mark(mark);
}
+EXPORT_SYMBOL_GPL(fsnotify_destroy_mark);
void fsnotify_destroy_marks(struct hlist_head *head, spinlock_t *lock)
{
@@ -415,6 +417,7 @@ err:
return ret;
}
+EXPORT_SYMBOL_GPL(fsnotify_add_mark);
int fsnotify_add_mark(struct fsnotify_mark *mark, struct fsnotify_group *group,
struct inode *inode, struct vfsmount *mnt, int allow_dups)
@@ -521,6 +524,7 @@ void fsnotify_duplicate_mark(struct fsno
new->mask = old->mask;
new->free_mark = old->free_mark;
}
+EXPORT_SYMBOL_GPL(fsnotify_init_mark);
/*
* Nothing fancy, just initialize lists and locks and counters.
diff -Nurp linux-4.9-aufs/fs/open.c linux-4.9-aufs-mod/fs/open.c
--- linux-4.9-aufs/fs/open.c 2016-12-11 21:17:54.000000000 +0200
+++ linux-4.9-aufs-mod/fs/open.c 2016-12-31 00:32:35.155785422 +0200
@@ -64,6 +64,7 @@ int do_truncate(struct dentry *dentry, l
inode_unlock(dentry->d_inode);
return ret;
}
+EXPORT_SYMBOL_GPL(do_truncate);
long vfs_truncate(const struct path *path, loff_t length)
{
@@ -695,6 +696,7 @@ int open_check_o_direct(struct file *f)
}
return 0;
}
+EXPORT_SYMBOL_GPL(open_check_o_direct);
static int do_dentry_open(struct file *f,
struct inode *inode,
diff -Nurp linux-4.9-aufs/fs/read_write.c linux-4.9-aufs-mod/fs/read_write.c
--- linux-4.9-aufs/fs/read_write.c 2016-12-31 00:31:52.380789379 +0200
+++ linux-4.9-aufs-mod/fs/read_write.c 2016-12-31 00:32:35.155785422 +0200
@@ -525,6 +525,7 @@ vfs_readf_t vfs_readf(struct file *file)
return new_sync_read;
return ERR_PTR(-ENOSYS);
}
+EXPORT_SYMBOL_GPL(vfs_readf);
vfs_writef_t vfs_writef(struct file *file)
{
@@ -536,6 +537,7 @@ vfs_writef_t vfs_writef(struct file *fil
return new_sync_write;
return ERR_PTR(-ENOSYS);
}
+EXPORT_SYMBOL_GPL(vfs_writef);
ssize_t __kernel_write(struct file *file, const char *buf, size_t count, loff_t *pos)
{
diff -Nurp linux-4.9-aufs/fs/splice.c linux-4.9-aufs-mod/fs/splice.c
--- linux-4.9-aufs/fs/splice.c 2016-12-31 00:31:52.380789379 +0200
+++ linux-4.9-aufs-mod/fs/splice.c 2016-12-31 00:32:35.156785422 +0200
@@ -868,6 +868,7 @@ long do_splice_from(struct pipe_inode_in
return splice_write(pipe, out, ppos, len, flags);
}
+EXPORT_SYMBOL_GPL(do_splice_from);
/*
* Attempt to initiate a splice from a file to a pipe.
@@ -897,6 +898,7 @@ long do_splice_to(struct file *in, loff_
return splice_read(in, ppos, pipe, len, flags);
}
+EXPORT_SYMBOL_GPL(do_splice_to);
/**
* splice_direct_to_actor - splices data directly between two non-pipes
diff -Nurp linux-4.9-aufs/fs/xattr.c linux-4.9-aufs-mod/fs/xattr.c
--- linux-4.9-aufs/fs/xattr.c 2016-12-11 21:17:54.000000000 +0200
+++ linux-4.9-aufs-mod/fs/xattr.c 2016-12-31 00:32:35.156785422 +0200
@@ -296,6 +296,7 @@ vfs_getxattr_alloc(struct dentry *dentry
*xattr_value = value;
return error;
}
+EXPORT_SYMBOL_GPL(vfs_getxattr_alloc);
ssize_t
__vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name,
diff -Nurp linux-4.9-aufs/kernel/task_work.c linux-4.9-aufs-mod/kernel/task_work.c
--- linux-4.9-aufs/kernel/task_work.c 2016-12-11 21:17:54.000000000 +0200
+++ linux-4.9-aufs-mod/kernel/task_work.c 2016-12-31 00:32:35.156785422 +0200
@@ -119,3 +119,4 @@ void task_work_run(void)
} while (work);
}
}
+EXPORT_SYMBOL_GPL(task_work_run);
diff -Nurp linux-4.9-aufs/security/commoncap.c linux-4.9-aufs-mod/security/commoncap.c
--- linux-4.9-aufs/security/commoncap.c 2016-12-11 21:17:54.000000000 +0200
+++ linux-4.9-aufs-mod/security/commoncap.c 2016-12-31 00:32:35.156785422 +0200
@@ -1061,12 +1061,14 @@ int cap_mmap_addr(unsigned long addr)
}
return ret;
}
+EXPORT_SYMBOL_GPL(cap_mmap_addr);
int cap_mmap_file(struct file *file, unsigned long reqprot,
unsigned long prot, unsigned long flags)
{
return 0;
}
+EXPORT_SYMBOL_GPL(cap_mmap_file);
#ifdef CONFIG_SECURITY
diff -Nurp linux-4.9-aufs/security/device_cgroup.c linux-4.9-aufs-mod/security/device_cgroup.c
--- linux-4.9-aufs/security/device_cgroup.c 2016-12-11 21:17:54.000000000 +0200
+++ linux-4.9-aufs-mod/security/device_cgroup.c 2016-12-31 00:32:35.156785422 +0200
@@ -7,6 +7,7 @@
#include <linux/device_cgroup.h>
#include <linux/cgroup.h>
#include <linux/ctype.h>
+#include <linux/export.h>
#include <linux/list.h>
#include <linux/uaccess.h>
#include <linux/seq_file.h>
@@ -849,6 +850,7 @@ int __devcgroup_inode_permission(struct
return __devcgroup_check_permission(type, imajor(inode), iminor(inode),
access);
}
+EXPORT_SYMBOL_GPL(__devcgroup_inode_permission);
int devcgroup_inode_mknod(int mode, dev_t dev)
{
diff -Nurp linux-4.9-aufs/security/security.c linux-4.9-aufs-mod/security/security.c
--- linux-4.9-aufs/security/security.c 2016-12-11 21:17:54.000000000 +0200
+++ linux-4.9-aufs-mod/security/security.c 2016-12-31 00:32:35.157785422 +0200
@@ -443,6 +443,7 @@ int security_path_rmdir(const struct pat
return 0;
return call_int_hook(path_rmdir, 0, dir, dentry);
}
+EXPORT_SYMBOL_GPL(security_path_rmdir);
int security_path_unlink(const struct path *dir, struct dentry *dentry)
{
@@ -459,6 +460,7 @@ int security_path_symlink(const struct p
return 0;
return call_int_hook(path_symlink, 0, dir, dentry, old_name);
}
+EXPORT_SYMBOL_GPL(security_path_symlink);
int security_path_link(struct dentry *old_dentry, const struct path *new_dir,
struct dentry *new_dentry)
@@ -467,6 +469,7 @@ int security_path_link(struct dentry *ol
return 0;
return call_int_hook(path_link, 0, old_dentry, new_dir, new_dentry);
}
+EXPORT_SYMBOL_GPL(security_path_link);
int security_path_rename(const struct path *old_dir, struct dentry *old_dentry,
const struct path *new_dir, struct dentry *new_dentry,
@@ -494,6 +497,7 @@ int security_path_truncate(const struct
return 0;
return call_int_hook(path_truncate, 0, path);
}
+EXPORT_SYMBOL_GPL(security_path_truncate);
int security_path_chmod(const struct path *path, umode_t mode)
{
@@ -501,6 +505,7 @@ int security_path_chmod(const struct pat
return 0;
return call_int_hook(path_chmod, 0, path, mode);
}
+EXPORT_SYMBOL_GPL(security_path_chmod);
int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid)
{
@@ -508,6 +513,7 @@ int security_path_chown(const struct pat
return 0;
return call_int_hook(path_chown, 0, path, uid, gid);
}
+EXPORT_SYMBOL_GPL(security_path_chown);
int security_path_chroot(const struct path *path)
{
@@ -593,6 +599,7 @@ int security_inode_readlink(struct dentr
return 0;
return call_int_hook(inode_readlink, 0, dentry);
}
+EXPORT_SYMBOL_GPL(security_inode_readlink);
int security_inode_follow_link(struct dentry *dentry, struct inode *inode,
bool rcu)
@@ -608,6 +615,7 @@ int security_inode_permission(struct ino
return 0;
return call_int_hook(inode_permission, 0, inode, mask);
}
+EXPORT_SYMBOL_GPL(security_inode_permission);
int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
{
@@ -779,6 +787,7 @@ int security_file_permission(struct file
return fsnotify_perm(file, mask);
}
+EXPORT_SYMBOL_GPL(security_file_permission);
int security_file_alloc(struct file *file)
{
@@ -838,6 +847,7 @@ int security_mmap_file(struct file *file
return ret;
return ima_file_mmap(file, prot);
}
+EXPORT_SYMBOL_GPL(security_mmap_file);
int security_mmap_addr(unsigned long addr)
{
File diff suppressed because it is too large Load Diff
@@ -1,12 +0,0 @@
diff -Nurp linux-5.3-aufs/include/uapi/linux/aufs_type.h linux-5.3-aufs-ver/include/uapi/linux/aufs_type.h
--- linux-5.3-aufs/include/uapi/linux/aufs_type.h 2019-09-24 16:13:44.012259519 +0300
+++ linux-5.3-aufs-ver/include/uapi/linux/aufs_type.h 2019-09-24 20:04:21.924707762 +0300
@@ -27,7 +27,7 @@
#include <linux/limits.h>
-#define AUFS_VERSION "5.x-rcN"
+#define AUFS_VERSION "5.4"
/* todo? move this to linux-2.6.19/include/magic.h */
#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
@@ -0,0 +1,39 @@
diff -Nurp linux-5.6.3-aufs/fs/aufs/procfs.c linux-5.6.3-aufs-fix/fs/aufs/procfs.c
--- linux-5.6.3-aufs/fs/aufs/procfs.c 2020-04-10 12:40:52.192049502 +0300
+++ linux-5.6.3-aufs-fix/fs/aufs/procfs.c 2020-04-10 17:46:50.019444421 +0300
@@ -116,10 +116,9 @@ out:
return err;
}
-static const struct file_operations au_procfs_plm_fop = {
- .write = au_procfs_plm_write,
- .release = au_procfs_plm_release,
- .owner = THIS_MODULE
+static const struct proc_ops au_procfs_plm_op = {
+ .proc_write = au_procfs_plm_write,
+ .proc_release = au_procfs_plm_release
};
/* ---------------------------------------------------------------------- */
@@ -143,7 +142,7 @@ int __init au_procfs_init(void)
goto out;
entry = proc_create(AUFS_PLINK_MAINT_NAME, S_IFREG | 0200,
- au_procfs_dir, &au_procfs_plm_fop);
+ au_procfs_dir, &au_procfs_plm_op);
if (unlikely(!entry))
goto out_dir;
diff -Nurp linux-5.6.3-aufs/fs/aufs/xino.c linux-5.6.3-aufs-fix/fs/aufs/xino.c
--- linux-5.6.3-aufs/fs/aufs/xino.c 2020-04-10 12:40:52.193049549 +0300
+++ linux-5.6.3-aufs-fix/fs/aufs/xino.c 2020-04-10 17:46:25.165284147 +0300
@@ -1344,7 +1344,8 @@ static void au_xino_release(struct kref
hlist_bl_lock(hbl);
hlist_bl_for_each_entry_safe(p, pos, n, hbl, node) {
hlist_bl_del(&p->node);
- au_kfree_rcu(p);
+ /* kmemleak reported au_kfree_rcu() doesn't free it */
+ kfree(p);
}
hlist_bl_unlock(hbl);
}
@@ -14,13 +14,12 @@
fs/xattr.c | 1 +
kernel/locking/lockdep.c | 1 +
kernel/task_work.c | 1 +
security/device_cgroup.c | 1 +
security/security.c | 8 ++++++++
17 files changed, 32 insertions(+), 1 deletion(-)
16 files changed, 31 insertions(+), 1 deletion(-)
diff -Nurp linux-5.4-aufs/fs/aufs/Kconfig linux-5.4-aufs-mod/fs/aufs/Kconfig
--- linux-5.4-aufs/fs/aufs/Kconfig 2019-11-28 01:25:59.062925618 +0200
+++ linux-5.4-aufs-mod/fs/aufs/Kconfig 2019-11-28 01:38:40.564895255 +0200
diff -Nurp linux-5.6.3-aufs/fs/aufs/Kconfig linux-5.6.3-aufs-mod/fs/aufs/Kconfig
--- linux-5.6.3-aufs/fs/aufs/Kconfig 2020-04-10 12:40:52.187049268 +0300
+++ linux-5.6.3-aufs-mod/fs/aufs/Kconfig 2020-04-10 13:15:44.979742386 +0300
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
config AUFS_FS
@@ -29,10 +28,10 @@ diff -Nurp linux-5.4-aufs/fs/aufs/Kconfig linux-5.4-aufs-mod/fs/aufs/Kconfig
help
Aufs is a stackable unification filesystem such as Unionfs,
which unifies several directories and provides a merged single
diff -Nurp linux-5.4-aufs/fs/dcache.c linux-5.4-aufs-mod/fs/dcache.c
--- linux-5.4-aufs/fs/dcache.c 2019-11-28 01:25:59.069925618 +0200
+++ linux-5.4-aufs-mod/fs/dcache.c 2019-11-28 01:38:40.585895254 +0200
@@ -1369,6 +1369,7 @@ rename_retry:
diff -Nurp linux-5.6.3-aufs/fs/dcache.c linux-5.6.3-aufs-mod/fs/dcache.c
--- linux-5.6.3-aufs/fs/dcache.c 2020-04-10 12:40:52.194049596 +0300
+++ linux-5.6.3-aufs-mod/fs/dcache.c 2020-04-10 13:15:44.979742386 +0300
@@ -1371,6 +1371,7 @@ rename_retry:
seq = 1;
goto again;
}
@@ -40,7 +39,7 @@ diff -Nurp linux-5.4-aufs/fs/dcache.c linux-5.4-aufs-mod/fs/dcache.c
struct check_mount {
struct vfsmount *mnt;
@@ -2914,6 +2915,7 @@ void d_exchange(struct dentry *dentry1,
@@ -2916,6 +2917,7 @@ void d_exchange(struct dentry *dentry1,
write_sequnlock(&rename_lock);
}
@@ -48,10 +47,10 @@ diff -Nurp linux-5.4-aufs/fs/dcache.c linux-5.4-aufs-mod/fs/dcache.c
/**
* d_ancestor - search for an ancestor
diff -Nurp linux-5.4-aufs/fs/exec.c linux-5.4-aufs-mod/fs/exec.c
--- linux-5.4-aufs/fs/exec.c 2019-11-25 02:32:01.000000000 +0200
+++ linux-5.4-aufs-mod/fs/exec.c 2019-11-28 01:38:40.589895254 +0200
@@ -110,6 +110,7 @@ bool path_noexec(const struct path *path
diff -Nurp linux-5.6.3-aufs/fs/exec.c linux-5.6.3-aufs-mod/fs/exec.c
--- linux-5.6.3-aufs/fs/exec.c 2020-03-30 01:25:41.000000000 +0300
+++ linux-5.6.3-aufs-mod/fs/exec.c 2020-04-10 13:15:44.979742386 +0300
@@ -109,6 +109,7 @@ bool path_noexec(const struct path *path
return (path->mnt->mnt_flags & MNT_NOEXEC) ||
(path->mnt->mnt_sb->s_iflags & SB_I_NOEXEC);
}
@@ -59,10 +58,10 @@ diff -Nurp linux-5.4-aufs/fs/exec.c linux-5.4-aufs-mod/fs/exec.c
#ifdef CONFIG_USELIB
/*
diff -Nurp linux-5.4-aufs/fs/fcntl.c linux-5.4-aufs-mod/fs/fcntl.c
--- linux-5.4-aufs/fs/fcntl.c 2019-11-28 01:25:59.069925618 +0200
+++ linux-5.4-aufs-mod/fs/fcntl.c 2019-11-28 01:38:40.589895254 +0200
@@ -85,6 +85,7 @@ int setfl(int fd, struct file * filp, un
diff -Nurp linux-5.6.3-aufs/fs/fcntl.c linux-5.6.3-aufs-mod/fs/fcntl.c
--- linux-5.6.3-aufs/fs/fcntl.c 2020-04-10 12:40:52.194049596 +0300
+++ linux-5.6.3-aufs-mod/fs/fcntl.c 2020-04-10 13:15:44.979742386 +0300
@@ -85,6 +85,7 @@ int setfl(int fd, struct file *filp, uns
out:
return error;
}
@@ -70,9 +69,9 @@ diff -Nurp linux-5.4-aufs/fs/fcntl.c linux-5.4-aufs-mod/fs/fcntl.c
static void f_modown(struct file *filp, struct pid *pid, enum pid_type type,
int force)
diff -Nurp linux-5.4-aufs/fs/file_table.c linux-5.4-aufs-mod/fs/file_table.c
--- linux-5.4-aufs/fs/file_table.c 2019-11-25 02:32:01.000000000 +0200
+++ linux-5.4-aufs-mod/fs/file_table.c 2019-11-28 01:38:40.589895254 +0200
diff -Nurp linux-5.6.3-aufs/fs/file_table.c linux-5.6.3-aufs-mod/fs/file_table.c
--- linux-5.6.3-aufs/fs/file_table.c 2020-03-30 01:25:41.000000000 +0300
+++ linux-5.6.3-aufs-mod/fs/file_table.c 2020-04-10 13:15:44.979742386 +0300
@@ -162,6 +162,7 @@ over:
}
return ERR_PTR(-ENFILE);
@@ -81,7 +80,7 @@ diff -Nurp linux-5.4-aufs/fs/file_table.c linux-5.4-aufs-mod/fs/file_table.c
/*
* Variant of alloc_empty_file() that doesn't check and modify nr_files.
@@ -375,6 +377,7 @@ void __fput_sync(struct file *file)
@@ -375,6 +376,7 @@ void __fput_sync(struct file *file)
}
EXPORT_SYMBOL(fput);
@@ -89,20 +88,20 @@ diff -Nurp linux-5.4-aufs/fs/file_table.c linux-5.4-aufs-mod/fs/file_table.c
void __init files_init(void)
{
diff -Nurp linux-5.4-aufs/fs/inode.c linux-5.4-aufs-mod/fs/inode.c
--- linux-5.4-aufs/fs/inode.c 2019-11-28 01:25:59.070925617 +0200
+++ linux-5.4-aufs-mod/fs/inode.c 2019-11-28 01:38:40.589895254 +0200
@@ -1682,6 +1682,7 @@ int update_time(struct inode *inode, str
return update_time(inode, time, flags);
diff -Nurp linux-5.6.3-aufs/fs/inode.c linux-5.6.3-aufs-mod/fs/inode.c
--- linux-5.6.3-aufs/fs/inode.c 2020-04-10 12:40:52.194049596 +0300
+++ linux-5.6.3-aufs-mod/fs/inode.c 2020-04-10 13:15:44.980742432 +0300
@@ -1694,6 +1694,7 @@ int update_time(struct inode *inode, str
return inode->i_op->update_time(inode, time, flags);
return generic_update_time(inode, time, flags);
}
+EXPORT_SYMBOL_GPL(update_time);
/**
* touch_atime - update the access time
diff -Nurp linux-5.4-aufs/fs/namespace.c linux-5.4-aufs-mod/fs/namespace.c
--- linux-5.4-aufs/fs/namespace.c 2019-11-28 01:25:59.070925617 +0200
+++ linux-5.4-aufs-mod/fs/namespace.c 2019-11-28 01:38:40.589895254 +0200
diff -Nurp linux-5.6.3-aufs/fs/namespace.c linux-5.6.3-aufs-mod/fs/namespace.c
--- linux-5.6.3-aufs/fs/namespace.c 2020-04-10 12:40:52.194049596 +0300
+++ linux-5.6.3-aufs-mod/fs/namespace.c 2020-04-10 13:15:44.980742432 +0300
@@ -431,6 +431,7 @@ void __mnt_drop_write(struct vfsmount *m
mnt_dec_writers(real_mount(mnt));
preempt_enable();
@@ -127,9 +126,9 @@ diff -Nurp linux-5.4-aufs/fs/namespace.c linux-5.4-aufs-mod/fs/namespace.c
static void lock_mnt_tree(struct mount *mnt)
{
diff -Nurp linux-5.4-aufs/fs/notify/group.c linux-5.4-aufs-mod/fs/notify/group.c
--- linux-5.4-aufs/fs/notify/group.c 2019-11-25 02:32:01.000000000 +0200
+++ linux-5.4-aufs-mod/fs/notify/group.c 2019-11-28 01:38:40.590895253 +0200
diff -Nurp linux-5.6.3-aufs/fs/notify/group.c linux-5.6.3-aufs-mod/fs/notify/group.c
--- linux-5.6.3-aufs/fs/notify/group.c 2020-03-30 01:25:41.000000000 +0300
+++ linux-5.6.3-aufs-mod/fs/notify/group.c 2020-04-10 13:15:44.980742432 +0300
@@ -99,6 +99,7 @@ void fsnotify_get_group(struct fsnotify_
{
refcount_inc(&group->refcnt);
@@ -138,9 +137,9 @@ diff -Nurp linux-5.4-aufs/fs/notify/group.c linux-5.4-aufs-mod/fs/notify/group.c
/*
* Drop a reference to a group. Free it if it's through.
diff -Nurp linux-5.4-aufs/fs/open.c linux-5.4-aufs-mod/fs/open.c
--- linux-5.4-aufs/fs/open.c 2019-11-25 02:32:01.000000000 +0200
+++ linux-5.4-aufs-mod/fs/open.c 2019-11-28 01:38:48.762894928 +0200
diff -Nurp linux-5.6.3-aufs/fs/open.c linux-5.6.3-aufs-mod/fs/open.c
--- linux-5.6.3-aufs/fs/open.c 2020-03-30 01:25:41.000000000 +0300
+++ linux-5.6.3-aufs-mod/fs/open.c 2020-04-10 13:15:44.980742432 +0300
@@ -65,6 +65,7 @@ int do_truncate(struct dentry *dentry, l
inode_unlock(dentry->d_inode);
return ret;
@@ -149,9 +148,9 @@ diff -Nurp linux-5.4-aufs/fs/open.c linux-5.4-aufs-mod/fs/open.c
long vfs_truncate(const struct path *path, loff_t length)
{
diff -Nurp linux-5.4-aufs/fs/read_write.c linux-5.4-aufs-mod/fs/read_write.c
--- linux-5.4-aufs/fs/read_write.c 2019-11-28 01:25:59.070925617 +0200
+++ linux-5.4-aufs-mod/fs/read_write.c 2019-11-28 01:38:48.780894927 +0200
diff -Nurp linux-5.6.3-aufs/fs/read_write.c linux-5.6.3-aufs-mod/fs/read_write.c
--- linux-5.6.3-aufs/fs/read_write.c 2020-04-10 12:40:52.194049596 +0300
+++ linux-5.6.3-aufs-mod/fs/read_write.c 2020-04-10 13:15:44.981742479 +0300
@@ -468,6 +468,7 @@ ssize_t vfs_read(struct file *file, char
return ret;
@@ -162,7 +161,7 @@ diff -Nurp linux-5.4-aufs/fs/read_write.c linux-5.4-aufs-mod/fs/read_write.c
{
@@ -508,6 +509,7 @@ vfs_readf_t vfs_readf(struct file *file)
return new_sync_read;
return ERR_PTR(-ENOSYS);
return ERR_PTR(-ENOSYS); /* doesn't have ->read(|_iter)() op */
}
+EXPORT_SYMBOL_GPL(vfs_readf);
@@ -170,7 +169,7 @@ diff -Nurp linux-5.4-aufs/fs/read_write.c linux-5.4-aufs-mod/fs/read_write.c
{
@@ -519,6 +521,7 @@ vfs_writef_t vfs_writef(struct file *fil
return new_sync_write;
return ERR_PTR(-ENOSYS);
return ERR_PTR(-ENOSYS); /* doesn't have ->write(|_iter)() op */
}
+EXPORT_SYMBOL_GPL(vfs_writef);
@@ -184,10 +183,10 @@ diff -Nurp linux-5.4-aufs/fs/read_write.c linux-5.4-aufs-mod/fs/read_write.c
/* file_ppos returns &file->f_pos or NULL if file is stream */
static inline loff_t *file_ppos(struct file *file)
diff -Nurp linux-5.4-aufs/fs/splice.c linux-5.4-aufs-mod/fs/splice.c
--- linux-5.4-aufs/fs/splice.c 2019-11-28 01:25:59.071925617 +0200
+++ linux-5.4-aufs-mod/fs/splice.c 2019-11-28 01:38:48.780894927 +0200
@@ -847,6 +847,7 @@ long do_splice_from(struct pipe_inode_in
diff -Nurp linux-5.6.3-aufs/fs/splice.c linux-5.6.3-aufs-mod/fs/splice.c
--- linux-5.6.3-aufs/fs/splice.c 2020-04-10 12:40:52.194049596 +0300
+++ linux-5.6.3-aufs-mod/fs/splice.c 2020-04-10 13:15:44.981742479 +0300
@@ -862,6 +862,7 @@ long do_splice_from(struct pipe_inode_in
return splice_write(pipe, out, ppos, len, flags);
}
@@ -195,7 +194,7 @@ diff -Nurp linux-5.4-aufs/fs/splice.c linux-5.4-aufs-mod/fs/splice.c
/*
* Attempt to initiate a splice from a file to a pipe.
@@ -876,6 +877,7 @@ long do_splice_to(struct file *in, loff_
@@ -891,6 +892,7 @@ long do_splice_to(struct file *in, loff_
return splice_read(in, ppos, pipe, len, flags);
}
@@ -203,9 +202,9 @@ diff -Nurp linux-5.4-aufs/fs/splice.c linux-5.4-aufs-mod/fs/splice.c
/**
* splice_direct_to_actor - splices data directly between two non-pipes
diff -Nurp linux-5.4-aufs/fs/sync.c linux-5.4-aufs-mod/fs/sync.c
--- linux-5.4-aufs/fs/sync.c 2019-11-28 01:25:59.071925617 +0200
+++ linux-5.4-aufs-mod/fs/sync.c 2019-11-28 01:38:48.780894927 +0200
diff -Nurp linux-5.6.3-aufs/fs/sync.c linux-5.6.3-aufs-mod/fs/sync.c
--- linux-5.6.3-aufs/fs/sync.c 2020-04-10 12:40:52.194049596 +0300
+++ linux-5.6.3-aufs-mod/fs/sync.c 2020-04-10 13:15:44.981742479 +0300
@@ -39,6 +39,7 @@ int __sync_filesystem(struct super_block
sb->s_op->sync_fs(sb, wait);
return __sync_blockdev(sb->s_bdev, wait);
@@ -214,9 +213,9 @@ diff -Nurp linux-5.4-aufs/fs/sync.c linux-5.4-aufs-mod/fs/sync.c
/*
* Write out and wait upon all dirty data associated with this
diff -Nurp linux-5.4-aufs/fs/xattr.c linux-5.4-aufs-mod/fs/xattr.c
--- linux-5.4-aufs/fs/xattr.c 2019-11-25 02:32:01.000000000 +0200
+++ linux-5.4-aufs-mod/fs/xattr.c 2019-11-28 01:38:48.780894927 +0200
diff -Nurp linux-5.6.3-aufs/fs/xattr.c linux-5.6.3-aufs-mod/fs/xattr.c
--- linux-5.6.3-aufs/fs/xattr.c 2020-03-30 01:25:41.000000000 +0300
+++ linux-5.6.3-aufs-mod/fs/xattr.c 2020-04-10 13:15:44.981742479 +0300
@@ -296,6 +296,7 @@ vfs_getxattr_alloc(struct dentry *dentry
*xattr_value = value;
return error;
@@ -225,9 +224,9 @@ diff -Nurp linux-5.4-aufs/fs/xattr.c linux-5.4-aufs-mod/fs/xattr.c
ssize_t
__vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name,
diff -Nurp linux-5.4-aufs/kernel/locking/lockdep.c linux-5.4-aufs-mod/kernel/locking/lockdep.c
--- linux-5.4-aufs/kernel/locking/lockdep.c 2019-11-28 01:25:59.072925617 +0200
+++ linux-5.4-aufs-mod/kernel/locking/lockdep.c 2019-11-28 01:38:48.780894927 +0200
diff -Nurp linux-5.6.3-aufs/kernel/locking/lockdep.c linux-5.6.3-aufs-mod/kernel/locking/lockdep.c
--- linux-5.6.3-aufs/kernel/locking/lockdep.c 2020-04-10 12:40:52.195049643 +0300
+++ linux-5.6.3-aufs-mod/kernel/locking/lockdep.c 2020-04-10 13:15:44.982742525 +0300
@@ -174,6 +174,7 @@ inline struct lock_class *lockdep_hlock_
*/
return lock_classes + class_idx;
@@ -236,26 +235,18 @@ diff -Nurp linux-5.4-aufs/kernel/locking/lockdep.c linux-5.4-aufs-mod/kernel/loc
#define hlock_class(hlock) lockdep_hlock_class(hlock)
#ifdef CONFIG_LOCK_STAT
diff -Nurp linux-5.4-aufs/kernel/task_work.c linux-5.4-aufs-mod/kernel/task_work.c
--- linux-5.4-aufs/kernel/task_work.c 2019-11-25 02:32:01.000000000 +0200
+++ linux-5.4-aufs-mod/kernel/task_work.c 2019-11-28 01:38:48.786894927 +0200
diff -Nurp linux-5.6.3-aufs/kernel/task_work.c linux-5.6.3-aufs-mod/kernel/task_work.c
--- linux-5.6.3-aufs/kernel/task_work.c 2020-03-30 01:25:41.000000000 +0300
+++ linux-5.6.3-aufs-mod/kernel/task_work.c 2020-04-10 13:15:44.982742525 +0300
@@ -116,3 +116,4 @@ void task_work_run(void)
} while (work);
}
}
+EXPORT_SYMBOL_GPL(task_work_run);
diff -Nurp linux-5.4-aufs/security/device_cgroup.c linux-5.4-aufs-mod/security/device_cgroup.c
--- linux-5.4-aufs/security/device_cgroup.c 2019-11-25 02:32:01.000000000 +0200
+++ linux-5.4-aufs-mod/security/device_cgroup.c 2019-11-28 01:38:48.790894927 +0200
@@ -824,3 +824,4 @@ int __devcgroup_check_permission(short t
return 0;
}
+EXPORT_SYMBOL_GPL(__devcgroup_check_permission);
diff -Nurp linux-5.4-aufs/security/security.c linux-5.4-aufs-mod/security/security.c
--- linux-5.4-aufs/security/security.c 2019-11-25 02:32:01.000000000 +0200
+++ linux-5.4-aufs-mod/security/security.c 2019-11-28 01:38:48.794894926 +0200
@@ -1036,6 +1036,7 @@ int security_path_rmdir(const struct pat
diff -Nurp linux-5.6.3-aufs/security/security.c linux-5.6.3-aufs-mod/security/security.c
--- linux-5.6.3-aufs/security/security.c 2020-03-30 01:25:41.000000000 +0300
+++ linux-5.6.3-aufs-mod/security/security.c 2020-04-10 13:15:44.982742525 +0300
@@ -1068,6 +1068,7 @@ int security_path_rmdir(const struct pat
return 0;
return call_int_hook(path_rmdir, 0, dir, dentry);
}
@@ -263,7 +254,7 @@ diff -Nurp linux-5.4-aufs/security/security.c linux-5.4-aufs-mod/security/securi
int security_path_unlink(const struct path *dir, struct dentry *dentry)
{
@@ -1052,6 +1053,7 @@ int security_path_symlink(const struct p
@@ -1084,6 +1085,7 @@ int security_path_symlink(const struct p
return 0;
return call_int_hook(path_symlink, 0, dir, dentry, old_name);
}
@@ -271,7 +262,7 @@ diff -Nurp linux-5.4-aufs/security/security.c linux-5.4-aufs-mod/security/securi
int security_path_link(struct dentry *old_dentry, const struct path *new_dir,
struct dentry *new_dentry)
@@ -1060,6 +1062,7 @@ int security_path_link(struct dentry *ol
@@ -1092,6 +1094,7 @@ int security_path_link(struct dentry *ol
return 0;
return call_int_hook(path_link, 0, old_dentry, new_dir, new_dentry);
}
@@ -279,7 +270,7 @@ diff -Nurp linux-5.4-aufs/security/security.c linux-5.4-aufs-mod/security/securi
int security_path_rename(const struct path *old_dir, struct dentry *old_dentry,
const struct path *new_dir, struct dentry *new_dentry,
@@ -1087,6 +1090,7 @@ int security_path_truncate(const struct
@@ -1119,6 +1122,7 @@ int security_path_truncate(const struct
return 0;
return call_int_hook(path_truncate, 0, path);
}
@@ -287,7 +278,7 @@ diff -Nurp linux-5.4-aufs/security/security.c linux-5.4-aufs-mod/security/securi
int security_path_chmod(const struct path *path, umode_t mode)
{
@@ -1094,6 +1098,7 @@ int security_path_chmod(const struct pat
@@ -1126,6 +1130,7 @@ int security_path_chmod(const struct pat
return 0;
return call_int_hook(path_chmod, 0, path, mode);
}
@@ -295,7 +286,7 @@ diff -Nurp linux-5.4-aufs/security/security.c linux-5.4-aufs-mod/security/securi
int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid)
{
@@ -1101,6 +1106,7 @@ int security_path_chown(const struct pat
@@ -1133,6 +1138,7 @@ int security_path_chown(const struct pat
return 0;
return call_int_hook(path_chown, 0, path, uid, gid);
}
@@ -303,7 +294,7 @@ diff -Nurp linux-5.4-aufs/security/security.c linux-5.4-aufs-mod/security/securi
int security_path_chroot(const struct path *path)
{
@@ -1201,6 +1207,7 @@ int security_inode_permission(struct ino
@@ -1233,6 +1239,7 @@ int security_inode_permission(struct ino
return 0;
return call_int_hook(inode_permission, 0, inode, mask);
}
@@ -311,7 +302,7 @@ diff -Nurp linux-5.4-aufs/security/security.c linux-5.4-aufs-mod/security/securi
int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
{
@@ -1378,6 +1385,7 @@ int security_file_permission(struct file
@@ -1410,6 +1417,7 @@ int security_file_permission(struct file
return fsnotify_perm(file, mask);
}
@@ -0,0 +1,96 @@
From b9d1e2e6265f5dc25e9f5dbfbde3e53d8a4958ac Mon Sep 17 00:00:00 2001
From: Namjae Jeon <namjae.jeon@samsung.com>
Date: Mon, 2 Mar 2020 15:21:42 +0900
Subject: [PATCH 11/14] exfat: add Kconfig and Makefile
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This adds the Kconfig and Makefile for exfat.
Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com>
Signed-off-by: Sungjong Seo <sj1557.seo@samsung.com>
Reviewed-by: Pali Rohár <pali.rohar@gmail.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/Kconfig | 3 ++-
fs/Makefile | 1 +
fs/exfat/Kconfig | 21 +++++++++++++++++++++
fs/exfat/Makefile | 8 ++++++++
4 files changed, 32 insertions(+), 1 deletion(-)
create mode 100644 fs/exfat/Kconfig
create mode 100644 fs/exfat/Makefile
diff --git a/fs/Kconfig b/fs/Kconfig
index 708ba336e689..f08fbbfafd9a 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -140,9 +140,10 @@ endmenu
endif # BLOCK
if BLOCK
-menu "DOS/FAT/NT Filesystems"
+menu "DOS/FAT/EXFAT/NT Filesystems"
source "fs/fat/Kconfig"
+source "fs/exfat/Kconfig"
source "fs/ntfs/Kconfig"
endmenu
diff --git a/fs/Makefile b/fs/Makefile
index 505e51166973..2ce5112b02c8 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -83,6 +83,7 @@ obj-$(CONFIG_HUGETLBFS) += hugetlbfs/
obj-$(CONFIG_CODA_FS) += coda/
obj-$(CONFIG_MINIX_FS) += minix/
obj-$(CONFIG_FAT_FS) += fat/
+obj-$(CONFIG_EXFAT_FS) += exfat/
obj-$(CONFIG_BFS_FS) += bfs/
obj-$(CONFIG_ISO9660_FS) += isofs/
obj-$(CONFIG_HFSPLUS_FS) += hfsplus/ # Before hfs to find wrapped HFS+
diff --git a/fs/exfat/Kconfig b/fs/exfat/Kconfig
new file mode 100644
index 000000000000..2d3636dc5b8c
--- /dev/null
+++ b/fs/exfat/Kconfig
@@ -0,0 +1,21 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+config EXFAT_FS
+ tristate "exFAT filesystem support"
+ select NLS
+ help
+ This allows you to mount devices formatted with the exFAT file system.
+ exFAT is typically used on SD-Cards or USB sticks.
+
+ To compile this as a module, choose M here: the module will be called
+ exfat.
+
+config EXFAT_DEFAULT_IOCHARSET
+ string "Default iocharset for exFAT"
+ default "utf8"
+ depends on EXFAT_FS
+ help
+ Set this to the default input/output character set to use for
+ converting between the encoding is used for user visible filename and
+ UTF-16 character that exfat filesystem use, and can be overridden with
+ the "iocharset" mount option for exFAT filesystems.
diff --git a/fs/exfat/Makefile b/fs/exfat/Makefile
new file mode 100644
index 000000000000..ed51926a4971
--- /dev/null
+++ b/fs/exfat/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Makefile for the linux exFAT filesystem support.
+#
+obj-$(CONFIG_EXFAT_FS) += exfat.o
+
+exfat-y := inode.o namei.o dir.o super.o fatent.o cache.o nls.o misc.o \
+ file.o balloc.o
--
2.25.1
@@ -0,0 +1,309 @@
From 1e49a94cf707204b66a3fb242f2814712c941f52 Mon Sep 17 00:00:00 2001
From: Namjae Jeon <namjae.jeon@samsung.com>
Date: Mon, 2 Mar 2020 15:21:38 +0900
Subject: [PATCH 07/14] exfat: add bitmap operations
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This adds the implementation of bitmap operations for exfat.
Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com>
Signed-off-by: Sungjong Seo <sj1557.seo@samsung.com>
Reviewed-by: Pali Rohár <pali.rohar@gmail.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/exfat/balloc.c | 280 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 280 insertions(+)
create mode 100644 fs/exfat/balloc.c
diff --git a/fs/exfat/balloc.c b/fs/exfat/balloc.c
new file mode 100644
index 000000000000..6a04cc02565a
--- /dev/null
+++ b/fs/exfat/balloc.c
@@ -0,0 +1,280 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
+ */
+
+#include <linux/blkdev.h>
+#include <linux/slab.h>
+#include <linux/buffer_head.h>
+
+#include "exfat_raw.h"
+#include "exfat_fs.h"
+
+static const unsigned char free_bit[] = {
+ 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2,/* 0 ~ 19*/
+ 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3,/* 20 ~ 39*/
+ 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2,/* 40 ~ 59*/
+ 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4,/* 60 ~ 79*/
+ 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2,/* 80 ~ 99*/
+ 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3,/*100 ~ 119*/
+ 0, 1, 0, 2, 0, 1, 0, 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2,/*120 ~ 139*/
+ 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5,/*140 ~ 159*/
+ 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2,/*160 ~ 179*/
+ 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3,/*180 ~ 199*/
+ 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2,/*200 ~ 219*/
+ 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4,/*220 ~ 239*/
+ 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 /*240 ~ 254*/
+};
+
+static const unsigned char used_bit[] = {
+ 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3,/* 0 ~ 19*/
+ 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4,/* 20 ~ 39*/
+ 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5,/* 40 ~ 59*/
+ 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,/* 60 ~ 79*/
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4,/* 80 ~ 99*/
+ 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6,/*100 ~ 119*/
+ 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4,/*120 ~ 139*/
+ 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,/*140 ~ 159*/
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5,/*160 ~ 179*/
+ 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5,/*180 ~ 199*/
+ 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6,/*200 ~ 219*/
+ 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,/*220 ~ 239*/
+ 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 /*240 ~ 255*/
+};
+
+/*
+ * Allocation Bitmap Management Functions
+ */
+static int exfat_allocate_bitmap(struct super_block *sb,
+ struct exfat_dentry *ep)
+{
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
+ long long map_size;
+ unsigned int i, need_map_size;
+ sector_t sector;
+
+ sbi->map_clu = le32_to_cpu(ep->dentry.bitmap.start_clu);
+ map_size = le64_to_cpu(ep->dentry.bitmap.size);
+ need_map_size = ((EXFAT_DATA_CLUSTER_COUNT(sbi) - 1) / BITS_PER_BYTE)
+ + 1;
+ if (need_map_size != map_size) {
+ exfat_msg(sb, KERN_ERR,
+ "bogus allocation bitmap size(need : %u, cur : %lld)",
+ need_map_size, map_size);
+ /*
+ * Only allowed when bogus allocation
+ * bitmap size is large
+ */
+ if (need_map_size > map_size)
+ return -EIO;
+ }
+ sbi->map_sectors = ((need_map_size - 1) >>
+ (sb->s_blocksize_bits)) + 1;
+ sbi->vol_amap = kmalloc_array(sbi->map_sectors,
+ sizeof(struct buffer_head *), GFP_KERNEL);
+ if (!sbi->vol_amap)
+ return -ENOMEM;
+
+ sector = exfat_cluster_to_sector(sbi, sbi->map_clu);
+ for (i = 0; i < sbi->map_sectors; i++) {
+ sbi->vol_amap[i] = sb_bread(sb, sector + i);
+ if (!sbi->vol_amap[i]) {
+ /* release all buffers and free vol_amap */
+ int j = 0;
+
+ while (j < i)
+ brelse(sbi->vol_amap[j++]);
+
+ kfree(sbi->vol_amap);
+ sbi->vol_amap = NULL;
+ return -EIO;
+ }
+ }
+
+ sbi->pbr_bh = NULL;
+ return 0;
+}
+
+int exfat_load_bitmap(struct super_block *sb)
+{
+ unsigned int i, type;
+ struct exfat_chain clu;
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
+
+ exfat_chain_set(&clu, sbi->root_dir, 0, ALLOC_FAT_CHAIN);
+ while (clu.dir != EXFAT_EOF_CLUSTER) {
+ for (i = 0; i < sbi->dentries_per_clu; i++) {
+ struct exfat_dentry *ep;
+ struct buffer_head *bh;
+
+ ep = exfat_get_dentry(sb, &clu, i, &bh, NULL);
+ if (!ep)
+ return -EIO;
+
+ type = exfat_get_entry_type(ep);
+ if (type == TYPE_UNUSED)
+ break;
+ if (type != TYPE_BITMAP)
+ continue;
+ if (ep->dentry.bitmap.flags == 0x0) {
+ int err;
+
+ err = exfat_allocate_bitmap(sb, ep);
+ brelse(bh);
+ return err;
+ }
+ brelse(bh);
+ }
+
+ if (exfat_get_next_cluster(sb, &clu.dir))
+ return -EIO;
+ }
+
+ return -EINVAL;
+}
+
+void exfat_free_bitmap(struct exfat_sb_info *sbi)
+{
+ int i;
+
+ brelse(sbi->pbr_bh);
+
+ for (i = 0; i < sbi->map_sectors; i++)
+ __brelse(sbi->vol_amap[i]);
+
+ kfree(sbi->vol_amap);
+}
+
+/*
+ * If the value of "clu" is 0, it means cluster 2 which is the first cluster of
+ * the cluster heap.
+ */
+int exfat_set_bitmap(struct inode *inode, unsigned int clu)
+{
+ int i, b;
+ unsigned int ent_idx;
+ struct super_block *sb = inode->i_sb;
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
+
+ WARN_ON(clu < EXFAT_FIRST_CLUSTER);
+ ent_idx = CLUSTER_TO_BITMAP_ENT(clu);
+ i = BITMAP_OFFSET_SECTOR_INDEX(sb, ent_idx);
+ b = BITMAP_OFFSET_BIT_IN_SECTOR(sb, ent_idx);
+
+ set_bit_le(b, sbi->vol_amap[i]->b_data);
+ exfat_update_bh(sb, sbi->vol_amap[i], IS_DIRSYNC(inode));
+ return 0;
+}
+
+/*
+ * If the value of "clu" is 0, it means cluster 2 which is the first cluster of
+ * the cluster heap.
+ */
+void exfat_clear_bitmap(struct inode *inode, unsigned int clu)
+{
+ int i, b;
+ unsigned int ent_idx;
+ struct super_block *sb = inode->i_sb;
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
+ struct exfat_mount_options *opts = &sbi->options;
+
+ WARN_ON(clu < EXFAT_FIRST_CLUSTER);
+ ent_idx = CLUSTER_TO_BITMAP_ENT(clu);
+ i = BITMAP_OFFSET_SECTOR_INDEX(sb, ent_idx);
+ b = BITMAP_OFFSET_BIT_IN_SECTOR(sb, ent_idx);
+
+ clear_bit_le(b, sbi->vol_amap[i]->b_data);
+ exfat_update_bh(sb, sbi->vol_amap[i], IS_DIRSYNC(inode));
+
+ if (opts->discard) {
+ int ret_discard;
+
+ ret_discard = sb_issue_discard(sb,
+ exfat_cluster_to_sector(sbi, clu +
+ EXFAT_RESERVED_CLUSTERS),
+ (1 << sbi->sect_per_clus_bits), GFP_NOFS, 0);
+
+ if (ret_discard == -EOPNOTSUPP) {
+ exfat_msg(sb, KERN_ERR,
+ "discard not supported by device, disabling");
+ opts->discard = 0;
+ }
+ }
+}
+
+/*
+ * If the value of "clu" is 0, it means cluster 2 which is the first cluster of
+ * the cluster heap.
+ */
+unsigned int exfat_find_free_bitmap(struct super_block *sb, unsigned int clu)
+{
+ unsigned int i, map_i, map_b, ent_idx;
+ unsigned int clu_base, clu_free;
+ unsigned char k, clu_mask;
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
+
+ WARN_ON(clu < EXFAT_FIRST_CLUSTER);
+ ent_idx = CLUSTER_TO_BITMAP_ENT(clu);
+ clu_base = BITMAP_ENT_TO_CLUSTER(ent_idx & ~(BITS_PER_BYTE_MASK));
+ clu_mask = IGNORED_BITS_REMAINED(clu, clu_base);
+
+ map_i = BITMAP_OFFSET_SECTOR_INDEX(sb, ent_idx);
+ map_b = BITMAP_OFFSET_BYTE_IN_SECTOR(sb, ent_idx);
+
+ for (i = EXFAT_FIRST_CLUSTER; i < sbi->num_clusters;
+ i += BITS_PER_BYTE) {
+ k = *(sbi->vol_amap[map_i]->b_data + map_b);
+ if (clu_mask > 0) {
+ k |= clu_mask;
+ clu_mask = 0;
+ }
+ if (k < 0xFF) {
+ clu_free = clu_base + free_bit[k];
+ if (clu_free < sbi->num_clusters)
+ return clu_free;
+ }
+ clu_base += BITS_PER_BYTE;
+
+ if (++map_b >= sb->s_blocksize ||
+ clu_base >= sbi->num_clusters) {
+ if (++map_i >= sbi->map_sectors) {
+ clu_base = EXFAT_FIRST_CLUSTER;
+ map_i = 0;
+ }
+ map_b = 0;
+ }
+ }
+
+ return EXFAT_EOF_CLUSTER;
+}
+
+int exfat_count_used_clusters(struct super_block *sb, unsigned int *ret_count)
+{
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
+ unsigned int count = 0;
+ unsigned int i, map_i = 0, map_b = 0;
+ unsigned int total_clus = EXFAT_DATA_CLUSTER_COUNT(sbi);
+ unsigned int last_mask = total_clus & BITS_PER_BYTE_MASK;
+ unsigned char clu_bits;
+ const unsigned char last_bit_mask[] = {0, 0b00000001, 0b00000011,
+ 0b00000111, 0b00001111, 0b00011111, 0b00111111, 0b01111111};
+
+ total_clus &= ~last_mask;
+ for (i = 0; i < total_clus; i += BITS_PER_BYTE) {
+ clu_bits = *(sbi->vol_amap[map_i]->b_data + map_b);
+ count += used_bit[clu_bits];
+ if (++map_b >= (unsigned int)sb->s_blocksize) {
+ map_i++;
+ map_b = 0;
+ }
+ }
+
+ if (last_mask) {
+ clu_bits = *(sbi->vol_amap[map_i]->b_data + map_b);
+ clu_bits &= last_bit_mask[last_mask];
+ count += used_bit[clu_bits];
+ }
+
+ *ret_count = count;
+ return 0;
+}
--
2.25.1
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,354 @@
From c35b6810c4952ae5776607e2c1d6a587425d5834 Mon Sep 17 00:00:00 2001
From: Namjae Jeon <namjae.jeon@samsung.com>
Date: Mon, 2 Mar 2020 15:21:39 +0900
Subject: [PATCH 08/14] exfat: add exfat cache
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This adds the implementation of exfat cache.
Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com>
Signed-off-by: Sungjong Seo <sj1557.seo@samsung.com>
Reviewed-by: Pali Rohár <pali.rohar@gmail.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/exfat/cache.c | 325 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 325 insertions(+)
create mode 100644 fs/exfat/cache.c
diff --git a/fs/exfat/cache.c b/fs/exfat/cache.c
new file mode 100644
index 000000000000..03d0824fc368
--- /dev/null
+++ b/fs/exfat/cache.c
@@ -0,0 +1,325 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * linux/fs/fat/cache.c
+ *
+ * Written 1992,1993 by Werner Almesberger
+ *
+ * Mar 1999. AV. Changed cache, so that it uses the starting cluster instead
+ * of inode number.
+ * May 1999. AV. Fixed the bogosity with FAT32 (read "FAT28"). Fscking lusers.
+ * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
+ */
+
+#include <linux/slab.h>
+#include <asm/unaligned.h>
+#include <linux/buffer_head.h>
+
+#include "exfat_raw.h"
+#include "exfat_fs.h"
+
+#define EXFAT_CACHE_VALID 0
+#define EXFAT_MAX_CACHE 16
+
+struct exfat_cache {
+ struct list_head cache_list;
+ unsigned int nr_contig; /* number of contiguous clusters */
+ unsigned int fcluster; /* cluster number in the file. */
+ unsigned int dcluster; /* cluster number on disk. */
+};
+
+struct exfat_cache_id {
+ unsigned int id;
+ unsigned int nr_contig;
+ unsigned int fcluster;
+ unsigned int dcluster;
+};
+
+static struct kmem_cache *exfat_cachep;
+
+static void exfat_cache_init_once(void *c)
+{
+ struct exfat_cache *cache = (struct exfat_cache *)c;
+
+ INIT_LIST_HEAD(&cache->cache_list);
+}
+
+int exfat_cache_init(void)
+{
+ exfat_cachep = kmem_cache_create("exfat_cache",
+ sizeof(struct exfat_cache),
+ 0, SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD,
+ exfat_cache_init_once);
+ if (!exfat_cachep)
+ return -ENOMEM;
+ return 0;
+}
+
+void exfat_cache_shutdown(void)
+{
+ if (!exfat_cachep)
+ return;
+ kmem_cache_destroy(exfat_cachep);
+}
+
+void exfat_cache_init_inode(struct inode *inode)
+{
+ struct exfat_inode_info *ei = EXFAT_I(inode);
+
+ spin_lock_init(&ei->cache_lru_lock);
+ ei->nr_caches = 0;
+ ei->cache_valid_id = EXFAT_CACHE_VALID + 1;
+ INIT_LIST_HEAD(&ei->cache_lru);
+}
+
+static inline struct exfat_cache *exfat_cache_alloc(void)
+{
+ return kmem_cache_alloc(exfat_cachep, GFP_NOFS);
+}
+
+static inline void exfat_cache_free(struct exfat_cache *cache)
+{
+ WARN_ON(!list_empty(&cache->cache_list));
+ kmem_cache_free(exfat_cachep, cache);
+}
+
+static inline void exfat_cache_update_lru(struct inode *inode,
+ struct exfat_cache *cache)
+{
+ struct exfat_inode_info *ei = EXFAT_I(inode);
+
+ if (ei->cache_lru.next != &cache->cache_list)
+ list_move(&cache->cache_list, &ei->cache_lru);
+}
+
+static unsigned int exfat_cache_lookup(struct inode *inode,
+ unsigned int fclus, struct exfat_cache_id *cid,
+ unsigned int *cached_fclus, unsigned int *cached_dclus)
+{
+ struct exfat_inode_info *ei = EXFAT_I(inode);
+ static struct exfat_cache nohit = { .fcluster = 0, };
+ struct exfat_cache *hit = &nohit, *p;
+ unsigned int offset = EXFAT_EOF_CLUSTER;
+
+ spin_lock(&ei->cache_lru_lock);
+ list_for_each_entry(p, &ei->cache_lru, cache_list) {
+ /* Find the cache of "fclus" or nearest cache. */
+ if (p->fcluster <= fclus && hit->fcluster < p->fcluster) {
+ hit = p;
+ if (hit->fcluster + hit->nr_contig < fclus) {
+ offset = hit->nr_contig;
+ } else {
+ offset = fclus - hit->fcluster;
+ break;
+ }
+ }
+ }
+ if (hit != &nohit) {
+ exfat_cache_update_lru(inode, hit);
+
+ cid->id = ei->cache_valid_id;
+ cid->nr_contig = hit->nr_contig;
+ cid->fcluster = hit->fcluster;
+ cid->dcluster = hit->dcluster;
+ *cached_fclus = cid->fcluster + offset;
+ *cached_dclus = cid->dcluster + offset;
+ }
+ spin_unlock(&ei->cache_lru_lock);
+
+ return offset;
+}
+
+static struct exfat_cache *exfat_cache_merge(struct inode *inode,
+ struct exfat_cache_id *new)
+{
+ struct exfat_inode_info *ei = EXFAT_I(inode);
+ struct exfat_cache *p;
+
+ list_for_each_entry(p, &ei->cache_lru, cache_list) {
+ /* Find the same part as "new" in cluster-chain. */
+ if (p->fcluster == new->fcluster) {
+ if (new->nr_contig > p->nr_contig)
+ p->nr_contig = new->nr_contig;
+ return p;
+ }
+ }
+ return NULL;
+}
+
+static void exfat_cache_add(struct inode *inode,
+ struct exfat_cache_id *new)
+{
+ struct exfat_inode_info *ei = EXFAT_I(inode);
+ struct exfat_cache *cache, *tmp;
+
+ if (new->fcluster == EXFAT_EOF_CLUSTER) /* dummy cache */
+ return;
+
+ spin_lock(&ei->cache_lru_lock);
+ if (new->id != EXFAT_CACHE_VALID &&
+ new->id != ei->cache_valid_id)
+ goto unlock; /* this cache was invalidated */
+
+ cache = exfat_cache_merge(inode, new);
+ if (cache == NULL) {
+ if (ei->nr_caches < EXFAT_MAX_CACHE) {
+ ei->nr_caches++;
+ spin_unlock(&ei->cache_lru_lock);
+
+ tmp = exfat_cache_alloc();
+ if (!tmp) {
+ spin_lock(&ei->cache_lru_lock);
+ ei->nr_caches--;
+ spin_unlock(&ei->cache_lru_lock);
+ return;
+ }
+
+ spin_lock(&ei->cache_lru_lock);
+ cache = exfat_cache_merge(inode, new);
+ if (cache != NULL) {
+ ei->nr_caches--;
+ exfat_cache_free(tmp);
+ goto out_update_lru;
+ }
+ cache = tmp;
+ } else {
+ struct list_head *p = ei->cache_lru.prev;
+
+ cache = list_entry(p,
+ struct exfat_cache, cache_list);
+ }
+ cache->fcluster = new->fcluster;
+ cache->dcluster = new->dcluster;
+ cache->nr_contig = new->nr_contig;
+ }
+out_update_lru:
+ exfat_cache_update_lru(inode, cache);
+unlock:
+ spin_unlock(&ei->cache_lru_lock);
+}
+
+/*
+ * Cache invalidation occurs rarely, thus the LRU chain is not updated. It
+ * fixes itself after a while.
+ */
+static void __exfat_cache_inval_inode(struct inode *inode)
+{
+ struct exfat_inode_info *ei = EXFAT_I(inode);
+ struct exfat_cache *cache;
+
+ while (!list_empty(&ei->cache_lru)) {
+ cache = list_entry(ei->cache_lru.next,
+ struct exfat_cache, cache_list);
+ list_del_init(&cache->cache_list);
+ ei->nr_caches--;
+ exfat_cache_free(cache);
+ }
+ /* Update. The copy of caches before this id is discarded. */
+ ei->cache_valid_id++;
+ if (ei->cache_valid_id == EXFAT_CACHE_VALID)
+ ei->cache_valid_id++;
+}
+
+void exfat_cache_inval_inode(struct inode *inode)
+{
+ struct exfat_inode_info *ei = EXFAT_I(inode);
+
+ spin_lock(&ei->cache_lru_lock);
+ __exfat_cache_inval_inode(inode);
+ spin_unlock(&ei->cache_lru_lock);
+}
+
+static inline int cache_contiguous(struct exfat_cache_id *cid,
+ unsigned int dclus)
+{
+ cid->nr_contig++;
+ return cid->dcluster + cid->nr_contig == dclus;
+}
+
+static inline void cache_init(struct exfat_cache_id *cid,
+ unsigned int fclus, unsigned int dclus)
+{
+ cid->id = EXFAT_CACHE_VALID;
+ cid->fcluster = fclus;
+ cid->dcluster = dclus;
+ cid->nr_contig = 0;
+}
+
+int exfat_get_cluster(struct inode *inode, unsigned int cluster,
+ unsigned int *fclus, unsigned int *dclus,
+ unsigned int *last_dclus, int allow_eof)
+{
+ struct super_block *sb = inode->i_sb;
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
+ unsigned int limit = sbi->num_clusters;
+ struct exfat_inode_info *ei = EXFAT_I(inode);
+ struct exfat_cache_id cid;
+ unsigned int content;
+
+ if (ei->start_clu == EXFAT_FREE_CLUSTER) {
+ exfat_fs_error(sb,
+ "invalid access to exfat cache (entry 0x%08x)",
+ ei->start_clu);
+ return -EIO;
+ }
+
+ *fclus = 0;
+ *dclus = ei->start_clu;
+ *last_dclus = *dclus;
+
+ /*
+ * Don`t use exfat_cache if zero offset or non-cluster allocation
+ */
+ if (cluster == 0 || *dclus == EXFAT_EOF_CLUSTER)
+ return 0;
+
+ cache_init(&cid, EXFAT_EOF_CLUSTER, EXFAT_EOF_CLUSTER);
+
+ if (exfat_cache_lookup(inode, cluster, &cid, fclus, dclus) ==
+ EXFAT_EOF_CLUSTER) {
+ /*
+ * dummy, always not contiguous
+ * This is reinitialized by cache_init(), later.
+ */
+ WARN_ON(cid.id != EXFAT_CACHE_VALID ||
+ cid.fcluster != EXFAT_EOF_CLUSTER ||
+ cid.dcluster != EXFAT_EOF_CLUSTER ||
+ cid.nr_contig != 0);
+ }
+
+ if (*fclus == cluster)
+ return 0;
+
+ while (*fclus < cluster) {
+ /* prevent the infinite loop of cluster chain */
+ if (*fclus > limit) {
+ exfat_fs_error(sb,
+ "detected the cluster chain loop (i_pos %u)",
+ (*fclus));
+ return -EIO;
+ }
+
+ if (exfat_ent_get(sb, *dclus, &content))
+ return -EIO;
+
+ *last_dclus = *dclus;
+ *dclus = content;
+ (*fclus)++;
+
+ if (content == EXFAT_EOF_CLUSTER) {
+ if (!allow_eof) {
+ exfat_fs_error(sb,
+ "invalid cluster chain (i_pos %u, last_clus 0x%08x is EOF)",
+ *fclus, (*last_dclus));
+ return -EIO;
+ }
+
+ break;
+ }
+
+ if (!cache_contiguous(&cid, *dclus))
+ cache_init(&cid, *fclus, *dclus);
+ }
+
+ exfat_cache_add(inode, &cid);
+ return 0;
+}
--
2.25.1
@@ -0,0 +1,492 @@
From 31023864e67a5f390cefbe92f72343027dc3aa33 Mon Sep 17 00:00:00 2001
From: Namjae Jeon <namjae.jeon@samsung.com>
Date: Mon, 2 Mar 2020 15:21:37 +0900
Subject: [PATCH 06/14] exfat: add fat entry operations
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This adds the implementation of fat entry operations for exfat.
Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com>
Signed-off-by: Sungjong Seo <sj1557.seo@samsung.com>
Reviewed-by: Pali Rohár <pali.rohar@gmail.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/exfat/fatent.c | 463 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 463 insertions(+)
create mode 100644 fs/exfat/fatent.c
diff --git a/fs/exfat/fatent.c b/fs/exfat/fatent.c
new file mode 100644
index 000000000000..a855b1769a96
--- /dev/null
+++ b/fs/exfat/fatent.c
@@ -0,0 +1,463 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
+ */
+
+#include <linux/slab.h>
+#include <asm/unaligned.h>
+#include <linux/buffer_head.h>
+
+#include "exfat_raw.h"
+#include "exfat_fs.h"
+
+static int exfat_mirror_bh(struct super_block *sb, sector_t sec,
+ struct buffer_head *bh)
+{
+ struct buffer_head *c_bh;
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
+ sector_t sec2;
+ int err = 0;
+
+ if (sbi->FAT2_start_sector != sbi->FAT1_start_sector) {
+ sec2 = sec - sbi->FAT1_start_sector + sbi->FAT2_start_sector;
+ c_bh = sb_getblk(sb, sec2);
+ if (!c_bh)
+ return -ENOMEM;
+ memcpy(c_bh->b_data, bh->b_data, sb->s_blocksize);
+ set_buffer_uptodate(c_bh);
+ mark_buffer_dirty(c_bh);
+ if (sb->s_flags & SB_SYNCHRONOUS)
+ err = sync_dirty_buffer(c_bh);
+ brelse(c_bh);
+ }
+
+ return err;
+}
+
+static int __exfat_ent_get(struct super_block *sb, unsigned int loc,
+ unsigned int *content)
+{
+ unsigned int off;
+ sector_t sec;
+ struct buffer_head *bh;
+
+ sec = FAT_ENT_OFFSET_SECTOR(sb, loc);
+ off = FAT_ENT_OFFSET_BYTE_IN_SECTOR(sb, loc);
+
+ bh = sb_bread(sb, sec);
+ if (!bh)
+ return -EIO;
+
+ *content = le32_to_cpu(*(__le32 *)(&bh->b_data[off]));
+
+ /* remap reserved clusters to simplify code */
+ if (*content > EXFAT_BAD_CLUSTER)
+ *content = EXFAT_EOF_CLUSTER;
+
+ brelse(bh);
+ return 0;
+}
+
+int exfat_ent_set(struct super_block *sb, unsigned int loc,
+ unsigned int content)
+{
+ unsigned int off;
+ sector_t sec;
+ __le32 *fat_entry;
+ struct buffer_head *bh;
+
+ sec = FAT_ENT_OFFSET_SECTOR(sb, loc);
+ off = FAT_ENT_OFFSET_BYTE_IN_SECTOR(sb, loc);
+
+ bh = sb_bread(sb, sec);
+ if (!bh)
+ return -EIO;
+
+ fat_entry = (__le32 *)&(bh->b_data[off]);
+ *fat_entry = cpu_to_le32(content);
+ exfat_update_bh(sb, bh, sb->s_flags & SB_SYNCHRONOUS);
+ exfat_mirror_bh(sb, sec, bh);
+ brelse(bh);
+ return 0;
+}
+
+static inline bool is_valid_cluster(struct exfat_sb_info *sbi,
+ unsigned int clus)
+{
+ if (clus < EXFAT_FIRST_CLUSTER || sbi->num_clusters <= clus)
+ return false;
+ return true;
+}
+
+int exfat_ent_get(struct super_block *sb, unsigned int loc,
+ unsigned int *content)
+{
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
+ int err;
+
+ if (!is_valid_cluster(sbi, loc)) {
+ exfat_fs_error(sb, "invalid access to FAT (entry 0x%08x)",
+ loc);
+ return -EIO;
+ }
+
+ err = __exfat_ent_get(sb, loc, content);
+ if (err) {
+ exfat_fs_error(sb,
+ "failed to access to FAT (entry 0x%08x, err:%d)",
+ loc, err);
+ return err;
+ }
+
+ if (*content == EXFAT_FREE_CLUSTER) {
+ exfat_fs_error(sb,
+ "invalid access to FAT free cluster (entry 0x%08x)",
+ loc);
+ return -EIO;
+ }
+
+ if (*content == EXFAT_BAD_CLUSTER) {
+ exfat_fs_error(sb,
+ "invalid access to FAT bad cluster (entry 0x%08x)",
+ loc);
+ return -EIO;
+ }
+
+ if (*content != EXFAT_EOF_CLUSTER && !is_valid_cluster(sbi, *content)) {
+ exfat_fs_error(sb,
+ "invalid access to FAT (entry 0x%08x) bogus content (0x%08x)",
+ loc, *content);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+int exfat_chain_cont_cluster(struct super_block *sb, unsigned int chain,
+ unsigned int len)
+{
+ if (!len)
+ return 0;
+
+ while (len > 1) {
+ if (exfat_ent_set(sb, chain, chain + 1))
+ return -EIO;
+ chain++;
+ len--;
+ }
+
+ if (exfat_ent_set(sb, chain, EXFAT_EOF_CLUSTER))
+ return -EIO;
+ return 0;
+}
+
+int exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain)
+{
+ unsigned int num_clusters = 0;
+ unsigned int clu;
+ struct super_block *sb = inode->i_sb;
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
+
+ /* invalid cluster number */
+ if (p_chain->dir == EXFAT_FREE_CLUSTER ||
+ p_chain->dir == EXFAT_EOF_CLUSTER ||
+ p_chain->dir < EXFAT_FIRST_CLUSTER)
+ return 0;
+
+ /* no cluster to truncate */
+ if (p_chain->size == 0)
+ return 0;
+
+ /* check cluster validation */
+ if (p_chain->dir < 2 && p_chain->dir >= sbi->num_clusters) {
+ exfat_msg(sb, KERN_ERR, "invalid start cluster (%u)",
+ p_chain->dir);
+ return -EIO;
+ }
+
+ set_bit(EXFAT_SB_DIRTY, &sbi->s_state);
+ clu = p_chain->dir;
+
+ if (p_chain->flags == ALLOC_NO_FAT_CHAIN) {
+ do {
+ exfat_clear_bitmap(inode, clu);
+ clu++;
+
+ num_clusters++;
+ } while (num_clusters < p_chain->size);
+ } else {
+ do {
+ exfat_clear_bitmap(inode, clu);
+
+ if (exfat_get_next_cluster(sb, &clu))
+ goto dec_used_clus;
+
+ num_clusters++;
+ } while (clu != EXFAT_EOF_CLUSTER);
+ }
+
+dec_used_clus:
+ sbi->used_clusters -= num_clusters;
+ return 0;
+}
+
+int exfat_find_last_cluster(struct super_block *sb, struct exfat_chain *p_chain,
+ unsigned int *ret_clu)
+{
+ unsigned int clu, next;
+ unsigned int count = 0;
+
+ next = p_chain->dir;
+ if (p_chain->flags == ALLOC_NO_FAT_CHAIN) {
+ *ret_clu = next + p_chain->size - 1;
+ return 0;
+ }
+
+ do {
+ count++;
+ clu = next;
+ if (exfat_ent_get(sb, clu, &next))
+ return -EIO;
+ } while (next != EXFAT_EOF_CLUSTER);
+
+ if (p_chain->size != count) {
+ exfat_fs_error(sb,
+ "bogus directory size (clus : ondisk(%d) != counted(%d))",
+ p_chain->size, count);
+ return -EIO;
+ }
+
+ *ret_clu = clu;
+ return 0;
+}
+
+static inline int exfat_sync_bhs(struct buffer_head **bhs, int nr_bhs)
+{
+ int i, err = 0;
+
+ for (i = 0; i < nr_bhs; i++)
+ write_dirty_buffer(bhs[i], 0);
+
+ for (i = 0; i < nr_bhs; i++) {
+ wait_on_buffer(bhs[i]);
+ if (!err && !buffer_uptodate(bhs[i]))
+ err = -EIO;
+ }
+ return err;
+}
+
+int exfat_zeroed_cluster(struct inode *dir, unsigned int clu)
+{
+ struct super_block *sb = dir->i_sb;
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
+ struct buffer_head *bhs[MAX_BUF_PER_PAGE];
+ int nr_bhs = MAX_BUF_PER_PAGE;
+ sector_t blknr, last_blknr;
+ int err, i, n;
+
+ blknr = exfat_cluster_to_sector(sbi, clu);
+ last_blknr = blknr + sbi->sect_per_clus;
+
+ if (last_blknr > sbi->num_sectors && sbi->num_sectors > 0) {
+ exfat_fs_error_ratelimit(sb,
+ "%s: out of range(sect:%llu len:%u)",
+ __func__, (unsigned long long)blknr,
+ sbi->sect_per_clus);
+ return -EIO;
+ }
+
+ /* Zeroing the unused blocks on this cluster */
+ n = 0;
+ while (blknr < last_blknr) {
+ bhs[n] = sb_getblk(sb, blknr);
+ if (!bhs[n]) {
+ err = -ENOMEM;
+ goto release_bhs;
+ }
+ memset(bhs[n]->b_data, 0, sb->s_blocksize);
+ exfat_update_bh(sb, bhs[n], 0);
+
+ n++;
+ blknr++;
+
+ if (n == nr_bhs) {
+ if (IS_DIRSYNC(dir)) {
+ err = exfat_sync_bhs(bhs, n);
+ if (err)
+ goto release_bhs;
+ }
+
+ for (i = 0; i < n; i++)
+ brelse(bhs[i]);
+ n = 0;
+ }
+ }
+
+ if (IS_DIRSYNC(dir)) {
+ err = exfat_sync_bhs(bhs, n);
+ if (err)
+ goto release_bhs;
+ }
+
+ for (i = 0; i < n; i++)
+ brelse(bhs[i]);
+
+ return 0;
+
+release_bhs:
+ exfat_msg(sb, KERN_ERR, "failed zeroed sect %llu\n",
+ (unsigned long long)blknr);
+ for (i = 0; i < n; i++)
+ bforget(bhs[i]);
+ return err;
+}
+
+int exfat_alloc_cluster(struct inode *inode, unsigned int num_alloc,
+ struct exfat_chain *p_chain)
+{
+ int ret = -ENOSPC;
+ unsigned int num_clusters = 0, total_cnt;
+ unsigned int hint_clu, new_clu, last_clu = EXFAT_EOF_CLUSTER;
+ struct super_block *sb = inode->i_sb;
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
+
+ total_cnt = EXFAT_DATA_CLUSTER_COUNT(sbi);
+
+ if (unlikely(total_cnt < sbi->used_clusters)) {
+ exfat_fs_error_ratelimit(sb,
+ "%s: invalid used clusters(t:%u,u:%u)\n",
+ __func__, total_cnt, sbi->used_clusters);
+ return -EIO;
+ }
+
+ if (num_alloc > total_cnt - sbi->used_clusters)
+ return -ENOSPC;
+
+ hint_clu = p_chain->dir;
+ /* find new cluster */
+ if (hint_clu == EXFAT_EOF_CLUSTER) {
+ if (sbi->clu_srch_ptr < EXFAT_FIRST_CLUSTER) {
+ exfat_msg(sb, KERN_ERR,
+ "sbi->clu_srch_ptr is invalid (%u)\n",
+ sbi->clu_srch_ptr);
+ sbi->clu_srch_ptr = EXFAT_FIRST_CLUSTER;
+ }
+
+ hint_clu = exfat_find_free_bitmap(sb, sbi->clu_srch_ptr);
+ if (hint_clu == EXFAT_EOF_CLUSTER)
+ return -ENOSPC;
+ }
+
+ /* check cluster validation */
+ if (hint_clu < EXFAT_FIRST_CLUSTER && hint_clu >= sbi->num_clusters) {
+ exfat_msg(sb, KERN_ERR, "hint_cluster is invalid (%u)\n",
+ hint_clu);
+ hint_clu = EXFAT_FIRST_CLUSTER;
+ if (p_chain->flags == ALLOC_NO_FAT_CHAIN) {
+ if (exfat_chain_cont_cluster(sb, p_chain->dir,
+ num_clusters))
+ return -EIO;
+ p_chain->flags = ALLOC_FAT_CHAIN;
+ }
+ }
+
+ set_bit(EXFAT_SB_DIRTY, &sbi->s_state);
+
+ p_chain->dir = EXFAT_EOF_CLUSTER;
+
+ while ((new_clu = exfat_find_free_bitmap(sb, hint_clu)) !=
+ EXFAT_EOF_CLUSTER) {
+ if (new_clu != hint_clu &&
+ p_chain->flags == ALLOC_NO_FAT_CHAIN) {
+ if (exfat_chain_cont_cluster(sb, p_chain->dir,
+ num_clusters)) {
+ ret = -EIO;
+ goto free_cluster;
+ }
+ p_chain->flags = ALLOC_FAT_CHAIN;
+ }
+
+ /* update allocation bitmap */
+ if (exfat_set_bitmap(inode, new_clu)) {
+ ret = -EIO;
+ goto free_cluster;
+ }
+
+ num_clusters++;
+
+ /* update FAT table */
+ if (p_chain->flags == ALLOC_FAT_CHAIN) {
+ if (exfat_ent_set(sb, new_clu, EXFAT_EOF_CLUSTER)) {
+ ret = -EIO;
+ goto free_cluster;
+ }
+ }
+
+ if (p_chain->dir == EXFAT_EOF_CLUSTER) {
+ p_chain->dir = new_clu;
+ } else if (p_chain->flags == ALLOC_FAT_CHAIN) {
+ if (exfat_ent_set(sb, last_clu, new_clu)) {
+ ret = -EIO;
+ goto free_cluster;
+ }
+ }
+ last_clu = new_clu;
+
+ if (--num_alloc == 0) {
+ sbi->clu_srch_ptr = hint_clu;
+ sbi->used_clusters += num_clusters;
+
+ p_chain->size += num_clusters;
+ return 0;
+ }
+
+ hint_clu = new_clu + 1;
+ if (hint_clu >= sbi->num_clusters) {
+ hint_clu = EXFAT_FIRST_CLUSTER;
+
+ if (p_chain->flags == ALLOC_NO_FAT_CHAIN) {
+ if (exfat_chain_cont_cluster(sb, p_chain->dir,
+ num_clusters)) {
+ ret = -EIO;
+ goto free_cluster;
+ }
+ p_chain->flags = ALLOC_FAT_CHAIN;
+ }
+ }
+ }
+free_cluster:
+ if (num_clusters)
+ exfat_free_cluster(inode, p_chain);
+ return ret;
+}
+
+int exfat_count_num_clusters(struct super_block *sb,
+ struct exfat_chain *p_chain, unsigned int *ret_count)
+{
+ unsigned int i, count;
+ unsigned int clu;
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
+
+ if (!p_chain->dir || p_chain->dir == EXFAT_EOF_CLUSTER) {
+ *ret_count = 0;
+ return 0;
+ }
+
+ if (p_chain->flags == ALLOC_NO_FAT_CHAIN) {
+ *ret_count = p_chain->size;
+ return 0;
+ }
+
+ clu = p_chain->dir;
+ count = 0;
+ for (i = EXFAT_FIRST_CLUSTER; i < sbi->num_clusters; i++) {
+ count++;
+ if (exfat_ent_get(sb, clu, &clu))
+ return -EIO;
+ if (clu == EXFAT_EOF_CLUSTER)
+ break;
+ }
+
+ *ret_count = count;
+ return 0;
+}
--
2.25.1
@@ -0,0 +1,390 @@
From 98d917047e8b7f4bb2ff61d81b0ccd94a00444f9 Mon Sep 17 00:00:00 2001
From: Namjae Jeon <namjae.jeon@samsung.com>
Date: Mon, 2 Mar 2020 15:21:36 +0900
Subject: [PATCH 05/14] exfat: add file operations
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This adds the implementation of file operations for exfat.
Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com>
Signed-off-by: Sungjong Seo <sj1557.seo@samsung.com>
Reviewed-by: Pali Rohár <pali.rohar@gmail.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/exfat/file.c | 360 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 360 insertions(+)
create mode 100644 fs/exfat/file.c
diff --git a/fs/exfat/file.c b/fs/exfat/file.c
new file mode 100644
index 000000000000..483f683757aa
--- /dev/null
+++ b/fs/exfat/file.c
@@ -0,0 +1,360 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
+ */
+
+#include <linux/slab.h>
+#include <linux/cred.h>
+#include <linux/buffer_head.h>
+
+#include "exfat_raw.h"
+#include "exfat_fs.h"
+
+static int exfat_cont_expand(struct inode *inode, loff_t size)
+{
+ struct address_space *mapping = inode->i_mapping;
+ loff_t start = i_size_read(inode), count = size - i_size_read(inode);
+ int err, err2;
+
+ err = generic_cont_expand_simple(inode, size);
+ if (err)
+ return err;
+
+ inode->i_ctime = inode->i_mtime = current_time(inode);
+ mark_inode_dirty(inode);
+
+ if (!IS_SYNC(inode))
+ return 0;
+
+ err = filemap_fdatawrite_range(mapping, start, start + count - 1);
+ err2 = sync_mapping_buffers(mapping);
+ if (!err)
+ err = err2;
+ err2 = write_inode_now(inode, 1);
+ if (!err)
+ err = err2;
+ if (err)
+ return err;
+
+ return filemap_fdatawait_range(mapping, start, start + count - 1);
+}
+
+static bool exfat_allow_set_time(struct exfat_sb_info *sbi, struct inode *inode)
+{
+ mode_t allow_utime = sbi->options.allow_utime;
+
+ if (!uid_eq(current_fsuid(), inode->i_uid)) {
+ if (in_group_p(inode->i_gid))
+ allow_utime >>= 3;
+ if (allow_utime & MAY_WRITE)
+ return true;
+ }
+
+ /* use a default check */
+ return false;
+}
+
+static int exfat_sanitize_mode(const struct exfat_sb_info *sbi,
+ struct inode *inode, umode_t *mode_ptr)
+{
+ mode_t i_mode, mask, perm;
+
+ i_mode = inode->i_mode;
+
+ mask = (S_ISREG(i_mode) || S_ISLNK(i_mode)) ?
+ sbi->options.fs_fmask : sbi->options.fs_dmask;
+ perm = *mode_ptr & ~(S_IFMT | mask);
+
+ /* Of the r and x bits, all (subject to umask) must be present.*/
+ if ((perm & 0555) != (i_mode & 0555))
+ return -EPERM;
+
+ if (exfat_mode_can_hold_ro(inode)) {
+ /*
+ * Of the w bits, either all (subject to umask) or none must
+ * be present.
+ */
+ if ((perm & 0222) && ((perm & 0222) != (0222 & ~mask)))
+ return -EPERM;
+ } else {
+ /*
+ * If exfat_mode_can_hold_ro(inode) is false, can't change
+ * w bits.
+ */
+ if ((perm & 0222) != (0222 & ~mask))
+ return -EPERM;
+ }
+
+ *mode_ptr &= S_IFMT | perm;
+
+ return 0;
+}
+
+/* resize the file length */
+int __exfat_truncate(struct inode *inode, loff_t new_size)
+{
+ unsigned int num_clusters_new, num_clusters_phys;
+ unsigned int last_clu = EXFAT_FREE_CLUSTER;
+ struct exfat_chain clu;
+ struct exfat_dentry *ep, *ep2;
+ struct super_block *sb = inode->i_sb;
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
+ struct exfat_inode_info *ei = EXFAT_I(inode);
+ struct exfat_entry_set_cache *es = NULL;
+ int evict = (ei->dir.dir == DIR_DELETED) ? 1 : 0;
+
+ /* check if the given file ID is opened */
+ if (ei->type != TYPE_FILE && ei->type != TYPE_DIR)
+ return -EPERM;
+
+ exfat_set_vol_flags(sb, VOL_DIRTY);
+
+ num_clusters_new = EXFAT_B_TO_CLU_ROUND_UP(i_size_read(inode), sbi);
+ num_clusters_phys =
+ EXFAT_B_TO_CLU_ROUND_UP(EXFAT_I(inode)->i_size_ondisk, sbi);
+
+ exfat_chain_set(&clu, ei->start_clu, num_clusters_phys, ei->flags);
+
+ if (new_size > 0) {
+ /*
+ * Truncate FAT chain num_clusters after the first cluster
+ * num_clusters = min(new, phys);
+ */
+ unsigned int num_clusters =
+ min(num_clusters_new, num_clusters_phys);
+
+ /*
+ * Follow FAT chain
+ * (defensive coding - works fine even with corrupted FAT table
+ */
+ if (clu.flags == ALLOC_NO_FAT_CHAIN) {
+ clu.dir += num_clusters;
+ clu.size -= num_clusters;
+ } else {
+ while (num_clusters > 0) {
+ last_clu = clu.dir;
+ if (exfat_get_next_cluster(sb, &(clu.dir)))
+ return -EIO;
+
+ num_clusters--;
+ clu.size--;
+ }
+ }
+ } else {
+ ei->flags = ALLOC_NO_FAT_CHAIN;
+ ei->start_clu = EXFAT_EOF_CLUSTER;
+ }
+
+ i_size_write(inode, new_size);
+
+ if (ei->type == TYPE_FILE)
+ ei->attr |= ATTR_ARCHIVE;
+
+ /* update the directory entry */
+ if (!evict) {
+ struct timespec64 ts;
+
+ es = exfat_get_dentry_set(sb, &(ei->dir), ei->entry,
+ ES_ALL_ENTRIES, &ep);
+ if (!es)
+ return -EIO;
+ ep2 = ep + 1;
+
+ ts = current_time(inode);
+ exfat_set_entry_time(sbi, &ts,
+ &ep->dentry.file.modify_tz,
+ &ep->dentry.file.modify_time,
+ &ep->dentry.file.modify_date,
+ &ep->dentry.file.modify_time_ms);
+ ep->dentry.file.attr = cpu_to_le16(ei->attr);
+
+ /* File size should be zero if there is no cluster allocated */
+ if (ei->start_clu == EXFAT_EOF_CLUSTER) {
+ ep->dentry.stream.valid_size = 0;
+ ep->dentry.stream.size = 0;
+ } else {
+ ep->dentry.stream.valid_size = cpu_to_le64(new_size);
+ ep->dentry.stream.size = ep->dentry.stream.valid_size;
+ }
+
+ if (new_size == 0) {
+ /* Any directory can not be truncated to zero */
+ WARN_ON(ei->type != TYPE_FILE);
+
+ ep2->dentry.stream.flags = ALLOC_FAT_CHAIN;
+ ep2->dentry.stream.start_clu = EXFAT_FREE_CLUSTER;
+ }
+
+ if (exfat_update_dir_chksum_with_entry_set(sb, es,
+ inode_needs_sync(inode)))
+ return -EIO;
+ kfree(es);
+ }
+
+ /* cut off from the FAT chain */
+ if (ei->flags == ALLOC_FAT_CHAIN && last_clu != EXFAT_FREE_CLUSTER &&
+ last_clu != EXFAT_EOF_CLUSTER) {
+ if (exfat_ent_set(sb, last_clu, EXFAT_EOF_CLUSTER))
+ return -EIO;
+ }
+
+ /* invalidate cache and free the clusters */
+ /* clear exfat cache */
+ exfat_cache_inval_inode(inode);
+
+ /* hint information */
+ ei->hint_bmap.off = EXFAT_EOF_CLUSTER;
+ ei->hint_bmap.clu = EXFAT_EOF_CLUSTER;
+ if (ei->rwoffset > new_size)
+ ei->rwoffset = new_size;
+
+ /* hint_stat will be used if this is directory. */
+ ei->hint_stat.eidx = 0;
+ ei->hint_stat.clu = ei->start_clu;
+ ei->hint_femp.eidx = EXFAT_HINT_NONE;
+
+ /* free the clusters */
+ if (exfat_free_cluster(inode, &clu))
+ return -EIO;
+
+ exfat_set_vol_flags(sb, VOL_CLEAN);
+
+ return 0;
+}
+
+void exfat_truncate(struct inode *inode, loff_t size)
+{
+ struct super_block *sb = inode->i_sb;
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
+ unsigned int blocksize = 1 << inode->i_blkbits;
+ loff_t aligned_size;
+ int err;
+
+ mutex_lock(&sbi->s_lock);
+ if (EXFAT_I(inode)->start_clu == 0) {
+ /*
+ * Empty start_clu != ~0 (not allocated)
+ */
+ exfat_fs_error(sb, "tried to truncate zeroed cluster.");
+ goto write_size;
+ }
+
+ err = __exfat_truncate(inode, i_size_read(inode));
+ if (err)
+ goto write_size;
+
+ inode->i_ctime = inode->i_mtime = current_time(inode);
+ if (IS_DIRSYNC(inode))
+ exfat_sync_inode(inode);
+ else
+ mark_inode_dirty(inode);
+
+ inode->i_blocks = ((i_size_read(inode) + (sbi->cluster_size - 1)) &
+ ~(sbi->cluster_size - 1)) >> inode->i_blkbits;
+write_size:
+ aligned_size = i_size_read(inode);
+ if (aligned_size & (blocksize - 1)) {
+ aligned_size |= (blocksize - 1);
+ aligned_size++;
+ }
+
+ if (EXFAT_I(inode)->i_size_ondisk > i_size_read(inode))
+ EXFAT_I(inode)->i_size_ondisk = aligned_size;
+
+ if (EXFAT_I(inode)->i_size_aligned > i_size_read(inode))
+ EXFAT_I(inode)->i_size_aligned = aligned_size;
+ mutex_unlock(&sbi->s_lock);
+}
+
+int exfat_getattr(const struct path *path, struct kstat *stat,
+ unsigned int request_mask, unsigned int query_flags)
+{
+ struct inode *inode = d_backing_inode(path->dentry);
+ struct exfat_inode_info *ei = EXFAT_I(inode);
+
+ generic_fillattr(inode, stat);
+ stat->result_mask |= STATX_BTIME;
+ stat->btime.tv_sec = ei->i_crtime.tv_sec;
+ stat->btime.tv_nsec = ei->i_crtime.tv_nsec;
+ stat->blksize = EXFAT_SB(inode->i_sb)->cluster_size;
+ return 0;
+}
+
+int exfat_setattr(struct dentry *dentry, struct iattr *attr)
+{
+ struct exfat_sb_info *sbi = EXFAT_SB(dentry->d_sb);
+ struct inode *inode = dentry->d_inode;
+ unsigned int ia_valid;
+ int error;
+
+ if ((attr->ia_valid & ATTR_SIZE) &&
+ attr->ia_size > i_size_read(inode)) {
+ error = exfat_cont_expand(inode, attr->ia_size);
+ if (error || attr->ia_valid == ATTR_SIZE)
+ return error;
+ attr->ia_valid &= ~ATTR_SIZE;
+ }
+
+ /* Check for setting the inode time. */
+ ia_valid = attr->ia_valid;
+ if ((ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)) &&
+ exfat_allow_set_time(sbi, inode)) {
+ attr->ia_valid &= ~(ATTR_MTIME_SET | ATTR_ATIME_SET |
+ ATTR_TIMES_SET);
+ }
+
+ error = setattr_prepare(dentry, attr);
+ attr->ia_valid = ia_valid;
+ if (error)
+ goto out;
+
+ if (((attr->ia_valid & ATTR_UID) &&
+ !uid_eq(attr->ia_uid, sbi->options.fs_uid)) ||
+ ((attr->ia_valid & ATTR_GID) &&
+ !gid_eq(attr->ia_gid, sbi->options.fs_gid)) ||
+ ((attr->ia_valid & ATTR_MODE) &&
+ (attr->ia_mode & ~(S_IFREG | S_IFLNK | S_IFDIR | 0777)))) {
+ error = -EPERM;
+ goto out;
+ }
+
+ /*
+ * We don't return -EPERM here. Yes, strange, but this is too
+ * old behavior.
+ */
+ if (attr->ia_valid & ATTR_MODE) {
+ if (exfat_sanitize_mode(sbi, inode, &attr->ia_mode) < 0)
+ attr->ia_valid &= ~ATTR_MODE;
+ }
+
+ if (attr->ia_valid & ATTR_SIZE) {
+ error = exfat_block_truncate_page(inode, attr->ia_size);
+ if (error)
+ goto out;
+
+ down_write(&EXFAT_I(inode)->truncate_lock);
+ truncate_setsize(inode, attr->ia_size);
+ exfat_truncate(inode, attr->ia_size);
+ up_write(&EXFAT_I(inode)->truncate_lock);
+ }
+
+ setattr_copy(inode, attr);
+ mark_inode_dirty(inode);
+
+out:
+ return error;
+}
+
+const struct file_operations exfat_file_operations = {
+ .llseek = generic_file_llseek,
+ .read_iter = generic_file_read_iter,
+ .write_iter = generic_file_write_iter,
+ .mmap = generic_file_mmap,
+ .fsync = generic_file_fsync,
+ .splice_read = generic_file_splice_read,
+};
+
+const struct inode_operations exfat_file_inode_operations = {
+ .setattr = exfat_setattr,
+ .getattr = exfat_getattr,
+};
--
2.25.1
@@ -0,0 +1,740 @@
From 1acf1a564b6034b5af1e7fb23cb98cb3bb4f6003 Mon Sep 17 00:00:00 2001
From: Namjae Jeon <namjae.jeon@samsung.com>
Date: Mon, 2 Mar 2020 15:21:32 +0900
Subject: [PATCH 01/14] exfat: add in-memory and on-disk structures and headers
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This adds in-memory and on-disk structures and headers.
Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com>
Signed-off-by: Sungjong Seo <sj1557.seo@samsung.com>
Reviewed-by: Pali Rohár <pali.rohar@gmail.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/exfat/exfat_fs.h | 519 +++++++++++++++++++++++++++++++++++++++++++
fs/exfat/exfat_raw.h | 184 +++++++++++++++
2 files changed, 703 insertions(+)
create mode 100644 fs/exfat/exfat_fs.h
create mode 100644 fs/exfat/exfat_raw.h
diff --git a/fs/exfat/exfat_fs.h b/fs/exfat/exfat_fs.h
new file mode 100644
index 000000000000..67d4e46fb810
--- /dev/null
+++ b/fs/exfat/exfat_fs.h
@@ -0,0 +1,519 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
+ */
+
+#ifndef _EXFAT_FS_H
+#define _EXFAT_FS_H
+
+#include <linux/fs.h>
+#include <linux/ratelimit.h>
+#include <linux/nls.h>
+
+#define EXFAT_SUPER_MAGIC 0x2011BAB0UL
+#define EXFAT_ROOT_INO 1
+
+#define EXFAT_SB_DIRTY 0
+
+#define EXFAT_CLUSTERS_UNTRACKED (~0u)
+
+/*
+ * exfat error flags
+ */
+enum exfat_error_mode {
+ EXFAT_ERRORS_CONT, /* ignore error and continue */
+ EXFAT_ERRORS_PANIC, /* panic on error */
+ EXFAT_ERRORS_RO, /* remount r/o on error */
+};
+
+/*
+ * exfat nls lossy flag
+ */
+enum {
+ NLS_NAME_NO_LOSSY, /* no lossy */
+ NLS_NAME_LOSSY, /* just detected incorrect filename(s) */
+ NLS_NAME_OVERLEN, /* the length is over than its limit */
+};
+
+#define EXFAT_HASH_BITS 8
+#define EXFAT_HASH_SIZE (1UL << EXFAT_HASH_BITS)
+
+/*
+ * Type Definitions
+ */
+#define ES_2_ENTRIES 2
+#define ES_ALL_ENTRIES 0
+
+#define DIR_DELETED 0xFFFF0321
+
+/* type values */
+#define TYPE_UNUSED 0x0000
+#define TYPE_DELETED 0x0001
+#define TYPE_INVALID 0x0002
+#define TYPE_CRITICAL_PRI 0x0100
+#define TYPE_BITMAP 0x0101
+#define TYPE_UPCASE 0x0102
+#define TYPE_VOLUME 0x0103
+#define TYPE_DIR 0x0104
+#define TYPE_FILE 0x011F
+#define TYPE_CRITICAL_SEC 0x0200
+#define TYPE_STREAM 0x0201
+#define TYPE_EXTEND 0x0202
+#define TYPE_ACL 0x0203
+#define TYPE_BENIGN_PRI 0x0400
+#define TYPE_GUID 0x0401
+#define TYPE_PADDING 0x0402
+#define TYPE_ACLTAB 0x0403
+#define TYPE_BENIGN_SEC 0x0800
+#define TYPE_ALL 0x0FFF
+
+#define MAX_CHARSET_SIZE 6 /* max size of multi-byte character */
+#define MAX_NAME_LENGTH 255 /* max len of file name excluding NULL */
+#define MAX_VFSNAME_BUF_SIZE ((MAX_NAME_LENGTH + 1) * MAX_CHARSET_SIZE)
+
+#define FAT_CACHE_SIZE 128
+#define FAT_CACHE_HASH_SIZE 64
+#define BUF_CACHE_SIZE 256
+#define BUF_CACHE_HASH_SIZE 64
+
+#define EXFAT_HINT_NONE -1
+#define EXFAT_MIN_SUBDIR 2
+
+/*
+ * helpers for cluster size to byte conversion.
+ */
+#define EXFAT_CLU_TO_B(b, sbi) ((b) << (sbi)->cluster_size_bits)
+#define EXFAT_B_TO_CLU(b, sbi) ((b) >> (sbi)->cluster_size_bits)
+#define EXFAT_B_TO_CLU_ROUND_UP(b, sbi) \
+ (((b - 1) >> (sbi)->cluster_size_bits) + 1)
+#define EXFAT_CLU_OFFSET(off, sbi) ((off) & ((sbi)->cluster_size - 1))
+
+/*
+ * helpers for block size to byte conversion.
+ */
+#define EXFAT_BLK_TO_B(b, sb) ((b) << (sb)->s_blocksize_bits)
+#define EXFAT_B_TO_BLK(b, sb) ((b) >> (sb)->s_blocksize_bits)
+#define EXFAT_B_TO_BLK_ROUND_UP(b, sb) \
+ (((b - 1) >> (sb)->s_blocksize_bits) + 1)
+#define EXFAT_BLK_OFFSET(off, sb) ((off) & ((sb)->s_blocksize - 1))
+
+/*
+ * helpers for block size to dentry size conversion.
+ */
+#define EXFAT_B_TO_DEN_IDX(b, sbi) \
+ ((b) << ((sbi)->cluster_size_bits - DENTRY_SIZE_BITS))
+#define EXFAT_B_TO_DEN(b) ((b) >> DENTRY_SIZE_BITS)
+#define EXFAT_DEN_TO_B(b) ((b) << DENTRY_SIZE_BITS)
+
+/*
+ * helpers for fat entry.
+ */
+#define FAT_ENT_SIZE (4)
+#define FAT_ENT_SIZE_BITS (2)
+#define FAT_ENT_OFFSET_SECTOR(sb, loc) (EXFAT_SB(sb)->FAT1_start_sector + \
+ (((u64)loc << FAT_ENT_SIZE_BITS) >> sb->s_blocksize_bits))
+#define FAT_ENT_OFFSET_BYTE_IN_SECTOR(sb, loc) \
+ ((loc << FAT_ENT_SIZE_BITS) & (sb->s_blocksize - 1))
+
+/*
+ * helpers for bitmap.
+ */
+#define CLUSTER_TO_BITMAP_ENT(clu) ((clu) - EXFAT_RESERVED_CLUSTERS)
+#define BITMAP_ENT_TO_CLUSTER(ent) ((ent) + EXFAT_RESERVED_CLUSTERS)
+#define BITS_PER_SECTOR(sb) ((sb)->s_blocksize * BITS_PER_BYTE)
+#define BITS_PER_SECTOR_MASK(sb) (BITS_PER_SECTOR(sb) - 1)
+#define BITMAP_OFFSET_SECTOR_INDEX(sb, ent) \
+ ((ent / BITS_PER_BYTE) >> (sb)->s_blocksize_bits)
+#define BITMAP_OFFSET_BIT_IN_SECTOR(sb, ent) (ent & BITS_PER_SECTOR_MASK(sb))
+#define BITMAP_OFFSET_BYTE_IN_SECTOR(sb, ent) \
+ ((ent / BITS_PER_BYTE) & ((sb)->s_blocksize - 1))
+#define BITS_PER_BYTE_MASK 0x7
+#define IGNORED_BITS_REMAINED(clu, clu_base) ((1 << ((clu) - (clu_base))) - 1)
+
+struct exfat_dentry_namebuf {
+ char *lfn;
+ int lfnbuf_len; /* usally MAX_UNINAME_BUF_SIZE */
+};
+
+/* unicode name structure */
+struct exfat_uni_name {
+ /* +3 for null and for converting */
+ unsigned short name[MAX_NAME_LENGTH + 3];
+ unsigned short name_hash;
+ unsigned char name_len;
+};
+
+/* directory structure */
+struct exfat_chain {
+ unsigned int dir;
+ unsigned int size;
+ unsigned char flags;
+};
+
+/* first empty entry hint information */
+struct exfat_hint_femp {
+ /* entry index of a directory */
+ int eidx;
+ /* count of continuous empty entry */
+ int count;
+ /* the cluster that first empty slot exists in */
+ struct exfat_chain cur;
+};
+
+/* hint structure */
+struct exfat_hint {
+ unsigned int clu;
+ union {
+ unsigned int off; /* cluster offset */
+ int eidx; /* entry index */
+ };
+};
+
+struct exfat_entry_set_cache {
+ /* sector number that contains file_entry */
+ sector_t sector;
+ /* byte offset in the sector */
+ unsigned int offset;
+ /* flag in stream entry. 01 for cluster chain, 03 for contig. */
+ int alloc_flag;
+ unsigned int num_entries;
+ struct exfat_dentry entries[];
+};
+
+struct exfat_dir_entry {
+ struct exfat_chain dir;
+ int entry;
+ unsigned int type;
+ unsigned int start_clu;
+ unsigned char flags;
+ unsigned short attr;
+ loff_t size;
+ unsigned int num_subdirs;
+ struct timespec64 atime;
+ struct timespec64 mtime;
+ struct timespec64 crtime;
+ struct exfat_dentry_namebuf namebuf;
+};
+
+/*
+ * exfat mount in-memory data
+ */
+struct exfat_mount_options {
+ kuid_t fs_uid;
+ kgid_t fs_gid;
+ unsigned short fs_fmask;
+ unsigned short fs_dmask;
+ /* permission for setting the [am]time */
+ unsigned short allow_utime;
+ /* charset for filename input/display */
+ char *iocharset;
+ /* on error: continue, panic, remount-ro */
+ enum exfat_error_mode errors;
+ unsigned utf8:1, /* Use of UTF-8 character set */
+ discard:1; /* Issue discard requests on deletions */
+ int time_offset; /* Offset of timestamps from UTC (in minutes) */
+};
+
+/*
+ * EXFAT file system superblock in-memory data
+ */
+struct exfat_sb_info {
+ unsigned long long num_sectors; /* num of sectors in volume */
+ unsigned int num_clusters; /* num of clusters in volume */
+ unsigned int cluster_size; /* cluster size in bytes */
+ unsigned int cluster_size_bits;
+ unsigned int sect_per_clus; /* cluster size in sectors */
+ unsigned int sect_per_clus_bits;
+ unsigned long long FAT1_start_sector; /* FAT1 start sector */
+ unsigned long long FAT2_start_sector; /* FAT2 start sector */
+ unsigned long long data_start_sector; /* data area start sector */
+ unsigned int num_FAT_sectors; /* num of FAT sectors */
+ unsigned int root_dir; /* root dir cluster */
+ unsigned int dentries_per_clu; /* num of dentries per cluster */
+ unsigned int vol_flag; /* volume dirty flag */
+ struct buffer_head *pbr_bh; /* buffer_head of PBR sector */
+
+ unsigned int map_clu; /* allocation bitmap start cluster */
+ unsigned int map_sectors; /* num of allocation bitmap sectors */
+ struct buffer_head **vol_amap; /* allocation bitmap */
+
+ unsigned short *vol_utbl; /* upcase table */
+
+ unsigned int clu_srch_ptr; /* cluster search pointer */
+ unsigned int used_clusters; /* number of used clusters */
+
+ unsigned long s_state;
+ struct mutex s_lock; /* superblock lock */
+ struct exfat_mount_options options;
+ struct nls_table *nls_io; /* Charset used for input and display */
+ struct ratelimit_state ratelimit;
+
+ spinlock_t inode_hash_lock;
+ struct hlist_head inode_hashtable[EXFAT_HASH_SIZE];
+
+ struct rcu_head rcu;
+};
+
+/*
+ * EXFAT file system inode in-memory data
+ */
+struct exfat_inode_info {
+ struct exfat_chain dir;
+ int entry;
+ unsigned int type;
+ unsigned short attr;
+ unsigned int start_clu;
+ unsigned char flags;
+ /*
+ * the copy of low 32bit of i_version to check
+ * the validation of hint_stat.
+ */
+ unsigned int version;
+ /* file offset or dentry index for readdir */
+ loff_t rwoffset;
+
+ /* hint for cluster last accessed */
+ struct exfat_hint hint_bmap;
+ /* hint for entry index we try to lookup next time */
+ struct exfat_hint hint_stat;
+ /* hint for first empty entry */
+ struct exfat_hint_femp hint_femp;
+
+ spinlock_t cache_lru_lock;
+ struct list_head cache_lru;
+ int nr_caches;
+ /* for avoiding the race between alloc and free */
+ unsigned int cache_valid_id;
+
+ /*
+ * NOTE: i_size_ondisk is 64bits, so must hold ->inode_lock to access.
+ * physically allocated size.
+ */
+ loff_t i_size_ondisk;
+ /* block-aligned i_size (used in cont_write_begin) */
+ loff_t i_size_aligned;
+ /* on-disk position of directory entry or 0 */
+ loff_t i_pos;
+ /* hash by i_location */
+ struct hlist_node i_hash_fat;
+ /* protect bmap against truncate */
+ struct rw_semaphore truncate_lock;
+ struct inode vfs_inode;
+ /* File creation time */
+ struct timespec64 i_crtime;
+};
+
+static inline struct exfat_sb_info *EXFAT_SB(struct super_block *sb)
+{
+ return sb->s_fs_info;
+}
+
+static inline struct exfat_inode_info *EXFAT_I(struct inode *inode)
+{
+ return container_of(inode, struct exfat_inode_info, vfs_inode);
+}
+
+/*
+ * If ->i_mode can't hold 0222 (i.e. ATTR_RO), we use ->i_attrs to
+ * save ATTR_RO instead of ->i_mode.
+ *
+ * If it's directory and !sbi->options.rodir, ATTR_RO isn't read-only
+ * bit, it's just used as flag for app.
+ */
+static inline int exfat_mode_can_hold_ro(struct inode *inode)
+{
+ struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb);
+
+ if (S_ISDIR(inode->i_mode))
+ return 0;
+
+ if ((~sbi->options.fs_fmask) & 0222)
+ return 1;
+ return 0;
+}
+
+/* Convert attribute bits and a mask to the UNIX mode. */
+static inline mode_t exfat_make_mode(struct exfat_sb_info *sbi,
+ unsigned short attr, mode_t mode)
+{
+ if ((attr & ATTR_READONLY) && !(attr & ATTR_SUBDIR))
+ mode &= ~0222;
+
+ if (attr & ATTR_SUBDIR)
+ return (mode & ~sbi->options.fs_dmask) | S_IFDIR;
+
+ return (mode & ~sbi->options.fs_fmask) | S_IFREG;
+}
+
+/* Return the FAT attribute byte for this inode */
+static inline unsigned short exfat_make_attr(struct inode *inode)
+{
+ unsigned short attr = EXFAT_I(inode)->attr;
+
+ if (S_ISDIR(inode->i_mode))
+ attr |= ATTR_SUBDIR;
+ if (exfat_mode_can_hold_ro(inode) && !(inode->i_mode & 0222))
+ attr |= ATTR_READONLY;
+ return attr;
+}
+
+static inline void exfat_save_attr(struct inode *inode, unsigned short attr)
+{
+ if (exfat_mode_can_hold_ro(inode))
+ EXFAT_I(inode)->attr = attr & (ATTR_RWMASK | ATTR_READONLY);
+ else
+ EXFAT_I(inode)->attr = attr & ATTR_RWMASK;
+}
+
+static inline bool exfat_is_last_sector_in_cluster(struct exfat_sb_info *sbi,
+ sector_t sec)
+{
+ return ((sec - sbi->data_start_sector + 1) &
+ ((1 << sbi->sect_per_clus_bits) - 1)) == 0;
+}
+
+static inline sector_t exfat_cluster_to_sector(struct exfat_sb_info *sbi,
+ unsigned int clus)
+{
+ return ((clus - EXFAT_RESERVED_CLUSTERS) << sbi->sect_per_clus_bits) +
+ sbi->data_start_sector;
+}
+
+static inline int exfat_sector_to_cluster(struct exfat_sb_info *sbi,
+ sector_t sec)
+{
+ return ((sec - sbi->data_start_sector) >> sbi->sect_per_clus_bits) +
+ EXFAT_RESERVED_CLUSTERS;
+}
+
+/* super.c */
+int exfat_set_vol_flags(struct super_block *sb, unsigned short new_flag);
+
+/* fatent.c */
+#define exfat_get_next_cluster(sb, pclu) exfat_ent_get(sb, *(pclu), pclu)
+
+int exfat_alloc_cluster(struct inode *inode, unsigned int num_alloc,
+ struct exfat_chain *p_chain);
+int exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain);
+int exfat_ent_get(struct super_block *sb, unsigned int loc,
+ unsigned int *content);
+int exfat_ent_set(struct super_block *sb, unsigned int loc,
+ unsigned int content);
+int exfat_count_ext_entries(struct super_block *sb, struct exfat_chain *p_dir,
+ int entry, struct exfat_dentry *p_entry);
+int exfat_chain_cont_cluster(struct super_block *sb, unsigned int chain,
+ unsigned int len);
+int exfat_zeroed_cluster(struct inode *dir, unsigned int clu);
+int exfat_find_last_cluster(struct super_block *sb, struct exfat_chain *p_chain,
+ unsigned int *ret_clu);
+int exfat_count_num_clusters(struct super_block *sb,
+ struct exfat_chain *p_chain, unsigned int *ret_count);
+
+/* balloc.c */
+int exfat_load_bitmap(struct super_block *sb);
+void exfat_free_bitmap(struct exfat_sb_info *sbi);
+int exfat_set_bitmap(struct inode *inode, unsigned int clu);
+void exfat_clear_bitmap(struct inode *inode, unsigned int clu);
+unsigned int exfat_find_free_bitmap(struct super_block *sb, unsigned int clu);
+int exfat_count_used_clusters(struct super_block *sb, unsigned int *ret_count);
+
+/* file.c */
+extern const struct file_operations exfat_file_operations;
+int __exfat_truncate(struct inode *inode, loff_t new_size);
+void exfat_truncate(struct inode *inode, loff_t size);
+int exfat_setattr(struct dentry *dentry, struct iattr *attr);
+int exfat_getattr(const struct path *path, struct kstat *stat,
+ unsigned int request_mask, unsigned int query_flags);
+
+/* namei.c */
+extern const struct dentry_operations exfat_dentry_ops;
+extern const struct dentry_operations exfat_utf8_dentry_ops;
+
+/* cache.c */
+int exfat_cache_init(void);
+void exfat_cache_shutdown(void);
+void exfat_cache_init_inode(struct inode *inode);
+void exfat_cache_inval_inode(struct inode *inode);
+int exfat_get_cluster(struct inode *inode, unsigned int cluster,
+ unsigned int *fclus, unsigned int *dclus,
+ unsigned int *last_dclus, int allow_eof);
+
+/* dir.c */
+extern const struct inode_operations exfat_dir_inode_operations;
+extern const struct file_operations exfat_dir_operations;
+unsigned int exfat_get_entry_type(struct exfat_dentry *p_entry);
+int exfat_init_dir_entry(struct inode *inode, struct exfat_chain *p_dir,
+ int entry, unsigned int type, unsigned int start_clu,
+ unsigned long long size);
+int exfat_init_ext_entry(struct inode *inode, struct exfat_chain *p_dir,
+ int entry, int num_entries, struct exfat_uni_name *p_uniname);
+int exfat_remove_entries(struct inode *inode, struct exfat_chain *p_dir,
+ int entry, int order, int num_entries);
+int exfat_update_dir_chksum(struct inode *inode, struct exfat_chain *p_dir,
+ int entry);
+int exfat_update_dir_chksum_with_entry_set(struct super_block *sb,
+ struct exfat_entry_set_cache *es, int sync);
+int exfat_calc_num_entries(struct exfat_uni_name *p_uniname);
+int exfat_find_dir_entry(struct super_block *sb, struct exfat_inode_info *ei,
+ struct exfat_chain *p_dir, struct exfat_uni_name *p_uniname,
+ int num_entries, unsigned int type);
+int exfat_alloc_new_dir(struct inode *inode, struct exfat_chain *clu);
+int exfat_find_location(struct super_block *sb, struct exfat_chain *p_dir,
+ int entry, sector_t *sector, int *offset);
+struct exfat_dentry *exfat_get_dentry(struct super_block *sb,
+ struct exfat_chain *p_dir, int entry, struct buffer_head **bh,
+ sector_t *sector);
+struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb,
+ struct exfat_chain *p_dir, int entry, unsigned int type,
+ struct exfat_dentry **file_ep);
+int exfat_count_dir_entries(struct super_block *sb, struct exfat_chain *p_dir);
+
+/* inode.c */
+extern const struct inode_operations exfat_file_inode_operations;
+void exfat_sync_inode(struct inode *inode);
+struct inode *exfat_build_inode(struct super_block *sb,
+ struct exfat_dir_entry *info, loff_t i_pos);
+void exfat_hash_inode(struct inode *inode, loff_t i_pos);
+void exfat_unhash_inode(struct inode *inode);
+struct inode *exfat_iget(struct super_block *sb, loff_t i_pos);
+int exfat_write_inode(struct inode *inode, struct writeback_control *wbc);
+void exfat_evict_inode(struct inode *inode);
+int exfat_block_truncate_page(struct inode *inode, loff_t from);
+
+/* exfat/nls.c */
+unsigned short exfat_toupper(struct super_block *sb, unsigned short a);
+int exfat_uniname_ncmp(struct super_block *sb, unsigned short *a,
+ unsigned short *b, unsigned int len);
+int exfat_utf16_to_nls(struct super_block *sb,
+ struct exfat_uni_name *uniname, unsigned char *p_cstring,
+ int len);
+int exfat_nls_to_utf16(struct super_block *sb,
+ const unsigned char *p_cstring, const int len,
+ struct exfat_uni_name *uniname, int *p_lossy);
+int exfat_create_upcase_table(struct super_block *sb);
+void exfat_free_upcase_table(struct exfat_sb_info *sbi);
+unsigned short exfat_high_surrogate(unicode_t u);
+unsigned short exfat_low_surrogate(unicode_t u);
+
+/* exfat/misc.c */
+void __exfat_fs_error(struct super_block *sb, int report, const char *fmt, ...)
+ __printf(3, 4) __cold;
+#define exfat_fs_error(sb, fmt, args...) \
+ __exfat_fs_error(sb, 1, fmt, ## args)
+#define exfat_fs_error_ratelimit(sb, fmt, args...) \
+ __exfat_fs_error(sb, __ratelimit(&EXFAT_SB(sb)->ratelimit), \
+ fmt, ## args)
+void exfat_msg(struct super_block *sb, const char *lv, const char *fmt, ...)
+ __printf(3, 4) __cold;
+void exfat_get_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts,
+ u8 tz, __le16 time, __le16 date, u8 time_ms);
+void exfat_set_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts,
+ u8 *tz, __le16 *time, __le16 *date, u8 *time_ms);
+unsigned short exfat_calc_chksum_2byte(void *data, int len,
+ unsigned short chksum, int type);
+void exfat_update_bh(struct super_block *sb, struct buffer_head *bh, int sync);
+void exfat_chain_set(struct exfat_chain *ec, unsigned int dir,
+ unsigned int size, unsigned char flags);
+void exfat_chain_dup(struct exfat_chain *dup, struct exfat_chain *ec);
+
+#endif /* !_EXFAT_FS_H */
diff --git a/fs/exfat/exfat_raw.h b/fs/exfat/exfat_raw.h
new file mode 100644
index 000000000000..2a841010e649
--- /dev/null
+++ b/fs/exfat/exfat_raw.h
@@ -0,0 +1,184 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
+ */
+
+#ifndef _EXFAT_RAW_H
+#define _EXFAT_RAW_H
+
+#include <linux/types.h>
+
+#define PBR_SIGNATURE 0xAA55
+
+#define EXFAT_MAX_FILE_LEN 255
+
+#define VOL_CLEAN 0x0000
+#define VOL_DIRTY 0x0002
+
+#define EXFAT_EOF_CLUSTER 0xFFFFFFFFu
+#define EXFAT_BAD_CLUSTER 0xFFFFFFF7u
+#define EXFAT_FREE_CLUSTER 0
+/* Cluster 0, 1 are reserved, the first cluster is 2 in the cluster heap. */
+#define EXFAT_RESERVED_CLUSTERS 2
+#define EXFAT_FIRST_CLUSTER 2
+#define EXFAT_DATA_CLUSTER_COUNT(sbi) \
+ ((sbi)->num_clusters - EXFAT_RESERVED_CLUSTERS)
+
+/* AllocationPossible and NoFatChain field in GeneralSecondaryFlags Field */
+#define ALLOC_FAT_CHAIN 0x01
+#define ALLOC_NO_FAT_CHAIN 0x03
+
+#define DENTRY_SIZE 32 /* directory entry size */
+#define DENTRY_SIZE_BITS 5
+/* exFAT allows 8388608(256MB) directory entries */
+#define MAX_EXFAT_DENTRIES 8388608
+
+/* dentry types */
+#define EXFAT_UNUSED 0x00 /* end of directory */
+#define EXFAT_DELETE (~0x80)
+#define IS_EXFAT_DELETED(x) ((x) < 0x80) /* deleted file (0x01~0x7F) */
+#define EXFAT_INVAL 0x80 /* invalid value */
+#define EXFAT_BITMAP 0x81 /* allocation bitmap */
+#define EXFAT_UPCASE 0x82 /* upcase table */
+#define EXFAT_VOLUME 0x83 /* volume label */
+#define EXFAT_FILE 0x85 /* file or dir */
+#define EXFAT_GUID 0xA0
+#define EXFAT_PADDING 0xA1
+#define EXFAT_ACLTAB 0xA2
+#define EXFAT_STREAM 0xC0 /* stream entry */
+#define EXFAT_NAME 0xC1 /* file name entry */
+#define EXFAT_ACL 0xC2 /* stream entry */
+
+#define IS_EXFAT_CRITICAL_PRI(x) (x < 0xA0)
+#define IS_EXFAT_BENIGN_PRI(x) (x < 0xC0)
+#define IS_EXFAT_CRITICAL_SEC(x) (x < 0xE0)
+
+/* checksum types */
+#define CS_DIR_ENTRY 0
+#define CS_PBR_SECTOR 1
+#define CS_DEFAULT 2
+
+/* file attributes */
+#define ATTR_READONLY 0x0001
+#define ATTR_HIDDEN 0x0002
+#define ATTR_SYSTEM 0x0004
+#define ATTR_VOLUME 0x0008
+#define ATTR_SUBDIR 0x0010
+#define ATTR_ARCHIVE 0x0020
+
+#define ATTR_RWMASK (ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME | \
+ ATTR_SUBDIR | ATTR_ARCHIVE)
+
+#define PBR64_JUMP_BOOT_LEN 3
+#define PBR64_OEM_NAME_LEN 8
+#define PBR64_RESERVED_LEN 53
+
+#define EXFAT_FILE_NAME_LEN 15
+
+/* EXFAT BIOS parameter block (64 bytes) */
+struct bpb64 {
+ __u8 jmp_boot[PBR64_JUMP_BOOT_LEN];
+ __u8 oem_name[PBR64_OEM_NAME_LEN];
+ __u8 res_zero[PBR64_RESERVED_LEN];
+} __packed;
+
+/* EXFAT EXTEND BIOS parameter block (56 bytes) */
+struct bsx64 {
+ __le64 vol_offset;
+ __le64 vol_length;
+ __le32 fat_offset;
+ __le32 fat_length;
+ __le32 clu_offset;
+ __le32 clu_count;
+ __le32 root_cluster;
+ __le32 vol_serial;
+ __u8 fs_version[2];
+ __le16 vol_flags;
+ __u8 sect_size_bits;
+ __u8 sect_per_clus_bits;
+ __u8 num_fats;
+ __u8 phy_drv_no;
+ __u8 perc_in_use;
+ __u8 reserved2[7];
+} __packed;
+
+/* EXFAT PBR[BPB+BSX] (120 bytes) */
+struct pbr64 {
+ struct bpb64 bpb;
+ struct bsx64 bsx;
+} __packed;
+
+/* Common PBR[Partition Boot Record] (512 bytes) */
+struct pbr {
+ union {
+ __u8 raw[64];
+ struct bpb64 f64;
+ } bpb;
+ union {
+ __u8 raw[56];
+ struct bsx64 f64;
+ } bsx;
+ __u8 boot_code[390];
+ __le16 signature;
+} __packed;
+
+struct exfat_dentry {
+ __u8 type;
+ union {
+ struct {
+ __u8 num_ext;
+ __le16 checksum;
+ __le16 attr;
+ __le16 reserved1;
+ __le16 create_time;
+ __le16 create_date;
+ __le16 modify_time;
+ __le16 modify_date;
+ __le16 access_time;
+ __le16 access_date;
+ __u8 create_time_ms;
+ __u8 modify_time_ms;
+ __u8 create_tz;
+ __u8 modify_tz;
+ __u8 access_tz;
+ __u8 reserved2[7];
+ } __packed file; /* file directory entry */
+ struct {
+ __u8 flags;
+ __u8 reserved1;
+ __u8 name_len;
+ __le16 name_hash;
+ __le16 reserved2;
+ __le64 valid_size;
+ __le32 reserved3;
+ __le32 start_clu;
+ __le64 size;
+ } __packed stream; /* stream extension directory entry */
+ struct {
+ __u8 flags;
+ __le16 unicode_0_14[EXFAT_FILE_NAME_LEN];
+ } __packed name; /* file name directory entry */
+ struct {
+ __u8 flags;
+ __u8 reserved[18];
+ __le32 start_clu;
+ __le64 size;
+ } __packed bitmap; /* allocation bitmap directory entry */
+ struct {
+ __u8 reserved1[3];
+ __le32 checksum;
+ __u8 reserved2[12];
+ __le32 start_clu;
+ __le64 size;
+ } __packed upcase; /* up-case table directory entry */
+ } __packed dentry;
+} __packed;
+
+#define EXFAT_TZ_VALID (1 << 7)
+
+/* Jan 1 GMT 00:00:00 1980 */
+#define EXFAT_MIN_TIMESTAMP_SECS 315532800LL
+/* Dec 31 GMT 23:59:59 2107 */
+#define EXFAT_MAX_TIMESTAMP_SECS 4354819199LL
+
+#endif /* !_EXFAT_RAW_H */
--
2.25.1
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,193 @@
From 772b29cca528fcb21374bb3e597d848779938d16 Mon Sep 17 00:00:00 2001
From: Namjae Jeon <namjae.jeon@samsung.com>
Date: Mon, 2 Mar 2020 15:21:40 +0900
Subject: [PATCH 09/14] exfat: add misc operations
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This adds the implementation of misc operations for exfat.
Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com>
Signed-off-by: Sungjong Seo <sj1557.seo@samsung.com>
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Reviewed-by: Pali Rohár <pali.rohar@gmail.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/exfat/misc.c | 163 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 163 insertions(+)
create mode 100644 fs/exfat/misc.c
diff --git a/fs/exfat/misc.c b/fs/exfat/misc.c
new file mode 100644
index 000000000000..14a3300848f6
--- /dev/null
+++ b/fs/exfat/misc.c
@@ -0,0 +1,163 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Written 1992,1993 by Werner Almesberger
+ * 22/11/2000 - Fixed fat_date_unix2dos for dates earlier than 01/01/1980
+ * and date_dos2unix for date==0 by Igor Zhbanov(bsg@uniyar.ac.ru)
+ * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
+ */
+
+#include <linux/time.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/buffer_head.h>
+
+#include "exfat_raw.h"
+#include "exfat_fs.h"
+
+/*
+ * exfat_fs_error reports a file system problem that might indicate fa data
+ * corruption/inconsistency. Depending on 'errors' mount option the
+ * panic() is called, or error message is printed FAT and nothing is done,
+ * or filesystem is remounted read-only (default behavior).
+ * In case the file system is remounted read-only, it can be made writable
+ * again by remounting it.
+ */
+void __exfat_fs_error(struct super_block *sb, int report, const char *fmt, ...)
+{
+ struct exfat_mount_options *opts = &EXFAT_SB(sb)->options;
+ va_list args;
+ struct va_format vaf;
+
+ if (report) {
+ va_start(args, fmt);
+ vaf.fmt = fmt;
+ vaf.va = &args;
+ exfat_msg(sb, KERN_ERR, "error, %pV\n", &vaf);
+ va_end(args);
+ }
+
+ if (opts->errors == EXFAT_ERRORS_PANIC) {
+ panic("exFAT-fs (%s): fs panic from previous error\n",
+ sb->s_id);
+ } else if (opts->errors == EXFAT_ERRORS_RO && !sb_rdonly(sb)) {
+ sb->s_flags |= SB_RDONLY;
+ exfat_msg(sb, KERN_ERR, "Filesystem has been set read-only");
+ }
+}
+
+/*
+ * exfat_msg() - print preformated EXFAT specific messages.
+ * All logs except what uses exfat_fs_error() should be written by exfat_msg()
+ */
+void exfat_msg(struct super_block *sb, const char *level, const char *fmt, ...)
+{
+ struct va_format vaf;
+ va_list args;
+
+ va_start(args, fmt);
+ vaf.fmt = fmt;
+ vaf.va = &args;
+ /* level means KERN_ pacility level */
+ printk("%sexFAT-fs (%s): %pV\n", level, sb->s_id, &vaf);
+ va_end(args);
+}
+
+#define SECS_PER_MIN (60)
+#define TIMEZONE_SEC(x) ((x) * 15 * SECS_PER_MIN)
+
+static void exfat_adjust_tz(struct timespec64 *ts, u8 tz_off)
+{
+ if (tz_off <= 0x3F)
+ ts->tv_sec -= TIMEZONE_SEC(tz_off);
+ else /* 0x40 <= (tz_off & 0x7F) <=0x7F */
+ ts->tv_sec += TIMEZONE_SEC(0x80 - tz_off);
+}
+
+/* Convert a EXFAT time/date pair to a UNIX date (seconds since 1 1 70). */
+void exfat_get_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts,
+ u8 tz, __le16 time, __le16 date, u8 time_ms)
+{
+ u16 t = le16_to_cpu(time);
+ u16 d = le16_to_cpu(date);
+
+ ts->tv_sec = mktime64(1980 + (d >> 9), d >> 5 & 0x000F, d & 0x001F,
+ t >> 11, (t >> 5) & 0x003F, (t & 0x001F) << 1);
+
+
+ /* time_ms field represent 0 ~ 199(1990 ms) */
+ if (time_ms) {
+ ts->tv_sec += time_ms / 100;
+ ts->tv_nsec = (time_ms % 100) * 10 * NSEC_PER_MSEC;
+ }
+
+ if (tz & EXFAT_TZ_VALID)
+ /* Adjust timezone to UTC0. */
+ exfat_adjust_tz(ts, tz & ~EXFAT_TZ_VALID);
+ else
+ /* Convert from local time to UTC using time_offset. */
+ ts->tv_sec -= sbi->options.time_offset * SECS_PER_MIN;
+}
+
+/* Convert linear UNIX date to a EXFAT time/date pair. */
+void exfat_set_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts,
+ u8 *tz, __le16 *time, __le16 *date, u8 *time_ms)
+{
+ struct tm tm;
+ u16 t, d;
+
+ time64_to_tm(ts->tv_sec, 0, &tm);
+ t = (tm.tm_hour << 11) | (tm.tm_min << 5) | (tm.tm_sec >> 1);
+ d = ((tm.tm_year - 80) << 9) | ((tm.tm_mon + 1) << 5) | tm.tm_mday;
+
+ *time = cpu_to_le16(t);
+ *date = cpu_to_le16(d);
+
+ /* time_ms field represent 0 ~ 199(1990 ms) */
+ if (time_ms)
+ *time_ms = (tm.tm_sec & 1) * 100 +
+ ts->tv_nsec / (10 * NSEC_PER_MSEC);
+
+ /*
+ * Record 00h value for OffsetFromUtc field and 1 value for OffsetValid
+ * to indicate that local time and UTC are the same.
+ */
+ *tz = EXFAT_TZ_VALID;
+}
+
+unsigned short exfat_calc_chksum_2byte(void *data, int len,
+ unsigned short chksum, int type)
+{
+ int i;
+ unsigned char *c = (unsigned char *)data;
+
+ for (i = 0; i < len; i++, c++) {
+ if (((i == 2) || (i == 3)) && (type == CS_DIR_ENTRY))
+ continue;
+ chksum = (((chksum & 1) << 15) | ((chksum & 0xFFFE) >> 1)) +
+ (unsigned short)*c;
+ }
+ return chksum;
+}
+
+void exfat_update_bh(struct super_block *sb, struct buffer_head *bh, int sync)
+{
+ set_bit(EXFAT_SB_DIRTY, &EXFAT_SB(sb)->s_state);
+ set_buffer_uptodate(bh);
+ mark_buffer_dirty(bh);
+
+ if (sync)
+ sync_dirty_buffer(bh);
+}
+
+void exfat_chain_set(struct exfat_chain *ec, unsigned int dir,
+ unsigned int size, unsigned char flags)
+{
+ ec->dir = dir;
+ ec->size = size;
+ ec->flags = flags;
+}
+
+void exfat_chain_dup(struct exfat_chain *dup, struct exfat_chain *ec)
+{
+ return exfat_chain_set(dup, ec->dir, ec->size, ec->flags);
+}
--
2.25.1
@@ -0,0 +1,30 @@
From c37f83b424911f9bb6c9f17a4543c9c77cd73282 Mon Sep 17 00:00:00 2001
From: Thomas Backlund <tmb@mageia.org>
Date: Sat, 4 Apr 2020 23:00:31 +0300
Subject: [PATCH v2] exfat: add missing MODULE_ALIAS_FS()
This adds the necessary MODULE_ALIAS_FS() to exfat so the module gets
automatically loaded when an exfat filesystem is mounted.
Signed-off-by: Thomas Backlund <tmb@mageia.org>
Cc: Namjae Jeon <namjae.jeon@samsung.com>
Cc: Sungjong Seo <sj1557.seo@samsung.com>
---
fs/exfat/super.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/fs/exfat/super.c b/fs/exfat/super.c
index 16ed202ef527..b4a4063a0272 100644
--- a/fs/exfat/super.c
+++ b/fs/exfat/super.c
@@ -717,6 +717,7 @@ static void __exit exit_exfat_fs(void)
module_init(init_exfat_fs);
module_exit(exit_exfat_fs);
+MODULE_ALIAS_FS("exfat");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("exFAT filesystem support");
MODULE_AUTHOR("Samsung Electronics Co., Ltd.");
--
2.26.0
@@ -0,0 +1,860 @@
From 370e812b3ec190fa492c9fd5a80c38b086d105c0 Mon Sep 17 00:00:00 2001
From: Namjae Jeon <namjae.jeon@samsung.com>
Date: Mon, 2 Mar 2020 15:21:41 +0900
Subject: [PATCH 10/14] exfat: add nls operations
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This adds the implementation of nls operations for exfat.
Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com>
Signed-off-by: Sungjong Seo <sj1557.seo@samsung.com>
Reviewed-by: Pali Rohár <pali.rohar@gmail.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/exfat/nls.c | 831 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 831 insertions(+)
create mode 100644 fs/exfat/nls.c
diff --git a/fs/exfat/nls.c b/fs/exfat/nls.c
new file mode 100644
index 000000000000..6d1c3ae130ff
--- /dev/null
+++ b/fs/exfat/nls.c
@@ -0,0 +1,831 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
+ */
+
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/buffer_head.h>
+#include <asm/unaligned.h>
+
+#include "exfat_raw.h"
+#include "exfat_fs.h"
+
+/* Upcase tabel macro */
+#define EXFAT_NUM_UPCASE (2918)
+#define UTBL_COUNT (0x10000)
+
+/*
+ * Upcase table in compressed format (7.2.5.1 Recommended Up-case Table
+ * in exfat specification, See:
+ * https://docs.microsoft.com/en-us/windows/win32/fileio/exfat-specification).
+ */
+static const unsigned short uni_def_upcase[EXFAT_NUM_UPCASE] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
+ 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
+ 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
+ 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
+ 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
+ 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
+ 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
+ 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
+ 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
+ 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
+ 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
+ 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00f7,
+ 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x0178,
+ 0x0100, 0x0100, 0x0102, 0x0102, 0x0104, 0x0104, 0x0106, 0x0106,
+ 0x0108, 0x0108, 0x010a, 0x010a, 0x010c, 0x010c, 0x010e, 0x010e,
+ 0x0110, 0x0110, 0x0112, 0x0112, 0x0114, 0x0114, 0x0116, 0x0116,
+ 0x0118, 0x0118, 0x011a, 0x011a, 0x011c, 0x011c, 0x011e, 0x011e,
+ 0x0120, 0x0120, 0x0122, 0x0122, 0x0124, 0x0124, 0x0126, 0x0126,
+ 0x0128, 0x0128, 0x012a, 0x012a, 0x012c, 0x012c, 0x012e, 0x012e,
+ 0x0130, 0x0131, 0x0132, 0x0132, 0x0134, 0x0134, 0x0136, 0x0136,
+ 0x0138, 0x0139, 0x0139, 0x013b, 0x013b, 0x013d, 0x013d, 0x013f,
+ 0x013f, 0x0141, 0x0141, 0x0143, 0x0143, 0x0145, 0x0145, 0x0147,
+ 0x0147, 0x0149, 0x014a, 0x014a, 0x014c, 0x014c, 0x014e, 0x014e,
+ 0x0150, 0x0150, 0x0152, 0x0152, 0x0154, 0x0154, 0x0156, 0x0156,
+ 0x0158, 0x0158, 0x015a, 0x015a, 0x015c, 0x015c, 0x015e, 0x015e,
+ 0x0160, 0x0160, 0x0162, 0x0162, 0x0164, 0x0164, 0x0166, 0x0166,
+ 0x0168, 0x0168, 0x016a, 0x016a, 0x016c, 0x016c, 0x016e, 0x016e,
+ 0x0170, 0x0170, 0x0172, 0x0172, 0x0174, 0x0174, 0x0176, 0x0176,
+ 0x0178, 0x0179, 0x0179, 0x017b, 0x017b, 0x017d, 0x017d, 0x017f,
+ 0x0243, 0x0181, 0x0182, 0x0182, 0x0184, 0x0184, 0x0186, 0x0187,
+ 0x0187, 0x0189, 0x018a, 0x018b, 0x018b, 0x018d, 0x018e, 0x018f,
+ 0x0190, 0x0191, 0x0191, 0x0193, 0x0194, 0x01f6, 0x0196, 0x0197,
+ 0x0198, 0x0198, 0x023d, 0x019b, 0x019c, 0x019d, 0x0220, 0x019f,
+ 0x01a0, 0x01a0, 0x01a2, 0x01a2, 0x01a4, 0x01a4, 0x01a6, 0x01a7,
+ 0x01a7, 0x01a9, 0x01aa, 0x01ab, 0x01ac, 0x01ac, 0x01ae, 0x01af,
+ 0x01af, 0x01b1, 0x01b2, 0x01b3, 0x01b3, 0x01b5, 0x01b5, 0x01b7,
+ 0x01b8, 0x01b8, 0x01ba, 0x01bb, 0x01bc, 0x01bc, 0x01be, 0x01f7,
+ 0x01c0, 0x01c1, 0x01c2, 0x01c3, 0x01c4, 0x01c5, 0x01c4, 0x01c7,
+ 0x01c8, 0x01c7, 0x01ca, 0x01cb, 0x01ca, 0x01cd, 0x01cd, 0x01cf,
+ 0x01cf, 0x01d1, 0x01d1, 0x01d3, 0x01d3, 0x01d5, 0x01d5, 0x01d7,
+ 0x01d7, 0x01d9, 0x01d9, 0x01db, 0x01db, 0x018e, 0x01de, 0x01de,
+ 0x01e0, 0x01e0, 0x01e2, 0x01e2, 0x01e4, 0x01e4, 0x01e6, 0x01e6,
+ 0x01e8, 0x01e8, 0x01ea, 0x01ea, 0x01ec, 0x01ec, 0x01ee, 0x01ee,
+ 0x01f0, 0x01f1, 0x01f2, 0x01f1, 0x01f4, 0x01f4, 0x01f6, 0x01f7,
+ 0x01f8, 0x01f8, 0x01fa, 0x01fa, 0x01fc, 0x01fc, 0x01fe, 0x01fe,
+ 0x0200, 0x0200, 0x0202, 0x0202, 0x0204, 0x0204, 0x0206, 0x0206,
+ 0x0208, 0x0208, 0x020a, 0x020a, 0x020c, 0x020c, 0x020e, 0x020e,
+ 0x0210, 0x0210, 0x0212, 0x0212, 0x0214, 0x0214, 0x0216, 0x0216,
+ 0x0218, 0x0218, 0x021a, 0x021a, 0x021c, 0x021c, 0x021e, 0x021e,
+ 0x0220, 0x0221, 0x0222, 0x0222, 0x0224, 0x0224, 0x0226, 0x0226,
+ 0x0228, 0x0228, 0x022a, 0x022a, 0x022c, 0x022c, 0x022e, 0x022e,
+ 0x0230, 0x0230, 0x0232, 0x0232, 0x0234, 0x0235, 0x0236, 0x0237,
+ 0x0238, 0x0239, 0x2c65, 0x023b, 0x023b, 0x023d, 0x2c66, 0x023f,
+ 0x0240, 0x0241, 0x0241, 0x0243, 0x0244, 0x0245, 0x0246, 0x0246,
+ 0x0248, 0x0248, 0x024a, 0x024a, 0x024c, 0x024c, 0x024e, 0x024e,
+ 0x0250, 0x0251, 0x0252, 0x0181, 0x0186, 0x0255, 0x0189, 0x018a,
+ 0x0258, 0x018f, 0x025a, 0x0190, 0x025c, 0x025d, 0x025e, 0x025f,
+ 0x0193, 0x0261, 0x0262, 0x0194, 0x0264, 0x0265, 0x0266, 0x0267,
+ 0x0197, 0x0196, 0x026a, 0x2c62, 0x026c, 0x026d, 0x026e, 0x019c,
+ 0x0270, 0x0271, 0x019d, 0x0273, 0x0274, 0x019f, 0x0276, 0x0277,
+ 0x0278, 0x0279, 0x027a, 0x027b, 0x027c, 0x2c64, 0x027e, 0x027f,
+ 0x01a6, 0x0281, 0x0282, 0x01a9, 0x0284, 0x0285, 0x0286, 0x0287,
+ 0x01ae, 0x0244, 0x01b1, 0x01b2, 0x0245, 0x028d, 0x028e, 0x028f,
+ 0x0290, 0x0291, 0x01b7, 0x0293, 0x0294, 0x0295, 0x0296, 0x0297,
+ 0x0298, 0x0299, 0x029a, 0x029b, 0x029c, 0x029d, 0x029e, 0x029f,
+ 0x02a0, 0x02a1, 0x02a2, 0x02a3, 0x02a4, 0x02a5, 0x02a6, 0x02a7,
+ 0x02a8, 0x02a9, 0x02aa, 0x02ab, 0x02ac, 0x02ad, 0x02ae, 0x02af,
+ 0x02b0, 0x02b1, 0x02b2, 0x02b3, 0x02b4, 0x02b5, 0x02b6, 0x02b7,
+ 0x02b8, 0x02b9, 0x02ba, 0x02bb, 0x02bc, 0x02bd, 0x02be, 0x02bf,
+ 0x02c0, 0x02c1, 0x02c2, 0x02c3, 0x02c4, 0x02c5, 0x02c6, 0x02c7,
+ 0x02c8, 0x02c9, 0x02ca, 0x02cb, 0x02cc, 0x02cd, 0x02ce, 0x02cf,
+ 0x02d0, 0x02d1, 0x02d2, 0x02d3, 0x02d4, 0x02d5, 0x02d6, 0x02d7,
+ 0x02d8, 0x02d9, 0x02da, 0x02db, 0x02dc, 0x02dd, 0x02de, 0x02df,
+ 0x02e0, 0x02e1, 0x02e2, 0x02e3, 0x02e4, 0x02e5, 0x02e6, 0x02e7,
+ 0x02e8, 0x02e9, 0x02ea, 0x02eb, 0x02ec, 0x02ed, 0x02ee, 0x02ef,
+ 0x02f0, 0x02f1, 0x02f2, 0x02f3, 0x02f4, 0x02f5, 0x02f6, 0x02f7,
+ 0x02f8, 0x02f9, 0x02fa, 0x02fb, 0x02fc, 0x02fd, 0x02fe, 0x02ff,
+ 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307,
+ 0x0308, 0x0309, 0x030a, 0x030b, 0x030c, 0x030d, 0x030e, 0x030f,
+ 0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317,
+ 0x0318, 0x0319, 0x031a, 0x031b, 0x031c, 0x031d, 0x031e, 0x031f,
+ 0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 0x0327,
+ 0x0328, 0x0329, 0x032a, 0x032b, 0x032c, 0x032d, 0x032e, 0x032f,
+ 0x0330, 0x0331, 0x0332, 0x0333, 0x0334, 0x0335, 0x0336, 0x0337,
+ 0x0338, 0x0339, 0x033a, 0x033b, 0x033c, 0x033d, 0x033e, 0x033f,
+ 0x0340, 0x0341, 0x0342, 0x0343, 0x0344, 0x0345, 0x0346, 0x0347,
+ 0x0348, 0x0349, 0x034a, 0x034b, 0x034c, 0x034d, 0x034e, 0x034f,
+ 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, 0x0355, 0x0356, 0x0357,
+ 0x0358, 0x0359, 0x035a, 0x035b, 0x035c, 0x035d, 0x035e, 0x035f,
+ 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367,
+ 0x0368, 0x0369, 0x036a, 0x036b, 0x036c, 0x036d, 0x036e, 0x036f,
+ 0x0370, 0x0371, 0x0372, 0x0373, 0x0374, 0x0375, 0x0376, 0x0377,
+ 0x0378, 0x0379, 0x037a, 0x03fd, 0x03fe, 0x03ff, 0x037e, 0x037f,
+ 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0386, 0x0387,
+ 0x0388, 0x0389, 0x038a, 0x038b, 0x038c, 0x038d, 0x038e, 0x038f,
+ 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
+ 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f,
+ 0x03a0, 0x03a1, 0x03a2, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7,
+ 0x03a8, 0x03a9, 0x03aa, 0x03ab, 0x0386, 0x0388, 0x0389, 0x038a,
+ 0x03b0, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
+ 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f,
+ 0x03a0, 0x03a1, 0x03a3, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7,
+ 0x03a8, 0x03a9, 0x03aa, 0x03ab, 0x038c, 0x038e, 0x038f, 0x03cf,
+ 0x03d0, 0x03d1, 0x03d2, 0x03d3, 0x03d4, 0x03d5, 0x03d6, 0x03d7,
+ 0x03d8, 0x03d8, 0x03da, 0x03da, 0x03dc, 0x03dc, 0x03de, 0x03de,
+ 0x03e0, 0x03e0, 0x03e2, 0x03e2, 0x03e4, 0x03e4, 0x03e6, 0x03e6,
+ 0x03e8, 0x03e8, 0x03ea, 0x03ea, 0x03ec, 0x03ec, 0x03ee, 0x03ee,
+ 0x03f0, 0x03f1, 0x03f9, 0x03f3, 0x03f4, 0x03f5, 0x03f6, 0x03f7,
+ 0x03f7, 0x03f9, 0x03fa, 0x03fa, 0x03fc, 0x03fd, 0x03fe, 0x03ff,
+ 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407,
+ 0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x040d, 0x040e, 0x040f,
+ 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
+ 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f,
+ 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
+ 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f,
+ 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
+ 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f,
+ 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
+ 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f,
+ 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407,
+ 0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x040d, 0x040e, 0x040f,
+ 0x0460, 0x0460, 0x0462, 0x0462, 0x0464, 0x0464, 0x0466, 0x0466,
+ 0x0468, 0x0468, 0x046a, 0x046a, 0x046c, 0x046c, 0x046e, 0x046e,
+ 0x0470, 0x0470, 0x0472, 0x0472, 0x0474, 0x0474, 0x0476, 0x0476,
+ 0x0478, 0x0478, 0x047a, 0x047a, 0x047c, 0x047c, 0x047e, 0x047e,
+ 0x0480, 0x0480, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487,
+ 0x0488, 0x0489, 0x048a, 0x048a, 0x048c, 0x048c, 0x048e, 0x048e,
+ 0x0490, 0x0490, 0x0492, 0x0492, 0x0494, 0x0494, 0x0496, 0x0496,
+ 0x0498, 0x0498, 0x049a, 0x049a, 0x049c, 0x049c, 0x049e, 0x049e,
+ 0x04a0, 0x04a0, 0x04a2, 0x04a2, 0x04a4, 0x04a4, 0x04a6, 0x04a6,
+ 0x04a8, 0x04a8, 0x04aa, 0x04aa, 0x04ac, 0x04ac, 0x04ae, 0x04ae,
+ 0x04b0, 0x04b0, 0x04b2, 0x04b2, 0x04b4, 0x04b4, 0x04b6, 0x04b6,
+ 0x04b8, 0x04b8, 0x04ba, 0x04ba, 0x04bc, 0x04bc, 0x04be, 0x04be,
+ 0x04c0, 0x04c1, 0x04c1, 0x04c3, 0x04c3, 0x04c5, 0x04c5, 0x04c7,
+ 0x04c7, 0x04c9, 0x04c9, 0x04cb, 0x04cb, 0x04cd, 0x04cd, 0x04c0,
+ 0x04d0, 0x04d0, 0x04d2, 0x04d2, 0x04d4, 0x04d4, 0x04d6, 0x04d6,
+ 0x04d8, 0x04d8, 0x04da, 0x04da, 0x04dc, 0x04dc, 0x04de, 0x04de,
+ 0x04e0, 0x04e0, 0x04e2, 0x04e2, 0x04e4, 0x04e4, 0x04e6, 0x04e6,
+ 0x04e8, 0x04e8, 0x04ea, 0x04ea, 0x04ec, 0x04ec, 0x04ee, 0x04ee,
+ 0x04f0, 0x04f0, 0x04f2, 0x04f2, 0x04f4, 0x04f4, 0x04f6, 0x04f6,
+ 0x04f8, 0x04f8, 0x04fa, 0x04fa, 0x04fc, 0x04fc, 0x04fe, 0x04fe,
+ 0x0500, 0x0500, 0x0502, 0x0502, 0x0504, 0x0504, 0x0506, 0x0506,
+ 0x0508, 0x0508, 0x050a, 0x050a, 0x050c, 0x050c, 0x050e, 0x050e,
+ 0x0510, 0x0510, 0x0512, 0x0512, 0x0514, 0x0515, 0x0516, 0x0517,
+ 0x0518, 0x0519, 0x051a, 0x051b, 0x051c, 0x051d, 0x051e, 0x051f,
+ 0x0520, 0x0521, 0x0522, 0x0523, 0x0524, 0x0525, 0x0526, 0x0527,
+ 0x0528, 0x0529, 0x052a, 0x052b, 0x052c, 0x052d, 0x052e, 0x052f,
+ 0x0530, 0x0531, 0x0532, 0x0533, 0x0534, 0x0535, 0x0536, 0x0537,
+ 0x0538, 0x0539, 0x053a, 0x053b, 0x053c, 0x053d, 0x053e, 0x053f,
+ 0x0540, 0x0541, 0x0542, 0x0543, 0x0544, 0x0545, 0x0546, 0x0547,
+ 0x0548, 0x0549, 0x054a, 0x054b, 0x054c, 0x054d, 0x054e, 0x054f,
+ 0x0550, 0x0551, 0x0552, 0x0553, 0x0554, 0x0555, 0x0556, 0x0557,
+ 0x0558, 0x0559, 0x055a, 0x055b, 0x055c, 0x055d, 0x055e, 0x055f,
+ 0x0560, 0x0531, 0x0532, 0x0533, 0x0534, 0x0535, 0x0536, 0x0537,
+ 0x0538, 0x0539, 0x053a, 0x053b, 0x053c, 0x053d, 0x053e, 0x053f,
+ 0x0540, 0x0541, 0x0542, 0x0543, 0x0544, 0x0545, 0x0546, 0x0547,
+ 0x0548, 0x0549, 0x054a, 0x054b, 0x054c, 0x054d, 0x054e, 0x054f,
+ 0x0550, 0x0551, 0x0552, 0x0553, 0x0554, 0x0555, 0x0556, 0xffff,
+ 0x17f6, 0x2c63, 0x1d7e, 0x1d7f, 0x1d80, 0x1d81, 0x1d82, 0x1d83,
+ 0x1d84, 0x1d85, 0x1d86, 0x1d87, 0x1d88, 0x1d89, 0x1d8a, 0x1d8b,
+ 0x1d8c, 0x1d8d, 0x1d8e, 0x1d8f, 0x1d90, 0x1d91, 0x1d92, 0x1d93,
+ 0x1d94, 0x1d95, 0x1d96, 0x1d97, 0x1d98, 0x1d99, 0x1d9a, 0x1d9b,
+ 0x1d9c, 0x1d9d, 0x1d9e, 0x1d9f, 0x1da0, 0x1da1, 0x1da2, 0x1da3,
+ 0x1da4, 0x1da5, 0x1da6, 0x1da7, 0x1da8, 0x1da9, 0x1daa, 0x1dab,
+ 0x1dac, 0x1dad, 0x1dae, 0x1daf, 0x1db0, 0x1db1, 0x1db2, 0x1db3,
+ 0x1db4, 0x1db5, 0x1db6, 0x1db7, 0x1db8, 0x1db9, 0x1dba, 0x1dbb,
+ 0x1dbc, 0x1dbd, 0x1dbe, 0x1dbf, 0x1dc0, 0x1dc1, 0x1dc2, 0x1dc3,
+ 0x1dc4, 0x1dc5, 0x1dc6, 0x1dc7, 0x1dc8, 0x1dc9, 0x1dca, 0x1dcb,
+ 0x1dcc, 0x1dcd, 0x1dce, 0x1dcf, 0x1dd0, 0x1dd1, 0x1dd2, 0x1dd3,
+ 0x1dd4, 0x1dd5, 0x1dd6, 0x1dd7, 0x1dd8, 0x1dd9, 0x1dda, 0x1ddb,
+ 0x1ddc, 0x1ddd, 0x1dde, 0x1ddf, 0x1de0, 0x1de1, 0x1de2, 0x1de3,
+ 0x1de4, 0x1de5, 0x1de6, 0x1de7, 0x1de8, 0x1de9, 0x1dea, 0x1deb,
+ 0x1dec, 0x1ded, 0x1dee, 0x1def, 0x1df0, 0x1df1, 0x1df2, 0x1df3,
+ 0x1df4, 0x1df5, 0x1df6, 0x1df7, 0x1df8, 0x1df9, 0x1dfa, 0x1dfb,
+ 0x1dfc, 0x1dfd, 0x1dfe, 0x1dff, 0x1e00, 0x1e00, 0x1e02, 0x1e02,
+ 0x1e04, 0x1e04, 0x1e06, 0x1e06, 0x1e08, 0x1e08, 0x1e0a, 0x1e0a,
+ 0x1e0c, 0x1e0c, 0x1e0e, 0x1e0e, 0x1e10, 0x1e10, 0x1e12, 0x1e12,
+ 0x1e14, 0x1e14, 0x1e16, 0x1e16, 0x1e18, 0x1e18, 0x1e1a, 0x1e1a,
+ 0x1e1c, 0x1e1c, 0x1e1e, 0x1e1e, 0x1e20, 0x1e20, 0x1e22, 0x1e22,
+ 0x1e24, 0x1e24, 0x1e26, 0x1e26, 0x1e28, 0x1e28, 0x1e2a, 0x1e2a,
+ 0x1e2c, 0x1e2c, 0x1e2e, 0x1e2e, 0x1e30, 0x1e30, 0x1e32, 0x1e32,
+ 0x1e34, 0x1e34, 0x1e36, 0x1e36, 0x1e38, 0x1e38, 0x1e3a, 0x1e3a,
+ 0x1e3c, 0x1e3c, 0x1e3e, 0x1e3e, 0x1e40, 0x1e40, 0x1e42, 0x1e42,
+ 0x1e44, 0x1e44, 0x1e46, 0x1e46, 0x1e48, 0x1e48, 0x1e4a, 0x1e4a,
+ 0x1e4c, 0x1e4c, 0x1e4e, 0x1e4e, 0x1e50, 0x1e50, 0x1e52, 0x1e52,
+ 0x1e54, 0x1e54, 0x1e56, 0x1e56, 0x1e58, 0x1e58, 0x1e5a, 0x1e5a,
+ 0x1e5c, 0x1e5c, 0x1e5e, 0x1e5e, 0x1e60, 0x1e60, 0x1e62, 0x1e62,
+ 0x1e64, 0x1e64, 0x1e66, 0x1e66, 0x1e68, 0x1e68, 0x1e6a, 0x1e6a,
+ 0x1e6c, 0x1e6c, 0x1e6e, 0x1e6e, 0x1e70, 0x1e70, 0x1e72, 0x1e72,
+ 0x1e74, 0x1e74, 0x1e76, 0x1e76, 0x1e78, 0x1e78, 0x1e7a, 0x1e7a,
+ 0x1e7c, 0x1e7c, 0x1e7e, 0x1e7e, 0x1e80, 0x1e80, 0x1e82, 0x1e82,
+ 0x1e84, 0x1e84, 0x1e86, 0x1e86, 0x1e88, 0x1e88, 0x1e8a, 0x1e8a,
+ 0x1e8c, 0x1e8c, 0x1e8e, 0x1e8e, 0x1e90, 0x1e90, 0x1e92, 0x1e92,
+ 0x1e94, 0x1e94, 0x1e96, 0x1e97, 0x1e98, 0x1e99, 0x1e9a, 0x1e9b,
+ 0x1e9c, 0x1e9d, 0x1e9e, 0x1e9f, 0x1ea0, 0x1ea0, 0x1ea2, 0x1ea2,
+ 0x1ea4, 0x1ea4, 0x1ea6, 0x1ea6, 0x1ea8, 0x1ea8, 0x1eaa, 0x1eaa,
+ 0x1eac, 0x1eac, 0x1eae, 0x1eae, 0x1eb0, 0x1eb0, 0x1eb2, 0x1eb2,
+ 0x1eb4, 0x1eb4, 0x1eb6, 0x1eb6, 0x1eb8, 0x1eb8, 0x1eba, 0x1eba,
+ 0x1ebc, 0x1ebc, 0x1ebe, 0x1ebe, 0x1ec0, 0x1ec0, 0x1ec2, 0x1ec2,
+ 0x1ec4, 0x1ec4, 0x1ec6, 0x1ec6, 0x1ec8, 0x1ec8, 0x1eca, 0x1eca,
+ 0x1ecc, 0x1ecc, 0x1ece, 0x1ece, 0x1ed0, 0x1ed0, 0x1ed2, 0x1ed2,
+ 0x1ed4, 0x1ed4, 0x1ed6, 0x1ed6, 0x1ed8, 0x1ed8, 0x1eda, 0x1eda,
+ 0x1edc, 0x1edc, 0x1ede, 0x1ede, 0x1ee0, 0x1ee0, 0x1ee2, 0x1ee2,
+ 0x1ee4, 0x1ee4, 0x1ee6, 0x1ee6, 0x1ee8, 0x1ee8, 0x1eea, 0x1eea,
+ 0x1eec, 0x1eec, 0x1eee, 0x1eee, 0x1ef0, 0x1ef0, 0x1ef2, 0x1ef2,
+ 0x1ef4, 0x1ef4, 0x1ef6, 0x1ef6, 0x1ef8, 0x1ef8, 0x1efa, 0x1efb,
+ 0x1efc, 0x1efd, 0x1efe, 0x1eff, 0x1f08, 0x1f09, 0x1f0a, 0x1f0b,
+ 0x1f0c, 0x1f0d, 0x1f0e, 0x1f0f, 0x1f08, 0x1f09, 0x1f0a, 0x1f0b,
+ 0x1f0c, 0x1f0d, 0x1f0e, 0x1f0f, 0x1f18, 0x1f19, 0x1f1a, 0x1f1b,
+ 0x1f1c, 0x1f1d, 0x1f16, 0x1f17, 0x1f18, 0x1f19, 0x1f1a, 0x1f1b,
+ 0x1f1c, 0x1f1d, 0x1f1e, 0x1f1f, 0x1f28, 0x1f29, 0x1f2a, 0x1f2b,
+ 0x1f2c, 0x1f2d, 0x1f2e, 0x1f2f, 0x1f28, 0x1f29, 0x1f2a, 0x1f2b,
+ 0x1f2c, 0x1f2d, 0x1f2e, 0x1f2f, 0x1f38, 0x1f39, 0x1f3a, 0x1f3b,
+ 0x1f3c, 0x1f3d, 0x1f3e, 0x1f3f, 0x1f38, 0x1f39, 0x1f3a, 0x1f3b,
+ 0x1f3c, 0x1f3d, 0x1f3e, 0x1f3f, 0x1f48, 0x1f49, 0x1f4a, 0x1f4b,
+ 0x1f4c, 0x1f4d, 0x1f46, 0x1f47, 0x1f48, 0x1f49, 0x1f4a, 0x1f4b,
+ 0x1f4c, 0x1f4d, 0x1f4e, 0x1f4f, 0x1f50, 0x1f59, 0x1f52, 0x1f5b,
+ 0x1f54, 0x1f5d, 0x1f56, 0x1f5f, 0x1f58, 0x1f59, 0x1f5a, 0x1f5b,
+ 0x1f5c, 0x1f5d, 0x1f5e, 0x1f5f, 0x1f68, 0x1f69, 0x1f6a, 0x1f6b,
+ 0x1f6c, 0x1f6d, 0x1f6e, 0x1f6f, 0x1f68, 0x1f69, 0x1f6a, 0x1f6b,
+ 0x1f6c, 0x1f6d, 0x1f6e, 0x1f6f, 0x1fba, 0x1fbb, 0x1fc8, 0x1fc9,
+ 0x1fca, 0x1fcb, 0x1fda, 0x1fdb, 0x1ff8, 0x1ff9, 0x1fea, 0x1feb,
+ 0x1ffa, 0x1ffb, 0x1f7e, 0x1f7f, 0x1f88, 0x1f89, 0x1f8a, 0x1f8b,
+ 0x1f8c, 0x1f8d, 0x1f8e, 0x1f8f, 0x1f88, 0x1f89, 0x1f8a, 0x1f8b,
+ 0x1f8c, 0x1f8d, 0x1f8e, 0x1f8f, 0x1f98, 0x1f99, 0x1f9a, 0x1f9b,
+ 0x1f9c, 0x1f9d, 0x1f9e, 0x1f9f, 0x1f98, 0x1f99, 0x1f9a, 0x1f9b,
+ 0x1f9c, 0x1f9d, 0x1f9e, 0x1f9f, 0x1fa8, 0x1fa9, 0x1faa, 0x1fab,
+ 0x1fac, 0x1fad, 0x1fae, 0x1faf, 0x1fa8, 0x1fa9, 0x1faa, 0x1fab,
+ 0x1fac, 0x1fad, 0x1fae, 0x1faf, 0x1fb8, 0x1fb9, 0x1fb2, 0x1fbc,
+ 0x1fb4, 0x1fb5, 0x1fb6, 0x1fb7, 0x1fb8, 0x1fb9, 0x1fba, 0x1fbb,
+ 0x1fbc, 0x1fbd, 0x1fbe, 0x1fbf, 0x1fc0, 0x1fc1, 0x1fc2, 0x1fc3,
+ 0x1fc4, 0x1fc5, 0x1fc6, 0x1fc7, 0x1fc8, 0x1fc9, 0x1fca, 0x1fcb,
+ 0x1fc3, 0x1fcd, 0x1fce, 0x1fcf, 0x1fd8, 0x1fd9, 0x1fd2, 0x1fd3,
+ 0x1fd4, 0x1fd5, 0x1fd6, 0x1fd7, 0x1fd8, 0x1fd9, 0x1fda, 0x1fdb,
+ 0x1fdc, 0x1fdd, 0x1fde, 0x1fdf, 0x1fe8, 0x1fe9, 0x1fe2, 0x1fe3,
+ 0x1fe4, 0x1fec, 0x1fe6, 0x1fe7, 0x1fe8, 0x1fe9, 0x1fea, 0x1feb,
+ 0x1fec, 0x1fed, 0x1fee, 0x1fef, 0x1ff0, 0x1ff1, 0x1ff2, 0x1ff3,
+ 0x1ff4, 0x1ff5, 0x1ff6, 0x1ff7, 0x1ff8, 0x1ff9, 0x1ffa, 0x1ffb,
+ 0x1ff3, 0x1ffd, 0x1ffe, 0x1fff, 0x2000, 0x2001, 0x2002, 0x2003,
+ 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200a, 0x200b,
+ 0x200c, 0x200d, 0x200e, 0x200f, 0x2010, 0x2011, 0x2012, 0x2013,
+ 0x2014, 0x2015, 0x2016, 0x2017, 0x2018, 0x2019, 0x201a, 0x201b,
+ 0x201c, 0x201d, 0x201e, 0x201f, 0x2020, 0x2021, 0x2022, 0x2023,
+ 0x2024, 0x2025, 0x2026, 0x2027, 0x2028, 0x2029, 0x202a, 0x202b,
+ 0x202c, 0x202d, 0x202e, 0x202f, 0x2030, 0x2031, 0x2032, 0x2033,
+ 0x2034, 0x2035, 0x2036, 0x2037, 0x2038, 0x2039, 0x203a, 0x203b,
+ 0x203c, 0x203d, 0x203e, 0x203f, 0x2040, 0x2041, 0x2042, 0x2043,
+ 0x2044, 0x2045, 0x2046, 0x2047, 0x2048, 0x2049, 0x204a, 0x204b,
+ 0x204c, 0x204d, 0x204e, 0x204f, 0x2050, 0x2051, 0x2052, 0x2053,
+ 0x2054, 0x2055, 0x2056, 0x2057, 0x2058, 0x2059, 0x205a, 0x205b,
+ 0x205c, 0x205d, 0x205e, 0x205f, 0x2060, 0x2061, 0x2062, 0x2063,
+ 0x2064, 0x2065, 0x2066, 0x2067, 0x2068, 0x2069, 0x206a, 0x206b,
+ 0x206c, 0x206d, 0x206e, 0x206f, 0x2070, 0x2071, 0x2072, 0x2073,
+ 0x2074, 0x2075, 0x2076, 0x2077, 0x2078, 0x2079, 0x207a, 0x207b,
+ 0x207c, 0x207d, 0x207e, 0x207f, 0x2080, 0x2081, 0x2082, 0x2083,
+ 0x2084, 0x2085, 0x2086, 0x2087, 0x2088, 0x2089, 0x208a, 0x208b,
+ 0x208c, 0x208d, 0x208e, 0x208f, 0x2090, 0x2091, 0x2092, 0x2093,
+ 0x2094, 0x2095, 0x2096, 0x2097, 0x2098, 0x2099, 0x209a, 0x209b,
+ 0x209c, 0x209d, 0x209e, 0x209f, 0x20a0, 0x20a1, 0x20a2, 0x20a3,
+ 0x20a4, 0x20a5, 0x20a6, 0x20a7, 0x20a8, 0x20a9, 0x20aa, 0x20ab,
+ 0x20ac, 0x20ad, 0x20ae, 0x20af, 0x20b0, 0x20b1, 0x20b2, 0x20b3,
+ 0x20b4, 0x20b5, 0x20b6, 0x20b7, 0x20b8, 0x20b9, 0x20ba, 0x20bb,
+ 0x20bc, 0x20bd, 0x20be, 0x20bf, 0x20c0, 0x20c1, 0x20c2, 0x20c3,
+ 0x20c4, 0x20c5, 0x20c6, 0x20c7, 0x20c8, 0x20c9, 0x20ca, 0x20cb,
+ 0x20cc, 0x20cd, 0x20ce, 0x20cf, 0x20d0, 0x20d1, 0x20d2, 0x20d3,
+ 0x20d4, 0x20d5, 0x20d6, 0x20d7, 0x20d8, 0x20d9, 0x20da, 0x20db,
+ 0x20dc, 0x20dd, 0x20de, 0x20df, 0x20e0, 0x20e1, 0x20e2, 0x20e3,
+ 0x20e4, 0x20e5, 0x20e6, 0x20e7, 0x20e8, 0x20e9, 0x20ea, 0x20eb,
+ 0x20ec, 0x20ed, 0x20ee, 0x20ef, 0x20f0, 0x20f1, 0x20f2, 0x20f3,
+ 0x20f4, 0x20f5, 0x20f6, 0x20f7, 0x20f8, 0x20f9, 0x20fa, 0x20fb,
+ 0x20fc, 0x20fd, 0x20fe, 0x20ff, 0x2100, 0x2101, 0x2102, 0x2103,
+ 0x2104, 0x2105, 0x2106, 0x2107, 0x2108, 0x2109, 0x210a, 0x210b,
+ 0x210c, 0x210d, 0x210e, 0x210f, 0x2110, 0x2111, 0x2112, 0x2113,
+ 0x2114, 0x2115, 0x2116, 0x2117, 0x2118, 0x2119, 0x211a, 0x211b,
+ 0x211c, 0x211d, 0x211e, 0x211f, 0x2120, 0x2121, 0x2122, 0x2123,
+ 0x2124, 0x2125, 0x2126, 0x2127, 0x2128, 0x2129, 0x212a, 0x212b,
+ 0x212c, 0x212d, 0x212e, 0x212f, 0x2130, 0x2131, 0x2132, 0x2133,
+ 0x2134, 0x2135, 0x2136, 0x2137, 0x2138, 0x2139, 0x213a, 0x213b,
+ 0x213c, 0x213d, 0x213e, 0x213f, 0x2140, 0x2141, 0x2142, 0x2143,
+ 0x2144, 0x2145, 0x2146, 0x2147, 0x2148, 0x2149, 0x214a, 0x214b,
+ 0x214c, 0x214d, 0x2132, 0x214f, 0x2150, 0x2151, 0x2152, 0x2153,
+ 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159, 0x215a, 0x215b,
+ 0x215c, 0x215d, 0x215e, 0x215f, 0x2160, 0x2161, 0x2162, 0x2163,
+ 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216a, 0x216b,
+ 0x216c, 0x216d, 0x216e, 0x216f, 0x2160, 0x2161, 0x2162, 0x2163,
+ 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216a, 0x216b,
+ 0x216c, 0x216d, 0x216e, 0x216f, 0x2180, 0x2181, 0x2182, 0x2183,
+ 0x2183, 0xffff, 0x034b, 0x24b6, 0x24b7, 0x24b8, 0x24b9, 0x24ba,
+ 0x24bb, 0x24bc, 0x24bd, 0x24be, 0x24bf, 0x24c0, 0x24c1, 0x24c2,
+ 0x24c3, 0x24c4, 0x24c5, 0x24c6, 0x24c7, 0x24c8, 0x24c9, 0x24ca,
+ 0x24cb, 0x24cc, 0x24cd, 0x24ce, 0x24cf, 0xffff, 0x0746, 0x2c00,
+ 0x2c01, 0x2c02, 0x2c03, 0x2c04, 0x2c05, 0x2c06, 0x2c07, 0x2c08,
+ 0x2c09, 0x2c0a, 0x2c0b, 0x2c0c, 0x2c0d, 0x2c0e, 0x2c0f, 0x2c10,
+ 0x2c11, 0x2c12, 0x2c13, 0x2c14, 0x2c15, 0x2c16, 0x2c17, 0x2c18,
+ 0x2c19, 0x2c1a, 0x2c1b, 0x2c1c, 0x2c1d, 0x2c1e, 0x2c1f, 0x2c20,
+ 0x2c21, 0x2c22, 0x2c23, 0x2c24, 0x2c25, 0x2c26, 0x2c27, 0x2c28,
+ 0x2c29, 0x2c2a, 0x2c2b, 0x2c2c, 0x2c2d, 0x2c2e, 0x2c5f, 0x2c60,
+ 0x2c60, 0x2c62, 0x2c63, 0x2c64, 0x2c65, 0x2c66, 0x2c67, 0x2c67,
+ 0x2c69, 0x2c69, 0x2c6b, 0x2c6b, 0x2c6d, 0x2c6e, 0x2c6f, 0x2c70,
+ 0x2c71, 0x2c72, 0x2c73, 0x2c74, 0x2c75, 0x2c75, 0x2c77, 0x2c78,
+ 0x2c79, 0x2c7a, 0x2c7b, 0x2c7c, 0x2c7d, 0x2c7e, 0x2c7f, 0x2c80,
+ 0x2c80, 0x2c82, 0x2c82, 0x2c84, 0x2c84, 0x2c86, 0x2c86, 0x2c88,
+ 0x2c88, 0x2c8a, 0x2c8a, 0x2c8c, 0x2c8c, 0x2c8e, 0x2c8e, 0x2c90,
+ 0x2c90, 0x2c92, 0x2c92, 0x2c94, 0x2c94, 0x2c96, 0x2c96, 0x2c98,
+ 0x2c98, 0x2c9a, 0x2c9a, 0x2c9c, 0x2c9c, 0x2c9e, 0x2c9e, 0x2ca0,
+ 0x2ca0, 0x2ca2, 0x2ca2, 0x2ca4, 0x2ca4, 0x2ca6, 0x2ca6, 0x2ca8,
+ 0x2ca8, 0x2caa, 0x2caa, 0x2cac, 0x2cac, 0x2cae, 0x2cae, 0x2cb0,
+ 0x2cb0, 0x2cb2, 0x2cb2, 0x2cb4, 0x2cb4, 0x2cb6, 0x2cb6, 0x2cb8,
+ 0x2cb8, 0x2cba, 0x2cba, 0x2cbc, 0x2cbc, 0x2cbe, 0x2cbe, 0x2cc0,
+ 0x2cc0, 0x2cc2, 0x2cc2, 0x2cc4, 0x2cc4, 0x2cc6, 0x2cc6, 0x2cc8,
+ 0x2cc8, 0x2cca, 0x2cca, 0x2ccc, 0x2ccc, 0x2cce, 0x2cce, 0x2cd0,
+ 0x2cd0, 0x2cd2, 0x2cd2, 0x2cd4, 0x2cd4, 0x2cd6, 0x2cd6, 0x2cd8,
+ 0x2cd8, 0x2cda, 0x2cda, 0x2cdc, 0x2cdc, 0x2cde, 0x2cde, 0x2ce0,
+ 0x2ce0, 0x2ce2, 0x2ce2, 0x2ce4, 0x2ce5, 0x2ce6, 0x2ce7, 0x2ce8,
+ 0x2ce9, 0x2cea, 0x2ceb, 0x2cec, 0x2ced, 0x2cee, 0x2cef, 0x2cf0,
+ 0x2cf1, 0x2cf2, 0x2cf3, 0x2cf4, 0x2cf5, 0x2cf6, 0x2cf7, 0x2cf8,
+ 0x2cf9, 0x2cfa, 0x2cfb, 0x2cfc, 0x2cfd, 0x2cfe, 0x2cff, 0x10a0,
+ 0x10a1, 0x10a2, 0x10a3, 0x10a4, 0x10a5, 0x10a6, 0x10a7, 0x10a8,
+ 0x10a9, 0x10aa, 0x10ab, 0x10ac, 0x10ad, 0x10ae, 0x10af, 0x10b0,
+ 0x10b1, 0x10b2, 0x10b3, 0x10b4, 0x10b5, 0x10b6, 0x10b7, 0x10b8,
+ 0x10b9, 0x10ba, 0x10bb, 0x10bc, 0x10bd, 0x10be, 0x10bf, 0x10c0,
+ 0x10c1, 0x10c2, 0x10c3, 0x10c4, 0x10c5, 0xffff, 0xd21b, 0xff21,
+ 0xff22, 0xff23, 0xff24, 0xff25, 0xff26, 0xff27, 0xff28, 0xff29,
+ 0xff2a, 0xff2b, 0xff2c, 0xff2d, 0xff2e, 0xff2f, 0xff30, 0xff31,
+ 0xff32, 0xff33, 0xff34, 0xff35, 0xff36, 0xff37, 0xff38, 0xff39,
+ 0xff3a, 0xff5b, 0xff5c, 0xff5d, 0xff5e, 0xff5f, 0xff60, 0xff61,
+ 0xff62, 0xff63, 0xff64, 0xff65, 0xff66, 0xff67, 0xff68, 0xff69,
+ 0xff6a, 0xff6b, 0xff6c, 0xff6d, 0xff6e, 0xff6f, 0xff70, 0xff71,
+ 0xff72, 0xff73, 0xff74, 0xff75, 0xff76, 0xff77, 0xff78, 0xff79,
+ 0xff7a, 0xff7b, 0xff7c, 0xff7d, 0xff7e, 0xff7f, 0xff80, 0xff81,
+ 0xff82, 0xff83, 0xff84, 0xff85, 0xff86, 0xff87, 0xff88, 0xff89,
+ 0xff8a, 0xff8b, 0xff8c, 0xff8d, 0xff8e, 0xff8f, 0xff90, 0xff91,
+ 0xff92, 0xff93, 0xff94, 0xff95, 0xff96, 0xff97, 0xff98, 0xff99,
+ 0xff9a, 0xff9b, 0xff9c, 0xff9d, 0xff9e, 0xff9f, 0xffa0, 0xffa1,
+ 0xffa2, 0xffa3, 0xffa4, 0xffa5, 0xffa6, 0xffa7, 0xffa8, 0xffa9,
+ 0xffaa, 0xffab, 0xffac, 0xffad, 0xffae, 0xffaf, 0xffb0, 0xffb1,
+ 0xffb2, 0xffb3, 0xffb4, 0xffb5, 0xffb6, 0xffb7, 0xffb8, 0xffb9,
+ 0xffba, 0xffbb, 0xffbc, 0xffbd, 0xffbe, 0xffbf, 0xffc0, 0xffc1,
+ 0xffc2, 0xffc3, 0xffc4, 0xffc5, 0xffc6, 0xffc7, 0xffc8, 0xffc9,
+ 0xffca, 0xffcb, 0xffcc, 0xffcd, 0xffce, 0xffcf, 0xffd0, 0xffd1,
+ 0xffd2, 0xffd3, 0xffd4, 0xffd5, 0xffd6, 0xffd7, 0xffd8, 0xffd9,
+ 0xffda, 0xffdb, 0xffdc, 0xffdd, 0xffde, 0xffdf, 0xffe0, 0xffe1,
+ 0xffe2, 0xffe3, 0xffe4, 0xffe5, 0xffe6, 0xffe7, 0xffe8, 0xffe9,
+ 0xffea, 0xffeb, 0xffec, 0xffed, 0xffee, 0xffef, 0xfff0, 0xfff1,
+ 0xfff2, 0xfff3, 0xfff4, 0xfff5, 0xfff6, 0xfff7, 0xfff8, 0xfff9,
+ 0xfffa, 0xfffb, 0xfffc, 0xfffd, 0xfffe, 0xffff,
+};
+
+/*
+ * Allow full-width illegal characters :
+ * "MS windows 7" supports full-width-invalid-name-characters.
+ * So we should check half-width-invalid-name-characters(ASCII) only
+ * for compatibility.
+ *
+ * " * / : < > ? \ |
+ */
+static unsigned short bad_uni_chars[] = {
+ 0x0022, 0x002A, 0x002F, 0x003A,
+ 0x003C, 0x003E, 0x003F, 0x005C, 0x007C,
+ 0
+};
+
+static int exfat_convert_char_to_ucs2(struct nls_table *nls,
+ const unsigned char *ch, int ch_len, unsigned short *ucs2,
+ int *lossy)
+{
+ int len;
+
+ *ucs2 = 0x0;
+
+ if (ch[0] < 0x80) {
+ *ucs2 = ch[0];
+ return 1;
+ }
+
+ len = nls->char2uni(ch, ch_len, ucs2);
+ if (len < 0) {
+ /* conversion failed */
+ if (lossy != NULL)
+ *lossy |= NLS_NAME_LOSSY;
+ *ucs2 = '_';
+ return 1;
+ }
+ return len;
+}
+
+static int exfat_convert_ucs2_to_char(struct nls_table *nls,
+ unsigned short ucs2, unsigned char *ch, int *lossy)
+{
+ int len;
+
+ ch[0] = 0x0;
+
+ if (ucs2 < 0x0080) {
+ ch[0] = ucs2;
+ return 1;
+ }
+
+ len = nls->uni2char(ucs2, ch, MAX_CHARSET_SIZE);
+ if (len < 0) {
+ /* conversion failed */
+ if (lossy != NULL)
+ *lossy |= NLS_NAME_LOSSY;
+ ch[0] = '_';
+ return 1;
+ }
+ return len;
+}
+
+unsigned short exfat_toupper(struct super_block *sb, unsigned short a)
+{
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
+
+ return sbi->vol_utbl[a] ? sbi->vol_utbl[a] : a;
+}
+
+static unsigned short *exfat_wstrchr(unsigned short *str, unsigned short wchar)
+{
+ while (*str) {
+ if (*(str++) == wchar)
+ return str;
+ }
+ return NULL;
+}
+
+int exfat_uniname_ncmp(struct super_block *sb, unsigned short *a,
+ unsigned short *b, unsigned int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++, a++, b++)
+ if (exfat_toupper(sb, *a) != exfat_toupper(sb, *b))
+ return 1;
+ return 0;
+}
+
+static int exfat_utf16_to_utf8(struct super_block *sb,
+ struct exfat_uni_name *p_uniname, unsigned char *p_cstring,
+ int buflen)
+{
+ int len;
+ const unsigned short *uniname = p_uniname->name;
+
+ /* always len >= 0 */
+ len = utf16s_to_utf8s(uniname, MAX_NAME_LENGTH, UTF16_HOST_ENDIAN,
+ p_cstring, buflen);
+ p_cstring[len] = '\0';
+ return len;
+}
+
+static int exfat_utf8_to_utf16(struct super_block *sb,
+ const unsigned char *p_cstring, const int len,
+ struct exfat_uni_name *p_uniname, int *p_lossy)
+{
+ int i, unilen, lossy = NLS_NAME_NO_LOSSY;
+ unsigned short upname[MAX_NAME_LENGTH + 1];
+ unsigned short *uniname = p_uniname->name;
+
+ WARN_ON(!len);
+
+ unilen = utf8s_to_utf16s(p_cstring, len, UTF16_HOST_ENDIAN,
+ (wchar_t *)uniname, MAX_NAME_LENGTH + 2);
+ if (unilen < 0) {
+ exfat_msg(sb, KERN_ERR,
+ "failed to %s (err : %d) nls len : %d",
+ __func__, unilen, len);
+ return unilen;
+ }
+
+ if (unilen > MAX_NAME_LENGTH) {
+ exfat_msg(sb, KERN_ERR,
+ "failed to %s (estr:ENAMETOOLONG) nls len : %d, unilen : %d > %d",
+ __func__, len, unilen, MAX_NAME_LENGTH);
+ return -ENAMETOOLONG;
+ }
+
+ p_uniname->name_len = unilen & 0xFF;
+
+ for (i = 0; i < unilen; i++) {
+ if (*uniname < 0x0020 ||
+ exfat_wstrchr(bad_uni_chars, *uniname))
+ lossy |= NLS_NAME_LOSSY;
+
+ upname[i] = exfat_toupper(sb, *uniname);
+ uniname++;
+ }
+
+ *uniname = '\0';
+ p_uniname->name_len = unilen;
+ p_uniname->name_hash = exfat_calc_chksum_2byte(upname, unilen << 1, 0,
+ CS_DEFAULT);
+
+ if (p_lossy)
+ *p_lossy = lossy;
+ return unilen;
+}
+
+#define PLANE_SIZE 0x00010000
+#define SURROGATE_MASK 0xfffff800
+#define SURROGATE_PAIR 0x0000d800
+#define SURROGATE_LOW 0x00000400
+#define SURROGATE_BITS 0x000003ff
+
+unsigned short exfat_high_surrogate(unicode_t u)
+{
+ return ((u - PLANE_SIZE) >> 10) + SURROGATE_PAIR;
+}
+
+unsigned short exfat_low_surrogate(unicode_t u)
+{
+ return ((u - PLANE_SIZE) & SURROGATE_BITS) | SURROGATE_PAIR |
+ SURROGATE_LOW;
+}
+
+static int __exfat_utf16_to_nls(struct super_block *sb,
+ struct exfat_uni_name *p_uniname, unsigned char *p_cstring,
+ int buflen)
+{
+ int i, j, len, out_len = 0;
+ unsigned char buf[MAX_CHARSET_SIZE];
+ const unsigned short *uniname = p_uniname->name;
+ struct nls_table *nls = EXFAT_SB(sb)->nls_io;
+
+ i = 0;
+ while (i < MAX_NAME_LENGTH && out_len < (buflen - 1)) {
+ if (*uniname == '\0')
+ break;
+ if ((*uniname & SURROGATE_MASK) != SURROGATE_PAIR) {
+ len = exfat_convert_ucs2_to_char(nls, *uniname, buf,
+ NULL);
+ } else {
+ /* Process UTF-16 surrogate pair as one character */
+ if (!(*uniname & SURROGATE_LOW) &&
+ i+1 < MAX_NAME_LENGTH &&
+ (*(uniname+1) & SURROGATE_MASK) == SURROGATE_PAIR &&
+ (*(uniname+1) & SURROGATE_LOW)) {
+ uniname++;
+ i++;
+ }
+
+ /*
+ * UTF-16 surrogate pair encodes code points above
+ * U+FFFF. Code points above U+FFFF are not supported
+ * by kernel NLS framework therefore use replacement
+ * character
+ */
+ len = 1;
+ buf[0] = '_';
+ }
+
+ if (out_len + len >= buflen)
+ len = buflen - 1 - out_len;
+ out_len += len;
+
+ if (len > 1) {
+ for (j = 0; j < len; j++)
+ *p_cstring++ = buf[j];
+ } else { /* len == 1 */
+ *p_cstring++ = *buf;
+ }
+
+ uniname++;
+ i++;
+ }
+
+ *p_cstring = '\0';
+ return out_len;
+}
+
+static int exfat_nls_to_ucs2(struct super_block *sb,
+ const unsigned char *p_cstring, const int len,
+ struct exfat_uni_name *p_uniname, int *p_lossy)
+{
+ int i = 0, unilen = 0, lossy = NLS_NAME_NO_LOSSY;
+ unsigned short upname[MAX_NAME_LENGTH + 1];
+ unsigned short *uniname = p_uniname->name;
+ struct nls_table *nls = EXFAT_SB(sb)->nls_io;
+
+ WARN_ON(!len);
+
+ while (unilen < MAX_NAME_LENGTH && i < len) {
+ i += exfat_convert_char_to_ucs2(nls, p_cstring + i, len - i,
+ uniname, &lossy);
+
+ if (*uniname < 0x0020 ||
+ exfat_wstrchr(bad_uni_chars, *uniname))
+ lossy |= NLS_NAME_LOSSY;
+
+ upname[unilen] = exfat_toupper(sb, *uniname);
+ uniname++;
+ unilen++;
+ }
+
+ if (p_cstring[i] != '\0')
+ lossy |= NLS_NAME_OVERLEN;
+
+ *uniname = '\0';
+ p_uniname->name_len = unilen;
+ p_uniname->name_hash = exfat_calc_chksum_2byte(upname, unilen << 1, 0,
+ CS_DEFAULT);
+
+ if (p_lossy)
+ *p_lossy = lossy;
+ return unilen;
+}
+
+int exfat_utf16_to_nls(struct super_block *sb, struct exfat_uni_name *uniname,
+ unsigned char *p_cstring, int buflen)
+{
+ if (EXFAT_SB(sb)->options.utf8)
+ return exfat_utf16_to_utf8(sb, uniname, p_cstring,
+ buflen);
+ return __exfat_utf16_to_nls(sb, uniname, p_cstring, buflen);
+}
+
+int exfat_nls_to_utf16(struct super_block *sb, const unsigned char *p_cstring,
+ const int len, struct exfat_uni_name *uniname, int *p_lossy)
+{
+ if (EXFAT_SB(sb)->options.utf8)
+ return exfat_utf8_to_utf16(sb, p_cstring, len,
+ uniname, p_lossy);
+ return exfat_nls_to_ucs2(sb, p_cstring, len, uniname, p_lossy);
+}
+
+static int exfat_load_upcase_table(struct super_block *sb,
+ sector_t sector, unsigned long long num_sectors,
+ unsigned int utbl_checksum)
+{
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
+ unsigned int sect_size = sb->s_blocksize;
+ unsigned int i, index = 0, checksum = 0;
+ int ret;
+ unsigned char skip = false;
+ unsigned short *upcase_table;
+
+ upcase_table = kcalloc(UTBL_COUNT, sizeof(unsigned short), GFP_KERNEL);
+ if (!upcase_table)
+ return -ENOMEM;
+
+ sbi->vol_utbl = upcase_table;
+ num_sectors += sector;
+
+ while (sector < num_sectors) {
+ struct buffer_head *bh;
+
+ bh = sb_bread(sb, sector);
+ if (!bh) {
+ exfat_msg(sb, KERN_ERR,
+ "failed to read sector(0x%llx)\n",
+ (unsigned long long)sector);
+ ret = -EIO;
+ goto free_table;
+ }
+ sector++;
+ for (i = 0; i < sect_size && index <= 0xFFFF; i += 2) {
+ unsigned short uni = get_unaligned_le16(bh->b_data + i);
+
+ checksum = ((checksum & 1) ? 0x80000000 : 0) +
+ (checksum >> 1) +
+ *(((unsigned char *)bh->b_data) + i);
+ checksum = ((checksum & 1) ? 0x80000000 : 0) +
+ (checksum >> 1) +
+ *(((unsigned char *)bh->b_data) + (i + 1));
+
+ if (skip) {
+ index += uni;
+ skip = false;
+ } else if (uni == index) {
+ index++;
+ } else if (uni == 0xFFFF) {
+ skip = true;
+ } else { /* uni != index , uni != 0xFFFF */
+ upcase_table[index] = uni;
+ index++;
+ }
+ }
+ brelse(bh);
+ }
+
+ if (index >= 0xFFFF && utbl_checksum == checksum)
+ return 0;
+
+ exfat_msg(sb, KERN_ERR,
+ "failed to load upcase table (idx : 0x%08x, chksum : 0x%08x, utbl_chksum : 0x%08x)\n",
+ index, checksum, utbl_checksum);
+ ret = -EINVAL;
+free_table:
+ exfat_free_upcase_table(sbi);
+ return ret;
+}
+
+static int exfat_load_default_upcase_table(struct super_block *sb)
+{
+ int i, ret = -EIO;
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
+ unsigned char skip = false;
+ unsigned short uni = 0, *upcase_table;
+ unsigned int index = 0;
+
+ upcase_table = kcalloc(UTBL_COUNT, sizeof(unsigned short), GFP_KERNEL);
+ if (!upcase_table)
+ return -ENOMEM;
+
+ sbi->vol_utbl = upcase_table;
+
+ for (i = 0; index <= 0xFFFF && i < EXFAT_NUM_UPCASE; i++) {
+ uni = uni_def_upcase[i];
+ if (skip) {
+ index += uni;
+ skip = false;
+ } else if (uni == index) {
+ index++;
+ } else if (uni == 0xFFFF) {
+ skip = true;
+ } else {
+ upcase_table[index] = uni;
+ index++;
+ }
+ }
+
+ if (index >= 0xFFFF)
+ return 0;
+
+ /* FATAL error: default upcase table has error */
+ exfat_free_upcase_table(sbi);
+ return ret;
+}
+
+int exfat_create_upcase_table(struct super_block *sb)
+{
+ int i, ret;
+ unsigned int tbl_clu, type;
+ sector_t sector;
+ unsigned long long tbl_size, num_sectors;
+ unsigned char blksize_bits = sb->s_blocksize_bits;
+ struct exfat_chain clu;
+ struct exfat_dentry *ep;
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
+ struct buffer_head *bh;
+
+ clu.dir = sbi->root_dir;
+ clu.flags = ALLOC_FAT_CHAIN;
+
+ while (clu.dir != EXFAT_EOF_CLUSTER) {
+ for (i = 0; i < sbi->dentries_per_clu; i++) {
+ ep = exfat_get_dentry(sb, &clu, i, &bh, NULL);
+ if (!ep)
+ return -EIO;
+
+ type = exfat_get_entry_type(ep);
+ if (type == TYPE_UNUSED) {
+ brelse(bh);
+ break;
+ }
+
+ if (type != TYPE_UPCASE) {
+ brelse(bh);
+ continue;
+ }
+
+ tbl_clu = le32_to_cpu(ep->dentry.upcase.start_clu);
+ tbl_size = le64_to_cpu(ep->dentry.upcase.size);
+
+ sector = exfat_cluster_to_sector(sbi, tbl_clu);
+ num_sectors = ((tbl_size - 1) >> blksize_bits) + 1;
+ ret = exfat_load_upcase_table(sb, sector, num_sectors,
+ le32_to_cpu(ep->dentry.upcase.checksum));
+
+ brelse(bh);
+ if (ret && ret != -EIO)
+ goto load_default;
+
+ /* load successfully */
+ return ret;
+ }
+
+ if (exfat_get_next_cluster(sb, &(clu.dir)))
+ return -EIO;
+ }
+
+load_default:
+ /* load default upcase table */
+ return exfat_load_default_upcase_table(sb);
+}
+
+void exfat_free_upcase_table(struct exfat_sb_info *sbi)
+{
+ kfree(sbi->vol_utbl);
+}
--
2.25.1
@@ -0,0 +1,758 @@
From 719c1e1829166da399903b13da6dcc5344e73449 Mon Sep 17 00:00:00 2001
From: Namjae Jeon <namjae.jeon@samsung.com>
Date: Mon, 2 Mar 2020 15:21:33 +0900
Subject: [PATCH 02/14] exfat: add super block operations
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This adds the implementation of superblock operations for exfat.
Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com>
Signed-off-by: Sungjong Seo <sj1557.seo@samsung.com>
Reviewed-by: Pali Rohár <pali.rohar@gmail.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/exfat/super.c | 728 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 728 insertions(+)
create mode 100644 fs/exfat/super.c
diff --git a/fs/exfat/super.c b/fs/exfat/super.c
new file mode 100644
index 000000000000..f06e0b53e393
--- /dev/null
+++ b/fs/exfat/super.c
@@ -0,0 +1,728 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
+ */
+
+#include <linux/fs_context.h>
+#include <linux/fs_parser.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/time.h>
+#include <linux/mount.h>
+#include <linux/cred.h>
+#include <linux/statfs.h>
+#include <linux/seq_file.h>
+#include <linux/blkdev.h>
+#include <linux/fs_struct.h>
+#include <linux/iversion.h>
+#include <linux/nls.h>
+#include <linux/buffer_head.h>
+
+#include "exfat_raw.h"
+#include "exfat_fs.h"
+
+static char exfat_default_iocharset[] = CONFIG_EXFAT_DEFAULT_IOCHARSET;
+static struct kmem_cache *exfat_inode_cachep;
+
+static void exfat_free_iocharset(struct exfat_sb_info *sbi)
+{
+ if (sbi->options.iocharset != exfat_default_iocharset)
+ kfree(sbi->options.iocharset);
+}
+
+static void exfat_delayed_free(struct rcu_head *p)
+{
+ struct exfat_sb_info *sbi = container_of(p, struct exfat_sb_info, rcu);
+
+ unload_nls(sbi->nls_io);
+ exfat_free_iocharset(sbi);
+ exfat_free_upcase_table(sbi);
+ kfree(sbi);
+}
+
+static void exfat_put_super(struct super_block *sb)
+{
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
+
+ mutex_lock(&sbi->s_lock);
+ if (test_and_clear_bit(EXFAT_SB_DIRTY, &sbi->s_state))
+ sync_blockdev(sb->s_bdev);
+ exfat_set_vol_flags(sb, VOL_CLEAN);
+ exfat_free_bitmap(sbi);
+ mutex_unlock(&sbi->s_lock);
+
+ call_rcu(&sbi->rcu, exfat_delayed_free);
+}
+
+static int exfat_sync_fs(struct super_block *sb, int wait)
+{
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
+ int err = 0;
+
+ /* If there are some dirty buffers in the bdev inode */
+ mutex_lock(&sbi->s_lock);
+ if (test_and_clear_bit(EXFAT_SB_DIRTY, &sbi->s_state)) {
+ sync_blockdev(sb->s_bdev);
+ if (exfat_set_vol_flags(sb, VOL_CLEAN))
+ err = -EIO;
+ }
+ mutex_unlock(&sbi->s_lock);
+ return err;
+}
+
+static int exfat_statfs(struct dentry *dentry, struct kstatfs *buf)
+{
+ struct super_block *sb = dentry->d_sb;
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
+ unsigned long long id = huge_encode_dev(sb->s_bdev->bd_dev);
+
+ if (sbi->used_clusters == EXFAT_CLUSTERS_UNTRACKED) {
+ mutex_lock(&sbi->s_lock);
+ if (exfat_count_used_clusters(sb, &sbi->used_clusters)) {
+ mutex_unlock(&sbi->s_lock);
+ return -EIO;
+ }
+ mutex_unlock(&sbi->s_lock);
+ }
+
+ buf->f_type = sb->s_magic;
+ buf->f_bsize = sbi->cluster_size;
+ buf->f_blocks = sbi->num_clusters - 2; /* clu 0 & 1 */
+ buf->f_bfree = buf->f_blocks - sbi->used_clusters;
+ buf->f_bavail = buf->f_bfree;
+ buf->f_fsid.val[0] = (unsigned int)id;
+ buf->f_fsid.val[1] = (unsigned int)(id >> 32);
+ /* Unicode utf16 255 characters */
+ buf->f_namelen = EXFAT_MAX_FILE_LEN * NLS_MAX_CHARSET_SIZE;
+ return 0;
+}
+
+int exfat_set_vol_flags(struct super_block *sb, unsigned short new_flag)
+{
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
+ struct pbr64 *bpb;
+ bool sync = 0;
+
+ /* flags are not changed */
+ if (sbi->vol_flag == new_flag)
+ return 0;
+
+ sbi->vol_flag = new_flag;
+
+ /* skip updating volume dirty flag,
+ * if this volume has been mounted with read-only
+ */
+ if (sb_rdonly(sb))
+ return 0;
+
+ if (!sbi->pbr_bh) {
+ sbi->pbr_bh = sb_bread(sb, 0);
+ if (!sbi->pbr_bh) {
+ exfat_msg(sb, KERN_ERR, "failed to read boot sector");
+ return -ENOMEM;
+ }
+ }
+
+ bpb = (struct pbr64 *)sbi->pbr_bh->b_data;
+ bpb->bsx.vol_flags = cpu_to_le16(new_flag);
+
+ if (new_flag == VOL_DIRTY && !buffer_dirty(sbi->pbr_bh))
+ sync = true;
+ else
+ sync = false;
+
+ set_buffer_uptodate(sbi->pbr_bh);
+ mark_buffer_dirty(sbi->pbr_bh);
+
+ if (sync)
+ sync_dirty_buffer(sbi->pbr_bh);
+ return 0;
+}
+
+static int exfat_show_options(struct seq_file *m, struct dentry *root)
+{
+ struct super_block *sb = root->d_sb;
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
+ struct exfat_mount_options *opts = &sbi->options;
+
+ /* Show partition info */
+ if (!uid_eq(opts->fs_uid, GLOBAL_ROOT_UID))
+ seq_printf(m, ",uid=%u",
+ from_kuid_munged(&init_user_ns, opts->fs_uid));
+ if (!gid_eq(opts->fs_gid, GLOBAL_ROOT_GID))
+ seq_printf(m, ",gid=%u",
+ from_kgid_munged(&init_user_ns, opts->fs_gid));
+ seq_printf(m, ",fmask=%04o,dmask=%04o", opts->fs_fmask, opts->fs_dmask);
+ if (opts->allow_utime)
+ seq_printf(m, ",allow_utime=%04o", opts->allow_utime);
+ if (opts->utf8)
+ seq_puts(m, ",iocharset=utf8");
+ else if (sbi->nls_io)
+ seq_printf(m, ",iocharset=%s", sbi->nls_io->charset);
+ seq_printf(m, ",bps=%ld", sb->s_blocksize);
+ if (opts->errors == EXFAT_ERRORS_CONT)
+ seq_puts(m, ",errors=continue");
+ else if (opts->errors == EXFAT_ERRORS_PANIC)
+ seq_puts(m, ",errors=panic");
+ else
+ seq_puts(m, ",errors=remount-ro");
+ if (opts->discard)
+ seq_puts(m, ",discard");
+ if (opts->time_offset)
+ seq_printf(m, ",time_offset=%d", opts->time_offset);
+ return 0;
+}
+
+static struct inode *exfat_alloc_inode(struct super_block *sb)
+{
+ struct exfat_inode_info *ei;
+
+ ei = kmem_cache_alloc(exfat_inode_cachep, GFP_NOFS);
+ if (!ei)
+ return NULL;
+
+ init_rwsem(&ei->truncate_lock);
+ return &ei->vfs_inode;
+}
+
+static void exfat_free_inode(struct inode *inode)
+{
+ kmem_cache_free(exfat_inode_cachep, EXFAT_I(inode));
+}
+
+static const struct super_operations exfat_sops = {
+ .alloc_inode = exfat_alloc_inode,
+ .free_inode = exfat_free_inode,
+ .write_inode = exfat_write_inode,
+ .evict_inode = exfat_evict_inode,
+ .put_super = exfat_put_super,
+ .sync_fs = exfat_sync_fs,
+ .statfs = exfat_statfs,
+ .show_options = exfat_show_options,
+};
+
+enum {
+ Opt_uid,
+ Opt_gid,
+ Opt_umask,
+ Opt_dmask,
+ Opt_fmask,
+ Opt_allow_utime,
+ Opt_charset,
+ Opt_errors,
+ Opt_discard,
+ Opt_time_offset,
+};
+
+static const struct fs_parameter_spec exfat_param_specs[] = {
+ fsparam_u32("uid", Opt_uid),
+ fsparam_u32("gid", Opt_gid),
+ fsparam_u32oct("umask", Opt_umask),
+ fsparam_u32oct("dmask", Opt_dmask),
+ fsparam_u32oct("fmask", Opt_fmask),
+ fsparam_u32oct("allow_utime", Opt_allow_utime),
+ fsparam_string("iocharset", Opt_charset),
+ fsparam_enum("errors", Opt_errors),
+ fsparam_flag("discard", Opt_discard),
+ fsparam_s32("time_offset", Opt_time_offset),
+ {}
+};
+
+static const struct fs_parameter_enum exfat_param_enums[] = {
+ { Opt_errors, "continue", EXFAT_ERRORS_CONT },
+ { Opt_errors, "panic", EXFAT_ERRORS_PANIC },
+ { Opt_errors, "remount-ro", EXFAT_ERRORS_RO },
+ {}
+};
+
+static const struct fs_parameter_description exfat_parameters = {
+ .name = "exfat",
+ .specs = exfat_param_specs,
+ .enums = exfat_param_enums,
+};
+
+static int exfat_parse_param(struct fs_context *fc, struct fs_parameter *param)
+{
+ struct exfat_sb_info *sbi = fc->s_fs_info;
+ struct exfat_mount_options *opts = &sbi->options;
+ struct fs_parse_result result;
+ int opt;
+
+ opt = fs_parse(fc, &exfat_parameters, param, &result);
+ if (opt < 0)
+ return opt;
+
+ switch (opt) {
+ case Opt_uid:
+ opts->fs_uid = make_kuid(current_user_ns(), result.uint_32);
+ break;
+ case Opt_gid:
+ opts->fs_gid = make_kgid(current_user_ns(), result.uint_32);
+ break;
+ case Opt_umask:
+ opts->fs_fmask = result.uint_32;
+ opts->fs_dmask = result.uint_32;
+ break;
+ case Opt_dmask:
+ opts->fs_dmask = result.uint_32;
+ break;
+ case Opt_fmask:
+ opts->fs_fmask = result.uint_32;
+ break;
+ case Opt_allow_utime:
+ opts->allow_utime = result.uint_32 & 0022;
+ break;
+ case Opt_charset:
+ exfat_free_iocharset(sbi);
+ opts->iocharset = kstrdup(param->string, GFP_KERNEL);
+ if (!opts->iocharset)
+ return -ENOMEM;
+ break;
+ case Opt_errors:
+ opts->errors = result.uint_32;
+ break;
+ case Opt_discard:
+ opts->discard = 1;
+ break;
+ case Opt_time_offset:
+ /*
+ * Make the limit 24 just in case someone invents something
+ * unusual.
+ */
+ if (result.int_32 < -24 * 60 || result.int_32 > 24 * 60)
+ return -EINVAL;
+ opts->time_offset = result.int_32;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void exfat_hash_init(struct super_block *sb)
+{
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
+ int i;
+
+ spin_lock_init(&sbi->inode_hash_lock);
+ for (i = 0; i < EXFAT_HASH_SIZE; i++)
+ INIT_HLIST_HEAD(&sbi->inode_hashtable[i]);
+}
+
+static int exfat_read_root(struct inode *inode)
+{
+ struct super_block *sb = inode->i_sb;
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
+ struct exfat_inode_info *ei = EXFAT_I(inode);
+ struct exfat_chain cdir;
+ int num_subdirs, num_clu = 0;
+
+ exfat_chain_set(&ei->dir, sbi->root_dir, 0, ALLOC_FAT_CHAIN);
+ ei->entry = -1;
+ ei->start_clu = sbi->root_dir;
+ ei->flags = ALLOC_FAT_CHAIN;
+ ei->type = TYPE_DIR;
+ ei->version = 0;
+ ei->rwoffset = 0;
+ ei->hint_bmap.off = EXFAT_EOF_CLUSTER;
+ ei->hint_stat.eidx = 0;
+ ei->hint_stat.clu = sbi->root_dir;
+ ei->hint_femp.eidx = EXFAT_HINT_NONE;
+
+ exfat_chain_set(&cdir, sbi->root_dir, 0, ALLOC_FAT_CHAIN);
+ if (exfat_count_num_clusters(sb, &cdir, &num_clu))
+ return -EIO;
+ i_size_write(inode, num_clu << sbi->cluster_size_bits);
+
+ num_subdirs = exfat_count_dir_entries(sb, &cdir);
+ if (num_subdirs < 0)
+ return -EIO;
+ set_nlink(inode, num_subdirs + EXFAT_MIN_SUBDIR);
+
+ inode->i_uid = sbi->options.fs_uid;
+ inode->i_gid = sbi->options.fs_gid;
+ inode_inc_iversion(inode);
+ inode->i_generation = 0;
+ inode->i_mode = exfat_make_mode(sbi, ATTR_SUBDIR, 0777);
+ inode->i_op = &exfat_dir_inode_operations;
+ inode->i_fop = &exfat_dir_operations;
+
+ inode->i_blocks = ((i_size_read(inode) + (sbi->cluster_size - 1))
+ & ~(sbi->cluster_size - 1)) >> inode->i_blkbits;
+ EXFAT_I(inode)->i_pos = ((loff_t)sbi->root_dir << 32) | 0xffffffff;
+ EXFAT_I(inode)->i_size_aligned = i_size_read(inode);
+ EXFAT_I(inode)->i_size_ondisk = i_size_read(inode);
+
+ exfat_save_attr(inode, ATTR_SUBDIR);
+ inode->i_mtime = inode->i_atime = inode->i_ctime = ei->i_crtime =
+ current_time(inode);
+ exfat_cache_init_inode(inode);
+ return 0;
+}
+
+static struct pbr *exfat_read_pbr_with_logical_sector(struct super_block *sb,
+ struct buffer_head **prev_bh)
+{
+ struct pbr *p_pbr = (struct pbr *) (*prev_bh)->b_data;
+ unsigned short logical_sect = 0;
+
+ logical_sect = 1 << p_pbr->bsx.f64.sect_size_bits;
+
+ if (!is_power_of_2(logical_sect) ||
+ logical_sect < 512 || logical_sect > 4096) {
+ exfat_msg(sb, KERN_ERR, "bogus logical sector size %u",
+ logical_sect);
+ return NULL;
+ }
+
+ if (logical_sect < sb->s_blocksize) {
+ exfat_msg(sb, KERN_ERR,
+ "logical sector size too small for device (logical sector size = %u)",
+ logical_sect);
+ return NULL;
+ }
+
+ if (logical_sect > sb->s_blocksize) {
+ struct buffer_head *bh = NULL;
+
+ __brelse(*prev_bh);
+ *prev_bh = NULL;
+
+ if (!sb_set_blocksize(sb, logical_sect)) {
+ exfat_msg(sb, KERN_ERR,
+ "unable to set blocksize %u", logical_sect);
+ return NULL;
+ }
+ bh = sb_bread(sb, 0);
+ if (!bh) {
+ exfat_msg(sb, KERN_ERR,
+ "unable to read boot sector (logical sector size = %lu)",
+ sb->s_blocksize);
+ return NULL;
+ }
+
+ *prev_bh = bh;
+ p_pbr = (struct pbr *) bh->b_data;
+ }
+ return p_pbr;
+}
+
+/* mount the file system volume */
+static int __exfat_fill_super(struct super_block *sb)
+{
+ int ret;
+ struct pbr *p_pbr;
+ struct pbr64 *p_bpb;
+ struct buffer_head *bh;
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
+
+ /* set block size to read super block */
+ sb_min_blocksize(sb, 512);
+
+ /* read boot sector */
+ bh = sb_bread(sb, 0);
+ if (!bh) {
+ exfat_msg(sb, KERN_ERR, "unable to read boot sector");
+ return -EIO;
+ }
+
+ /* PRB is read */
+ p_pbr = (struct pbr *)bh->b_data;
+
+ /* check the validity of PBR */
+ if (le16_to_cpu((p_pbr->signature)) != PBR_SIGNATURE) {
+ exfat_msg(sb, KERN_ERR, "invalid boot record signature");
+ ret = -EINVAL;
+ goto free_bh;
+ }
+
+
+ /* check logical sector size */
+ p_pbr = exfat_read_pbr_with_logical_sector(sb, &bh);
+ if (!p_pbr) {
+ ret = -EIO;
+ goto free_bh;
+ }
+
+ /*
+ * res_zero field must be filled with zero to prevent mounting
+ * from FAT volume.
+ */
+ if (memchr_inv(p_pbr->bpb.f64.res_zero, 0,
+ sizeof(p_pbr->bpb.f64.res_zero))) {
+ ret = -EINVAL;
+ goto free_bh;
+ }
+
+ p_bpb = (struct pbr64 *)p_pbr;
+ if (!p_bpb->bsx.num_fats) {
+ exfat_msg(sb, KERN_ERR, "bogus number of FAT structure");
+ ret = -EINVAL;
+ goto free_bh;
+ }
+
+ sbi->sect_per_clus = 1 << p_bpb->bsx.sect_per_clus_bits;
+ sbi->sect_per_clus_bits = p_bpb->bsx.sect_per_clus_bits;
+ sbi->cluster_size_bits = sbi->sect_per_clus_bits + sb->s_blocksize_bits;
+ sbi->cluster_size = 1 << sbi->cluster_size_bits;
+ sbi->num_FAT_sectors = le32_to_cpu(p_bpb->bsx.fat_length);
+ sbi->FAT1_start_sector = le32_to_cpu(p_bpb->bsx.fat_offset);
+ sbi->FAT2_start_sector = p_bpb->bsx.num_fats == 1 ?
+ sbi->FAT1_start_sector :
+ sbi->FAT1_start_sector + sbi->num_FAT_sectors;
+ sbi->data_start_sector = le32_to_cpu(p_bpb->bsx.clu_offset);
+ sbi->num_sectors = le64_to_cpu(p_bpb->bsx.vol_length);
+ /* because the cluster index starts with 2 */
+ sbi->num_clusters = le32_to_cpu(p_bpb->bsx.clu_count) +
+ EXFAT_RESERVED_CLUSTERS;
+
+ sbi->root_dir = le32_to_cpu(p_bpb->bsx.root_cluster);
+ sbi->dentries_per_clu = 1 <<
+ (sbi->cluster_size_bits - DENTRY_SIZE_BITS);
+
+ sbi->vol_flag = le16_to_cpu(p_bpb->bsx.vol_flags);
+ sbi->clu_srch_ptr = EXFAT_FIRST_CLUSTER;
+ sbi->used_clusters = EXFAT_CLUSTERS_UNTRACKED;
+
+ if (le16_to_cpu(p_bpb->bsx.vol_flags) & VOL_DIRTY) {
+ sbi->vol_flag |= VOL_DIRTY;
+ exfat_msg(sb, KERN_WARNING,
+ "Volume was not properly unmounted. Some data may be corrupt. Please run fsck.");
+ }
+
+ /* exFAT file size is limited by a disk volume size */
+ sb->s_maxbytes = (u64)(sbi->num_clusters - EXFAT_RESERVED_CLUSTERS) <<
+ sbi->cluster_size_bits;
+
+ ret = exfat_create_upcase_table(sb);
+ if (ret) {
+ exfat_msg(sb, KERN_ERR, "failed to load upcase table");
+ goto free_bh;
+ }
+
+ ret = exfat_load_bitmap(sb);
+ if (ret) {
+ exfat_msg(sb, KERN_ERR, "failed to load alloc-bitmap");
+ goto free_upcase_table;
+ }
+
+ ret = exfat_count_used_clusters(sb, &sbi->used_clusters);
+ if (ret) {
+ exfat_msg(sb, KERN_ERR, "failed to scan clusters");
+ goto free_alloc_bitmap;
+ }
+
+ return 0;
+
+free_alloc_bitmap:
+ exfat_free_bitmap(sbi);
+free_upcase_table:
+ exfat_free_upcase_table(sbi);
+free_bh:
+ brelse(bh);
+ return ret;
+}
+
+static int exfat_fill_super(struct super_block *sb, struct fs_context *fc)
+{
+ struct exfat_sb_info *sbi = sb->s_fs_info;
+ struct exfat_mount_options *opts = &sbi->options;
+ struct inode *root_inode;
+ int err;
+
+ if (opts->allow_utime == (unsigned short)-1)
+ opts->allow_utime = ~opts->fs_dmask & 0022;
+
+ if (opts->discard) {
+ struct request_queue *q = bdev_get_queue(sb->s_bdev);
+
+ if (!blk_queue_discard(q))
+ exfat_msg(sb, KERN_WARNING,
+ "mounting with \"discard\" option, but the device does not support discard");
+ opts->discard = 0;
+ }
+
+ sb->s_flags |= SB_NODIRATIME;
+ sb->s_magic = EXFAT_SUPER_MAGIC;
+ sb->s_op = &exfat_sops;
+
+ sb->s_time_gran = 1;
+ sb->s_time_min = EXFAT_MIN_TIMESTAMP_SECS;
+ sb->s_time_max = EXFAT_MAX_TIMESTAMP_SECS;
+
+ err = __exfat_fill_super(sb);
+ if (err) {
+ exfat_msg(sb, KERN_ERR, "failed to recognize exfat type");
+ goto check_nls_io;
+ }
+
+ /* set up enough so that it can read an inode */
+ exfat_hash_init(sb);
+
+ if (!strcmp(sbi->options.iocharset, "utf8"))
+ opts->utf8 = 1;
+ else {
+ sbi->nls_io = load_nls(sbi->options.iocharset);
+ if (!sbi->nls_io) {
+ exfat_msg(sb, KERN_ERR, "IO charset %s not found",
+ sbi->options.iocharset);
+ err = -EINVAL;
+ goto free_table;
+ }
+ }
+
+ if (sbi->options.utf8)
+ sb->s_d_op = &exfat_utf8_dentry_ops;
+ else
+ sb->s_d_op = &exfat_dentry_ops;
+
+ root_inode = new_inode(sb);
+ if (!root_inode) {
+ exfat_msg(sb, KERN_ERR, "failed to allocate root inode.");
+ err = -ENOMEM;
+ goto free_table;
+ }
+
+ root_inode->i_ino = EXFAT_ROOT_INO;
+ inode_set_iversion(root_inode, 1);
+ err = exfat_read_root(root_inode);
+ if (err) {
+ exfat_msg(sb, KERN_ERR, "failed to initialize root inode.");
+ goto put_inode;
+ }
+
+ exfat_hash_inode(root_inode, EXFAT_I(root_inode)->i_pos);
+ insert_inode_hash(root_inode);
+
+ sb->s_root = d_make_root(root_inode);
+ if (!sb->s_root) {
+ exfat_msg(sb, KERN_ERR, "failed to get the root dentry");
+ err = -ENOMEM;
+ goto put_inode;
+ }
+
+ return 0;
+
+put_inode:
+ iput(root_inode);
+ sb->s_root = NULL;
+
+free_table:
+ exfat_free_upcase_table(sbi);
+ exfat_free_bitmap(sbi);
+
+check_nls_io:
+ unload_nls(sbi->nls_io);
+ exfat_free_iocharset(sbi);
+ sb->s_fs_info = NULL;
+ kfree(sbi);
+ return err;
+}
+
+static int exfat_get_tree(struct fs_context *fc)
+{
+ return get_tree_bdev(fc, exfat_fill_super);
+}
+
+static void exfat_free(struct fs_context *fc)
+{
+ kfree(fc->s_fs_info);
+}
+
+static const struct fs_context_operations exfat_context_ops = {
+ .parse_param = exfat_parse_param,
+ .get_tree = exfat_get_tree,
+ .free = exfat_free,
+};
+
+static int exfat_init_fs_context(struct fs_context *fc)
+{
+ struct exfat_sb_info *sbi;
+
+ sbi = kzalloc(sizeof(struct exfat_sb_info), GFP_KERNEL);
+ if (!sbi)
+ return -ENOMEM;
+
+ mutex_init(&sbi->s_lock);
+ ratelimit_state_init(&sbi->ratelimit, DEFAULT_RATELIMIT_INTERVAL,
+ DEFAULT_RATELIMIT_BURST);
+
+ sbi->options.fs_uid = current_uid();
+ sbi->options.fs_gid = current_gid();
+ sbi->options.fs_fmask = current->fs->umask;
+ sbi->options.fs_dmask = current->fs->umask;
+ sbi->options.allow_utime = -1;
+ sbi->options.iocharset = exfat_default_iocharset;
+ sbi->options.errors = EXFAT_ERRORS_RO;
+
+ fc->s_fs_info = sbi;
+ fc->ops = &exfat_context_ops;
+ return 0;
+}
+
+static struct file_system_type exfat_fs_type = {
+ .owner = THIS_MODULE,
+ .name = "exfat",
+ .init_fs_context = exfat_init_fs_context,
+ .parameters = &exfat_parameters,
+ .kill_sb = kill_block_super,
+ .fs_flags = FS_REQUIRES_DEV,
+};
+
+static void exfat_inode_init_once(void *foo)
+{
+ struct exfat_inode_info *ei = (struct exfat_inode_info *)foo;
+
+ INIT_HLIST_NODE(&ei->i_hash_fat);
+ inode_init_once(&ei->vfs_inode);
+}
+
+static int __init init_exfat_fs(void)
+{
+ int err;
+
+ err = exfat_cache_init();
+ if (err)
+ return err;
+
+ exfat_inode_cachep = kmem_cache_create("exfat_inode_cache",
+ sizeof(struct exfat_inode_info),
+ 0, SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD,
+ exfat_inode_init_once);
+ if (!exfat_inode_cachep) {
+ err = -ENOMEM;
+ goto shutdown_cache;
+ }
+
+ err = register_filesystem(&exfat_fs_type);
+ if (err)
+ goto destroy_cache;
+
+ return 0;
+
+destroy_cache:
+ kmem_cache_destroy(exfat_inode_cachep);
+shutdown_cache:
+ exfat_cache_shutdown();
+ return err;
+}
+
+static void __exit exit_exfat_fs(void)
+{
+ /*
+ * Make sure all delayed rcu free inodes are flushed before we
+ * destroy cache.
+ */
+ rcu_barrier();
+ kmem_cache_destroy(exfat_inode_cachep);
+ unregister_filesystem(&exfat_fs_type);
+ exfat_cache_shutdown();
+}
+
+module_init(init_exfat_fs);
+module_exit(exit_exfat_fs);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("exFAT filesystem support");
+MODULE_AUTHOR("Samsung Electronics Co., Ltd.");
--
2.25.1
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,84 @@
From 9acd0d53800c55c6e2186e29b6433daf24617451 Mon Sep 17 00:00:00 2001
From: Valdis Kletnieks <valdis.kletnieks@vt.edu>
Date: Mon, 2 Mar 2020 15:21:45 +0900
Subject: [PATCH] exfat: update file system parameter handling
Al Viro recently reworked the way file system parameters are handled
Update super.c to work with it in linux-next 20200203.
Signed-off-by: Valdis Kletnieks <valdis.kletnieks@vt.edu>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Acked-by: Namjae Jeon <namjae.jeon@samsung.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/exfat/super.c | 28 +++++++++++-----------------
1 file changed, 11 insertions(+), 17 deletions(-)
diff --git a/fs/exfat/super.c b/fs/exfat/super.c
index f06e0b53e393..16ed202ef527 100644
--- a/fs/exfat/super.c
+++ b/fs/exfat/super.c
@@ -214,7 +214,14 @@ enum {
Opt_time_offset,
};
-static const struct fs_parameter_spec exfat_param_specs[] = {
+static const struct constant_table exfat_param_enums[] = {
+ { "continue", EXFAT_ERRORS_CONT },
+ { "panic", EXFAT_ERRORS_PANIC },
+ { "remount-ro", EXFAT_ERRORS_RO },
+ {}
+};
+
+static const struct fs_parameter_spec exfat_parameters[] = {
fsparam_u32("uid", Opt_uid),
fsparam_u32("gid", Opt_gid),
fsparam_u32oct("umask", Opt_umask),
@@ -222,25 +229,12 @@ static const struct fs_parameter_spec exfat_param_specs[] = {
fsparam_u32oct("fmask", Opt_fmask),
fsparam_u32oct("allow_utime", Opt_allow_utime),
fsparam_string("iocharset", Opt_charset),
- fsparam_enum("errors", Opt_errors),
+ fsparam_enum("errors", Opt_errors, exfat_param_enums),
fsparam_flag("discard", Opt_discard),
fsparam_s32("time_offset", Opt_time_offset),
{}
};
-static const struct fs_parameter_enum exfat_param_enums[] = {
- { Opt_errors, "continue", EXFAT_ERRORS_CONT },
- { Opt_errors, "panic", EXFAT_ERRORS_PANIC },
- { Opt_errors, "remount-ro", EXFAT_ERRORS_RO },
- {}
-};
-
-static const struct fs_parameter_description exfat_parameters = {
- .name = "exfat",
- .specs = exfat_param_specs,
- .enums = exfat_param_enums,
-};
-
static int exfat_parse_param(struct fs_context *fc, struct fs_parameter *param)
{
struct exfat_sb_info *sbi = fc->s_fs_info;
@@ -248,7 +242,7 @@ static int exfat_parse_param(struct fs_context *fc, struct fs_parameter *param)
struct fs_parse_result result;
int opt;
- opt = fs_parse(fc, &exfat_parameters, param, &result);
+ opt = fs_parse(fc, exfat_parameters, param, &result);
if (opt < 0)
return opt;
@@ -665,7 +659,7 @@ static struct file_system_type exfat_fs_type = {
.owner = THIS_MODULE,
.name = "exfat",
.init_fs_context = exfat_init_fs_context,
- .parameters = &exfat_parameters,
+ .parameters = exfat_parameters,
.kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV,
};
--
2.26.0
@@ -1,39 +0,0 @@
From: Jan Kara <jack@suse.cz>
Subject: [PATCH] jbd2: Fix dbench4 performance regression for 'nobarrier' mounts
Date: Fri, 28 Apr 2017 11:59:34 +0200
Commit b685d3d65ac7 "block: treat REQ_FUA and REQ_PREFLUSH as
synchronous" removed REQ_SYNC flag from WRITE_FUA implementation. Since
JBD2 strips REQ_FUA and REQ_FLUSH flags from submitted IO when the
filesystem is mounted with nobarrier mount option, journal superblock
writes ended up being async writes after this patch and that caused
heavy performance regression for dbench4 benchmark with high number of
processes. In my test setup with HP RAID array with non-volatile write
cache and 32 GB ram, dbench4 runs with 8 processes regressed by ~25%.
Fix the problem by making sure journal superblock writes are always
treated as synchronous since they generally block progress of the
journalling machinery and thus the whole filesystem.
Fixes: b685d3d65ac791406e0dfd8779cc9b3707fea5a3
CC: stable@vger.kernel.org
Signed-off-by: Jan Kara <jack@suse.cz>
---
fs/jbd2/journal.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
index 5adc2fb62b0f..e768126f6a72 100644
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -1348,7 +1348,7 @@ static int jbd2_write_superblock(journal_t *journal, int write_flags)
jbd2_superblock_csum_set(journal, sb);
get_bh(bh);
bh->b_end_io = end_buffer_write_sync;
- ret = submit_bh(REQ_OP_WRITE, write_flags, bh);
+ ret = submit_bh(REQ_OP_WRITE, write_flags | REQ_SYNC, bh);
wait_on_buffer(bh);
if (buffer_write_io_error(bh)) {
clear_buffer_write_io_error(bh);
--
2.12.0
@@ -1,44 +0,0 @@
From e522751d605d99a81508e58390a8f51ee96fb662 Mon Sep 17 00:00:00 2001
From: Tomasz Majchrzak <tomasz.majchrzak@intel.com>
Date: Tue, 29 Nov 2016 15:18:20 +0100
Subject: [PATCH] seq_file: reset iterator to first record for zero offset
If kernfs file is empty on a first read, successive read operations
using the same file descriptor will return no data, even when data is
available. Default kernfs 'seq_next' implementation advances iterator
position even when next object is not there. Kernfs 'seq_start' for
following requests will not return iterator as position is already on
the second object.
This defect doesn't allow to monitor badblocks sysfs files from MD raid.
They are initially empty but if data appears at some stage, userspace is
not able to read it.
Signed-off-by: Tomasz Majchrzak <tomasz.majchrzak@intel.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/seq_file.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/fs/seq_file.c b/fs/seq_file.c
index 368bfb9..a11f271 100644
--- a/fs/seq_file.c
+++ b/fs/seq_file.c
@@ -190,6 +190,13 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
*/
m->version = file->f_version;
+ /*
+ * if request is to read from zero offset, reset iterator to first
+ * record as it might have been already advanced by previous requests
+ */
+ if (*ppos == 0)
+ m->index = 0;
+
/* Don't assume *ppos is where we left it */
if (unlikely(*ppos != m->read_pos)) {
while ((err = traverse(m, *ppos)) == -EAGAIN)
--
2.10.2
File diff suppressed because it is too large Load Diff
@@ -1,28 +0,0 @@
From cf8c73afb3abf0f8905efbaddd4ce11a0deec9da Mon Sep 17 00:00:00 2001
From: Evan Quan <evan.quan@amd.com>
Date: Fri, 17 Mar 2017 10:22:51 +0800
Subject: [PATCH] drm/amd/amdgpu: add POLARIS12 PCI ID
Signed-off-by: Evan Quan <evan.quan@amd.com>
Reviewed-by: Junwei Zhang <Jerry.Zhang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org
---
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index f7adbac..b76cd69 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -421,6 +421,7 @@ static const struct pci_device_id pciidlist[] = {
{0x1002, 0x6985, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
{0x1002, 0x6986, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
{0x1002, 0x6987, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
+ {0x1002, 0x6995, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
{0x1002, 0x699F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
{0, 0, 0}
--
2.10.2
@@ -1,38 +0,0 @@
From fc8e9c54699e42754094ff475da46440778d8f19 Mon Sep 17 00:00:00 2001
From: Junwei Zhang <Jerry.Zhang@amd.com>
Date: Thu, 4 Aug 2016 12:54:22 +0800
Subject: [PATCH] drm/amd/amdgpu: add Polaris12 PCI ID
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Junwei Zhang <Jerry.Zhang@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Ken Wang <Qingqing.Wang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 8cb937b..2534ada 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -418,6 +418,13 @@ static const struct pci_device_id pciidlist[] = {
{0x1002, 0x67CA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
{0x1002, 0x67CC, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
{0x1002, 0x67CF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
+ /* Polaris12 */
+ {0x1002, 0x6980, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
+ {0x1002, 0x6981, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
+ {0x1002, 0x6985, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
+ {0x1002, 0x6986, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
+ {0x1002, 0x6987, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
+ {0x1002, 0x699F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
{0, 0, 0}
};
--
2.10.2
@@ -1,469 +0,0 @@
From c4642a479fac9f5c224ff7425d86c427b94011af Mon Sep 17 00:00:00 2001
From: Junwei Zhang <Jerry.Zhang@amd.com>
Date: Wed, 14 Dec 2016 15:32:28 -0500
Subject: [PATCH] drm/amd/amdgpu: add Polaris12 support (v3)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
v2: agd: squash in various fixes
v3: agd: squash in:
drm/amdgpu: remove unnecessary smc sk firmware for polaris12
Signed-off-by: Junwei Zhang <Jerry.Zhang@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Ken Wang <Qingqing.Wang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
[ rebased for 4.9 / tmb ]
Signed-off-by: Thomas Backlund <tmb@mageia.org>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c | 3 +++
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 ++
drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 5 +++++
drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c | 5 +++++
drivers/gpu/drm/amd/amdgpu/dce_v11_0.c | 13 ++++++++++---
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 31 +++++++++++++++++++++++++-----
drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 5 +++++
drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c | 6 ++++++
drivers/gpu/drm/amd/amdgpu/vce_v3_0.c | 5 +++--
drivers/gpu/drm/amd/amdgpu/vi.c | 10 ++++++++++
drivers/gpu/drm/amd/include/amd_shared.h | 1 +
11 files changed, 76 insertions(+), 10 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c
index 9ada56c..4c851fde 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c
@@ -840,6 +840,9 @@ static int amdgpu_cgs_get_firmware_info(struct cgs_device *cgs_device,
else if (type == CGS_UCODE_ID_SMU_SK)
strcpy(fw_name, "amdgpu/polaris10_smc_sk.bin");
break;
+ case CHIP_POLARIS12:
+ strcpy(fw_name, "amdgpu/polaris12_smc.bin");
+ break;
default:
DRM_ERROR("SMC firmware not supported\n");
return -EINVAL;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 60bd4af..fe3bb94 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -73,6 +73,7 @@ static const char *amdgpu_asic_name[] = {
"STONEY",
"POLARIS10",
"POLARIS11",
+ "POLARIS12",
"LAST",
};
@@ -1277,6 +1278,7 @@ static int amdgpu_early_init(struct amdgpu_device *adev)
case CHIP_FIJI:
case CHIP_POLARIS11:
case CHIP_POLARIS10:
+ case CHIP_POLARIS12:
case CHIP_CARRIZO:
case CHIP_STONEY:
if (adev->asic_type == CHIP_CARRIZO || adev->asic_type == CHIP_STONEY)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
index a81dfae..1d564be 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
@@ -65,6 +65,7 @@
#define FIRMWARE_STONEY "amdgpu/stoney_uvd.bin"
#define FIRMWARE_POLARIS10 "amdgpu/polaris10_uvd.bin"
#define FIRMWARE_POLARIS11 "amdgpu/polaris11_uvd.bin"
+#define FIRMWARE_POLARIS12 "amdgpu/polaris12_uvd.bin"
/**
* amdgpu_uvd_cs_ctx - Command submission parser context
@@ -98,6 +99,7 @@ MODULE_FIRMWARE(FIRMWARE_FIJI);
MODULE_FIRMWARE(FIRMWARE_STONEY);
MODULE_FIRMWARE(FIRMWARE_POLARIS10);
MODULE_FIRMWARE(FIRMWARE_POLARIS11);
+MODULE_FIRMWARE(FIRMWARE_POLARIS12);
static void amdgpu_uvd_idle_work_handler(struct work_struct *work);
@@ -149,6 +151,9 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev)
case CHIP_POLARIS11:
fw_name = FIRMWARE_POLARIS11;
break;
+ case CHIP_POLARIS12:
+ fw_name = FIRMWARE_POLARIS12;
+ break;
default:
return -EINVAL;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
index 69b66b9..8fec802 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
@@ -52,6 +52,7 @@
#define FIRMWARE_STONEY "amdgpu/stoney_vce.bin"
#define FIRMWARE_POLARIS10 "amdgpu/polaris10_vce.bin"
#define FIRMWARE_POLARIS11 "amdgpu/polaris11_vce.bin"
+#define FIRMWARE_POLARIS12 "amdgpu/polaris12_vce.bin"
#ifdef CONFIG_DRM_AMDGPU_CIK
MODULE_FIRMWARE(FIRMWARE_BONAIRE);
@@ -66,6 +67,7 @@ MODULE_FIRMWARE(FIRMWARE_FIJI);
MODULE_FIRMWARE(FIRMWARE_STONEY);
MODULE_FIRMWARE(FIRMWARE_POLARIS10);
MODULE_FIRMWARE(FIRMWARE_POLARIS11);
+MODULE_FIRMWARE(FIRMWARE_POLARIS12);
static void amdgpu_vce_idle_work_handler(struct work_struct *work);
@@ -121,6 +123,9 @@ int amdgpu_vce_sw_init(struct amdgpu_device *adev, unsigned long size)
case CHIP_POLARIS11:
fw_name = FIRMWARE_POLARIS11;
break;
+ case CHIP_POLARIS12:
+ fw_name = FIRMWARE_POLARIS12;
+ break;
default:
return -EINVAL;
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
index b3d62b9..2006abb 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
@@ -167,6 +167,7 @@ static void dce_v11_0_init_golden_registers(struct amdgpu_device *adev)
(const u32)ARRAY_SIZE(stoney_golden_settings_a11));
break;
case CHIP_POLARIS11:
+ case CHIP_POLARIS12:
amdgpu_program_register_sequence(adev,
polaris11_golden_settings_a11,
(const u32)ARRAY_SIZE(polaris11_golden_settings_a11));
@@ -608,6 +609,7 @@ static int dce_v11_0_get_num_crtc (struct amdgpu_device *adev)
num_crtc = 6;
break;
case CHIP_POLARIS11:
+ case CHIP_POLARIS12:
num_crtc = 5;
break;
default:
@@ -1589,6 +1591,7 @@ static int dce_v11_0_audio_init(struct amdgpu_device *adev)
adev->mode_info.audio.num_pins = 8;
break;
case CHIP_POLARIS11:
+ case CHIP_POLARIS12:
adev->mode_info.audio.num_pins = 6;
break;
default:
@@ -2388,7 +2391,8 @@ static u32 dce_v11_0_pick_pll(struct drm_crtc *crtc)
int pll;
if ((adev->asic_type == CHIP_POLARIS10) ||
- (adev->asic_type == CHIP_POLARIS11)) {
+ (adev->asic_type == CHIP_POLARIS11) ||
+ (adev->asic_type == CHIP_POLARIS12)) {
struct amdgpu_encoder *amdgpu_encoder =
to_amdgpu_encoder(amdgpu_crtc->encoder);
struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv;
@@ -2822,7 +2826,8 @@ static int dce_v11_0_crtc_mode_set(struct drm_crtc *crtc,
return -EINVAL;
if ((adev->asic_type == CHIP_POLARIS10) ||
- (adev->asic_type == CHIP_POLARIS11)) {
+ (adev->asic_type == CHIP_POLARIS11) ||
+ (adev->asic_type == CHIP_POLARIS12)) {
struct amdgpu_encoder *amdgpu_encoder =
to_amdgpu_encoder(amdgpu_crtc->encoder);
int encoder_mode =
@@ -2992,6 +2997,7 @@ static int dce_v11_0_early_init(void *handle)
adev->mode_info.num_dig = 6;
break;
case CHIP_POLARIS11:
+ case CHIP_POLARIS12:
adev->mode_info.num_hpd = 5;
adev->mode_info.num_dig = 5;
break;
@@ -3101,7 +3107,8 @@ static int dce_v11_0_hw_init(void *handle)
amdgpu_atombios_crtc_powergate_init(adev);
amdgpu_atombios_encoder_init_dig(adev);
if ((adev->asic_type == CHIP_POLARIS10) ||
- (adev->asic_type == CHIP_POLARIS11)) {
+ (adev->asic_type == CHIP_POLARIS11) ||
+ (adev->asic_type == CHIP_POLARIS12)) {
amdgpu_atombios_crtc_set_dce_clock(adev, adev->clock.default_dispclk,
DCE_CLOCK_TYPE_DISPCLK, ATOM_GCK_DFS);
amdgpu_atombios_crtc_set_dce_clock(adev, 0,
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
index d0ec009..3733741 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
@@ -138,6 +138,13 @@ MODULE_FIRMWARE("amdgpu/polaris10_mec.bi
MODULE_FIRMWARE("amdgpu/polaris10_mec2.bin");
MODULE_FIRMWARE("amdgpu/polaris10_rlc.bin");
+MODULE_FIRMWARE("amdgpu/polaris12_ce.bin");
+MODULE_FIRMWARE("amdgpu/polaris12_pfp.bin");
+MODULE_FIRMWARE("amdgpu/polaris12_me.bin");
+MODULE_FIRMWARE("amdgpu/polaris12_mec.bin");
+MODULE_FIRMWARE("amdgpu/polaris12_mec2.bin");
+MODULE_FIRMWARE("amdgpu/polaris12_rlc.bin");
+
static const struct amdgpu_gds_reg_offset amdgpu_gds_reg_offset[] =
{
{mmGDS_VMID0_BASE, mmGDS_VMID0_SIZE, mmGDS_GWS_VMID0, mmGDS_OA_VMID0},
@@ -687,6 +694,7 @@ static void gfx_v8_0_init_golden_registe
(const u32)ARRAY_SIZE(tonga_golden_common_all));
break;
case CHIP_POLARIS11:
+ case CHIP_POLARIS12:
amdgpu_program_register_sequence(adev,
golden_settings_polaris11_a11,
(const u32)ARRAY_SIZE(golden_settings_polaris11_a11));
@@ -901,6 +909,9 @@ static int gfx_v8_0_init_microcode(struc
case CHIP_POLARIS10:
chip_name = "polaris10";
break;
+ case CHIP_POLARIS12:
+ chip_name = "polaris12";
+ break;
case CHIP_STONEY:
chip_name = "stoney";
break;
@@ -1777,6 +1788,7 @@ static int gfx_v8_0_gpu_early_init(struc
gb_addr_config = TONGA_GB_ADDR_CONFIG_GOLDEN;
break;
case CHIP_POLARIS11:
+ case CHIP_POLARIS12:
ret = amdgpu_atombios_get_gfx_info(adev);
if (ret)
return ret;
@@ -2695,6 +2707,7 @@ static void gfx_v8_0_tiling_mode_table_i
break;
case CHIP_POLARIS11:
+ case CHIP_POLARIS12:
modearray[0] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
PIPE_CONFIG(ADDR_SURF_P4_16x16) |
TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
@@ -3516,6 +3529,7 @@ gfx_v8_0_raster_config(struct amdgpu_dev
*rconf1 |= 0x0;
break;
case CHIP_POLARIS11:
+ case CHIP_POLARIS12:
*rconf |= RB_MAP_PKR0(2) | RB_XSEL2(1) | SE_MAP(2) |
SE_XSEL(1) | SE_YSEL(1);
*rconf1 |= 0x0;
@@ -4029,7 +4043,8 @@ static void gfx_v8_0_init_pg(struct amdg
cz_enable_cp_power_gating(adev, true);
else
cz_enable_cp_power_gating(adev, false);
- } else if (adev->asic_type == CHIP_POLARIS11) {
+ } else if ((adev->asic_type == CHIP_POLARIS11) ||
+ (adev->asic_type == CHIP_POLARIS11)) {
gfx_v8_0_init_power_gating(adev);
}
}
@@ -4100,7 +4115,8 @@ static int gfx_v8_0_rlc_resume(struct am
RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK);
WREG32(mmRLC_CGCG_CGLS_CTRL, tmp);
if (adev->asic_type == CHIP_POLARIS11 ||
- adev->asic_type == CHIP_POLARIS10) {
+ adev->asic_type == CHIP_POLARIS10 ||
+ adev->asic_type == CHIP_POLARIS12) {
tmp = RREG32(mmRLC_CGCG_CGLS_CTRL_3D);
tmp &= ~0x3;
WREG32(mmRLC_CGCG_CGLS_CTRL_3D, tmp);
@@ -4288,6 +4304,7 @@ static int gfx_v8_0_cp_gfx_start(struct
amdgpu_ring_write(ring, 0x0000002A);
break;
case CHIP_POLARIS11:
+ case CHIP_POLARIS12:
amdgpu_ring_write(ring, 0x16000012);
amdgpu_ring_write(ring, 0x00000000);
break;
@@ -4938,7 +4955,8 @@ static int gfx_v8_0_cp_compute_resume(st
(adev->asic_type == CHIP_FIJI) ||
(adev->asic_type == CHIP_STONEY) ||
(adev->asic_type == CHIP_POLARIS11) ||
- (adev->asic_type == CHIP_POLARIS10)) {
+ (adev->asic_type == CHIP_POLARIS10) ||
+ (adev->asic_type == CHIP_POLARIS12)) {
WREG32(mmCP_MEC_DOORBELL_RANGE_LOWER,
AMDGPU_DOORBELL_KIQ << 2);
WREG32(mmCP_MEC_DOORBELL_RANGE_UPPER,
@@ -4974,7 +4992,8 @@ static int gfx_v8_0_cp_compute_resume(st
mqd->cp_hqd_persistent_state = tmp;
if (adev->asic_type == CHIP_STONEY ||
adev->asic_type == CHIP_POLARIS11 ||
- adev->asic_type == CHIP_POLARIS10) {
+ adev->asic_type == CHIP_POLARIS10 ||
+ adev->asic_type == CHIP_POLARIS12) {
tmp = RREG32(mmCP_ME1_PIPE3_INT_CNTL);
tmp = REG_SET_FIELD(tmp, CP_ME1_PIPE3_INT_CNTL, GENERIC2_INT_ENABLE, 1);
WREG32(mmCP_ME1_PIPE3_INT_CNTL, tmp);
@@ -5488,7 +5507,8 @@ static int gfx_v8_0_late_init(void *hand
static void gfx_v8_0_enable_gfx_static_mg_power_gating(struct amdgpu_device *adev,
bool enable)
{
- if (adev->asic_type == CHIP_POLARIS11)
+ if ((adev->asic_type == CHIP_POLARIS11) ||
+ (adev->asic_type == CHIP_POLARIS12))
/* Send msg to SMU via Powerplay */
amdgpu_set_powergating_state(adev,
AMD_IP_BLOCK_TYPE_SMC,
@@ -5565,6 +5585,7 @@ static int gfx_v8_0_set_powergating_stat
gfx_v8_0_enable_gfx_dynamic_mg_power_gating(adev, false);
break;
case CHIP_POLARIS11:
+ case CHIP_POLARIS12:
if ((adev->pg_flags & AMD_PG_SUPPORT_GFX_SMG) && enable)
gfx_v8_0_enable_gfx_static_mg_power_gating(adev, true);
else
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
index 0daac3a..476bc9f 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
@@ -46,6 +46,7 @@ static int gmc_v8_0_wait_for_idle(void *handle);
MODULE_FIRMWARE("amdgpu/tonga_mc.bin");
MODULE_FIRMWARE("amdgpu/polaris11_mc.bin");
MODULE_FIRMWARE("amdgpu/polaris10_mc.bin");
+MODULE_FIRMWARE("amdgpu/polaris12_mc.bin");
static const u32 golden_settings_tonga_a11[] =
{
@@ -130,6 +131,7 @@ static void gmc_v8_0_init_golden_registers(struct amdgpu_device *adev)
(const u32)ARRAY_SIZE(golden_settings_tonga_a11));
break;
case CHIP_POLARIS11:
+ case CHIP_POLARIS12:
amdgpu_program_register_sequence(adev,
golden_settings_polaris11_a11,
(const u32)ARRAY_SIZE(golden_settings_polaris11_a11));
@@ -225,6 +227,9 @@ static int gmc_v8_0_init_microcode(struct amdgpu_device *adev)
case CHIP_POLARIS10:
chip_name = "polaris10";
break;
+ case CHIP_POLARIS12:
+ chip_name = "polaris12";
+ break;
case CHIP_FIJI:
case CHIP_CARRIZO:
case CHIP_STONEY:
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
index 1170a64..034ace7 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
@@ -60,6 +60,8 @@ MODULE_FIRMWARE("amdgpu/polaris10_sdma.bin");
MODULE_FIRMWARE("amdgpu/polaris10_sdma1.bin");
MODULE_FIRMWARE("amdgpu/polaris11_sdma.bin");
MODULE_FIRMWARE("amdgpu/polaris11_sdma1.bin");
+MODULE_FIRMWARE("amdgpu/polaris12_sdma.bin");
+MODULE_FIRMWARE("amdgpu/polaris12_sdma1.bin");
static const u32 sdma_offsets[SDMA_MAX_INSTANCE] =
@@ -206,6 +208,7 @@ static void sdma_v3_0_init_golden_registers(struct amdgpu_device *adev)
(const u32)ARRAY_SIZE(golden_settings_tonga_a11));
break;
case CHIP_POLARIS11:
+ case CHIP_POLARIS12:
amdgpu_program_register_sequence(adev,
golden_settings_polaris11_a11,
(const u32)ARRAY_SIZE(golden_settings_polaris11_a11));
@@ -278,6 +281,9 @@ static int sdma_v3_0_init_microcode(struct amdgpu_device *adev)
case CHIP_POLARIS10:
chip_name = "polaris10";
break;
+ case CHIP_POLARIS12:
+ chip_name = "polaris12";
+ break;
case CHIP_CARRIZO:
chip_name = "carrizo";
break;
diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
index 6b3293a..5fb0b7f 100644
--- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
@@ -320,11 +320,12 @@ static unsigned vce_v3_0_get_harvest_config(struct amdgpu_device *adev)
{
u32 tmp;
- /* Fiji, Stoney, Polaris10, Polaris11 are single pipe */
+ /* Fiji, Stoney, Polaris10, Polaris11, Polaris12 are single pipe */
if ((adev->asic_type == CHIP_FIJI) ||
(adev->asic_type == CHIP_STONEY) ||
(adev->asic_type == CHIP_POLARIS10) ||
- (adev->asic_type == CHIP_POLARIS11))
+ (adev->asic_type == CHIP_POLARIS11) ||
+ (adev->asic_type == CHIP_POLARIS12))
return AMDGPU_VCE_HARVEST_VCE1;
/* Tonga and CZ are dual or single pipe */
diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c
index bf088d6..c2ac54f 100644
--- a/drivers/gpu/drm/amd/amdgpu/vi.c
+++ b/drivers/gpu/drm/amd/amdgpu/vi.c
@@ -88,6 +88,7 @@ MODULE_FIRMWARE("amdgpu/polaris10_smc.bi
MODULE_FIRMWARE("amdgpu/polaris10_smc_sk.bin");
MODULE_FIRMWARE("amdgpu/polaris11_smc.bin");
MODULE_FIRMWARE("amdgpu/polaris11_smc_sk.bin");
+MODULE_FIRMWARE("amdgpu/polaris12_smc.bin");
/*
* Indirect registers accessor
@@ -312,6 +313,7 @@ static void vi_init_golden_registers(str
break;
case CHIP_POLARIS11:
case CHIP_POLARIS10:
+ case CHIP_POLARIS12:
default:
break;
}
@@ -592,6 +594,7 @@ static int vi_read_register(struct amdgp
case CHIP_TONGA:
case CHIP_POLARIS11:
case CHIP_POLARIS10:
+ case CHIP_POLARIS12:
case CHIP_CARRIZO:
case CHIP_STONEY:
asic_register_table = cz_allowed_read_registers;
@@ -1465,6 +1468,7 @@ int vi_set_ip_blocks(struct amdgpu_devic
break;
case CHIP_POLARIS11:
case CHIP_POLARIS10:
+ case CHIP_POLARIS12:
adev->ip_blocks = polaris11_ip_blocks_vd;
adev->num_ip_blocks = ARRAY_SIZE(polaris11_ip_blocks_vd);
break;
@@ -1608,6 +1612,11 @@ static int vi_common_early_init(void *ha
adev->pg_flags = 0;
adev->external_rev_id = adev->rev_id + 0x50;
break;
+ case CHIP_POLARIS12:
+ adev->cg_flags = AMD_CG_SUPPORT_UVD_MGCG;
+ adev->pg_flags = 0;
+ adev->external_rev_id = adev->rev_id + 0x64;
+ break;
case CHIP_CARRIZO:
adev->cg_flags = AMD_CG_SUPPORT_UVD_MGCG |
AMD_CG_SUPPORT_GFX_MGCG |
@@ -1897,6 +1906,7 @@ static int vi_common_set_clockgating_sta
case CHIP_TONGA:
case CHIP_POLARIS10:
case CHIP_POLARIS11:
+ case CHIP_POLARIS12:
vi_common_set_clockgating_state_by_smu(adev, state);
default:
break;
diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h
index c02469a..5f59117 100644
--- a/drivers/gpu/drm/amd/include/amd_shared.h
+++ b/drivers/gpu/drm/amd/include/amd_shared.h
@@ -46,6 +46,7 @@ enum amd_asic_type {
CHIP_STONEY,
CHIP_POLARIS10,
CHIP_POLARIS11,
+ CHIP_POLARIS12,
CHIP_LAST,
};
--
2.10.2
@@ -1,24 +0,0 @@
From 6e88491cf2a3b17199c78bd53348b39dc6a88275 Mon Sep 17 00:00:00 2001
From: Junshan Fang <Junshan.Fang@amd.com>
Date: Thu, 15 Jun 2017 14:02:20 +0800
Subject: [PATCH] drm/amdgpu: add Polaris12 DID
Signed-off-by: Junshan Fang <Junshan.Fang@amd.com>
Reviewed-by: Roger.He <Hongbo.He@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index f2d705e6a75a..ab6b0d0febab 100644
@@ -418,6 +418,7 @@ static const struct pci_device_id pciidl
{0x1002, 0x6986, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
{0x1002, 0x6987, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
{0x1002, 0x6995, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
+ {0x1002, 0x6997, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
{0x1002, 0x699F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
{0, 0, 0}
@@ -1,32 +0,0 @@
From c10c8f7c27103bd7ac02d041d9d6e97296d48fc1 Mon Sep 17 00:00:00 2001
From: Alex Deucher <alexander.deucher@amd.com>
Date: Fri, 10 Feb 2017 18:09:32 -0500
Subject: [PATCH] drm/amdgpu/pm: check for headless before calling
compute_clocks
Don't update display bandwidth on headless asics.
bug:
https://bugs.freedesktop.org/show_bug.cgi?id=99387
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org
---
drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
index 95e026a..346e80a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
@@ -1283,7 +1283,9 @@ void amdgpu_pm_compute_clocks(struct amd
if (adev->pp_enabled) {
int i = 0;
- amdgpu_display_bandwidth_update(adev);
+ if (adev->mode_info.num_crtc)
+ amdgpu_display_bandwidth_update(adev);
+
for (i = 0; i < AMDGPU_MAX_RINGS; i++) {
struct amdgpu_ring *ring = adev->rings[i];
if (ring && ring->ready)
@@ -1,81 +0,0 @@
From f4309526576db325264b6dc9ee150ee70b330a42 Mon Sep 17 00:00:00 2001
From: Junwei Zhang <Jerry.Zhang@amd.com>
Date: Wed, 14 Dec 2016 15:40:48 -0500
Subject: [PATCH] drm/amdgpu/powerplay: add Polaris12 support
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Junwei Zhang <Jerry.Zhang@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Ken Wang <Qingqing.Wang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c | 1 +
drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c | 3 ++-
drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c | 2 +-
drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c | 1 +
4 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c
index fc592c2..95a568d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c
@@ -98,6 +98,7 @@ static int amdgpu_pp_early_init(void *handle)
switch (adev->asic_type) {
case CHIP_POLARIS11:
case CHIP_POLARIS10:
+ case CHIP_POLARIS12:
case CHIP_TONGA:
case CHIP_FIJI:
case CHIP_TOPAZ:
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c
index dc6700a..b036064 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c
@@ -95,6 +95,7 @@ int hwmgr_init(struct amd_pp_init *pp_init, struct pp_instance *handle)
break;
case CHIP_POLARIS11:
case CHIP_POLARIS10:
+ case CHIP_POLARIS12:
polaris_set_asic_special_caps(hwmgr);
hwmgr->feature_mask &= ~(PP_UVD_HANDSHAKE_MASK);
break;
@@ -745,7 +746,7 @@ int polaris_set_asic_special_caps(struct pp_hwmgr *hwmgr)
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_TablelessHardwareInterface);
- if (hwmgr->chip_id == CHIP_POLARIS11)
+ if ((hwmgr->chip_id == CHIP_POLARIS11) || (hwmgr->chip_id == CHIP_POLARIS12))
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_SPLLShutdownSupport);
return 0;
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c
index 26477f0..6cd1287 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c
@@ -521,7 +521,7 @@ int smu7_enable_didt_config(struct pp_hwmgr *hwmgr)
PP_ASSERT_WITH_CODE((result == 0), "DIDT Config failed.", return result);
result = smu7_program_pt_config_registers(hwmgr, DIDTConfig_Polaris10);
PP_ASSERT_WITH_CODE((result == 0), "DIDT Config failed.", return result);
- } else if (hwmgr->chip_id == CHIP_POLARIS11) {
+ } else if ((hwmgr->chip_id == CHIP_POLARIS11) || (hwmgr->chip_id == CHIP_POLARIS12)) {
result = smu7_program_pt_config_registers(hwmgr, GCCACConfig_Polaris11);
PP_ASSERT_WITH_CODE((result == 0), "DIDT Config failed.", return result);
result = smu7_program_pt_config_registers(hwmgr, DIDTConfig_Polaris11);
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c
index e5812aa..6e618aa 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c
@@ -65,6 +65,7 @@ int smum_init(struct amd_pp_init *pp_init, struct pp_instance *handle)
break;
case CHIP_POLARIS11:
case CHIP_POLARIS10:
+ case CHIP_POLARIS12:
polaris10_smum_init(smumgr);
break;
default:
--
2.10.2
@@ -1,42 +0,0 @@
From 853277481178fdf14d1a4e9e6ac7174d6046176f Mon Sep 17 00:00:00 2001
From: Jani Nikula <jani.nikula@intel.com>
Date: Wed, 1 Feb 2017 15:46:09 +0200
Subject: [PATCH] drm/i915: don't warn about Skylake CPU - KabyPoint PCH combo
Apparently there are machines out there with Skylake CPU and KabyPoint
PCH. Judging from our driver code, there doesn't seem to be any code
paths that would do anything different between SunrisePoint and
KabyPoint PCHs, so it would seem okay to accept the combo without
warnings.
Fixes: 22dea0be50b2 ("drm/i915: Introduce Kabypoint PCH for Kabylake H/DT.")
References: https://lists.freedesktop.org/archives/intel-gfx/2017-February/118611.html
Reported-by: Rainer Koenig <Rainer.Koenig@ts.fujitsu.com>
Cc: Rainer Koenig <Rainer.Koenig@ts.fujitsu.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: <stable@vger.kernel.org> # v4.8+
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1485956769-26015-1-git-send-email-jani.nikula@intel.com
(cherry picked from commit 3aac4acb89710fe782c9e78e7b1febf76e112c6c)
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
[ rebased for 4.9 / tmb ]
Signed-off-by: Thomas Backlund <tmb@mageia.org>
---
drivers/gpu/drm/i915/i915_drv.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index b2c4a0b..8d63098 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -207,7 +207,8 @@ static void intel_detect_pch(struct drm_
} else if (id == INTEL_PCH_KBP_DEVICE_ID_TYPE) {
dev_priv->pch_type = PCH_KBP;
DRM_DEBUG_KMS("Found KabyPoint PCH\n");
- WARN_ON(!IS_KABYLAKE(dev));
+ WARN_ON(!IS_SKYLAKE(dev) &&
+ !IS_KABYLAKE(dev));
} else if ((id == INTEL_PCH_P2X_DEVICE_ID_TYPE) ||
(id == INTEL_PCH_P3X_DEVICE_ID_TYPE) ||
((id == INTEL_PCH_QEMU_DEVICE_ID_TYPE) &&
@@ -1,100 +0,0 @@
Adapt mach64 to build with 2.6.31 series kernels
Signed-off-by: Thomas Backlund <tmb@mandriva.org>
diff -urp linux-2.6.31-rc3-git5-mnb1/drivers/gpu/drm/mach64/mach64_dma.c linux-2.6.31-rc3-git5-mnb1/drivers/gpu/drm/mach64.fixed/mach64_dma.c
--- linux-2.6.31-rc3-git5-mnb1/drivers/gpu/drm/mach64/mach64_dma.c 2009-07-23 00:24:12.000000000 +0300
+++ linux-2.6.31-rc3-git5-mnb1/drivers/gpu/drm/mach64.fixed/mach64_dma.c 2009-07-23 02:28:21.000000000 +0300
@@ -1006,7 +1006,7 @@ static int mach64_do_dma_init(struct drm
DRM_DEBUG("\n");
- dev_priv = drm_alloc(sizeof(drm_mach64_private_t), DRM_MEM_DRIVER);
+ dev_priv = kmalloc(sizeof(drm_mach64_private_t), GFP_KERNEL);
if (dev_priv == NULL)
return -ENOMEM;
@@ -1386,8 +1386,7 @@ int mach64_do_cleanup_dma(struct drm_dev
mach64_destroy_freelist(dev);
- drm_free(dev_priv, sizeof(drm_mach64_private_t),
- DRM_MEM_DRIVER);
+ kfree(dev_priv);
dev->dev_private = NULL;
}
@@ -1476,8 +1475,8 @@ int mach64_init_freelist(struct drm_devi
for (i = 0; i < dma->buf_count; i++) {
if ((entry =
(drm_mach64_freelist_t *)
- drm_alloc(sizeof(drm_mach64_freelist_t),
- DRM_MEM_BUFLISTS)) == NULL)
+ kmalloc(sizeof(drm_mach64_freelist_t),
+ GFP_KERNEL)) == NULL)
return -ENOMEM;
memset(entry, 0, sizeof(drm_mach64_freelist_t));
entry->buf = dma->buflist[i];
@@ -1500,18 +1499,18 @@ void mach64_destroy_freelist(struct drm_
list_for_each_safe(ptr, tmp, &dev_priv->pending) {
list_del(ptr);
entry = list_entry(ptr, drm_mach64_freelist_t, list);
- drm_free(entry, sizeof(*entry), DRM_MEM_BUFLISTS);
+ kfree(entry);
}
list_for_each_safe(ptr, tmp, &dev_priv->placeholders) {
list_del(ptr);
entry = list_entry(ptr, drm_mach64_freelist_t, list);
- drm_free(entry, sizeof(*entry), DRM_MEM_BUFLISTS);
+ kfree(entry);
}
list_for_each_safe(ptr, tmp, &dev_priv->free_list) {
list_del(ptr);
entry = list_entry(ptr, drm_mach64_freelist_t, list);
- drm_free(entry, sizeof(*entry), DRM_MEM_BUFLISTS);
+ kfree(entry);
}
}
diff -urp linux-2.6.31-rc3-git5-mnb1/drivers/gpu/drm/mach64/mach64_state.c linux-2.6.31-rc3-git5-mnb1/drivers/gpu/drm/mach64.fixed/mach64_state.c
--- linux-2.6.31-rc3-git5-mnb1/drivers/gpu/drm/mach64/mach64_state.c 2009-07-23 00:24:12.000000000 +0300
+++ linux-2.6.31-rc3-git5-mnb1/drivers/gpu/drm/mach64.fixed/mach64_state.c 2009-07-23 02:29:24.000000000 +0300
@@ -490,12 +490,12 @@ static __inline__ int copy_from_user_ver
unsigned long n = bytes; /* dwords remaining in buffer */
u32 *from, *orig_from;
- from = drm_alloc(bytes, DRM_MEM_DRIVER);
+ from = kmalloc(bytes, GFP_KERNEL);
if (from == NULL)
return -ENOMEM;
if (DRM_COPY_FROM_USER(from, ufrom, bytes)) {
- drm_free(from, bytes, DRM_MEM_DRIVER);
+ kfree(from);
return -EFAULT;
}
orig_from = from; /* we'll be modifying the "from" ptr, so save it */
@@ -526,19 +526,19 @@ static __inline__ int copy_from_user_ver
to += count;
} else {
DRM_ERROR("Got bad command: 0x%04x\n", reg);
- drm_free(orig_from, bytes, DRM_MEM_DRIVER);
+ kfree(orig_from);
return -EACCES;
}
} else {
DRM_ERROR
("Got bad command count(=%u) dwords remaining=%lu\n",
count, n);
- drm_free(orig_from, bytes, DRM_MEM_DRIVER);
+ kfree(orig_from);
return -EINVAL;
}
}
- drm_free(orig_from, bytes, DRM_MEM_DRIVER);
+ kfree(orig_from);
if (n == 0)
return 0;
else {
@@ -1,27 +0,0 @@
--- linux-2.6.35/drivers/gpu/drm/mach64/mach64_state.c.orig 2010-10-03 13:29:10.000000000 +0300
+++ linux-2.6.35/drivers/gpu/drm/mach64/mach64_state.c 2010-10-03 14:04:45.991164007 +0300
@@ -41,15 +41,15 @@
*
*/
struct drm_ioctl_desc mach64_ioctls[] = {
- DRM_IOCTL_DEF(DRM_MACH64_INIT, mach64_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_MACH64_CLEAR, mach64_dma_clear, DRM_AUTH),
- DRM_IOCTL_DEF(DRM_MACH64_SWAP, mach64_dma_swap, DRM_AUTH),
- DRM_IOCTL_DEF(DRM_MACH64_IDLE, mach64_dma_idle, DRM_AUTH),
- DRM_IOCTL_DEF(DRM_MACH64_RESET, mach64_engine_reset, DRM_AUTH),
- DRM_IOCTL_DEF(DRM_MACH64_VERTEX, mach64_dma_vertex, DRM_AUTH),
- DRM_IOCTL_DEF(DRM_MACH64_BLIT, mach64_dma_blit, DRM_AUTH),
- DRM_IOCTL_DEF(DRM_MACH64_FLUSH, mach64_dma_flush, DRM_AUTH),
- DRM_IOCTL_DEF(DRM_MACH64_GETPARAM, mach64_get_param, DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(MACH64_INIT, mach64_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF_DRV(MACH64_CLEAR, mach64_dma_clear, DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(MACH64_SWAP, mach64_dma_swap, DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(MACH64_IDLE, mach64_dma_idle, DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(MACH64_RESET, mach64_engine_reset, DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(MACH64_VERTEX, mach64_dma_vertex, DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(MACH64_BLIT, mach64_dma_blit, DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(MACH64_FLUSH, mach64_dma_flush, DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(MACH64_GETPARAM, mach64_get_param, DRM_AUTH),
};
int mach64_max_ioctl = DRM_ARRAY_SIZE(mach64_ioctls);
@@ -1,24 +0,0 @@
Fix build for 2.6.37
Signed-off-by: Thomas Backlund <tmb@mandriva.org>
--- a/drivers/gpu/drm/mach64/mach64_drv.c.orig 2011-01-02 16:55:48.000000000 +0200
+++ a/drivers/gpu/drm/mach64/mach64_drv.c 2011-01-02 17:53:54.808775632 +0200
@@ -51,8 +51,6 @@ static struct drm_driver driver = {
.irq_uninstall = mach64_driver_irq_uninstall,
.irq_handler = mach64_driver_irq_handler,
.reclaim_buffers = drm_core_reclaim_buffers,
- .get_map_ofs = drm_core_get_map_ofs,
- .get_reg_ofs = drm_core_get_reg_ofs,
.ioctls = mach64_ioctls,
.dma_ioctl = mach64_dma_buffers,
.fops = {
@@ -63,6 +61,7 @@ static struct drm_driver driver = {
.mmap = drm_mmap,
.poll = drm_poll,
.fasync = drm_fasync,
+ .llseek = noop_llseek,
},
.pci_driver = {
.name = DRIVER_NAME,
@@ -1,44 +0,0 @@
fix build with linux-3.0
Signed-off-by: Thomas Backlund <tmb@mageia.org>
drivers/gpu/drm/mach64/mach64_drv.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
--- a/drivers/gpu/drm/mach64/mach64_drv.c.orig 2011-07-15 02:48:40.000000000 +0300
+++ a/drivers/gpu/drm/mach64/mach64_drv.c 2011-07-15 13:24:41.454753025 +0300
@@ -63,10 +63,6 @@ static struct drm_driver driver = {
.fasync = drm_fasync,
.llseek = noop_llseek,
},
- .pci_driver = {
- .name = DRIVER_NAME,
- .id_table = pciidlist,
- },
.name = DRIVER_NAME,
.desc = DRIVER_DESC,
@@ -76,15 +72,20 @@ static struct drm_driver driver = {
.patchlevel = DRIVER_PATCHLEVEL,
};
+static struct pci_driver mach64_pci_driver = {
+ .name = DRIVER_NAME,
+ .id_table = pciidlist,
+};
+
static int __init mach64_init(void)
{
driver.num_ioctls = mach64_max_ioctl;
- return drm_init(&driver);
+ return drm_pci_init(&driver, &mach64_pci_driver);
}
static void __exit mach64_exit(void)
{
- drm_exit(&driver);
+ drm_pci_exit(&driver, &mach64_pci_driver);
}
module_init(mach64_init);
@@ -1,17 +0,0 @@
--- linux/drivers/gpu/drm/mach64/mach64_drv.c.orig 2013-10-13 12:19:41.000000000 +0300
+++ linux/drivers/gpu/drm/mach64/mach64_drv.c 2013-10-13 14:27:25.684247911 +0300
@@ -46,13 +46,12 @@ static const struct file_operations mach
.unlocked_ioctl = drm_ioctl,
.mmap = drm_mmap,
.poll = drm_poll,
- .fasync = drm_fasync,
.llseek = noop_llseek,
};
static struct drm_driver driver = {
.driver_features =
- DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_HAVE_DMA
+ DRIVER_USE_AGP | DRIVER_PCI_DMA | DRIVER_HAVE_DMA
| DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
.lastclose = mach64_driver_lastclose,
.get_vblank_counter = mach64_get_vblank_counter,
@@ -1,31 +0,0 @@
Adapt for kernel-3.17
DRM_ARRAY_SIZE is a duplicate of ARRAY_SIZE and have been dropped.
drm_dev_to_irq has been dropped, so call dev->pdev->irq directly
for code simplicity.
Signed-off-by: Thomas Backlund <tmb@mageia.org>
diff -urp linux/drivers/gpu/drm/mach64/mach64_state.c.orig linux/drivers/gpu/drm/mach64/mach64_state.c
--- linux/drivers/gpu/drm/mach64/mach64_state.c.orig
+++ linux/drivers/gpu/drm/mach64/mach64_state.c
@@ -52,7 +52,7 @@ struct drm_ioctl_desc mach64_ioctls[] =
DRM_IOCTL_DEF_DRV(MACH64_GETPARAM, mach64_get_param, DRM_AUTH),
};
-int mach64_max_ioctl = DRM_ARRAY_SIZE(mach64_ioctls);
+int mach64_max_ioctl = ARRAY_SIZE(mach64_ioctls);
/* ================================================================
* DMA hardware state programming functions
@@ -895,7 +895,7 @@ int mach64_get_param(struct drm_device *
value = mach64_do_get_frames_queued(dev_priv);
break;
case MACH64_PARAM_IRQ_NR:
- value = drm_dev_to_irq(dev);
+ value = dev->pdev->irq;
break;
default:
return -EINVAL;
@@ -1,142 +0,0 @@
Fix build with kernel 3.18
Signed-off-by: Thomas Backlund <tmb@mageia.org>
diff -urp linux/drivers/gpu/drm/mach64.orig/mach64_dma.c linux/drivers/gpu/drm/mach64/mach64_dma.c
--- linux/drivers/gpu/drm/mach64.orig/mach64_dma.c 2014-11-29 22:01:54.000000000 +0200
+++ linux/drivers/gpu/drm/mach64/mach64_dma.c 2014-11-30 00:02:06.906821818 +0200
@@ -1038,21 +1038,21 @@ static int mach64_do_dma_init(struct drm
INIT_LIST_HEAD(&dev_priv->placeholders);
INIT_LIST_HEAD(&dev_priv->pending);
- dev_priv->sarea = drm_getsarea(dev);
+ dev_priv->sarea = drm_legacy_getsarea(dev);
if (!dev_priv->sarea) {
DRM_ERROR("can not find sarea!\n");
dev->dev_private = (void *)dev_priv;
mach64_do_cleanup_dma(dev);
return -EINVAL;
}
- dev_priv->fb = drm_core_findmap(dev, init->fb_offset);
+ dev_priv->fb = drm_legacy_findmap(dev, init->fb_offset);
if (!dev_priv->fb) {
DRM_ERROR("can not find frame buffer map!\n");
dev->dev_private = (void *)dev_priv;
mach64_do_cleanup_dma(dev);
return -EINVAL;
}
- dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
+ dev_priv->mmio = drm_legacy_findmap(dev, init->mmio_offset);
if (!dev_priv->mmio) {
DRM_ERROR("can not find mmio map!\n");
dev->dev_private = (void *)dev_priv;
@@ -1060,7 +1060,7 @@ static int mach64_do_dma_init(struct drm
return -EINVAL;
}
- dev_priv->ring_map = drm_core_findmap(dev, init->ring_offset);
+ dev_priv->ring_map = drm_legacy_findmap(dev, init->ring_offset);
if (!dev_priv->ring_map) {
DRM_ERROR("can not find ring map!\n");
dev->dev_private = (void *)dev_priv;
@@ -1072,7 +1072,7 @@ static int mach64_do_dma_init(struct drm
((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset);
if (!dev_priv->is_pci) {
- drm_core_ioremap(dev_priv->ring_map, dev);
+ drm_legacy_ioremap(dev_priv->ring_map, dev);
if (!dev_priv->ring_map->handle) {
DRM_ERROR("can not ioremap virtual address for"
" descriptor ring\n");
@@ -1082,7 +1082,7 @@ static int mach64_do_dma_init(struct drm
}
dev->agp_buffer_token = init->buffers_offset;
dev->agp_buffer_map =
- drm_core_findmap(dev, init->buffers_offset);
+ drm_legacy_findmap(dev, init->buffers_offset);
if (!dev->agp_buffer_map) {
DRM_ERROR("can not find dma buffer map!\n");
dev->dev_private = (void *)dev_priv;
@@ -1093,7 +1093,7 @@ static int mach64_do_dma_init(struct drm
dev isn't passed all the way though the mach64 - DA */
dev_priv->dev_buffers = dev->agp_buffer_map;
- drm_core_ioremap(dev->agp_buffer_map, dev);
+ drm_legacy_ioremap(dev->agp_buffer_map, dev);
if (!dev->agp_buffer_map->handle) {
DRM_ERROR("can not ioremap virtual address for"
" dma buffer\n");
@@ -1102,7 +1102,7 @@ static int mach64_do_dma_init(struct drm
return -ENOMEM;
}
dev_priv->agp_textures =
- drm_core_findmap(dev, init->agp_textures_offset);
+ drm_legacy_findmap(dev, init->agp_textures_offset);
if (!dev_priv->agp_textures) {
DRM_ERROR("can not find agp texture region!\n");
dev->dev_private = (void *)dev_priv;
@@ -1376,10 +1376,10 @@ int mach64_do_cleanup_dma(struct drm_dev
if (!dev_priv->is_pci) {
if (dev_priv->ring_map)
- drm_core_ioremapfree(dev_priv->ring_map, dev);
+ drm_legacy_ioremapfree(dev_priv->ring_map, dev);
if (dev->agp_buffer_map) {
- drm_core_ioremapfree(dev->agp_buffer_map, dev);
+ drm_legacy_ioremapfree(dev->agp_buffer_map, dev);
dev->agp_buffer_map = NULL;
}
}
diff -urp linux/drivers/gpu/drm/mach64.orig/mach64_drv.c linux/drivers/gpu/drm/mach64/mach64_drv.c
--- linux/drivers/gpu/drm/mach64.orig/mach64_drv.c 2014-11-29 22:01:54.000000000 +0200
+++ linux/drivers/gpu/drm/mach64/mach64_drv.c 2014-11-29 23:14:21.918009653 +0200
@@ -34,6 +34,7 @@
#include "mach64_drv.h"
#include <drm/drm_pciids.h>
+#include <drm/drm_legacy.h>
static struct pci_device_id pciidlist[] = {
mach64_PCI_IDS
@@ -44,7 +45,7 @@ static const struct file_operations mach
.open = drm_open,
.release = drm_release,
.unlocked_ioctl = drm_ioctl,
- .mmap = drm_mmap,
+ .mmap = drm_legacy_mmap,
.poll = drm_poll,
.llseek = noop_llseek,
};
diff -urp linux/drivers/gpu/drm/mach64.orig/mach64_drv.h linux/drivers/gpu/drm/mach64/mach64_drv.h
--- linux/drivers/gpu/drm/mach64.orig/mach64_drv.h 2014-11-29 22:01:54.000000000 +0200
+++ linux/drivers/gpu/drm/mach64/mach64_drv.h 2014-11-29 23:58:20.111491646 +0200
@@ -35,6 +35,8 @@
#ifndef __MACH64_DRV_H__
#define __MACH64_DRV_H__
+#include <drm/drm_legacy.h>
+
/* General customization:
*/
@@ -102,12 +104,12 @@ typedef struct drm_mach64_private {
u32 back_offset_pitch;
u32 depth_offset_pitch;
- drm_local_map_t *sarea;
- drm_local_map_t *fb;
- drm_local_map_t *mmio;
- drm_local_map_t *ring_map;
- drm_local_map_t *dev_buffers; /* this is a pointer to a structure in dev */
- drm_local_map_t *agp_textures;
+ struct drm_local_map *sarea;
+ struct drm_local_map *fb;
+ struct drm_local_map *mmio;
+ struct drm_local_map *ring_map;
+ struct drm_local_map *dev_buffers; /* this is a pointer to a structure in dev */
+ struct drm_local_map *agp_textures;
} drm_mach64_private_t;
extern struct drm_ioctl_desc mach64_ioctls[];
@@ -1,47 +0,0 @@
This moves the .fops to a separate struct as required by kernel-3.3
Signed-off-by: Thomas Backlund <tmb@mageia.org>
b/drivers/gpu/drm/mach64/mach64_drv.c | 23 ++++++++++++-----------
1 file changed, 12 insertions(+), 11 deletions(-)
--- a/drivers/gpu/drm/mach64/mach64_drv.c
+++ b/drivers/gpu/drm/mach64/mach64_drv.c
@@ -39,6 +39,17 @@ static struct pci_device_id pciidlist[]
mach64_PCI_IDS
};
+static const struct file_operations mach64_driver_fops = {
+ .owner = THIS_MODULE,
+ .open = drm_open,
+ .release = drm_release,
+ .unlocked_ioctl = drm_ioctl,
+ .mmap = drm_mmap,
+ .poll = drm_poll,
+ .fasync = drm_fasync,
+ .llseek = noop_llseek,
+};
+
static struct drm_driver driver = {
.driver_features =
DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_HAVE_DMA
@@ -54,17 +65,7 @@ static struct drm_driver driver = {
.reclaim_buffers = drm_core_reclaim_buffers,
.ioctls = mach64_ioctls,
.dma_ioctl = mach64_dma_buffers,
- .fops = {
- .owner = THIS_MODULE,
- .open = drm_open,
- .release = drm_release,
- .unlocked_ioctl = drm_ioctl,
- .mmap = drm_mmap,
- .poll = drm_poll,
- .fasync = drm_fasync,
- .llseek = noop_llseek,
- },
-
+ .fops = &mach64_driver_fops,
.name = DRIVER_NAME,
.desc = DRIVER_DESC,
.date = DRIVER_DATE,
@@ -1,15 +0,0 @@
reclaim_buffers is gone in 3.6
Signed-off-by: Thomas Backlund <tmb@mageia.org>
--- linux/drivers/gpu/drm/mach64/mach64_drv.c.orig 2012-10-17 22:26:58.000000000 +0300
+++ linux/drivers/gpu/drm/mach64/mach64_drv.c 2012-10-17 23:05:10.212566630 +0300
@@ -62,7 +62,6 @@ static struct drm_driver driver = {
.irq_postinstall = mach64_driver_irq_postinstall,
.irq_uninstall = mach64_driver_irq_uninstall,
.irq_handler = mach64_driver_irq_handler,
- .reclaim_buffers = drm_core_reclaim_buffers,
.ioctls = mach64_ioctls,
.dma_ioctl = mach64_dma_buffers,
.fops = &mach64_driver_fops,
@@ -1,61 +0,0 @@
diff -Nurp linux-3.7-rc8/drivers/gpu/drm/mach64.orig/mach64_dma.c linux-3.7-rc8/drivers/gpu/drm/mach64/mach64_dma.c
--- linux-3.7-rc8/drivers/gpu/drm/mach64.orig/mach64_dma.c 2012-12-06 19:50:10.000000000 +0200
+++ linux-3.7-rc8/drivers/gpu/drm/mach64/mach64_dma.c 2012-12-06 20:19:10.590681644 +0200
@@ -34,8 +34,8 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#include "drmP.h"
-#include "drm.h"
+#include <drm/drmP.h>
+#include <drm/drm.h>
#include "mach64_drm.h"
#include "mach64_drv.h"
diff -Nurp linux-3.7-rc8/drivers/gpu/drm/mach64.orig/mach64_drv.c linux-3.7-rc8/drivers/gpu/drm/mach64/mach64_drv.c
--- linux-3.7-rc8/drivers/gpu/drm/mach64.orig/mach64_drv.c 2012-12-06 19:50:10.000000000 +0200
+++ linux-3.7-rc8/drivers/gpu/drm/mach64/mach64_drv.c 2012-12-06 20:20:13.062073838 +0200
@@ -28,12 +28,12 @@
*/
#include <linux/module.h>
-#include "drmP.h"
-#include "drm.h"
+#include <drm/drmP.h>
+#include <drm/drm.h>
#include "mach64_drm.h"
#include "mach64_drv.h"
-#include "drm_pciids.h"
+#include <drm/drm_pciids.h>
static struct pci_device_id pciidlist[] = {
mach64_PCI_IDS
diff -Nurp linux-3.7-rc8/drivers/gpu/drm/mach64.orig/mach64_irq.c linux-3.7-rc8/drivers/gpu/drm/mach64/mach64_irq.c
--- linux-3.7-rc8/drivers/gpu/drm/mach64.orig/mach64_irq.c 2012-12-06 19:50:10.000000000 +0200
+++ linux-3.7-rc8/drivers/gpu/drm/mach64/mach64_irq.c 2012-12-06 20:20:40.192678476 +0200
@@ -35,8 +35,8 @@
* Leif Delgass <ldelgass@retinalburn.net>
*/
-#include "drmP.h"
-#include "drm.h"
+#include <drm/drmP.h>
+#include <drm/drm.h>
#include "mach64_drm.h"
#include "mach64_drv.h"
diff -Nurp linux-3.7-rc8/drivers/gpu/drm/mach64.orig/mach64_state.c linux-3.7-rc8/drivers/gpu/drm/mach64/mach64_state.c
--- linux-3.7-rc8/drivers/gpu/drm/mach64.orig/mach64_state.c 2012-12-06 19:50:10.000000000 +0200
+++ linux-3.7-rc8/drivers/gpu/drm/mach64/mach64_state.c 2012-12-06 20:21:00.783137370 +0200
@@ -30,8 +30,8 @@
* José Fonseca <j_r_fonseca@yahoo.co.uk>
*/
-#include "drmP.h"
-#include "drm.h"
+#include <drm/drmP.h>
+#include <drm/drm.h>
#include "mach64_drm.h"
#include "mach64_drv.h"
@@ -1,20 +0,0 @@
Update mach64 for changes in drm_ioctl done in 2.6.33:
"drm: convert drm_ioctl to unlocked_ioctl" (commit ed8b670)
Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
---
drivers/gpu/drm/mach64/mach64_drv.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff -p -up linux-2.6.33/drivers/gpu/drm/mach64/mach64_drv.c.orig linux-2.6.33/drivers/gpu/drm/mach64/mach64_drv.c
--- linux-2.6.33/drivers/gpu/drm/mach64/mach64_drv.c.orig 2010-03-16 19:27:22.517068880 -0300
+++ linux-2.6.33/drivers/gpu/drm/mach64/mach64_drv.c 2010-03-16 19:27:54.890318416 -0300
@@ -59,7 +59,7 @@ static struct drm_driver driver = {
.owner = THIS_MODULE,
.open = drm_open,
.release = drm_release,
- .ioctl = drm_ioctl,
+ .unlocked_ioctl = drm_ioctl,
.mmap = drm_mmap,
.poll = drm_poll,
.fasync = drm_fasync,
@@ -1,12 +0,0 @@
diff -p -up linux-2.6.32/drivers/gpu/drm/mach64/mach64_dma.c.orig linux-2.6.32/drivers/gpu/drm/mach64/mach64_dma.c
--- linux-2.6.32/drivers/gpu/drm/mach64/mach64_dma.c.orig 2010-01-06 11:35:13.784843304 -0200
+++ linux-2.6.32/drivers/gpu/drm/mach64/mach64_dma.c 2010-01-06 11:37:50.793843502 -0200
@@ -835,7 +835,7 @@ static int mach64_bm_dma_test(struct drm
/* FIXME: get a dma buffer from the freelist here */
DRM_DEBUG("Allocating data memory ...\n");
cpu_addr_dmah =
- drm_pci_alloc(dev, 0x1000, 0x1000, 0xfffffffful);
+ drm_pci_alloc(dev, 0x1000, 0x1000);
if (!cpu_addr_dmah) {
DRM_INFO("data-memory allocation failed!\n");
return -ENOMEM;
@@ -1,97 +0,0 @@
Fix/cleanup mach64 drm module for building with current kernel.
Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
---
drivers/gpu/drm/mach64/mach64_dma.c | 9 +--------
drivers/gpu/drm/mach64/mach64_drv.c | 11 +----------
drivers/gpu/drm/mach64/mach64_state.c | 4 ++--
3 files changed, 4 insertions(+), 20 deletions(-)
diff -p -up linux-2.6.28/drivers/gpu/drm/mach64/mach64_dma.c.orig linux-2.6.28/drivers/gpu/drm/mach64/mach64_dma.c
--- linux-2.6.28/drivers/gpu/drm/mach64/mach64_dma.c.orig 2008-12-10 12:19:14.000000000 -0500
+++ linux-2.6.28/drivers/gpu/drm/mach64/mach64_dma.c 2008-12-10 13:34:19.000000000 -0500
@@ -834,14 +834,8 @@ static int mach64_bm_dma_test(struct drm
/* FIXME: get a dma buffer from the freelist here */
DRM_DEBUG("Allocating data memory ...\n");
-#ifdef __FreeBSD__
- DRM_UNLOCK();
-#endif
cpu_addr_dmah =
drm_pci_alloc(dev, 0x1000, 0x1000, 0xfffffffful);
-#ifdef __FreeBSD__
- DRM_LOCK();
-#endif
if (!cpu_addr_dmah) {
DRM_INFO("data-memory allocation failed!\n");
return -ENOMEM;
@@ -1375,8 +1369,7 @@ int mach64_do_cleanup_dma(struct drm_dev
* may not have been called from userspace and after dev_private
* is freed, it's too late.
*/
- if (dev->irq)
- drm_irq_uninstall(dev);
+ drm_irq_uninstall(dev);
if (dev->dev_private) {
drm_mach64_private_t *dev_priv = dev->dev_private;
diff -p -up linux-2.6.28/drivers/gpu/drm/mach64/mach64_drv.c.orig linux-2.6.28/drivers/gpu/drm/mach64/mach64_drv.c
--- linux-2.6.28/drivers/gpu/drm/mach64/mach64_drv.c.orig 2008-12-10 12:13:13.000000000 -0500
+++ linux-2.6.28/drivers/gpu/drm/mach64/mach64_drv.c 2008-12-10 12:16:54.000000000 -0500
@@ -38,7 +38,6 @@ static struct pci_device_id pciidlist[]
mach64_PCI_IDS
};
-static int probe(struct pci_dev *pdev, const struct pci_device_id *ent);
static struct drm_driver driver = {
.driver_features =
DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_HAVE_DMA
@@ -68,8 +67,6 @@ static struct drm_driver driver = {
.pci_driver = {
.name = DRIVER_NAME,
.id_table = pciidlist,
- .probe = probe,
- .remove = __devexit_p(drm_cleanup_pci),
},
.name = DRIVER_NAME,
@@ -80,16 +77,10 @@ static struct drm_driver driver = {
.patchlevel = DRIVER_PATCHLEVEL,
};
-static int probe(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
- return drm_get_dev(pdev, ent, &driver);
-}
-
-
static int __init mach64_init(void)
{
driver.num_ioctls = mach64_max_ioctl;
- return drm_init(&driver, pciidlist);
+ return drm_init(&driver);
}
static void __exit mach64_exit(void)
diff -p -up linux-2.6.28/drivers/gpu/drm/mach64/mach64_state.c.orig linux-2.6.28/drivers/gpu/drm/mach64/mach64_state.c
--- linux-2.6.28/drivers/gpu/drm/mach64/mach64_state.c.orig 2008-12-10 12:13:13.000000000 -0500
+++ linux-2.6.28/drivers/gpu/drm/mach64/mach64_state.c 2008-12-10 13:38:54.000000000 -0500
@@ -455,7 +455,7 @@ static int mach64_do_get_frames_queued(d
head = ring->head;
start = (MACH64_MAX_QUEUED_FRAMES -
- DRM_MIN(MACH64_MAX_QUEUED_FRAMES, sarea_priv->frames_queued));
+ min(MACH64_MAX_QUEUED_FRAMES, sarea_priv->frames_queued));
if (head == tail) {
sarea_priv->frames_queued = 0;
@@ -895,7 +895,7 @@ int mach64_get_param(struct drm_device *
value = mach64_do_get_frames_queued(dev_priv);
break;
case MACH64_PARAM_IRQ_NR:
- value = dev->irq;
+ value = drm_dev_to_irq(dev);
break;
default:
return -EINVAL;
@@ -1,10 +0,0 @@
--- linux/drivers/gpu/drm/mach64/mach64_drv.c.orig 2011-12-25 00:48:42.814932355 +0200
+++ linux/drivers/gpu/drm/mach64/mach64_drv.c 2011-12-25 00:47:43.393625260 +0200
@@ -27,6 +27,7 @@
* Leif Delgass <ldelgass@retinalburn.net>
*/
+#include <linux/module.h>
#include "drmP.h"
#include "drm.h"
#include "mach64_drm.h"

Some files were not shown because too many files have changed in this diff Show More