Merge pull request #643 from ertugerata/kernel_4_9

Kernel 4.9.35 ok
This commit is contained in:
Ertuğrul Erata
2017-07-02 16:07:04 +03:00
committed by GitHub
158 changed files with 779319 additions and 37199 deletions
+10 -3
View File
@@ -11,7 +11,7 @@
<Summary>Kernel module allowing to switch dedicated graphics card on Optimus laptops</Summary>
<Description>kernel module allowing to switch dedicated graphics card on Optimus laptops</Description>
<BuildDependencies>
<Dependency version="4.9.6">kernel-module-headers</Dependency>
<Dependency version="4.9.35">kernel-module-headers</Dependency>
</BuildDependencies>
<Archive sha1sum="e282ee682d794e3962baa4dead01917c42571e78" type="targz">https://github.com/Bumblebee-Project/bbswitch/archive/v0.8.tar.gz</Archive>
<Patches>
@@ -20,7 +20,7 @@
<Package>
<Name>module-bbswitch</Name>
<RuntimeDependencies>
<Dependency version="4.9.6">kernel</Dependency>
<Dependency version="4.9.35">kernel</Dependency>
</RuntimeDependencies>
<Files>
<Path fileType="library" permanent="true">/lib/modules</Path>
@@ -34,6 +34,13 @@
</Package>
<History>
<Update release="9">
<Date>2017-07-02</Date>
<Version>0.8</Version>
<Comment>Rebuild for new kernel.</Comment>
<Name>Kamil Atlı</Name>
<Email>suvari@pisilinux.org</Email>
</Update>
<Update release="8">
<Date>2017-02-01</Date>
<Version>0.8</Version>
@@ -91,4 +98,4 @@
<Email>ertugrulerata@gmail.com</Email>
</Update>
</History>
</PISI>
</PISI>
+9 -2
View File
@@ -15,7 +15,7 @@
<Archive sha1sum="8acbdbb4ab4ab4123d1773b616904798fbef9277" type="targz" target="i686">https://docs.broadcom.com/docs-and-downloads/docs/linux_sta/hybrid-v35-nodebug-pcoem-6_30_223_271.tar.gz</Archive>
<Archive sha1sum="1f568bb989d175813c5631c6629d9479eae6f3be" type="targz" target="x86_64">https://docs.broadcom.com/docs-and-downloads/docs/linux_sta/hybrid-v35_64-nodebug-pcoem-6_30_223_271.tar.gz</Archive>
<BuildDependencies>
<Dependency version="4.9.6">kernel-module-headers</Dependency>
<Dependency version="4.9.35">kernel-module-headers</Dependency>
</BuildDependencies>
<Patches>
<Patch level="1">patch/license.patch</Patch>
@@ -28,7 +28,7 @@
<Package>
<Name>module-broadcom-wl</Name>
<RuntimeDependencies>
<Dependency version="4.9.6">kernel</Dependency>
<Dependency version="4.9.35">kernel</Dependency>
<Dependency release="current">module-broadcom-wl-userspace</Dependency>
</RuntimeDependencies>
<Files>
@@ -57,6 +57,13 @@
</Package>
<History>
<Update release="9">
<Date>2017-07-02</Date>
<Version>6.30.223.271</Version>
<Comment>Rebuild for new kernel.</Comment>
<Name>Kamil Atlı</Name>
<Email>suvari@pisilinux.org</Email>
</Update>
<Update release="8">
<Date>2017-02-01</Date>
<Version>6.30.223.271</Version>
@@ -14,14 +14,14 @@
<Description>This package provides the kernel modules needed for mouse integration and shared folder support between VirtualBox host and guest systems.</Description>
<Archive sha1sum="87b355193a306ed5516e8d348f7eb83854e08ac1" type="tarxz">https://sourceforge.net/projects/pisilinux/files/source/module-virtualbox-guest-5.1.14.tar.xz</Archive>
<BuildDependencies>
<Dependency version="4.9.6">kernel-module-headers</Dependency>
<Dependency version="4.9.35">kernel-module-headers</Dependency>
</BuildDependencies>
</Source>
<Package>
<Name>module-virtualbox-guest</Name>
<RuntimeDependencies>
<Dependency version="4.9.6">kernel</Dependency>
<Dependency version="4.9.35">kernel</Dependency>
<Dependency>baselayout</Dependency>
<Dependency version="current">module-virtualbox-guest-userspace</Dependency>
</RuntimeDependencies>
@@ -52,6 +52,13 @@
</Package>
<History>
<Update release="15">
<Date>2017-07-02</Date>
<Version>5.1.14</Version>
<Comment>Rebuild for new kernel.</Comment>
<Name>Kamil Atlı</Name>
<Email>suvari@pisilinux.org</Email>
</Update>
<Update release="14">
<Date>2017-02-01</Date>
<Version>5.1.14</Version>
@@ -151,4 +158,4 @@
<Email>ertugrulerata@gmail.com</Email>
</Update>
</History>
</PISI>
</PISI>
+10 -3
View File
@@ -14,7 +14,7 @@
<Description>This package provides the kernel support for VirtualBox.</Description>
<Archive sha1sum="7489ae3b501407d5ca2826e6ef1d5b2000e06154" type="tarxz">https://sourceforge.net/projects/pisilinux/files/source/module-virtualbox-5.1.14.tar.xz</Archive>
<BuildDependencies>
<Dependency version="4.9.6">kernel-module-headers</Dependency>
<Dependency version="4.9.35">kernel-module-headers</Dependency>
</BuildDependencies>
<!--Patches>
<Patch>vbox_linux-4.3.diff</Patch>
@@ -24,7 +24,7 @@
<Package>
<Name>module-virtualbox</Name>
<RuntimeDependencies>
<Dependency version="4.9.6">kernel</Dependency>
<Dependency version="4.9.35">kernel</Dependency>
<Dependency version="current">module-virtualbox-userspace</Dependency>
</RuntimeDependencies>
<Files>
@@ -50,6 +50,13 @@
</Package>
<History>
<Update release="15">
<Date>2017-07-02</Date>
<Version>5.1.14</Version>
<Comment>Rebuild for new kernel.</Comment>
<Name>Kamil Atlı</Name>
<Email>suvari@pisilinux.org</Email>
</Update>
<Update release="14">
<Date>2017-02-01</Date>
<Version>5.1.14</Version>
@@ -149,4 +156,4 @@
<Email>ertugrulerata@gmail.com</Email>
</Update>
</History>
</PISI>
</PISI>
+9 -2
View File
@@ -15,7 +15,7 @@
<Description>module-ndiswrapper allows you to use Windows XP drivers for WLAN cards without proper Linux drivers.</Description>
<Archive sha1sum="20998237cf6d37b86391dc8736c10031110db578" type="targz">http://download.sourceforge.net/ndiswrapper/ndiswrapper-1.60.tar.gz</Archive>
<BuildDependencies>
<Dependency version="4.9.6">kernel-module-headers</Dependency>
<Dependency version="4.9.35">kernel-module-headers</Dependency>
</BuildDependencies>
<Patches>
<Patch>upstream.patch</Patch>
@@ -25,7 +25,7 @@
<Package>
<Name>ndiswrapper</Name>
<RuntimeDependencies>
<Dependency version="4.9.6">kernel</Dependency>
<Dependency version="4.9.35">kernel</Dependency>
</RuntimeDependencies>
<Files>
<Path fileType="library" permanent="true">/lib/modules</Path>
@@ -41,6 +41,13 @@
</Package>
<History>
<Update release="8">
<Date>2017-07-02</Date>
<Version>1.60</Version>
<Comment>Rebuild for new kernel.</Comment>
<Name>PisiLinux Community</Name>
<Email>admin@pisilinux.org</Email>
</Update>
<Update release="7">
<Date>2017-02-07</Date>
<Version>1.60</Version>
-24
View File
@@ -34,27 +34,3 @@ def install():
# Generate some module lists to use within mkinitramfs
shelltools.system("./generate-module-list %s/lib/modules/%s" % (get.installDIR(), kerneltools.__getSuffix()))
#mkinitcpio default config
pisitools.dodir("/etc/mkinitcpio.d")
shelltools.touch("linux.preset")
shelltools.echo("linux.preset", "# mkinitcpio preset file for the 'linux' package\n" +
'ALL_config="/etc/mkinitcpio.conf"\n'+
'ALL_kver="/boot/kernel-%s"\n\n'% get.srcVERSION() +
"PRESETS=('default' 'fallback') \n\n" +
'#default_config="/etc/mkinitcpio.conf"\n' +
'default_image="/boot/initramfs-%s.img"\n'% get.srcVERSION() +
'#default_options=""\n\n' +
'#fallback_config="/etc/mkinitcpio.conf"\n'+
'fallback_image="/boot/initramfs-%s-fallback.img"\n'% get.srcVERSION() +
'fallback_options="-S autodetect"\n')
pisitools.insinto("/etc/mkinitcpio.d", "linux.preset")
@@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
# Linux/x86_64 4.9.6 Kernel Configuration
# Linux/x86_64 4.9.35 Kernel Configuration
#
CONFIG_64BIT=y
CONFIG_X86_64=y
@@ -373,8 +373,7 @@ CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
CONFIG_CFQ_GROUP_IOSCHED=y
CONFIG_IOSCHED_BFQ=m
# CONFIG_BFQ_GROUP_IOSCHED is not set
# CONFIG_IOSCHED_BFQ is not set
CONFIG_DEFAULT_DEADLINE=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
@@ -6935,7 +6934,8 @@ CONFIG_SBITMAP=y
#
# Unofficial 3rd party kernel additions
#
CONFIG_NDISWRAPPER=m
CONFIG_VIAHSS=m
CONFIG_RTL8723BS=m
CONFIG_WLAN_SDIO=y
CONFIG_NDISWRAPPER=m
CONFIG_VIAHSS=m
# CONFIG_RTL8812AU is not set
@@ -0,0 +1,86 @@
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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large Load Diff
@@ -1,70 +0,0 @@
From ca45663819accf038291dbe2d67ed66dc48d714c Mon Sep 17 00:00:00 2001
From: Thomas Backlund <tmb@mageia.org>
Date: Sun, 29 Nov 2015 14:44:22 +0200
Subject: [PATCH] Revert "x86/mm/mtrr: Remove kernel internal MTRR interfaces:
unexport mtrr_add() and mtrr_del()"
This reverts commit 2baa891e42d84159b693eadd44f6fe1486285bdc.
It currently breaks nvidia304 driver.
Signed-of-by: Thomas Backlund <tmb@mageia.org>
---
Documentation/x86/mtrr.txt | 20 ++++----------------
arch/x86/kernel/cpu/mtrr/main.c | 2 ++
2 files changed, 6 insertions(+), 16 deletions(-)
diff --git a/Documentation/x86/mtrr.txt b/Documentation/x86/mtrr.txt
index dc3e703..860bc3a 100644
--- a/Documentation/x86/mtrr.txt
+++ b/Documentation/x86/mtrr.txt
@@ -6,22 +6,10 @@ Luis R. Rodriguez <mcgrof@do-not-panic.com> - April 9, 2015
===============================================================================
Phasing out MTRR use
-MTRR use is replaced on modern x86 hardware with PAT. Direct MTRR use by
-drivers on Linux is now completely phased out, device drivers should use
-arch_phys_wc_add() in combination with ioremap_wc() to make MTRR effective on
-non-PAT systems while a no-op but equally effective on PAT enabled systems.
-
-Even if Linux does not use MTRRs directly, some x86 platform firmware may still
-set up MTRRs early before booting the OS. They do this as some platform
-firmware may still have implemented access to MTRRs which would be controlled
-and handled by the platform firmware directly. An example of platform use of
-MTRRs is through the use of SMI handlers, one case could be for fan control,
-the platform code would need uncachable access to some of its fan control
-registers. Such platform access does not need any Operating System MTRR code in
-place other than mtrr_type_lookup() to ensure any OS specific mapping requests
-are aligned with platform MTRR setup. If MTRRs are only set up by the platform
-firmware code though and the OS does not make any specific MTRR mapping
-requests mtrr_type_lookup() should always return MTRR_TYPE_INVALID.
+MTRR use is replaced on modern x86 hardware with PAT. Over time the only type
+of effective MTRR that is expected to be supported will be for write-combining.
+As MTRR use is phased out device drivers should use arch_phys_wc_add() to make
+MTRR effective on non-PAT systems while a no-op on PAT enabled systems.
For details refer to Documentation/x86/pat.txt.
diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c
index f891b47..e7ed0d8 100644
--- a/arch/x86/kernel/cpu/mtrr/main.c
+++ b/arch/x86/kernel/cpu/mtrr/main.c
@@ -448,6 +448,7 @@ int mtrr_add(unsigned long base, unsigned long size, unsigned int type,
return mtrr_add_page(base >> PAGE_SHIFT, size >> PAGE_SHIFT, type,
increment);
}
+EXPORT_SYMBOL(mtrr_add);
/**
* mtrr_del_page - delete a memory type region
@@ -536,6 +537,7 @@ int mtrr_del(int reg, unsigned long base, unsigned long size)
return -EINVAL;
return mtrr_del_page(reg, base >> PAGE_SHIFT, size >> PAGE_SHIFT);
}
+EXPORT_SYMBOL(mtrr_del);
/**
* arch_phys_wc_add - add a WC MTRR and handle errors if PAT is unavailable
--
2.3.10
@@ -0,0 +1,192 @@
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,9 +1,13 @@
From 3e3791c0b4ef3b2067f8454e58001af8e3da3840 Mon Sep 17 00:00:00 2001
From 0432a5c7bfc4a11531c1e58f574c733a2552f149 Mon Sep 17 00:00:00 2001
From: Paolo Valente <paolo.valente@linaro.org>
Date: Tue, 17 May 2016 08:28:04 +0200
Subject: [PATCH 4/4] Turn into BFQ-v8r6 for 4.9.0
Subject: [PATCH 4/4] Turn into BFQ-v8r7 for 4.9.0
CHANGELOG from v8r4 to v8r6
CHANGELOG from v8r4 to v8r7
BFQ v8r7
BUGFIX: make BFQ compile also without hierarchical support
BFQ v8r6
@@ -125,9 +129,9 @@ Signed-off-by: Paolo Valente <paolo.valente@linaro.org>
block/Kconfig.iosched | 18 +-
block/bfq-cgroup.c | 501 +++---
block/bfq-iosched.c | 3278 ++++++++++++++++++++++-------------
block/bfq-sched.c | 1270 +++++++++++---
block/bfq-sched.c | 1288 +++++++++++---
block/bfq.h | 800 +++++----
7 files changed, 4310 insertions(+), 2089 deletions(-)
7 files changed, 4320 insertions(+), 2097 deletions(-)
create mode 100644 Documentation/block/bfq-iosched.txt
diff --git a/Documentation/block/00-INDEX b/Documentation/block/00-INDEX
@@ -1601,7 +1605,7 @@ index 0367996..bbaecd0 100644
static struct bfq_group *
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
index cf3e9b1..0f9cd53 100644
index cf3e9b1..2a2c130 100644
--- a/block/bfq-iosched.c
+++ b/block/bfq-iosched.c
@@ -1,5 +1,5 @@
@@ -6201,7 +6205,7 @@ index cf3e9b1..0f9cd53 100644
-
- if (bfq_timeout_async == 0)
- bfq_timeout_async = 1;
+ char msg[60] = "BFQ I/O-scheduler: v8r6";
+ char msg[60] = "BFQ I/O-scheduler: v8r7";
#ifdef CONFIG_BFQ_GROUP_IOSCHED
ret = blkcg_policy_register(&blkcg_policy_bfq);
@@ -6265,10 +6269,10 @@ index cf3e9b1..0f9cd53 100644
return 0;
diff --git a/block/bfq-sched.c b/block/bfq-sched.c
index a5ed694..4af77f4 100644
index a5ed694..797bce7 100644
--- a/block/bfq-sched.c
+++ b/block/bfq-sched.c
@@ -7,28 +7,46 @@
@@ -7,28 +7,166 @@
* Copyright (C) 2008 Fabio Checconi <fabio@gandalf.sssup.it>
* Paolo Valente <paolo.valente@unimore.it>
*
@@ -6276,8 +6280,8 @@ index a5ed694..4af77f4 100644
+ * Copyright (C) 2015 Paolo Valente <paolo.valente@unimore.it>
+ *
+ * Copyright (C) 2016 Paolo Valente <paolo.valente@linaro.org>
*/
+ */
+
+static struct bfq_group *bfqq_group(struct bfq_queue *bfqq);
+
+/**
@@ -6292,63 +6296,17 @@ index a5ed694..4af77f4 100644
+ return (s64)(a - b) > 0;
+}
+
#ifdef CONFIG_BFQ_GROUP_IOSCHED
-#define for_each_entity(entity) \
+/* both next loops stop at one of the child entities of the root group */
+#define for_each_entity(entity) \
for (; entity ; entity = entity->parent)
#define for_each_entity_safe(entity, parent) \
for (; entity && ({ parent = entity->parent; 1; }); entity = parent)
-static struct bfq_entity *bfq_lookup_next_entity(struct bfq_sched_data *sd,
- int extract,
- struct bfq_data *bfqd);
-
-static struct bfq_group *bfqq_group(struct bfq_queue *bfqq);
+static struct bfq_entity *bfq_lookup_next_entity(struct bfq_sched_data *sd);
-static void bfq_update_budget(struct bfq_entity *next_in_service)
+/*
+ * Returns true if this budget changes may let next_in_service->parent
+ * become the next_in_service entity for its parent entity.
+ */
+static bool bfq_update_parent_budget(struct bfq_entity *next_in_service)
{
struct bfq_entity *bfqg_entity;
struct bfq_group *bfqg;
struct bfq_sched_data *group_sd;
+ bool ret = false;
BUG_ON(!next_in_service);
@@ -41,39 +59,134 @@ static void bfq_update_budget(struct bfq_entity *next_in_service)
* as it must never become an in-service entity.
*/
bfqg_entity = bfqg->my_entity;
- if (bfqg_entity)
+ if (bfqg_entity) {
+ if (bfqg_entity->budget > next_in_service->budget)
+ ret = true;
bfqg_entity->budget = next_in_service->budget;
+ }
+
+ return ret;
}
-static int bfq_update_next_in_service(struct bfq_sched_data *sd)
+static struct bfq_entity *bfq_root_active_entity(struct rb_root *tree)
{
- struct bfq_entity *next_in_service;
+{
+ struct rb_node *node = tree->rb_node;
- if (sd->in_service_entity)
- /* will update/requeue at the end of service */
- return 0;
+
+ return rb_entry(node, struct bfq_entity, rb_node);
+}
+
+static struct bfq_entity *bfq_lookup_next_entity(struct bfq_sched_data *sd);
+
+static bool bfq_update_parent_budget(struct bfq_entity *next_in_service);
+
+/**
+ * bfq_update_next_in_service - update sd->next_in_service
+ * @sd: sched_data for which to perform the update.
@@ -6371,20 +6329,15 @@ index a5ed694..4af77f4 100644
+ * Returns true if sd->next_in_service changes in such a way that
+ * entity->parent may become the next_in_service for its parent
+ * entity.
+ */
*/
+static bool bfq_update_next_in_service(struct bfq_sched_data *sd,
+ struct bfq_entity *new_entity)
+{
+ struct bfq_entity *next_in_service = sd->next_in_service;
+ struct bfq_queue *bfqq;
+ bool parent_sched_may_change = false;
/*
- * NOTE: this can be improved in many ways, such as returning
- * 1 (and thus propagating upwards the update) only when the
- * budget changes, or caching the bfqq that will be scheduled
- * next from this subtree. By now we worry more about
- * correctness than about performance...
+
+ /*
+ * If this update is triggered by the activation, requeueing
+ * or repositiong of an entity that does not coincide with
+ * sd->next_in_service, then a full lookup in the active tree
@@ -6395,8 +6348,7 @@ index a5ed694..4af77f4 100644
+ * finish time than sd->next_in_service. If this compound
+ * condition holds, then the new entity becomes the new
+ * next_in_service. Otherwise no change is needed.
*/
- next_in_service = bfq_lookup_next_entity(sd, 0, NULL);
+ */
+ if (new_entity && new_entity != sd->next_in_service) {
+ /*
+ * Flag used to decide whether to replace
@@ -6445,54 +6397,160 @@ index a5ed694..4af77f4 100644
+ bfq_update_parent_budget(next_in_service);
+ }
+
sd->next_in_service = next_in_service;
- if (next_in_service)
- bfq_update_budget(next_in_service);
+ sd->next_in_service = next_in_service;
+
+ if (!next_in_service)
+ return parent_sched_may_change;
- return 1;
-}
+ bfqq = bfq_entity_to_bfqq(next_in_service);
+ if (bfqq)
+ bfq_log_bfqq(bfqq->bfqd, bfqq,
+ "update_next_in_service: chosen this queue");
+#ifdef CONFIG_BFQ_GROUP_IOSCHED
#ifdef CONFIG_BFQ_GROUP_IOSCHED
-#define for_each_entity(entity) \
+ else {
+ struct bfq_group *bfqg =
+ container_of(next_in_service,
+ struct bfq_group, entity);
-static void bfq_check_next_in_service(struct bfq_sched_data *sd,
- struct bfq_entity *entity)
-{
- BUG_ON(sd->next_in_service != entity);
+
+ bfq_log_bfqg((struct bfq_data *)bfqg->bfqd, bfqg,
+ "update_next_in_service: chosen this entity");
+ }
+#endif
+ return parent_sched_may_change;
}
+}
+
#else
#define for_each_entity(entity) \
for (; entity ; entity = NULL)
@@ -86,12 +199,7 @@ static int bfq_update_next_in_service(struct bfq_sched_data *sd)
return 0;
+#ifdef CONFIG_BFQ_GROUP_IOSCHED
+/* both next loops stop at one of the child entities of the root group */
+#define for_each_entity(entity) \
for (; entity ; entity = entity->parent)
#define for_each_entity_safe(entity, parent) \
for (; entity && ({ parent = entity->parent; 1; }); entity = parent)
-
-static struct bfq_entity *bfq_lookup_next_entity(struct bfq_sched_data *sd,
- int extract,
- struct bfq_data *bfqd);
-
-static struct bfq_group *bfqq_group(struct bfq_queue *bfqq);
-
-static void bfq_update_budget(struct bfq_entity *next_in_service)
+/*
+ * Returns true if this budget changes may let next_in_service->parent
+ * become the next_in_service entity for its parent entity.
+ */
+static bool bfq_update_parent_budget(struct bfq_entity *next_in_service)
{
struct bfq_entity *bfqg_entity;
struct bfq_group *bfqg;
struct bfq_sched_data *group_sd;
+ bool ret = false;
BUG_ON(!next_in_service);
@@ -41,60 +179,68 @@ static void bfq_update_budget(struct bfq_entity *next_in_service)
* as it must never become an in-service entity.
*/
bfqg_entity = bfqg->my_entity;
- if (bfqg_entity)
+ if (bfqg_entity) {
+ if (bfqg_entity->budget > next_in_service->budget)
+ ret = true;
bfqg_entity->budget = next_in_service->budget;
+ }
+
+ return ret;
}
-static int bfq_update_next_in_service(struct bfq_sched_data *sd)
+/*
+ * This function tells whether entity stops being a candidate for next
+ * service, according to the following logic.
+ *
+ * This function is invoked for an entity that is about to be set in
+ * service. If such an entity is a queue, then the entity is no longer
+ * a candidate for next service (i.e, a candidate entity to serve
+ * after the in-service entity is expired). The function then returns
+ * true.
+ *
+ * In contrast, the entity could stil be a candidate for next service
+ * if it is not a queue, and has more than one child. In fact, even if
+ * one of its children is about to be set in service, other children
+ * may still be the next to serve. As a consequence, a non-queue
+ * entity is not a candidate for next-service only if it has only one
+ * child. And only if this condition holds, then the function returns
+ * true for a non-queue entity.
+ */
+static bool bfq_no_longer_next_in_service(struct bfq_entity *entity)
{
- struct bfq_entity *next_in_service;
+ struct bfq_group *bfqg;
- if (sd->in_service_entity)
- /* will update/requeue at the end of service */
- return 0;
+ if (bfq_entity_to_bfqq(entity))
+ return true;
- /*
- * NOTE: this can be improved in many ways, such as returning
- * 1 (and thus propagating upwards the update) only when the
- * budget changes, or caching the bfqq that will be scheduled
- * next from this subtree. By now we worry more about
- * correctness than about performance...
- */
- next_in_service = bfq_lookup_next_entity(sd, 0, NULL);
- sd->next_in_service = next_in_service;
+ bfqg = container_of(entity, struct bfq_group, entity);
- if (next_in_service)
- bfq_update_budget(next_in_service);
+ BUG_ON(bfqg == ((struct bfq_data *)(bfqg->bfqd))->root_group);
+ BUG_ON(bfqg->active_entities == 0);
+ if (bfqg->active_entities == 1)
+ return true;
- return 1;
+ return false;
}
-static void bfq_check_next_in_service(struct bfq_sched_data *sd,
- struct bfq_entity *entity)
-{
- BUG_ON(sd->next_in_service != entity);
-}
-
-static void bfq_update_budget(struct bfq_entity *next_in_service)
+static void bfq_update_parent_budget(struct bfq_entity *next_in_service)
-#else
+#else /* CONFIG_BFQ_GROUP_IOSCHED */
#define for_each_entity(entity) \
for (; entity ; entity = NULL)
#define for_each_entity_safe(entity, parent) \
for (parent = NULL; entity ; entity = parent)
-static int bfq_update_next_in_service(struct bfq_sched_data *sd)
+static bool bfq_update_parent_budget(struct bfq_entity *next_in_service)
{
- return 0;
+ return false;
}
#endif
@@ -105,18 +213,6 @@ static void bfq_update_budget(struct bfq_entity *next_in_service)
-static void bfq_check_next_in_service(struct bfq_sched_data *sd,
- struct bfq_entity *entity)
+static bool bfq_no_longer_next_in_service(struct bfq_entity *entity)
{
+ return true;
}
-static void bfq_update_budget(struct bfq_entity *next_in_service)
-{
-}
-#endif
+#endif /* CONFIG_BFQ_GROUP_IOSCHED */
/*
* Shift for timestamp calculations. This actually limits the maximum
@@ -105,18 +251,6 @@ static void bfq_update_budget(struct bfq_entity *next_in_service)
*/
#define WFQ_SERVICE_SHIFT 22
@@ -6511,7 +6569,7 @@ index a5ed694..4af77f4 100644
static struct bfq_queue *bfq_entity_to_bfqq(struct bfq_entity *entity)
{
struct bfq_queue *bfqq = NULL;
@@ -151,20 +247,36 @@ static u64 bfq_delta(unsigned long service, unsigned long weight)
@@ -151,20 +285,36 @@ static u64 bfq_delta(unsigned long service, unsigned long weight)
static void bfq_calc_finish(struct bfq_entity *entity, unsigned long service)
{
struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity);
@@ -6550,7 +6608,7 @@ index a5ed694..4af77f4 100644
}
}
@@ -293,10 +405,26 @@ static void bfq_update_min(struct bfq_entity *entity, struct rb_node *node)
@@ -293,10 +443,26 @@ static void bfq_update_min(struct bfq_entity *entity, struct rb_node *node)
static void bfq_update_active_node(struct rb_node *node)
{
struct bfq_entity *entity = rb_entry(node, struct bfq_entity, rb_node);
@@ -6577,7 +6635,7 @@ index a5ed694..4af77f4 100644
}
/**
@@ -386,8 +514,6 @@ static void bfq_active_insert(struct bfq_service_tree *st,
@@ -386,8 +552,6 @@ static void bfq_active_insert(struct bfq_service_tree *st,
BUG_ON(!bfqg);
BUG_ON(!bfqd);
bfqg->active_entities++;
@@ -6586,7 +6644,7 @@ index a5ed694..4af77f4 100644
}
#endif
}
@@ -399,7 +525,7 @@ static void bfq_active_insert(struct bfq_service_tree *st,
@@ -399,7 +563,7 @@ static void bfq_active_insert(struct bfq_service_tree *st,
static unsigned short bfq_ioprio_to_weight(int ioprio)
{
BUG_ON(ioprio < 0 || ioprio >= IOPRIO_BE_NR);
@@ -6595,7 +6653,7 @@ index a5ed694..4af77f4 100644
}
/**
@@ -422,9 +548,9 @@ static void bfq_get_entity(struct bfq_entity *entity)
@@ -422,9 +586,9 @@ static void bfq_get_entity(struct bfq_entity *entity)
struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity);
if (bfqq) {
@@ -6607,7 +6665,7 @@ index a5ed694..4af77f4 100644
}
}
@@ -499,10 +625,6 @@ static void bfq_active_extract(struct bfq_service_tree *st,
@@ -499,10 +663,6 @@ static void bfq_active_extract(struct bfq_service_tree *st,
BUG_ON(!bfqd);
BUG_ON(!bfqg->active_entities);
bfqg->active_entities--;
@@ -6618,7 +6676,7 @@ index a5ed694..4af77f4 100644
}
#endif
}
@@ -547,12 +669,12 @@ static void bfq_forget_entity(struct bfq_service_tree *st,
@@ -547,12 +707,12 @@ static void bfq_forget_entity(struct bfq_service_tree *st,
BUG_ON(!entity->on_st);
@@ -6633,7 +6691,7 @@ index a5ed694..4af77f4 100644
bfq_put_queue(bfqq);
}
}
@@ -602,7 +724,7 @@ __bfq_entity_update_weight_prio(struct bfq_service_tree *old_st,
@@ -602,7 +762,7 @@ __bfq_entity_update_weight_prio(struct bfq_service_tree *old_st,
if (entity->prio_changed) {
struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity);
@@ -6642,7 +6700,7 @@ index a5ed694..4af77f4 100644
struct bfq_data *bfqd = NULL;
struct rb_root *root;
#ifdef CONFIG_BFQ_GROUP_IOSCHED
@@ -630,7 +752,10 @@ __bfq_entity_update_weight_prio(struct bfq_service_tree *old_st,
@@ -630,7 +790,10 @@ __bfq_entity_update_weight_prio(struct bfq_service_tree *old_st,
entity->new_weight > BFQ_MAX_WEIGHT) {
pr_crit("update_weight_prio: new_weight %d\n",
entity->new_weight);
@@ -6654,7 +6712,7 @@ index a5ed694..4af77f4 100644
}
entity->orig_weight = entity->new_weight;
if (bfqq)
@@ -661,6 +786,13 @@ __bfq_entity_update_weight_prio(struct bfq_service_tree *old_st,
@@ -661,6 +824,13 @@ __bfq_entity_update_weight_prio(struct bfq_service_tree *old_st,
* associated with its new weight.
*/
if (prev_weight != new_weight) {
@@ -6668,7 +6726,7 @@ index a5ed694..4af77f4 100644
root = bfqq ? &bfqd->queue_weights_tree :
&bfqd->group_weights_tree;
bfq_weights_tree_remove(bfqd, entity, root);
@@ -707,7 +839,7 @@ static void bfq_bfqq_served(struct bfq_queue *bfqq, int served)
@@ -707,7 +877,7 @@ static void bfq_bfqq_served(struct bfq_queue *bfqq, int served)
st = bfq_entity_service_tree(entity);
entity->service += served;
@@ -6677,7 +6735,7 @@ index a5ed694..4af77f4 100644
BUG_ON(st->wsum == 0);
st->vtime += bfq_delta(served, st->wsum);
@@ -716,170 +848,419 @@ static void bfq_bfqq_served(struct bfq_queue *bfqq, int served)
@@ -716,170 +886,419 @@ static void bfq_bfqq_served(struct bfq_queue *bfqq, int served)
#ifdef CONFIG_BFQ_GROUP_IOSCHED
bfqg_stats_set_start_empty_time(bfqq_group(bfqq));
#endif
@@ -6731,17 +6789,17 @@ index a5ed694..4af77f4 100644
+ if (time_ms > 0 && time_ms < timeout_ms)
+ tot_serv_to_charge =
+ (bfqd->bfq_max_budget * time_ms) / timeout_ms;
+
- bfq_log_bfqq(bfqq->bfqd, bfqq, "charge_full_budget");
+ if (tot_serv_to_charge < entity->service)
+ tot_serv_to_charge = entity->service;
- bfq_log_bfqq(bfqq->bfqd, bfqq, "charge_full_budget");
- bfq_bfqq_served(bfqq, entity->budget - entity->service);
+ bfq_log_bfqq(bfqq->bfqd, bfqq,
+ "charge_time: %lu/%u ms, %d/%d/%d sectors",
+ time_ms, timeout_ms, entity->service,
+ tot_serv_to_charge, entity->budget);
- bfq_bfqq_served(bfqq, entity->budget - entity->service);
+
+ /* Increase budget to avoid inconsistencies */
+ if (tot_serv_to_charge > entity->budget)
+ entity->budget = tot_serv_to_charge;
@@ -6948,19 +7006,20 @@ index a5ed694..4af77f4 100644
- * @entity: the entity to activate.
+ * __bfq_requeue_entity - handle requeueing or repositioning of an entity.
+ * @entity: the entity being requeued or repositioned.
*
- * Activate @entity and all the entities on the path from it to the root.
+ *
+ * Requeueing is needed if this entity stops being served, which
+ * happens if a leaf descendant entity has expired. On the other hand,
+ * repositioning is needed if the next_inservice_entity for the child
+ * entity has changed. See the comments inside the function for
+ * details.
+ *
*
- * Activate @entity and all the entities on the path from it to the root.
+ * Basically, this function: 1) removes entity from its active tree if
+ * present there, 2) updates the timestamps of entity and 3) inserts
+ * entity back into its active tree (in the new, right position for
+ * the new values of the timestamps).
+ */
*/
-static void bfq_activate_entity(struct bfq_entity *entity)
+static void __bfq_requeue_entity(struct bfq_entity *entity)
+{
+ struct bfq_sched_data *sd = entity->sched_data;
@@ -7065,8 +7124,7 @@ index a5ed694..4af77f4 100644
+ * @requeue: true if this is a requeue, which implies that bfqq is
+ * being expired; thus ALL its ancestors stop being served and must
+ * therefore be requeued
*/
-static void bfq_activate_entity(struct bfq_entity *entity)
+ */
+static void bfq_activate_requeue_entity(struct bfq_entity *entity,
+ bool non_blocking_wait_rq,
+ bool requeue)
@@ -7186,7 +7244,7 @@ index a5ed694..4af77f4 100644
{
struct bfq_sched_data *sd;
struct bfq_entity *parent;
@@ -887,63 +1268,153 @@ static void bfq_deactivate_entity(struct bfq_entity *entity, int requeue)
@@ -887,63 +1306,154 @@ static void bfq_deactivate_entity(struct bfq_entity *entity, int requeue)
for_each_entity_safe(entity, parent) {
sd = entity->sched_data;
@@ -7309,7 +7367,8 @@ index a5ed694..4af77f4 100644
+ if (!bfq_update_next_in_service(sd, entity) &&
+ !expiration)
+ /*
+ * next_in_service unchanged, and no
+ * next_in_service unchanged or not causing
+ * any change in entity->parent->sd, and no
+ * requeueing needed for expiration: stop
+ * here.
+ */
@@ -7339,13 +7398,13 @@ index a5ed694..4af77f4 100644
- struct bfq_entity *entry;
- struct rb_node *node = st->active.rb_node;
+ struct bfq_entity *root_entity = bfq_root_active_entity(&st->active);
+
+ if (bfq_gt(root_entity->min_start, st->vtime)) {
+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(root_entity);
- entry = rb_entry(node, struct bfq_entity, rb_node);
- if (bfq_gt(entry->min_start, st->vtime)) {
- st->vtime = entry->min_start;
+ if (bfq_gt(root_entity->min_start, st->vtime)) {
+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(root_entity);
+
+ if (bfqq)
+ bfq_log_bfqq(bfqq->bfqd, bfqq,
+ "calc_vtime_jump: new value %llu",
@@ -7373,7 +7432,7 @@ index a5ed694..4af77f4 100644
bfq_forget_idle(st);
}
}
@@ -952,6 +1423,7 @@ static void bfq_update_vtime(struct bfq_service_tree *st)
@@ -952,6 +1462,7 @@ static void bfq_update_vtime(struct bfq_service_tree *st)
* bfq_first_active_entity - find the eligible entity with
* the smallest finish time
* @st: the service tree to select from.
@@ -7381,7 +7440,7 @@ index a5ed694..4af77f4 100644
*
* This function searches the first schedulable entity, starting from the
* root of the tree and going on the left every time on this side there is
@@ -959,7 +1431,8 @@ static void bfq_update_vtime(struct bfq_service_tree *st)
@@ -959,7 +1470,8 @@ static void bfq_update_vtime(struct bfq_service_tree *st)
* the right is followed only if a) the left subtree contains no eligible
* entities and b) no eligible entity has been found yet.
*/
@@ -7391,7 +7450,7 @@ index a5ed694..4af77f4 100644
{
struct bfq_entity *entry, *first = NULL;
struct rb_node *node = st->active.rb_node;
@@ -967,15 +1440,15 @@ static struct bfq_entity *bfq_first_active_entity(struct bfq_service_tree *st)
@@ -967,15 +1479,15 @@ static struct bfq_entity *bfq_first_active_entity(struct bfq_service_tree *st)
while (node) {
entry = rb_entry(node, struct bfq_entity, rb_node);
left:
@@ -7410,7 +7469,7 @@ index a5ed694..4af77f4 100644
node = node->rb_left;
goto left;
}
@@ -993,31 +1466,84 @@ static struct bfq_entity *bfq_first_active_entity(struct bfq_service_tree *st)
@@ -993,31 +1505,84 @@ static struct bfq_entity *bfq_first_active_entity(struct bfq_service_tree *st)
* __bfq_lookup_next_entity - return the first eligible entity in @st.
* @st: the service tree.
*
@@ -7510,7 +7569,7 @@ index a5ed694..4af77f4 100644
return entity;
}
@@ -1025,50 +1551,118 @@ static struct bfq_entity *__bfq_lookup_next_entity(struct bfq_service_tree *st,
@@ -1025,50 +1590,81 @@ static struct bfq_entity *__bfq_lookup_next_entity(struct bfq_service_tree *st,
/**
* bfq_lookup_next_entity - return the first eligible entity in @sd.
* @sd: the sched_data.
@@ -7620,48 +7679,11 @@ index a5ed694..4af77f4 100644
+
+ return sd->next_in_service != sd->in_service_entity;
+}
+
+/*
+ * This function tells whether entity stops being a candidate for next
+ * service, according to the following logic.
+ *
+ * This function is invoked for an entity that is about to be set in
+ * service. If such an entity is a queue, then the entity is no longer
+ * a candidate for next service (i.e, a candidate entity to serve
+ * after the in-service entity is expired). The function then returns
+ * true.
+ *
+ * In contrast, the entity could stil be a candidate for next service
+ * if it is not a queue, and has more than one child. In fact, even if
+ * one of its children is about to be set in service, other children
+ * may still be the next to serve. As a consequence, a non-queue
+ * entity is not a candidate for next-service only if it has only one
+ * child. And only if this condition holds, then the function returns
+ * true for a non-queue entity.
+ */
+static bool bfq_no_longer_next_in_service(struct bfq_entity *entity)
+{
+ struct bfq_group *bfqg;
+
+ if (bfq_entity_to_bfqq(entity))
+ return true;
+
+#ifdef CONFIG_BFQ_GROUP_IOSCHED
+ bfqg = container_of(entity, struct bfq_group, entity);
+
+ BUG_ON(bfqg == ((struct bfq_data *)(bfqg->bfqd))->root_group);
+ BUG_ON(bfqg->active_entities == 0);
+ if (bfqg->active_entities == 1)
+ return true;
+#endif
+
+ return false;
+}
+
/*
* Get next queue for service.
*/
@@ -1083,58 +1677,208 @@ static struct bfq_queue *bfq_get_next_queue(struct bfq_data *bfqd)
@@ -1083,58 +1679,208 @@ static struct bfq_queue *bfq_get_next_queue(struct bfq_data *bfqd)
if (bfqd->busy_queues == 0)
return NULL;
@@ -7883,7 +7905,7 @@ index a5ed694..4af77f4 100644
{
BUG_ON(!bfq_bfqq_busy(bfqq));
BUG_ON(!RB_EMPTY_ROOT(&bfqq->sort_list));
@@ -1146,27 +1890,20 @@ static void bfq_del_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq,
@@ -1146,27 +1892,20 @@ static void bfq_del_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq,
BUG_ON(bfqd->busy_queues == 0);
bfqd->busy_queues--;
@@ -7918,7 +7940,7 @@ index a5ed694..4af77f4 100644
}
/*
@@ -1184,16 +1921,11 @@ static void bfq_add_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq)
@@ -1184,16 +1923,11 @@ static void bfq_add_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq)
bfq_mark_bfqq_busy(bfqq);
bfqd->busy_queues++;
@@ -7938,13 +7960,13 @@ index a5ed694..4af77f4 100644
bfqd->wr_busy_queues++;
}
diff --git a/block/bfq.h b/block/bfq.h
index fcce855..57ab51d 100644
index fcce855..bef8244 100644
--- a/block/bfq.h
+++ b/block/bfq.h
@@ -1,5 +1,5 @@
/*
- * BFQ-v7r11 for 4.5.0: data structures and common functions prototypes.
+ * BFQ v8r6 for 4.9.0: data structures and common functions prototypes.
+ * BFQ v8r7 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>
@@ -0,0 +1,34 @@
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
@@ -0,0 +1,69 @@
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>
@@ -0,0 +1,729 @@
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
@@ -0,0 +1,39 @@
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
@@ -0,0 +1,28 @@
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
@@ -0,0 +1,38 @@
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
@@ -0,0 +1,469 @@
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
@@ -0,0 +1,24 @@
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}
@@ -0,0 +1,32 @@
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)
@@ -0,0 +1,81 @@
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,97 +0,0 @@
From 8726f2faa371514fba2f594d799db95203dfeee0 Mon Sep 17 00:00:00 2001
From: Francisco Jerez <currojerez@riseup.net>
Date: Thu, 12 Jan 2017 12:44:54 +0200
Subject: drm/i915: Remove WaDisableLSQCROPERFforOCL KBL workaround.
The WaDisableLSQCROPERFforOCL workaround has the side effect of
disabling an L3SQ optimization that has huge performance implications
and is unlikely to be necessary for the correct functioning of usual
graphic workloads. Userspace is free to re-enable the workaround on
demand, and is generally in a better position to determine whether the
workaround is necessary than the DRM is (e.g. only during the
execution of compute kernels that rely on both L3 fences and HDC R/W
requests).
The same workaround seems to apply to BDW (at least to production
stepping G1) and SKL as well (the internal workaround database claims
that it does for all steppings, while the BSpec workaround table only
mentions pre-production steppings), but the DRM doesn't do anything
beyond whitelisting the L3SQCREG4 register so userspace can enable it
when it sees fit. Do the same on KBL platforms.
Improves performance of the GFXBench4 gl_manhattan31 benchmark by 60%,
and gl_4 (AKA car chase) by 14% on a KBL GT2 running Mesa master --
This is followed by a regression of 35% and 10% respectively for the
same benchmarks and platform caused by my recent patch series
switching userspace to use the dataport constant cache instead of the
sampler to implement uniform pull constant loads, which caused us to
hit more heavily the L3 cache (and on platforms other than KBL had the
opposite effect of improving performance of the same two benchmarks).
The overall effect on KBL of this change combined with the recent
userspace change is respectively 4.6% and 2.6%. SynMark2 OglShMapPcf
was affected by the constant cache changes (though it improved as it
did on other platforms rather than regressing), but is not
significantly affected by this patch (with statistical significance of
5% and sample size 20).
v2: Drop some more code to avoid unused variable warning.
Fixes: 738fa1b3123f ("drm/i915/kbl: Add WaDisableLSQCROPERFforOCL")
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=99256
Signed-off-by: Francisco Jerez <currojerez@riseup.net>
Cc: Matthew Auld <matthew.william.auld@gmail.com>
Cc: Eero Tamminen <eero.t.tamminen@intel.com>
Cc: Jani Nikula <jani.nikula@intel.com>
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
Cc: beignet@lists.freedesktop.org
Cc: <stable@vger.kernel.org> # v4.7+
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
[Removed double Fixes tag]
Signed-off-by: Mika Kuoppala <mika.kuoppala@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1484217894-20505-1-git-send-email-mika.kuoppala@intel.com
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index db714dc..8acab87 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -970,18 +970,8 @@ static inline int gen8_emit_flush_coherentl3_wa(struct intel_engine_cs *engine,
uint32_t *batch,
uint32_t index)
{
- struct drm_i915_private *dev_priv = engine->i915;
uint32_t l3sqc4_flush = (0x40400000 | GEN8_LQSC_FLUSH_COHERENT_LINES);
- /*
- * WaDisableLSQCROPERFforOCL:kbl
- * This WA is implemented in skl_init_clock_gating() but since
- * this batch updates GEN8_L3SQCREG4 with default value we need to
- * set this bit here to retain the WA during flush.
- */
- if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_E0))
- l3sqc4_flush |= GEN8_LQSC_RO_PERF_DIS;
-
wa_ctx_emit(batch, index, (MI_STORE_REGISTER_MEM_GEN8 |
MI_SRM_LRM_GLOBAL_GTT));
wa_ctx_emit_reg(batch, index, GEN8_L3SQCREG4);
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index ab83fc2..49fa800 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -1095,14 +1095,6 @@ static int kbl_init_workarounds(struct intel_engine_cs *engine)
WA_SET_BIT_MASKED(HDC_CHICKEN0,
HDC_FENCE_DEST_SLM_DISABLE);
- /* GEN8_L3SQCREG4 has a dependency with WA batch so any new changes
- * involving this register should also be added to WA batch as required.
- */
- if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_E0))
- /* WaDisableLSQCROPERFforOCL:kbl */
- I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) |
- GEN8_LQSC_RO_PERF_DIS);
-
/* WaToEnableHwFixForPushConstHWBug:kbl */
if (IS_KBL_REVID(dev_priv, KBL_REVID_C0, REVID_FOREVER))
WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
--
cgit v0.10.2
@@ -0,0 +1,42 @@
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,127 +0,0 @@
From a117f378f44150e6d13d2f19740fb757425b651f Mon Sep 17 00:00:00 2001
From: Jani Nikula <jani.nikula@intel.com>
Date: Fri, 16 Sep 2016 16:59:44 +0300
Subject: drm/i915/skl: drop workarounds for A0 and B0 revisions
Pre-production hardware is not supported.
Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/7929af62a68504c84038a8db1625bd96ebaa9e6f.1474034059.git.jani.nikula@intel.com
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 0568fb5..57da2b7 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1299,10 +1299,6 @@ bool intel_dp_source_supports_hbr2(struct intel_dp *intel_dp)
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
struct drm_device *dev = dig_port->base.base.dev;
- /* WaDisableHBR2:skl */
- if (IS_SKL_REVID(dev, 0, SKL_REVID_B0))
- return false;
-
if ((IS_HASWELL(dev) && !IS_HSW_ULX(dev)) || IS_BROADWELL(dev) ||
(INTEL_INFO(dev)->gen >= 9))
return true;
diff --git a/drivers/gpu/drm/i915/intel_dp_link_training.c b/drivers/gpu/drm/i915/intel_dp_link_training.c
index c438b02..0048b52 100644
--- a/drivers/gpu/drm/i915/intel_dp_link_training.c
+++ b/drivers/gpu/drm/i915/intel_dp_link_training.c
@@ -225,9 +225,6 @@ static u32 intel_dp_training_pattern(struct intel_dp *intel_dp)
* Intel platforms that support HBR2 also support TPS3. TPS3 support is
* also mandatory for downstream devices that support HBR2. However, not
* all sinks follow the spec.
- *
- * Due to WaDisableHBR2 SKL < B0 is the only exception where TPS3 is
- * supported in source but still not enabled.
*/
source_tps3 = intel_dp_source_supports_hbr2(intel_dp);
sink_tps3 = drm_dp_tps3_supported(intel_dp->dpcd);
diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c
index 6fd39ef..acc1dbd 100644
--- a/drivers/gpu/drm/i915/intel_guc_loader.c
+++ b/drivers/gpu/drm/i915/intel_guc_loader.c
@@ -375,9 +375,8 @@ static int guc_ucode_xfer(struct drm_i915_private *dev_priv)
/* Enable MIA caching. GuC clock gating is disabled. */
I915_WRITE(GUC_SHIM_CONTROL, GUC_SHIM_CONTROL_VALUE);
- /* WaDisableMinuteIaClockGating:skl,bxt */
- if (IS_SKL_REVID(dev, 0, SKL_REVID_B0) ||
- IS_BXT_REVID(dev, 0, BXT_REVID_A1)) {
+ /* WaDisableMinuteIaClockGating:bxt */
+ if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) {
I915_WRITE(GUC_SHIM_CONTROL, (I915_READ(GUC_SHIM_CONTROL) &
~GUC_ENABLE_MIA_CLOCK_GATING));
}
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 39417b7..47f7afa 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -269,8 +269,7 @@ logical_ring_init_platform_invariants(struct intel_engine_cs *engine)
struct drm_i915_private *dev_priv = engine->i915;
engine->disable_lite_restore_wa =
- (IS_SKL_REVID(dev_priv, 0, SKL_REVID_B0) ||
- IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) &&
+ IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1) &&
(engine->id == VCS || engine->id == VCS2);
engine->ctx_desc_template = GEN8_CTX_VALID;
@@ -1068,9 +1067,8 @@ static int gen9_init_perctx_bb(struct intel_engine_cs *engine,
{
uint32_t index = wa_ctx_start(wa_ctx, *offset, CACHELINE_DWORDS);
- /* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:skl,bxt */
- if (IS_SKL_REVID(engine->i915, 0, SKL_REVID_B0) ||
- IS_BXT_REVID(engine->i915, 0, BXT_REVID_A1)) {
+ /* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:bxt */
+ if (IS_BXT_REVID(engine->i915, 0, BXT_REVID_A1)) {
wa_ctx_emit(batch, index, MI_LOAD_REGISTER_IMM(1));
wa_ctx_emit_reg(batch, index, GEN9_SLICE_COMMON_ECO_CHICKEN0);
wa_ctx_emit(batch, index,
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 7a74750..2faf64f 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -851,15 +851,13 @@ static int gen9_init_workarounds(struct intel_engine_cs *engine)
WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC);
- /* WaDisableDgMirrorFixInHalfSliceChicken5:skl,bxt */
- if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_B0) ||
- IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
+ /* WaDisableDgMirrorFixInHalfSliceChicken5:bxt */
+ if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5,
GEN9_DG_MIRROR_FIX_ENABLE);
- /* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:skl,bxt */
- if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_B0) ||
- IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) {
+ /* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:bxt */
+ if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) {
WA_SET_BIT_MASKED(GEN7_COMMON_SLICE_CHICKEN1,
GEN9_RHWO_OPTIMIZATION_DISABLE);
/*
@@ -1023,15 +1021,8 @@ static int skl_init_workarounds(struct intel_engine_cs *engine)
GEN8_LQSC_RO_PERF_DIS);
/* WaEnableGapsTsvCreditFix:skl */
- if (IS_SKL_REVID(dev_priv, SKL_REVID_C0, REVID_FOREVER)) {
- I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) |
- GEN9_GAPS_TSV_CREDIT_DISABLE));
- }
-
- /* WaDisablePowerCompilerClockGating:skl */
- if (IS_SKL_REVID(dev_priv, SKL_REVID_B0, SKL_REVID_B0))
- WA_SET_BIT_MASKED(HIZ_CHICKEN,
- BDW_HIZ_POWER_COMPILER_CLOCK_GATING_DISABLE);
+ I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) |
+ GEN9_GAPS_TSV_CREDIT_DISABLE));
/* WaBarrierPerformanceFixDisable:skl */
if (IS_SKL_REVID(dev_priv, SKL_REVID_C0, SKL_REVID_D0))
--
cgit v0.10.2
@@ -1,86 +0,0 @@
From 9fc736e833d226853fd53843e35d6a1d542394ed Mon Sep 17 00:00:00 2001
From: Jani Nikula <jani.nikula@intel.com>
Date: Fri, 16 Sep 2016 16:59:46 +0300
Subject: drm/i915/skl: drop workarounds for D0 revision
Pre-production hardware is not supported.
Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/d28d21ceddeec226b5d1a20a7382bee9a72709a4.1474034059.git.jani.nikula@intel.com
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 47f7afa..ca649cc 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -994,9 +994,8 @@ static int gen9_init_indirectctx_bb(struct intel_engine_cs *engine,
struct drm_i915_private *dev_priv = engine->i915;
uint32_t index = wa_ctx_start(wa_ctx, *offset, CACHELINE_DWORDS);
- /* WaDisableCtxRestoreArbitration:skl,bxt */
- if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_D0) ||
- IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
+ /* WaDisableCtxRestoreArbitration:bxt */
+ if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
wa_ctx_emit(batch, index, MI_ARB_ON_OFF | MI_ARB_DISABLE);
/* WaFlushCoherentL3CacheLinesAtContextSwitch:skl,bxt */
@@ -1095,9 +1094,8 @@ static int gen9_init_perctx_bb(struct intel_engine_cs *engine,
wa_ctx_emit(batch, index, MI_NOOP);
}
- /* WaDisableCtxRestoreArbitration:skl,bxt */
- if (IS_SKL_REVID(engine->i915, 0, SKL_REVID_D0) ||
- IS_BXT_REVID(engine->i915, 0, BXT_REVID_A1))
+ /* WaDisableCtxRestoreArbitration:bxt */
+ if (IS_BXT_REVID(engine->i915, 0, BXT_REVID_A1))
wa_ctx_emit(batch, index, MI_ARB_ON_OFF | MI_ARB_ENABLE);
wa_ctx_emit(batch, index, MI_BATCH_BUFFER_END);
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 2df06b7..a860c40 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -5335,8 +5335,7 @@ static void gen9_enable_rc6(struct drm_i915_private *dev_priv)
rc6_mask = GEN6_RC_CTL_RC6_ENABLE;
DRM_INFO("RC6 %s\n", onoff(rc6_mask & GEN6_RC_CTL_RC6_ENABLE));
/* WaRsUseTimeoutMode */
- if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_D0) ||
- IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) {
+ if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) {
I915_WRITE(GEN6_RC6_THRESHOLD, 625); /* 800us */
I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE |
GEN7_RC_CTL_TO_MODE |
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 474ce84..6880082 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -1000,10 +1000,8 @@ static int skl_init_workarounds(struct intel_engine_cs *engine)
* until D0 which is the default case so this is equivalent to
* !WaDisablePerCtxtPreemptionGranularityControl:skl
*/
- if (IS_SKL_REVID(dev_priv, SKL_REVID_E0, REVID_FOREVER)) {
- I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1,
- _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL));
- }
+ I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1,
+ _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL));
if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_E0)) {
/* WaDisableChickenBitTSGBarrierAckForFFSliceCS:skl */
@@ -1023,12 +1021,6 @@ static int skl_init_workarounds(struct intel_engine_cs *engine)
I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) |
GEN9_GAPS_TSV_CREDIT_DISABLE));
- /* WaBarrierPerformanceFixDisable:skl */
- if (IS_SKL_REVID(dev_priv, SKL_REVID_C0, SKL_REVID_D0))
- WA_SET_BIT_MASKED(HDC_CHICKEN0,
- HDC_FENCE_DEST_SLM_DISABLE |
- HDC_BARRIER_PERFORMANCE_DISABLE);
-
/* WaDisableSbeCacheDispatchPortSharing:skl */
if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_F0))
WA_SET_BIT_MASKED(
--
cgit v0.10.2
@@ -1,59 +0,0 @@
From 3be192e92ddcad15f7bf6b4b9e3f195eb8c1fe76 Mon Sep 17 00:00:00 2001
From: Jani Nikula <jani.nikula@intel.com>
Date: Fri, 16 Sep 2016 16:59:47 +0300
Subject: drm/i915/skl: drop workarounds for E0 revision
Pre-production hardware is not supported.
Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/0633a02177195703502ef2396aab03efc0314334.1474034059.git.jani.nikula@intel.com
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index ca649cc..2d8eb2e 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -845,13 +845,12 @@ static inline int gen8_emit_flush_coherentl3_wa(struct intel_engine_cs *engine,
uint32_t l3sqc4_flush = (0x40400000 | GEN8_LQSC_FLUSH_COHERENT_LINES);
/*
- * WaDisableLSQCROPERFforOCL:skl,kbl
+ * WaDisableLSQCROPERFforOCL:kbl
* This WA is implemented in skl_init_clock_gating() but since
* this batch updates GEN8_L3SQCREG4 with default value we need to
* set this bit here to retain the WA during flush.
*/
- if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_E0) ||
- IS_KBL_REVID(dev_priv, 0, KBL_REVID_E0))
+ if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_E0))
l3sqc4_flush |= GEN8_LQSC_RO_PERF_DIS;
wa_ctx_emit(batch, index, (MI_STORE_REGISTER_MEM_GEN8 |
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 6880082..68dc27f 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -1003,20 +1003,6 @@ static int skl_init_workarounds(struct intel_engine_cs *engine)
I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1,
_MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL));
- if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_E0)) {
- /* WaDisableChickenBitTSGBarrierAckForFFSliceCS:skl */
- I915_WRITE(FF_SLICE_CS_CHICKEN2,
- _MASKED_BIT_ENABLE(GEN9_TSG_BARRIER_ACK_DISABLE));
- }
-
- /* GEN8_L3SQCREG4 has a dependency with WA batch so any new changes
- * involving this register should also be added to WA batch as required.
- */
- if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_E0))
- /* WaDisableLSQCROPERFforOCL:skl */
- I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) |
- GEN8_LQSC_RO_PERF_DIS);
-
/* WaEnableGapsTsvCreditFix:skl */
I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) |
GEN9_GAPS_TSV_CREDIT_DISABLE));
--
cgit v0.10.2
@@ -0,0 +1,102 @@
From: Arindam Nath <arindam.nath@amd.com>
Change History
--------------
v3:
- add Fixes and CC tags
- add link to Bugzilla
v2: changes suggested by Joerg
- add flush flag to improve efficiency of flush operation
v1:
- The idea behind flush queues is to defer the IOTLB flushing
for domains for which the mappings are no longer valid. We
add such domains in queue_add(), and when the queue size
reaches FLUSH_QUEUE_SIZE, we perform __queue_flush().
Since we have already taken lock before __queue_flush()
is called, we need to make sure the IOTLB flushing is
performed as quickly as possible.
In the current implementation, we perform IOTLB flushing
for all domains irrespective of which ones were actually
added in the flush queue initially. This can be quite
expensive especially for domains for which unmapping is
not required at this point of time.
This patch makes use of domain information in
'struct flush_queue_entry' to make sure we only flush
IOTLBs for domains who need it, skipping others.
Bugzilla: https://bugs.freedesktop.org/101029
Fixes: b1516a14657a ("iommu/amd: Implement flush queue")
Cc: stable@vger.kernel.org
Suggested-by: Joerg Roedel <joro@8bytes.org>
Signed-off-by: Arindam Nath <arindam.nath@amd.com>
---
drivers/iommu/amd_iommu.c | 27 ++++++++++++++++++++-------
drivers/iommu/amd_iommu_types.h | 2 ++
2 files changed, 22 insertions(+), 7 deletions(-)
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 63cacf5..1edeebec 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -2227,15 +2227,26 @@ static struct iommu_group *amd_iommu_device_group(struct device *dev)
static void __queue_flush(struct flush_queue *queue)
{
- struct protection_domain *domain;
- unsigned long flags;
int idx;
- /* First flush TLB of all known domains */
- spin_lock_irqsave(&amd_iommu_pd_lock, flags);
- list_for_each_entry(domain, &amd_iommu_pd_list, list)
- domain_flush_tlb(domain);
- spin_unlock_irqrestore(&amd_iommu_pd_lock, flags);
+ /* First flush TLB of all domains which were added to flush queue */
+ for (idx = 0; idx < queue->next; ++idx) {
+ struct flush_queue_entry *entry;
+
+ entry = queue->entries + idx;
+
+ /*
+ * There might be cases where multiple IOVA entries for the
+ * same domain are queued in the flush queue. To avoid
+ * flushing the same domain again, we check whether the
+ * flag is set or not. This improves the efficiency of
+ * flush operation.
+ */
+ if (!entry->dma_dom->domain.already_flushed) {
+ entry->dma_dom->domain.already_flushed = true;
+ domain_flush_tlb(&entry->dma_dom->domain);
+ }
+ }
/* Wait until flushes have completed */
domain_flush_complete(NULL);
@@ -2289,6 +2300,8 @@ static void queue_add(struct dma_ops_domain *dma_dom,
pages = __roundup_pow_of_two(pages);
address >>= PAGE_SHIFT;
+ dma_dom->domain.already_flushed = false;
+
queue = get_cpu_ptr(&flush_queue);
spin_lock_irqsave(&queue->lock, flags);
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
index 4de8f41..4f5519d 100644
--- a/drivers/iommu/amd_iommu_types.h
+++ b/drivers/iommu/amd_iommu_types.h
@@ -454,6 +454,8 @@ struct protection_domain {
bool updated; /* complete domain flush required */
unsigned dev_cnt; /* devices assigned to this domain */
unsigned dev_iommu[MAX_IOMMUS]; /* per-IOMMU reference count */
+ bool already_flushed; /* flag to avoid flushing the same domain again
+ in a single invocation of __queue_flush() */
};
/*
@@ -0,0 +1,46 @@
From 2638fd0f92d4397884fd991d8f4925cb3f081901 Mon Sep 17 00:00:00 2001
From: Eric Dumazet <edumazet@google.com>
Date: Mon, 3 Apr 2017 10:55:11 -0700
Subject: [PATCH] netfilter: xt_TCPMSS: add more sanity tests on tcph->doff
Denys provided an awesome KASAN report pointing to an use
after free in xt_TCPMSS
I have provided three patches to fix this issue, either in xt_TCPMSS or
in xt_tcpudp.c. It seems xt_TCPMSS patch has the smallest possible
impact.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reported-by: Denys Fedoryshchenko <nuclearcat@nuclearcat.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/netfilter/xt_TCPMSS.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c
index 27241a767f17..c64aca611ac5 100644
--- a/net/netfilter/xt_TCPMSS.c
+++ b/net/netfilter/xt_TCPMSS.c
@@ -104,7 +104,7 @@ tcpmss_mangle_packet(struct sk_buff *skb,
tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff);
tcp_hdrlen = tcph->doff * 4;
- if (len < tcp_hdrlen)
+ if (len < tcp_hdrlen || tcp_hdrlen < sizeof(struct tcphdr))
return -1;
if (info->mss == XT_TCPMSS_CLAMP_PMTU) {
@@ -152,6 +152,10 @@ tcpmss_mangle_packet(struct sk_buff *skb,
if (len > tcp_hdrlen)
return 0;
+ /* tcph->doff has 4 bits, do not wrap it to 0 */
+ if (tcp_hdrlen >= 15 * 4)
+ return 0;
+
/*
* MSS Option not found ?! add it..
*/
--
2.13.2
@@ -1,29 +0,0 @@
From: Gavin Li <git@thegavinli.com>
brcmf_sdio_fromevntchan() was being called on the the data frame
rather than the software header, causing some frames to be
mischaracterized as on the event channel rather than the data channel.
This fixes a major performance regression (due to dropped packets).
Fixes: c56caa9db8ab ("brcmfmac: screening firmware event packet")
Signed-off-by: Gavin Li <git@thegavinli.com>
Cc: <stable@vger.kernel.org> [4.7+]
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
index dfb0658713d9..d2219885071f 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -1661,7 +1661,7 @@ static u8 brcmf_sdio_rxglom(struct brcmf_sdio *bus, u8 rxseq)
pfirst->len, pfirst->next,
pfirst->prev);
skb_unlink(pfirst, &bus->glom);
- if (brcmf_sdio_fromevntchan(pfirst->data))
+ if (brcmf_sdio_fromevntchan(&dptr[SDPCM_HWHDR_LEN]))
brcmf_rx_event(bus->sdiodev->dev, pfirst);
else
brcmf_rx_frame(bus->sdiodev->dev, pfirst,
@@ -0,0 +1,371 @@
From upstream 4.11-rc2+ git
Fixes mga #20508
Signed-off-by: Thomas Backlund <tmb@mageia.org>
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 29 ++--
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c | 2
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c | 4
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723a.c | 2
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_872tb.c | 2
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 121 +++++++++++------
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h | 2
7 files changed, 105 insertions(+), 57 deletions(-)
diff -Nurp linux-4.9.16/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c linux-4.11-rc/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c
--- linux-4.9.16/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c 2016-12-11 21:17:54.000000000 +0200
+++ linux-4.11-rc/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c 2017-03-07 22:29:07.840867965 +0200
@@ -1,7 +1,7 @@
/*
* RTL8XXXU mac80211 USB driver - 8188c/8188r/8192c specific subdriver
*
- * Copyright (c) 2014 - 2016 Jes Sorensen <Jes.Sorensen@redhat.com>
+ * Copyright (c) 2014 - 2017 Jes Sorensen <Jes.Sorensen@gmail.com>
*
* Portions, notably calibration code:
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
diff -Nurp linux-4.9.16/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c linux-4.11-rc/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c
--- linux-4.9.16/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c 2016-12-11 21:17:54.000000000 +0200
+++ linux-4.11-rc/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c 2017-03-07 22:29:07.841868054 +0200
@@ -1,7 +1,7 @@
/*
* RTL8XXXU mac80211 USB driver - 8192e specific subdriver
*
- * Copyright (c) 2014 - 2016 Jes Sorensen <Jes.Sorensen@redhat.com>
+ * Copyright (c) 2014 - 2017 Jes Sorensen <Jes.Sorensen@gmail.com>
*
* Portions, notably calibration code:
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
@@ -1556,7 +1556,7 @@ exit:
return ret;
}
-void rtl8192eu_power_off(struct rtl8xxxu_priv *priv)
+static void rtl8192eu_power_off(struct rtl8xxxu_priv *priv)
{
u8 val8;
u16 val16;
diff -Nurp linux-4.9.16/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723a.c linux-4.11-rc/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723a.c
--- linux-4.9.16/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723a.c 2016-12-11 21:17:54.000000000 +0200
+++ linux-4.11-rc/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723a.c 2017-03-07 22:29:07.841868054 +0200
@@ -1,7 +1,7 @@
/*
* RTL8XXXU mac80211 USB driver - 8723a specific subdriver
*
- * Copyright (c) 2014 - 2016 Jes Sorensen <Jes.Sorensen@redhat.com>
+ * Copyright (c) 2014 - 2017 Jes Sorensen <Jes.Sorensen@gmail.com>
*
* Portions, notably calibration code:
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
diff -Nurp linux-4.9.16/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c linux-4.11-rc/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c
--- linux-4.9.16/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c 2016-12-11 21:17:54.000000000 +0200
+++ linux-4.11-rc/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c 2017-03-07 22:29:07.841868054 +0200
@@ -1,7 +1,7 @@
/*
* RTL8XXXU mac80211 USB driver - 8723b specific subdriver
*
- * Copyright (c) 2014 - 2016 Jes Sorensen <Jes.Sorensen@redhat.com>
+ * Copyright (c) 2014 - 2017 Jes Sorensen <Jes.Sorensen@gmail.com>
*
* Portions, notably calibration code:
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
diff -Nurp linux-4.9.16/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c linux-4.11-rc/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
--- linux-4.9.16/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c 2017-03-18 13:35:47.148080457 +0200
+++ linux-4.11-rc/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c 2017-03-07 22:29:07.841868054 +0200
@@ -1,7 +1,7 @@
/*
* RTL8XXXU mac80211 USB driver
*
- * Copyright (c) 2014 - 2016 Jes Sorensen <Jes.Sorensen@redhat.com>
+ * Copyright (c) 2014 - 2017 Jes Sorensen <Jes.Sorensen@gmail.com>
*
* Portions, notably calibration code:
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
@@ -48,7 +48,7 @@ static bool rtl8xxxu_dma_aggregation;
static int rtl8xxxu_dma_agg_timeout = -1;
static int rtl8xxxu_dma_agg_pages = -1;
-MODULE_AUTHOR("Jes Sorensen <Jes.Sorensen@redhat.com>");
+MODULE_AUTHOR("Jes Sorensen <Jes.Sorensen@gmail.com>");
MODULE_DESCRIPTION("RTL8XXXu USB mac80211 Wireless LAN Driver");
MODULE_LICENSE("GPL");
MODULE_FIRMWARE("rtlwifi/rtl8723aufw_A.bin");
@@ -4767,13 +4767,28 @@ static void rtl8xxxu_dump_action(struct
* This format is used on 8188cu/8192cu/8723au
*/
void
-rtl8xxxu_fill_txdesc_v1(struct ieee80211_hdr *hdr,
- struct rtl8xxxu_txdesc32 *tx_desc, u32 rate,
- u16 rate_flag, bool sgi, bool short_preamble,
- bool ampdu_enable)
+rtl8xxxu_fill_txdesc_v1(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
+ struct ieee80211_tx_info *tx_info,
+ struct rtl8xxxu_txdesc32 *tx_desc, bool sgi,
+ bool short_preamble, bool ampdu_enable, u32 rts_rate)
{
+ struct ieee80211_rate *tx_rate = ieee80211_get_tx_rate(hw, tx_info);
+ struct rtl8xxxu_priv *priv = hw->priv;
+ struct device *dev = &priv->udev->dev;
+ u32 rate;
+ u16 rate_flags = tx_info->control.rates[0].flags;
u16 seq_number;
+ if (rate_flags & IEEE80211_TX_RC_MCS &&
+ !ieee80211_is_mgmt(hdr->frame_control))
+ rate = tx_info->control.rates[0].idx + DESC_RATE_MCS0;
+ else
+ rate = tx_rate->hw_value;
+
+ if (rtl8xxxu_debug & RTL8XXXU_DEBUG_TX)
+ dev_info(dev, "%s: TX rate: %d, pkt size %d\n",
+ __func__, rate, cpu_to_le16(tx_desc->pkt_size));
+
seq_number = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));
tx_desc->txdw5 = cpu_to_le32(rate);
@@ -4804,15 +4819,16 @@ rtl8xxxu_fill_txdesc_v1(struct ieee80211
if (sgi)
tx_desc->txdw5 |= cpu_to_le32(TXDESC32_SHORT_GI);
- if (rate_flag & IEEE80211_TX_RC_USE_RTS_CTS) {
- /*
- * Use RTS rate 24M - does the mac80211 tell
- * us which to use?
- */
- tx_desc->txdw4 |= cpu_to_le32(DESC_RATE_24M <<
- TXDESC32_RTS_RATE_SHIFT);
+ /*
+ * rts_rate is zero if RTS/CTS or CTS to SELF are not enabled
+ */
+ tx_desc->txdw4 |= cpu_to_le32(rts_rate << TXDESC32_RTS_RATE_SHIFT);
+ if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
tx_desc->txdw4 |= cpu_to_le32(TXDESC32_RTS_CTS_ENABLE);
tx_desc->txdw4 |= cpu_to_le32(TXDESC32_HW_RTS_ENABLE);
+ } else if (rate_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
+ tx_desc->txdw4 |= cpu_to_le32(TXDESC32_CTS_SELF_ENABLE);
+ tx_desc->txdw4 |= cpu_to_le32(TXDESC32_HW_RTS_ENABLE);
}
}
@@ -4821,16 +4837,31 @@ rtl8xxxu_fill_txdesc_v1(struct ieee80211
* This format is used on 8192eu/8723bu
*/
void
-rtl8xxxu_fill_txdesc_v2(struct ieee80211_hdr *hdr,
- struct rtl8xxxu_txdesc32 *tx_desc32, u32 rate,
- u16 rate_flag, bool sgi, bool short_preamble,
- bool ampdu_enable)
+rtl8xxxu_fill_txdesc_v2(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
+ struct ieee80211_tx_info *tx_info,
+ struct rtl8xxxu_txdesc32 *tx_desc32, bool sgi,
+ bool short_preamble, bool ampdu_enable, u32 rts_rate)
{
+ struct ieee80211_rate *tx_rate = ieee80211_get_tx_rate(hw, tx_info);
+ struct rtl8xxxu_priv *priv = hw->priv;
+ struct device *dev = &priv->udev->dev;
struct rtl8xxxu_txdesc40 *tx_desc40;
+ u32 rate;
+ u16 rate_flags = tx_info->control.rates[0].flags;
u16 seq_number;
tx_desc40 = (struct rtl8xxxu_txdesc40 *)tx_desc32;
+ if (rate_flags & IEEE80211_TX_RC_MCS &&
+ !ieee80211_is_mgmt(hdr->frame_control))
+ rate = tx_info->control.rates[0].idx + DESC_RATE_MCS0;
+ else
+ rate = tx_rate->hw_value;
+
+ if (rtl8xxxu_debug & RTL8XXXU_DEBUG_TX)
+ dev_info(dev, "%s: TX rate: %d, pkt size %d\n",
+ __func__, rate, cpu_to_le16(tx_desc40->pkt_size));
+
seq_number = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));
tx_desc40->txdw4 = cpu_to_le32(rate);
@@ -4857,15 +4888,19 @@ rtl8xxxu_fill_txdesc_v2(struct ieee80211
if (short_preamble)
tx_desc40->txdw5 |= cpu_to_le32(TXDESC40_SHORT_PREAMBLE);
- if (rate_flag & IEEE80211_TX_RC_USE_RTS_CTS) {
- /*
- * Use RTS rate 24M - does the mac80211 tell
- * us which to use?
- */
- tx_desc40->txdw4 |= cpu_to_le32(DESC_RATE_24M <<
- TXDESC40_RTS_RATE_SHIFT);
+ tx_desc40->txdw4 |= cpu_to_le32(rts_rate << TXDESC40_RTS_RATE_SHIFT);
+ /*
+ * rts_rate is zero if RTS/CTS or CTS to SELF are not enabled
+ */
+ if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
tx_desc40->txdw3 |= cpu_to_le32(TXDESC40_RTS_CTS_ENABLE);
tx_desc40->txdw3 |= cpu_to_le32(TXDESC40_HW_RTS_ENABLE);
+ } else if (rate_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
+ /*
+ * For some reason the vendor driver doesn't set
+ * TXDESC40_HW_RTS_ENABLE for CTS to SELF
+ */
+ tx_desc40->txdw3 |= cpu_to_le32(TXDESC40_CTS_SELF_ENABLE);
}
}
@@ -4875,14 +4910,13 @@ static void rtl8xxxu_tx(struct ieee80211
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
- struct ieee80211_rate *tx_rate = ieee80211_get_tx_rate(hw, tx_info);
struct rtl8xxxu_priv *priv = hw->priv;
struct rtl8xxxu_txdesc32 *tx_desc;
struct rtl8xxxu_tx_urb *tx_urb;
struct ieee80211_sta *sta = NULL;
struct ieee80211_vif *vif = tx_info->control.vif;
struct device *dev = &priv->udev->dev;
- u32 queue, rate;
+ u32 queue, rts_rate;
u16 pktlen = skb->len;
u16 seq_number;
u16 rate_flag = tx_info->control.rates[0].flags;
@@ -4909,10 +4943,6 @@ static void rtl8xxxu_tx(struct ieee80211
goto error;
}
- if (rtl8xxxu_debug & RTL8XXXU_DEBUG_TX)
- dev_info(dev, "%s: TX rate: %d (%d), pkt size %d\n",
- __func__, tx_rate->bitrate, tx_rate->hw_value, pktlen);
-
if (ieee80211_is_action(hdr->frame_control))
rtl8xxxu_dump_action(dev, hdr);
@@ -4966,12 +4996,6 @@ static void rtl8xxxu_tx(struct ieee80211
}
}
- if (rate_flag & IEEE80211_TX_RC_MCS &&
- !ieee80211_is_mgmt(hdr->frame_control))
- rate = tx_info->control.rates[0].idx + DESC_RATE_MCS0;
- else
- rate = tx_rate->hw_value;
-
if (rate_flag & IEEE80211_TX_RC_SHORT_GI ||
(ieee80211_is_data_qos(hdr->frame_control) &&
sta && sta->ht_cap.cap &
@@ -4982,10 +5006,17 @@ static void rtl8xxxu_tx(struct ieee80211
(sta && vif && vif->bss_conf.use_short_preamble))
short_preamble = true;
+ if (rate_flag & IEEE80211_TX_RC_USE_RTS_CTS)
+ rts_rate = ieee80211_get_rts_cts_rate(hw, tx_info)->hw_value;
+ else if (rate_flag & IEEE80211_TX_RC_USE_CTS_PROTECT)
+ rts_rate = ieee80211_get_rts_cts_rate(hw, tx_info)->hw_value;
+ else
+ rts_rate = 0;
+
seq_number = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));
- priv->fops->fill_txdesc(hdr, tx_desc, rate, rate_flag,
- sgi, short_preamble, ampdu_enable);
+ priv->fops->fill_txdesc(hw, hdr, tx_info, tx_desc, sgi, short_preamble,
+ ampdu_enable, rts_rate);
rtl8xxxu_calc_tx_desc_csum(tx_desc);
@@ -5969,6 +6000,7 @@ static int rtl8xxxu_probe(struct usb_int
case 0x8176:
case 0x8178:
case 0x817f:
+ case 0x818b:
untested = 0;
break;
}
@@ -6165,6 +6197,12 @@ static struct usb_device_id dev_table[]
.driver_info = (unsigned long)&rtl8723au_fops},
{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x818b, 0xff, 0xff, 0xff),
.driver_info = (unsigned long)&rtl8192eu_fops},
+/* TP-Link TL-WN822N v4 */
+{USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0108, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192eu_fops},
+/* D-Link DWA-131 rev E1, tested by David Patiño */
+{USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3319, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192eu_fops},
/* Tested by Myckel Habets */
{USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0109, 0xff, 0xff, 0xff),
.driver_info = (unsigned long)&rtl8192eu_fops},
@@ -6316,6 +6354,13 @@ static struct usb_device_id dev_table[]
.driver_info = (unsigned long)&rtl8192cu_fops},
{USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0x7822, 0xff, 0xff, 0xff),
.driver_info = (unsigned long)&rtl8192cu_fops},
+/* found in rtl8192eu vendor driver */
+{USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0107, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192eu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x2019, 0xab33, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192eu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x818c, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192eu_fops},
#endif
{ }
};
diff -Nurp linux-4.9.16/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h linux-4.11-rc/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
--- linux-4.9.16/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h 2016-12-11 21:17:54.000000000 +0200
+++ linux-4.11-rc/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h 2017-03-07 22:29:07.840867965 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014 - 2016 Jes Sorensen <Jes.Sorensen@redhat.com>
+ * Copyright (c) 2014 - 2017 Jes Sorensen <Jes.Sorensen@gmail.com>
*
* 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
@@ -1337,10 +1337,11 @@ struct rtl8xxxu_fileops {
u32 ramask, int sgi);
void (*report_connect) (struct rtl8xxxu_priv *priv,
u8 macid, bool connect);
- void (*fill_txdesc) (struct ieee80211_hdr *hdr,
- struct rtl8xxxu_txdesc32 *tx_desc, u32 rate,
- u16 rate_flag, bool sgi, bool short_preamble,
- bool ampdu_enable);
+ void (*fill_txdesc) (struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
+ struct ieee80211_tx_info *tx_info,
+ struct rtl8xxxu_txdesc32 *tx_desc, bool sgi,
+ bool short_preamble, bool ampdu_enable,
+ u32 rts_rate);
int writeN_block_size;
int rx_agg_buf_size;
char tx_desc_size;
@@ -1434,14 +1435,16 @@ int rtl8xxxu_parse_rxdesc24(struct rtl8x
int rtl8xxxu_gen2_channel_to_group(int channel);
bool rtl8xxxu_gen2_simularity_compare(struct rtl8xxxu_priv *priv,
int result[][8], int c1, int c2);
-void rtl8xxxu_fill_txdesc_v1(struct ieee80211_hdr *hdr,
- struct rtl8xxxu_txdesc32 *tx_desc, u32 rate,
- u16 rate_flag, bool sgi, bool short_preamble,
- bool ampdu_enable);
-void rtl8xxxu_fill_txdesc_v2(struct ieee80211_hdr *hdr,
- struct rtl8xxxu_txdesc32 *tx_desc32, u32 rate,
- u16 rate_flag, bool sgi, bool short_preamble,
- bool ampdu_enable);
+void rtl8xxxu_fill_txdesc_v1(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
+ struct ieee80211_tx_info *tx_info,
+ struct rtl8xxxu_txdesc32 *tx_desc, bool sgi,
+ bool short_preamble, bool ampdu_enable,
+ u32 rts_rate);
+void rtl8xxxu_fill_txdesc_v2(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
+ struct ieee80211_tx_info *tx_info,
+ struct rtl8xxxu_txdesc32 *tx_desc32, bool sgi,
+ bool short_preamble, bool ampdu_enable,
+ u32 rts_rate);
extern struct rtl8xxxu_fileops rtl8192cu_fops;
extern struct rtl8xxxu_fileops rtl8192eu_fops;
diff -Nurp linux-4.9.16/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h linux-4.11-rc/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h
--- linux-4.9.16/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h 2016-12-11 21:17:54.000000000 +0200
+++ linux-4.11-rc/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h 2017-03-07 22:29:07.842868144 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014 - 2016 Jes Sorensen <Jes.Sorensen@redhat.com>
+ * Copyright (c) 2014 - 2017 Jes Sorensen <Jes.Sorensen@gmail.com>
*
* 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
@@ -0,0 +1,43 @@
From: Joerg Roedel <jroedel@suse.de>
ATS is broken on these devices. Under invalidation load, the
GPU does not reply to invalidations anymore, causing
Completion-wait loop timeouts on the AMD IOMMU driver side.
Fix it by not enabling ATS on these devices.
Note that below mentioned commit is not broken, it just
triggers the issue because it might cause invalidation
storms on devices.
Fixes: b1516a14657a ('iommu/amd: Implement flush queue')
Reported-by: Daniel Drake <drake@endlessm.com>
Cc: Daniel Drake <drake@endlessm.com>
Cc: Alexander Deucher <Alexander.Deucher@amd.com>
Signed-off-by: Joerg Roedel <jroedel@suse.de>
---
drivers/pci/ats.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/pci/ats.c b/drivers/pci/ats.c
index eeb9fb2..711bdb2 100644
--- a/drivers/pci/ats.c
+++ b/drivers/pci/ats.c
@@ -17,10 +17,18 @@
#include "pci.h"
+static const struct pci_device_id broken_ats_tbl[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x98e4) }, /* AMD Stoney GPU part */
+ { 0 }
+};
+
void pci_ats_init(struct pci_dev *dev)
{
int pos;
+ if (pci_match_id(broken_ats_tbl, dev))
+ return;
+
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS);
if (!pos)
return;
@@ -0,0 +1,179 @@
From ba714a9c1dea85e0bf2899d02dfeb9c70040427c Mon Sep 17 00:00:00 2001
From: Thomas Gleixner <tglx@linutronix.de>
Date: Tue, 23 May 2017 23:23:32 +0200
Subject: [PATCH] pinctrl/amd: Use regular interrupt instead of chained
The AMD pinctrl driver uses a chained interrupt to demultiplex the GPIO
interrupts. Kevin Vandeventer reported, that his new AMD Ryzen locks up
hard on boot when the AMD pinctrl driver is initialized. The reason is an
interrupt storm. It's not clear whether that's caused by hardware or
firmware or both.
Using chained interrupts on X86 is a dangerous endavour. If a system is
misconfigured or the hardware buggy there is no safety net to catch an
interrupt storm.
Convert the driver to use a regular interrupt for the demultiplex
handler. This allows the interrupt storm detector to catch the malfunction
and lets the system boot up.
This should be backported to stable because it's likely that more users run
into this problem as the AMD Ryzen machines are spreading.
Reported-by: Kevin Vandeventer
Link: https://bugzilla.suse.com/show_bug.cgi?id=1034261
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Backported to 4.9 by: Borislav Petkov <bp@alien8.de>
---
drivers/pinctrl/pinctrl-amd.c | 91 +++++++++++++++++++------------------------
1 file changed, 41 insertions(+), 50 deletions(-)
Date: Thu, 22 Jun 2017 11:16:31 +0200
From:
To: Thomas Backlund <tmb@mageia.org>
Cc: stable <stable@vger.kernel.org>, Thomas Gleixner <tglx@linutronix.de>,
Linus Walleij <linus.walleij@linaro.org>,
"Shah, Nehal-bakulchandra" <Nehal-bakulchandra.Shah@amd.com>,
"Xue, Ken" <Ken.Xue@amd.com>,
"S-k, Shyam-sundar" <Shyam-sundar.S-k@amd.com>,
Sherry Hurwitz <sherry.hurwitz@amd.com>
Subject: Re: ba714a9c1dea ("pinctrl/amd: Use regular interrupt instead of chained")
On Thu, Jun 22, 2017 at 12:03:50PM +0300, Thomas Backlund wrote:
> If it's intended for 4.9 -longterm, a proper backport is needed.
Something like this, I guess. But I need to find a box to test it.
Regards/Gruss,
Boris.
diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
index c9a146948192..531e2224f38f 100644
--- a/drivers/pinctrl/pinctrl-amd.c
+++ b/drivers/pinctrl/pinctrl-amd.c
@@ -476,64 +476,54 @@ static struct irq_chip amd_gpio_irqchip = {
.irq_set_type = amd_gpio_irq_set_type,
};
-static void amd_gpio_irq_handler(struct irq_desc *desc)
+#define PIN_IRQ_PENDING (BIT(INTERRUPT_STS_OFF) | BIT(WAKE_STS_OFF))
+
+static irqreturn_t amd_gpio_irq_handler(int irq, void *dev_id)
{
- u32 i;
- u32 off;
- u32 reg;
- u32 pin_reg;
- u64 reg64;
- int handled = 0;
- unsigned int irq;
+ struct amd_gpio *gpio_dev = dev_id;
+ struct gpio_chip *gc = &gpio_dev->gc;
+ irqreturn_t ret = IRQ_NONE;
+ unsigned int i, irqnr;
unsigned long flags;
- struct irq_chip *chip = irq_desc_get_chip(desc);
- struct gpio_chip *gc = irq_desc_get_handler_data(desc);
- struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
+ u32 *regs, regval;
+ u64 status, mask;
- chained_irq_enter(chip, desc);
- /*enable GPIO interrupt again*/
+ /* Read the wake status */
spin_lock_irqsave(&gpio_dev->lock, flags);
- reg = readl(gpio_dev->base + WAKE_INT_STATUS_REG1);
- reg64 = reg;
- reg64 = reg64 << 32;
-
- reg = readl(gpio_dev->base + WAKE_INT_STATUS_REG0);
- reg64 |= reg;
+ status = readl(gpio_dev->base + WAKE_INT_STATUS_REG1);
+ status <<= 32;
+ status |= readl(gpio_dev->base + WAKE_INT_STATUS_REG0);
spin_unlock_irqrestore(&gpio_dev->lock, flags);
- /*
- * first 46 bits indicates interrupt status.
- * one bit represents four interrupt sources.
- */
- for (off = 0; off < 46 ; off++) {
- if (reg64 & BIT(off)) {
- for (i = 0; i < 4; i++) {
- pin_reg = readl(gpio_dev->base +
- (off * 4 + i) * 4);
- if ((pin_reg & BIT(INTERRUPT_STS_OFF)) ||
- (pin_reg & BIT(WAKE_STS_OFF))) {
- irq = irq_find_mapping(gc->irqdomain,
- off * 4 + i);
- generic_handle_irq(irq);
- writel(pin_reg,
- gpio_dev->base
- + (off * 4 + i) * 4);
- handled++;
- }
- }
+ /* Bit 0-45 contain the relevant status bits */
+ status &= (1ULL << 46) - 1;
+ regs = gpio_dev->base;
+ for (mask = 1, irqnr = 0; status; mask <<= 1, regs += 4, irqnr += 4) {
+ if (!(status & mask))
+ continue;
+ status &= ~mask;
+
+ /* Each status bit covers four pins */
+ for (i = 0; i < 4; i++) {
+ regval = readl(regs + i);
+ if (!(regval & PIN_IRQ_PENDING))
+ continue;
+ irq = irq_find_mapping(gc->irqdomain, irqnr + i);
+ generic_handle_irq(irq);
+ /* Clear interrupt */
+ writel(regval, regs + i);
+ ret = IRQ_HANDLED;
}
}
- if (handled == 0)
- handle_bad_irq(desc);
-
+ /* Signal EOI to the GPIO unit */
spin_lock_irqsave(&gpio_dev->lock, flags);
- reg = readl(gpio_dev->base + WAKE_INT_MASTER_REG);
- reg |= EOI_MASK;
- writel(reg, gpio_dev->base + WAKE_INT_MASTER_REG);
+ regval = readl(gpio_dev->base + WAKE_INT_MASTER_REG);
+ regval |= EOI_MASK;
+ writel(regval, gpio_dev->base + WAKE_INT_MASTER_REG);
spin_unlock_irqrestore(&gpio_dev->lock, flags);
- chained_irq_exit(chip, desc);
+ return ret;
}
static int amd_get_groups_count(struct pinctrl_dev *pctldev)
@@ -801,10 +791,11 @@ static int amd_gpio_probe(struct platform_device *pdev)
goto out2;
}
- gpiochip_set_chained_irqchip(&gpio_dev->gc,
- &amd_gpio_irqchip,
- irq_base,
- amd_gpio_irq_handler);
+ ret = devm_request_irq(&pdev->dev, irq_base, amd_gpio_irq_handler, 0,
+ KBUILD_MODNAME, gpio_dev);
+ if (ret)
+ goto out2;
+
platform_set_drvdata(pdev, gpio_dev);
--
Regards/Gruss,
Boris.
Good mailing practices for 400: avoid top-posting and trim the reply.
+91 -19
View File
@@ -14,14 +14,31 @@
###
### Stable Queue
###
# CVE-2016-8405
stable-fbdev-color-map-copying-bounds-checking.patch
stable-tile-ptrace-preserve-previous-registers-for-short-regset-write.patch
stable-drm-schedule-the-output_poll_work-with-1s-delay-if-we-have-delayed-event.patch
stable-drm-fix-broken-vt-switch-with-video-1366x768-option.patch
stable-drm-i915-ignore-bogus-plane-coordinates-on-skl-when-the-plane-is-not-visible.patch
stable-ipv6-release-dst-on-error-in-ip6_dst_lookup_tail.patch
stable-net-don-t-call-strlen-on-non-terminated-string-in-dev_set_alias.patch
stable-decnet-dn_rtmsg-improve-input-length-sanitization-in-dnrmg_receive_user_skb.patch
stable-net-zero-ifla_vf_info-in-rtnl_fill_vfinfo.patch
stable-net-vrf-make-add_fib_rules-per-network-namespace-flag.patch
stable-af_unix-add-sockaddr-length-checks-before-accessing-sa_family-in-bind-and-connect-handlers.patch
stable-fix-an-intermittent-pr_emerg-warning-about-lo-becoming-free.patch
stable-sctp-disable-bh-in-sctp_for_each_endpoint.patch
stable-net-caif-fix-a-sleep-in-atomic-bug-in-cfpkt_create_pfx.patch
stable-net-tipc-fix-a-sleep-in-atomic-bug-in-tipc_msg_reverse.patch
stable-net-mlx5e-added-bw-check-for-dim-decision-mechanism.patch
stable-net-mlx5e-fix-wrong-indications-in-dim-due-to-counter-wraparound.patch
stable-proc-snmp6-use-correct-type-in-memset.patch
stable-igmp-acquire-pmc-lock-for-ip_mc_clear_src.patch
stable-igmp-add-a-missing-spin_lock_init.patch
stable-ipv6-fix-calling-in6_ifa_hold-incorrectly-for-dad-work.patch
stable-sctp-return-next-obj-by-passing-pos-1-into-sctp_transport_get_idx.patch
stable-net-mlx5e-avoid-doing-a-cleanup-call-if-the-profile-doesn-t-have-it.patch
stable-net-mlx5-wait-for-fw-readiness-before-initializing-command-interface.patch
stable-net-mlx5e-fix-timestamping-capabilities-reporting.patch
stable-decnet-always-not-take-dst-__refcnt-when-inserting-dst-into-hash-table.patch
stable-net-8021q-fix-one-possible-panic-caused-by-bug_on-in-free_netdev.patch
stable-sfc-provide-dummy-definitions-of-vswitch-functions.patch
stable-ipv6-do-not-leak-throw-route-references.patch
stable-rtnetlink-add-ifla_group-to-ifla_policy.patch
###
### Arch x86
@@ -46,14 +63,14 @@ x86-increase-default-minimum-vmalloc-area-by-64MB-to-192MB.patch
# slows down boot
Revert-cpufreq-pcc-Enable-autoload-of-pcc-cpufreq-fo.patch
# breaks nvidia304
Revert-x86-mm-mtrr-Remove-kernel-internal-MTRR-inter.patch
###
### Core
###
base-cacheinfo-silence-DT-warnings.patch
# fixes crash on boot on some Amd systems
iommu-amd-flush-IOTLB-for-specific-domains-only-v3.patch
###
### i2c
###
@@ -68,6 +85,9 @@ base-cacheinfo-silence-DT-warnings.patch
pci-add-ALI-M5229-ide-compatibility-mode-quirk.patch
pci-quirks-drop-devinit-exit.patch
# Stoney iommu hang
pci-Blacklist-AMD-Stoney-GPU-devices-for-ATS.patch
###
### PNP core
###
@@ -88,6 +108,9 @@ ACPI-video-Add-a-quirk-to-force-acpi-video-backlight.patch
# drop obsolete warn
acpi-do-not-warn-if-_BQC-does-not-exist.patch
# silence useless acpi warnings
acpi-ACPICA-Events-Fix-acpi_ev_initialize_region-return-v.patch
###
### Block
###
@@ -135,7 +158,12 @@ block-Make-CFQ-default-to-IOPS-mode-on-SSDs.patch
block-cgroups-kconfig-build-bits-for-BFQ-v7r11-4.5.0.patch
block-introduce-the-BFQ-v7r11-I-O-sched-for-4.5.0.patch
block-bfq-add-Early-Queue-Merge-EQM-to-BFQ-v7r11-for.patch
block-Turn-into-BFQ-v8r6-for-4.9.0.patch
block-Turn-into-BFQ-v8r7-for-4.9.0.patch
block-update-bfq-from-v8r7-to-v8r10.patch
block-update-bfq-from-v8r10-to-v8r11.patch
# new macbooks
block-nvme-detect-NVMe-controller-in-recent-MacBooks.patch
###
### Char
@@ -161,6 +189,9 @@ fs-aufs-4.9-modular.patch
# needed for mdadm: imsm: enable bad block support for imsm metadata
fs-seq_file-reset-iterator-to-first-record-for-zero-off.patch
# performance regression fix
fs-jbd2-Fix-dbench4-performance-regression-for-nobarrier-mounts.patch
###
### FireWire
###
@@ -194,11 +225,18 @@ gpu-drm-mach64-linux-3.14-buildfix.patch
gpu-drm-mach64-3.17-buildfix.patch
gpu-drm-mach64-3.18-buildfix.patch
# i915 skl/kbl speedup
gpu-drm-i915-skl-drop-workarounds-for-A0-and-B0-revisions.patch
gpu-drm-i915-skl-drop-workarounds-for-D0-revision.patch
gpu-drm-i915-skl-drop-workarounds-for-E0-revision.patch
gpu-drm-i915-Remove-WaDisableLSQCROPERFforOCL-KBL-workaround.patch
#
gpu-drm-i915-don-t-warn-about-Skylake-CPU-KabyPoint-PCH-.patch
# Amd polaris12 support
gpu-drm-amd-amdgpu-add-Polaris12-PCI-ID.patch
gpu-drm-amd-amdgpu-add-Polaris12-support-v3.patch
gpu-drm-amdgpu-powerplay-add-Polaris12-support.patch
gpu-drm-amd-amdgpu-add-POLARIS12-PCI-ID.patch
gpu-drm-amdgpu-add-Polaris12-DID.patch
# fix crash
gpu-drm-amdgpu-pm-check-for-headless-before-calling-comp.patch
###
### Hardware Monitoring
@@ -256,8 +294,18 @@ net-netfilter-psd-fix-redefines.patch
net-wireless-rtlwifi-Use-dev_kfree_skb_irq-instead-of-kfree_skb.patch
net-wireless-rtlwifi-Fix-kernel-oops-introduced-with-commit-e4965.patch
# fix speed regression
net-wireless-brcmfmac-fix-incorrect-event-channel-deduction.patch
# update rtl8xxxu for mga#20508
net-wireless-realtek-rtl8xxxu-linux-4.11-rc.patch
# fixes issue triggable by remote peers
net-netfilter-xt_TCPMSS-add-more-sanity-tests-on-tcph-do.patch
###
### pinctrl
###
# fix non-booting Ryzen+ due to interrupt storm
pinctrl_amd-Use-regular-interrupt-instead-of-chained.patch
###
### Platform drivers
@@ -284,6 +332,24 @@ include-kbuild-export-pci_ids.patch
### Sound
###
# new codecs
sound-ALSA-hda-realtek-Add-new-codec-ID-ALC299.patch
sound-ALSA-hda-realtek-New-codec-support-of-ALC1220.patch
# add support for Gigabyte GA-AX370 Gaming 5 with dual codecs (TTL: 4.12)
sound-ALSA-hda-A-new-flag-to-enforce-prefix-to-each-pin.patch
sound-ALSA-hda-Allow-to-enable-disable-vmaster-build-expli.patch
sound-ALSA-hda-Support-Gigabyte-Gaming-board-with-dual-Rea.patch
sound-ALSA-hda-Use-a-helper-function-for-renaming-kctl-nam.patch
# another dual codec system
sound-ALSA-hda-Apply-dual-codec-quirk-for-MSI-Z270-Gaming-.patch
sound-ALSA-hda-Fix-applying-MSI-dual-codec-mobo-quirk.patch
# intel
sound-ALSA-hda-Add-Geminilake-id-to-SKL_PLUS.patch
sound-ALSA-hda-Add-Coffelake-PCI-ID.patch
sound-ALSA-hda-Apply-quirks-to-Broxton-T-too.patch
###
### Staging
###
@@ -306,6 +372,9 @@ hid-usbhid-IBM-BladeCenterHS20-quirk.patch
usb-storage-unusual_devs-add-id.patch
usb-storage-unusual_devs-add-id-2.6.37-buildfix.patch
# amd xhci fix
usb-xhci-Limit-USB2-port-wake-support-for-AMD-Promontory-hosts.patch
###
### V4L
###
@@ -364,6 +433,9 @@ video-mageia-logo.patch
# add rtl8723bs support (mga#15874)
3rd-rtl8723bs.patch
# add rtl8812 support (mga#21043)
3rd-rtl8812au.patch
###
### Security
###
@@ -0,0 +1,68 @@
From 9f3dadb156692e15933a4a97ef659f65151be4a1 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 10 Apr 2017 17:12:33 +0200
Subject: [PATCH 1/4] ALSA: hda - A new flag to enforce prefix to each pin
This is a preliminary patch for a smooth multi-codec support, and it
introduces a new flag, force_pin_prefix, to struct hda_codec.
This flag is used to force to add the pin location prefix to each
input pin. For example, when there is only one microphone pin,
usually the auto-parser assigns the string "Mic". With this flag on,
it'll be like "Front Mic". Also, the creation of "Master" or "PCM"
playback volume for a single pin is suppressed, too.
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=195305
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
sound/pci/hda/hda_auto_parser.c | 1 +
sound/pci/hda/hda_codec.h | 1 +
sound/pci/hda/hda_generic.c | 2 ++
3 files changed, 4 insertions(+)
diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c
index a03cf68..d3ea731 100644
--- a/sound/pci/hda/hda_auto_parser.c
+++ b/sound/pci/hda/hda_auto_parser.c
@@ -580,6 +580,7 @@ const char *hda_get_autocfg_input_label(struct hda_codec *codec,
has_multiple_pins = 1;
if (has_multiple_pins && type == AUTO_PIN_MIC)
has_multiple_pins &= check_mic_location_need(codec, cfg, input);
+ has_multiple_pins |= codec->force_pin_prefix;
return hda_get_input_pin_label(codec, &cfg->inputs[input],
cfg->inputs[input].pin,
has_multiple_pins);
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index f17f252..d6fb2d5 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -256,6 +256,7 @@ struct hda_codec {
unsigned int dump_coef:1; /* dump processing coefs in codec proc file */
unsigned int power_save_node:1; /* advanced PM for each widget */
unsigned int auto_runtime_pm:1; /* enable automatic codec runtime pm */
+ unsigned int force_pin_prefix:1; /* Add location prefix */
#ifdef CONFIG_PM
unsigned long power_on_acct;
unsigned long power_off_acct;
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index e7c8f4f..4438328 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -1125,6 +1125,7 @@ static const char *get_line_out_pfx(struct hda_codec *codec, int ch,
*index = 0;
if (cfg->line_outs == 1 && !spec->multi_ios &&
+ !codec->force_pin_prefix &&
!cfg->hp_outs && !cfg->speaker_outs)
return spec->vmaster_mute.hook ? "PCM" : "Master";
@@ -1132,6 +1133,7 @@ static const char *get_line_out_pfx(struct hda_codec *codec, int ch,
* use it master (or "PCM" if a vmaster hook is present)
*/
if (spec->multiout.num_dacs == 1 && !spec->mixer_nid &&
+ !codec->force_pin_prefix &&
!spec->multiout.hp_out_nid[0] && !spec->multiout.extra_out_nid[0])
return spec->vmaster_mute.hook ? "PCM" : "Master";
--
2.10.2
@@ -0,0 +1,45 @@
From e79b0006c45c9b0b22f3ea54ff6e256b34c1f208 Mon Sep 17 00:00:00 2001
From: Megha Dey <megha.dey@intel.com>
Date: Wed, 14 Jun 2017 09:51:56 +0530
Subject: [PATCH] ALSA: hda - Add Coffelake PCI ID
Coffelake is another Intel part, so need to add PCI ID for it.
Signed-off-by: Megha Dey <megha.dey@intel.com>
Signed-off-by: Subhransu S. Prusty <subhransu.s.prusty@intel.com>
Acked-by: Vinod Koul <vinod.koul@intel.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
sound/pci/hda/hda_intel.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 1770f085c2a6..e3c696c46a21 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -371,9 +371,10 @@ enum {
#define IS_KBL_H(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa2f0)
#define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98)
#define IS_GLK(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x3198)
+#define IS_CFL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa348)
#define IS_SKL_PLUS(pci) (IS_SKL(pci) || IS_SKL_LP(pci) || IS_BXT(pci)) || \
IS_KBL(pci) || IS_KBL_LP(pci) || IS_KBL_H(pci) || \
- IS_GLK(pci)
+ IS_GLK(pci) || IS_CFL(pci)
static char *driver_short_names[] = {
[AZX_DRIVER_ICH] = "HDA Intel",
@@ -2378,6 +2379,9 @@ static const struct pci_device_id azx_ids[] = {
/* Kabylake-H */
{ PCI_DEVICE(0x8086, 0xa2f0),
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE },
+ /* Coffelake */
+ { PCI_DEVICE(0x8086, 0xa348),
+ .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE},
/* Broxton-P(Apollolake) */
{ PCI_DEVICE(0x8086, 0x5a98),
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_BROXTON },
--
2.13.1
@@ -0,0 +1,36 @@
From 12ee4022f67f8854061b46e5c0a7ad6258ab66c2 Mon Sep 17 00:00:00 2001
From: "Subhransu S. Prusty" <subhransu.s.prusty@intel.com>
Date: Wed, 12 Apr 2017 09:54:00 +0530
Subject: [PATCH] ALSA: hda: Add Geminilake id to SKL_PLUS
Geminilake is Skylake family platform. So add it's id to skl_plus check.
Fixes: 126cfa2f5e15 ("ALSA: hda: Add Geminilake HDMI codec ID")
Signed-off-by: Subhransu S. Prusty <subhransu.s.prusty@intel.com>
Cc: Senthilnathan Veppur <senthilnathanx.veppur@intel.com>
Cc: Vinod Koul <vinod.koul@intel.com>
Cc: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
sound/pci/hda/hda_intel.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 59ab34fa0bc8..b786fbab029f 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -370,8 +370,10 @@ enum {
#define IS_KBL_LP(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9d71)
#define IS_KBL_H(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa2f0)
#define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98)
+#define IS_GLK(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x3198)
#define IS_SKL_PLUS(pci) (IS_SKL(pci) || IS_SKL_LP(pci) || IS_BXT(pci)) || \
- IS_KBL(pci) || IS_KBL_LP(pci) || IS_KBL_H(pci)
+ IS_KBL(pci) || IS_KBL_LP(pci) || IS_KBL_H(pci) || \
+ IS_GLK(pci)
static char *driver_short_names[] = {
[AZX_DRIVER_ICH] = "HDA Intel",
--
2.13.1
@@ -0,0 +1,78 @@
From 7480316c265c9fcdbf73b1b8dec061b893b7e987 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 10 Apr 2017 17:37:34 +0200
Subject: [PATCH 2/4] ALSA: hda - Allow to enable/disable vmaster build
explicitly
Another preliminary patch for the dual-codec support: since the
support of vmaster over multiple codecs is difficult, simply disable
it by a new flag to hda_codec struct. A new user hint is added as
well for consistency.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
Documentation/sound/hd-audio/notes.rst | 2 ++
sound/pci/hda/hda_generic.c | 7 +++++--
sound/pci/hda/hda_generic.h | 1 +
3 files changed, 8 insertions(+), 2 deletions(-)
#diff --git a/Documentation/sound/hd-audio/notes.rst b/Documentation/sound/hd-audio/notes.rst
#index 9eeb9b4..f59c3cd 100644
#--- a/Documentation/sound/hd-audio/notes.rst
#+++ b/Documentation/sound/hd-audio/notes.rst
#@@ -494,6 +494,8 @@ add_hp_mic (bool)
# hp_mic_detect (bool)
# enable/disable the hp/mic shared input for a single built-in mic
# case; default true
#+vmaster (bool)
#+ enable/disable the virtual Master control; default true
# mixer_nid (int)
# specifies the widget NID of the analog-loopback mixer
#
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 4438328..2842c82 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -196,6 +196,9 @@ static void parse_user_hints(struct hda_codec *codec)
val = snd_hda_get_bool_hint(codec, "hp_mic_detect");
if (val >= 0)
spec->suppress_hp_mic_detect = !val;
+ val = snd_hda_get_bool_hint(codec, "vmaster");
+ if (val >= 0)
+ spec->suppress_vmaster = !val;
if (!snd_hda_get_int_hint(codec, "mixer_nid", &val))
spec->mixer_nid = val;
@@ -5033,7 +5036,7 @@ int snd_hda_gen_build_controls(struct hda_codec *codec)
}
/* if we have no master control, let's create it */
- if (!spec->no_analog &&
+ if (!spec->no_analog && !spec->suppress_vmaster &&
!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
err = snd_hda_add_vmaster(codec, "Master Playback Volume",
spec->vmaster_tlv, slave_pfxs,
@@ -5041,7 +5044,7 @@ int snd_hda_gen_build_controls(struct hda_codec *codec)
if (err < 0)
return err;
}
- if (!spec->no_analog &&
+ if (!spec->no_analog && !spec->suppress_vmaster &&
!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
NULL, slave_pfxs,
diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h
index f66fc7e..6177231 100644
--- a/sound/pci/hda/hda_generic.h
+++ b/sound/pci/hda/hda_generic.h
@@ -229,6 +229,7 @@ struct hda_gen_spec {
unsigned int add_jack_modes:1; /* add i/o jack mode enum ctls */
unsigned int power_down_unused:1; /* power down unused widgets */
unsigned int dac_min_mute:1; /* minimal = mute for DACs */
+ unsigned int suppress_vmaster:1; /* don't create vmaster kctls */
/* other internal flags */
unsigned int no_analog:1; /* digital I/O only */
--
2.10.2
@@ -0,0 +1,28 @@
From 63691587f7b0028326ddd1226c378aaaeca4d4e4 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 22 May 2017 16:32:46 +0200
Subject: [PATCH] ALSA: hda - Apply dual-codec quirk for MSI Z270-Gaming mobo
MSI Z270-Gamin mobo has also two ALC1220 codecs like Gigabyte AZ370-
Gaming mobo. Apply the same quirk to this one.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
sound/pci/hda/patch_realtek.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 9c22ad694534..3fdd5af190a4 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -2328,6 +2328,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE),
SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
+ SND_PCI_QUIRK(0x1462, 0xda57, "MSI Z270-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX),
SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD),
SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD),
--
2.13.1
@@ -0,0 +1,38 @@
From c7ecb9068e6772c43941ce609f08bc53f36e1dce Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Wed, 14 Jun 2017 07:37:14 +0200
Subject: [PATCH] ALSA: hda - Apply quirks to Broxton-T, too
Broxton-T was a forgotten child and we didn't apply the quirks for
Skylake+ properly. Meanwhile, a quirk for reducing the DMA latency
seems specific to the early Broxton model, so we leave as is.
Cc: <stable@vger.kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
sound/pci/hda/hda_intel.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index e3c696c46a21..01eb1dc7b5b3 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -370,11 +370,12 @@ enum {
#define IS_KBL_LP(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9d71)
#define IS_KBL_H(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa2f0)
#define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98)
+#define IS_BXT_T(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x1a98)
#define IS_GLK(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x3198)
#define IS_CFL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa348)
-#define IS_SKL_PLUS(pci) (IS_SKL(pci) || IS_SKL_LP(pci) || IS_BXT(pci)) || \
- IS_KBL(pci) || IS_KBL_LP(pci) || IS_KBL_H(pci) || \
- IS_GLK(pci) || IS_CFL(pci)
+#define IS_SKL_PLUS(pci) (IS_SKL(pci) || IS_SKL_LP(pci) || IS_BXT(pci) || \
+ IS_BXT_T(pci) || IS_KBL(pci) || IS_KBL_LP(pci) || \
+ IS_KBL_H(pci) || IS_GLK(pci) || IS_CFL(pci))
static char *driver_short_names[] = {
[AZX_DRIVER_ICH] = "HDA Intel",
--
2.13.1
@@ -0,0 +1,42 @@
From d2c3b14e1f0dcebdb695617c0c1342a36b914a47 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Thu, 1 Jun 2017 09:35:30 +0200
Subject: [PATCH] ALSA: hda - Fix applying MSI dual-codec mobo quirk
The previous commit [63691587f7b0: ALSA: hda - Apply dual-codec quirk
for MSI Z270-Gaming mobo] attempted to apply the existing dual-codec
quirk for a MSI mobo. But it turned out that this isn't applied
properly due to the MSI-vendor quirk before this entry. I overlooked
such two MSI entries just because they were put in the wrong position,
although we have a list ordered by PCI SSID numbers.
This patch fixes it by rearranging the unordered entries.
Fixes: 63691587f7b0 ("ALSA: hda - Apply dual-codec quirk for MSI Z270-Gaming mobo")
Reported-by: Rudolf Schmidt <info@rudolfschmidt.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
sound/pci/hda/patch_realtek.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 918e45268915..a57988d617e9 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -2324,11 +2324,11 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_MBA11_VREF),
SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD),
- SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
- SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE),
SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
+ SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
SND_PCI_QUIRK(0x1462, 0xda57, "MSI Z270-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
+ SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX),
SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD),
SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD),
--
2.13.1
@@ -0,0 +1,122 @@
From 7beb3a6e9335d13872f24566b451f8371edd238f Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 10 Apr 2017 18:05:52 +0200
Subject: [PATCH 3/4] ALSA: hda - Support Gigabyte Gaming board with dual
Realtek codecs
This patch adds some workarounds to make Gigabyte GA-AX370 Gaming 5
board working without the conflicts of kctls, etc. In general, the
dual codec configs result in the conflicts of the following stuff:
- Master controls
- Capture controls
- Analog loopback controls
In addition, the auto-mute and the auto-mic can't work well among
multiple codecs.
The current "solution" is to disable all these features, and use UCM
for a better PulseAudio management. For a dedicated UCM profile, the
patch overrides the card longname so that the system an get a unique
profile path.
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=195305
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
sound/pci/hda/patch_realtek.c | 61 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 61 insertions(+)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 9371f1a..e81cf83 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -1800,6 +1800,7 @@ enum {
ALC882_FIXUP_NO_PRIMARY_HP,
ALC887_FIXUP_ASUS_BASS,
ALC887_FIXUP_BASS_CHMAP,
+ ALC1220_FIXUP_GB_DUAL_CODECS,
};
static void alc889_fixup_coef(struct hda_codec *codec,
@@ -1962,6 +1963,61 @@ static void alc882_fixup_no_primary_hp(struct hda_codec *codec,
static void alc_fixup_bass_chmap(struct hda_codec *codec,
const struct hda_fixup *fix, int action);
+/* For dual-codec configuration, we need to disable some features to avoid
+ * conflicts of kctls and PCM streams
+ */
+static void alc_fixup_dual_codecs(struct hda_codec *codec,
+ const struct hda_fixup *fix, int action)
+{
+ struct alc_spec *spec = codec->spec;
+
+ if (action != HDA_FIXUP_ACT_PRE_PROBE)
+ return;
+ /* disable vmaster */
+ spec->gen.suppress_vmaster = 1;
+ /* auto-mute and auto-mic switch don't work with multiple codecs */
+ spec->gen.suppress_auto_mute = 1;
+ spec->gen.suppress_auto_mic = 1;
+ /* disable aamix as well */
+ spec->gen.mixer_nid = 0;
+ /* add location prefix to avoid conflicts */
+ codec->force_pin_prefix = 1;
+}
+
+static void rename_ctl(struct hda_codec *codec, const char *oldname,
+ const char *newname)
+{
+ struct snd_kcontrol *kctl;
+
+ kctl = snd_hda_find_mixer_ctl(codec, oldname);
+ if (kctl)
+ strcpy(kctl->id.name, newname);
+}
+
+static void alc1220_fixup_gb_dual_codecs(struct hda_codec *codec,
+ const struct hda_fixup *fix,
+ int action)
+{
+ alc_fixup_dual_codecs(codec, fix, action);
+ switch (action) {
+ case HDA_FIXUP_ACT_PRE_PROBE:
+ /* override card longname to provide a unique UCM profile */
+ strcpy(codec->card->longname, "HDAudio-Gigabyte-ALC1220DualCodecs");
+ break;
+ case HDA_FIXUP_ACT_BUILD:
+ /* rename Capture controls depending on the codec */
+ rename_ctl(codec, "Capture Volume",
+ codec->addr == 0 ?
+ "Rear-Panel Capture Volume" :
+ "Front-Panel Capture Volume");
+ rename_ctl(codec, "Capture Switch",
+ codec->addr == 0 ?
+ "Rear-Panel Capture Switch" :
+ "Front-Panel Capture Switch");
+ break;
+ }
+}
+
static const struct hda_fixup alc882_fixups[] = {
[ALC882_FIXUP_ABIT_AW9D_MAX] = {
.type = HDA_FIXUP_PINS,
@@ -2198,6 +2254,10 @@ static const struct hda_fixup alc882_fixups[] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc_fixup_bass_chmap,
},
+ [ALC1220_FIXUP_GB_DUAL_CODECS] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc1220_fixup_gb_dual_codecs,
+ },
};
static const struct snd_pci_quirk alc882_fixup_tbl[] = {
@@ -2267,6 +2327,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX),
SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD),
SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD),
--
2.10.2
@@ -0,0 +1,42 @@
From 56798e6b3a2264b58d50b93cfd66586ede77d661 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Tue, 11 Apr 2017 08:10:52 +0200
Subject: [PATCH 4/4] ALSA: hda - Use a helper function for renaming kctl names
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
sound/pci/hda/patch_realtek.c | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index e81cf83..57eeefd 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -4724,7 +4724,6 @@ static void alc282_fixup_asus_tx300(struct hda_codec *codec,
{ 0x1b, 0x21114000 }, /* dock speaker pin */
{}
};
- struct snd_kcontrol *kctl;
switch (action) {
case HDA_FIXUP_ACT_PRE_PROBE:
@@ -4739,12 +4738,10 @@ static void alc282_fixup_asus_tx300(struct hda_codec *codec,
/* this is a bit tricky; give more sane names for the main
* (tablet) speaker and the dock speaker, respectively
*/
- kctl = snd_hda_find_mixer_ctl(codec, "Speaker Playback Switch");
- if (kctl)
- strcpy(kctl->id.name, "Dock Speaker Playback Switch");
- kctl = snd_hda_find_mixer_ctl(codec, "Bass Speaker Playback Switch");
- if (kctl)
- strcpy(kctl->id.name, "Speaker Playback Switch");
+ rename_ctl(codec, "Speaker Playback Switch",
+ "Dock Speaker Playback Switch");
+ rename_ctl(codec, "Bass Speaker Playback Switch",
+ "Speaker Playback Switch");
break;
}
}
--
2.10.2
@@ -0,0 +1,102 @@
From 28f1f9b26cee161ddd3985b3eb78e3ffada08dda Mon Sep 17 00:00:00 2001
From: Kailang Yang <kailang@realtek.com>
Date: Wed, 4 Jan 2017 14:49:07 +0800
Subject: [PATCH] ALSA: hda/realtek - Add new codec ID ALC299
ALC299 was similar as ALC225.
Add headset support for ALC299.
ALC3271 was for Dell rename.
Signed-off-by: Kailang Yang <kailang@realtek.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
sound/pci/hda/patch_realtek.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 1ae29fd..3c69647 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -337,6 +337,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
case 0x10ec0288:
case 0x10ec0295:
case 0x10ec0298:
+ case 0x10ec0299:
alc_update_coef_idx(codec, 0x10, 1<<9, 0);
break;
case 0x10ec0285:
@@ -912,6 +913,7 @@ static struct alc_codec_rename_pci_table rename_pci_tbl[] = {
{ 0x10ec0256, 0x1028, 0, "ALC3246" },
{ 0x10ec0225, 0x1028, 0, "ALC3253" },
{ 0x10ec0295, 0x1028, 0, "ALC3254" },
+ { 0x10ec0299, 0x1028, 0, "ALC3271" },
{ 0x10ec0670, 0x1025, 0, "ALC669X" },
{ 0x10ec0676, 0x1025, 0, "ALC679X" },
{ 0x10ec0282, 0x1043, 0, "ALC3229" },
@@ -3716,6 +3718,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec)
break;
case 0x10ec0225:
case 0x10ec0295:
+ case 0x10ec0299:
alc_process_coef_fw(codec, coef0225);
break;
case 0x10ec0867:
@@ -3823,6 +3826,7 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin,
break;
case 0x10ec0225:
case 0x10ec0295:
+ case 0x10ec0299:
alc_update_coef_idx(codec, 0x45, 0x3f<<10, 0x31<<10);
snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
alc_process_coef_fw(codec, coef0225);
@@ -3881,6 +3885,7 @@ static void alc_headset_mode_default(struct hda_codec *codec)
switch (codec->core.vendor_id) {
case 0x10ec0225:
case 0x10ec0295:
+ case 0x10ec0299:
alc_process_coef_fw(codec, coef0225);
break;
case 0x10ec0255:
@@ -3996,6 +4001,7 @@ static void alc_headset_mode_ctia(struct hda_codec *codec)
break;
case 0x10ec0225:
case 0x10ec0295:
+ case 0x10ec0299:
alc_process_coef_fw(codec, coef0225);
break;
case 0x10ec0867:
@@ -4089,6 +4095,7 @@ static void alc_headset_mode_omtp(struct hda_codec *codec)
break;
case 0x10ec0225:
case 0x10ec0295:
+ case 0x10ec0299:
alc_process_coef_fw(codec, coef0225);
break;
}
@@ -4173,6 +4180,7 @@ static void alc_determine_headset_type(struct hda_codec *codec)
break;
case 0x10ec0225:
case 0x10ec0295:
+ case 0x10ec0299:
alc_process_coef_fw(codec, coef0225);
msleep(800);
val = alc_read_coef_idx(codec, 0x46);
@@ -6219,6 +6227,7 @@ static int patch_alc269(struct hda_codec *codec)
break;
case 0x10ec0225:
case 0x10ec0295:
+ case 0x10ec0299:
spec->codec_variant = ALC269_TYPE_ALC225;
break;
case 0x10ec0234:
@@ -7256,6 +7265,7 @@ static const struct hda_device_id snd_hda_id_realtek[] = {
HDA_CODEC_ENTRY(0x10ec0294, "ALC294", patch_alc269),
HDA_CODEC_ENTRY(0x10ec0295, "ALC295", patch_alc269),
HDA_CODEC_ENTRY(0x10ec0298, "ALC298", patch_alc269),
+ HDA_CODEC_ENTRY(0x10ec0299, "ALC299", patch_alc269),
HDA_CODEC_REV_ENTRY(0x10ec0861, 0x100340, "ALC660", patch_alc861),
HDA_CODEC_ENTRY(0x10ec0660, "ALC660-VD", patch_alc861vd),
HDA_CODEC_ENTRY(0x10ec0861, "ALC861", patch_alc861),
--
2.10.2
@@ -0,0 +1,45 @@
From a535ad57d0e6b959cd79914a1127caade36a9459 Mon Sep 17 00:00:00 2001
From: Kailang Yang <kailang@realtek.com>
Date: Mon, 16 Jan 2017 16:59:26 +0800
Subject: [PATCH] ALSA: hda/realtek - New codec support of ALC1220
Add support for new codec of ALC1220.
It's compatible with ALC882 & co.
Signed-off-by: Kailang Yang <kailang@realtek.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
sound/pci/hda/patch_realtek.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 3c69647..1c88da8 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -380,6 +380,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
break;
case 0x10ec0899:
case 0x10ec0900:
+ case 0x10ec1220:
alc_update_coef_idx(codec, 0x7, 1<<1, 0);
break;
}
@@ -2310,6 +2311,7 @@ static int patch_alc882(struct hda_codec *codec)
case 0x10ec0882:
case 0x10ec0885:
case 0x10ec0900:
+ case 0x10ec1220:
break;
default:
/* ALC883 and variants */
@@ -7297,6 +7299,7 @@ static const struct hda_device_id snd_hda_id_realtek[] = {
HDA_CODEC_ENTRY(0x10ec0892, "ALC892", patch_alc662),
HDA_CODEC_ENTRY(0x10ec0899, "ALC898", patch_alc882),
HDA_CODEC_ENTRY(0x10ec0900, "ALC1150", patch_alc882),
+ HDA_CODEC_ENTRY(0x10ec1220, "ALC1220", patch_alc882),
{} /* terminator */
};
MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_realtek);
--
2.10.2
@@ -0,0 +1,47 @@
From foo@baz Thu Jun 29 18:57:46 CEST 2017
From: Mateusz Jurczyk <mjurczyk@google.com>
Date: Thu, 8 Jun 2017 11:13:36 +0200
Subject: af_unix: Add sockaddr length checks before accessing sa_family in bind and connect handlers
From: Mateusz Jurczyk <mjurczyk@google.com>
[ Upstream commit defbcf2decc903a28d8398aa477b6881e711e3ea ]
Verify that the caller-provided sockaddr structure is large enough to
contain the sa_family field, before accessing it in bind() and connect()
handlers of the AF_UNIX socket. Since neither syscall enforces a minimum
size of the corresponding memory region, very short sockaddrs (zero or
one byte long) result in operating on uninitialized memory while
referencing .sa_family.
Signed-off-by: Mateusz Jurczyk <mjurczyk@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/unix/af_unix.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -998,7 +998,8 @@ static int unix_bind(struct socket *sock
struct path path = { NULL, NULL };
err = -EINVAL;
- if (sunaddr->sun_family != AF_UNIX)
+ if (addr_len < offsetofend(struct sockaddr_un, sun_family) ||
+ sunaddr->sun_family != AF_UNIX)
goto out;
if (addr_len == sizeof(short)) {
@@ -1109,6 +1110,10 @@ static int unix_dgram_connect(struct soc
unsigned int hash;
int err;
+ err = -EINVAL;
+ if (alen < offsetofend(struct sockaddr, sa_family))
+ goto out;
+
if (addr->sa_family != AF_UNSPEC) {
err = unix_mkname(sunaddr, alen, &hash);
if (err < 0)
@@ -0,0 +1,89 @@
From foo@baz Thu Jun 29 18:57:46 CEST 2017
From: Wei Wang <weiwan@google.com>
Date: Fri, 16 Jun 2017 10:46:37 -0700
Subject: decnet: always not take dst->__refcnt when inserting dst into hash table
From: Wei Wang <weiwan@google.com>
[ Upstream commit 76371d2e3ad1f84426a30ebcd8c3b9b98f4c724f ]
In the existing dn_route.c code, dn_route_output_slow() takes
dst->__refcnt before calling dn_insert_route() while dn_route_input_slow()
does not take dst->__refcnt before calling dn_insert_route().
This makes the whole routing code very buggy.
In dn_dst_check_expire(), dnrt_free() is called when rt expires. This
makes the routes inserted by dn_route_output_slow() not able to be
freed as the refcnt is not released.
In dn_dst_gc(), dnrt_drop() is called to release rt which could
potentially cause the dst->__refcnt to be dropped to -1.
In dn_run_flush(), dst_free() is called to release all the dst. Again,
it makes the dst inserted by dn_route_output_slow() not able to be
released and also, it does not wait on the rcu and could potentially
cause crash in the path where other users still refer to this dst.
This patch makes sure both input and output path do not take
dst->__refcnt before calling dn_insert_route() and also makes sure
dnrt_free()/dst_free() is called when removing dst from the hash table.
The only difference between those 2 calls is that dnrt_free() waits on
the rcu while dst_free() does not.
Signed-off-by: Wei Wang <weiwan@google.com>
Acked-by: Martin KaFai Lau <kafai@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/decnet/dn_route.c | 14 ++++----------
1 file changed, 4 insertions(+), 10 deletions(-)
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -188,12 +188,6 @@ static inline void dnrt_free(struct dn_r
call_rcu_bh(&rt->dst.rcu_head, dst_rcu_free);
}
-static inline void dnrt_drop(struct dn_route *rt)
-{
- dst_release(&rt->dst);
- call_rcu_bh(&rt->dst.rcu_head, dst_rcu_free);
-}
-
static void dn_dst_check_expire(unsigned long dummy)
{
int i;
@@ -248,7 +242,7 @@ static int dn_dst_gc(struct dst_ops *ops
}
*rtp = rt->dst.dn_next;
rt->dst.dn_next = NULL;
- dnrt_drop(rt);
+ dnrt_free(rt);
break;
}
spin_unlock_bh(&dn_rt_hash_table[i].lock);
@@ -350,7 +344,7 @@ static int dn_insert_route(struct dn_rou
dst_use(&rth->dst, now);
spin_unlock_bh(&dn_rt_hash_table[hash].lock);
- dnrt_drop(rt);
+ dst_free(&rt->dst);
*rp = rth;
return 0;
}
@@ -380,7 +374,7 @@ static void dn_run_flush(unsigned long d
for(; rt; rt = next) {
next = rcu_dereference_raw(rt->dst.dn_next);
RCU_INIT_POINTER(rt->dst.dn_next, NULL);
- dst_free((struct dst_entry *)rt);
+ dnrt_free(rt);
}
nothing_to_declare:
@@ -1187,7 +1181,7 @@ make_route:
if (dev_out->flags & IFF_LOOPBACK)
flags |= RTCF_LOCAL;
- rt = dst_alloc(&dn_dst_ops, dev_out, 1, DST_OBSOLETE_NONE, DST_HOST);
+ rt = dst_alloc(&dn_dst_ops, dev_out, 0, DST_OBSOLETE_NONE, DST_HOST);
if (rt == NULL)
goto e_nobufs;
@@ -0,0 +1,42 @@
From foo@baz Thu Jun 29 18:57:46 CEST 2017
From: Mateusz Jurczyk <mjurczyk@google.com>
Date: Wed, 7 Jun 2017 16:14:29 +0200
Subject: decnet: dn_rtmsg: Improve input length sanitization in dnrmg_receive_user_skb
From: Mateusz Jurczyk <mjurczyk@google.com>
[ Upstream commit dd0da17b209ed91f39872766634ca967c170ada1 ]
Verify that the length of the socket buffer is sufficient to cover the
nlmsghdr structure before accessing the nlh->nlmsg_len field for further
input sanitization. If the client only supplies 1-3 bytes of data in
sk_buff, then nlh->nlmsg_len remains partially uninitialized and
contains leftover memory from the corresponding kernel allocation.
Operating on such data may result in indeterminate evaluation of the
nlmsg_len < sizeof(*nlh) expression.
The bug was discovered by a runtime instrumentation designed to detect
use of uninitialized memory in the kernel. The patch prevents this and
other similar tools (e.g. KMSAN) from flagging this behavior in the future.
Signed-off-by: Mateusz Jurczyk <mjurczyk@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/decnet/netfilter/dn_rtmsg.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/net/decnet/netfilter/dn_rtmsg.c
+++ b/net/decnet/netfilter/dn_rtmsg.c
@@ -102,7 +102,9 @@ static inline void dnrmg_receive_user_sk
{
struct nlmsghdr *nlh = nlmsg_hdr(skb);
- if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len)
+ if (skb->len < sizeof(*nlh) ||
+ nlh->nlmsg_len < sizeof(*nlh) ||
+ skb->len < nlh->nlmsg_len)
return;
if (!netlink_capable(skb, CAP_NET_ADMIN))
@@ -1,71 +0,0 @@
From fdf35a6b22247746a7053fc764d04218a9306f82 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 9 Jan 2017 15:56:14 +0100
Subject: drm: Fix broken VT switch with video=1366x768 option
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
From: Takashi Iwai <tiwai@suse.de>
commit fdf35a6b22247746a7053fc764d04218a9306f82 upstream.
I noticed that the VT switch doesn't work any longer with a Dell
laptop with 1366x768 eDP when the machine is connected with a DP
monitor. It behaves as if VT were switched, but the graphics remain
frozen. Actually the keyboard works, so I could switch back to VT7
again.
I tried to track down the problem, and encountered a long story until
we reach to this error:
- The machine is booted with video=1366x768 option (the distro
installer seems to add it as default).
- Recently, drm_helper_probe_single_connector_modes() deals with
cmdline modes, and it tries to create a new mode when no
matching mode is found.
- The drm_mode_create_from_cmdline_mode() creates a mode based on
either CVT of GFT according to the given cmdline mode; in our case,
it's 1366x768.
- Since both CVT and GFT can't express the width 1366 due to
alignment, the resultant mode becomes 1368x768, slightly larger than
the given size.
- Later on, the atomic commit is performed, and in
drm_atomic_check_only(), the size of each plane is checked.
- The size check of 1366x768 fails due to the above, and eventually
the whole VT switch fails.
Back in the history, we've had a manual fix-up of 1368x768 in various
places via c09dedb7a50e ("drm/edid: Add a workaround for 1366x768 HD
panel"), but they have been all in drm_edid.c at probing the modes
from EDID. For addressing the problem above, we need a similar hack
to the mode newly created from cmdline, manually adjusting the width
when the expected size is 1366 while we get 1368 instead.
Fixes: eaf99c749d43 ("drm: Perform cmdline mode parsing during...")
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Link: http://patchwork.freedesktop.org/patch/msgid/20170109145614.29454-1-tiwai@suse.de
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/drm_modes.c | 7 +++++++
1 file changed, 7 insertions(+)
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -1462,6 +1462,13 @@ drm_mode_create_from_cmdline_mode(struct
return NULL;
mode->type |= DRM_MODE_TYPE_USERDEF;
+ /* fix up 1368x768: GFT/CVT can't express 1366 width due to alignment */
+ if (cmd->xres == 1366 && mode->hdisplay == 1368) {
+ mode->hdisplay = 1366;
+ mode->hsync_start--;
+ mode->hsync_end--;
+ drm_mode_set_name(mode);
+ }
drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
return mode;
}
@@ -1,49 +0,0 @@
From 3bfdfdcbce2796ce75bf2d85fd8471858d702e5d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com>
Date: Mon, 7 Nov 2016 22:20:54 +0200
Subject: drm/i915: Ignore bogus plane coordinates on SKL when the plane is not visible
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
From: Ville Syrjälä <ville.syrjala@linux.intel.com>
commit 3bfdfdcbce2796ce75bf2d85fd8471858d702e5d upstream.
When the plane is invisible we may have all sorts of bogus stuff
in the coordinates, which we must ignore or else we might fail the
plane update. This started to happen on SKL when I moved the plane
offset computation to happen in the check phase. Previously we
happily ignored it all since we never called the update_plane hook
with an invisible plane.
Cc: Sivakumar Thulasimani <sivakumar.thulasimani@intel.com>
Cc: drm-intel-fixes@lists.freedesktop.org
Fixes: b63a16f6cd89 ("drm/i915: Compute display surface offset in the plane check hook for SKL+")
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=98258
Testcase: igt/pm_rpm/legacy-planes
Testcase: igt/pm_rpm/universal-planes
Reviewed-by: Matt Roper <matthew.d.roper@intel.com>
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1478550057-24864-3-git-send-email-ville.syrjala@linux.intel.com
(cherry picked from commit a5e4c7d0aa6784d8abe95c3ceef0da9656d17468)
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/i915/intel_display.c | 3 +++
1 file changed, 3 insertions(+)
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2975,6 +2975,9 @@ int skl_check_plane_surface(struct intel
unsigned int rotation = plane_state->base.rotation;
int ret;
+ if (!plane_state->base.visible)
+ return 0;
+
/* Rotate src coordinates to match rotated GTT view */
if (intel_rotation_90_or_270(rotation))
drm_rect_rotate(&plane_state->base.src,
@@ -1,55 +0,0 @@
From 68f458eec7069d618a6c884ca007426e0cea411b Mon Sep 17 00:00:00 2001
From: Peter Ujfalusi <peter.ujfalusi@ti.com>
Date: Mon, 9 Jan 2017 16:31:58 +0200
Subject: drm: Schedule the output_poll_work with 1s delay if we have delayed event
From: Peter Ujfalusi <peter.ujfalusi@ti.com>
commit 68f458eec7069d618a6c884ca007426e0cea411b upstream.
Instead of scheduling the work to handle the initial delayed event, use 1s
delay.
This delay should not be needed, but Optimus/nouveau will fail in a
mysterious way if the delayed event is handled as soon as possible like it
is done in drm_helper_probe_single_connector_modes() in case the poll
was enabled before.
Reverting 339fd36238dd would give back the 10 sec (!) delay to handle the
delayed event. Adding 1sec delay to the poll_work is enough to work around
the issue in Optimus setups and gives shorter response on handling the
initial delayed event.
Fixes: 339fd36238dd ("drm: drm_probe_helper: Fix output_poll_work scheduling")
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
[danvet: Add FIXME to the comment to make it stick out more.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/20170109143158.21917-1-peter.ujfalusi@ti.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/drm_probe_helper.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
--- a/drivers/gpu/drm/drm_probe_helper.c
+++ b/drivers/gpu/drm/drm_probe_helper.c
@@ -143,8 +143,18 @@ void drm_kms_helper_poll_enable_locked(s
}
if (dev->mode_config.delayed_event) {
+ /*
+ * FIXME:
+ *
+ * Use short (1s) delay to handle the initial delayed event.
+ * This delay should not be needed, but Optimus/nouveau will
+ * fail in a mysterious way if the delayed event is handled as
+ * soon as possible like it is done in
+ * drm_helper_probe_single_connector_modes() in case the poll
+ * was enabled before.
+ */
poll = true;
- delay = 0;
+ delay = HZ;
}
if (poll)
@@ -1,82 +0,0 @@
From 2dc705a9930b4806250fbf5a76e55266e59389f2 Mon Sep 17 00:00:00 2001
From: Kees Cook <keescook@chromium.org>
Date: Tue, 24 Jan 2017 15:18:24 -0800
Subject: fbdev: color map copying bounds checking
From: Kees Cook <keescook@chromium.org>
commit 2dc705a9930b4806250fbf5a76e55266e59389f2 upstream.
Copying color maps to userspace doesn't check the value of to->start,
which will cause kernel heap buffer OOB read due to signedness wraps.
CVE-2016-8405
Link: http://lkml.kernel.org/r/20170105224249.GA50925@beast
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Kees Cook <keescook@chromium.org>
Reported-by: Peter Pi (@heisecode) of Trend Micro
Cc: Min Chong <mchong@google.com>
Cc: Dan Carpenter <dan.carpenter@oracle.com>
Cc: Tomi Valkeinen <tomi.valkeinen@ti.com>
Cc: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/video/fbdev/core/fbcmap.c | 26 ++++++++++++++------------
1 file changed, 14 insertions(+), 12 deletions(-)
--- a/drivers/video/fbdev/core/fbcmap.c
+++ b/drivers/video/fbdev/core/fbcmap.c
@@ -163,17 +163,18 @@ void fb_dealloc_cmap(struct fb_cmap *cma
int fb_copy_cmap(const struct fb_cmap *from, struct fb_cmap *to)
{
- int tooff = 0, fromoff = 0;
- int size;
+ unsigned int tooff = 0, fromoff = 0;
+ size_t size;
if (to->start > from->start)
fromoff = to->start - from->start;
else
tooff = from->start - to->start;
- size = to->len - tooff;
- if (size > (int) (from->len - fromoff))
- size = from->len - fromoff;
- if (size <= 0)
+ if (fromoff >= from->len || tooff >= to->len)
+ return -EINVAL;
+
+ size = min_t(size_t, to->len - tooff, from->len - fromoff);
+ if (size == 0)
return -EINVAL;
size *= sizeof(u16);
@@ -187,17 +188,18 @@ int fb_copy_cmap(const struct fb_cmap *f
int fb_cmap_to_user(const struct fb_cmap *from, struct fb_cmap_user *to)
{
- int tooff = 0, fromoff = 0;
- int size;
+ unsigned int tooff = 0, fromoff = 0;
+ size_t size;
if (to->start > from->start)
fromoff = to->start - from->start;
else
tooff = from->start - to->start;
- size = to->len - tooff;
- if (size > (int) (from->len - fromoff))
- size = from->len - fromoff;
- if (size <= 0)
+ if (fromoff >= from->len || tooff >= to->len)
+ return -EINVAL;
+
+ size = min_t(size_t, to->len - tooff, from->len - fromoff);
+ if (size == 0)
return -EINVAL;
size *= sizeof(u16);
@@ -0,0 +1,76 @@
From foo@baz Thu Jun 29 18:57:46 CEST 2017
From: Krister Johansen <kjlx@templeofstupid.com>
Date: Thu, 8 Jun 2017 13:12:38 -0700
Subject: Fix an intermittent pr_emerg warning about lo becoming free.
From: Krister Johansen <kjlx@templeofstupid.com>
[ Upstream commit f186ce61bb8235d80068c390dc2aad7ca427a4c2 ]
It looks like this:
Message from syslogd@flamingo at Apr 26 00:45:00 ...
kernel:unregister_netdevice: waiting for lo to become free. Usage count = 4
They seem to coincide with net namespace teardown.
The message is emitted by netdev_wait_allrefs().
Forced a kdump in netdev_run_todo, but found that the refcount on the lo
device was already 0 at the time we got to the panic.
Used bcc to check the blocking in netdev_run_todo. The only places
where we're off cpu there are in the rcu_barrier() and msleep() calls.
That behavior is expected. The msleep time coincides with the amount of
time we spend waiting for the refcount to reach zero; the rcu_barrier()
wait times are not excessive.
After looking through the list of callbacks that the netdevice notifiers
invoke in this path, it appears that the dst_dev_event is the most
interesting. The dst_ifdown path places a hold on the loopback_dev as
part of releasing the dev associated with the original dst cache entry.
Most of our notifier callbacks are straight-forward, but this one a)
looks complex, and b) places a hold on the network interface in
question.
I constructed a new bcc script that watches various events in the
liftime of a dst cache entry. Note that dst_ifdown will take a hold on
the loopback device until the invalidated dst entry gets freed.
[ __dst_free] on DST: ffff883ccabb7900 IF tap1008300eth0 invoked at 1282115677036183
__dst_free
rcu_nocb_kthread
kthread
ret_from_fork
Acked-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/core/dst.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -470,6 +470,20 @@ static int dst_dev_event(struct notifier
spin_lock_bh(&dst_garbage.lock);
dst = dst_garbage.list;
dst_garbage.list = NULL;
+ /* The code in dst_ifdown places a hold on the loopback device.
+ * If the gc entry processing is set to expire after a lengthy
+ * interval, this hold can cause netdev_wait_allrefs() to hang
+ * out and wait for a long time -- until the the loopback
+ * interface is released. If we're really unlucky, it'll emit
+ * pr_emerg messages to console too. Reset the interval here,
+ * so dst cleanups occur in a more timely fashion.
+ */
+ if (dst_garbage.timer_inc > DST_GC_INC) {
+ dst_garbage.timer_inc = DST_GC_INC;
+ dst_garbage.timer_expires = DST_GC_MIN;
+ mod_delayed_work(system_wq, &dst_gc_work,
+ dst_garbage.timer_expires);
+ }
spin_unlock_bh(&dst_garbage.lock);
if (last)
@@ -0,0 +1,82 @@
From foo@baz Thu Jun 29 18:57:46 CEST 2017
From: WANG Cong <xiyou.wangcong@gmail.com>
Date: Mon, 12 Jun 2017 09:52:26 -0700
Subject: igmp: acquire pmc lock for ip_mc_clear_src()
From: WANG Cong <xiyou.wangcong@gmail.com>
[ Upstream commit c38b7d327aafd1e3ad7ff53eefac990673b65667 ]
Andrey reported a use-after-free in add_grec():
for (psf = *psf_list; psf; psf = psf_next) {
...
psf_next = psf->sf_next;
where the struct ip_sf_list's were already freed by:
kfree+0xe8/0x2b0 mm/slub.c:3882
ip_mc_clear_src+0x69/0x1c0 net/ipv4/igmp.c:2078
ip_mc_dec_group+0x19a/0x470 net/ipv4/igmp.c:1618
ip_mc_drop_socket+0x145/0x230 net/ipv4/igmp.c:2609
inet_release+0x4e/0x1c0 net/ipv4/af_inet.c:411
sock_release+0x8d/0x1e0 net/socket.c:597
sock_close+0x16/0x20 net/socket.c:1072
This happens because we don't hold pmc->lock in ip_mc_clear_src()
and a parallel mr_ifc_timer timer could jump in and access them.
The RCU lock is there but it is merely for pmc itself, this
spinlock could actually ensure we don't access them in parallel.
Thanks to Eric and Long for discussion on this bug.
Reported-by: Andrey Konovalov <andreyknvl@google.com>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Xin Long <lucien.xin@gmail.com>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
Reviewed-by: Xin Long <lucien.xin@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/ipv4/igmp.c | 21 +++++++++++++--------
1 file changed, 13 insertions(+), 8 deletions(-)
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -2071,21 +2071,26 @@ static int ip_mc_add_src(struct in_devic
static void ip_mc_clear_src(struct ip_mc_list *pmc)
{
- struct ip_sf_list *psf, *nextpsf;
+ struct ip_sf_list *psf, *nextpsf, *tomb, *sources;
- for (psf = pmc->tomb; psf; psf = nextpsf) {
+ spin_lock_bh(&pmc->lock);
+ tomb = pmc->tomb;
+ pmc->tomb = NULL;
+ sources = pmc->sources;
+ pmc->sources = NULL;
+ pmc->sfmode = MCAST_EXCLUDE;
+ pmc->sfcount[MCAST_INCLUDE] = 0;
+ pmc->sfcount[MCAST_EXCLUDE] = 1;
+ spin_unlock_bh(&pmc->lock);
+
+ for (psf = tomb; psf; psf = nextpsf) {
nextpsf = psf->sf_next;
kfree(psf);
}
- pmc->tomb = NULL;
- for (psf = pmc->sources; psf; psf = nextpsf) {
+ for (psf = sources; psf; psf = nextpsf) {
nextpsf = psf->sf_next;
kfree(psf);
}
- pmc->sources = NULL;
- pmc->sfmode = MCAST_EXCLUDE;
- pmc->sfcount[MCAST_INCLUDE] = 0;
- pmc->sfcount[MCAST_EXCLUDE] = 1;
}
/* Join a multicast group
@@ -0,0 +1,57 @@
From foo@baz Thu Jun 29 18:57:46 CEST 2017
From: WANG Cong <xiyou.wangcong@gmail.com>
Date: Tue, 20 Jun 2017 10:46:27 -0700
Subject: igmp: add a missing spin_lock_init()
From: WANG Cong <xiyou.wangcong@gmail.com>
[ Upstream commit b4846fc3c8559649277e3e4e6b5cec5348a8d208 ]
Andrey reported a lockdep warning on non-initialized
spinlock:
INFO: trying to register non-static key.
the code is fine but needs lockdep annotation.
turning off the locking correctness validator.
CPU: 1 PID: 4099 Comm: a.out Not tainted 4.12.0-rc6+ #9
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
Call Trace:
__dump_stack lib/dump_stack.c:16
dump_stack+0x292/0x395 lib/dump_stack.c:52
register_lock_class+0x717/0x1aa0 kernel/locking/lockdep.c:755
? 0xffffffffa0000000
__lock_acquire+0x269/0x3690 kernel/locking/lockdep.c:3255
lock_acquire+0x22d/0x560 kernel/locking/lockdep.c:3855
__raw_spin_lock_bh ./include/linux/spinlock_api_smp.h:135
_raw_spin_lock_bh+0x36/0x50 kernel/locking/spinlock.c:175
spin_lock_bh ./include/linux/spinlock.h:304
ip_mc_clear_src+0x27/0x1e0 net/ipv4/igmp.c:2076
igmpv3_clear_delrec+0xee/0x4f0 net/ipv4/igmp.c:1194
ip_mc_destroy_dev+0x4e/0x190 net/ipv4/igmp.c:1736
We miss a spin_lock_init() in igmpv3_add_delrec(), probably
because previously we never use it on this code path. Since
we already unlink it from the global mc_tomb list, it is
probably safe not to acquire this spinlock here. It does not
harm to have it although, to avoid conditional locking.
Fixes: c38b7d327aaf ("igmp: acquire pmc lock for ip_mc_clear_src()")
Reported-by: Andrey Konovalov <andreyknvl@google.com>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/ipv4/igmp.c | 1 +
1 file changed, 1 insertion(+)
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -1112,6 +1112,7 @@ static void igmpv3_add_delrec(struct in_
pmc = kzalloc(sizeof(*pmc), GFP_KERNEL);
if (!pmc)
return;
+ spin_lock_init(&pmc->lock);
spin_lock_bh(&im->lock);
pmc->interface = im->interface;
in_dev_hold(in_dev);
@@ -0,0 +1,95 @@
From foo@baz Thu Jun 29 18:57:46 CEST 2017
From: Serhey Popovych <serhe.popovych@gmail.com>
Date: Tue, 20 Jun 2017 13:29:25 +0300
Subject: ipv6: Do not leak throw route references
From: Serhey Popovych <serhe.popovych@gmail.com>
[ Upstream commit 07f615574f8ac499875b21c1142f26308234a92c ]
While commit 73ba57bfae4a ("ipv6: fix backtracking for throw routes")
does good job on error propagation to the fib_rules_lookup()
in fib rules core framework that also corrects throw routes
handling, it does not solve route reference leakage problem
happened when we return -EAGAIN to the fib_rules_lookup()
and leave routing table entry referenced in arg->result.
If rule with matched throw route isn't last matched in the
list we overwrite arg->result losing reference on throw
route stored previously forever.
We also partially revert commit ab997ad40839 ("ipv6: fix the
incorrect return value of throw route") since we never return
routing table entry with dst.error == -EAGAIN when
CONFIG_IPV6_MULTIPLE_TABLES is on. Also there is no point
to check for RTF_REJECT flag since it is always set throw
route.
Fixes: 73ba57bfae4a ("ipv6: fix backtracking for throw routes")
Signed-off-by: Serhey Popovych <serhe.popovych@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/ipv6/fib6_rules.c | 22 ++++++----------------
net/ipv6/ip6_fib.c | 3 +--
2 files changed, 7 insertions(+), 18 deletions(-)
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -32,7 +32,6 @@ struct fib6_rule {
struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
int flags, pol_lookup_t lookup)
{
- struct rt6_info *rt;
struct fib_lookup_arg arg = {
.lookup_ptr = lookup,
.flags = FIB_LOOKUP_NOREF,
@@ -44,21 +43,11 @@ struct dst_entry *fib6_rule_lookup(struc
fib_rules_lookup(net->ipv6.fib6_rules_ops,
flowi6_to_flowi(fl6), flags, &arg);
- rt = arg.result;
+ if (arg.result)
+ return arg.result;
- if (!rt) {
- dst_hold(&net->ipv6.ip6_null_entry->dst);
- return &net->ipv6.ip6_null_entry->dst;
- }
-
- if (rt->rt6i_flags & RTF_REJECT &&
- rt->dst.error == -EAGAIN) {
- ip6_rt_put(rt);
- rt = net->ipv6.ip6_null_entry;
- dst_hold(&rt->dst);
- }
-
- return &rt->dst;
+ dst_hold(&net->ipv6.ip6_null_entry->dst);
+ return &net->ipv6.ip6_null_entry->dst;
}
static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
@@ -121,7 +110,8 @@ static int fib6_rule_action(struct fib_r
flp6->saddr = saddr;
}
err = rt->dst.error;
- goto out;
+ if (err != -EAGAIN)
+ goto out;
}
again:
ip6_rt_put(rt);
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -289,8 +289,7 @@ struct dst_entry *fib6_rule_lookup(struc
struct rt6_info *rt;
rt = lookup(net, net->ipv6.fib6_main_tbl, fl6, flags);
- if (rt->rt6i_flags & RTF_REJECT &&
- rt->dst.error == -EAGAIN) {
+ if (rt->dst.error == -EAGAIN) {
ip6_rt_put(rt);
rt = net->ipv6.ip6_null_entry;
dst_hold(&rt->dst);
@@ -0,0 +1,64 @@
From foo@baz Thu Jun 29 18:57:46 CEST 2017
From: Xin Long <lucien.xin@gmail.com>
Date: Thu, 15 Jun 2017 16:33:58 +0800
Subject: ipv6: fix calling in6_ifa_hold incorrectly for dad work
From: Xin Long <lucien.xin@gmail.com>
[ Upstream commit f8a894b218138888542a5058d0e902378fd0d4ec ]
Now when starting the dad work in addrconf_mod_dad_work, if the dad work
is idle and queued, it needs to hold ifa.
The problem is there's one gap in [1], during which if the pending dad work
is removed elsewhere. It will miss to hold ifa, but the dad word is still
idea and queue.
if (!delayed_work_pending(&ifp->dad_work))
in6_ifa_hold(ifp);
<--------------[1]
mod_delayed_work(addrconf_wq, &ifp->dad_work, delay);
An use-after-free issue can be caused by this.
Chen Wei found this issue when WARN_ON(!hlist_unhashed(&ifp->addr_lst)) in
net6_ifa_finish_destroy was hit because of it.
As Hannes' suggestion, this patch is to fix it by holding ifa first in
addrconf_mod_dad_work, then calling mod_delayed_work and putting ifa if
the dad_work is already in queue.
Note that this patch did not choose to fix it with:
if (!mod_delayed_work(delay))
in6_ifa_hold(ifp);
As with it, when delay == 0, dad_work would be scheduled immediately, all
addrconf_mod_dad_work(0) callings had to be moved under ifp->lock.
Reported-by: Wei Chen <weichen@redhat.com>
Suggested-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: Xin Long <lucien.xin@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/ipv6/addrconf.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -315,9 +315,9 @@ static void addrconf_mod_rs_timer(struct
static void addrconf_mod_dad_work(struct inet6_ifaddr *ifp,
unsigned long delay)
{
- if (!delayed_work_pending(&ifp->dad_work))
- in6_ifa_hold(ifp);
- mod_delayed_work(addrconf_wq, &ifp->dad_work, delay);
+ in6_ifa_hold(ifp);
+ if (mod_delayed_work(addrconf_wq, &ifp->dad_work, delay))
+ in6_ifa_put(ifp);
}
static int snmp6_alloc_dev(struct inet6_dev *idev)
@@ -0,0 +1,38 @@
From 00ea1ceebe0d9f2dc1cc2b7bd575a00100c27869 Mon Sep 17 00:00:00 2001
From: Willem de Bruijn <willemb@google.com>
Date: Sat, 18 Feb 2017 19:00:45 -0500
Subject: ipv6: release dst on error in ip6_dst_lookup_tail
From: Willem de Bruijn <willemb@google.com>
commit 00ea1ceebe0d9f2dc1cc2b7bd575a00100c27869 upstream.
If ip6_dst_lookup_tail has acquired a dst and fails the IPv4-mapped
check, release the dst before returning an error.
Fixes: ec5e3b0a1d41 ("ipv6: Inhibit IPv4-mapped src address on the wire.")
Signed-off-by: Willem de Bruijn <willemb@google.com>
Acked-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Cc: Ben Hutchings <ben.hutchings@codethink.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/ipv6/ip6_output.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1020,8 +1020,10 @@ static int ip6_dst_lookup_tail(struct ne
}
#endif
if (ipv6_addr_v4mapped(&fl6->saddr) &&
- !(ipv6_addr_v4mapped(&fl6->daddr) || ipv6_addr_any(&fl6->daddr)))
- return -EAFNOSUPPORT;
+ !(ipv6_addr_v4mapped(&fl6->daddr) || ipv6_addr_any(&fl6->daddr))) {
+ err = -EAFNOSUPPORT;
+ goto out_err_release;
+ }
return 0;
@@ -0,0 +1,73 @@
From foo@baz Thu Jun 29 18:57:46 CEST 2017
From: Gao Feng <gfree.wind@vip.163.com>
Date: Fri, 16 Jun 2017 15:00:02 +0800
Subject: net: 8021q: Fix one possible panic caused by BUG_ON in free_netdev
From: Gao Feng <gfree.wind@vip.163.com>
[ Upstream commit 9745e362add89432d2c951272a99b0a5fe4348a9 ]
The register_vlan_device would invoke free_netdev directly, when
register_vlan_dev failed. It would trigger the BUG_ON in free_netdev
if the dev was already registered. In this case, the netdev would be
freed in netdev_run_todo later.
So add one condition check now. Only when dev is not registered, then
free it directly.
The following is the part coredump when netdev_upper_dev_link failed
in register_vlan_dev. I removed the lines which are too long.
[ 411.237457] ------------[ cut here ]------------
[ 411.237458] kernel BUG at net/core/dev.c:7998!
[ 411.237484] invalid opcode: 0000 [#1] SMP
[ 411.237705] [last unloaded: 8021q]
[ 411.237718] CPU: 1 PID: 12845 Comm: vconfig Tainted: G E 4.12.0-rc5+ #6
[ 411.237737] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 07/02/2015
[ 411.237764] task: ffff9cbeb6685580 task.stack: ffffa7d2807d8000
[ 411.237782] RIP: 0010:free_netdev+0x116/0x120
[ 411.237794] RSP: 0018:ffffa7d2807dbdb0 EFLAGS: 00010297
[ 411.237808] RAX: 0000000000000002 RBX: ffff9cbeb6ba8fd8 RCX: 0000000000001878
[ 411.237826] RDX: 0000000000000001 RSI: 0000000000000282 RDI: 0000000000000000
[ 411.237844] RBP: ffffa7d2807dbdc8 R08: 0002986100029841 R09: 0002982100029801
[ 411.237861] R10: 0004000100029980 R11: 0004000100029980 R12: ffff9cbeb6ba9000
[ 411.238761] R13: ffff9cbeb6ba9060 R14: ffff9cbe60f1a000 R15: ffff9cbeb6ba9000
[ 411.239518] FS: 00007fb690d81700(0000) GS:ffff9cbebb640000(0000) knlGS:0000000000000000
[ 411.239949] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 411.240454] CR2: 00007f7115624000 CR3: 0000000077cdf000 CR4: 00000000003406e0
[ 411.240936] Call Trace:
[ 411.241462] vlan_ioctl_handler+0x3f1/0x400 [8021q]
[ 411.241910] sock_ioctl+0x18b/0x2c0
[ 411.242394] do_vfs_ioctl+0xa1/0x5d0
[ 411.242853] ? sock_alloc_file+0xa6/0x130
[ 411.243465] SyS_ioctl+0x79/0x90
[ 411.243900] entry_SYSCALL_64_fastpath+0x1e/0xa9
[ 411.244425] RIP: 0033:0x7fb69089a357
[ 411.244863] RSP: 002b:00007ffcd04e0fc8 EFLAGS: 00000202 ORIG_RAX: 0000000000000010
[ 411.245445] RAX: ffffffffffffffda RBX: 00007ffcd04e2884 RCX: 00007fb69089a357
[ 411.245903] RDX: 00007ffcd04e0fd0 RSI: 0000000000008983 RDI: 0000000000000003
[ 411.246527] RBP: 00007ffcd04e0fd0 R08: 0000000000000000 R09: 1999999999999999
[ 411.246976] R10: 000000000000053f R11: 0000000000000202 R12: 0000000000000004
[ 411.247414] R13: 00007ffcd04e1128 R14: 00007ffcd04e2888 R15: 0000000000000001
[ 411.249129] RIP: free_netdev+0x116/0x120 RSP: ffffa7d2807dbdb0
Signed-off-by: Gao Feng <gfree.wind@vip.163.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/8021q/vlan.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -277,7 +277,8 @@ static int register_vlan_device(struct n
return 0;
out_free_newdev:
- free_netdev(new_dev);
+ if (new_dev->reg_state == NETREG_UNINITIALIZED)
+ free_netdev(new_dev);
return err;
}
@@ -0,0 +1,50 @@
From foo@baz Thu Jun 29 18:57:46 CEST 2017
From: Jia-Ju Bai <baijiaju1990@163.com>
Date: Sat, 10 Jun 2017 16:49:39 +0800
Subject: net: caif: Fix a sleep-in-atomic bug in cfpkt_create_pfx
From: Jia-Ju Bai <baijiaju1990@163.com>
[ Upstream commit f146e872eb12ebbe92d8e583b2637e0741440db3 ]
The kernel may sleep under a rcu read lock in cfpkt_create_pfx, and the
function call path is:
cfcnfg_linkup_rsp (acquire the lock by rcu_read_lock)
cfctrl_linkdown_req
cfpkt_create
cfpkt_create_pfx
alloc_skb(GFP_KERNEL) --> may sleep
cfserl_receive (acquire the lock by rcu_read_lock)
cfpkt_split
cfpkt_create_pfx
alloc_skb(GFP_KERNEL) --> may sleep
There is "in_interrupt" in cfpkt_create_pfx to decide use "GFP_KERNEL" or
"GFP_ATOMIC". In this situation, "GFP_KERNEL" is used because the function
is called under a rcu read lock, instead in interrupt.
To fix it, only "GFP_ATOMIC" is used in cfpkt_create_pfx.
Signed-off-by: Jia-Ju Bai <baijiaju1990@163.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/caif/cfpkt_skbuff.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
--- a/net/caif/cfpkt_skbuff.c
+++ b/net/caif/cfpkt_skbuff.c
@@ -81,11 +81,7 @@ static struct cfpkt *cfpkt_create_pfx(u1
{
struct sk_buff *skb;
- if (likely(in_interrupt()))
- skb = alloc_skb(len + pfx, GFP_ATOMIC);
- else
- skb = alloc_skb(len + pfx, GFP_KERNEL);
-
+ skb = alloc_skb(len + pfx, GFP_ATOMIC);
if (unlikely(skb == NULL))
return NULL;
@@ -0,0 +1,34 @@
From foo@baz Thu Jun 29 18:57:46 CEST 2017
From: Alexander Potapenko <glider@google.com>
Date: Tue, 6 Jun 2017 15:56:54 +0200
Subject: net: don't call strlen on non-terminated string in dev_set_alias()
From: Alexander Potapenko <glider@google.com>
[ Upstream commit c28294b941232931fbd714099798eb7aa7e865d7 ]
KMSAN reported a use of uninitialized memory in dev_set_alias(),
which was caused by calling strlcpy() (which in turn called strlen())
on the user-supplied non-terminated string.
Signed-off-by: Alexander Potapenko <glider@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/core/dev.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1250,8 +1250,9 @@ int dev_set_alias(struct net_device *dev
if (!new_ifalias)
return -ENOMEM;
dev->ifalias = new_ifalias;
+ memcpy(dev->ifalias, alias, len);
+ dev->ifalias[len] = 0;
- strlcpy(dev->ifalias, alias, len+1);
return len;
}
@@ -0,0 +1,56 @@
From foo@baz Thu Jun 29 18:57:46 CEST 2017
From: Eli Cohen <eli@mellanox.com>
Date: Thu, 8 Jun 2017 11:33:16 -0500
Subject: net/mlx5: Wait for FW readiness before initializing command interface
From: Eli Cohen <eli@mellanox.com>
[ Upstream commit 6c780a0267b8a1075f40b39851132eeaefefcff5 ]
Before attempting to initialize the command interface we must wait till
the fw_initializing bit is clear.
If we fail to meet this condition the hardware will drop our
configuration, specifically the descriptors page address. This scenario
can happen when the firmware is still executing an FLR flow and did not
finish yet so the driver needs to wait for that to finish.
Fixes: e3297246c2c8 ('net/mlx5_core: Wait for FW readiness on startup')
Signed-off-by: Eli Cohen <eli@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/ethernet/mellanox/mlx5/core/main.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
@@ -155,8 +155,9 @@ static struct mlx5_profile profile[] = {
},
};
-#define FW_INIT_TIMEOUT_MILI 2000
-#define FW_INIT_WAIT_MS 2
+#define FW_INIT_TIMEOUT_MILI 2000
+#define FW_INIT_WAIT_MS 2
+#define FW_PRE_INIT_TIMEOUT_MILI 10000
static int wait_fw_init(struct mlx5_core_dev *dev, u32 max_wait_mili)
{
@@ -956,6 +957,15 @@ static int mlx5_load_one(struct mlx5_cor
*/
dev->state = MLX5_DEVICE_STATE_UP;
+ /* wait for firmware to accept initialization segments configurations
+ */
+ err = wait_fw_init(dev, FW_PRE_INIT_TIMEOUT_MILI);
+ if (err) {
+ dev_err(&dev->pdev->dev, "Firmware over %d MS in pre-initializing state, aborting\n",
+ FW_PRE_INIT_TIMEOUT_MILI);
+ goto out;
+ }
+
err = mlx5_cmd_init(dev);
if (err) {
dev_err(&pdev->dev, "Failed initializing command interface, aborting\n");
@@ -0,0 +1,130 @@
From foo@baz Thu Jun 29 18:57:46 CEST 2017
From: Tal Gilboa <talgi@mellanox.com>
Date: Mon, 15 May 2017 14:13:16 +0300
Subject: net/mlx5e: Added BW check for DIM decision mechanism
From: Tal Gilboa <talgi@mellanox.com>
[ Upstream commit c3164d2fc48fd4fa0477ab658b644559c3fe9073 ]
DIM (Dynamically-tuned Interrupt Moderation) is a mechanism designed for
changing the channel interrupt moderation values in order to reduce CPU
overhead for all traffic types.
Until now only interrupt and packet rate were sampled.
We found a scenario on which we get a false indication since a change in
DIM caused more aggregation and reduced packet rate while increasing BW.
We now regard a change as succesfull iff:
current_BW > (prev_BW + threshold) or
current_BW ~= prev_BW and current_PR > (prev_PR + threshold) or
current_BW ~= prev_BW and current_PR ~= prev_PR and
current_IR < (prev_IR - threshold)
Where BW = Bandwidth, PR = Packet rate and IR = Interrupt rate
Improvements (ConnectX-4Lx 25GbE, single RX queue, LRO off)
--------------------------------------------------
packet size | before[Mb/s] | after[Mb/s] | gain |
2B | 343.4 | 359.4 | 4.5% |
16B | 2739.7 | 2814.8 | 2.7% |
64B | 9739 | 10185.3 | 4.5% |
Fixes: cb3c7fd4f839 ("net/mlx5e: Support adaptive RX coalescing")
Signed-off-by: Tal Gilboa <talgi@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/ethernet/mellanox/mlx5/core/en.h | 2 +
drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c | 41 +++++++++++----------
2 files changed, 24 insertions(+), 19 deletions(-)
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -283,12 +283,14 @@ struct mlx5e_dma_info {
struct mlx5e_rx_am_stats {
int ppms; /* packets per msec */
+ int bpms; /* bytes per msec */
int epms; /* events per msec */
};
struct mlx5e_rx_am_sample {
ktime_t time;
unsigned int pkt_ctr;
+ unsigned int byte_ctr;
u16 event_ctr;
};
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c
@@ -183,28 +183,27 @@ static void mlx5e_am_exit_parking(struct
mlx5e_am_step(am);
}
+#define IS_SIGNIFICANT_DIFF(val, ref) \
+ (((100 * abs((val) - (ref))) / (ref)) > 10) /* more than 10% difference */
+
static int mlx5e_am_stats_compare(struct mlx5e_rx_am_stats *curr,
struct mlx5e_rx_am_stats *prev)
{
- int diff;
-
- if (!prev->ppms)
- return curr->ppms ? MLX5E_AM_STATS_BETTER :
- MLX5E_AM_STATS_SAME;
-
- diff = curr->ppms - prev->ppms;
- if (((100 * abs(diff)) / prev->ppms) > 10) /* more than 10% diff */
- return (diff > 0) ? MLX5E_AM_STATS_BETTER :
- MLX5E_AM_STATS_WORSE;
-
- if (!prev->epms)
- return curr->epms ? MLX5E_AM_STATS_WORSE :
+ if (!prev->bpms)
+ return curr->bpms ? MLX5E_AM_STATS_BETTER :
MLX5E_AM_STATS_SAME;
- diff = curr->epms - prev->epms;
- if (((100 * abs(diff)) / prev->epms) > 10) /* more than 10% diff */
- return (diff < 0) ? MLX5E_AM_STATS_BETTER :
- MLX5E_AM_STATS_WORSE;
+ if (IS_SIGNIFICANT_DIFF(curr->bpms, prev->bpms))
+ return (curr->bpms > prev->bpms) ? MLX5E_AM_STATS_BETTER :
+ MLX5E_AM_STATS_WORSE;
+
+ if (IS_SIGNIFICANT_DIFF(curr->ppms, prev->ppms))
+ return (curr->ppms > prev->ppms) ? MLX5E_AM_STATS_BETTER :
+ MLX5E_AM_STATS_WORSE;
+
+ if (IS_SIGNIFICANT_DIFF(curr->epms, prev->epms))
+ return (curr->epms < prev->epms) ? MLX5E_AM_STATS_BETTER :
+ MLX5E_AM_STATS_WORSE;
return MLX5E_AM_STATS_SAME;
}
@@ -266,6 +265,7 @@ static void mlx5e_am_sample(struct mlx5e
{
s->time = ktime_get();
s->pkt_ctr = rq->stats.packets;
+ s->byte_ctr = rq->stats.bytes;
s->event_ctr = rq->cq.event_ctr;
}
@@ -278,12 +278,15 @@ static void mlx5e_am_calc_stats(struct m
/* u32 holds up to 71 minutes, should be enough */
u32 delta_us = ktime_us_delta(end->time, start->time);
unsigned int npkts = end->pkt_ctr - start->pkt_ctr;
+ unsigned int nbytes = end->byte_ctr - start->byte_ctr;
if (!delta_us)
return;
- curr_stats->ppms = (npkts * USEC_PER_MSEC) / delta_us;
- curr_stats->epms = (MLX5E_AM_NEVENTS * USEC_PER_MSEC) / delta_us;
+ curr_stats->ppms = DIV_ROUND_UP(npkts * USEC_PER_MSEC, delta_us);
+ curr_stats->bpms = DIV_ROUND_UP(nbytes * USEC_PER_MSEC, delta_us);
+ curr_stats->epms = DIV_ROUND_UP(MLX5E_AM_NEVENTS * USEC_PER_MSEC,
+ delta_us);
}
void mlx5e_rx_am_work(struct work_struct *work)
@@ -0,0 +1,38 @@
From foo@baz Thu Jun 29 18:57:46 CEST 2017
From: Or Gerlitz <ogerlitz@mellanox.com>
Date: Thu, 15 Jun 2017 20:08:32 +0300
Subject: net/mlx5e: Avoid doing a cleanup call if the profile doesn't have it
From: Or Gerlitz <ogerlitz@mellanox.com>
[ Upstream commit 31ac93386d135a6c96de9c8bab406f5ccabf5a4d ]
The error flow of mlx5e_create_netdev calls the cleanup call
of the given profile without checking if it exists, fix that.
Currently the VF reps don't register that callback and we crash
if getting into error -- can be reproduced by the user doing ctrl^C
while attempting to change the sriov mode from legacy to switchdev.
Fixes: 26e59d8077a3 '(net/mlx5e: Implement mlx5e interface attach/detach callbacks')
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Reported-by: Sabrina Dubroca <sdubroca@redhat.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -3846,7 +3846,8 @@ struct net_device *mlx5e_create_netdev(s
return netdev;
err_cleanup_nic:
- profile->cleanup(priv);
+ if (profile->cleanup)
+ profile->cleanup(priv);
free_netdev(netdev);
return NULL;
@@ -0,0 +1,40 @@
From foo@baz Thu Jun 29 18:57:46 CEST 2017
From: Maor Dickman <maord@mellanox.com>
Date: Thu, 18 May 2017 15:15:08 +0300
Subject: net/mlx5e: Fix timestamping capabilities reporting
From: Maor Dickman <maord@mellanox.com>
[ Upstream commit f0b381178b01b831f9907d72f467d6443afdea67 ]
Misuse of (BIT) macro caused to report wrong flags for
"Hardware Transmit Timestamp Modes" and "Hardware Receive
Filter Modes"
Fixes: ef9814deafd0 ('net/mlx5e: Add HW timestamping (TS) support')
Signed-off-by: Maor Dickman <maord@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
@@ -1183,11 +1183,11 @@ static int mlx5e_get_ts_info(struct net_
SOF_TIMESTAMPING_RX_HARDWARE |
SOF_TIMESTAMPING_RAW_HARDWARE;
- info->tx_types = (BIT(1) << HWTSTAMP_TX_OFF) |
- (BIT(1) << HWTSTAMP_TX_ON);
+ info->tx_types = BIT(HWTSTAMP_TX_OFF) |
+ BIT(HWTSTAMP_TX_ON);
- info->rx_filters = (BIT(1) << HWTSTAMP_FILTER_NONE) |
- (BIT(1) << HWTSTAMP_FILTER_ALL);
+ info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) |
+ BIT(HWTSTAMP_FILTER_ALL);
return 0;
}
@@ -0,0 +1,87 @@
From foo@baz Thu Jun 29 18:57:46 CEST 2017
From: Tal Gilboa <talgi@mellanox.com>
Date: Mon, 29 May 2017 17:02:55 +0300
Subject: net/mlx5e: Fix wrong indications in DIM due to counter wraparound
From: Tal Gilboa <talgi@mellanox.com>
[ Upstream commit 53acd76ce571e3b71f9205f2d49ab285a9f1aad8 ]
DIM (Dynamically-tuned Interrupt Moderation) is a mechanism designed for
changing the channel interrupt moderation values in order to reduce CPU
overhead for all traffic types.
Each iteration of the algorithm, DIM calculates the difference in
throughput, packet rate and interrupt rate from last iteration in order
to make a decision. DIM relies on counters for each metric. When these
counters get to their type's max value they wraparound. In this case
the delta between 'end' and 'start' samples is negative and when
translated to unsigned integers - very high. This results in a false
indication to the algorithm and might result in a wrong decision.
The fix calculates the 'distance' between 'end' and 'start' samples in a
cyclic way around the relevant type's max value. It can also be viewed as
an absolute value around the type's max value instead of around 0.
Testing show higher stability in DIM profile selection and no wraparound
issues.
Fixes: cb3c7fd4f839 ("net/mlx5e: Support adaptive RX coalescing")
Signed-off-by: Tal Gilboa <talgi@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/ethernet/mellanox/mlx5/core/en.h | 8 ++++----
drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c | 10 +++++++---
2 files changed, 11 insertions(+), 7 deletions(-)
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -288,10 +288,10 @@ struct mlx5e_rx_am_stats {
};
struct mlx5e_rx_am_sample {
- ktime_t time;
- unsigned int pkt_ctr;
- unsigned int byte_ctr;
- u16 event_ctr;
+ ktime_t time;
+ u32 pkt_ctr;
+ u32 byte_ctr;
+ u16 event_ctr;
};
struct mlx5e_rx_am { /* Adaptive Moderation */
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c
@@ -270,6 +270,8 @@ static void mlx5e_am_sample(struct mlx5e
}
#define MLX5E_AM_NEVENTS 64
+#define BITS_PER_TYPE(type) (sizeof(type) * BITS_PER_BYTE)
+#define BIT_GAP(bits, end, start) ((((end) - (start)) + BIT_ULL(bits)) & (BIT_ULL(bits) - 1))
static void mlx5e_am_calc_stats(struct mlx5e_rx_am_sample *start,
struct mlx5e_rx_am_sample *end,
@@ -277,8 +279,9 @@ static void mlx5e_am_calc_stats(struct m
{
/* u32 holds up to 71 minutes, should be enough */
u32 delta_us = ktime_us_delta(end->time, start->time);
- unsigned int npkts = end->pkt_ctr - start->pkt_ctr;
- unsigned int nbytes = end->byte_ctr - start->byte_ctr;
+ u32 npkts = BIT_GAP(BITS_PER_TYPE(u32), end->pkt_ctr, start->pkt_ctr);
+ u32 nbytes = BIT_GAP(BITS_PER_TYPE(u32), end->byte_ctr,
+ start->byte_ctr);
if (!delta_us)
return;
@@ -311,7 +314,8 @@ void mlx5e_rx_am(struct mlx5e_rq *rq)
switch (am->state) {
case MLX5E_AM_MEASURE_IN_PROGRESS:
- nevents = rq->cq.event_ctr - am->start_sample.event_ctr;
+ nevents = BIT_GAP(BITS_PER_TYPE(u16), rq->cq.event_ctr,
+ am->start_sample.event_ctr);
if (nevents < MLX5E_AM_NEVENTS)
break;
mlx5e_am_sample(rq, &end_sample);
@@ -0,0 +1,44 @@
From foo@baz Thu Jun 29 18:57:46 CEST 2017
From: Jia-Ju Bai <baijiaju1990@163.com>
Date: Sat, 10 Jun 2017 17:03:35 +0800
Subject: net: tipc: Fix a sleep-in-atomic bug in tipc_msg_reverse
From: Jia-Ju Bai <baijiaju1990@163.com>
[ Upstream commit 343eba69c6968190d8654b857aea952fed9a6749 ]
The kernel may sleep under a rcu read lock in tipc_msg_reverse, and the
function call path is:
tipc_l2_rcv_msg (acquire the lock by rcu_read_lock)
tipc_rcv
tipc_sk_rcv
tipc_msg_reverse
pskb_expand_head(GFP_KERNEL) --> may sleep
tipc_node_broadcast
tipc_node_xmit_skb
tipc_node_xmit
tipc_sk_rcv
tipc_msg_reverse
pskb_expand_head(GFP_KERNEL) --> may sleep
To fix it, "GFP_KERNEL" is replaced with "GFP_ATOMIC".
Signed-off-by: Jia-Ju Bai <baijiaju1990@163.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/tipc/msg.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/net/tipc/msg.c
+++ b/net/tipc/msg.c
@@ -508,7 +508,7 @@ bool tipc_msg_reverse(u32 own_node, str
}
if (skb_cloned(_skb) &&
- pskb_expand_head(_skb, BUF_HEADROOM, BUF_TAILROOM, GFP_KERNEL))
+ pskb_expand_head(_skb, BUF_HEADROOM, BUF_TAILROOM, GFP_ATOMIC))
goto exit;
/* Now reverse the concerned fields */
@@ -0,0 +1,110 @@
From foo@baz Thu Jun 29 18:57:46 CEST 2017
From: David Ahern <dsahern@gmail.com>
Date: Thu, 8 Jun 2017 11:31:11 -0600
Subject: net: vrf: Make add_fib_rules per network namespace flag
From: David Ahern <dsahern@gmail.com>
[ Upstream commit 097d3c9508dc58286344e4a22b300098cf0c1566 ]
Commit 1aa6c4f6b8cd8 ("net: vrf: Add l3mdev rules on first device create")
adds the l3mdev FIB rule the first time a VRF device is created. However,
it only creates the rule once and only in the namespace the first device
is created - which may not be init_net. Fix by using the net_generic
capability to make the add_fib_rules flag per network namespace.
Fixes: 1aa6c4f6b8cd8 ("net: vrf: Add l3mdev rules on first device create")
Reported-by: Petr Machata <petrm@mellanox.com>
Signed-off-by: David Ahern <dsahern@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/vrf.c | 36 ++++++++++++++++++++++++++++++++----
1 file changed, 32 insertions(+), 4 deletions(-)
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -36,12 +36,14 @@
#include <net/addrconf.h>
#include <net/l3mdev.h>
#include <net/fib_rules.h>
+#include <net/netns/generic.h>
#define DRV_NAME "vrf"
#define DRV_VERSION "1.0"
#define FIB_RULE_PREF 1000 /* default preference for FIB rules */
-static bool add_fib_rules = true;
+
+static unsigned int vrf_net_id;
struct net_vrf {
struct rtable __rcu *rth;
@@ -1237,6 +1239,8 @@ static int vrf_newlink(struct net *src_n
struct nlattr *tb[], struct nlattr *data[])
{
struct net_vrf *vrf = netdev_priv(dev);
+ bool *add_fib_rules;
+ struct net *net;
int err;
if (!data || !data[IFLA_VRF_TABLE])
@@ -1252,13 +1256,15 @@ static int vrf_newlink(struct net *src_n
if (err)
goto out;
- if (add_fib_rules) {
+ net = dev_net(dev);
+ add_fib_rules = net_generic(net, vrf_net_id);
+ if (*add_fib_rules) {
err = vrf_add_fib_rules(dev);
if (err) {
unregister_netdevice(dev);
goto out;
}
- add_fib_rules = false;
+ *add_fib_rules = false;
}
out:
@@ -1341,16 +1347,38 @@ static struct notifier_block vrf_notifie
.notifier_call = vrf_device_event,
};
+/* Initialize per network namespace state */
+static int __net_init vrf_netns_init(struct net *net)
+{
+ bool *add_fib_rules = net_generic(net, vrf_net_id);
+
+ *add_fib_rules = true;
+
+ return 0;
+}
+
+static struct pernet_operations vrf_net_ops __net_initdata = {
+ .init = vrf_netns_init,
+ .id = &vrf_net_id,
+ .size = sizeof(bool),
+};
+
static int __init vrf_init_module(void)
{
int rc;
register_netdevice_notifier(&vrf_notifier_block);
- rc = rtnl_link_register(&vrf_link_ops);
+ rc = register_pernet_subsys(&vrf_net_ops);
if (rc < 0)
goto error;
+ rc = rtnl_link_register(&vrf_link_ops);
+ if (rc < 0) {
+ unregister_pernet_subsys(&vrf_net_ops);
+ goto error;
+ }
+
return 0;
error:
@@ -0,0 +1,42 @@
From foo@baz Thu Jun 29 18:57:46 CEST 2017
From: "Mintz, Yuval" <Yuval.Mintz@cavium.com>
Date: Wed, 7 Jun 2017 21:00:33 +0300
Subject: net: Zero ifla_vf_info in rtnl_fill_vfinfo()
From: "Mintz, Yuval" <Yuval.Mintz@cavium.com>
[ Upstream commit 0eed9cf58446b28b233388b7f224cbca268b6986 ]
Some of the structure's fields are not initialized by the
rtnetlink. If driver doesn't set those in ndo_get_vf_config(),
they'd leak memory to user.
Signed-off-by: Yuval Mintz <Yuval.Mintz@cavium.com>
CC: Michal Schmidt <mschmidt@redhat.com>
Reviewed-by: Greg Rose <gvrose8192@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/core/rtnetlink.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1130,6 +1130,8 @@ static noinline_for_stack int rtnl_fill_
struct ifla_vf_mac vf_mac;
struct ifla_vf_info ivi;
+ memset(&ivi, 0, sizeof(ivi));
+
/* Not all SR-IOV capable drivers support the
* spoofcheck and "RSS query enable" query. Preset to
* -1 so the user space tool can detect that the driver
@@ -1138,7 +1140,6 @@ static noinline_for_stack int rtnl_fill_
ivi.spoofchk = -1;
ivi.rss_query_en = -1;
ivi.trusted = -1;
- memset(ivi.mac, 0, sizeof(ivi.mac));
/* The default value for VF link state is "auto"
* IFLA_VF_LINK_STATE_AUTO which equals zero
*/
@@ -0,0 +1,32 @@
From foo@baz Thu Jun 29 18:57:46 CEST 2017
From: Christian Perle <christian.perle@secunet.com>
Date: Mon, 12 Jun 2017 10:06:57 +0200
Subject: proc: snmp6: Use correct type in memset
From: Christian Perle <christian.perle@secunet.com>
[ Upstream commit 3500cd73dff48f28f4ba80c171c4c80034d40f76 ]
Reading /proc/net/snmp6 yields bogus values on 32 bit kernels.
Use "u64" instead of "unsigned long" in sizeof().
Fixes: 4a4857b1c81e ("proc: Reduce cache miss in snmp6_seq_show")
Signed-off-by: Christian Perle <christian.perle@secunet.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/ipv6/proc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -219,7 +219,7 @@ static void snmp6_seq_show_item64(struct
u64 buff64[SNMP_MIB_MAX];
int i;
- memset(buff64, 0, sizeof(unsigned long) * SNMP_MIB_MAX);
+ memset(buff64, 0, sizeof(u64) * SNMP_MIB_MAX);
snmp_get_cpu_field64_batch(buff64, itemlist, mib, syncpoff);
for (i = 0; itemlist[i].name; i++)
@@ -0,0 +1,42 @@
From foo@baz Thu Jun 29 18:57:46 CEST 2017
From: Serhey Popovych <serhe.popovych@gmail.com>
Date: Tue, 20 Jun 2017 14:35:23 +0300
Subject: rtnetlink: add IFLA_GROUP to ifla_policy
From: Serhey Popovych <serhe.popovych@gmail.com>
[ Upstream commit db833d40ad3263b2ee3b59a1ba168bb3cfed8137 ]
Network interface groups support added while ago, however
there is no IFLA_GROUP attribute description in policy
and netlink message size calculations until now.
Add IFLA_GROUP attribute to the policy.
Fixes: cbda10fa97d7 ("net_device: add support for network device groups")
Signed-off-by: Serhey Popovych <serhe.popovych@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/core/rtnetlink.c | 2 ++
1 file changed, 2 insertions(+)
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -937,6 +937,7 @@ static noinline size_t if_nlmsg_size(con
+ nla_total_size(1) /* IFLA_LINKMODE */
+ nla_total_size(4) /* IFLA_CARRIER_CHANGES */
+ nla_total_size(4) /* IFLA_LINK_NETNSID */
+ + nla_total_size(4) /* IFLA_GROUP */
+ nla_total_size(ext_filter_mask
& RTEXT_FILTER_VF ? 4 : 0) /* IFLA_NUM_VF */
+ rtnl_vfinfo_size(dev, ext_filter_mask) /* IFLA_VFINFO_LIST */
@@ -1465,6 +1466,7 @@ static const struct nla_policy ifla_poli
[IFLA_LINK_NETNSID] = { .type = NLA_S32 },
[IFLA_PROTO_DOWN] = { .type = NLA_U8 },
[IFLA_XDP] = { .type = NLA_NESTED },
+ [IFLA_GROUP] = { .type = NLA_U32 },
};
static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
@@ -0,0 +1,49 @@
From foo@baz Thu Jun 29 18:57:46 CEST 2017
From: Xin Long <lucien.xin@gmail.com>
Date: Sat, 10 Jun 2017 14:48:14 +0800
Subject: sctp: disable BH in sctp_for_each_endpoint
From: Xin Long <lucien.xin@gmail.com>
[ Upstream commit 581409dacc9176b0de1f6c4ca8d66e13aa8e1b29 ]
Now sctp holds read_lock when foreach sctp_ep_hashtable without disabling
BH. If CPU schedules to another thread A at this moment, the thread A may
be trying to hold the write_lock with disabling BH.
As BH is disabled and CPU cannot schedule back to the thread holding the
read_lock, while the thread A keeps waiting for the read_lock. A dead
lock would be triggered by this.
This patch is to fix this dead lock by calling read_lock_bh instead to
disable BH when holding the read_lock in sctp_for_each_endpoint.
Fixes: 626d16f50f39 ("sctp: export some apis or variables for sctp_diag and reuse some for proc")
Reported-by: Xiumei Mu <xmu@redhat.com>
Signed-off-by: Xin Long <lucien.xin@gmail.com>
Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/sctp/socket.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -4460,13 +4460,13 @@ int sctp_for_each_endpoint(int (*cb)(str
for (head = sctp_ep_hashtable; hash < sctp_ep_hashsize;
hash++, head++) {
- read_lock(&head->lock);
+ read_lock_bh(&head->lock);
sctp_for_each_hentry(epb, &head->chain) {
err = cb(sctp_ep(epb), p);
if (err)
break;
}
- read_unlock(&head->lock);
+ read_unlock_bh(&head->lock);
}
return err;
@@ -0,0 +1,46 @@
From foo@baz Thu Jun 29 18:57:46 CEST 2017
From: Xin Long <lucien.xin@gmail.com>
Date: Thu, 15 Jun 2017 17:49:08 +0800
Subject: sctp: return next obj by passing pos + 1 into sctp_transport_get_idx
From: Xin Long <lucien.xin@gmail.com>
[ Upstream commit 988c7322116970696211e902b468aefec95b6ec4 ]
In sctp_for_each_transport, pos is used to save how many objs it has
dumped. Now it gets the last obj by sctp_transport_get_idx, then gets
the next obj by sctp_transport_get_next.
The issue is that in the meanwhile if some objs in transport hashtable
are removed and the objs nums are less than pos, sctp_transport_get_idx
would return NULL and hti.walker.tbl is NULL as well. At this moment
it should stop hti, instead of continue getting the next obj. Or it
would cause a NULL pointer dereference in sctp_transport_get_next.
This patch is to pass pos + 1 into sctp_transport_get_idx to get the
next obj directly, even if pos > objs nums, it would return NULL and
stop hti.
Fixes: 626d16f50f39 ("sctp: export some apis or variables for sctp_diag and reuse some for proc")
Signed-off-by: Xin Long <lucien.xin@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/sctp/socket.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -4506,9 +4506,8 @@ int sctp_for_each_transport(int (*cb)(st
if (err)
return err;
- sctp_transport_get_idx(net, &hti, pos);
- obj = sctp_transport_get_next(net, &hti);
- for (; obj && !IS_ERR(obj); obj = sctp_transport_get_next(net, &hti)) {
+ obj = sctp_transport_get_idx(net, &hti, pos + 1);
+ for (; !IS_ERR_OR_NULL(obj); obj = sctp_transport_get_next(net, &hti)) {
struct sctp_transport *transport = obj;
if (!sctp_transport_hold(transport))
@@ -0,0 +1,50 @@
From foo@baz Thu Jun 29 18:57:46 CEST 2017
From: Bert Kenward <bkenward@solarflare.com>
Date: Fri, 16 Jun 2017 09:45:08 +0100
Subject: sfc: provide dummy definitions of vswitch functions
From: Bert Kenward <bkenward@solarflare.com>
efx_probe_all() calls efx->type->vswitching_probe during probe. For
SFC4000 (Falcon) NICs this function is not defined, leading to a BUG
with the top of the call stack similar to:
? efx_pci_probe_main+0x29a/0x830
efx_pci_probe+0x7d3/0xe70
vswitching_restore and vswitching_remove also need to be defined.
Fixed in mainline by:
commit 5a6681e22c14 ("sfc: separate out SFC4000 ("Falcon") support into new sfc-falcon driver")
Fixes: 6d8aaaf6f798 ("sfc: create VEB vswitch and vport above default firmware setup")
Signed-off-by: Bert Kenward <bkenward@solarflare.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/ethernet/sfc/falcon.c | 10 ++++++++++
1 file changed, 10 insertions(+)
--- a/drivers/net/ethernet/sfc/falcon.c
+++ b/drivers/net/ethernet/sfc/falcon.c
@@ -2801,6 +2801,11 @@ const struct efx_nic_type falcon_a1_nic_
.timer_period_max = 1 << FRF_AB_TC_TIMER_VAL_WIDTH,
.offload_features = NETIF_F_IP_CSUM,
.mcdi_max_ver = -1,
+#ifdef CONFIG_SFC_SRIOV
+ .vswitching_probe = efx_port_dummy_op_int,
+ .vswitching_restore = efx_port_dummy_op_int,
+ .vswitching_remove = efx_port_dummy_op_void,
+#endif
};
const struct efx_nic_type falcon_b0_nic_type = {
@@ -2902,4 +2907,9 @@ const struct efx_nic_type falcon_b0_nic_
.offload_features = NETIF_F_IP_CSUM | NETIF_F_RXHASH | NETIF_F_NTUPLE,
.mcdi_max_ver = -1,
.max_rx_ip_filters = FR_BZ_RX_FILTER_TBL0_ROWS,
+#ifdef CONFIG_SFC_SRIOV
+ .vswitching_probe = efx_port_dummy_op_int,
+ .vswitching_restore = efx_port_dummy_op_int,
+ .vswitching_remove = efx_port_dummy_op_void,
+#endif
};
@@ -1,32 +0,0 @@
From fd7c99142d77dc4a851879a66715abf12a3193fb Mon Sep 17 00:00:00 2001
From: Dave Martin <Dave.Martin@arm.com>
Date: Fri, 6 Jan 2017 17:54:51 +0000
Subject: tile/ptrace: Preserve previous registers for short regset write
From: Dave Martin <Dave.Martin@arm.com>
commit fd7c99142d77dc4a851879a66715abf12a3193fb upstream.
Ensure that if userspace supplies insufficient data to
PTRACE_SETREGSET to fill all the registers, the thread's old
registers are preserved.
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Signed-off-by: Chris Metcalf <cmetcalf@mellanox.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
arch/tile/kernel/ptrace.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/arch/tile/kernel/ptrace.c
+++ b/arch/tile/kernel/ptrace.c
@@ -111,7 +111,7 @@ static int tile_gpr_set(struct task_stru
const void *kbuf, const void __user *ubuf)
{
int ret;
- struct pt_regs regs;
+ struct pt_regs regs = *task_pt_regs(target);
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &regs, 0,
sizeof(regs));
@@ -0,0 +1,84 @@
From dec08194ffeccfa1cf085906b53d301930eae18f Mon Sep 17 00:00:00 2001
From: Jiahau Chang <jiahau@gmail.com>
Date: Mon, 19 Jun 2017 13:08:30 +0300
Subject: xhci: Limit USB2 port wake support for AMD Promontory hosts
For AMD Promontory xHCI host, although you can disable USB 2.0 ports in
BIOS settings, those ports will be enabled anyway after you remove a
device on that port and re-plug it in again. It's a known limitation of
the chip. As a workaround we can clear the PORT_WAKE_BITS.
This will disable wake on connect, disconnect and overcurrent on
AMD Promontory USB2 ports
[checkpatch cleanup and commit message reword -Mathias]
Cc: <stable@vger.kernel.org>
Cc: Tsai Nicholas <nicholas.tsai@amd.com>
Signed-off-by: Jiahau Chang <Lars_Chang@asmedia.com.tw>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/usb/host/xhci-hub.c | 3 +++
drivers/usb/host/xhci-pci.c | 12 ++++++++++++
drivers/usb/host/xhci.h | 1 +
3 files changed, 16 insertions(+)
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 0dde49c..1adae9e 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -1461,6 +1461,9 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
t2 |= PORT_WKOC_E | PORT_WKCONN_E;
t2 &= ~PORT_WKDISC_E;
}
+ if ((xhci->quirks & XHCI_U2_DISABLE_WAKE) &&
+ (hcd->speed < HCD_USB3))
+ t2 &= ~PORT_WAKE_BITS;
} else
t2 &= ~PORT_WAKE_BITS;
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 1bcf971..0965bae 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -54,6 +54,11 @@
#define PCI_DEVICE_ID_INTEL_APL_XHCI 0x5aa8
#define PCI_DEVICE_ID_INTEL_DNV_XHCI 0x19d0
+#define PCI_DEVICE_ID_AMD_PROMONTORYA_4 0x43b9
+#define PCI_DEVICE_ID_AMD_PROMONTORYA_3 0x43ba
+#define PCI_DEVICE_ID_AMD_PROMONTORYA_2 0x43bb
+#define PCI_DEVICE_ID_AMD_PROMONTORYA_1 0x43bc
+
static const char hcd_name[] = "xhci_hcd";
static struct hc_driver __read_mostly xhci_pci_hc_driver;
@@ -135,6 +140,13 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
if (pdev->vendor == PCI_VENDOR_ID_AMD)
xhci->quirks |= XHCI_TRUST_TX_LENGTH;
+ if ((pdev->vendor == PCI_VENDOR_ID_AMD) &&
+ ((pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_4) ||
+ (pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_3) ||
+ (pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_2) ||
+ (pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_1)))
+ xhci->quirks |= XHCI_U2_DISABLE_WAKE;
+
if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
xhci->quirks |= XHCI_LPM_SUPPORT;
xhci->quirks |= XHCI_INTEL_HOST;
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 73a28a9..dcd9649 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1819,6 +1819,7 @@ struct xhci_hcd {
/* For controller with a broken Port Disable implementation */
#define XHCI_BROKEN_PORT_PED (1 << 25)
#define XHCI_LIMIT_ENDPOINT_INTERVAL_7 (1 << 26)
+#define XHCI_U2_DISABLE_WAKE (1 << 27)
unsigned int num_active_eps;
unsigned int limit_active_eps;
--
cgit v1.1
File diff suppressed because it is too large Load Diff
+73 -17
View File
@@ -28,25 +28,48 @@
</BuildDependencies>
<Patches>
<!-- Linux patches -->
<Patch level="1" compressionType="xz">patches/linux/patch-4.9.6.xz</Patch>
<!-- Mageia Linux patches // compatible with http://svnweb.mageia.org/packages/cauldron/kernel/releases/4.9.6/1.mga6/PATCHES/patches/series-->
<Patch level="1" compressionType="xz">patches/linux/patch-4.9.35.xz</Patch>
<!-- Mageia Linux patches // compatible with http://svnweb.mageia.org/packages/cauldron/kernel/releases/4.9.35/1.mga6/PATCHES/patches/series-->
<!--stable patches-->
<Patch level="1">patches/mageia/stable-ipv6-release-dst-on-error-in-ip6_dst_lookup_tail.patch</Patch>
<Patch level="1">patches/mageia/stable-net-don-t-call-strlen-on-non-terminated-string-in-dev_set_alias.patch</Patch>
<Patch level="1">patches/mageia/stable-decnet-dn_rtmsg-improve-input-length-sanitization-in-dnrmg_receive_user_skb.patch</Patch>
<Patch level="1">patches/mageia/stable-net-zero-ifla_vf_info-in-rtnl_fill_vfinfo.patch</Patch>
<Patch level="1">patches/mageia/stable-net-vrf-make-add_fib_rules-per-network-namespace-flag.patch</Patch>
<Patch level="1">patches/mageia/stable-af_unix-add-sockaddr-length-checks-before-accessing-sa_family-in-bind-and-connect-handlers.patch</Patch>
<Patch level="1">patches/mageia/stable-fix-an-intermittent-pr_emerg-warning-about-lo-becoming-free.patch</Patch>
<Patch level="1">patches/mageia/stable-sctp-disable-bh-in-sctp_for_each_endpoint.patch</Patch>
<Patch level="1">patches/mageia/stable-net-caif-fix-a-sleep-in-atomic-bug-in-cfpkt_create_pfx.patch</Patch>
<Patch level="1">patches/mageia/stable-net-tipc-fix-a-sleep-in-atomic-bug-in-tipc_msg_reverse.patch</Patch>
<Patch level="1">patches/mageia/stable-net-mlx5e-added-bw-check-for-dim-decision-mechanism.patch</Patch>
<Patch level="1">patches/mageia/stable-net-mlx5e-fix-wrong-indications-in-dim-due-to-counter-wraparound.patch</Patch>
<Patch level="1">patches/mageia/stable-proc-snmp6-use-correct-type-in-memset.patch</Patch>
<Patch level="1">patches/mageia/stable-igmp-acquire-pmc-lock-for-ip_mc_clear_src.patch</Patch>
<Patch level="1">patches/mageia/stable-igmp-add-a-missing-spin_lock_init.patch</Patch>
<Patch level="1">patches/mageia/stable-ipv6-fix-calling-in6_ifa_hold-incorrectly-for-dad-work.patch</Patch>
<Patch level="1">patches/mageia/stable-sctp-return-next-obj-by-passing-pos-1-into-sctp_transport_get_idx.patch</Patch>
<Patch level="1">patches/mageia/stable-net-mlx5e-avoid-doing-a-cleanup-call-if-the-profile-doesn-t-have-it.patch</Patch>
<Patch level="1">patches/mageia/stable-net-mlx5-wait-for-fw-readiness-before-initializing-command-interface.patch</Patch>
<Patch level="1">patches/mageia/stable-net-mlx5e-fix-timestamping-capabilities-reporting.patch</Patch>
<Patch level="1">patches/mageia/stable-decnet-always-not-take-dst-__refcnt-when-inserting-dst-into-hash-table.patch</Patch>
<Patch level="1">patches/mageia/stable-net-8021q-fix-one-possible-panic-caused-by-bug_on-in-free_netdev.patch</Patch>
<Patch level="1">patches/mageia/stable-sfc-provide-dummy-definitions-of-vswitch-functions.patch</Patch>
<Patch level="1">patches/mageia/stable-ipv6-do-not-leak-throw-route-references.patch</Patch>
<Patch level="1">patches/mageia/stable-rtnetlink-add-ifla_group-to-ifla_policy.patch</Patch>
<!--CVE-2016-8405-->
<Patch level="1">patches/mageia/stable-fbdev-color-map-copying-bounds-checking.patch</Patch>
<Patch level="1">patches/mageia/stable-tile-ptrace-preserve-previous-registers-for-short-regset-write.patch</Patch>
<Patch level="1">patches/mageia/stable-drm-schedule-the-output_poll_work-with-1s-delay-if-we-have-delayed-event.patch</Patch>
<Patch level="1">patches/mageia/stable-drm-fix-broken-vt-switch-with-video-1366x768-option.patch</Patch>
<Patch level="1">patches/mageia/stable-drm-i915-ignore-bogus-plane-coordinates-on-skl-when-the-plane-is-not-visible.patch</Patch>
<!--other patches-->
<Patch level="1">patches/mageia/Revert-cpufreq-pcc-Enable-autoload-of-pcc-cpufreq-fo.patch</Patch>
<Patch level="1">patches/mageia/Revert-x86-mm-mtrr-Remove-kernel-internal-MTRR-inter.patch</Patch>
<Patch level="1">patches/mageia/base-cacheinfo-silence-DT-warnings.patch</Patch>
<Patch level="1">patches/mageia/iommu-amd-flush-IOTLB-for-specific-domains-only-v3.patch</Patch>
<Patch level="1">patches/mageia/pci-add-ALI-M5229-ide-compatibility-mode-quirk.patch</Patch>
<Patch level="1">patches/mageia/pci-quirks-drop-devinit-exit.patch</Patch>
<Patch level="1">patches/mageia/pci-Blacklist-AMD-Stoney-GPU-devices-for-ATS.patch</Patch>
<Patch level="1">patches/mageia/acpi-CLEVO-M360S-disable_acpi_irq.patch</Patch>
<Patch level="1">patches/mageia/acpi-processor-M720SR-limit-to-C2.patch</Patch>
<Patch level="1">patches/mageia/ACPI-video-Add-a-quirk-to-force-acpi-video-backlight.patch</Patch>
<Patch level="1">patches/mageia/acpi-do-not-warn-if-_BQC-does-not-exist.patch</Patch>
<Patch level="1">patches/mageia/acpi-ACPICA-Events-Fix-acpi_ev_initialize_region-return-v.patch</Patch>
<!--Patch level="1">patches/mageia/scsi-ppscsi-2.6.2.patch</Patch>
<Patch level="1">patches/mageia/scsi-ppscsi_fixes.patch</Patch>
<Patch level="1">patches/mageia/scsi-ppscsi-sg-helper-update.patch</Patch>
@@ -60,17 +83,23 @@
<Patch level="1">patches/mageia/block-floppy-disable-pnp-modalias.patch</Patch>
<Patch level="1">patches/mageia/ata-prefer-ata-drivers-over-ide-drivers-when-both-are-built.patch</Patch>
<Patch level="1">patches/mageia/block-Make-CFQ-default-to-IOPS-mode-on-SSDs.patch</Patch>
<!--Patch level="1">patches/mageia/block-cgroups-kconfig-build-bits-for-BFQ-v7r11-4.5.0.patch</Patch>
<!--2-->
<Patch level="1">patches/mageia/block-cgroups-kconfig-build-bits-for-BFQ-v7r11-4.5.0.patch</Patch>
<Patch level="1">patches/mageia/block-introduce-the-BFQ-v7r11-I-O-sched-for-4.5.0.patch</Patch>
<Patch level="1">patches/mageia/block-bfq-add-Early-Queue-Merge-EQM-to-BFQ-v7r11-for.patch</Patch>
<Patch level="1">patches/mageia/block-Turn-into-BFQ-v8r6-for-4.9.0.patch</Patch>--><!--2-->
<Patch level="1">patches/mageia/block-Turn-into-BFQ-v8r7-for-4.9.0.patch</Patch>
<Patch level="1">patches/mageia/block-update-bfq-from-v8r7-to-v8r10.patch</Patch>
<Patch level="1">patches/mageia/block-update-bfq-from-v8r10-to-v8r11.patch</Patch><!--2-->
<Patch level="1">patches/mageia/block-nvme-detect-NVMe-controller-in-recent-MacBooks.patch</Patch>
<Patch level="1">patches/mageia/char-tpm-tpm_crb-implement-tpm-crb-idle-state.patch</Patch>
<Patch level="1">patches/mageia/char-tmp-tpm_crb-fix-Intel-PTT-hw-bug-during-idle-state.patch</Patch>
<Patch level="1">patches/mageia/char-tpm-tpm_crb-open-code-the-crb_init-into-acpi_add.patch</Patch>
<Patch level="1">patches/mageia/char-tmp-tpm_crb-implement-runtime-pm-for-tpm_crb.patch</Patch>
<Patch level="1">patches/mageia/fs-aufs-4.9.patch</Patch>
<Patch level="1">patches/fs-aufs-4.9-posix_acl.patch</Patch>
<Patch level="1">patches/mageia/fs-aufs-4.9-modular.patch</Patch>
<Patch level="1">patches/mageia/fs-seq_file-reset-iterator-to-first-record-for-zero-off.patch</Patch>
<Patch level="1">patches/mageia/fs-jbd2-Fix-dbench4-performance-regression-for-nobarrier-mounts.patch</Patch>
<Patch level="1">patches/mageia/firewire-ieee1394-module-aliases.patch</Patch>
<Patch level="1">patches/mageia/char-agp-intel-new-Q57-id.patch</Patch>
<!--remove external mach64 support for buildfix-->
@@ -91,10 +120,13 @@
<Patch level="1">patches/mageia/gpu-drm-mach64-linux-3.14-buildfix.patch</Patch>
<Patch level="1">patches/mageia/gpu-drm-mach64-3.17-buildfix.patch</Patch>
<Patch level="1">patches/mageia/gpu-drm-mach64-3.18-buildfix.patch</Patch--><!--1-->
<Patch level="1">patches/mageia/gpu-drm-i915-skl-drop-workarounds-for-A0-and-B0-revisions.patch</Patch>
<Patch level="1">patches/mageia/gpu-drm-i915-skl-drop-workarounds-for-D0-revision.patch</Patch>
<Patch level="1">patches/mageia/gpu-drm-i915-skl-drop-workarounds-for-E0-revision.patch</Patch>
<Patch level="1">patches/mageia/gpu-drm-i915-Remove-WaDisableLSQCROPERFforOCL-KBL-workaround.patch</Patch>
<Patch level="1">patches/mageia/gpu-drm-i915-don-t-warn-about-Skylake-CPU-KabyPoint-PCH-.patch</Patch>
<Patch level="1">patches/mageia/gpu-drm-amd-amdgpu-add-Polaris12-PCI-ID.patch</Patch>
<Patch level="1">patches/mageia/gpu-drm-amdgpu-add-Polaris12-DID.patch</Patch>
<Patch level="1">patches/mageia/gpu-drm-amd-amdgpu-add-Polaris12-support-v3.patch</Patch>
<Patch level="1">patches/mageia/gpu-drm-amdgpu-powerplay-add-Polaris12-support.patch</Patch>
<Patch level="1">patches/mageia/gpu-drm-amd-amdgpu-add-POLARIS12-PCI-ID.patch</Patch>
<Patch level="1">patches/mageia/gpu-drm-amdgpu-pm-check-for-headless-before-calling-comp.patch</Patch>
<Patch level="1">patches/mageia/input-i8042-quirks-for-Fujitsu-Lifebook-A544-and-Lif.patch</Patch>
<Patch level="1">patches/mageia/net-sis190-fix-list-usage.patch</Patch>
<Patch level="1">patches/mageia/net-netfilter-IFWLOG.patch</Patch>
@@ -110,14 +142,28 @@
<Patch level="1">patches/mageia/net-netfilter-psd-fix-redefines.patch</Patch>
<Patch level="1">patches/mageia/net-wireless-rtlwifi-Use-dev_kfree_skb_irq-instead-of-kfree_skb.patch</Patch>
<Patch level="1">patches/mageia/net-wireless-rtlwifi-Fix-kernel-oops-introduced-with-commit-e4965.patch</Patch>
<Patch level="1">patches/mageia/net-wireless-brcmfmac-fix-incorrect-event-channel-deduction.patch</Patch>
<Patch level="1">patches/mageia/net-wireless-realtek-rtl8xxxu-linux-4.11-rc.patch</Patch>
<Patch level="1">patches/mageia/net-netfilter-xt_TCPMSS-add-more-sanity-tests-on-tcph-do.patch</Patch>
<Patch level="1">patches/mageia/pinctrl_amd-Use-regular-interrupt-instead-of-chained.patch</Patch>
<Patch level="1">patches/mageia/platform-x86-add-shuttle-wmi-driver.patch</Patch>
<Patch level="1">patches/mageia/platform-x86-shuttle-wmi-drop-devinit-exit.patch</Patch>
<Patch level="1">patches/mageia/platform-x86-shuttle-wmi-4.2-buildfix.patch</Patch>
<Patch level="1">patches/mageia/include-kbuild-export-pci_ids.patch</Patch>
<Patch level="1">patches/mageia/sound-ALSA-hda-realtek-Add-new-codec-ID-ALC299.patch</Patch>
<Patch level="1">patches/mageia/sound-ALSA-hda-realtek-New-codec-support-of-ALC1220.patch</Patch>
<Patch level="1">patches/mageia/sound-ALSA-hda-A-new-flag-to-enforce-prefix-to-each-pin.patch</Patch>
<Patch level="1">patches/mageia/sound-ALSA-hda-Allow-to-enable-disable-vmaster-build-expli.patch</Patch>
<Patch level="1">patches/mageia/sound-ALSA-hda-Support-Gigabyte-Gaming-board-with-dual-Rea.patch</Patch>
<Patch level="1">patches/mageia/sound-ALSA-hda-Use-a-helper-function-for-renaming-kctl-nam.patch</Patch>
<Patch level="1">patches/mageia/sound-ALSA-hda-Apply-dual-codec-quirk-for-MSI-Z270-Gaming-.patch</Patch>
<Patch level="1">patches/mageia/sound-ALSA-hda-Fix-applying-MSI-dual-codec-mobo-quirk.patch</Patch>
<Patch level="1">patches/mageia/sound-ALSA-hda-Add-Geminilake-id-to-SKL_PLUS.patch</Patch>
<Patch level="1">patches/mageia/sound-ALSA-hda-Add-Coffelake-PCI-ID.patch</Patch>
<Patch level="1">patches/mageia/sound-ALSA-hda-Apply-quirks-to-Broxton-T-too.patch</Patch>
<Patch level="1">patches/mageia/hid-usbhid-IBM-BladeCenterHS20-quirk.patch</Patch>
<Patch level="1">patches/mageia/usb-storage-unusual_devs-add-id.patch</Patch>
<Patch level="1">patches/mageia/usb-storage-unusual_devs-add-id-2.6.37-buildfix.patch</Patch>
<Patch level="1">patches/mageia/usb-xhci-Limit-USB2-port-wake-support-for-AMD-Promontory-hosts.patch</Patch>
<Patch level="1">patches/mageia/media-usb-pwc-lie-in-proc-usb-devices.patch</Patch>
<Patch level="1">patches/mageia/3rd-3rdparty-1.0-tree.patch</Patch>
<Patch level="1">patches/mageia/3rd-3rdparty-merge.patch</Patch>
@@ -145,6 +191,7 @@
<Patch level="1">patches/mageia/3rd-viahss-2.6.35-buildfix.patch</Patch>
<Patch level="1">patches/mageia/3rd-viahss-3.0-buildfix.patch</Patch>
<Patch level="1">patches/mageia/3rd-rtl8723bs.patch</Patch>
<Patch level="1">patches/mageia/3rd-rtl8812au.patch</Patch>
<Patch level="1">patches/mageia/tools-testing-selftest-Makefile-remove-powerpc-reference.patch</Patch>
<Patch level="1">patches/mageia/tools-build-Make-fixdep-parsing-wait-for-last-target.patch</Patch>
<Patch level="1">patches/mageia/tools-perf-tools-Force-fixdep-compilation-at-the-start-of-.patch</Patch>
@@ -158,13 +205,11 @@
<Dependency>pisi</Dependency>
<Dependency>linux-firmware</Dependency>
<Dependency>grub2</Dependency>
<!--Dependency>mkinitcpio</Dependency-->
</RuntimeDependencies>
<Files>
<Path fileType="executable" permanent="true">/boot</Path>
<Path fileType="library" permanent="true">/lib/modules</Path>
<Path fileType="data">/etc/kernel</Path>
<Path fileType="config">/etc/mkinitcpio.d</Path>
</Files>
<Provides>
<COMAR script="package.py">System.Package</COMAR>
@@ -204,6 +249,17 @@
</Package>
<History>
<Update release="10">
<Date>2017-07-02</Date>
<Version>4.9.35</Version>
<Comment>Version Bump.</Comment>
<Type package="kernel">security</Type>
<Requires>
<Action package="kernel">systemRestart</Action>
</Requires>
<Name>Ertuğrul Erata</Name>
<Email>ertugrulerata@gmail.com</Email>
</Update>
<Update release="9">
<Date>2017-01-27</Date>
<Version>4.9.6</Version>
@@ -0,0 +1,86 @@
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
};
File diff suppressed because it is too large Load Diff
@@ -1,70 +0,0 @@
From ca45663819accf038291dbe2d67ed66dc48d714c Mon Sep 17 00:00:00 2001
From: Thomas Backlund <tmb@mageia.org>
Date: Sun, 29 Nov 2015 14:44:22 +0200
Subject: [PATCH] Revert "x86/mm/mtrr: Remove kernel internal MTRR interfaces:
unexport mtrr_add() and mtrr_del()"
This reverts commit 2baa891e42d84159b693eadd44f6fe1486285bdc.
It currently breaks nvidia304 driver.
Signed-of-by: Thomas Backlund <tmb@mageia.org>
---
Documentation/x86/mtrr.txt | 20 ++++----------------
arch/x86/kernel/cpu/mtrr/main.c | 2 ++
2 files changed, 6 insertions(+), 16 deletions(-)
diff --git a/Documentation/x86/mtrr.txt b/Documentation/x86/mtrr.txt
index dc3e703..860bc3a 100644
--- a/Documentation/x86/mtrr.txt
+++ b/Documentation/x86/mtrr.txt
@@ -6,22 +6,10 @@ Luis R. Rodriguez <mcgrof@do-not-panic.com> - April 9, 2015
===============================================================================
Phasing out MTRR use
-MTRR use is replaced on modern x86 hardware with PAT. Direct MTRR use by
-drivers on Linux is now completely phased out, device drivers should use
-arch_phys_wc_add() in combination with ioremap_wc() to make MTRR effective on
-non-PAT systems while a no-op but equally effective on PAT enabled systems.
-
-Even if Linux does not use MTRRs directly, some x86 platform firmware may still
-set up MTRRs early before booting the OS. They do this as some platform
-firmware may still have implemented access to MTRRs which would be controlled
-and handled by the platform firmware directly. An example of platform use of
-MTRRs is through the use of SMI handlers, one case could be for fan control,
-the platform code would need uncachable access to some of its fan control
-registers. Such platform access does not need any Operating System MTRR code in
-place other than mtrr_type_lookup() to ensure any OS specific mapping requests
-are aligned with platform MTRR setup. If MTRRs are only set up by the platform
-firmware code though and the OS does not make any specific MTRR mapping
-requests mtrr_type_lookup() should always return MTRR_TYPE_INVALID.
+MTRR use is replaced on modern x86 hardware with PAT. Over time the only type
+of effective MTRR that is expected to be supported will be for write-combining.
+As MTRR use is phased out device drivers should use arch_phys_wc_add() to make
+MTRR effective on non-PAT systems while a no-op on PAT enabled systems.
For details refer to Documentation/x86/pat.txt.
diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c
index f891b47..e7ed0d8 100644
--- a/arch/x86/kernel/cpu/mtrr/main.c
+++ b/arch/x86/kernel/cpu/mtrr/main.c
@@ -448,6 +448,7 @@ int mtrr_add(unsigned long base, unsigned long size, unsigned int type,
return mtrr_add_page(base >> PAGE_SHIFT, size >> PAGE_SHIFT, type,
increment);
}
+EXPORT_SYMBOL(mtrr_add);
/**
* mtrr_del_page - delete a memory type region
@@ -536,6 +537,7 @@ int mtrr_del(int reg, unsigned long base, unsigned long size)
return -EINVAL;
return mtrr_del_page(reg, base >> PAGE_SHIFT, size >> PAGE_SHIFT);
}
+EXPORT_SYMBOL(mtrr_del);
/**
* arch_phys_wc_add - add a WC MTRR and handle errors if PAT is unavailable
--
2.3.10
@@ -0,0 +1,192 @@
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,9 +1,13 @@
From 3e3791c0b4ef3b2067f8454e58001af8e3da3840 Mon Sep 17 00:00:00 2001
From 0432a5c7bfc4a11531c1e58f574c733a2552f149 Mon Sep 17 00:00:00 2001
From: Paolo Valente <paolo.valente@linaro.org>
Date: Tue, 17 May 2016 08:28:04 +0200
Subject: [PATCH 4/4] Turn into BFQ-v8r6 for 4.9.0
Subject: [PATCH 4/4] Turn into BFQ-v8r7 for 4.9.0
CHANGELOG from v8r4 to v8r6
CHANGELOG from v8r4 to v8r7
BFQ v8r7
BUGFIX: make BFQ compile also without hierarchical support
BFQ v8r6
@@ -125,9 +129,9 @@ Signed-off-by: Paolo Valente <paolo.valente@linaro.org>
block/Kconfig.iosched | 18 +-
block/bfq-cgroup.c | 501 +++---
block/bfq-iosched.c | 3278 ++++++++++++++++++++++-------------
block/bfq-sched.c | 1270 +++++++++++---
block/bfq-sched.c | 1288 +++++++++++---
block/bfq.h | 800 +++++----
7 files changed, 4310 insertions(+), 2089 deletions(-)
7 files changed, 4320 insertions(+), 2097 deletions(-)
create mode 100644 Documentation/block/bfq-iosched.txt
diff --git a/Documentation/block/00-INDEX b/Documentation/block/00-INDEX
@@ -1601,7 +1605,7 @@ index 0367996..bbaecd0 100644
static struct bfq_group *
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
index cf3e9b1..0f9cd53 100644
index cf3e9b1..2a2c130 100644
--- a/block/bfq-iosched.c
+++ b/block/bfq-iosched.c
@@ -1,5 +1,5 @@
@@ -6201,7 +6205,7 @@ index cf3e9b1..0f9cd53 100644
-
- if (bfq_timeout_async == 0)
- bfq_timeout_async = 1;
+ char msg[60] = "BFQ I/O-scheduler: v8r6";
+ char msg[60] = "BFQ I/O-scheduler: v8r7";
#ifdef CONFIG_BFQ_GROUP_IOSCHED
ret = blkcg_policy_register(&blkcg_policy_bfq);
@@ -6265,10 +6269,10 @@ index cf3e9b1..0f9cd53 100644
return 0;
diff --git a/block/bfq-sched.c b/block/bfq-sched.c
index a5ed694..4af77f4 100644
index a5ed694..797bce7 100644
--- a/block/bfq-sched.c
+++ b/block/bfq-sched.c
@@ -7,28 +7,46 @@
@@ -7,28 +7,166 @@
* Copyright (C) 2008 Fabio Checconi <fabio@gandalf.sssup.it>
* Paolo Valente <paolo.valente@unimore.it>
*
@@ -6276,8 +6280,8 @@ index a5ed694..4af77f4 100644
+ * Copyright (C) 2015 Paolo Valente <paolo.valente@unimore.it>
+ *
+ * Copyright (C) 2016 Paolo Valente <paolo.valente@linaro.org>
*/
+ */
+
+static struct bfq_group *bfqq_group(struct bfq_queue *bfqq);
+
+/**
@@ -6292,63 +6296,17 @@ index a5ed694..4af77f4 100644
+ return (s64)(a - b) > 0;
+}
+
#ifdef CONFIG_BFQ_GROUP_IOSCHED
-#define for_each_entity(entity) \
+/* both next loops stop at one of the child entities of the root group */
+#define for_each_entity(entity) \
for (; entity ; entity = entity->parent)
#define for_each_entity_safe(entity, parent) \
for (; entity && ({ parent = entity->parent; 1; }); entity = parent)
-static struct bfq_entity *bfq_lookup_next_entity(struct bfq_sched_data *sd,
- int extract,
- struct bfq_data *bfqd);
-
-static struct bfq_group *bfqq_group(struct bfq_queue *bfqq);
+static struct bfq_entity *bfq_lookup_next_entity(struct bfq_sched_data *sd);
-static void bfq_update_budget(struct bfq_entity *next_in_service)
+/*
+ * Returns true if this budget changes may let next_in_service->parent
+ * become the next_in_service entity for its parent entity.
+ */
+static bool bfq_update_parent_budget(struct bfq_entity *next_in_service)
{
struct bfq_entity *bfqg_entity;
struct bfq_group *bfqg;
struct bfq_sched_data *group_sd;
+ bool ret = false;
BUG_ON(!next_in_service);
@@ -41,39 +59,134 @@ static void bfq_update_budget(struct bfq_entity *next_in_service)
* as it must never become an in-service entity.
*/
bfqg_entity = bfqg->my_entity;
- if (bfqg_entity)
+ if (bfqg_entity) {
+ if (bfqg_entity->budget > next_in_service->budget)
+ ret = true;
bfqg_entity->budget = next_in_service->budget;
+ }
+
+ return ret;
}
-static int bfq_update_next_in_service(struct bfq_sched_data *sd)
+static struct bfq_entity *bfq_root_active_entity(struct rb_root *tree)
{
- struct bfq_entity *next_in_service;
+{
+ struct rb_node *node = tree->rb_node;
- if (sd->in_service_entity)
- /* will update/requeue at the end of service */
- return 0;
+
+ return rb_entry(node, struct bfq_entity, rb_node);
+}
+
+static struct bfq_entity *bfq_lookup_next_entity(struct bfq_sched_data *sd);
+
+static bool bfq_update_parent_budget(struct bfq_entity *next_in_service);
+
+/**
+ * bfq_update_next_in_service - update sd->next_in_service
+ * @sd: sched_data for which to perform the update.
@@ -6371,20 +6329,15 @@ index a5ed694..4af77f4 100644
+ * Returns true if sd->next_in_service changes in such a way that
+ * entity->parent may become the next_in_service for its parent
+ * entity.
+ */
*/
+static bool bfq_update_next_in_service(struct bfq_sched_data *sd,
+ struct bfq_entity *new_entity)
+{
+ struct bfq_entity *next_in_service = sd->next_in_service;
+ struct bfq_queue *bfqq;
+ bool parent_sched_may_change = false;
/*
- * NOTE: this can be improved in many ways, such as returning
- * 1 (and thus propagating upwards the update) only when the
- * budget changes, or caching the bfqq that will be scheduled
- * next from this subtree. By now we worry more about
- * correctness than about performance...
+
+ /*
+ * If this update is triggered by the activation, requeueing
+ * or repositiong of an entity that does not coincide with
+ * sd->next_in_service, then a full lookup in the active tree
@@ -6395,8 +6348,7 @@ index a5ed694..4af77f4 100644
+ * finish time than sd->next_in_service. If this compound
+ * condition holds, then the new entity becomes the new
+ * next_in_service. Otherwise no change is needed.
*/
- next_in_service = bfq_lookup_next_entity(sd, 0, NULL);
+ */
+ if (new_entity && new_entity != sd->next_in_service) {
+ /*
+ * Flag used to decide whether to replace
@@ -6445,54 +6397,160 @@ index a5ed694..4af77f4 100644
+ bfq_update_parent_budget(next_in_service);
+ }
+
sd->next_in_service = next_in_service;
- if (next_in_service)
- bfq_update_budget(next_in_service);
+ sd->next_in_service = next_in_service;
+
+ if (!next_in_service)
+ return parent_sched_may_change;
- return 1;
-}
+ bfqq = bfq_entity_to_bfqq(next_in_service);
+ if (bfqq)
+ bfq_log_bfqq(bfqq->bfqd, bfqq,
+ "update_next_in_service: chosen this queue");
+#ifdef CONFIG_BFQ_GROUP_IOSCHED
#ifdef CONFIG_BFQ_GROUP_IOSCHED
-#define for_each_entity(entity) \
+ else {
+ struct bfq_group *bfqg =
+ container_of(next_in_service,
+ struct bfq_group, entity);
-static void bfq_check_next_in_service(struct bfq_sched_data *sd,
- struct bfq_entity *entity)
-{
- BUG_ON(sd->next_in_service != entity);
+
+ bfq_log_bfqg((struct bfq_data *)bfqg->bfqd, bfqg,
+ "update_next_in_service: chosen this entity");
+ }
+#endif
+ return parent_sched_may_change;
}
+}
+
#else
#define for_each_entity(entity) \
for (; entity ; entity = NULL)
@@ -86,12 +199,7 @@ static int bfq_update_next_in_service(struct bfq_sched_data *sd)
return 0;
+#ifdef CONFIG_BFQ_GROUP_IOSCHED
+/* both next loops stop at one of the child entities of the root group */
+#define for_each_entity(entity) \
for (; entity ; entity = entity->parent)
#define for_each_entity_safe(entity, parent) \
for (; entity && ({ parent = entity->parent; 1; }); entity = parent)
-
-static struct bfq_entity *bfq_lookup_next_entity(struct bfq_sched_data *sd,
- int extract,
- struct bfq_data *bfqd);
-
-static struct bfq_group *bfqq_group(struct bfq_queue *bfqq);
-
-static void bfq_update_budget(struct bfq_entity *next_in_service)
+/*
+ * Returns true if this budget changes may let next_in_service->parent
+ * become the next_in_service entity for its parent entity.
+ */
+static bool bfq_update_parent_budget(struct bfq_entity *next_in_service)
{
struct bfq_entity *bfqg_entity;
struct bfq_group *bfqg;
struct bfq_sched_data *group_sd;
+ bool ret = false;
BUG_ON(!next_in_service);
@@ -41,60 +179,68 @@ static void bfq_update_budget(struct bfq_entity *next_in_service)
* as it must never become an in-service entity.
*/
bfqg_entity = bfqg->my_entity;
- if (bfqg_entity)
+ if (bfqg_entity) {
+ if (bfqg_entity->budget > next_in_service->budget)
+ ret = true;
bfqg_entity->budget = next_in_service->budget;
+ }
+
+ return ret;
}
-static int bfq_update_next_in_service(struct bfq_sched_data *sd)
+/*
+ * This function tells whether entity stops being a candidate for next
+ * service, according to the following logic.
+ *
+ * This function is invoked for an entity that is about to be set in
+ * service. If such an entity is a queue, then the entity is no longer
+ * a candidate for next service (i.e, a candidate entity to serve
+ * after the in-service entity is expired). The function then returns
+ * true.
+ *
+ * In contrast, the entity could stil be a candidate for next service
+ * if it is not a queue, and has more than one child. In fact, even if
+ * one of its children is about to be set in service, other children
+ * may still be the next to serve. As a consequence, a non-queue
+ * entity is not a candidate for next-service only if it has only one
+ * child. And only if this condition holds, then the function returns
+ * true for a non-queue entity.
+ */
+static bool bfq_no_longer_next_in_service(struct bfq_entity *entity)
{
- struct bfq_entity *next_in_service;
+ struct bfq_group *bfqg;
- if (sd->in_service_entity)
- /* will update/requeue at the end of service */
- return 0;
+ if (bfq_entity_to_bfqq(entity))
+ return true;
- /*
- * NOTE: this can be improved in many ways, such as returning
- * 1 (and thus propagating upwards the update) only when the
- * budget changes, or caching the bfqq that will be scheduled
- * next from this subtree. By now we worry more about
- * correctness than about performance...
- */
- next_in_service = bfq_lookup_next_entity(sd, 0, NULL);
- sd->next_in_service = next_in_service;
+ bfqg = container_of(entity, struct bfq_group, entity);
- if (next_in_service)
- bfq_update_budget(next_in_service);
+ BUG_ON(bfqg == ((struct bfq_data *)(bfqg->bfqd))->root_group);
+ BUG_ON(bfqg->active_entities == 0);
+ if (bfqg->active_entities == 1)
+ return true;
- return 1;
+ return false;
}
-static void bfq_check_next_in_service(struct bfq_sched_data *sd,
- struct bfq_entity *entity)
-{
- BUG_ON(sd->next_in_service != entity);
-}
-
-static void bfq_update_budget(struct bfq_entity *next_in_service)
+static void bfq_update_parent_budget(struct bfq_entity *next_in_service)
-#else
+#else /* CONFIG_BFQ_GROUP_IOSCHED */
#define for_each_entity(entity) \
for (; entity ; entity = NULL)
#define for_each_entity_safe(entity, parent) \
for (parent = NULL; entity ; entity = parent)
-static int bfq_update_next_in_service(struct bfq_sched_data *sd)
+static bool bfq_update_parent_budget(struct bfq_entity *next_in_service)
{
- return 0;
+ return false;
}
#endif
@@ -105,18 +213,6 @@ static void bfq_update_budget(struct bfq_entity *next_in_service)
-static void bfq_check_next_in_service(struct bfq_sched_data *sd,
- struct bfq_entity *entity)
+static bool bfq_no_longer_next_in_service(struct bfq_entity *entity)
{
+ return true;
}
-static void bfq_update_budget(struct bfq_entity *next_in_service)
-{
-}
-#endif
+#endif /* CONFIG_BFQ_GROUP_IOSCHED */
/*
* Shift for timestamp calculations. This actually limits the maximum
@@ -105,18 +251,6 @@ static void bfq_update_budget(struct bfq_entity *next_in_service)
*/
#define WFQ_SERVICE_SHIFT 22
@@ -6511,7 +6569,7 @@ index a5ed694..4af77f4 100644
static struct bfq_queue *bfq_entity_to_bfqq(struct bfq_entity *entity)
{
struct bfq_queue *bfqq = NULL;
@@ -151,20 +247,36 @@ static u64 bfq_delta(unsigned long service, unsigned long weight)
@@ -151,20 +285,36 @@ static u64 bfq_delta(unsigned long service, unsigned long weight)
static void bfq_calc_finish(struct bfq_entity *entity, unsigned long service)
{
struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity);
@@ -6550,7 +6608,7 @@ index a5ed694..4af77f4 100644
}
}
@@ -293,10 +405,26 @@ static void bfq_update_min(struct bfq_entity *entity, struct rb_node *node)
@@ -293,10 +443,26 @@ static void bfq_update_min(struct bfq_entity *entity, struct rb_node *node)
static void bfq_update_active_node(struct rb_node *node)
{
struct bfq_entity *entity = rb_entry(node, struct bfq_entity, rb_node);
@@ -6577,7 +6635,7 @@ index a5ed694..4af77f4 100644
}
/**
@@ -386,8 +514,6 @@ static void bfq_active_insert(struct bfq_service_tree *st,
@@ -386,8 +552,6 @@ static void bfq_active_insert(struct bfq_service_tree *st,
BUG_ON(!bfqg);
BUG_ON(!bfqd);
bfqg->active_entities++;
@@ -6586,7 +6644,7 @@ index a5ed694..4af77f4 100644
}
#endif
}
@@ -399,7 +525,7 @@ static void bfq_active_insert(struct bfq_service_tree *st,
@@ -399,7 +563,7 @@ static void bfq_active_insert(struct bfq_service_tree *st,
static unsigned short bfq_ioprio_to_weight(int ioprio)
{
BUG_ON(ioprio < 0 || ioprio >= IOPRIO_BE_NR);
@@ -6595,7 +6653,7 @@ index a5ed694..4af77f4 100644
}
/**
@@ -422,9 +548,9 @@ static void bfq_get_entity(struct bfq_entity *entity)
@@ -422,9 +586,9 @@ static void bfq_get_entity(struct bfq_entity *entity)
struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity);
if (bfqq) {
@@ -6607,7 +6665,7 @@ index a5ed694..4af77f4 100644
}
}
@@ -499,10 +625,6 @@ static void bfq_active_extract(struct bfq_service_tree *st,
@@ -499,10 +663,6 @@ static void bfq_active_extract(struct bfq_service_tree *st,
BUG_ON(!bfqd);
BUG_ON(!bfqg->active_entities);
bfqg->active_entities--;
@@ -6618,7 +6676,7 @@ index a5ed694..4af77f4 100644
}
#endif
}
@@ -547,12 +669,12 @@ static void bfq_forget_entity(struct bfq_service_tree *st,
@@ -547,12 +707,12 @@ static void bfq_forget_entity(struct bfq_service_tree *st,
BUG_ON(!entity->on_st);
@@ -6633,7 +6691,7 @@ index a5ed694..4af77f4 100644
bfq_put_queue(bfqq);
}
}
@@ -602,7 +724,7 @@ __bfq_entity_update_weight_prio(struct bfq_service_tree *old_st,
@@ -602,7 +762,7 @@ __bfq_entity_update_weight_prio(struct bfq_service_tree *old_st,
if (entity->prio_changed) {
struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity);
@@ -6642,7 +6700,7 @@ index a5ed694..4af77f4 100644
struct bfq_data *bfqd = NULL;
struct rb_root *root;
#ifdef CONFIG_BFQ_GROUP_IOSCHED
@@ -630,7 +752,10 @@ __bfq_entity_update_weight_prio(struct bfq_service_tree *old_st,
@@ -630,7 +790,10 @@ __bfq_entity_update_weight_prio(struct bfq_service_tree *old_st,
entity->new_weight > BFQ_MAX_WEIGHT) {
pr_crit("update_weight_prio: new_weight %d\n",
entity->new_weight);
@@ -6654,7 +6712,7 @@ index a5ed694..4af77f4 100644
}
entity->orig_weight = entity->new_weight;
if (bfqq)
@@ -661,6 +786,13 @@ __bfq_entity_update_weight_prio(struct bfq_service_tree *old_st,
@@ -661,6 +824,13 @@ __bfq_entity_update_weight_prio(struct bfq_service_tree *old_st,
* associated with its new weight.
*/
if (prev_weight != new_weight) {
@@ -6668,7 +6726,7 @@ index a5ed694..4af77f4 100644
root = bfqq ? &bfqd->queue_weights_tree :
&bfqd->group_weights_tree;
bfq_weights_tree_remove(bfqd, entity, root);
@@ -707,7 +839,7 @@ static void bfq_bfqq_served(struct bfq_queue *bfqq, int served)
@@ -707,7 +877,7 @@ static void bfq_bfqq_served(struct bfq_queue *bfqq, int served)
st = bfq_entity_service_tree(entity);
entity->service += served;
@@ -6677,7 +6735,7 @@ index a5ed694..4af77f4 100644
BUG_ON(st->wsum == 0);
st->vtime += bfq_delta(served, st->wsum);
@@ -716,170 +848,419 @@ static void bfq_bfqq_served(struct bfq_queue *bfqq, int served)
@@ -716,170 +886,419 @@ static void bfq_bfqq_served(struct bfq_queue *bfqq, int served)
#ifdef CONFIG_BFQ_GROUP_IOSCHED
bfqg_stats_set_start_empty_time(bfqq_group(bfqq));
#endif
@@ -6731,17 +6789,17 @@ index a5ed694..4af77f4 100644
+ if (time_ms > 0 && time_ms < timeout_ms)
+ tot_serv_to_charge =
+ (bfqd->bfq_max_budget * time_ms) / timeout_ms;
+
- bfq_log_bfqq(bfqq->bfqd, bfqq, "charge_full_budget");
+ if (tot_serv_to_charge < entity->service)
+ tot_serv_to_charge = entity->service;
- bfq_log_bfqq(bfqq->bfqd, bfqq, "charge_full_budget");
- bfq_bfqq_served(bfqq, entity->budget - entity->service);
+ bfq_log_bfqq(bfqq->bfqd, bfqq,
+ "charge_time: %lu/%u ms, %d/%d/%d sectors",
+ time_ms, timeout_ms, entity->service,
+ tot_serv_to_charge, entity->budget);
- bfq_bfqq_served(bfqq, entity->budget - entity->service);
+
+ /* Increase budget to avoid inconsistencies */
+ if (tot_serv_to_charge > entity->budget)
+ entity->budget = tot_serv_to_charge;
@@ -6948,19 +7006,20 @@ index a5ed694..4af77f4 100644
- * @entity: the entity to activate.
+ * __bfq_requeue_entity - handle requeueing or repositioning of an entity.
+ * @entity: the entity being requeued or repositioned.
*
- * Activate @entity and all the entities on the path from it to the root.
+ *
+ * Requeueing is needed if this entity stops being served, which
+ * happens if a leaf descendant entity has expired. On the other hand,
+ * repositioning is needed if the next_inservice_entity for the child
+ * entity has changed. See the comments inside the function for
+ * details.
+ *
*
- * Activate @entity and all the entities on the path from it to the root.
+ * Basically, this function: 1) removes entity from its active tree if
+ * present there, 2) updates the timestamps of entity and 3) inserts
+ * entity back into its active tree (in the new, right position for
+ * the new values of the timestamps).
+ */
*/
-static void bfq_activate_entity(struct bfq_entity *entity)
+static void __bfq_requeue_entity(struct bfq_entity *entity)
+{
+ struct bfq_sched_data *sd = entity->sched_data;
@@ -7065,8 +7124,7 @@ index a5ed694..4af77f4 100644
+ * @requeue: true if this is a requeue, which implies that bfqq is
+ * being expired; thus ALL its ancestors stop being served and must
+ * therefore be requeued
*/
-static void bfq_activate_entity(struct bfq_entity *entity)
+ */
+static void bfq_activate_requeue_entity(struct bfq_entity *entity,
+ bool non_blocking_wait_rq,
+ bool requeue)
@@ -7186,7 +7244,7 @@ index a5ed694..4af77f4 100644
{
struct bfq_sched_data *sd;
struct bfq_entity *parent;
@@ -887,63 +1268,153 @@ static void bfq_deactivate_entity(struct bfq_entity *entity, int requeue)
@@ -887,63 +1306,154 @@ static void bfq_deactivate_entity(struct bfq_entity *entity, int requeue)
for_each_entity_safe(entity, parent) {
sd = entity->sched_data;
@@ -7309,7 +7367,8 @@ index a5ed694..4af77f4 100644
+ if (!bfq_update_next_in_service(sd, entity) &&
+ !expiration)
+ /*
+ * next_in_service unchanged, and no
+ * next_in_service unchanged or not causing
+ * any change in entity->parent->sd, and no
+ * requeueing needed for expiration: stop
+ * here.
+ */
@@ -7339,13 +7398,13 @@ index a5ed694..4af77f4 100644
- struct bfq_entity *entry;
- struct rb_node *node = st->active.rb_node;
+ struct bfq_entity *root_entity = bfq_root_active_entity(&st->active);
+
+ if (bfq_gt(root_entity->min_start, st->vtime)) {
+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(root_entity);
- entry = rb_entry(node, struct bfq_entity, rb_node);
- if (bfq_gt(entry->min_start, st->vtime)) {
- st->vtime = entry->min_start;
+ if (bfq_gt(root_entity->min_start, st->vtime)) {
+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(root_entity);
+
+ if (bfqq)
+ bfq_log_bfqq(bfqq->bfqd, bfqq,
+ "calc_vtime_jump: new value %llu",
@@ -7373,7 +7432,7 @@ index a5ed694..4af77f4 100644
bfq_forget_idle(st);
}
}
@@ -952,6 +1423,7 @@ static void bfq_update_vtime(struct bfq_service_tree *st)
@@ -952,6 +1462,7 @@ static void bfq_update_vtime(struct bfq_service_tree *st)
* bfq_first_active_entity - find the eligible entity with
* the smallest finish time
* @st: the service tree to select from.
@@ -7381,7 +7440,7 @@ index a5ed694..4af77f4 100644
*
* This function searches the first schedulable entity, starting from the
* root of the tree and going on the left every time on this side there is
@@ -959,7 +1431,8 @@ static void bfq_update_vtime(struct bfq_service_tree *st)
@@ -959,7 +1470,8 @@ static void bfq_update_vtime(struct bfq_service_tree *st)
* the right is followed only if a) the left subtree contains no eligible
* entities and b) no eligible entity has been found yet.
*/
@@ -7391,7 +7450,7 @@ index a5ed694..4af77f4 100644
{
struct bfq_entity *entry, *first = NULL;
struct rb_node *node = st->active.rb_node;
@@ -967,15 +1440,15 @@ static struct bfq_entity *bfq_first_active_entity(struct bfq_service_tree *st)
@@ -967,15 +1479,15 @@ static struct bfq_entity *bfq_first_active_entity(struct bfq_service_tree *st)
while (node) {
entry = rb_entry(node, struct bfq_entity, rb_node);
left:
@@ -7410,7 +7469,7 @@ index a5ed694..4af77f4 100644
node = node->rb_left;
goto left;
}
@@ -993,31 +1466,84 @@ static struct bfq_entity *bfq_first_active_entity(struct bfq_service_tree *st)
@@ -993,31 +1505,84 @@ static struct bfq_entity *bfq_first_active_entity(struct bfq_service_tree *st)
* __bfq_lookup_next_entity - return the first eligible entity in @st.
* @st: the service tree.
*
@@ -7510,7 +7569,7 @@ index a5ed694..4af77f4 100644
return entity;
}
@@ -1025,50 +1551,118 @@ static struct bfq_entity *__bfq_lookup_next_entity(struct bfq_service_tree *st,
@@ -1025,50 +1590,81 @@ static struct bfq_entity *__bfq_lookup_next_entity(struct bfq_service_tree *st,
/**
* bfq_lookup_next_entity - return the first eligible entity in @sd.
* @sd: the sched_data.
@@ -7620,48 +7679,11 @@ index a5ed694..4af77f4 100644
+
+ return sd->next_in_service != sd->in_service_entity;
+}
+
+/*
+ * This function tells whether entity stops being a candidate for next
+ * service, according to the following logic.
+ *
+ * This function is invoked for an entity that is about to be set in
+ * service. If such an entity is a queue, then the entity is no longer
+ * a candidate for next service (i.e, a candidate entity to serve
+ * after the in-service entity is expired). The function then returns
+ * true.
+ *
+ * In contrast, the entity could stil be a candidate for next service
+ * if it is not a queue, and has more than one child. In fact, even if
+ * one of its children is about to be set in service, other children
+ * may still be the next to serve. As a consequence, a non-queue
+ * entity is not a candidate for next-service only if it has only one
+ * child. And only if this condition holds, then the function returns
+ * true for a non-queue entity.
+ */
+static bool bfq_no_longer_next_in_service(struct bfq_entity *entity)
+{
+ struct bfq_group *bfqg;
+
+ if (bfq_entity_to_bfqq(entity))
+ return true;
+
+#ifdef CONFIG_BFQ_GROUP_IOSCHED
+ bfqg = container_of(entity, struct bfq_group, entity);
+
+ BUG_ON(bfqg == ((struct bfq_data *)(bfqg->bfqd))->root_group);
+ BUG_ON(bfqg->active_entities == 0);
+ if (bfqg->active_entities == 1)
+ return true;
+#endif
+
+ return false;
+}
+
/*
* Get next queue for service.
*/
@@ -1083,58 +1677,208 @@ static struct bfq_queue *bfq_get_next_queue(struct bfq_data *bfqd)
@@ -1083,58 +1679,208 @@ static struct bfq_queue *bfq_get_next_queue(struct bfq_data *bfqd)
if (bfqd->busy_queues == 0)
return NULL;
@@ -7883,7 +7905,7 @@ index a5ed694..4af77f4 100644
{
BUG_ON(!bfq_bfqq_busy(bfqq));
BUG_ON(!RB_EMPTY_ROOT(&bfqq->sort_list));
@@ -1146,27 +1890,20 @@ static void bfq_del_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq,
@@ -1146,27 +1892,20 @@ static void bfq_del_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq,
BUG_ON(bfqd->busy_queues == 0);
bfqd->busy_queues--;
@@ -7918,7 +7940,7 @@ index a5ed694..4af77f4 100644
}
/*
@@ -1184,16 +1921,11 @@ static void bfq_add_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq)
@@ -1184,16 +1923,11 @@ static void bfq_add_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq)
bfq_mark_bfqq_busy(bfqq);
bfqd->busy_queues++;
@@ -7938,13 +7960,13 @@ index a5ed694..4af77f4 100644
bfqd->wr_busy_queues++;
}
diff --git a/block/bfq.h b/block/bfq.h
index fcce855..57ab51d 100644
index fcce855..bef8244 100644
--- a/block/bfq.h
+++ b/block/bfq.h
@@ -1,5 +1,5 @@
/*
- * BFQ-v7r11 for 4.5.0: data structures and common functions prototypes.
+ * BFQ v8r6 for 4.9.0: data structures and common functions prototypes.
+ * BFQ v8r7 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>
@@ -0,0 +1,34 @@
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
@@ -0,0 +1,69 @@
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>
@@ -0,0 +1,729 @@
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
@@ -0,0 +1,39 @@
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
@@ -0,0 +1,28 @@
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
@@ -0,0 +1,38 @@
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
@@ -0,0 +1,469 @@
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
@@ -0,0 +1,24 @@
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}

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