mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-17 02:36:21 +00:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Conflicts: drivers/net/ethernet/google/gve/gve.h 3ce934558097 ("gve: Secure enough bytes in the first TX desc for all TCP pkts") 75eaae158b1b ("gve: Add XDP DROP and TX support for GQI-QPL format") https://lore.kernel.org/all/20230406104927.45d176f5@canb.auug.org.au/ https://lore.kernel.org/all/c5872985-1a95-0bc8-9dcc-b6f23b439e9d@tessares.net/ Adjacent changes: net/can/isotp.c 051737439eae ("can: isotp: fix race between isotp_sendsmg() and isotp_release()") 96d1c81e6a04 ("can: isotp: add module parameter for maximum pdu size") Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
d9c960675a
@ -36,7 +36,6 @@ problems and bugs in particular.
|
|||||||
|
|
||||||
reporting-issues
|
reporting-issues
|
||||||
reporting-regressions
|
reporting-regressions
|
||||||
security-bugs
|
|
||||||
bug-hunting
|
bug-hunting
|
||||||
bug-bisect
|
bug-bisect
|
||||||
tainted-kernels
|
tainted-kernels
|
||||||
|
@ -395,7 +395,7 @@ might want to be aware of; it for example explains how to add your issue to the
|
|||||||
list of tracked regressions, to ensure it won't fall through the cracks.
|
list of tracked regressions, to ensure it won't fall through the cracks.
|
||||||
|
|
||||||
What qualifies as security issue is left to your judgment. Consider reading
|
What qualifies as security issue is left to your judgment. Consider reading
|
||||||
Documentation/admin-guide/security-bugs.rst before proceeding, as it
|
Documentation/process/security-bugs.rst before proceeding, as it
|
||||||
provides additional details how to best handle security issues.
|
provides additional details how to best handle security issues.
|
||||||
|
|
||||||
An issue is a 'really severe problem' when something totally unacceptably bad
|
An issue is a 'really severe problem' when something totally unacceptably bad
|
||||||
@ -1269,7 +1269,7 @@ them when sending the report by mail. If you filed it in a bug tracker, forward
|
|||||||
the report's text to these addresses; but on top of it put a small note where
|
the report's text to these addresses; but on top of it put a small note where
|
||||||
you mention that you filed it with a link to the ticket.
|
you mention that you filed it with a link to the ticket.
|
||||||
|
|
||||||
See Documentation/admin-guide/security-bugs.rst for more information.
|
See Documentation/process/security-bugs.rst for more information.
|
||||||
|
|
||||||
|
|
||||||
Duties after the report went out
|
Duties after the report went out
|
||||||
|
@ -96,9 +96,11 @@ $defs:
|
|||||||
2: Lower Slew rate (slower edges)
|
2: Lower Slew rate (slower edges)
|
||||||
3: Reserved (No adjustments)
|
3: Reserved (No adjustments)
|
||||||
|
|
||||||
|
bias-bus-hold: true
|
||||||
bias-pull-down: true
|
bias-pull-down: true
|
||||||
bias-pull-up: true
|
bias-pull-up: true
|
||||||
bias-disable: true
|
bias-disable: true
|
||||||
|
input-enable: true
|
||||||
output-high: true
|
output-high: true
|
||||||
output-low: true
|
output-low: true
|
||||||
|
|
||||||
|
@ -138,7 +138,7 @@ required reading:
|
|||||||
philosophy and is very important for people moving to Linux from
|
philosophy and is very important for people moving to Linux from
|
||||||
development on other Operating Systems.
|
development on other Operating Systems.
|
||||||
|
|
||||||
:ref:`Documentation/admin-guide/security-bugs.rst <securitybugs>`
|
:ref:`Documentation/process/security-bugs.rst <securitybugs>`
|
||||||
If you feel you have found a security problem in the Linux kernel,
|
If you feel you have found a security problem in the Linux kernel,
|
||||||
please follow the steps in this document to help notify the kernel
|
please follow the steps in this document to help notify the kernel
|
||||||
developers, and help solve the issue.
|
developers, and help solve the issue.
|
||||||
|
@ -35,6 +35,14 @@ Below are the essential guides that every developer should read.
|
|||||||
kernel-enforcement-statement
|
kernel-enforcement-statement
|
||||||
kernel-driver-statement
|
kernel-driver-statement
|
||||||
|
|
||||||
|
For security issues, see:
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 1
|
||||||
|
|
||||||
|
security-bugs
|
||||||
|
embargoed-hardware-issues
|
||||||
|
|
||||||
Other guides to the community that are of interest to most developers are:
|
Other guides to the community that are of interest to most developers are:
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
@ -47,7 +55,6 @@ Other guides to the community that are of interest to most developers are:
|
|||||||
submit-checklist
|
submit-checklist
|
||||||
kernel-docs
|
kernel-docs
|
||||||
deprecated
|
deprecated
|
||||||
embargoed-hardware-issues
|
|
||||||
maintainers
|
maintainers
|
||||||
researcher-guidelines
|
researcher-guidelines
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ Before contributing, carefully read the appropriate documentation:
|
|||||||
* Documentation/process/development-process.rst
|
* Documentation/process/development-process.rst
|
||||||
* Documentation/process/submitting-patches.rst
|
* Documentation/process/submitting-patches.rst
|
||||||
* Documentation/admin-guide/reporting-issues.rst
|
* Documentation/admin-guide/reporting-issues.rst
|
||||||
* Documentation/admin-guide/security-bugs.rst
|
* Documentation/process/security-bugs.rst
|
||||||
|
|
||||||
Then send a patch (including a commit log with all the details listed
|
Then send a patch (including a commit log with all the details listed
|
||||||
below) and follow up on any feedback from other developers.
|
below) and follow up on any feedback from other developers.
|
||||||
|
@ -39,7 +39,7 @@ Procedure for submitting patches to the -stable tree
|
|||||||
|
|
||||||
Security patches should not be handled (solely) by the -stable review
|
Security patches should not be handled (solely) by the -stable review
|
||||||
process but should follow the procedures in
|
process but should follow the procedures in
|
||||||
:ref:`Documentation/admin-guide/security-bugs.rst <securitybugs>`.
|
:ref:`Documentation/process/security-bugs.rst <securitybugs>`.
|
||||||
|
|
||||||
For all other submissions, choose one of the following procedures
|
For all other submissions, choose one of the following procedures
|
||||||
-----------------------------------------------------------------
|
-----------------------------------------------------------------
|
||||||
|
@ -254,7 +254,7 @@ If you have a patch that fixes an exploitable security bug, send that patch
|
|||||||
to security@kernel.org. For severe bugs, a short embargo may be considered
|
to security@kernel.org. For severe bugs, a short embargo may be considered
|
||||||
to allow distributors to get the patch out to users; in such cases,
|
to allow distributors to get the patch out to users; in such cases,
|
||||||
obviously, the patch should not be sent to any public lists. See also
|
obviously, the patch should not be sent to any public lists. See also
|
||||||
Documentation/admin-guide/security-bugs.rst.
|
Documentation/process/security-bugs.rst.
|
||||||
|
|
||||||
Patches that fix a severe bug in a released kernel should be directed
|
Patches that fix a severe bug in a released kernel should be directed
|
||||||
toward the stable maintainers by putting a line like this::
|
toward the stable maintainers by putting a line like this::
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
.. include:: ../disclaimer-ita.rst
|
.. include:: ../disclaimer-ita.rst
|
||||||
|
|
||||||
:Original: :ref:`Documentation/admin-guide/security-bugs.rst <securitybugs>`
|
:Original: :ref:`Documentation/process/security-bugs.rst <securitybugs>`
|
||||||
|
|
||||||
.. _it_securitybugs:
|
.. _it_securitybugs:
|
||||||
|
|
||||||
|
@ -272,7 +272,7 @@ embargo potrebbe essere preso in considerazione per dare il tempo alle
|
|||||||
distribuzioni di prendere la patch e renderla disponibile ai loro utenti;
|
distribuzioni di prendere la patch e renderla disponibile ai loro utenti;
|
||||||
in questo caso, ovviamente, la patch non dovrebbe essere inviata su alcuna
|
in questo caso, ovviamente, la patch non dovrebbe essere inviata su alcuna
|
||||||
lista di discussione pubblica. Leggete anche
|
lista di discussione pubblica. Leggete anche
|
||||||
Documentation/admin-guide/security-bugs.rst.
|
Documentation/process/security-bugs.rst.
|
||||||
|
|
||||||
Patch che correggono bachi importanti su un kernel già rilasciato, dovrebbero
|
Patch che correggono bachi importanti su un kernel già rilasciato, dovrebbero
|
||||||
essere inviate ai manutentori dei kernel stabili aggiungendo la seguente riga::
|
essere inviate ai manutentori dei kernel stabili aggiungendo la seguente riga::
|
||||||
|
@ -167,7 +167,7 @@ linux-api@vger.kernel.org に送ることを勧めます。
|
|||||||
このドキュメントは Linux 開発の思想を理解するのに非常に重要です。
|
このドキュメントは Linux 開発の思想を理解するのに非常に重要です。
|
||||||
そして、他のOSでの開発者が Linux に移る時にとても重要です。
|
そして、他のOSでの開発者が Linux に移る時にとても重要です。
|
||||||
|
|
||||||
:ref:`Documentation/admin-guide/security-bugs.rst <securitybugs>`
|
:ref:`Documentation/process/security-bugs.rst <securitybugs>`
|
||||||
もし Linux カーネルでセキュリティ問題を発見したように思ったら、こ
|
もし Linux カーネルでセキュリティ問題を発見したように思ったら、こ
|
||||||
のドキュメントのステップに従ってカーネル開発者に連絡し、問題解決を
|
のドキュメントのステップに従ってカーネル開発者に連絡し、問題解決を
|
||||||
支援してください。
|
支援してください。
|
||||||
|
@ -157,7 +157,7 @@ mtk.manpages@gmail.com의 메인테이너에게 보낼 것을 권장한다.
|
|||||||
리눅스로 전향하는 사람들에게는 매우 중요하다.
|
리눅스로 전향하는 사람들에게는 매우 중요하다.
|
||||||
|
|
||||||
|
|
||||||
:ref:`Documentation/admin-guide/security-bugs.rst <securitybugs>`
|
:ref:`Documentation/process/security-bugs.rst <securitybugs>`
|
||||||
여러분들이 리눅스 커널의 보안 문제를 발견했다고 생각한다면 이 문서에
|
여러분들이 리눅스 커널의 보안 문제를 발견했다고 생각한다면 이 문서에
|
||||||
나온 단계에 따라서 커널 개발자들에게 알리고 그 문제를 해결할 수 있도록
|
나온 단계에 따라서 커널 개발자들에게 알리고 그 문제를 해결할 수 있도록
|
||||||
도와 달라.
|
도와 달라.
|
||||||
|
@ -135,7 +135,7 @@ de obligada lectura:
|
|||||||
de Linux y es muy importante para las personas que se mudan a Linux
|
de Linux y es muy importante para las personas que se mudan a Linux
|
||||||
tras desarrollar otros sistemas operativos.
|
tras desarrollar otros sistemas operativos.
|
||||||
|
|
||||||
:ref:`Documentation/admin-guide/security-bugs.rst <securitybugs>`
|
:ref:`Documentation/process/security-bugs.rst <securitybugs>`
|
||||||
Si cree que ha encontrado un problema de seguridad en el kernel de
|
Si cree que ha encontrado un problema de seguridad en el kernel de
|
||||||
Linux, siga los pasos de este documento para ayudar a notificar a los
|
Linux, siga los pasos de este documento para ayudar a notificar a los
|
||||||
desarrolladores del kernel y ayudar a resolver el problema.
|
desarrolladores del kernel y ayudar a resolver el problema.
|
||||||
|
@ -276,7 +276,7 @@ parche a security@kernel.org. Para errores graves, se debe mantener un
|
|||||||
poco de discreción y permitir que los distribuidores entreguen el parche a
|
poco de discreción y permitir que los distribuidores entreguen el parche a
|
||||||
los usuarios; en esos casos, obviamente, el parche no debe enviarse a
|
los usuarios; en esos casos, obviamente, el parche no debe enviarse a
|
||||||
ninguna lista pública. Revise también
|
ninguna lista pública. Revise también
|
||||||
Documentation/admin-guide/security-bugs.rst.
|
Documentation/process/security-bugs.rst.
|
||||||
|
|
||||||
Los parches que corrigen un error grave en un kernel en uso deben dirigirse
|
Los parches que corrigen un error grave en un kernel en uso deben dirigirse
|
||||||
hacia los maintainers estables poniendo una línea como esta::
|
hacia los maintainers estables poniendo una línea como esta::
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
.. include:: ../disclaimer-zh_CN.rst
|
.. include:: ../disclaimer-zh_CN.rst
|
||||||
|
|
||||||
:Original: :doc:`../../../admin-guide/security-bugs`
|
:Original: :doc:`../../../process/security-bugs`
|
||||||
|
|
||||||
:译者:
|
:译者:
|
||||||
|
|
||||||
|
@ -125,7 +125,7 @@ Linux内核代码中包含有大量的文档。这些文档对于学习如何与
|
|||||||
这篇文档对于理解Linux的开发哲学至关重要。对于将开发平台从其他操作系
|
这篇文档对于理解Linux的开发哲学至关重要。对于将开发平台从其他操作系
|
||||||
统转移到Linux的人来说也很重要。
|
统转移到Linux的人来说也很重要。
|
||||||
|
|
||||||
:ref:`Documentation/admin-guide/security-bugs.rst <securitybugs>`
|
:ref:`Documentation/process/security-bugs.rst <securitybugs>`
|
||||||
如果你认为自己发现了Linux内核的安全性问题,请根据这篇文档中的步骤来
|
如果你认为自己发现了Linux内核的安全性问题,请根据这篇文档中的步骤来
|
||||||
提醒其他内核开发者并帮助解决这个问题。
|
提醒其他内核开发者并帮助解决这个问题。
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
.. include:: ../disclaimer-zh_TW.rst
|
.. include:: ../disclaimer-zh_TW.rst
|
||||||
|
|
||||||
:Original: :doc:`../../../admin-guide/security-bugs`
|
:Original: :doc:`../../../process/security-bugs`
|
||||||
|
|
||||||
:譯者:
|
:譯者:
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ Linux內核代碼中包含有大量的文檔。這些文檔對於學習如何與
|
|||||||
這篇文檔對於理解Linux的開發哲學至關重要。對於將開發平台從其他操作系
|
這篇文檔對於理解Linux的開發哲學至關重要。對於將開發平台從其他操作系
|
||||||
統轉移到Linux的人來說也很重要。
|
統轉移到Linux的人來說也很重要。
|
||||||
|
|
||||||
:ref:`Documentation/admin-guide/security-bugs.rst <securitybugs>`
|
:ref:`Documentation/process/security-bugs.rst <securitybugs>`
|
||||||
如果你認爲自己發現了Linux內核的安全性問題,請根據這篇文檔中的步驟來
|
如果你認爲自己發現了Linux內核的安全性問題,請根據這篇文檔中的步驟來
|
||||||
提醒其他內核開發者並幫助解決這個問題。
|
提醒其他內核開發者並幫助解決這個問題。
|
||||||
|
|
||||||
|
@ -8296,11 +8296,11 @@ ENOSYS for the others.
|
|||||||
8.35 KVM_CAP_PMU_CAPABILITY
|
8.35 KVM_CAP_PMU_CAPABILITY
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
:Capability KVM_CAP_PMU_CAPABILITY
|
:Capability: KVM_CAP_PMU_CAPABILITY
|
||||||
:Architectures: x86
|
:Architectures: x86
|
||||||
:Type: vm
|
:Type: vm
|
||||||
:Parameters: arg[0] is bitmask of PMU virtualization capabilities.
|
:Parameters: arg[0] is bitmask of PMU virtualization capabilities.
|
||||||
:Returns 0 on success, -EINVAL when arg[0] contains invalid bits
|
:Returns: 0 on success, -EINVAL when arg[0] contains invalid bits
|
||||||
|
|
||||||
This capability alters PMU virtualization in KVM.
|
This capability alters PMU virtualization in KVM.
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ Tips for patch submitters
|
|||||||
and ideally, should come with a patch proposal. Please do not send
|
and ideally, should come with a patch proposal. Please do not send
|
||||||
automated reports to this list either. Such bugs will be handled
|
automated reports to this list either. Such bugs will be handled
|
||||||
better and faster in the usual public places. See
|
better and faster in the usual public places. See
|
||||||
Documentation/admin-guide/security-bugs.rst for details.
|
Documentation/process/security-bugs.rst for details.
|
||||||
|
|
||||||
8. Happy hacking.
|
8. Happy hacking.
|
||||||
|
|
||||||
@ -18312,8 +18312,9 @@ F: drivers/s390/block/dasd*
|
|||||||
F: include/linux/dasd_mod.h
|
F: include/linux/dasd_mod.h
|
||||||
|
|
||||||
S390 IOMMU (PCI)
|
S390 IOMMU (PCI)
|
||||||
|
M: Niklas Schnelle <schnelle@linux.ibm.com>
|
||||||
M: Matthew Rosato <mjrosato@linux.ibm.com>
|
M: Matthew Rosato <mjrosato@linux.ibm.com>
|
||||||
M: Gerald Schaefer <gerald.schaefer@linux.ibm.com>
|
R: Gerald Schaefer <gerald.schaefer@linux.ibm.com>
|
||||||
L: linux-s390@vger.kernel.org
|
L: linux-s390@vger.kernel.org
|
||||||
S: Supported
|
S: Supported
|
||||||
F: drivers/iommu/s390-iommu.c
|
F: drivers/iommu/s390-iommu.c
|
||||||
@ -18822,7 +18823,7 @@ F: include/uapi/linux/sed*
|
|||||||
SECURITY CONTACT
|
SECURITY CONTACT
|
||||||
M: Security Officers <security@kernel.org>
|
M: Security Officers <security@kernel.org>
|
||||||
S: Supported
|
S: Supported
|
||||||
F: Documentation/admin-guide/security-bugs.rst
|
F: Documentation/process/security-bugs.rst
|
||||||
|
|
||||||
SECURITY SUBSYSTEM
|
SECURITY SUBSYSTEM
|
||||||
M: Paul Moore <paul@paul-moore.com>
|
M: Paul Moore <paul@paul-moore.com>
|
||||||
|
2
Makefile
2
Makefile
@ -2,7 +2,7 @@
|
|||||||
VERSION = 6
|
VERSION = 6
|
||||||
PATCHLEVEL = 3
|
PATCHLEVEL = 3
|
||||||
SUBLEVEL = 0
|
SUBLEVEL = 0
|
||||||
EXTRAVERSION = -rc4
|
EXTRAVERSION = -rc5
|
||||||
NAME = Hurr durr I'ma ninja sloth
|
NAME = Hurr durr I'ma ninja sloth
|
||||||
|
|
||||||
# *DOCUMENTATION*
|
# *DOCUMENTATION*
|
||||||
|
@ -220,6 +220,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
|
|||||||
case KVM_CAP_VCPU_ATTRIBUTES:
|
case KVM_CAP_VCPU_ATTRIBUTES:
|
||||||
case KVM_CAP_PTP_KVM:
|
case KVM_CAP_PTP_KVM:
|
||||||
case KVM_CAP_ARM_SYSTEM_SUSPEND:
|
case KVM_CAP_ARM_SYSTEM_SUSPEND:
|
||||||
|
case KVM_CAP_IRQFD_RESAMPLE:
|
||||||
r = 1;
|
r = 1;
|
||||||
break;
|
break;
|
||||||
case KVM_CAP_SET_GUEST_DEBUG2:
|
case KVM_CAP_SET_GUEST_DEBUG2:
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
#include <asm/bmips.h>
|
#include <asm/bmips.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
|
|
||||||
|
bool bmips_rac_flush_disable;
|
||||||
|
|
||||||
void arch_sync_dma_for_cpu_all(void)
|
void arch_sync_dma_for_cpu_all(void)
|
||||||
{
|
{
|
||||||
void __iomem *cbr = BMIPS_GET_CBR();
|
void __iomem *cbr = BMIPS_GET_CBR();
|
||||||
@ -15,6 +17,9 @@ void arch_sync_dma_for_cpu_all(void)
|
|||||||
boot_cpu_type() != CPU_BMIPS4380)
|
boot_cpu_type() != CPU_BMIPS4380)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (unlikely(bmips_rac_flush_disable))
|
||||||
|
return;
|
||||||
|
|
||||||
/* Flush stale data out of the readahead cache */
|
/* Flush stale data out of the readahead cache */
|
||||||
cfg = __raw_readl(cbr + BMIPS_RAC_CONFIG);
|
cfg = __raw_readl(cbr + BMIPS_RAC_CONFIG);
|
||||||
__raw_writel(cfg | 0x100, cbr + BMIPS_RAC_CONFIG);
|
__raw_writel(cfg | 0x100, cbr + BMIPS_RAC_CONFIG);
|
||||||
|
@ -35,6 +35,8 @@
|
|||||||
#define REG_BCM6328_OTP ((void __iomem *)CKSEG1ADDR(0x1000062c))
|
#define REG_BCM6328_OTP ((void __iomem *)CKSEG1ADDR(0x1000062c))
|
||||||
#define BCM6328_TP1_DISABLED BIT(9)
|
#define BCM6328_TP1_DISABLED BIT(9)
|
||||||
|
|
||||||
|
extern bool bmips_rac_flush_disable;
|
||||||
|
|
||||||
static const unsigned long kbase = VMLINUX_LOAD_ADDRESS & 0xfff00000;
|
static const unsigned long kbase = VMLINUX_LOAD_ADDRESS & 0xfff00000;
|
||||||
|
|
||||||
struct bmips_quirk {
|
struct bmips_quirk {
|
||||||
@ -104,6 +106,12 @@ static void bcm6358_quirks(void)
|
|||||||
* disable SMP for now
|
* disable SMP for now
|
||||||
*/
|
*/
|
||||||
bmips_smp_enabled = 0;
|
bmips_smp_enabled = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RAC flush causes kernel panics on BCM6358 when booting from TP1
|
||||||
|
* because the bootloader is not initializing it properly.
|
||||||
|
*/
|
||||||
|
bmips_rac_flush_disable = !!(read_c0_brcm_cmt_local() & (1 << 31));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bcm6368_quirks(void)
|
static void bcm6368_quirks(void)
|
||||||
|
@ -148,6 +148,11 @@ static inline void flush_tlb_fix_spurious_fault(struct vm_area_struct *vma,
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool __pte_protnone(unsigned long pte)
|
||||||
|
{
|
||||||
|
return (pte & (pgprot_val(PAGE_NONE) | _PAGE_RWX)) == pgprot_val(PAGE_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool __pte_flags_need_flush(unsigned long oldval,
|
static inline bool __pte_flags_need_flush(unsigned long oldval,
|
||||||
unsigned long newval)
|
unsigned long newval)
|
||||||
{
|
{
|
||||||
@ -164,8 +169,8 @@ static inline bool __pte_flags_need_flush(unsigned long oldval,
|
|||||||
/*
|
/*
|
||||||
* We do not expect kernel mappings or non-PTEs or not-present PTEs.
|
* We do not expect kernel mappings or non-PTEs or not-present PTEs.
|
||||||
*/
|
*/
|
||||||
VM_WARN_ON_ONCE(oldval & _PAGE_PRIVILEGED);
|
VM_WARN_ON_ONCE(!__pte_protnone(oldval) && oldval & _PAGE_PRIVILEGED);
|
||||||
VM_WARN_ON_ONCE(newval & _PAGE_PRIVILEGED);
|
VM_WARN_ON_ONCE(!__pte_protnone(newval) && newval & _PAGE_PRIVILEGED);
|
||||||
VM_WARN_ON_ONCE(!(oldval & _PAGE_PTE));
|
VM_WARN_ON_ONCE(!(oldval & _PAGE_PTE));
|
||||||
VM_WARN_ON_ONCE(!(newval & _PAGE_PTE));
|
VM_WARN_ON_ONCE(!(newval & _PAGE_PTE));
|
||||||
VM_WARN_ON_ONCE(!(oldval & _PAGE_PRESENT));
|
VM_WARN_ON_ONCE(!(oldval & _PAGE_PRESENT));
|
||||||
|
@ -290,6 +290,9 @@ static int gpr_set(struct task_struct *target, const struct user_regset *regset,
|
|||||||
static int ppr_get(struct task_struct *target, const struct user_regset *regset,
|
static int ppr_get(struct task_struct *target, const struct user_regset *regset,
|
||||||
struct membuf to)
|
struct membuf to)
|
||||||
{
|
{
|
||||||
|
if (!target->thread.regs)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
return membuf_write(&to, &target->thread.regs->ppr, sizeof(u64));
|
return membuf_write(&to, &target->thread.regs->ppr, sizeof(u64));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,6 +300,9 @@ static int ppr_set(struct task_struct *target, const struct user_regset *regset,
|
|||||||
unsigned int pos, unsigned int count, const void *kbuf,
|
unsigned int pos, unsigned int count, const void *kbuf,
|
||||||
const void __user *ubuf)
|
const void __user *ubuf)
|
||||||
{
|
{
|
||||||
|
if (!target->thread.regs)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
||||||
&target->thread.regs->ppr, 0, sizeof(u64));
|
&target->thread.regs->ppr, 0, sizeof(u64));
|
||||||
}
|
}
|
||||||
|
@ -576,6 +576,12 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
|
|||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_HAVE_KVM_IRQFD
|
||||||
|
case KVM_CAP_IRQFD_RESAMPLE:
|
||||||
|
r = !xive_enabled();
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
case KVM_CAP_PPC_ALLOC_HTAB:
|
case KVM_CAP_PPC_ALLOC_HTAB:
|
||||||
r = hv_enabled;
|
r = hv_enabled;
|
||||||
break;
|
break;
|
||||||
|
@ -856,6 +856,13 @@ int pseries_vas_dlpar_cpu(void)
|
|||||||
{
|
{
|
||||||
int new_nr_creds, rc;
|
int new_nr_creds, rc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NX-GZIP is not enabled. Nothing to do for DLPAR event
|
||||||
|
*/
|
||||||
|
if (!copypaste_feat)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
|
||||||
rc = h_query_vas_capabilities(H_QUERY_VAS_CAPABILITIES,
|
rc = h_query_vas_capabilities(H_QUERY_VAS_CAPABILITIES,
|
||||||
vascaps[VAS_GZIP_DEF_FEAT_TYPE].feat,
|
vascaps[VAS_GZIP_DEF_FEAT_TYPE].feat,
|
||||||
(u64)virt_to_phys(&hv_cop_caps));
|
(u64)virt_to_phys(&hv_cop_caps));
|
||||||
@ -1012,6 +1019,7 @@ static int __init pseries_vas_init(void)
|
|||||||
* Linux supports user space COPY/PASTE only with Radix
|
* Linux supports user space COPY/PASTE only with Radix
|
||||||
*/
|
*/
|
||||||
if (!radix_enabled()) {
|
if (!radix_enabled()) {
|
||||||
|
copypaste_feat = false;
|
||||||
pr_err("API is supported only with radix page tables\n");
|
pr_err("API is supported only with radix page tables\n");
|
||||||
return -ENOTSUPP;
|
return -ENOTSUPP;
|
||||||
}
|
}
|
||||||
|
@ -126,6 +126,7 @@ config RISCV
|
|||||||
select OF_IRQ
|
select OF_IRQ
|
||||||
select PCI_DOMAINS_GENERIC if PCI
|
select PCI_DOMAINS_GENERIC if PCI
|
||||||
select PCI_MSI if PCI
|
select PCI_MSI if PCI
|
||||||
|
select RISCV_ALTERNATIVE if !XIP_KERNEL
|
||||||
select RISCV_INTC
|
select RISCV_INTC
|
||||||
select RISCV_TIMER if RISCV_SBI
|
select RISCV_TIMER if RISCV_SBI
|
||||||
select SIFIVE_PLIC
|
select SIFIVE_PLIC
|
||||||
@ -401,9 +402,8 @@ config RISCV_ISA_C
|
|||||||
config RISCV_ISA_SVPBMT
|
config RISCV_ISA_SVPBMT
|
||||||
bool "SVPBMT extension support"
|
bool "SVPBMT extension support"
|
||||||
depends on 64BIT && MMU
|
depends on 64BIT && MMU
|
||||||
depends on !XIP_KERNEL
|
depends on RISCV_ALTERNATIVE
|
||||||
default y
|
default y
|
||||||
select RISCV_ALTERNATIVE
|
|
||||||
help
|
help
|
||||||
Adds support to dynamically detect the presence of the SVPBMT
|
Adds support to dynamically detect the presence of the SVPBMT
|
||||||
ISA-extension (Supervisor-mode: page-based memory types) and
|
ISA-extension (Supervisor-mode: page-based memory types) and
|
||||||
@ -428,8 +428,8 @@ config TOOLCHAIN_HAS_ZBB
|
|||||||
config RISCV_ISA_ZBB
|
config RISCV_ISA_ZBB
|
||||||
bool "Zbb extension support for bit manipulation instructions"
|
bool "Zbb extension support for bit manipulation instructions"
|
||||||
depends on TOOLCHAIN_HAS_ZBB
|
depends on TOOLCHAIN_HAS_ZBB
|
||||||
depends on !XIP_KERNEL && MMU
|
depends on MMU
|
||||||
select RISCV_ALTERNATIVE
|
depends on RISCV_ALTERNATIVE
|
||||||
default y
|
default y
|
||||||
help
|
help
|
||||||
Adds support to dynamically detect the presence of the ZBB
|
Adds support to dynamically detect the presence of the ZBB
|
||||||
@ -443,9 +443,9 @@ config RISCV_ISA_ZBB
|
|||||||
|
|
||||||
config RISCV_ISA_ZICBOM
|
config RISCV_ISA_ZICBOM
|
||||||
bool "Zicbom extension support for non-coherent DMA operation"
|
bool "Zicbom extension support for non-coherent DMA operation"
|
||||||
depends on !XIP_KERNEL && MMU
|
depends on MMU
|
||||||
|
depends on RISCV_ALTERNATIVE
|
||||||
default y
|
default y
|
||||||
select RISCV_ALTERNATIVE
|
|
||||||
select RISCV_DMA_NONCOHERENT
|
select RISCV_DMA_NONCOHERENT
|
||||||
help
|
help
|
||||||
Adds support to dynamically detect the presence of the ZICBOM
|
Adds support to dynamically detect the presence of the ZICBOM
|
||||||
|
@ -2,8 +2,7 @@ menu "CPU errata selection"
|
|||||||
|
|
||||||
config ERRATA_SIFIVE
|
config ERRATA_SIFIVE
|
||||||
bool "SiFive errata"
|
bool "SiFive errata"
|
||||||
depends on !XIP_KERNEL
|
depends on RISCV_ALTERNATIVE
|
||||||
select RISCV_ALTERNATIVE
|
|
||||||
help
|
help
|
||||||
All SiFive errata Kconfig depend on this Kconfig. Disabling
|
All SiFive errata Kconfig depend on this Kconfig. Disabling
|
||||||
this Kconfig will disable all SiFive errata. Please say "Y"
|
this Kconfig will disable all SiFive errata. Please say "Y"
|
||||||
@ -35,8 +34,7 @@ config ERRATA_SIFIVE_CIP_1200
|
|||||||
|
|
||||||
config ERRATA_THEAD
|
config ERRATA_THEAD
|
||||||
bool "T-HEAD errata"
|
bool "T-HEAD errata"
|
||||||
depends on !XIP_KERNEL
|
depends on RISCV_ALTERNATIVE
|
||||||
select RISCV_ALTERNATIVE
|
|
||||||
help
|
help
|
||||||
All T-HEAD errata Kconfig depend on this Kconfig. Disabling
|
All T-HEAD errata Kconfig depend on this Kconfig. Disabling
|
||||||
this Kconfig will disable all T-HEAD errata. Please say "Y"
|
this Kconfig will disable all T-HEAD errata. Please say "Y"
|
||||||
|
@ -57,18 +57,31 @@ struct riscv_isa_ext_data {
|
|||||||
unsigned int isa_ext_id;
|
unsigned int isa_ext_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
unsigned long riscv_isa_extension_base(const unsigned long *isa_bitmap);
|
||||||
|
|
||||||
|
#define riscv_isa_extension_mask(ext) BIT_MASK(RISCV_ISA_EXT_##ext)
|
||||||
|
|
||||||
|
bool __riscv_isa_extension_available(const unsigned long *isa_bitmap, int bit);
|
||||||
|
#define riscv_isa_extension_available(isa_bitmap, ext) \
|
||||||
|
__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_##ext)
|
||||||
|
|
||||||
static __always_inline bool
|
static __always_inline bool
|
||||||
riscv_has_extension_likely(const unsigned long ext)
|
riscv_has_extension_likely(const unsigned long ext)
|
||||||
{
|
{
|
||||||
compiletime_assert(ext < RISCV_ISA_EXT_MAX,
|
compiletime_assert(ext < RISCV_ISA_EXT_MAX,
|
||||||
"ext must be < RISCV_ISA_EXT_MAX");
|
"ext must be < RISCV_ISA_EXT_MAX");
|
||||||
|
|
||||||
asm_volatile_goto(
|
if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE)) {
|
||||||
ALTERNATIVE("j %l[l_no]", "nop", 0, %[ext], 1)
|
asm_volatile_goto(
|
||||||
:
|
ALTERNATIVE("j %l[l_no]", "nop", 0, %[ext], 1)
|
||||||
: [ext] "i" (ext)
|
:
|
||||||
:
|
: [ext] "i" (ext)
|
||||||
: l_no);
|
:
|
||||||
|
: l_no);
|
||||||
|
} else {
|
||||||
|
if (!__riscv_isa_extension_available(NULL, ext))
|
||||||
|
goto l_no;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
l_no:
|
l_no:
|
||||||
@ -81,26 +94,23 @@ riscv_has_extension_unlikely(const unsigned long ext)
|
|||||||
compiletime_assert(ext < RISCV_ISA_EXT_MAX,
|
compiletime_assert(ext < RISCV_ISA_EXT_MAX,
|
||||||
"ext must be < RISCV_ISA_EXT_MAX");
|
"ext must be < RISCV_ISA_EXT_MAX");
|
||||||
|
|
||||||
asm_volatile_goto(
|
if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE)) {
|
||||||
ALTERNATIVE("nop", "j %l[l_yes]", 0, %[ext], 1)
|
asm_volatile_goto(
|
||||||
:
|
ALTERNATIVE("nop", "j %l[l_yes]", 0, %[ext], 1)
|
||||||
: [ext] "i" (ext)
|
:
|
||||||
:
|
: [ext] "i" (ext)
|
||||||
: l_yes);
|
:
|
||||||
|
: l_yes);
|
||||||
|
} else {
|
||||||
|
if (__riscv_isa_extension_available(NULL, ext))
|
||||||
|
goto l_yes;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
l_yes:
|
l_yes:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long riscv_isa_extension_base(const unsigned long *isa_bitmap);
|
|
||||||
|
|
||||||
#define riscv_isa_extension_mask(ext) BIT_MASK(RISCV_ISA_EXT_##ext)
|
|
||||||
|
|
||||||
bool __riscv_isa_extension_available(const unsigned long *isa_bitmap, int bit);
|
|
||||||
#define riscv_isa_extension_available(isa_bitmap, ext) \
|
|
||||||
__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_##ext)
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* _ASM_RISCV_HWCAP_H */
|
#endif /* _ASM_RISCV_HWCAP_H */
|
||||||
|
@ -271,10 +271,18 @@ static int handle_prog(struct kvm_vcpu *vcpu)
|
|||||||
* handle_external_interrupt - used for external interruption interceptions
|
* handle_external_interrupt - used for external interruption interceptions
|
||||||
* @vcpu: virtual cpu
|
* @vcpu: virtual cpu
|
||||||
*
|
*
|
||||||
* This interception only occurs if the CPUSTAT_EXT_INT bit was set, or if
|
* This interception occurs if:
|
||||||
* the new PSW does not have external interrupts disabled. In the first case,
|
* - the CPUSTAT_EXT_INT bit was already set when the external interrupt
|
||||||
* we've got to deliver the interrupt manually, and in the second case, we
|
* occurred. In this case, the interrupt needs to be injected manually to
|
||||||
* drop to userspace to handle the situation there.
|
* preserve interrupt priority.
|
||||||
|
* - the external new PSW has external interrupts enabled, which will cause an
|
||||||
|
* interruption loop. We drop to userspace in this case.
|
||||||
|
*
|
||||||
|
* The latter case can be detected by inspecting the external mask bit in the
|
||||||
|
* external new psw.
|
||||||
|
*
|
||||||
|
* Under PV, only the latter case can occur, since interrupt priorities are
|
||||||
|
* handled in the ultravisor.
|
||||||
*/
|
*/
|
||||||
static int handle_external_interrupt(struct kvm_vcpu *vcpu)
|
static int handle_external_interrupt(struct kvm_vcpu *vcpu)
|
||||||
{
|
{
|
||||||
@ -285,10 +293,18 @@ static int handle_external_interrupt(struct kvm_vcpu *vcpu)
|
|||||||
|
|
||||||
vcpu->stat.exit_external_interrupt++;
|
vcpu->stat.exit_external_interrupt++;
|
||||||
|
|
||||||
rc = read_guest_lc(vcpu, __LC_EXT_NEW_PSW, &newpsw, sizeof(psw_t));
|
if (kvm_s390_pv_cpu_is_protected(vcpu)) {
|
||||||
if (rc)
|
newpsw = vcpu->arch.sie_block->gpsw;
|
||||||
return rc;
|
} else {
|
||||||
/* We can not handle clock comparator or timer interrupt with bad PSW */
|
rc = read_guest_lc(vcpu, __LC_EXT_NEW_PSW, &newpsw, sizeof(psw_t));
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clock comparator or timer interrupt with external interrupt enabled
|
||||||
|
* will cause interrupt loop. Drop to userspace.
|
||||||
|
*/
|
||||||
if ((eic == EXT_IRQ_CLK_COMP || eic == EXT_IRQ_CPU_TIMER) &&
|
if ((eic == EXT_IRQ_CLK_COMP || eic == EXT_IRQ_CPU_TIMER) &&
|
||||||
(newpsw.mask & PSW_MASK_EXT))
|
(newpsw.mask & PSW_MASK_EXT))
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
@ -573,6 +573,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
|
|||||||
case KVM_CAP_S390_VCPU_RESETS:
|
case KVM_CAP_S390_VCPU_RESETS:
|
||||||
case KVM_CAP_SET_GUEST_DEBUG:
|
case KVM_CAP_SET_GUEST_DEBUG:
|
||||||
case KVM_CAP_S390_DIAG318:
|
case KVM_CAP_S390_DIAG318:
|
||||||
|
case KVM_CAP_IRQFD_RESAMPLE:
|
||||||
r = 1;
|
r = 1;
|
||||||
break;
|
break;
|
||||||
case KVM_CAP_SET_GUEST_DEBUG2:
|
case KVM_CAP_SET_GUEST_DEBUG2:
|
||||||
|
@ -358,12 +358,16 @@ static void __init ms_hyperv_init_platform(void)
|
|||||||
* To mirror what Windows does we should extract CPU management
|
* To mirror what Windows does we should extract CPU management
|
||||||
* features and use the ReservedIdentityBit to detect if Linux is the
|
* features and use the ReservedIdentityBit to detect if Linux is the
|
||||||
* root partition. But that requires negotiating CPU management
|
* root partition. But that requires negotiating CPU management
|
||||||
* interface (a process to be finalized).
|
* interface (a process to be finalized). For now, use the privilege
|
||||||
|
* flag as the indicator for running as root.
|
||||||
*
|
*
|
||||||
* For now, use the privilege flag as the indicator for running as
|
* Hyper-V should never specify running as root and as a Confidential
|
||||||
* root.
|
* VM. But to protect against a compromised/malicious Hyper-V trying
|
||||||
|
* to exploit root behavior to expose Confidential VM memory, ignore
|
||||||
|
* the root partition setting if also a Confidential VM.
|
||||||
*/
|
*/
|
||||||
if (cpuid_ebx(HYPERV_CPUID_FEATURES) & HV_CPU_MANAGEMENT) {
|
if ((ms_hyperv.priv_high & HV_CPU_MANAGEMENT) &&
|
||||||
|
!(ms_hyperv.priv_high & HV_ISOLATION)) {
|
||||||
hv_root_partition = true;
|
hv_root_partition = true;
|
||||||
pr_info("Hyper-V: running as root partition\n");
|
pr_info("Hyper-V: running as root partition\n");
|
||||||
}
|
}
|
||||||
|
@ -368,9 +368,39 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val)
|
|||||||
mask_after = e->fields.mask;
|
mask_after = e->fields.mask;
|
||||||
if (mask_before != mask_after)
|
if (mask_before != mask_after)
|
||||||
kvm_fire_mask_notifiers(ioapic->kvm, KVM_IRQCHIP_IOAPIC, index, mask_after);
|
kvm_fire_mask_notifiers(ioapic->kvm, KVM_IRQCHIP_IOAPIC, index, mask_after);
|
||||||
if (e->fields.trig_mode == IOAPIC_LEVEL_TRIG
|
if (e->fields.trig_mode == IOAPIC_LEVEL_TRIG &&
|
||||||
&& ioapic->irr & (1 << index))
|
ioapic->irr & (1 << index) && !e->fields.mask && !e->fields.remote_irr) {
|
||||||
ioapic_service(ioapic, index, false);
|
/*
|
||||||
|
* Pending status in irr may be outdated: the IRQ line may have
|
||||||
|
* already been deasserted by a device while the IRQ was masked.
|
||||||
|
* This occurs, for instance, if the interrupt is handled in a
|
||||||
|
* Linux guest as a oneshot interrupt (IRQF_ONESHOT). In this
|
||||||
|
* case the guest acknowledges the interrupt to the device in
|
||||||
|
* its threaded irq handler, i.e. after the EOI but before
|
||||||
|
* unmasking, so at the time of unmasking the IRQ line is
|
||||||
|
* already down but our pending irr bit is still set. In such
|
||||||
|
* cases, injecting this pending interrupt to the guest is
|
||||||
|
* buggy: the guest will receive an extra unwanted interrupt.
|
||||||
|
*
|
||||||
|
* So we need to check here if the IRQ is actually still pending.
|
||||||
|
* As we are generally not able to probe the IRQ line status
|
||||||
|
* directly, we do it through irqfd resampler. Namely, we clear
|
||||||
|
* the pending status and notify the resampler that this interrupt
|
||||||
|
* is done, without actually injecting it into the guest. If the
|
||||||
|
* IRQ line is actually already deasserted, we are done. If it is
|
||||||
|
* still asserted, a new interrupt will be shortly triggered
|
||||||
|
* through irqfd and injected into the guest.
|
||||||
|
*
|
||||||
|
* If, however, it's not possible to resample (no irqfd resampler
|
||||||
|
* registered for this irq), then unconditionally inject this
|
||||||
|
* pending interrupt into the guest, so the guest will not miss
|
||||||
|
* an interrupt, although may get an extra unwanted interrupt.
|
||||||
|
*/
|
||||||
|
if (kvm_notify_irqfd_resampler(ioapic->kvm, KVM_IRQCHIP_IOAPIC, index))
|
||||||
|
ioapic->irr &= ~(1 << index);
|
||||||
|
else
|
||||||
|
ioapic_service(ioapic, index, false);
|
||||||
|
}
|
||||||
if (e->fields.delivery_mode == APIC_DM_FIXED) {
|
if (e->fields.delivery_mode == APIC_DM_FIXED) {
|
||||||
struct kvm_lapic_irq irq;
|
struct kvm_lapic_irq irq;
|
||||||
|
|
||||||
|
@ -12,6 +12,11 @@ int hv_remote_flush_tlb_with_range(struct kvm *kvm,
|
|||||||
int hv_remote_flush_tlb(struct kvm *kvm);
|
int hv_remote_flush_tlb(struct kvm *kvm);
|
||||||
void hv_track_root_tdp(struct kvm_vcpu *vcpu, hpa_t root_tdp);
|
void hv_track_root_tdp(struct kvm_vcpu *vcpu, hpa_t root_tdp);
|
||||||
#else /* !CONFIG_HYPERV */
|
#else /* !CONFIG_HYPERV */
|
||||||
|
static inline int hv_remote_flush_tlb(struct kvm *kvm)
|
||||||
|
{
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void hv_track_root_tdp(struct kvm_vcpu *vcpu, hpa_t root_tdp)
|
static inline void hv_track_root_tdp(struct kvm_vcpu *vcpu, hpa_t root_tdp)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -3729,7 +3729,7 @@ static void svm_enable_nmi_window(struct kvm_vcpu *vcpu)
|
|||||||
svm->vmcb->save.rflags |= (X86_EFLAGS_TF | X86_EFLAGS_RF);
|
svm->vmcb->save.rflags |= (X86_EFLAGS_TF | X86_EFLAGS_RF);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void svm_flush_tlb_current(struct kvm_vcpu *vcpu)
|
static void svm_flush_tlb_asid(struct kvm_vcpu *vcpu)
|
||||||
{
|
{
|
||||||
struct vcpu_svm *svm = to_svm(vcpu);
|
struct vcpu_svm *svm = to_svm(vcpu);
|
||||||
|
|
||||||
@ -3753,6 +3753,37 @@ static void svm_flush_tlb_current(struct kvm_vcpu *vcpu)
|
|||||||
svm->current_vmcb->asid_generation--;
|
svm->current_vmcb->asid_generation--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void svm_flush_tlb_current(struct kvm_vcpu *vcpu)
|
||||||
|
{
|
||||||
|
hpa_t root_tdp = vcpu->arch.mmu->root.hpa;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When running on Hyper-V with EnlightenedNptTlb enabled, explicitly
|
||||||
|
* flush the NPT mappings via hypercall as flushing the ASID only
|
||||||
|
* affects virtual to physical mappings, it does not invalidate guest
|
||||||
|
* physical to host physical mappings.
|
||||||
|
*/
|
||||||
|
if (svm_hv_is_enlightened_tlb_enabled(vcpu) && VALID_PAGE(root_tdp))
|
||||||
|
hyperv_flush_guest_mapping(root_tdp);
|
||||||
|
|
||||||
|
svm_flush_tlb_asid(vcpu);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void svm_flush_tlb_all(struct kvm_vcpu *vcpu)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* When running on Hyper-V with EnlightenedNptTlb enabled, remote TLB
|
||||||
|
* flushes should be routed to hv_remote_flush_tlb() without requesting
|
||||||
|
* a "regular" remote flush. Reaching this point means either there's
|
||||||
|
* a KVM bug or a prior hv_remote_flush_tlb() call failed, both of
|
||||||
|
* which might be fatal to the guest. Yell, but try to recover.
|
||||||
|
*/
|
||||||
|
if (WARN_ON_ONCE(svm_hv_is_enlightened_tlb_enabled(vcpu)))
|
||||||
|
hv_remote_flush_tlb(vcpu->kvm);
|
||||||
|
|
||||||
|
svm_flush_tlb_asid(vcpu);
|
||||||
|
}
|
||||||
|
|
||||||
static void svm_flush_tlb_gva(struct kvm_vcpu *vcpu, gva_t gva)
|
static void svm_flush_tlb_gva(struct kvm_vcpu *vcpu, gva_t gva)
|
||||||
{
|
{
|
||||||
struct vcpu_svm *svm = to_svm(vcpu);
|
struct vcpu_svm *svm = to_svm(vcpu);
|
||||||
@ -4745,10 +4776,10 @@ static struct kvm_x86_ops svm_x86_ops __initdata = {
|
|||||||
.set_rflags = svm_set_rflags,
|
.set_rflags = svm_set_rflags,
|
||||||
.get_if_flag = svm_get_if_flag,
|
.get_if_flag = svm_get_if_flag,
|
||||||
|
|
||||||
.flush_tlb_all = svm_flush_tlb_current,
|
.flush_tlb_all = svm_flush_tlb_all,
|
||||||
.flush_tlb_current = svm_flush_tlb_current,
|
.flush_tlb_current = svm_flush_tlb_current,
|
||||||
.flush_tlb_gva = svm_flush_tlb_gva,
|
.flush_tlb_gva = svm_flush_tlb_gva,
|
||||||
.flush_tlb_guest = svm_flush_tlb_current,
|
.flush_tlb_guest = svm_flush_tlb_asid,
|
||||||
|
|
||||||
.vcpu_pre_run = svm_vcpu_pre_run,
|
.vcpu_pre_run = svm_vcpu_pre_run,
|
||||||
.vcpu_run = svm_vcpu_run,
|
.vcpu_run = svm_vcpu_run,
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
#ifndef __ARCH_X86_KVM_SVM_ONHYPERV_H__
|
#ifndef __ARCH_X86_KVM_SVM_ONHYPERV_H__
|
||||||
#define __ARCH_X86_KVM_SVM_ONHYPERV_H__
|
#define __ARCH_X86_KVM_SVM_ONHYPERV_H__
|
||||||
|
|
||||||
|
#include <asm/mshyperv.h>
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_HYPERV)
|
#if IS_ENABLED(CONFIG_HYPERV)
|
||||||
|
|
||||||
#include "kvm_onhyperv.h"
|
#include "kvm_onhyperv.h"
|
||||||
@ -15,6 +17,14 @@ static struct kvm_x86_ops svm_x86_ops;
|
|||||||
|
|
||||||
int svm_hv_enable_l2_tlb_flush(struct kvm_vcpu *vcpu);
|
int svm_hv_enable_l2_tlb_flush(struct kvm_vcpu *vcpu);
|
||||||
|
|
||||||
|
static inline bool svm_hv_is_enlightened_tlb_enabled(struct kvm_vcpu *vcpu)
|
||||||
|
{
|
||||||
|
struct hv_vmcb_enlightenments *hve = &to_svm(vcpu)->vmcb->control.hv_enlightenments;
|
||||||
|
|
||||||
|
return ms_hyperv.nested_features & HV_X64_NESTED_ENLIGHTENED_TLB &&
|
||||||
|
!!hve->hv_enlightenments_control.enlightened_npt_tlb;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void svm_hv_init_vmcb(struct vmcb *vmcb)
|
static inline void svm_hv_init_vmcb(struct vmcb *vmcb)
|
||||||
{
|
{
|
||||||
struct hv_vmcb_enlightenments *hve = &vmcb->control.hv_enlightenments;
|
struct hv_vmcb_enlightenments *hve = &vmcb->control.hv_enlightenments;
|
||||||
@ -80,6 +90,11 @@ static inline void svm_hv_update_vp_id(struct vmcb *vmcb, struct kvm_vcpu *vcpu)
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
static inline bool svm_hv_is_enlightened_tlb_enabled(struct kvm_vcpu *vcpu)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void svm_hv_init_vmcb(struct vmcb *vmcb)
|
static inline void svm_hv_init_vmcb(struct vmcb *vmcb)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -3868,7 +3868,12 @@ static void nested_vmx_inject_exception_vmexit(struct kvm_vcpu *vcpu)
|
|||||||
exit_qual = 0;
|
exit_qual = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ex->has_error_code) {
|
/*
|
||||||
|
* Unlike AMD's Paged Real Mode, which reports an error code on #PF
|
||||||
|
* VM-Exits even if the CPU is in Real Mode, Intel VMX never sets the
|
||||||
|
* "has error code" flags on VM-Exit if the CPU is in Real Mode.
|
||||||
|
*/
|
||||||
|
if (ex->has_error_code && is_protmode(vcpu)) {
|
||||||
/*
|
/*
|
||||||
* Intel CPUs do not generate error codes with bits 31:16 set,
|
* Intel CPUs do not generate error codes with bits 31:16 set,
|
||||||
* and more importantly VMX disallows setting bits 31:16 in the
|
* and more importantly VMX disallows setting bits 31:16 in the
|
||||||
|
@ -4432,6 +4432,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
|
|||||||
case KVM_CAP_VAPIC:
|
case KVM_CAP_VAPIC:
|
||||||
case KVM_CAP_ENABLE_CAP:
|
case KVM_CAP_ENABLE_CAP:
|
||||||
case KVM_CAP_VM_DISABLE_NX_HUGE_PAGES:
|
case KVM_CAP_VM_DISABLE_NX_HUGE_PAGES:
|
||||||
|
case KVM_CAP_IRQFD_RESAMPLE:
|
||||||
r = 1;
|
r = 1;
|
||||||
break;
|
break;
|
||||||
case KVM_CAP_EXIT_HYPERCALL:
|
case KVM_CAP_EXIT_HYPERCALL:
|
||||||
@ -8903,6 +8904,8 @@ restart:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ctxt->have_exception) {
|
if (ctxt->have_exception) {
|
||||||
|
WARN_ON_ONCE(vcpu->mmio_needed && !vcpu->mmio_is_write);
|
||||||
|
vcpu->mmio_needed = false;
|
||||||
r = 1;
|
r = 1;
|
||||||
inject_emulated_exception(vcpu);
|
inject_emulated_exception(vcpu);
|
||||||
} else if (vcpu->arch.pio.count) {
|
} else if (vcpu->arch.pio.count) {
|
||||||
@ -9906,13 +9909,20 @@ int kvm_check_nested_events(struct kvm_vcpu *vcpu)
|
|||||||
|
|
||||||
static void kvm_inject_exception(struct kvm_vcpu *vcpu)
|
static void kvm_inject_exception(struct kvm_vcpu *vcpu)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* Suppress the error code if the vCPU is in Real Mode, as Real Mode
|
||||||
|
* exceptions don't report error codes. The presence of an error code
|
||||||
|
* is carried with the exception and only stripped when the exception
|
||||||
|
* is injected as intercepted #PF VM-Exits for AMD's Paged Real Mode do
|
||||||
|
* report an error code despite the CPU being in Real Mode.
|
||||||
|
*/
|
||||||
|
vcpu->arch.exception.has_error_code &= is_protmode(vcpu);
|
||||||
|
|
||||||
trace_kvm_inj_exception(vcpu->arch.exception.vector,
|
trace_kvm_inj_exception(vcpu->arch.exception.vector,
|
||||||
vcpu->arch.exception.has_error_code,
|
vcpu->arch.exception.has_error_code,
|
||||||
vcpu->arch.exception.error_code,
|
vcpu->arch.exception.error_code,
|
||||||
vcpu->arch.exception.injected);
|
vcpu->arch.exception.injected);
|
||||||
|
|
||||||
if (vcpu->arch.exception.error_code && !is_protmode(vcpu))
|
|
||||||
vcpu->arch.exception.error_code = false;
|
|
||||||
static_call(kvm_x86_inject_exception)(vcpu);
|
static_call(kvm_x86_inject_exception)(vcpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -461,26 +461,22 @@ ivpu_job_prepare_bos_for_submit(struct drm_file *file, struct ivpu_job *job, u32
|
|||||||
|
|
||||||
job->cmd_buf_vpu_addr = bo->vpu_addr + commands_offset;
|
job->cmd_buf_vpu_addr = bo->vpu_addr + commands_offset;
|
||||||
|
|
||||||
ret = drm_gem_lock_reservations((struct drm_gem_object **)job->bos, buf_count,
|
ret = drm_gem_lock_reservations((struct drm_gem_object **)job->bos, 1, &acquire_ctx);
|
||||||
&acquire_ctx);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ivpu_warn(vdev, "Failed to lock reservations: %d\n", ret);
|
ivpu_warn(vdev, "Failed to lock reservations: %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < buf_count; i++) {
|
ret = dma_resv_reserve_fences(bo->base.resv, 1);
|
||||||
ret = dma_resv_reserve_fences(job->bos[i]->base.resv, 1);
|
if (ret) {
|
||||||
if (ret) {
|
ivpu_warn(vdev, "Failed to reserve fences: %d\n", ret);
|
||||||
ivpu_warn(vdev, "Failed to reserve fences: %d\n", ret);
|
goto unlock_reservations;
|
||||||
goto unlock_reservations;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < buf_count; i++)
|
dma_resv_add_fence(bo->base.resv, job->done_fence, DMA_RESV_USAGE_WRITE);
|
||||||
dma_resv_add_fence(job->bos[i]->base.resv, job->done_fence, DMA_RESV_USAGE_WRITE);
|
|
||||||
|
|
||||||
unlock_reservations:
|
unlock_reservations:
|
||||||
drm_gem_unlock_reservations((struct drm_gem_object **)job->bos, buf_count, &acquire_ctx);
|
drm_gem_unlock_reservations((struct drm_gem_object **)job->bos, 1, &acquire_ctx);
|
||||||
|
|
||||||
wmb(); /* Flush write combining buffers */
|
wmb(); /* Flush write combining buffers */
|
||||||
|
|
||||||
|
@ -140,32 +140,28 @@ int ivpu_pm_suspend_cb(struct device *dev)
|
|||||||
{
|
{
|
||||||
struct drm_device *drm = dev_get_drvdata(dev);
|
struct drm_device *drm = dev_get_drvdata(dev);
|
||||||
struct ivpu_device *vdev = to_ivpu_device(drm);
|
struct ivpu_device *vdev = to_ivpu_device(drm);
|
||||||
int ret;
|
unsigned long timeout;
|
||||||
|
|
||||||
ivpu_dbg(vdev, PM, "Suspend..\n");
|
ivpu_dbg(vdev, PM, "Suspend..\n");
|
||||||
|
|
||||||
ret = ivpu_suspend(vdev);
|
timeout = jiffies + msecs_to_jiffies(vdev->timeout.tdr);
|
||||||
if (ret && vdev->pm->suspend_reschedule_counter) {
|
while (!ivpu_hw_is_idle(vdev)) {
|
||||||
ivpu_dbg(vdev, PM, "Failed to enter idle, rescheduling suspend, retries left %d\n",
|
cond_resched();
|
||||||
vdev->pm->suspend_reschedule_counter);
|
if (time_after_eq(jiffies, timeout)) {
|
||||||
pm_schedule_suspend(dev, vdev->timeout.reschedule_suspend);
|
ivpu_err(vdev, "Failed to enter idle on system suspend\n");
|
||||||
vdev->pm->suspend_reschedule_counter--;
|
return -EBUSY;
|
||||||
return -EBUSY;
|
}
|
||||||
} else if (!vdev->pm->suspend_reschedule_counter) {
|
|
||||||
ivpu_warn(vdev, "Failed to enter idle, force suspend\n");
|
|
||||||
ivpu_pm_prepare_cold_boot(vdev);
|
|
||||||
} else {
|
|
||||||
ivpu_pm_prepare_warm_boot(vdev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vdev->pm->suspend_reschedule_counter = PM_RESCHEDULE_LIMIT;
|
ivpu_suspend(vdev);
|
||||||
|
ivpu_pm_prepare_warm_boot(vdev);
|
||||||
|
|
||||||
pci_save_state(to_pci_dev(dev));
|
pci_save_state(to_pci_dev(dev));
|
||||||
pci_set_power_state(to_pci_dev(dev), PCI_D3hot);
|
pci_set_power_state(to_pci_dev(dev), PCI_D3hot);
|
||||||
|
|
||||||
ivpu_dbg(vdev, PM, "Suspend done.\n");
|
ivpu_dbg(vdev, PM, "Suspend done.\n");
|
||||||
|
|
||||||
return ret;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ivpu_pm_resume_cb(struct device *dev)
|
int ivpu_pm_resume_cb(struct device *dev)
|
||||||
|
@ -459,85 +459,67 @@ out_free:
|
|||||||
Notification Handling
|
Notification Handling
|
||||||
-------------------------------------------------------------------------- */
|
-------------------------------------------------------------------------- */
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* acpi_bus_notify
|
* acpi_bus_notify - Global system-level (0x00-0x7F) notifications handler
|
||||||
* ---------------
|
* @handle: Target ACPI object.
|
||||||
* Callback for all 'system-level' device notifications (values 0x00-0x7F).
|
* @type: Notification type.
|
||||||
|
* @data: Ignored.
|
||||||
|
*
|
||||||
|
* This only handles notifications related to device hotplug.
|
||||||
*/
|
*/
|
||||||
static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
|
static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
|
||||||
{
|
{
|
||||||
struct acpi_device *adev;
|
struct acpi_device *adev;
|
||||||
u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
|
|
||||||
bool hotplug_event = false;
|
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ACPI_NOTIFY_BUS_CHECK:
|
case ACPI_NOTIFY_BUS_CHECK:
|
||||||
acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n");
|
acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n");
|
||||||
hotplug_event = true;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ACPI_NOTIFY_DEVICE_CHECK:
|
case ACPI_NOTIFY_DEVICE_CHECK:
|
||||||
acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n");
|
acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n");
|
||||||
hotplug_event = true;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ACPI_NOTIFY_DEVICE_WAKE:
|
case ACPI_NOTIFY_DEVICE_WAKE:
|
||||||
acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_WAKE event\n");
|
acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_WAKE event\n");
|
||||||
break;
|
return;
|
||||||
|
|
||||||
case ACPI_NOTIFY_EJECT_REQUEST:
|
case ACPI_NOTIFY_EJECT_REQUEST:
|
||||||
acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
|
acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
|
||||||
hotplug_event = true;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ACPI_NOTIFY_DEVICE_CHECK_LIGHT:
|
case ACPI_NOTIFY_DEVICE_CHECK_LIGHT:
|
||||||
acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK_LIGHT event\n");
|
acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK_LIGHT event\n");
|
||||||
/* TBD: Exactly what does 'light' mean? */
|
/* TBD: Exactly what does 'light' mean? */
|
||||||
break;
|
return;
|
||||||
|
|
||||||
case ACPI_NOTIFY_FREQUENCY_MISMATCH:
|
case ACPI_NOTIFY_FREQUENCY_MISMATCH:
|
||||||
acpi_handle_err(handle, "Device cannot be configured due "
|
acpi_handle_err(handle, "Device cannot be configured due "
|
||||||
"to a frequency mismatch\n");
|
"to a frequency mismatch\n");
|
||||||
break;
|
return;
|
||||||
|
|
||||||
case ACPI_NOTIFY_BUS_MODE_MISMATCH:
|
case ACPI_NOTIFY_BUS_MODE_MISMATCH:
|
||||||
acpi_handle_err(handle, "Device cannot be configured due "
|
acpi_handle_err(handle, "Device cannot be configured due "
|
||||||
"to a bus mode mismatch\n");
|
"to a bus mode mismatch\n");
|
||||||
break;
|
return;
|
||||||
|
|
||||||
case ACPI_NOTIFY_POWER_FAULT:
|
case ACPI_NOTIFY_POWER_FAULT:
|
||||||
acpi_handle_err(handle, "Device has suffered a power fault\n");
|
acpi_handle_err(handle, "Device has suffered a power fault\n");
|
||||||
break;
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
acpi_handle_debug(handle, "Unknown event type 0x%x\n", type);
|
acpi_handle_debug(handle, "Unknown event type 0x%x\n", type);
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
adev = acpi_get_acpi_dev(handle);
|
|
||||||
if (!adev)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
if (adev->dev.driver) {
|
|
||||||
struct acpi_driver *driver = to_acpi_driver(adev->dev.driver);
|
|
||||||
|
|
||||||
if (driver && driver->ops.notify &&
|
|
||||||
(driver->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS))
|
|
||||||
driver->ops.notify(adev, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hotplug_event) {
|
|
||||||
acpi_put_acpi_dev(adev);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ACPI_SUCCESS(acpi_hotplug_schedule(adev, type)))
|
adev = acpi_get_acpi_dev(handle);
|
||||||
|
|
||||||
|
if (adev && ACPI_SUCCESS(acpi_hotplug_schedule(adev, type)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
acpi_put_acpi_dev(adev);
|
acpi_put_acpi_dev(adev);
|
||||||
|
|
||||||
err:
|
acpi_evaluate_ost(handle, type, ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL);
|
||||||
acpi_evaluate_ost(handle, type, ost_code, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void acpi_notify_device(acpi_handle handle, u32 event, void *data)
|
static void acpi_notify_device(acpi_handle handle, u32 event, void *data)
|
||||||
@ -562,42 +544,51 @@ static u32 acpi_device_fixed_event(void *data)
|
|||||||
return ACPI_INTERRUPT_HANDLED;
|
return ACPI_INTERRUPT_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int acpi_device_install_notify_handler(struct acpi_device *device)
|
static int acpi_device_install_notify_handler(struct acpi_device *device,
|
||||||
|
struct acpi_driver *acpi_drv)
|
||||||
{
|
{
|
||||||
acpi_status status;
|
acpi_status status;
|
||||||
|
|
||||||
if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON)
|
if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON) {
|
||||||
status =
|
status =
|
||||||
acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
|
acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
|
||||||
acpi_device_fixed_event,
|
acpi_device_fixed_event,
|
||||||
device);
|
device);
|
||||||
else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON)
|
} else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON) {
|
||||||
status =
|
status =
|
||||||
acpi_install_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
|
acpi_install_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
|
||||||
acpi_device_fixed_event,
|
acpi_device_fixed_event,
|
||||||
device);
|
device);
|
||||||
else
|
} else {
|
||||||
status = acpi_install_notify_handler(device->handle,
|
u32 type = acpi_drv->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS ?
|
||||||
ACPI_DEVICE_NOTIFY,
|
ACPI_ALL_NOTIFY : ACPI_DEVICE_NOTIFY;
|
||||||
|
|
||||||
|
status = acpi_install_notify_handler(device->handle, type,
|
||||||
acpi_notify_device,
|
acpi_notify_device,
|
||||||
device);
|
device);
|
||||||
|
}
|
||||||
|
|
||||||
if (ACPI_FAILURE(status))
|
if (ACPI_FAILURE(status))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void acpi_device_remove_notify_handler(struct acpi_device *device)
|
static void acpi_device_remove_notify_handler(struct acpi_device *device,
|
||||||
|
struct acpi_driver *acpi_drv)
|
||||||
{
|
{
|
||||||
if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON)
|
if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON) {
|
||||||
acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
|
acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
|
||||||
acpi_device_fixed_event);
|
acpi_device_fixed_event);
|
||||||
else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON)
|
} else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON) {
|
||||||
acpi_remove_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
|
acpi_remove_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
|
||||||
acpi_device_fixed_event);
|
acpi_device_fixed_event);
|
||||||
else
|
} else {
|
||||||
acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
|
u32 type = acpi_drv->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS ?
|
||||||
|
ACPI_ALL_NOTIFY : ACPI_DEVICE_NOTIFY;
|
||||||
|
|
||||||
|
acpi_remove_notify_handler(device->handle, type,
|
||||||
acpi_notify_device);
|
acpi_notify_device);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle events targeting \_SB device (at present only graceful shutdown) */
|
/* Handle events targeting \_SB device (at present only graceful shutdown) */
|
||||||
@ -1039,7 +1030,7 @@ static int acpi_device_probe(struct device *dev)
|
|||||||
acpi_drv->name, acpi_dev->pnp.bus_id);
|
acpi_drv->name, acpi_dev->pnp.bus_id);
|
||||||
|
|
||||||
if (acpi_drv->ops.notify) {
|
if (acpi_drv->ops.notify) {
|
||||||
ret = acpi_device_install_notify_handler(acpi_dev);
|
ret = acpi_device_install_notify_handler(acpi_dev, acpi_drv);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
if (acpi_drv->ops.remove)
|
if (acpi_drv->ops.remove)
|
||||||
acpi_drv->ops.remove(acpi_dev);
|
acpi_drv->ops.remove(acpi_dev);
|
||||||
@ -1062,7 +1053,7 @@ static void acpi_device_remove(struct device *dev)
|
|||||||
struct acpi_driver *acpi_drv = to_acpi_driver(dev->driver);
|
struct acpi_driver *acpi_drv = to_acpi_driver(dev->driver);
|
||||||
|
|
||||||
if (acpi_drv->ops.notify)
|
if (acpi_drv->ops.notify)
|
||||||
acpi_device_remove_notify_handler(acpi_dev);
|
acpi_device_remove_notify_handler(acpi_dev, acpi_drv);
|
||||||
|
|
||||||
if (acpi_drv->ops.remove)
|
if (acpi_drv->ops.remove)
|
||||||
acpi_drv->ops.remove(acpi_dev);
|
acpi_drv->ops.remove(acpi_dev);
|
||||||
|
@ -474,12 +474,18 @@ int detect_cache_attributes(unsigned int cpu)
|
|||||||
|
|
||||||
populate_leaves:
|
populate_leaves:
|
||||||
/*
|
/*
|
||||||
* populate_cache_leaves() may completely setup the cache leaves and
|
* If LLC is valid the cache leaves were already populated so just go to
|
||||||
* shared_cpu_map or it may leave it partially setup.
|
* update the cpu map.
|
||||||
*/
|
*/
|
||||||
ret = populate_cache_leaves(cpu);
|
if (!last_level_cache_is_valid(cpu)) {
|
||||||
if (ret)
|
/*
|
||||||
goto free_ci;
|
* populate_cache_leaves() may completely setup the cache leaves and
|
||||||
|
* shared_cpu_map or it may leave it partially setup.
|
||||||
|
*/
|
||||||
|
ret = populate_cache_leaves(cpu);
|
||||||
|
if (ret)
|
||||||
|
goto free_ci;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For systems using DT for cache hierarchy, fw_token
|
* For systems using DT for cache hierarchy, fw_token
|
||||||
|
@ -1010,9 +1010,6 @@ static int loop_configure(struct loop_device *lo, fmode_t mode,
|
|||||||
/* This is safe, since we have a reference from open(). */
|
/* This is safe, since we have a reference from open(). */
|
||||||
__module_get(THIS_MODULE);
|
__module_get(THIS_MODULE);
|
||||||
|
|
||||||
/* suppress uevents while reconfiguring the device */
|
|
||||||
dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 1);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we don't hold exclusive handle for the device, upgrade to it
|
* If we don't hold exclusive handle for the device, upgrade to it
|
||||||
* here to avoid changing device under exclusive owner.
|
* here to avoid changing device under exclusive owner.
|
||||||
@ -1067,6 +1064,9 @@ static int loop_configure(struct loop_device *lo, fmode_t mode,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* suppress uevents while reconfiguring the device */
|
||||||
|
dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 1);
|
||||||
|
|
||||||
disk_force_media_change(lo->lo_disk, DISK_EVENT_MEDIA_CHANGE);
|
disk_force_media_change(lo->lo_disk, DISK_EVENT_MEDIA_CHANGE);
|
||||||
set_disk_ro(lo->lo_disk, (lo->lo_flags & LO_FLAGS_READ_ONLY) != 0);
|
set_disk_ro(lo->lo_disk, (lo->lo_flags & LO_FLAGS_READ_ONLY) != 0);
|
||||||
|
|
||||||
@ -1109,17 +1109,17 @@ static int loop_configure(struct loop_device *lo, fmode_t mode,
|
|||||||
if (partscan)
|
if (partscan)
|
||||||
clear_bit(GD_SUPPRESS_PART_SCAN, &lo->lo_disk->state);
|
clear_bit(GD_SUPPRESS_PART_SCAN, &lo->lo_disk->state);
|
||||||
|
|
||||||
|
/* enable and uncork uevent now that we are done */
|
||||||
|
dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 0);
|
||||||
|
|
||||||
loop_global_unlock(lo, is_loop);
|
loop_global_unlock(lo, is_loop);
|
||||||
if (partscan)
|
if (partscan)
|
||||||
loop_reread_partitions(lo);
|
loop_reread_partitions(lo);
|
||||||
|
|
||||||
if (!(mode & FMODE_EXCL))
|
if (!(mode & FMODE_EXCL))
|
||||||
bd_abort_claiming(bdev, loop_configure);
|
bd_abort_claiming(bdev, loop_configure);
|
||||||
|
|
||||||
error = 0;
|
return 0;
|
||||||
done:
|
|
||||||
/* enable and uncork uevent now that we are done */
|
|
||||||
dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 0);
|
|
||||||
return error;
|
|
||||||
|
|
||||||
out_unlock:
|
out_unlock:
|
||||||
loop_global_unlock(lo, is_loop);
|
loop_global_unlock(lo, is_loop);
|
||||||
@ -1130,7 +1130,7 @@ out_putf:
|
|||||||
fput(file);
|
fput(file);
|
||||||
/* This is safe: open() is still holding a reference. */
|
/* This is safe: open() is still holding a reference. */
|
||||||
module_put(THIS_MODULE);
|
module_put(THIS_MODULE);
|
||||||
goto done;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __loop_clr_fd(struct loop_device *lo, bool release)
|
static void __loop_clr_fd(struct loop_device *lo, bool release)
|
||||||
|
@ -232,7 +232,7 @@ static int intel_dp_dsc_mst_compute_link_config(struct intel_encoder *encoder,
|
|||||||
return slots;
|
return slots;
|
||||||
}
|
}
|
||||||
|
|
||||||
intel_link_compute_m_n(crtc_state->pipe_bpp,
|
intel_link_compute_m_n(crtc_state->dsc.compressed_bpp,
|
||||||
crtc_state->lane_count,
|
crtc_state->lane_count,
|
||||||
adjusted_mode->crtc_clock,
|
adjusted_mode->crtc_clock,
|
||||||
crtc_state->port_clock,
|
crtc_state->port_clock,
|
||||||
|
@ -1067,11 +1067,12 @@ static vm_fault_t vm_fault_ttm(struct vm_fault *vmf)
|
|||||||
.interruptible = true,
|
.interruptible = true,
|
||||||
.no_wait_gpu = true, /* should be idle already */
|
.no_wait_gpu = true, /* should be idle already */
|
||||||
};
|
};
|
||||||
|
int err;
|
||||||
|
|
||||||
GEM_BUG_ON(!bo->ttm || !(bo->ttm->page_flags & TTM_TT_FLAG_SWAPPED));
|
GEM_BUG_ON(!bo->ttm || !(bo->ttm->page_flags & TTM_TT_FLAG_SWAPPED));
|
||||||
|
|
||||||
ret = ttm_bo_validate(bo, i915_ttm_sys_placement(), &ctx);
|
err = ttm_bo_validate(bo, i915_ttm_sys_placement(), &ctx);
|
||||||
if (ret) {
|
if (err) {
|
||||||
dma_resv_unlock(bo->base.resv);
|
dma_resv_unlock(bo->base.resv);
|
||||||
return VM_FAULT_SIGBUS;
|
return VM_FAULT_SIGBUS;
|
||||||
}
|
}
|
||||||
|
@ -2018,6 +2018,8 @@ process_csb(struct intel_engine_cs *engine, struct i915_request **inactive)
|
|||||||
* inspecting the queue to see if we need to resumbit.
|
* inspecting the queue to see if we need to resumbit.
|
||||||
*/
|
*/
|
||||||
if (*prev != *execlists->active) { /* elide lite-restores */
|
if (*prev != *execlists->active) { /* elide lite-restores */
|
||||||
|
struct intel_context *prev_ce = NULL, *active_ce = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note the inherent discrepancy between the HW runtime,
|
* Note the inherent discrepancy between the HW runtime,
|
||||||
* recorded as part of the context switch, and the CPU
|
* recorded as part of the context switch, and the CPU
|
||||||
@ -2029,9 +2031,15 @@ process_csb(struct intel_engine_cs *engine, struct i915_request **inactive)
|
|||||||
* and correct overselves later when updating from HW.
|
* and correct overselves later when updating from HW.
|
||||||
*/
|
*/
|
||||||
if (*prev)
|
if (*prev)
|
||||||
lrc_runtime_stop((*prev)->context);
|
prev_ce = (*prev)->context;
|
||||||
if (*execlists->active)
|
if (*execlists->active)
|
||||||
lrc_runtime_start((*execlists->active)->context);
|
active_ce = (*execlists->active)->context;
|
||||||
|
if (prev_ce != active_ce) {
|
||||||
|
if (prev_ce)
|
||||||
|
lrc_runtime_stop(prev_ce);
|
||||||
|
if (active_ce)
|
||||||
|
lrc_runtime_start(active_ce);
|
||||||
|
}
|
||||||
new_timeslice(execlists);
|
new_timeslice(execlists);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,6 +235,13 @@ static void delayed_huc_load_fini(struct intel_huc *huc)
|
|||||||
i915_sw_fence_fini(&huc->delayed_load.fence);
|
i915_sw_fence_fini(&huc->delayed_load.fence);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int intel_huc_sanitize(struct intel_huc *huc)
|
||||||
|
{
|
||||||
|
delayed_huc_load_complete(huc);
|
||||||
|
intel_uc_fw_sanitize(&huc->fw);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static bool vcs_supported(struct intel_gt *gt)
|
static bool vcs_supported(struct intel_gt *gt)
|
||||||
{
|
{
|
||||||
intel_engine_mask_t mask = gt->info.engine_mask;
|
intel_engine_mask_t mask = gt->info.engine_mask;
|
||||||
|
@ -41,6 +41,7 @@ struct intel_huc {
|
|||||||
} delayed_load;
|
} delayed_load;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int intel_huc_sanitize(struct intel_huc *huc);
|
||||||
void intel_huc_init_early(struct intel_huc *huc);
|
void intel_huc_init_early(struct intel_huc *huc);
|
||||||
int intel_huc_init(struct intel_huc *huc);
|
int intel_huc_init(struct intel_huc *huc);
|
||||||
void intel_huc_fini(struct intel_huc *huc);
|
void intel_huc_fini(struct intel_huc *huc);
|
||||||
@ -54,12 +55,6 @@ bool intel_huc_is_authenticated(struct intel_huc *huc);
|
|||||||
void intel_huc_register_gsc_notifier(struct intel_huc *huc, struct bus_type *bus);
|
void intel_huc_register_gsc_notifier(struct intel_huc *huc, struct bus_type *bus);
|
||||||
void intel_huc_unregister_gsc_notifier(struct intel_huc *huc, struct bus_type *bus);
|
void intel_huc_unregister_gsc_notifier(struct intel_huc *huc, struct bus_type *bus);
|
||||||
|
|
||||||
static inline int intel_huc_sanitize(struct intel_huc *huc)
|
|
||||||
{
|
|
||||||
intel_uc_fw_sanitize(&huc->fw);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool intel_huc_is_supported(struct intel_huc *huc)
|
static inline bool intel_huc_is_supported(struct intel_huc *huc)
|
||||||
{
|
{
|
||||||
return intel_uc_fw_is_supported(&huc->fw);
|
return intel_uc_fw_is_supported(&huc->fw);
|
||||||
|
@ -4638,13 +4638,13 @@ int i915_perf_add_config_ioctl(struct drm_device *dev, void *data,
|
|||||||
err = oa_config->id;
|
err = oa_config->id;
|
||||||
goto sysfs_err;
|
goto sysfs_err;
|
||||||
}
|
}
|
||||||
|
id = oa_config->id;
|
||||||
mutex_unlock(&perf->metrics_lock);
|
|
||||||
|
|
||||||
drm_dbg(&perf->i915->drm,
|
drm_dbg(&perf->i915->drm,
|
||||||
"Added config %s id=%i\n", oa_config->uuid, oa_config->id);
|
"Added config %s id=%i\n", oa_config->uuid, oa_config->id);
|
||||||
|
mutex_unlock(&perf->metrics_lock);
|
||||||
|
|
||||||
return oa_config->id;
|
return id;
|
||||||
|
|
||||||
sysfs_err:
|
sysfs_err:
|
||||||
mutex_unlock(&perf->metrics_lock);
|
mutex_unlock(&perf->metrics_lock);
|
||||||
|
@ -363,6 +363,35 @@ nv50_outp_atomic_check_view(struct drm_encoder *encoder,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
nv50_outp_atomic_fix_depth(struct drm_encoder *encoder, struct drm_crtc_state *crtc_state)
|
||||||
|
{
|
||||||
|
struct nv50_head_atom *asyh = nv50_head_atom(crtc_state);
|
||||||
|
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
|
||||||
|
struct drm_display_mode *mode = &asyh->state.adjusted_mode;
|
||||||
|
unsigned int max_rate, mode_rate;
|
||||||
|
|
||||||
|
switch (nv_encoder->dcb->type) {
|
||||||
|
case DCB_OUTPUT_DP:
|
||||||
|
max_rate = nv_encoder->dp.link_nr * nv_encoder->dp.link_bw;
|
||||||
|
|
||||||
|
/* we don't support more than 10 anyway */
|
||||||
|
asyh->or.bpc = min_t(u8, asyh->or.bpc, 10);
|
||||||
|
|
||||||
|
/* reduce the bpc until it works out */
|
||||||
|
while (asyh->or.bpc > 6) {
|
||||||
|
mode_rate = DIV_ROUND_UP(mode->clock * asyh->or.bpc * 3, 8);
|
||||||
|
if (mode_rate <= max_rate)
|
||||||
|
break;
|
||||||
|
|
||||||
|
asyh->or.bpc -= 2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
nv50_outp_atomic_check(struct drm_encoder *encoder,
|
nv50_outp_atomic_check(struct drm_encoder *encoder,
|
||||||
struct drm_crtc_state *crtc_state,
|
struct drm_crtc_state *crtc_state,
|
||||||
@ -381,6 +410,9 @@ nv50_outp_atomic_check(struct drm_encoder *encoder,
|
|||||||
if (crtc_state->mode_changed || crtc_state->connectors_changed)
|
if (crtc_state->mode_changed || crtc_state->connectors_changed)
|
||||||
asyh->or.bpc = connector->display_info.bpc;
|
asyh->or.bpc = connector->display_info.bpc;
|
||||||
|
|
||||||
|
/* We might have to reduce the bpc */
|
||||||
|
nv50_outp_atomic_fix_depth(encoder, crtc_state);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,8 +263,6 @@ nouveau_dp_irq(struct work_struct *work)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* TODO:
|
/* TODO:
|
||||||
* - Use the minimum possible BPC here, once we add support for the max bpc
|
|
||||||
* property.
|
|
||||||
* - Validate against the DP caps advertised by the GPU (we don't check these
|
* - Validate against the DP caps advertised by the GPU (we don't check these
|
||||||
* yet)
|
* yet)
|
||||||
*/
|
*/
|
||||||
@ -276,7 +274,11 @@ nv50_dp_mode_valid(struct drm_connector *connector,
|
|||||||
{
|
{
|
||||||
const unsigned int min_clock = 25000;
|
const unsigned int min_clock = 25000;
|
||||||
unsigned int max_rate, mode_rate, ds_max_dotclock, clock = mode->clock;
|
unsigned int max_rate, mode_rate, ds_max_dotclock, clock = mode->clock;
|
||||||
const u8 bpp = connector->display_info.bpc * 3;
|
/* Check with the minmum bpc always, so we can advertise better modes.
|
||||||
|
* In particlar not doing this causes modes to be dropped on HDR
|
||||||
|
* displays as we might check with a bpc of 16 even.
|
||||||
|
*/
|
||||||
|
const u8 bpp = 6 * 3;
|
||||||
|
|
||||||
if (mode->flags & DRM_MODE_FLAG_INTERLACE && !outp->caps.dp_interlace)
|
if (mode->flags & DRM_MODE_FLAG_INTERLACE && !outp->caps.dp_interlace)
|
||||||
return MODE_NO_INTERLACE;
|
return MODE_NO_INTERLACE;
|
||||||
|
@ -504,6 +504,7 @@ static int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as,
|
|||||||
if (IS_ERR(pages[i])) {
|
if (IS_ERR(pages[i])) {
|
||||||
mutex_unlock(&bo->base.pages_lock);
|
mutex_unlock(&bo->base.pages_lock);
|
||||||
ret = PTR_ERR(pages[i]);
|
ret = PTR_ERR(pages[i]);
|
||||||
|
pages[i] = NULL;
|
||||||
goto err_pages;
|
goto err_pages;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -409,6 +409,10 @@ void vmbus_disconnect(void)
|
|||||||
*/
|
*/
|
||||||
struct vmbus_channel *relid2channel(u32 relid)
|
struct vmbus_channel *relid2channel(u32 relid)
|
||||||
{
|
{
|
||||||
|
if (vmbus_connection.channels == NULL) {
|
||||||
|
pr_warn_once("relid2channel: relid=%d: No channels mapped!\n", relid);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
if (WARN_ON(relid >= MAX_CHANNEL_RELIDS))
|
if (WARN_ON(relid >= MAX_CHANNEL_RELIDS))
|
||||||
return NULL;
|
return NULL;
|
||||||
return READ_ONCE(vmbus_connection.channels[relid]);
|
return READ_ONCE(vmbus_connection.channels[relid]);
|
||||||
|
@ -781,9 +781,6 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d
|
|||||||
input_report_key(dev, BTN_C, data[8]);
|
input_report_key(dev, BTN_C, data[8]);
|
||||||
input_report_key(dev, BTN_Z, data[9]);
|
input_report_key(dev, BTN_Z, data[9]);
|
||||||
|
|
||||||
/* Profile button has a value of 0-3, so it is reported as an axis */
|
|
||||||
if (xpad->mapping & MAP_PROFILE_BUTTON)
|
|
||||||
input_report_abs(dev, ABS_PROFILE, data[34]);
|
|
||||||
|
|
||||||
input_sync(dev);
|
input_sync(dev);
|
||||||
}
|
}
|
||||||
@ -1061,6 +1058,10 @@ static void xpadone_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char
|
|||||||
(__u16) le16_to_cpup((__le16 *)(data + 8)));
|
(__u16) le16_to_cpup((__le16 *)(data + 8)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Profile button has a value of 0-3, so it is reported as an axis */
|
||||||
|
if (xpad->mapping & MAP_PROFILE_BUTTON)
|
||||||
|
input_report_abs(dev, ABS_PROFILE, data[34]);
|
||||||
|
|
||||||
/* paddle handling */
|
/* paddle handling */
|
||||||
/* based on SDL's SDL_hidapi_xboxone.c */
|
/* based on SDL's SDL_hidapi_xboxone.c */
|
||||||
if (xpad->mapping & MAP_PADDLES) {
|
if (xpad->mapping & MAP_PADDLES) {
|
||||||
|
@ -852,8 +852,8 @@ static void alps_process_packet_v6(struct psmouse *psmouse)
|
|||||||
x = y = z = 0;
|
x = y = z = 0;
|
||||||
|
|
||||||
/* Divide 4 since trackpoint's speed is too fast */
|
/* Divide 4 since trackpoint's speed is too fast */
|
||||||
input_report_rel(dev2, REL_X, (char)x / 4);
|
input_report_rel(dev2, REL_X, (s8)x / 4);
|
||||||
input_report_rel(dev2, REL_Y, -((char)y / 4));
|
input_report_rel(dev2, REL_Y, -((s8)y / 4));
|
||||||
|
|
||||||
psmouse_report_standard_buttons(dev2, packet[3]);
|
psmouse_report_standard_buttons(dev2, packet[3]);
|
||||||
|
|
||||||
@ -1104,8 +1104,8 @@ static void alps_process_trackstick_packet_v7(struct psmouse *psmouse)
|
|||||||
((packet[3] & 0x20) << 1);
|
((packet[3] & 0x20) << 1);
|
||||||
z = (packet[5] & 0x3f) | ((packet[3] & 0x80) >> 1);
|
z = (packet[5] & 0x3f) | ((packet[3] & 0x80) >> 1);
|
||||||
|
|
||||||
input_report_rel(dev2, REL_X, (char)x);
|
input_report_rel(dev2, REL_X, (s8)x);
|
||||||
input_report_rel(dev2, REL_Y, -((char)y));
|
input_report_rel(dev2, REL_Y, -((s8)y));
|
||||||
input_report_abs(dev2, ABS_PRESSURE, z);
|
input_report_abs(dev2, ABS_PRESSURE, z);
|
||||||
|
|
||||||
psmouse_report_standard_buttons(dev2, packet[1]);
|
psmouse_report_standard_buttons(dev2, packet[1]);
|
||||||
@ -2294,20 +2294,20 @@ static int alps_get_v3_v7_resolution(struct psmouse *psmouse, int reg_pitch)
|
|||||||
if (reg < 0)
|
if (reg < 0)
|
||||||
return reg;
|
return reg;
|
||||||
|
|
||||||
x_pitch = (char)(reg << 4) >> 4; /* sign extend lower 4 bits */
|
x_pitch = (s8)(reg << 4) >> 4; /* sign extend lower 4 bits */
|
||||||
x_pitch = 50 + 2 * x_pitch; /* In 0.1 mm units */
|
x_pitch = 50 + 2 * x_pitch; /* In 0.1 mm units */
|
||||||
|
|
||||||
y_pitch = (char)reg >> 4; /* sign extend upper 4 bits */
|
y_pitch = (s8)reg >> 4; /* sign extend upper 4 bits */
|
||||||
y_pitch = 36 + 2 * y_pitch; /* In 0.1 mm units */
|
y_pitch = 36 + 2 * y_pitch; /* In 0.1 mm units */
|
||||||
|
|
||||||
reg = alps_command_mode_read_reg(psmouse, reg_pitch + 1);
|
reg = alps_command_mode_read_reg(psmouse, reg_pitch + 1);
|
||||||
if (reg < 0)
|
if (reg < 0)
|
||||||
return reg;
|
return reg;
|
||||||
|
|
||||||
x_electrode = (char)(reg << 4) >> 4; /* sign extend lower 4 bits */
|
x_electrode = (s8)(reg << 4) >> 4; /* sign extend lower 4 bits */
|
||||||
x_electrode = 17 + x_electrode;
|
x_electrode = 17 + x_electrode;
|
||||||
|
|
||||||
y_electrode = (char)reg >> 4; /* sign extend upper 4 bits */
|
y_electrode = (s8)reg >> 4; /* sign extend upper 4 bits */
|
||||||
y_electrode = 13 + y_electrode;
|
y_electrode = 13 + y_electrode;
|
||||||
|
|
||||||
x_phys = x_pitch * (x_electrode - 1); /* In 0.1 mm units */
|
x_phys = x_pitch * (x_electrode - 1); /* In 0.1 mm units */
|
||||||
|
@ -202,8 +202,8 @@ static void focaltech_process_rel_packet(struct psmouse *psmouse,
|
|||||||
state->pressed = packet[0] >> 7;
|
state->pressed = packet[0] >> 7;
|
||||||
finger1 = ((packet[0] >> 4) & 0x7) - 1;
|
finger1 = ((packet[0] >> 4) & 0x7) - 1;
|
||||||
if (finger1 < FOC_MAX_FINGERS) {
|
if (finger1 < FOC_MAX_FINGERS) {
|
||||||
state->fingers[finger1].x += (char)packet[1];
|
state->fingers[finger1].x += (s8)packet[1];
|
||||||
state->fingers[finger1].y += (char)packet[2];
|
state->fingers[finger1].y += (s8)packet[2];
|
||||||
} else {
|
} else {
|
||||||
psmouse_err(psmouse, "First finger in rel packet invalid: %d\n",
|
psmouse_err(psmouse, "First finger in rel packet invalid: %d\n",
|
||||||
finger1);
|
finger1);
|
||||||
@ -218,8 +218,8 @@ static void focaltech_process_rel_packet(struct psmouse *psmouse,
|
|||||||
*/
|
*/
|
||||||
finger2 = ((packet[3] >> 4) & 0x7) - 1;
|
finger2 = ((packet[3] >> 4) & 0x7) - 1;
|
||||||
if (finger2 < FOC_MAX_FINGERS) {
|
if (finger2 < FOC_MAX_FINGERS) {
|
||||||
state->fingers[finger2].x += (char)packet[4];
|
state->fingers[finger2].x += (s8)packet[4];
|
||||||
state->fingers[finger2].y += (char)packet[5];
|
state->fingers[finger2].y += (s8)packet[5];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -610,6 +610,14 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = {
|
|||||||
},
|
},
|
||||||
.driver_data = (void *)(SERIO_QUIRK_NOMUX)
|
.driver_data = (void *)(SERIO_QUIRK_NOMUX)
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
/* Fujitsu Lifebook A574/H */
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
|
||||||
|
DMI_MATCH(DMI_PRODUCT_NAME, "FMVA0501PZ"),
|
||||||
|
},
|
||||||
|
.driver_data = (void *)(SERIO_QUIRK_NOMUX)
|
||||||
|
},
|
||||||
{
|
{
|
||||||
/* Gigabyte M912 */
|
/* Gigabyte M912 */
|
||||||
.matches = {
|
.matches = {
|
||||||
@ -1116,6 +1124,20 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = {
|
|||||||
.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
|
.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
|
||||||
SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
|
SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Setting SERIO_QUIRK_NOMUX or SERIO_QUIRK_RESET_ALWAYS makes
|
||||||
|
* the keyboard very laggy for ~5 seconds after boot and
|
||||||
|
* sometimes also after resume.
|
||||||
|
* However both are required for the keyboard to not fail
|
||||||
|
* completely sometimes after boot or resume.
|
||||||
|
*/
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_BOARD_NAME, "N150CU"),
|
||||||
|
},
|
||||||
|
.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
|
||||||
|
SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.matches = {
|
.matches = {
|
||||||
DMI_MATCH(DMI_BOARD_NAME, "NH5xAx"),
|
DMI_MATCH(DMI_BOARD_NAME, "NH5xAx"),
|
||||||
@ -1123,6 +1145,20 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = {
|
|||||||
.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
|
.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
|
||||||
SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
|
SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Setting SERIO_QUIRK_NOMUX or SERIO_QUIRK_RESET_ALWAYS makes
|
||||||
|
* the keyboard very laggy for ~5 seconds after boot and
|
||||||
|
* sometimes also after resume.
|
||||||
|
* However both are required for the keyboard to not fail
|
||||||
|
* completely sometimes after boot or resume.
|
||||||
|
*/
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_BOARD_NAME, "NHxxRZQ"),
|
||||||
|
},
|
||||||
|
.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
|
||||||
|
SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.matches = {
|
.matches = {
|
||||||
DMI_MATCH(DMI_BOARD_NAME, "NL5xRU"),
|
DMI_MATCH(DMI_BOARD_NAME, "NL5xRU"),
|
||||||
|
@ -124,10 +124,18 @@ static const unsigned long goodix_irq_flags[] = {
|
|||||||
static const struct dmi_system_id nine_bytes_report[] = {
|
static const struct dmi_system_id nine_bytes_report[] = {
|
||||||
#if defined(CONFIG_DMI) && defined(CONFIG_X86)
|
#if defined(CONFIG_DMI) && defined(CONFIG_X86)
|
||||||
{
|
{
|
||||||
.ident = "Lenovo YogaBook",
|
/* Lenovo Yoga Book X90F / X90L */
|
||||||
/* YB1-X91L/F and YB1-X90L/F */
|
|
||||||
.matches = {
|
.matches = {
|
||||||
DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X9")
|
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
|
||||||
|
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"),
|
||||||
|
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "YETI-11"),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* Lenovo Yoga Book X91F / X91L */
|
||||||
|
.matches = {
|
||||||
|
/* Non exact match to match F + L versions */
|
||||||
|
DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X91"),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
|
@ -1415,23 +1415,26 @@ static struct iommu_device *exynos_iommu_probe_device(struct device *dev)
|
|||||||
return &data->iommu;
|
return &data->iommu;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void exynos_iommu_release_device(struct device *dev)
|
static void exynos_iommu_set_platform_dma(struct device *dev)
|
||||||
{
|
{
|
||||||
struct exynos_iommu_owner *owner = dev_iommu_priv_get(dev);
|
struct exynos_iommu_owner *owner = dev_iommu_priv_get(dev);
|
||||||
struct sysmmu_drvdata *data;
|
|
||||||
|
|
||||||
if (owner->domain) {
|
if (owner->domain) {
|
||||||
struct iommu_group *group = iommu_group_get(dev);
|
struct iommu_group *group = iommu_group_get(dev);
|
||||||
|
|
||||||
if (group) {
|
if (group) {
|
||||||
#ifndef CONFIG_ARM
|
|
||||||
WARN_ON(owner->domain !=
|
|
||||||
iommu_group_default_domain(group));
|
|
||||||
#endif
|
|
||||||
exynos_iommu_detach_device(owner->domain, dev);
|
exynos_iommu_detach_device(owner->domain, dev);
|
||||||
iommu_group_put(group);
|
iommu_group_put(group);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void exynos_iommu_release_device(struct device *dev)
|
||||||
|
{
|
||||||
|
struct exynos_iommu_owner *owner = dev_iommu_priv_get(dev);
|
||||||
|
struct sysmmu_drvdata *data;
|
||||||
|
|
||||||
|
exynos_iommu_set_platform_dma(dev);
|
||||||
|
|
||||||
list_for_each_entry(data, &owner->controllers, owner_node)
|
list_for_each_entry(data, &owner->controllers, owner_node)
|
||||||
device_link_del(data->link);
|
device_link_del(data->link);
|
||||||
@ -1479,7 +1482,7 @@ static const struct iommu_ops exynos_iommu_ops = {
|
|||||||
.domain_alloc = exynos_iommu_domain_alloc,
|
.domain_alloc = exynos_iommu_domain_alloc,
|
||||||
.device_group = generic_device_group,
|
.device_group = generic_device_group,
|
||||||
#ifdef CONFIG_ARM
|
#ifdef CONFIG_ARM
|
||||||
.set_platform_dma_ops = exynos_iommu_release_device,
|
.set_platform_dma_ops = exynos_iommu_set_platform_dma,
|
||||||
#endif
|
#endif
|
||||||
.probe_device = exynos_iommu_probe_device,
|
.probe_device = exynos_iommu_probe_device,
|
||||||
.release_device = exynos_iommu_release_device,
|
.release_device = exynos_iommu_release_device,
|
||||||
|
@ -1071,7 +1071,8 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
if (cap_sagaw(iommu->cap) == 0) {
|
if (!cap_sagaw(iommu->cap) &&
|
||||||
|
(!ecap_smts(iommu->ecap) || ecap_slts(iommu->ecap))) {
|
||||||
pr_info("%s: No supported address widths. Not attempting DMA translation.\n",
|
pr_info("%s: No supported address widths. Not attempting DMA translation.\n",
|
||||||
iommu->name);
|
iommu->name);
|
||||||
drhd->ignored = 1;
|
drhd->ignored = 1;
|
||||||
|
@ -641,6 +641,8 @@ struct iommu_pmu {
|
|||||||
DECLARE_BITMAP(used_mask, IOMMU_PMU_IDX_MAX);
|
DECLARE_BITMAP(used_mask, IOMMU_PMU_IDX_MAX);
|
||||||
struct perf_event *event_list[IOMMU_PMU_IDX_MAX];
|
struct perf_event *event_list[IOMMU_PMU_IDX_MAX];
|
||||||
unsigned char irq_name[16];
|
unsigned char irq_name[16];
|
||||||
|
struct hlist_node cpuhp_node;
|
||||||
|
int cpu;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define IOMMU_IRQ_ID_OFFSET_PRQ (DMAR_UNITS_SUPPORTED)
|
#define IOMMU_IRQ_ID_OFFSET_PRQ (DMAR_UNITS_SUPPORTED)
|
||||||
|
@ -311,14 +311,12 @@ static int set_ioapic_sid(struct irte *irte, int apic)
|
|||||||
if (!irte)
|
if (!irte)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
down_read(&dmar_global_lock);
|
|
||||||
for (i = 0; i < MAX_IO_APICS; i++) {
|
for (i = 0; i < MAX_IO_APICS; i++) {
|
||||||
if (ir_ioapic[i].iommu && ir_ioapic[i].id == apic) {
|
if (ir_ioapic[i].iommu && ir_ioapic[i].id == apic) {
|
||||||
sid = (ir_ioapic[i].bus << 8) | ir_ioapic[i].devfn;
|
sid = (ir_ioapic[i].bus << 8) | ir_ioapic[i].devfn;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
up_read(&dmar_global_lock);
|
|
||||||
|
|
||||||
if (sid == 0) {
|
if (sid == 0) {
|
||||||
pr_warn("Failed to set source-id of IOAPIC (%d)\n", apic);
|
pr_warn("Failed to set source-id of IOAPIC (%d)\n", apic);
|
||||||
@ -338,14 +336,12 @@ static int set_hpet_sid(struct irte *irte, u8 id)
|
|||||||
if (!irte)
|
if (!irte)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
down_read(&dmar_global_lock);
|
|
||||||
for (i = 0; i < MAX_HPET_TBS; i++) {
|
for (i = 0; i < MAX_HPET_TBS; i++) {
|
||||||
if (ir_hpet[i].iommu && ir_hpet[i].id == id) {
|
if (ir_hpet[i].iommu && ir_hpet[i].id == id) {
|
||||||
sid = (ir_hpet[i].bus << 8) | ir_hpet[i].devfn;
|
sid = (ir_hpet[i].bus << 8) | ir_hpet[i].devfn;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
up_read(&dmar_global_lock);
|
|
||||||
|
|
||||||
if (sid == 0) {
|
if (sid == 0) {
|
||||||
pr_warn("Failed to set source-id of HPET block (%d)\n", id);
|
pr_warn("Failed to set source-id of HPET block (%d)\n", id);
|
||||||
@ -1339,9 +1335,7 @@ static int intel_irq_remapping_alloc(struct irq_domain *domain,
|
|||||||
if (!data)
|
if (!data)
|
||||||
goto out_free_parent;
|
goto out_free_parent;
|
||||||
|
|
||||||
down_read(&dmar_global_lock);
|
|
||||||
index = alloc_irte(iommu, &data->irq_2_iommu, nr_irqs);
|
index = alloc_irte(iommu, &data->irq_2_iommu, nr_irqs);
|
||||||
up_read(&dmar_global_lock);
|
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
pr_warn("Failed to allocate IRTE\n");
|
pr_warn("Failed to allocate IRTE\n");
|
||||||
kfree(data);
|
kfree(data);
|
||||||
|
@ -773,19 +773,34 @@ static void iommu_pmu_unset_interrupt(struct intel_iommu *iommu)
|
|||||||
iommu->perf_irq = 0;
|
iommu->perf_irq = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iommu_pmu_cpu_online(unsigned int cpu)
|
static int iommu_pmu_cpu_online(unsigned int cpu, struct hlist_node *node)
|
||||||
{
|
{
|
||||||
|
struct iommu_pmu *iommu_pmu = hlist_entry_safe(node, typeof(*iommu_pmu), cpuhp_node);
|
||||||
|
|
||||||
if (cpumask_empty(&iommu_pmu_cpu_mask))
|
if (cpumask_empty(&iommu_pmu_cpu_mask))
|
||||||
cpumask_set_cpu(cpu, &iommu_pmu_cpu_mask);
|
cpumask_set_cpu(cpu, &iommu_pmu_cpu_mask);
|
||||||
|
|
||||||
|
if (cpumask_test_cpu(cpu, &iommu_pmu_cpu_mask))
|
||||||
|
iommu_pmu->cpu = cpu;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iommu_pmu_cpu_offline(unsigned int cpu)
|
static int iommu_pmu_cpu_offline(unsigned int cpu, struct hlist_node *node)
|
||||||
{
|
{
|
||||||
struct dmar_drhd_unit *drhd;
|
struct iommu_pmu *iommu_pmu = hlist_entry_safe(node, typeof(*iommu_pmu), cpuhp_node);
|
||||||
struct intel_iommu *iommu;
|
int target = cpumask_first(&iommu_pmu_cpu_mask);
|
||||||
int target;
|
|
||||||
|
/*
|
||||||
|
* The iommu_pmu_cpu_mask has been updated when offline the CPU
|
||||||
|
* for the first iommu_pmu. Migrate the other iommu_pmu to the
|
||||||
|
* new target.
|
||||||
|
*/
|
||||||
|
if (target < nr_cpu_ids && target != iommu_pmu->cpu) {
|
||||||
|
perf_pmu_migrate_context(&iommu_pmu->pmu, cpu, target);
|
||||||
|
iommu_pmu->cpu = target;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!cpumask_test_and_clear_cpu(cpu, &iommu_pmu_cpu_mask))
|
if (!cpumask_test_and_clear_cpu(cpu, &iommu_pmu_cpu_mask))
|
||||||
return 0;
|
return 0;
|
||||||
@ -795,45 +810,50 @@ static int iommu_pmu_cpu_offline(unsigned int cpu)
|
|||||||
if (target < nr_cpu_ids)
|
if (target < nr_cpu_ids)
|
||||||
cpumask_set_cpu(target, &iommu_pmu_cpu_mask);
|
cpumask_set_cpu(target, &iommu_pmu_cpu_mask);
|
||||||
else
|
else
|
||||||
target = -1;
|
return 0;
|
||||||
|
|
||||||
rcu_read_lock();
|
perf_pmu_migrate_context(&iommu_pmu->pmu, cpu, target);
|
||||||
|
iommu_pmu->cpu = target;
|
||||||
for_each_iommu(iommu, drhd) {
|
|
||||||
if (!iommu->pmu)
|
|
||||||
continue;
|
|
||||||
perf_pmu_migrate_context(&iommu->pmu->pmu, cpu, target);
|
|
||||||
}
|
|
||||||
rcu_read_unlock();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nr_iommu_pmu;
|
static int nr_iommu_pmu;
|
||||||
|
static enum cpuhp_state iommu_cpuhp_slot;
|
||||||
|
|
||||||
static int iommu_pmu_cpuhp_setup(struct iommu_pmu *iommu_pmu)
|
static int iommu_pmu_cpuhp_setup(struct iommu_pmu *iommu_pmu)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (nr_iommu_pmu++)
|
if (!nr_iommu_pmu) {
|
||||||
return 0;
|
ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN,
|
||||||
|
"driver/iommu/intel/perfmon:online",
|
||||||
|
iommu_pmu_cpu_online,
|
||||||
|
iommu_pmu_cpu_offline);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
iommu_cpuhp_slot = ret;
|
||||||
|
}
|
||||||
|
|
||||||
ret = cpuhp_setup_state(CPUHP_AP_PERF_X86_IOMMU_PERF_ONLINE,
|
ret = cpuhp_state_add_instance(iommu_cpuhp_slot, &iommu_pmu->cpuhp_node);
|
||||||
"driver/iommu/intel/perfmon:online",
|
if (ret) {
|
||||||
iommu_pmu_cpu_online,
|
if (!nr_iommu_pmu)
|
||||||
iommu_pmu_cpu_offline);
|
cpuhp_remove_multi_state(iommu_cpuhp_slot);
|
||||||
if (ret)
|
return ret;
|
||||||
nr_iommu_pmu = 0;
|
}
|
||||||
|
nr_iommu_pmu++;
|
||||||
|
|
||||||
return ret;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void iommu_pmu_cpuhp_free(struct iommu_pmu *iommu_pmu)
|
static void iommu_pmu_cpuhp_free(struct iommu_pmu *iommu_pmu)
|
||||||
{
|
{
|
||||||
|
cpuhp_state_remove_instance(iommu_cpuhp_slot, &iommu_pmu->cpuhp_node);
|
||||||
|
|
||||||
if (--nr_iommu_pmu)
|
if (--nr_iommu_pmu)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cpuhp_remove_state(CPUHP_AP_PERF_X86_IOMMU_PERF_ONLINE);
|
cpuhp_remove_multi_state(iommu_cpuhp_slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
void iommu_pmu_register(struct intel_iommu *iommu)
|
void iommu_pmu_register(struct intel_iommu *iommu)
|
||||||
|
@ -294,9 +294,9 @@ static void batch_clear_carry(struct pfn_batch *batch, unsigned int keep_pfns)
|
|||||||
batch->npfns[batch->end - 1] < keep_pfns);
|
batch->npfns[batch->end - 1] < keep_pfns);
|
||||||
|
|
||||||
batch->total_pfns = keep_pfns;
|
batch->total_pfns = keep_pfns;
|
||||||
batch->npfns[0] = keep_pfns;
|
|
||||||
batch->pfns[0] = batch->pfns[batch->end - 1] +
|
batch->pfns[0] = batch->pfns[batch->end - 1] +
|
||||||
(batch->npfns[batch->end - 1] - keep_pfns);
|
(batch->npfns[batch->end - 1] - keep_pfns);
|
||||||
|
batch->npfns[0] = keep_pfns;
|
||||||
batch->end = 0;
|
batch->end = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1142,6 +1142,7 @@ struct iopt_pages *iopt_alloc_pages(void __user *uptr, unsigned long length,
|
|||||||
bool writable)
|
bool writable)
|
||||||
{
|
{
|
||||||
struct iopt_pages *pages;
|
struct iopt_pages *pages;
|
||||||
|
unsigned long end;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The iommu API uses size_t as the length, and protect the DIV_ROUND_UP
|
* The iommu API uses size_t as the length, and protect the DIV_ROUND_UP
|
||||||
@ -1150,6 +1151,9 @@ struct iopt_pages *iopt_alloc_pages(void __user *uptr, unsigned long length,
|
|||||||
if (length > SIZE_MAX - PAGE_SIZE || length == 0)
|
if (length > SIZE_MAX - PAGE_SIZE || length == 0)
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
|
if (check_add_overflow((unsigned long)uptr, length, &end))
|
||||||
|
return ERR_PTR(-EOVERFLOW);
|
||||||
|
|
||||||
pages = kzalloc(sizeof(*pages), GFP_KERNEL_ACCOUNT);
|
pages = kzalloc(sizeof(*pages), GFP_KERNEL_ACCOUNT);
|
||||||
if (!pages)
|
if (!pages)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
@ -1203,13 +1207,21 @@ iopt_area_unpin_domain(struct pfn_batch *batch, struct iopt_area *area,
|
|||||||
unsigned long start =
|
unsigned long start =
|
||||||
max(start_index, *unmapped_end_index);
|
max(start_index, *unmapped_end_index);
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_IOMMUFD_TEST) &&
|
||||||
|
batch->total_pfns)
|
||||||
|
WARN_ON(*unmapped_end_index -
|
||||||
|
batch->total_pfns !=
|
||||||
|
start_index);
|
||||||
batch_from_domain(batch, domain, area, start,
|
batch_from_domain(batch, domain, area, start,
|
||||||
last_index);
|
last_index);
|
||||||
batch_last_index = start + batch->total_pfns - 1;
|
batch_last_index = start_index + batch->total_pfns - 1;
|
||||||
} else {
|
} else {
|
||||||
batch_last_index = last_index;
|
batch_last_index = last_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_IOMMUFD_TEST))
|
||||||
|
WARN_ON(batch_last_index > real_last_index);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* unmaps must always 'cut' at a place where the pfns are not
|
* unmaps must always 'cut' at a place where the pfns are not
|
||||||
* contiguous to pair with the maps that always install
|
* contiguous to pair with the maps that always install
|
||||||
|
@ -6260,7 +6260,6 @@ static void __md_stop(struct mddev *mddev)
|
|||||||
module_put(pers->owner);
|
module_put(pers->owner);
|
||||||
clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
|
clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
|
||||||
|
|
||||||
percpu_ref_exit(&mddev->writes_pending);
|
|
||||||
percpu_ref_exit(&mddev->active_io);
|
percpu_ref_exit(&mddev->active_io);
|
||||||
bioset_exit(&mddev->bio_set);
|
bioset_exit(&mddev->bio_set);
|
||||||
bioset_exit(&mddev->sync_set);
|
bioset_exit(&mddev->sync_set);
|
||||||
@ -6273,6 +6272,7 @@ void md_stop(struct mddev *mddev)
|
|||||||
*/
|
*/
|
||||||
__md_stop_writes(mddev);
|
__md_stop_writes(mddev);
|
||||||
__md_stop(mddev);
|
__md_stop(mddev);
|
||||||
|
percpu_ref_exit(&mddev->writes_pending);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL_GPL(md_stop);
|
EXPORT_SYMBOL_GPL(md_stop);
|
||||||
@ -7843,6 +7843,7 @@ static void md_free_disk(struct gendisk *disk)
|
|||||||
{
|
{
|
||||||
struct mddev *mddev = disk->private_data;
|
struct mddev *mddev = disk->private_data;
|
||||||
|
|
||||||
|
percpu_ref_exit(&mddev->writes_pending);
|
||||||
mddev_free(mddev);
|
mddev_free(mddev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1098,7 +1098,7 @@ static int imx290_runtime_suspend(struct device *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const struct dev_pm_ops imx290_pm_ops = {
|
static const struct dev_pm_ops imx290_pm_ops = {
|
||||||
SET_RUNTIME_PM_OPS(imx290_runtime_suspend, imx290_runtime_resume, NULL)
|
RUNTIME_PM_OPS(imx290_runtime_suspend, imx290_runtime_resume, NULL)
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
@ -1362,8 +1362,8 @@ static struct i2c_driver imx290_i2c_driver = {
|
|||||||
.remove = imx290_remove,
|
.remove = imx290_remove,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "imx290",
|
.name = "imx290",
|
||||||
.pm = &imx290_pm_ops,
|
.pm = pm_ptr(&imx290_pm_ops),
|
||||||
.of_match_table = of_match_ptr(imx290_of_match),
|
.of_match_table = imx290_of_match,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -38,8 +38,8 @@ static void venus_reset_cpu(struct venus_core *core)
|
|||||||
writel(fw_size, wrapper_base + WRAPPER_FW_END_ADDR);
|
writel(fw_size, wrapper_base + WRAPPER_FW_END_ADDR);
|
||||||
writel(0, wrapper_base + WRAPPER_CPA_START_ADDR);
|
writel(0, wrapper_base + WRAPPER_CPA_START_ADDR);
|
||||||
writel(fw_size, wrapper_base + WRAPPER_CPA_END_ADDR);
|
writel(fw_size, wrapper_base + WRAPPER_CPA_END_ADDR);
|
||||||
writel(0, wrapper_base + WRAPPER_NONPIX_START_ADDR);
|
writel(fw_size, wrapper_base + WRAPPER_NONPIX_START_ADDR);
|
||||||
writel(0, wrapper_base + WRAPPER_NONPIX_END_ADDR);
|
writel(fw_size, wrapper_base + WRAPPER_NONPIX_END_ADDR);
|
||||||
|
|
||||||
if (IS_V6(core)) {
|
if (IS_V6(core)) {
|
||||||
/* Bring XTSS out of reset */
|
/* Bring XTSS out of reset */
|
||||||
|
@ -3343,7 +3343,19 @@ static struct spi_mem_driver spi_nor_driver = {
|
|||||||
.remove = spi_nor_remove,
|
.remove = spi_nor_remove,
|
||||||
.shutdown = spi_nor_shutdown,
|
.shutdown = spi_nor_shutdown,
|
||||||
};
|
};
|
||||||
module_spi_mem_driver(spi_nor_driver);
|
|
||||||
|
static int __init spi_nor_module_init(void)
|
||||||
|
{
|
||||||
|
return spi_mem_driver_register(&spi_nor_driver);
|
||||||
|
}
|
||||||
|
module_init(spi_nor_module_init);
|
||||||
|
|
||||||
|
static void __exit spi_nor_module_exit(void)
|
||||||
|
{
|
||||||
|
spi_mem_driver_unregister(&spi_nor_driver);
|
||||||
|
spi_nor_debugfs_shutdown();
|
||||||
|
}
|
||||||
|
module_exit(spi_nor_module_exit);
|
||||||
|
|
||||||
MODULE_LICENSE("GPL v2");
|
MODULE_LICENSE("GPL v2");
|
||||||
MODULE_AUTHOR("Huang Shijie <shijie8@gmail.com>");
|
MODULE_AUTHOR("Huang Shijie <shijie8@gmail.com>");
|
||||||
|
@ -711,8 +711,10 @@ static inline struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd)
|
|||||||
|
|
||||||
#ifdef CONFIG_DEBUG_FS
|
#ifdef CONFIG_DEBUG_FS
|
||||||
void spi_nor_debugfs_register(struct spi_nor *nor);
|
void spi_nor_debugfs_register(struct spi_nor *nor);
|
||||||
|
void spi_nor_debugfs_shutdown(void);
|
||||||
#else
|
#else
|
||||||
static inline void spi_nor_debugfs_register(struct spi_nor *nor) {}
|
static inline void spi_nor_debugfs_register(struct spi_nor *nor) {}
|
||||||
|
static inline void spi_nor_debugfs_shutdown(void) {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* __LINUX_MTD_SPI_NOR_INTERNAL_H */
|
#endif /* __LINUX_MTD_SPI_NOR_INTERNAL_H */
|
||||||
|
@ -226,13 +226,13 @@ static void spi_nor_debugfs_unregister(void *data)
|
|||||||
nor->debugfs_root = NULL;
|
nor->debugfs_root = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct dentry *rootdir;
|
||||||
|
|
||||||
void spi_nor_debugfs_register(struct spi_nor *nor)
|
void spi_nor_debugfs_register(struct spi_nor *nor)
|
||||||
{
|
{
|
||||||
struct dentry *rootdir, *d;
|
struct dentry *d;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Create rootdir once. Will never be deleted again. */
|
|
||||||
rootdir = debugfs_lookup(SPI_NOR_DEBUGFS_ROOT, NULL);
|
|
||||||
if (!rootdir)
|
if (!rootdir)
|
||||||
rootdir = debugfs_create_dir(SPI_NOR_DEBUGFS_ROOT, NULL);
|
rootdir = debugfs_create_dir(SPI_NOR_DEBUGFS_ROOT, NULL);
|
||||||
|
|
||||||
@ -247,3 +247,8 @@ void spi_nor_debugfs_register(struct spi_nor *nor)
|
|||||||
debugfs_create_file("capabilities", 0444, d, nor,
|
debugfs_create_file("capabilities", 0444, d, nor,
|
||||||
&spi_nor_capabilities_fops);
|
&spi_nor_capabilities_fops);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void spi_nor_debugfs_shutdown(void)
|
||||||
|
{
|
||||||
|
debugfs_remove(rootdir);
|
||||||
|
}
|
||||||
|
@ -5613,7 +5613,7 @@ static const struct mv88e6xxx_ops mv88e6393x_ops = {
|
|||||||
* .port_set_upstream_port method.
|
* .port_set_upstream_port method.
|
||||||
*/
|
*/
|
||||||
.set_egress_port = mv88e6393x_set_egress_port,
|
.set_egress_port = mv88e6393x_set_egress_port,
|
||||||
.watchdog_ops = &mv88e6390_watchdog_ops,
|
.watchdog_ops = &mv88e6393x_watchdog_ops,
|
||||||
.mgmt_rsvd2cpu = mv88e6393x_port_mgmt_rsvd2cpu,
|
.mgmt_rsvd2cpu = mv88e6393x_port_mgmt_rsvd2cpu,
|
||||||
.pot_clear = mv88e6xxx_g2_pot_clear,
|
.pot_clear = mv88e6xxx_g2_pot_clear,
|
||||||
.reset = mv88e6352_g1_reset,
|
.reset = mv88e6352_g1_reset,
|
||||||
|
@ -943,6 +943,26 @@ const struct mv88e6xxx_irq_ops mv88e6390_watchdog_ops = {
|
|||||||
.irq_free = mv88e6390_watchdog_free,
|
.irq_free = mv88e6390_watchdog_free,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int mv88e6393x_watchdog_action(struct mv88e6xxx_chip *chip, int irq)
|
||||||
|
{
|
||||||
|
mv88e6390_watchdog_action(chip, irq);
|
||||||
|
|
||||||
|
/* Fix for clearing the force WD event bit.
|
||||||
|
* Unreleased erratum on mv88e6393x.
|
||||||
|
*/
|
||||||
|
mv88e6xxx_g2_write(chip, MV88E6390_G2_WDOG_CTL,
|
||||||
|
MV88E6390_G2_WDOG_CTL_UPDATE |
|
||||||
|
MV88E6390_G2_WDOG_CTL_PTR_EVENT);
|
||||||
|
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct mv88e6xxx_irq_ops mv88e6393x_watchdog_ops = {
|
||||||
|
.irq_action = mv88e6393x_watchdog_action,
|
||||||
|
.irq_setup = mv88e6390_watchdog_setup,
|
||||||
|
.irq_free = mv88e6390_watchdog_free,
|
||||||
|
};
|
||||||
|
|
||||||
static irqreturn_t mv88e6xxx_g2_watchdog_thread_fn(int irq, void *dev_id)
|
static irqreturn_t mv88e6xxx_g2_watchdog_thread_fn(int irq, void *dev_id)
|
||||||
{
|
{
|
||||||
struct mv88e6xxx_chip *chip = dev_id;
|
struct mv88e6xxx_chip *chip = dev_id;
|
||||||
|
@ -369,6 +369,7 @@ int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip, int target,
|
|||||||
extern const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops;
|
extern const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops;
|
||||||
extern const struct mv88e6xxx_irq_ops mv88e6250_watchdog_ops;
|
extern const struct mv88e6xxx_irq_ops mv88e6250_watchdog_ops;
|
||||||
extern const struct mv88e6xxx_irq_ops mv88e6390_watchdog_ops;
|
extern const struct mv88e6xxx_irq_ops mv88e6390_watchdog_ops;
|
||||||
|
extern const struct mv88e6xxx_irq_ops mv88e6393x_watchdog_ops;
|
||||||
|
|
||||||
extern const struct mv88e6xxx_avb_ops mv88e6165_avb_ops;
|
extern const struct mv88e6xxx_avb_ops mv88e6165_avb_ops;
|
||||||
extern const struct mv88e6xxx_avb_ops mv88e6352_avb_ops;
|
extern const struct mv88e6xxx_avb_ops mv88e6352_avb_ops;
|
||||||
|
@ -507,6 +507,11 @@ struct bufdesc_ex {
|
|||||||
/* i.MX6Q adds pm_qos support */
|
/* i.MX6Q adds pm_qos support */
|
||||||
#define FEC_QUIRK_HAS_PMQOS BIT(23)
|
#define FEC_QUIRK_HAS_PMQOS BIT(23)
|
||||||
|
|
||||||
|
/* Not all FEC hardware block MDIOs support accesses in C45 mode.
|
||||||
|
* Older blocks in the ColdFire parts do not support it.
|
||||||
|
*/
|
||||||
|
#define FEC_QUIRK_HAS_MDIO_C45 BIT(24)
|
||||||
|
|
||||||
struct bufdesc_prop {
|
struct bufdesc_prop {
|
||||||
int qid;
|
int qid;
|
||||||
/* Address of Rx and Tx buffers */
|
/* Address of Rx and Tx buffers */
|
||||||
|
@ -100,18 +100,19 @@ struct fec_devinfo {
|
|||||||
|
|
||||||
static const struct fec_devinfo fec_imx25_info = {
|
static const struct fec_devinfo fec_imx25_info = {
|
||||||
.quirks = FEC_QUIRK_USE_GASKET | FEC_QUIRK_MIB_CLEAR |
|
.quirks = FEC_QUIRK_USE_GASKET | FEC_QUIRK_MIB_CLEAR |
|
||||||
FEC_QUIRK_HAS_FRREG,
|
FEC_QUIRK_HAS_FRREG | FEC_QUIRK_HAS_MDIO_C45,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct fec_devinfo fec_imx27_info = {
|
static const struct fec_devinfo fec_imx27_info = {
|
||||||
.quirks = FEC_QUIRK_MIB_CLEAR | FEC_QUIRK_HAS_FRREG,
|
.quirks = FEC_QUIRK_MIB_CLEAR | FEC_QUIRK_HAS_FRREG |
|
||||||
|
FEC_QUIRK_HAS_MDIO_C45,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct fec_devinfo fec_imx28_info = {
|
static const struct fec_devinfo fec_imx28_info = {
|
||||||
.quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_SWAP_FRAME |
|
.quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_SWAP_FRAME |
|
||||||
FEC_QUIRK_SINGLE_MDIO | FEC_QUIRK_HAS_RACC |
|
FEC_QUIRK_SINGLE_MDIO | FEC_QUIRK_HAS_RACC |
|
||||||
FEC_QUIRK_HAS_FRREG | FEC_QUIRK_CLEAR_SETUP_MII |
|
FEC_QUIRK_HAS_FRREG | FEC_QUIRK_CLEAR_SETUP_MII |
|
||||||
FEC_QUIRK_NO_HARD_RESET,
|
FEC_QUIRK_NO_HARD_RESET | FEC_QUIRK_HAS_MDIO_C45,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct fec_devinfo fec_imx6q_info = {
|
static const struct fec_devinfo fec_imx6q_info = {
|
||||||
@ -119,11 +120,12 @@ static const struct fec_devinfo fec_imx6q_info = {
|
|||||||
FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
|
FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
|
||||||
FEC_QUIRK_HAS_VLAN | FEC_QUIRK_ERR006358 |
|
FEC_QUIRK_HAS_VLAN | FEC_QUIRK_ERR006358 |
|
||||||
FEC_QUIRK_HAS_RACC | FEC_QUIRK_CLEAR_SETUP_MII |
|
FEC_QUIRK_HAS_RACC | FEC_QUIRK_CLEAR_SETUP_MII |
|
||||||
FEC_QUIRK_HAS_PMQOS,
|
FEC_QUIRK_HAS_PMQOS | FEC_QUIRK_HAS_MDIO_C45,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct fec_devinfo fec_mvf600_info = {
|
static const struct fec_devinfo fec_mvf600_info = {
|
||||||
.quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_RACC,
|
.quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_RACC |
|
||||||
|
FEC_QUIRK_HAS_MDIO_C45,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct fec_devinfo fec_imx6x_info = {
|
static const struct fec_devinfo fec_imx6x_info = {
|
||||||
@ -132,7 +134,8 @@ static const struct fec_devinfo fec_imx6x_info = {
|
|||||||
FEC_QUIRK_HAS_VLAN | FEC_QUIRK_HAS_AVB |
|
FEC_QUIRK_HAS_VLAN | FEC_QUIRK_HAS_AVB |
|
||||||
FEC_QUIRK_ERR007885 | FEC_QUIRK_BUG_CAPTURE |
|
FEC_QUIRK_ERR007885 | FEC_QUIRK_BUG_CAPTURE |
|
||||||
FEC_QUIRK_HAS_RACC | FEC_QUIRK_HAS_COALESCE |
|
FEC_QUIRK_HAS_RACC | FEC_QUIRK_HAS_COALESCE |
|
||||||
FEC_QUIRK_CLEAR_SETUP_MII | FEC_QUIRK_HAS_MULTI_QUEUES,
|
FEC_QUIRK_CLEAR_SETUP_MII | FEC_QUIRK_HAS_MULTI_QUEUES |
|
||||||
|
FEC_QUIRK_HAS_MDIO_C45,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct fec_devinfo fec_imx6ul_info = {
|
static const struct fec_devinfo fec_imx6ul_info = {
|
||||||
@ -140,7 +143,8 @@ static const struct fec_devinfo fec_imx6ul_info = {
|
|||||||
FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
|
FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
|
||||||
FEC_QUIRK_HAS_VLAN | FEC_QUIRK_ERR007885 |
|
FEC_QUIRK_HAS_VLAN | FEC_QUIRK_ERR007885 |
|
||||||
FEC_QUIRK_BUG_CAPTURE | FEC_QUIRK_HAS_RACC |
|
FEC_QUIRK_BUG_CAPTURE | FEC_QUIRK_HAS_RACC |
|
||||||
FEC_QUIRK_HAS_COALESCE | FEC_QUIRK_CLEAR_SETUP_MII,
|
FEC_QUIRK_HAS_COALESCE | FEC_QUIRK_CLEAR_SETUP_MII |
|
||||||
|
FEC_QUIRK_HAS_MDIO_C45,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct fec_devinfo fec_imx8mq_info = {
|
static const struct fec_devinfo fec_imx8mq_info = {
|
||||||
@ -150,7 +154,8 @@ static const struct fec_devinfo fec_imx8mq_info = {
|
|||||||
FEC_QUIRK_ERR007885 | FEC_QUIRK_BUG_CAPTURE |
|
FEC_QUIRK_ERR007885 | FEC_QUIRK_BUG_CAPTURE |
|
||||||
FEC_QUIRK_HAS_RACC | FEC_QUIRK_HAS_COALESCE |
|
FEC_QUIRK_HAS_RACC | FEC_QUIRK_HAS_COALESCE |
|
||||||
FEC_QUIRK_CLEAR_SETUP_MII | FEC_QUIRK_HAS_MULTI_QUEUES |
|
FEC_QUIRK_CLEAR_SETUP_MII | FEC_QUIRK_HAS_MULTI_QUEUES |
|
||||||
FEC_QUIRK_HAS_EEE | FEC_QUIRK_WAKEUP_FROM_INT2,
|
FEC_QUIRK_HAS_EEE | FEC_QUIRK_WAKEUP_FROM_INT2 |
|
||||||
|
FEC_QUIRK_HAS_MDIO_C45,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct fec_devinfo fec_imx8qm_info = {
|
static const struct fec_devinfo fec_imx8qm_info = {
|
||||||
@ -160,14 +165,15 @@ static const struct fec_devinfo fec_imx8qm_info = {
|
|||||||
FEC_QUIRK_ERR007885 | FEC_QUIRK_BUG_CAPTURE |
|
FEC_QUIRK_ERR007885 | FEC_QUIRK_BUG_CAPTURE |
|
||||||
FEC_QUIRK_HAS_RACC | FEC_QUIRK_HAS_COALESCE |
|
FEC_QUIRK_HAS_RACC | FEC_QUIRK_HAS_COALESCE |
|
||||||
FEC_QUIRK_CLEAR_SETUP_MII | FEC_QUIRK_HAS_MULTI_QUEUES |
|
FEC_QUIRK_CLEAR_SETUP_MII | FEC_QUIRK_HAS_MULTI_QUEUES |
|
||||||
FEC_QUIRK_DELAYED_CLKS_SUPPORT,
|
FEC_QUIRK_DELAYED_CLKS_SUPPORT | FEC_QUIRK_HAS_MDIO_C45,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct fec_devinfo fec_s32v234_info = {
|
static const struct fec_devinfo fec_s32v234_info = {
|
||||||
.quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT |
|
.quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT |
|
||||||
FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
|
FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
|
||||||
FEC_QUIRK_HAS_VLAN | FEC_QUIRK_HAS_AVB |
|
FEC_QUIRK_HAS_VLAN | FEC_QUIRK_HAS_AVB |
|
||||||
FEC_QUIRK_ERR007885 | FEC_QUIRK_BUG_CAPTURE,
|
FEC_QUIRK_ERR007885 | FEC_QUIRK_BUG_CAPTURE |
|
||||||
|
FEC_QUIRK_HAS_MDIO_C45,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct platform_device_id fec_devtype[] = {
|
static struct platform_device_id fec_devtype[] = {
|
||||||
@ -2434,8 +2440,10 @@ static int fec_enet_mii_init(struct platform_device *pdev)
|
|||||||
fep->mii_bus->name = "fec_enet_mii_bus";
|
fep->mii_bus->name = "fec_enet_mii_bus";
|
||||||
fep->mii_bus->read = fec_enet_mdio_read_c22;
|
fep->mii_bus->read = fec_enet_mdio_read_c22;
|
||||||
fep->mii_bus->write = fec_enet_mdio_write_c22;
|
fep->mii_bus->write = fec_enet_mdio_write_c22;
|
||||||
fep->mii_bus->read_c45 = fec_enet_mdio_read_c45;
|
if (fep->quirks & FEC_QUIRK_HAS_MDIO_C45) {
|
||||||
fep->mii_bus->write_c45 = fec_enet_mdio_write_c45;
|
fep->mii_bus->read_c45 = fec_enet_mdio_read_c45;
|
||||||
|
fep->mii_bus->write_c45 = fec_enet_mdio_write_c45;
|
||||||
|
}
|
||||||
snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
|
snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
|
||||||
pdev->name, fep->dev_id + 1);
|
pdev->name, fep->dev_id + 1);
|
||||||
fep->mii_bus->priv = fep;
|
fep->mii_bus->priv = fep;
|
||||||
|
@ -51,6 +51,8 @@
|
|||||||
|
|
||||||
#define GVE_TX_MAX_HEADER_SIZE 182
|
#define GVE_TX_MAX_HEADER_SIZE 182
|
||||||
|
|
||||||
|
#define GVE_GQ_TX_MIN_PKT_DESC_BYTES 182
|
||||||
|
|
||||||
/* Each slot in the desc ring has a 1:1 mapping to a slot in the data ring */
|
/* Each slot in the desc ring has a 1:1 mapping to a slot in the data ring */
|
||||||
struct gve_rx_desc_queue {
|
struct gve_rx_desc_queue {
|
||||||
struct gve_rx_desc *desc_ring; /* the descriptor ring */
|
struct gve_rx_desc *desc_ring; /* the descriptor ring */
|
||||||
|
@ -351,8 +351,8 @@ static inline int gve_skb_fifo_bytes_required(struct gve_tx_ring *tx,
|
|||||||
int bytes;
|
int bytes;
|
||||||
int hlen;
|
int hlen;
|
||||||
|
|
||||||
hlen = skb_is_gso(skb) ? skb_checksum_start_offset(skb) +
|
hlen = skb_is_gso(skb) ? skb_checksum_start_offset(skb) + tcp_hdrlen(skb) :
|
||||||
tcp_hdrlen(skb) : skb_headlen(skb);
|
min_t(int, GVE_GQ_TX_MIN_PKT_DESC_BYTES, skb->len);
|
||||||
|
|
||||||
pad_bytes = gve_tx_fifo_pad_alloc_one_frag(&tx->tx_fifo,
|
pad_bytes = gve_tx_fifo_pad_alloc_one_frag(&tx->tx_fifo,
|
||||||
hlen);
|
hlen);
|
||||||
@ -522,13 +522,11 @@ static int gve_tx_add_skb_copy(struct gve_priv *priv, struct gve_tx_ring *tx, st
|
|||||||
pkt_desc = &tx->desc[idx];
|
pkt_desc = &tx->desc[idx];
|
||||||
|
|
||||||
l4_hdr_offset = skb_checksum_start_offset(skb);
|
l4_hdr_offset = skb_checksum_start_offset(skb);
|
||||||
/* If the skb is gso, then we want the tcp header in the first segment
|
/* If the skb is gso, then we want the tcp header alone in the first segment
|
||||||
* otherwise we want the linear portion of the skb (which will contain
|
* otherwise we want the minimum required by the gVNIC spec.
|
||||||
* the checksum because skb->csum_start and skb->csum_offset are given
|
|
||||||
* relative to skb->head) in the first segment.
|
|
||||||
*/
|
*/
|
||||||
hlen = is_gso ? l4_hdr_offset + tcp_hdrlen(skb) :
|
hlen = is_gso ? l4_hdr_offset + tcp_hdrlen(skb) :
|
||||||
skb_headlen(skb);
|
min_t(int, GVE_GQ_TX_MIN_PKT_DESC_BYTES, skb->len);
|
||||||
|
|
||||||
info->skb = skb;
|
info->skb = skb;
|
||||||
/* We don't want to split the header, so if necessary, pad to the end
|
/* We don't want to split the header, so if necessary, pad to the end
|
||||||
|
@ -541,6 +541,21 @@ static void ice_vc_fdir_rem_prof_all(struct ice_vf *vf)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ice_vc_fdir_reset_cnt_all - reset all FDIR counters for this VF FDIR
|
||||||
|
* @fdir: pointer to the VF FDIR structure
|
||||||
|
*/
|
||||||
|
static void ice_vc_fdir_reset_cnt_all(struct ice_vf_fdir *fdir)
|
||||||
|
{
|
||||||
|
enum ice_fltr_ptype flow;
|
||||||
|
|
||||||
|
for (flow = ICE_FLTR_PTYPE_NONF_NONE;
|
||||||
|
flow < ICE_FLTR_PTYPE_MAX; flow++) {
|
||||||
|
fdir->fdir_fltr_cnt[flow][0] = 0;
|
||||||
|
fdir->fdir_fltr_cnt[flow][1] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ice_vc_fdir_has_prof_conflict
|
* ice_vc_fdir_has_prof_conflict
|
||||||
* @vf: pointer to the VF structure
|
* @vf: pointer to the VF structure
|
||||||
@ -1871,7 +1886,7 @@ int ice_vc_add_fdir_fltr(struct ice_vf *vf, u8 *msg)
|
|||||||
v_ret = VIRTCHNL_STATUS_SUCCESS;
|
v_ret = VIRTCHNL_STATUS_SUCCESS;
|
||||||
stat->status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE;
|
stat->status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE;
|
||||||
dev_dbg(dev, "VF %d: set FDIR context failed\n", vf->vf_id);
|
dev_dbg(dev, "VF %d: set FDIR context failed\n", vf->vf_id);
|
||||||
goto err_free_conf;
|
goto err_rem_entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = ice_vc_fdir_write_fltr(vf, conf, true, is_tun);
|
ret = ice_vc_fdir_write_fltr(vf, conf, true, is_tun);
|
||||||
@ -1880,15 +1895,16 @@ int ice_vc_add_fdir_fltr(struct ice_vf *vf, u8 *msg)
|
|||||||
stat->status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE;
|
stat->status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE;
|
||||||
dev_err(dev, "VF %d: writing FDIR rule failed, ret:%d\n",
|
dev_err(dev, "VF %d: writing FDIR rule failed, ret:%d\n",
|
||||||
vf->vf_id, ret);
|
vf->vf_id, ret);
|
||||||
goto err_rem_entry;
|
goto err_clr_irq;
|
||||||
}
|
}
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
kfree(stat);
|
kfree(stat);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
err_rem_entry:
|
err_clr_irq:
|
||||||
ice_vc_fdir_clear_irq_ctx(vf);
|
ice_vc_fdir_clear_irq_ctx(vf);
|
||||||
|
err_rem_entry:
|
||||||
ice_vc_fdir_remove_entry(vf, conf, conf->flow_id);
|
ice_vc_fdir_remove_entry(vf, conf, conf->flow_id);
|
||||||
err_free_conf:
|
err_free_conf:
|
||||||
devm_kfree(dev, conf);
|
devm_kfree(dev, conf);
|
||||||
@ -1997,6 +2013,7 @@ void ice_vf_fdir_init(struct ice_vf *vf)
|
|||||||
spin_lock_init(&fdir->ctx_lock);
|
spin_lock_init(&fdir->ctx_lock);
|
||||||
fdir->ctx_irq.flags = 0;
|
fdir->ctx_irq.flags = 0;
|
||||||
fdir->ctx_done.flags = 0;
|
fdir->ctx_done.flags = 0;
|
||||||
|
ice_vc_fdir_reset_cnt_all(fdir);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -729,6 +729,7 @@ static void mtk_mac_link_up(struct phylink_config *config,
|
|||||||
MAC_MCR_FORCE_RX_FC);
|
MAC_MCR_FORCE_RX_FC);
|
||||||
|
|
||||||
/* Configure speed */
|
/* Configure speed */
|
||||||
|
mac->speed = speed;
|
||||||
switch (speed) {
|
switch (speed) {
|
||||||
case SPEED_2500:
|
case SPEED_2500:
|
||||||
case SPEED_1000:
|
case SPEED_1000:
|
||||||
@ -3232,6 +3233,9 @@ found:
|
|||||||
if (dp->index >= MTK_QDMA_NUM_QUEUES)
|
if (dp->index >= MTK_QDMA_NUM_QUEUES)
|
||||||
return NOTIFY_DONE;
|
return NOTIFY_DONE;
|
||||||
|
|
||||||
|
if (mac->speed > 0 && mac->speed <= s.base.speed)
|
||||||
|
s.base.speed = 0;
|
||||||
|
|
||||||
mtk_set_queue_speed(eth, dp->index + 3, s.base.speed);
|
mtk_set_queue_speed(eth, dp->index + 3, s.base.speed);
|
||||||
|
|
||||||
return NOTIFY_DONE;
|
return NOTIFY_DONE;
|
||||||
|
@ -251,7 +251,6 @@ static void intel_speed_mode_2500(struct net_device *ndev, void *intel_data)
|
|||||||
priv->plat->mdio_bus_data->xpcs_an_inband = false;
|
priv->plat->mdio_bus_data->xpcs_an_inband = false;
|
||||||
} else {
|
} else {
|
||||||
priv->plat->max_speed = 1000;
|
priv->plat->max_speed = 1000;
|
||||||
priv->plat->mdio_bus_data->xpcs_an_inband = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1134,20 +1134,26 @@ static void stmmac_check_pcs_mode(struct stmmac_priv *priv)
|
|||||||
static int stmmac_init_phy(struct net_device *dev)
|
static int stmmac_init_phy(struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct stmmac_priv *priv = netdev_priv(dev);
|
struct stmmac_priv *priv = netdev_priv(dev);
|
||||||
|
struct fwnode_handle *phy_fwnode;
|
||||||
struct fwnode_handle *fwnode;
|
struct fwnode_handle *fwnode;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (!phylink_expects_phy(priv->phylink))
|
||||||
|
return 0;
|
||||||
|
|
||||||
fwnode = of_fwnode_handle(priv->plat->phylink_node);
|
fwnode = of_fwnode_handle(priv->plat->phylink_node);
|
||||||
if (!fwnode)
|
if (!fwnode)
|
||||||
fwnode = dev_fwnode(priv->device);
|
fwnode = dev_fwnode(priv->device);
|
||||||
|
|
||||||
if (fwnode)
|
if (fwnode)
|
||||||
ret = phylink_fwnode_phy_connect(priv->phylink, fwnode, 0);
|
phy_fwnode = fwnode_get_phy_node(fwnode);
|
||||||
|
else
|
||||||
|
phy_fwnode = NULL;
|
||||||
|
|
||||||
/* Some DT bindings do not set-up the PHY handle. Let's try to
|
/* Some DT bindings do not set-up the PHY handle. Let's try to
|
||||||
* manually parse it
|
* manually parse it
|
||||||
*/
|
*/
|
||||||
if (!fwnode || ret) {
|
if (!phy_fwnode || IS_ERR(phy_fwnode)) {
|
||||||
int addr = priv->plat->phy_addr;
|
int addr = priv->plat->phy_addr;
|
||||||
struct phy_device *phydev;
|
struct phy_device *phydev;
|
||||||
|
|
||||||
@ -1163,6 +1169,9 @@ static int stmmac_init_phy(struct net_device *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret = phylink_connect_phy(priv->phylink, phydev);
|
ret = phylink_connect_phy(priv->phylink, phydev);
|
||||||
|
} else {
|
||||||
|
fwnode_handle_put(phy_fwnode);
|
||||||
|
ret = phylink_fwnode_phy_connect(priv->phylink, fwnode, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!priv->plat->pmt) {
|
if (!priv->plat->pmt) {
|
||||||
@ -6622,6 +6631,8 @@ int stmmac_xdp_open(struct net_device *dev)
|
|||||||
goto init_error;
|
goto init_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stmmac_reset_queues_param(priv);
|
||||||
|
|
||||||
/* DMA CSR Channel configuration */
|
/* DMA CSR Channel configuration */
|
||||||
for (chan = 0; chan < dma_csr_ch; chan++) {
|
for (chan = 0; chan < dma_csr_ch; chan++) {
|
||||||
stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, chan);
|
stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, chan);
|
||||||
@ -6948,7 +6959,7 @@ static void stmmac_napi_del(struct net_device *dev)
|
|||||||
int stmmac_reinit_queues(struct net_device *dev, u32 rx_cnt, u32 tx_cnt)
|
int stmmac_reinit_queues(struct net_device *dev, u32 rx_cnt, u32 tx_cnt)
|
||||||
{
|
{
|
||||||
struct stmmac_priv *priv = netdev_priv(dev);
|
struct stmmac_priv *priv = netdev_priv(dev);
|
||||||
int ret = 0;
|
int ret = 0, i;
|
||||||
|
|
||||||
if (netif_running(dev))
|
if (netif_running(dev))
|
||||||
stmmac_release(dev);
|
stmmac_release(dev);
|
||||||
@ -6957,6 +6968,10 @@ int stmmac_reinit_queues(struct net_device *dev, u32 rx_cnt, u32 tx_cnt)
|
|||||||
|
|
||||||
priv->plat->rx_queues_to_use = rx_cnt;
|
priv->plat->rx_queues_to_use = rx_cnt;
|
||||||
priv->plat->tx_queues_to_use = tx_cnt;
|
priv->plat->tx_queues_to_use = tx_cnt;
|
||||||
|
if (!netif_is_rxfh_configured(dev))
|
||||||
|
for (i = 0; i < ARRAY_SIZE(priv->rss.table); i++)
|
||||||
|
priv->rss.table[i] = ethtool_rxfh_indir_default(i,
|
||||||
|
rx_cnt);
|
||||||
|
|
||||||
stmmac_napi_add(dev);
|
stmmac_napi_add(dev);
|
||||||
|
|
||||||
|
@ -2957,7 +2957,8 @@ err_free_phylink:
|
|||||||
am65_cpsw_nuss_phylink_cleanup(common);
|
am65_cpsw_nuss_phylink_cleanup(common);
|
||||||
am65_cpts_release(common->cpts);
|
am65_cpts_release(common->cpts);
|
||||||
err_of_clear:
|
err_of_clear:
|
||||||
of_platform_device_destroy(common->mdio_dev, NULL);
|
if (common->mdio_dev)
|
||||||
|
of_platform_device_destroy(common->mdio_dev, NULL);
|
||||||
err_pm_clear:
|
err_pm_clear:
|
||||||
pm_runtime_put_sync(dev);
|
pm_runtime_put_sync(dev);
|
||||||
pm_runtime_disable(dev);
|
pm_runtime_disable(dev);
|
||||||
@ -2987,7 +2988,8 @@ static int am65_cpsw_nuss_remove(struct platform_device *pdev)
|
|||||||
am65_cpts_release(common->cpts);
|
am65_cpts_release(common->cpts);
|
||||||
am65_cpsw_disable_serdes_phy(common);
|
am65_cpsw_disable_serdes_phy(common);
|
||||||
|
|
||||||
of_platform_device_destroy(common->mdio_dev, NULL);
|
if (common->mdio_dev)
|
||||||
|
of_platform_device_destroy(common->mdio_dev, NULL);
|
||||||
|
|
||||||
pm_runtime_put_sync(&pdev->dev);
|
pm_runtime_put_sync(&pdev->dev);
|
||||||
pm_runtime_disable(&pdev->dev);
|
pm_runtime_disable(&pdev->dev);
|
||||||
|
@ -1583,6 +1583,25 @@ void phylink_destroy(struct phylink *pl)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(phylink_destroy);
|
EXPORT_SYMBOL_GPL(phylink_destroy);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* phylink_expects_phy() - Determine if phylink expects a phy to be attached
|
||||||
|
* @pl: a pointer to a &struct phylink returned from phylink_create()
|
||||||
|
*
|
||||||
|
* When using fixed-link mode, or in-band mode with 1000base-X or 2500base-X,
|
||||||
|
* no PHY is needed.
|
||||||
|
*
|
||||||
|
* Returns true if phylink will be expecting a PHY.
|
||||||
|
*/
|
||||||
|
bool phylink_expects_phy(struct phylink *pl)
|
||||||
|
{
|
||||||
|
if (pl->cfg_link_an_mode == MLO_AN_FIXED ||
|
||||||
|
(pl->cfg_link_an_mode == MLO_AN_INBAND &&
|
||||||
|
phy_interface_mode_is_8023z(pl->link_config.interface)))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(phylink_expects_phy);
|
||||||
|
|
||||||
static void phylink_phy_change(struct phy_device *phydev, bool up)
|
static void phylink_phy_change(struct phy_device *phydev, bool up)
|
||||||
{
|
{
|
||||||
struct phylink *pl = phydev->phylink;
|
struct phylink *pl = phydev->phylink;
|
||||||
|
@ -406,6 +406,10 @@ static const struct sfp_quirk sfp_quirks[] = {
|
|||||||
|
|
||||||
SFP_QUIRK_F("HALNy", "HL-GSFP", sfp_fixup_halny_gsfp),
|
SFP_QUIRK_F("HALNy", "HL-GSFP", sfp_fixup_halny_gsfp),
|
||||||
|
|
||||||
|
// HG MXPD-483II-F 2.5G supports 2500Base-X, but incorrectly reports
|
||||||
|
// 2600MBd in their EERPOM
|
||||||
|
SFP_QUIRK_M("HG GENUINE", "MXPD-483II", sfp_quirk_2500basex),
|
||||||
|
|
||||||
// Huawei MA5671A can operate at 2500base-X, but report 1.2GBd NRZ in
|
// Huawei MA5671A can operate at 2500base-X, but report 1.2GBd NRZ in
|
||||||
// their EEPROM
|
// their EEPROM
|
||||||
SFP_QUIRK("HUAWEI", "MA5671A", sfp_quirk_2500basex,
|
SFP_QUIRK("HUAWEI", "MA5671A", sfp_quirk_2500basex,
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
#include "pci.h"
|
#include "pci.h"
|
||||||
#include "pcic.h"
|
#include "pcic.h"
|
||||||
|
|
||||||
#define MHI_TIMEOUT_DEFAULT_MS 90000
|
#define MHI_TIMEOUT_DEFAULT_MS 20000
|
||||||
#define RDDM_DUMP_SIZE 0x420000
|
#define RDDM_DUMP_SIZE 0x420000
|
||||||
|
|
||||||
static struct mhi_channel_config ath11k_mhi_channels_qca6390[] = {
|
static struct mhi_channel_config ath11k_mhi_channels_qca6390[] = {
|
||||||
|
@ -994,15 +994,34 @@ static const struct sdio_device_id brcmf_sdmmc_ids[] = {
|
|||||||
MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
|
MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
|
||||||
|
|
||||||
|
|
||||||
static void brcmf_sdiod_acpi_set_power_manageable(struct device *dev,
|
static void brcmf_sdiod_acpi_save_power_manageable(struct brcmf_sdio_dev *sdiodev)
|
||||||
int val)
|
|
||||||
{
|
{
|
||||||
#if IS_ENABLED(CONFIG_ACPI)
|
#if IS_ENABLED(CONFIG_ACPI)
|
||||||
struct acpi_device *adev;
|
struct acpi_device *adev;
|
||||||
|
|
||||||
adev = ACPI_COMPANION(dev);
|
adev = ACPI_COMPANION(&sdiodev->func1->dev);
|
||||||
if (adev)
|
if (adev)
|
||||||
adev->flags.power_manageable = 0;
|
sdiodev->func1_power_manageable = adev->flags.power_manageable;
|
||||||
|
|
||||||
|
adev = ACPI_COMPANION(&sdiodev->func2->dev);
|
||||||
|
if (adev)
|
||||||
|
sdiodev->func2_power_manageable = adev->flags.power_manageable;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void brcmf_sdiod_acpi_set_power_manageable(struct brcmf_sdio_dev *sdiodev,
|
||||||
|
int enable)
|
||||||
|
{
|
||||||
|
#if IS_ENABLED(CONFIG_ACPI)
|
||||||
|
struct acpi_device *adev;
|
||||||
|
|
||||||
|
adev = ACPI_COMPANION(&sdiodev->func1->dev);
|
||||||
|
if (adev)
|
||||||
|
adev->flags.power_manageable = enable ? sdiodev->func1_power_manageable : 0;
|
||||||
|
|
||||||
|
adev = ACPI_COMPANION(&sdiodev->func2->dev);
|
||||||
|
if (adev)
|
||||||
|
adev->flags.power_manageable = enable ? sdiodev->func2_power_manageable : 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1012,7 +1031,6 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
|
|||||||
int err;
|
int err;
|
||||||
struct brcmf_sdio_dev *sdiodev;
|
struct brcmf_sdio_dev *sdiodev;
|
||||||
struct brcmf_bus *bus_if;
|
struct brcmf_bus *bus_if;
|
||||||
struct device *dev;
|
|
||||||
|
|
||||||
brcmf_dbg(SDIO, "Enter\n");
|
brcmf_dbg(SDIO, "Enter\n");
|
||||||
brcmf_dbg(SDIO, "Class=%x\n", func->class);
|
brcmf_dbg(SDIO, "Class=%x\n", func->class);
|
||||||
@ -1020,14 +1038,9 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
|
|||||||
brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device);
|
brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device);
|
||||||
brcmf_dbg(SDIO, "Function#: %d\n", func->num);
|
brcmf_dbg(SDIO, "Function#: %d\n", func->num);
|
||||||
|
|
||||||
dev = &func->dev;
|
|
||||||
|
|
||||||
/* Set MMC_QUIRK_LENIENT_FN0 for this card */
|
/* Set MMC_QUIRK_LENIENT_FN0 for this card */
|
||||||
func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
|
func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
|
||||||
|
|
||||||
/* prohibit ACPI power management for this device */
|
|
||||||
brcmf_sdiod_acpi_set_power_manageable(dev, 0);
|
|
||||||
|
|
||||||
/* Consume func num 1 but dont do anything with it. */
|
/* Consume func num 1 but dont do anything with it. */
|
||||||
if (func->num == 1)
|
if (func->num == 1)
|
||||||
return 0;
|
return 0;
|
||||||
@ -1059,6 +1072,7 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
|
|||||||
dev_set_drvdata(&sdiodev->func1->dev, bus_if);
|
dev_set_drvdata(&sdiodev->func1->dev, bus_if);
|
||||||
sdiodev->dev = &sdiodev->func1->dev;
|
sdiodev->dev = &sdiodev->func1->dev;
|
||||||
|
|
||||||
|
brcmf_sdiod_acpi_save_power_manageable(sdiodev);
|
||||||
brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_DOWN);
|
brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_DOWN);
|
||||||
|
|
||||||
brcmf_dbg(SDIO, "F2 found, calling brcmf_sdiod_probe...\n");
|
brcmf_dbg(SDIO, "F2 found, calling brcmf_sdiod_probe...\n");
|
||||||
@ -1124,6 +1138,8 @@ void brcmf_sdio_wowl_config(struct device *dev, bool enabled)
|
|||||||
|
|
||||||
if (sdiodev->settings->bus.sdio.oob_irq_supported ||
|
if (sdiodev->settings->bus.sdio.oob_irq_supported ||
|
||||||
pm_caps & MMC_PM_WAKE_SDIO_IRQ) {
|
pm_caps & MMC_PM_WAKE_SDIO_IRQ) {
|
||||||
|
/* Stop ACPI from turning off the device when wowl is enabled */
|
||||||
|
brcmf_sdiod_acpi_set_power_manageable(sdiodev, !enabled);
|
||||||
sdiodev->wowl_enabled = enabled;
|
sdiodev->wowl_enabled = enabled;
|
||||||
brcmf_dbg(SDIO, "Configuring WOWL, enabled=%d\n", enabled);
|
brcmf_dbg(SDIO, "Configuring WOWL, enabled=%d\n", enabled);
|
||||||
return;
|
return;
|
||||||
|
@ -188,6 +188,8 @@ struct brcmf_sdio_dev {
|
|||||||
char nvram_name[BRCMF_FW_NAME_LEN];
|
char nvram_name[BRCMF_FW_NAME_LEN];
|
||||||
char clm_name[BRCMF_FW_NAME_LEN];
|
char clm_name[BRCMF_FW_NAME_LEN];
|
||||||
bool wowl_enabled;
|
bool wowl_enabled;
|
||||||
|
bool func1_power_manageable;
|
||||||
|
bool func2_power_manageable;
|
||||||
enum brcmf_sdiod_state state;
|
enum brcmf_sdiod_state state;
|
||||||
struct brcmf_sdiod_freezer *freezer;
|
struct brcmf_sdiod_freezer *freezer;
|
||||||
const struct firmware *clm_fw;
|
const struct firmware *clm_fw;
|
||||||
|
@ -512,15 +512,15 @@ mt7603_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|||||||
!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
|
!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
if (cmd == SET_KEY) {
|
if (cmd != SET_KEY) {
|
||||||
key->hw_key_idx = wcid->idx;
|
|
||||||
wcid->hw_key_idx = idx;
|
|
||||||
} else {
|
|
||||||
if (idx == wcid->hw_key_idx)
|
if (idx == wcid->hw_key_idx)
|
||||||
wcid->hw_key_idx = -1;
|
wcid->hw_key_idx = -1;
|
||||||
|
|
||||||
key = NULL;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
key->hw_key_idx = wcid->idx;
|
||||||
|
wcid->hw_key_idx = idx;
|
||||||
mt76_wcid_key_setup(&dev->mt76, wcid, key);
|
mt76_wcid_key_setup(&dev->mt76, wcid, key);
|
||||||
|
|
||||||
return mt7603_wtbl_set_key(dev, wcid->idx, key);
|
return mt7603_wtbl_set_key(dev, wcid->idx, key);
|
||||||
|
@ -1193,8 +1193,7 @@ EXPORT_SYMBOL_GPL(mt7615_mac_enable_rtscts);
|
|||||||
static int
|
static int
|
||||||
mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
|
mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
|
||||||
struct ieee80211_key_conf *key,
|
struct ieee80211_key_conf *key,
|
||||||
enum mt76_cipher_type cipher, u16 cipher_mask,
|
enum mt76_cipher_type cipher, u16 cipher_mask)
|
||||||
enum set_key_cmd cmd)
|
|
||||||
{
|
{
|
||||||
u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx) + 30 * 4;
|
u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx) + 30 * 4;
|
||||||
u8 data[32] = {};
|
u8 data[32] = {};
|
||||||
@ -1203,27 +1202,18 @@ mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
mt76_rr_copy(dev, addr, data, sizeof(data));
|
mt76_rr_copy(dev, addr, data, sizeof(data));
|
||||||
if (cmd == SET_KEY) {
|
if (cipher == MT_CIPHER_TKIP) {
|
||||||
if (cipher == MT_CIPHER_TKIP) {
|
/* Rx/Tx MIC keys are swapped */
|
||||||
/* Rx/Tx MIC keys are swapped */
|
memcpy(data, key->key, 16);
|
||||||
memcpy(data, key->key, 16);
|
memcpy(data + 16, key->key + 24, 8);
|
||||||
memcpy(data + 16, key->key + 24, 8);
|
memcpy(data + 24, key->key + 16, 8);
|
||||||
memcpy(data + 24, key->key + 16, 8);
|
|
||||||
} else {
|
|
||||||
if (cipher_mask == BIT(cipher))
|
|
||||||
memcpy(data, key->key, key->keylen);
|
|
||||||
else if (cipher != MT_CIPHER_BIP_CMAC_128)
|
|
||||||
memcpy(data, key->key, 16);
|
|
||||||
if (cipher == MT_CIPHER_BIP_CMAC_128)
|
|
||||||
memcpy(data + 16, key->key, 16);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
|
if (cipher_mask == BIT(cipher))
|
||||||
|
memcpy(data, key->key, key->keylen);
|
||||||
|
else if (cipher != MT_CIPHER_BIP_CMAC_128)
|
||||||
|
memcpy(data, key->key, 16);
|
||||||
if (cipher == MT_CIPHER_BIP_CMAC_128)
|
if (cipher == MT_CIPHER_BIP_CMAC_128)
|
||||||
memset(data + 16, 0, 16);
|
memcpy(data + 16, key->key, 16);
|
||||||
else if (cipher_mask)
|
|
||||||
memset(data, 0, 16);
|
|
||||||
if (!cipher_mask)
|
|
||||||
memset(data, 0, sizeof(data));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mt76_wr_copy(dev, addr, data, sizeof(data));
|
mt76_wr_copy(dev, addr, data, sizeof(data));
|
||||||
@ -1234,7 +1224,7 @@ mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
|
|||||||
static int
|
static int
|
||||||
mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid,
|
mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid,
|
||||||
enum mt76_cipher_type cipher, u16 cipher_mask,
|
enum mt76_cipher_type cipher, u16 cipher_mask,
|
||||||
int keyidx, enum set_key_cmd cmd)
|
int keyidx)
|
||||||
{
|
{
|
||||||
u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx), w0, w1;
|
u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx), w0, w1;
|
||||||
|
|
||||||
@ -1253,9 +1243,7 @@ mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid,
|
|||||||
else
|
else
|
||||||
w0 &= ~MT_WTBL_W0_RX_IK_VALID;
|
w0 &= ~MT_WTBL_W0_RX_IK_VALID;
|
||||||
|
|
||||||
if (cmd == SET_KEY &&
|
if (cipher != MT_CIPHER_BIP_CMAC_128 || cipher_mask == BIT(cipher)) {
|
||||||
(cipher != MT_CIPHER_BIP_CMAC_128 ||
|
|
||||||
cipher_mask == BIT(cipher))) {
|
|
||||||
w0 &= ~MT_WTBL_W0_KEY_IDX;
|
w0 &= ~MT_WTBL_W0_KEY_IDX;
|
||||||
w0 |= FIELD_PREP(MT_WTBL_W0_KEY_IDX, keyidx);
|
w0 |= FIELD_PREP(MT_WTBL_W0_KEY_IDX, keyidx);
|
||||||
}
|
}
|
||||||
@ -1272,19 +1260,10 @@ mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid,
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
mt7615_mac_wtbl_update_cipher(struct mt7615_dev *dev, struct mt76_wcid *wcid,
|
mt7615_mac_wtbl_update_cipher(struct mt7615_dev *dev, struct mt76_wcid *wcid,
|
||||||
enum mt76_cipher_type cipher, u16 cipher_mask,
|
enum mt76_cipher_type cipher, u16 cipher_mask)
|
||||||
enum set_key_cmd cmd)
|
|
||||||
{
|
{
|
||||||
u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx);
|
u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx);
|
||||||
|
|
||||||
if (!cipher_mask) {
|
|
||||||
mt76_clear(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cmd != SET_KEY)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (cipher == MT_CIPHER_BIP_CMAC_128 &&
|
if (cipher == MT_CIPHER_BIP_CMAC_128 &&
|
||||||
cipher_mask & ~BIT(MT_CIPHER_BIP_CMAC_128))
|
cipher_mask & ~BIT(MT_CIPHER_BIP_CMAC_128))
|
||||||
return;
|
return;
|
||||||
@ -1295,8 +1274,7 @@ mt7615_mac_wtbl_update_cipher(struct mt7615_dev *dev, struct mt76_wcid *wcid,
|
|||||||
|
|
||||||
int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
|
int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
|
||||||
struct mt76_wcid *wcid,
|
struct mt76_wcid *wcid,
|
||||||
struct ieee80211_key_conf *key,
|
struct ieee80211_key_conf *key)
|
||||||
enum set_key_cmd cmd)
|
|
||||||
{
|
{
|
||||||
enum mt76_cipher_type cipher;
|
enum mt76_cipher_type cipher;
|
||||||
u16 cipher_mask = wcid->cipher;
|
u16 cipher_mask = wcid->cipher;
|
||||||
@ -1306,19 +1284,14 @@ int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
|
|||||||
if (cipher == MT_CIPHER_NONE)
|
if (cipher == MT_CIPHER_NONE)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
if (cmd == SET_KEY)
|
cipher_mask |= BIT(cipher);
|
||||||
cipher_mask |= BIT(cipher);
|
mt7615_mac_wtbl_update_cipher(dev, wcid, cipher, cipher_mask);
|
||||||
else
|
err = mt7615_mac_wtbl_update_key(dev, wcid, key, cipher, cipher_mask);
|
||||||
cipher_mask &= ~BIT(cipher);
|
|
||||||
|
|
||||||
mt7615_mac_wtbl_update_cipher(dev, wcid, cipher, cipher_mask, cmd);
|
|
||||||
err = mt7615_mac_wtbl_update_key(dev, wcid, key, cipher, cipher_mask,
|
|
||||||
cmd);
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
err = mt7615_mac_wtbl_update_pk(dev, wcid, cipher, cipher_mask,
|
err = mt7615_mac_wtbl_update_pk(dev, wcid, cipher, cipher_mask,
|
||||||
key->keyidx, cmd);
|
key->keyidx);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
@ -1329,13 +1302,12 @@ int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
|
|||||||
|
|
||||||
int mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
|
int mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
|
||||||
struct mt76_wcid *wcid,
|
struct mt76_wcid *wcid,
|
||||||
struct ieee80211_key_conf *key,
|
struct ieee80211_key_conf *key)
|
||||||
enum set_key_cmd cmd)
|
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
spin_lock_bh(&dev->mt76.lock);
|
spin_lock_bh(&dev->mt76.lock);
|
||||||
err = __mt7615_mac_wtbl_set_key(dev, wcid, key, cmd);
|
err = __mt7615_mac_wtbl_set_key(dev, wcid, key);
|
||||||
spin_unlock_bh(&dev->mt76.lock);
|
spin_unlock_bh(&dev->mt76.lock);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
@ -391,18 +391,17 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|||||||
|
|
||||||
if (cmd == SET_KEY)
|
if (cmd == SET_KEY)
|
||||||
*wcid_keyidx = idx;
|
*wcid_keyidx = idx;
|
||||||
else if (idx == *wcid_keyidx)
|
else {
|
||||||
*wcid_keyidx = -1;
|
if (idx == *wcid_keyidx)
|
||||||
else
|
*wcid_keyidx = -1;
|
||||||
goto out;
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
mt76_wcid_key_setup(&dev->mt76, wcid,
|
mt76_wcid_key_setup(&dev->mt76, wcid, key);
|
||||||
cmd == SET_KEY ? key : NULL);
|
|
||||||
|
|
||||||
if (mt76_is_mmio(&dev->mt76))
|
if (mt76_is_mmio(&dev->mt76))
|
||||||
err = mt7615_mac_wtbl_set_key(dev, wcid, key, cmd);
|
err = mt7615_mac_wtbl_set_key(dev, wcid, key);
|
||||||
else
|
else
|
||||||
err = __mt7615_mac_wtbl_set_key(dev, wcid, key, cmd);
|
err = __mt7615_mac_wtbl_set_key(dev, wcid, key);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
mt7615_mutex_release(dev);
|
mt7615_mutex_release(dev);
|
||||||
|
@ -490,11 +490,9 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi,
|
|||||||
void mt7615_mac_set_timing(struct mt7615_phy *phy);
|
void mt7615_mac_set_timing(struct mt7615_phy *phy);
|
||||||
int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
|
int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
|
||||||
struct mt76_wcid *wcid,
|
struct mt76_wcid *wcid,
|
||||||
struct ieee80211_key_conf *key,
|
struct ieee80211_key_conf *key);
|
||||||
enum set_key_cmd cmd);
|
|
||||||
int mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
|
int mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
|
||||||
struct ieee80211_key_conf *key,
|
struct ieee80211_key_conf *key);
|
||||||
enum set_key_cmd cmd);
|
|
||||||
void mt7615_mac_reset_work(struct work_struct *work);
|
void mt7615_mac_reset_work(struct work_struct *work);
|
||||||
u32 mt7615_mac_get_sta_tid_sn(struct mt7615_dev *dev, int wcid, u8 tid);
|
u32 mt7615_mac_get_sta_tid_sn(struct mt7615_dev *dev, int wcid, u8 tid);
|
||||||
|
|
||||||
|
@ -454,20 +454,20 @@ int mt76x02_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|||||||
msta = sta ? (struct mt76x02_sta *)sta->drv_priv : NULL;
|
msta = sta ? (struct mt76x02_sta *)sta->drv_priv : NULL;
|
||||||
wcid = msta ? &msta->wcid : &mvif->group_wcid;
|
wcid = msta ? &msta->wcid : &mvif->group_wcid;
|
||||||
|
|
||||||
if (cmd == SET_KEY) {
|
if (cmd != SET_KEY) {
|
||||||
key->hw_key_idx = wcid->idx;
|
|
||||||
wcid->hw_key_idx = idx;
|
|
||||||
if (key->flags & IEEE80211_KEY_FLAG_RX_MGMT) {
|
|
||||||
key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
|
|
||||||
wcid->sw_iv = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (idx == wcid->hw_key_idx) {
|
if (idx == wcid->hw_key_idx) {
|
||||||
wcid->hw_key_idx = -1;
|
wcid->hw_key_idx = -1;
|
||||||
wcid->sw_iv = false;
|
wcid->sw_iv = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
key = NULL;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
key->hw_key_idx = wcid->idx;
|
||||||
|
wcid->hw_key_idx = idx;
|
||||||
|
if (key->flags & IEEE80211_KEY_FLAG_RX_MGMT) {
|
||||||
|
key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
|
||||||
|
wcid->sw_iv = true;
|
||||||
}
|
}
|
||||||
mt76_wcid_key_setup(&dev->mt76, wcid, key);
|
mt76_wcid_key_setup(&dev->mt76, wcid, key);
|
||||||
|
|
||||||
|
@ -410,16 +410,15 @@ static int mt7915_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|||||||
mt7915_mcu_add_bss_info(phy, vif, true);
|
mt7915_mcu_add_bss_info(phy, vif, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmd == SET_KEY)
|
if (cmd == SET_KEY) {
|
||||||
*wcid_keyidx = idx;
|
*wcid_keyidx = idx;
|
||||||
else if (idx == *wcid_keyidx)
|
} else {
|
||||||
*wcid_keyidx = -1;
|
if (idx == *wcid_keyidx)
|
||||||
else
|
*wcid_keyidx = -1;
|
||||||
goto out;
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
mt76_wcid_key_setup(&dev->mt76, wcid,
|
mt76_wcid_key_setup(&dev->mt76, wcid, key);
|
||||||
cmd == SET_KEY ? key : NULL);
|
|
||||||
|
|
||||||
err = mt76_connac_mcu_add_key(&dev->mt76, vif, &msta->bip,
|
err = mt76_connac_mcu_add_key(&dev->mt76, vif, &msta->bip,
|
||||||
key, MCU_EXT_CMD(STA_REC_UPDATE),
|
key, MCU_EXT_CMD(STA_REC_UPDATE),
|
||||||
&msta->wcid, cmd);
|
&msta->wcid, cmd);
|
||||||
|
@ -171,12 +171,12 @@ mt7921_mac_init_band(struct mt7921_dev *dev, u8 band)
|
|||||||
|
|
||||||
u8 mt7921_check_offload_capability(struct device *dev, const char *fw_wm)
|
u8 mt7921_check_offload_capability(struct device *dev, const char *fw_wm)
|
||||||
{
|
{
|
||||||
struct mt7921_fw_features *features = NULL;
|
|
||||||
const struct mt76_connac2_fw_trailer *hdr;
|
const struct mt76_connac2_fw_trailer *hdr;
|
||||||
struct mt7921_realease_info *rel_info;
|
struct mt7921_realease_info *rel_info;
|
||||||
const struct firmware *fw;
|
const struct firmware *fw;
|
||||||
int ret, i, offset = 0;
|
int ret, i, offset = 0;
|
||||||
const u8 *data, *end;
|
const u8 *data, *end;
|
||||||
|
u8 offload_caps = 0;
|
||||||
|
|
||||||
ret = request_firmware(&fw, fw_wm, dev);
|
ret = request_firmware(&fw, fw_wm, dev);
|
||||||
if (ret)
|
if (ret)
|
||||||
@ -208,7 +208,10 @@ u8 mt7921_check_offload_capability(struct device *dev, const char *fw_wm)
|
|||||||
data += sizeof(*rel_info);
|
data += sizeof(*rel_info);
|
||||||
|
|
||||||
if (rel_info->tag == MT7921_FW_TAG_FEATURE) {
|
if (rel_info->tag == MT7921_FW_TAG_FEATURE) {
|
||||||
|
struct mt7921_fw_features *features;
|
||||||
|
|
||||||
features = (struct mt7921_fw_features *)data;
|
features = (struct mt7921_fw_features *)data;
|
||||||
|
offload_caps = features->data;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,7 +221,7 @@ u8 mt7921_check_offload_capability(struct device *dev, const char *fw_wm)
|
|||||||
out:
|
out:
|
||||||
release_firmware(fw);
|
release_firmware(fw);
|
||||||
|
|
||||||
return features ? features->data : 0;
|
return offload_caps;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(mt7921_check_offload_capability);
|
EXPORT_SYMBOL_GPL(mt7921_check_offload_capability);
|
||||||
|
|
||||||
|
@ -569,16 +569,15 @@ static int mt7921_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|||||||
|
|
||||||
mt7921_mutex_acquire(dev);
|
mt7921_mutex_acquire(dev);
|
||||||
|
|
||||||
if (cmd == SET_KEY)
|
if (cmd == SET_KEY) {
|
||||||
*wcid_keyidx = idx;
|
*wcid_keyidx = idx;
|
||||||
else if (idx == *wcid_keyidx)
|
} else {
|
||||||
*wcid_keyidx = -1;
|
if (idx == *wcid_keyidx)
|
||||||
else
|
*wcid_keyidx = -1;
|
||||||
goto out;
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
mt76_wcid_key_setup(&dev->mt76, wcid,
|
mt76_wcid_key_setup(&dev->mt76, wcid, key);
|
||||||
cmd == SET_KEY ? key : NULL);
|
|
||||||
|
|
||||||
err = mt76_connac_mcu_add_key(&dev->mt76, vif, &msta->bip,
|
err = mt76_connac_mcu_add_key(&dev->mt76, vif, &msta->bip,
|
||||||
key, MCU_UNI_CMD(STA_REC_UPDATE),
|
key, MCU_UNI_CMD(STA_REC_UPDATE),
|
||||||
&msta->wcid, cmd);
|
&msta->wcid, cmd);
|
||||||
|
@ -20,7 +20,7 @@ static const struct pci_device_id mt7921_pci_device_table[] = {
|
|||||||
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x0608),
|
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x0608),
|
||||||
.driver_data = (kernel_ulong_t)MT7921_FIRMWARE_WM },
|
.driver_data = (kernel_ulong_t)MT7921_FIRMWARE_WM },
|
||||||
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x0616),
|
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x0616),
|
||||||
.driver_data = (kernel_ulong_t)MT7921_FIRMWARE_WM },
|
.driver_data = (kernel_ulong_t)MT7922_FIRMWARE_WM },
|
||||||
{ },
|
{ },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -351,16 +351,15 @@ static int mt7996_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|||||||
mt7996_mcu_add_bss_info(phy, vif, true);
|
mt7996_mcu_add_bss_info(phy, vif, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmd == SET_KEY)
|
if (cmd == SET_KEY) {
|
||||||
*wcid_keyidx = idx;
|
*wcid_keyidx = idx;
|
||||||
else if (idx == *wcid_keyidx)
|
} else {
|
||||||
*wcid_keyidx = -1;
|
if (idx == *wcid_keyidx)
|
||||||
else
|
*wcid_keyidx = -1;
|
||||||
goto out;
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
mt76_wcid_key_setup(&dev->mt76, wcid,
|
mt76_wcid_key_setup(&dev->mt76, wcid, key);
|
||||||
cmd == SET_KEY ? key : NULL);
|
|
||||||
|
|
||||||
err = mt7996_mcu_add_key(&dev->mt76, vif, &msta->bip,
|
err = mt7996_mcu_add_key(&dev->mt76, vif, &msta->bip,
|
||||||
key, MCU_WMWA_UNI_CMD(STA_REC_UPDATE),
|
key, MCU_WMWA_UNI_CMD(STA_REC_UPDATE),
|
||||||
&msta->wcid, cmd);
|
&msta->wcid, cmd);
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user