Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net

Lots of simnple overlapping additions.

With a build fix from Stephen Rothwell.

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2021-10-22 11:41:16 +01:00
commit bdfa75ad70
364 changed files with 3812 additions and 2436 deletions

@ -33,6 +33,8 @@ Al Viro <viro@zenIV.linux.org.uk>
Andi Kleen <ak@linux.intel.com> <ak@suse.de> Andi Kleen <ak@linux.intel.com> <ak@suse.de>
Andi Shyti <andi@etezian.org> <andi.shyti@samsung.com> Andi Shyti <andi@etezian.org> <andi.shyti@samsung.com>
Andreas Herrmann <aherrman@de.ibm.com> Andreas Herrmann <aherrman@de.ibm.com>
Andrej Shadura <andrew.shadura@collabora.co.uk>
Andrej Shadura <andrew@shadura.me> <andrew@beldisplaytech.com>
Andrew Morton <akpm@linux-foundation.org> Andrew Morton <akpm@linux-foundation.org>
Andrew Murray <amurray@thegoodpenguin.co.uk> <amurray@embedded-bits.co.uk> Andrew Murray <amurray@thegoodpenguin.co.uk> <amurray@embedded-bits.co.uk>
Andrew Murray <amurray@thegoodpenguin.co.uk> <andrew.murray@arm.com> Andrew Murray <amurray@thegoodpenguin.co.uk> <andrew.murray@arm.com>

@ -171,7 +171,7 @@ examples:
cs-gpios = <&gpio0 13 0>, cs-gpios = <&gpio0 13 0>,
<&gpio0 14 0>; <&gpio0 14 0>;
rx-sample-delay-ns = <3>; rx-sample-delay-ns = <3>;
spi-flash@1 { flash@1 {
compatible = "spi-nand"; compatible = "spi-nand";
reg = <1>; reg = <1>;
rx-sample-delay-ns = <7>; rx-sample-delay-ns = <7>;

@ -4,103 +4,112 @@
NTFS3 NTFS3
===== =====
Summary and Features Summary and Features
==================== ====================
NTFS3 is fully functional NTFS Read-Write driver. The driver works with NTFS3 is fully functional NTFS Read-Write driver. The driver works with NTFS
NTFS versions up to 3.1, normal/compressed/sparse files versions up to 3.1. File system type to use on mount is *ntfs3*.
and journal replaying. File system type to use on mount is 'ntfs3'.
- This driver implements NTFS read/write support for normal, sparse and - This driver implements NTFS read/write support for normal, sparse and
compressed files. compressed files.
- Supports native journal replaying; - Supports native journal replaying.
- Supports extended attributes
Predefined extended attributes:
- 'system.ntfs_security' gets/sets security
descriptor (SECURITY_DESCRIPTOR_RELATIVE)
- 'system.ntfs_attrib' gets/sets ntfs file/dir attributes.
Note: applied to empty files, this allows to switch type between
sparse(0x200), compressed(0x800) and normal;
- Supports NFS export of mounted NTFS volumes. - Supports NFS export of mounted NTFS volumes.
- Supports extended attributes. Predefined extended attributes:
- *system.ntfs_security* gets/sets security
Descriptor: SECURITY_DESCRIPTOR_RELATIVE
- *system.ntfs_attrib* gets/sets ntfs file/dir attributes.
Note: Applied to empty files, this allows to switch type between
sparse(0x200), compressed(0x800) and normal.
Mount Options Mount Options
============= =============
The list below describes mount options supported by NTFS3 driver in addition to The list below describes mount options supported by NTFS3 driver in addition to
generic ones. generic ones. You can use every mount option with **no** option. If it is in
this table marked with no it means default is without **no**.
=============================================================================== .. flat-table::
:widths: 1 5
:fill-cells:
nls=name This option informs the driver how to interpret path * - iocharset=name
strings and translate them to Unicode and back. If - This option informs the driver how to interpret path strings and
this option is not set, the default codepage will be translate them to Unicode and back. If this option is not set, the
used (CONFIG_NLS_DEFAULT). default codepage will be used (CONFIG_NLS_DEFAULT).
Examples:
'nls=utf8'
uid= Example: iocharset=utf8
gid=
umask= Controls the default permissions for files/directories created
after the NTFS volume is mounted.
fmask= * - uid=
dmask= Instead of specifying umask which applies both to - :rspan:`1`
files and directories, fmask applies only to files and * - gid=
dmask only to directories.
nohidden Files with the Windows-specific HIDDEN (FILE_ATTRIBUTE_HIDDEN) * - umask=
attribute will not be shown under Linux. - Controls the default permissions for files/directories created after
the NTFS volume is mounted.
sys_immutable Files with the Windows-specific SYSTEM * - dmask=
(FILE_ATTRIBUTE_SYSTEM) attribute will be marked as system - :rspan:`1` Instead of specifying umask which applies both to files and
immutable files. directories, fmask applies only to files and dmask only to directories.
* - fmask=
discard Enable support of the TRIM command for improved performance * - noacsrules
on delete operations, which is recommended for use with the - "No access rules" mount option sets access rights for files/folders to
solid-state drives (SSD). 777 and owner/group to root. This mount option absorbs all other
permissions.
force Forces the driver to mount partitions even if 'dirty' flag - Permissions change for files/folders will be reported as successful,
(volume dirty) is set. Not recommended for use. but they will remain 777.
sparse Create new files as "sparse". - Owner/group change will be reported as successful, butthey will stay
as root.
showmeta Use this parameter to show all meta-files (System Files) on * - nohidden
a mounted NTFS partition. - Files with the Windows-specific HIDDEN (FILE_ATTRIBUTE_HIDDEN) attribute
By default, all meta-files are hidden. will not be shown under Linux.
prealloc Preallocate space for files excessively when file size is * - sys_immutable
increasing on writes. Decreases fragmentation in case of - Files with the Windows-specific SYSTEM (FILE_ATTRIBUTE_SYSTEM) attribute
parallel write operations to different files. will be marked as system immutable files.
no_acs_rules "No access rules" mount option sets access rights for * - discard
files/folders to 777 and owner/group to root. This mount - Enable support of the TRIM command for improved performance on delete
option absorbs all other permissions: operations, which is recommended for use with the solid-state drives
- permissions change for files/folders will be reported (SSD).
as successful, but they will remain 777;
- owner/group change will be reported as successful, but
they will stay as root
acl Support POSIX ACLs (Access Control Lists). Effective if * - force
supported by Kernel. Not to be confused with NTFS ACLs. - Forces the driver to mount partitions even if volume is marked dirty.
The option specified as acl enables support for POSIX ACLs. Not recommended for use.
noatime All files and directories will not update their last access * - sparse
time attribute if a partition is mounted with this parameter. - Create new files as sparse.
This option can speed up file system operation.
=============================================================================== * - showmeta
- Use this parameter to show all meta-files (System Files) on a mounted
NTFS partition. By default, all meta-files are hidden.
ToDo list * - prealloc
- Preallocate space for files excessively when file size is increasing on
writes. Decreases fragmentation in case of parallel write operations to
different files.
* - acl
- Support POSIX ACLs (Access Control Lists). Effective if supported by
Kernel. Not to be confused with NTFS ACLs. The option specified as acl
enables support for POSIX ACLs.
Todo list
========= =========
- Full journaling support over JBD. Currently journal replaying is supported
- Full journaling support (currently journal replaying is supported) over JBD. which is not necessarily as effectice as JBD would be.
References References
========== ==========
https://www.paragon-software.com/home/ntfs-linux-professional/ - Commercial version of the NTFS driver for Linux.
- Commercial version of the NTFS driver for Linux. https://www.paragon-software.com/home/ntfs-linux-professional/
almaz.alexandrovich@paragon-software.com - Direct e-mail address for feedback and requests on the NTFS3 implementation.
- Direct e-mail address for feedback and requests on the NTFS3 implementation. almaz.alexandrovich@paragon-software.com

@ -30,10 +30,11 @@ The ``ice`` driver reports the following versions
PHY, link, etc. PHY, link, etc.
* - ``fw.mgmt.api`` * - ``fw.mgmt.api``
- running - running
- 1.5 - 1.5.1
- 2-digit version number of the API exported over the AdminQ by the - 3-digit version number (major.minor.patch) of the API exported over
management firmware. Used by the driver to identify what commands the AdminQ by the management firmware. Used by the driver to
are supported. identify what commands are supported. Historical versions of the
kernel only displayed a 2-digit version number (major.minor).
* - ``fw.mgmt.build`` * - ``fw.mgmt.build``
- running - running
- 0x305d955f - 0x305d955f

@ -59,11 +59,11 @@ specified with a ``sockaddr`` type, with a single-byte endpoint address:
}; };
struct sockaddr_mctp { struct sockaddr_mctp {
unsigned short int smctp_family; __kernel_sa_family_t smctp_family;
int smctp_network; unsigned int smctp_network;
struct mctp_addr smctp_addr; struct mctp_addr smctp_addr;
__u8 smctp_type; __u8 smctp_type;
__u8 smctp_tag; __u8 smctp_tag;
}; };
#define MCTP_NET_ANY 0x0 #define MCTP_NET_ANY 0x0

@ -18,7 +18,7 @@ types can be added after the security issue of corresponding device driver
is clarified or fixed in the future. is clarified or fixed in the future.
Create/Destroy VDUSE devices Create/Destroy VDUSE devices
------------------------ ----------------------------
VDUSE devices are created as follows: VDUSE devices are created as follows:

@ -7349,10 +7349,11 @@ F: include/uapi/linux/fpga-dfl.h
FPGA MANAGER FRAMEWORK FPGA MANAGER FRAMEWORK
M: Moritz Fischer <mdf@kernel.org> M: Moritz Fischer <mdf@kernel.org>
M: Wu Hao <hao.wu@intel.com>
M: Xu Yilun <yilun.xu@intel.com>
R: Tom Rix <trix@redhat.com> R: Tom Rix <trix@redhat.com>
L: linux-fpga@vger.kernel.org L: linux-fpga@vger.kernel.org
S: Maintained S: Maintained
W: http://www.rocketboards.org
Q: http://patchwork.kernel.org/project/linux-fpga/list/ Q: http://patchwork.kernel.org/project/linux-fpga/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mdf/linux-fpga.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/mdf/linux-fpga.git
F: Documentation/devicetree/bindings/fpga/ F: Documentation/devicetree/bindings/fpga/
@ -10285,7 +10286,6 @@ KERNEL VIRTUAL MACHINE for s390 (KVM/s390)
M: Christian Borntraeger <borntraeger@de.ibm.com> M: Christian Borntraeger <borntraeger@de.ibm.com>
M: Janosch Frank <frankja@linux.ibm.com> M: Janosch Frank <frankja@linux.ibm.com>
R: David Hildenbrand <david@redhat.com> R: David Hildenbrand <david@redhat.com>
R: Cornelia Huck <cohuck@redhat.com>
R: Claudio Imbrenda <imbrenda@linux.ibm.com> R: Claudio Imbrenda <imbrenda@linux.ibm.com>
L: kvm@vger.kernel.org L: kvm@vger.kernel.org
S: Supported S: Supported
@ -16308,6 +16308,7 @@ S390
M: Heiko Carstens <hca@linux.ibm.com> M: Heiko Carstens <hca@linux.ibm.com>
M: Vasily Gorbik <gor@linux.ibm.com> M: Vasily Gorbik <gor@linux.ibm.com>
M: Christian Borntraeger <borntraeger@de.ibm.com> M: Christian Borntraeger <borntraeger@de.ibm.com>
R: Alexander Gordeev <agordeev@linux.ibm.com>
L: linux-s390@vger.kernel.org L: linux-s390@vger.kernel.org
S: Supported S: Supported
W: http://www.ibm.com/developerworks/linux/linux390/ W: http://www.ibm.com/developerworks/linux/linux390/
@ -16386,7 +16387,6 @@ F: drivers/s390/crypto/vfio_ap_ops.c
F: drivers/s390/crypto/vfio_ap_private.h F: drivers/s390/crypto/vfio_ap_private.h
S390 VFIO-CCW DRIVER S390 VFIO-CCW DRIVER
M: Cornelia Huck <cohuck@redhat.com>
M: Eric Farman <farman@linux.ibm.com> M: Eric Farman <farman@linux.ibm.com>
M: Matthew Rosato <mjrosato@linux.ibm.com> M: Matthew Rosato <mjrosato@linux.ibm.com>
R: Halil Pasic <pasic@linux.ibm.com> R: Halil Pasic <pasic@linux.ibm.com>
@ -17993,7 +17993,7 @@ F: net/switchdev/
SY8106A REGULATOR DRIVER SY8106A REGULATOR DRIVER
M: Icenowy Zheng <icenowy@aosc.io> M: Icenowy Zheng <icenowy@aosc.io>
S: Maintained S: Maintained
F: Documentation/devicetree/bindings/regulator/sy8106a-regulator.txt F: Documentation/devicetree/bindings/regulator/silergy,sy8106a.yaml
F: drivers/regulator/sy8106a-regulator.c F: drivers/regulator/sy8106a-regulator.c
SYNC FILE FRAMEWORK SYNC FILE FRAMEWORK

@ -2,7 +2,7 @@
VERSION = 5 VERSION = 5
PATCHLEVEL = 15 PATCHLEVEL = 15
SUBLEVEL = 0 SUBLEVEL = 0
EXTRAVERSION = -rc5 EXTRAVERSION = -rc6
NAME = Opossums on Parade NAME = Opossums on Parade
# *DOCUMENTATION* # *DOCUMENTATION*

@ -26,11 +26,6 @@ extern char empty_zero_page[PAGE_SIZE];
extern pgd_t swapper_pg_dir[] __aligned(PAGE_SIZE); extern pgd_t swapper_pg_dir[] __aligned(PAGE_SIZE);
/* Macro to mark a page protection as uncacheable */
#define pgprot_noncached(prot) (__pgprot(pgprot_val(prot) & ~_PAGE_CACHEABLE))
extern pgd_t swapper_pg_dir[] __aligned(PAGE_SIZE);
/* to cope with aliasing VIPT cache */ /* to cope with aliasing VIPT cache */
#define HAVE_ARCH_UNMAPPED_AREA #define HAVE_ARCH_UNMAPPED_AREA

@ -40,8 +40,8 @@ sd_io_1v8_reg: sd_io_1v8_reg {
regulator-always-on; regulator-always-on;
regulator-settling-time-us = <5000>; regulator-settling-time-us = <5000>;
gpios = <&expgpio 4 GPIO_ACTIVE_HIGH>; gpios = <&expgpio 4 GPIO_ACTIVE_HIGH>;
states = <1800000 0x1 states = <1800000 0x1>,
3300000 0x0>; <3300000 0x0>;
status = "okay"; status = "okay";
}; };
@ -217,15 +217,16 @@ phy1: ethernet-phy@1 {
}; };
&pcie0 { &pcie0 {
pci@1,0 { pci@0,0 {
device_type = "pci";
#address-cells = <3>; #address-cells = <3>;
#size-cells = <2>; #size-cells = <2>;
ranges; ranges;
reg = <0 0 0 0 0>; reg = <0 0 0 0 0>;
usb@1,0 { usb@0,0 {
reg = <0x10000 0 0 0 0>; reg = <0 0 0 0 0>;
resets = <&reset RASPBERRYPI_FIRMWARE_RESET_ID_USB>; resets = <&reset RASPBERRYPI_FIRMWARE_RESET_ID_USB>;
}; };
}; };

@ -300,6 +300,14 @@ pixelvalve3: pixelvalve@7ec12000 {
status = "disabled"; status = "disabled";
}; };
vec: vec@7ec13000 {
compatible = "brcm,bcm2711-vec";
reg = <0x7ec13000 0x1000>;
clocks = <&clocks BCM2835_CLOCK_VEC>;
interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
};
dvp: clock@7ef00000 { dvp: clock@7ef00000 {
compatible = "brcm,brcm2711-dvp"; compatible = "brcm,brcm2711-dvp";
reg = <0x7ef00000 0x10>; reg = <0x7ef00000 0x10>;
@ -532,8 +540,8 @@ genet_mdio: mdio@e14 {
compatible = "brcm,genet-mdio-v5"; compatible = "brcm,genet-mdio-v5";
reg = <0xe14 0x8>; reg = <0xe14 0x8>;
reg-names = "mdio"; reg-names = "mdio";
#address-cells = <0x0>; #address-cells = <0x1>;
#size-cells = <0x1>; #size-cells = <0x0>;
}; };
}; };
}; };

@ -106,6 +106,14 @@ i2c2: i2c@7e805000 {
status = "okay"; status = "okay";
}; };
vec: vec@7e806000 {
compatible = "brcm,bcm2835-vec";
reg = <0x7e806000 0x1000>;
clocks = <&clocks BCM2835_CLOCK_VEC>;
interrupts = <2 27>;
status = "disabled";
};
pixelvalve@7e807000 { pixelvalve@7e807000 {
compatible = "brcm,bcm2835-pixelvalve2"; compatible = "brcm,bcm2835-pixelvalve2";
reg = <0x7e807000 0x100>; reg = <0x7e807000 0x100>;

@ -464,14 +464,6 @@ i2c1: i2c@7e804000 {
status = "disabled"; status = "disabled";
}; };
vec: vec@7e806000 {
compatible = "brcm,bcm2835-vec";
reg = <0x7e806000 0x1000>;
clocks = <&clocks BCM2835_CLOCK_VEC>;
interrupts = <2 27>;
status = "disabled";
};
usb: usb@7e980000 { usb: usb@7e980000 {
compatible = "brcm,bcm2835-usb"; compatible = "brcm,bcm2835-usb";
reg = <0x7e980000 0x10000>; reg = <0x7e980000 0x10000>;

@ -197,7 +197,6 @@ CONFIG_PCI_EPF_TEST=m
CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y CONFIG_DEVTMPFS_MOUNT=y
CONFIG_OMAP_OCP2SCP=y CONFIG_OMAP_OCP2SCP=y
CONFIG_SIMPLE_PM_BUS=y
CONFIG_MTD=y CONFIG_MTD=y
CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_BLOCK=y CONFIG_MTD_BLOCK=y

@ -46,7 +46,6 @@ CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y CONFIG_DEVTMPFS_MOUNT=y
CONFIG_DMA_CMA=y CONFIG_DMA_CMA=y
CONFIG_CMA_SIZE_MBYTES=64 CONFIG_CMA_SIZE_MBYTES=64
CONFIG_SIMPLE_PM_BUS=y
CONFIG_MTD=y CONFIG_MTD=y
CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_BLOCK=y CONFIG_MTD_BLOCK=y

@ -40,7 +40,6 @@ CONFIG_PCI_RCAR_GEN2=y
CONFIG_PCIE_RCAR_HOST=y CONFIG_PCIE_RCAR_HOST=y
CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y CONFIG_DEVTMPFS_MOUNT=y
CONFIG_SIMPLE_PM_BUS=y
CONFIG_MTD=y CONFIG_MTD=y
CONFIG_MTD_BLOCK=y CONFIG_MTD_BLOCK=y
CONFIG_MTD_CFI=y CONFIG_MTD_CFI=y

@ -9,6 +9,7 @@
#include <linux/iopoll.h> #include <linux/iopoll.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/reset-controller.h> #include <linux/reset-controller.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <asm/smp_plat.h> #include <asm/smp_plat.h>
@ -81,11 +82,6 @@ static const struct reset_control_ops imx_src_ops = {
.reset = imx_src_reset_module, .reset = imx_src_reset_module,
}; };
static struct reset_controller_dev imx_reset_controller = {
.ops = &imx_src_ops,
.nr_resets = ARRAY_SIZE(sw_reset_bits),
};
static void imx_gpcv2_set_m_core_pgc(bool enable, u32 offset) static void imx_gpcv2_set_m_core_pgc(bool enable, u32 offset)
{ {
writel_relaxed(enable, gpc_base + offset); writel_relaxed(enable, gpc_base + offset);
@ -177,10 +173,6 @@ void __init imx_src_init(void)
src_base = of_iomap(np, 0); src_base = of_iomap(np, 0);
WARN_ON(!src_base); WARN_ON(!src_base);
imx_reset_controller.of_node = np;
if (IS_ENABLED(CONFIG_RESET_CONTROLLER))
reset_controller_register(&imx_reset_controller);
/* /*
* force warm reset sources to generate cold reset * force warm reset sources to generate cold reset
* for a more reliable restart * for a more reliable restart
@ -214,3 +206,33 @@ void __init imx7_src_init(void)
if (!gpc_base) if (!gpc_base)
return; return;
} }
static const struct of_device_id imx_src_dt_ids[] = {
{ .compatible = "fsl,imx51-src" },
{ /* sentinel */ }
};
static int imx_src_probe(struct platform_device *pdev)
{
struct reset_controller_dev *rcdev;
rcdev = devm_kzalloc(&pdev->dev, sizeof(*rcdev), GFP_KERNEL);
if (!rcdev)
return -ENOMEM;
rcdev->ops = &imx_src_ops;
rcdev->dev = &pdev->dev;
rcdev->of_node = pdev->dev.of_node;
rcdev->nr_resets = ARRAY_SIZE(sw_reset_bits);
return devm_reset_controller_register(&pdev->dev, rcdev);
}
static struct platform_driver imx_src_driver = {
.driver = {
.name = "imx-src",
.of_match_table = imx_src_dt_ids,
},
.probe = imx_src_probe,
};
builtin_platform_driver(imx_src_driver);

@ -112,7 +112,6 @@ config ARCH_OMAP2PLUS
select PM_GENERIC_DOMAINS select PM_GENERIC_DOMAINS
select PM_GENERIC_DOMAINS_OF select PM_GENERIC_DOMAINS_OF
select RESET_CONTROLLER select RESET_CONTROLLER
select SIMPLE_PM_BUS
select SOC_BUS select SOC_BUS
select TI_SYSC select TI_SYSC
select OMAP_IRQCHIP select OMAP_IRQCHIP

@ -245,7 +245,6 @@ CONFIG_DEVTMPFS_MOUNT=y
CONFIG_FW_LOADER_USER_HELPER=y CONFIG_FW_LOADER_USER_HELPER=y
CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
CONFIG_HISILICON_LPC=y CONFIG_HISILICON_LPC=y
CONFIG_SIMPLE_PM_BUS=y
CONFIG_FSL_MC_BUS=y CONFIG_FSL_MC_BUS=y
CONFIG_TEGRA_ACONNECT=m CONFIG_TEGRA_ACONNECT=m
CONFIG_GNSS=m CONFIG_GNSS=m

@ -24,6 +24,7 @@ struct hyp_pool {
/* Allocation */ /* Allocation */
void *hyp_alloc_pages(struct hyp_pool *pool, unsigned short order); void *hyp_alloc_pages(struct hyp_pool *pool, unsigned short order);
void hyp_split_page(struct hyp_page *page);
void hyp_get_page(struct hyp_pool *pool, void *addr); void hyp_get_page(struct hyp_pool *pool, void *addr);
void hyp_put_page(struct hyp_pool *pool, void *addr); void hyp_put_page(struct hyp_pool *pool, void *addr);

@ -35,7 +35,18 @@ const u8 pkvm_hyp_id = 1;
static void *host_s2_zalloc_pages_exact(size_t size) static void *host_s2_zalloc_pages_exact(size_t size)
{ {
return hyp_alloc_pages(&host_s2_pool, get_order(size)); void *addr = hyp_alloc_pages(&host_s2_pool, get_order(size));
hyp_split_page(hyp_virt_to_page(addr));
/*
* The size of concatenated PGDs is always a power of two of PAGE_SIZE,
* so there should be no need to free any of the tail pages to make the
* allocation exact.
*/
WARN_ON(size != (PAGE_SIZE << get_order(size)));
return addr;
} }
static void *host_s2_zalloc_page(void *pool) static void *host_s2_zalloc_page(void *pool)

@ -152,6 +152,7 @@ static inline void hyp_page_ref_inc(struct hyp_page *p)
static inline int hyp_page_ref_dec_and_test(struct hyp_page *p) static inline int hyp_page_ref_dec_and_test(struct hyp_page *p)
{ {
BUG_ON(!p->refcount);
p->refcount--; p->refcount--;
return (p->refcount == 0); return (p->refcount == 0);
} }
@ -193,6 +194,20 @@ void hyp_get_page(struct hyp_pool *pool, void *addr)
hyp_spin_unlock(&pool->lock); hyp_spin_unlock(&pool->lock);
} }
void hyp_split_page(struct hyp_page *p)
{
unsigned short order = p->order;
unsigned int i;
p->order = 0;
for (i = 1; i < (1 << order); i++) {
struct hyp_page *tail = p + i;
tail->order = 0;
hyp_set_page_refcounted(tail);
}
}
void *hyp_alloc_pages(struct hyp_pool *pool, unsigned short order) void *hyp_alloc_pages(struct hyp_pool *pool, unsigned short order)
{ {
unsigned short i = order; unsigned short i = order;

@ -1529,8 +1529,10 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
* when updating the PG_mte_tagged page flag, see * when updating the PG_mte_tagged page flag, see
* sanitise_mte_tags for more details. * sanitise_mte_tags for more details.
*/ */
if (kvm_has_mte(kvm) && vma->vm_flags & VM_SHARED) if (kvm_has_mte(kvm) && vma->vm_flags & VM_SHARED) {
return -EINVAL; ret = -EINVAL;
break;
}
if (vma->vm_flags & VM_PFNMAP) { if (vma->vm_flags & VM_PFNMAP) {
/* IO region dirty page logging not allowed */ /* IO region dirty page logging not allowed */

@ -8,7 +8,7 @@ config CSKY
select ARCH_HAS_SYNC_DMA_FOR_DEVICE select ARCH_HAS_SYNC_DMA_FOR_DEVICE
select ARCH_USE_BUILTIN_BSWAP select ARCH_USE_BUILTIN_BSWAP
select ARCH_USE_QUEUED_RWLOCKS select ARCH_USE_QUEUED_RWLOCKS
select ARCH_WANT_FRAME_POINTERS if !CPU_CK610 select ARCH_WANT_FRAME_POINTERS if !CPU_CK610 && $(cc-option,-mbacktrace)
select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT
select COMMON_CLK select COMMON_CLK
select CLKSRC_MMIO select CLKSRC_MMIO
@ -241,6 +241,7 @@ endchoice
menuconfig HAVE_TCM menuconfig HAVE_TCM
bool "Tightly-Coupled/Sram Memory" bool "Tightly-Coupled/Sram Memory"
depends on !COMPILE_TEST
help help
The implementation are not only used by TCM (Tightly-Coupled Meory) The implementation are not only used by TCM (Tightly-Coupled Meory)
but also used by sram on SOC bus. It follow existed linux tcm but also used by sram on SOC bus. It follow existed linux tcm

@ -74,7 +74,6 @@ static __always_inline unsigned long __fls(unsigned long x)
* bug fix, why only could use atomic!!!! * bug fix, why only could use atomic!!!!
*/ */
#include <asm-generic/bitops/non-atomic.h> #include <asm-generic/bitops/non-atomic.h>
#define __clear_bit(nr, vaddr) clear_bit(nr, vaddr)
#include <asm-generic/bitops/le.h> #include <asm-generic/bitops/le.h>
#include <asm-generic/bitops/ext2-atomic.h> #include <asm-generic/bitops/ext2-atomic.h>

@ -99,7 +99,8 @@ static int gpr_set(struct task_struct *target,
if (ret) if (ret)
return ret; return ret;
regs.sr = task_pt_regs(target)->sr; /* BIT(0) of regs.sr is Condition Code/Carry bit */
regs.sr = (regs.sr & BIT(0)) | (task_pt_regs(target)->sr & ~BIT(0));
#ifdef CONFIG_CPU_HAS_HILO #ifdef CONFIG_CPU_HAS_HILO
regs.dcsr = task_pt_regs(target)->dcsr; regs.dcsr = task_pt_regs(target)->dcsr;
#endif #endif

@ -52,10 +52,14 @@ static long restore_sigcontext(struct pt_regs *regs,
struct sigcontext __user *sc) struct sigcontext __user *sc)
{ {
int err = 0; int err = 0;
unsigned long sr = regs->sr;
/* sc_pt_regs is structured the same as the start of pt_regs */ /* sc_pt_regs is structured the same as the start of pt_regs */
err |= __copy_from_user(regs, &sc->sc_pt_regs, sizeof(struct pt_regs)); err |= __copy_from_user(regs, &sc->sc_pt_regs, sizeof(struct pt_regs));
/* BIT(0) of regs->sr is Condition Code/Carry bit */
regs->sr = (sr & ~1) | (regs->sr & 1);
/* Restore the floating-point state. */ /* Restore the floating-point state. */
err |= restore_fpu_state(sc); err |= restore_fpu_state(sc);

@ -9,7 +9,7 @@
static inline unsigned long arch_local_save_flags(void) static inline unsigned long arch_local_save_flags(void)
{ {
return RDCTL(CTL_STATUS); return RDCTL(CTL_FSTATUS);
} }
/* /*
@ -18,7 +18,7 @@ static inline unsigned long arch_local_save_flags(void)
*/ */
static inline void arch_local_irq_restore(unsigned long flags) static inline void arch_local_irq_restore(unsigned long flags)
{ {
WRCTL(CTL_STATUS, flags); WRCTL(CTL_FSTATUS, flags);
} }
static inline void arch_local_irq_disable(void) static inline void arch_local_irq_disable(void)

@ -11,7 +11,7 @@
#endif #endif
/* control register numbers */ /* control register numbers */
#define CTL_STATUS 0 #define CTL_FSTATUS 0
#define CTL_ESTATUS 1 #define CTL_ESTATUS 1
#define CTL_BSTATUS 2 #define CTL_BSTATUS 2
#define CTL_IENABLE 3 #define CTL_IENABLE 3

@ -126,14 +126,16 @@ _GLOBAL(idle_return_gpr_loss)
/* /*
* This is the sequence required to execute idle instructions, as * This is the sequence required to execute idle instructions, as
* specified in ISA v2.07 (and earlier). MSR[IR] and MSR[DR] must be 0. * specified in ISA v2.07 (and earlier). MSR[IR] and MSR[DR] must be 0.
* * We have to store a GPR somewhere, ptesync, then reload it, and create
* The 0(r1) slot is used to save r2 in isa206, so use that here. * a false dependency on the result of the load. It doesn't matter which
* GPR we store, or where we store it. We have already stored r2 to the
* stack at -8(r1) in isa206_idle_insn_mayloss, so use that.
*/ */
#define IDLE_STATE_ENTER_SEQ_NORET(IDLE_INST) \ #define IDLE_STATE_ENTER_SEQ_NORET(IDLE_INST) \
/* Magic NAP/SLEEP/WINKLE mode enter sequence */ \ /* Magic NAP/SLEEP/WINKLE mode enter sequence */ \
std r2,0(r1); \ std r2,-8(r1); \
ptesync; \ ptesync; \
ld r2,0(r1); \ ld r2,-8(r1); \
236: cmpd cr0,r2,r2; \ 236: cmpd cr0,r2,r2; \
bne 236b; \ bne 236b; \
IDLE_INST; \ IDLE_INST; \

@ -1730,8 +1730,6 @@ void __cpu_die(unsigned int cpu)
void arch_cpu_idle_dead(void) void arch_cpu_idle_dead(void)
{ {
sched_preempt_enable_no_resched();
/* /*
* Disable on the down path. This will be re-enabled by * Disable on the down path. This will be re-enabled by
* start_secondary() via start_secondary_resume() below * start_secondary() via start_secondary_resume() below

@ -255,13 +255,16 @@ kvm_novcpu_exit:
* r3 contains the SRR1 wakeup value, SRR1 is trashed. * r3 contains the SRR1 wakeup value, SRR1 is trashed.
*/ */
_GLOBAL(idle_kvm_start_guest) _GLOBAL(idle_kvm_start_guest)
ld r4,PACAEMERGSP(r13)
mfcr r5 mfcr r5
mflr r0 mflr r0
std r1,0(r4) std r5, 8(r1) // Save CR in caller's frame
std r5,8(r4) std r0, 16(r1) // Save LR in caller's frame
std r0,16(r4) // Create frame on emergency stack
subi r1,r4,STACK_FRAME_OVERHEAD ld r4, PACAEMERGSP(r13)
stdu r1, -SWITCH_FRAME_SIZE(r4)
// Switch to new frame on emergency stack
mr r1, r4
std r3, 32(r1) // Save SRR1 wakeup value
SAVE_NVGPRS(r1) SAVE_NVGPRS(r1)
/* /*
@ -313,6 +316,10 @@ kvm_unsplit_wakeup:
kvm_secondary_got_guest: kvm_secondary_got_guest:
// About to go to guest, clear saved SRR1
li r0, 0
std r0, 32(r1)
/* Set HSTATE_DSCR(r13) to something sensible */ /* Set HSTATE_DSCR(r13) to something sensible */
ld r6, PACA_DSCR_DEFAULT(r13) ld r6, PACA_DSCR_DEFAULT(r13)
std r6, HSTATE_DSCR(r13) std r6, HSTATE_DSCR(r13)
@ -392,13 +399,12 @@ kvm_no_guest:
mfspr r4, SPRN_LPCR mfspr r4, SPRN_LPCR
rlwimi r4, r3, 0, LPCR_PECE0 | LPCR_PECE1 rlwimi r4, r3, 0, LPCR_PECE0 | LPCR_PECE1
mtspr SPRN_LPCR, r4 mtspr SPRN_LPCR, r4
/* set up r3 for return */ // Return SRR1 wakeup value, or 0 if we went into the guest
mfspr r3,SPRN_SRR1 ld r3, 32(r1)
REST_NVGPRS(r1) REST_NVGPRS(r1)
addi r1, r1, STACK_FRAME_OVERHEAD ld r1, 0(r1) // Switch back to caller stack
ld r0, 16(r1) ld r0, 16(r1) // Reload LR
ld r5, 8(r1) ld r5, 8(r1) // Reload CR
ld r1, 0(r1)
mtlr r0 mtlr r0
mtcr r5 mtcr r5
blr blr

@ -945,7 +945,8 @@ static int xive_get_irqchip_state(struct irq_data *data,
* interrupt to be inactive in that case. * interrupt to be inactive in that case.
*/ */
*state = (pq != XIVE_ESB_INVALID) && !xd->stale_p && *state = (pq != XIVE_ESB_INVALID) && !xd->stale_p &&
(xd->saved_p || !!(pq & XIVE_ESB_VAL_P)); (xd->saved_p || (!!(pq & XIVE_ESB_VAL_P) &&
!irqd_irq_disabled(data)));
return 0; return 0;
default: default:
return -EINVAL; return -EINVAL;

@ -894,6 +894,11 @@ int access_guest_real(struct kvm_vcpu *vcpu, unsigned long gra,
/** /**
* guest_translate_address - translate guest logical into guest absolute address * guest_translate_address - translate guest logical into guest absolute address
* @vcpu: virtual cpu
* @gva: Guest virtual address
* @ar: Access register
* @gpa: Guest physical address
* @mode: Translation access mode
* *
* Parameter semantics are the same as the ones from guest_translate. * Parameter semantics are the same as the ones from guest_translate.
* The memory contents at the guest address are not changed. * The memory contents at the guest address are not changed.
@ -934,6 +939,11 @@ int guest_translate_address(struct kvm_vcpu *vcpu, unsigned long gva, u8 ar,
/** /**
* check_gva_range - test a range of guest virtual addresses for accessibility * check_gva_range - test a range of guest virtual addresses for accessibility
* @vcpu: virtual cpu
* @gva: Guest virtual address
* @ar: Access register
* @length: Length of test range
* @mode: Translation access mode
*/ */
int check_gva_range(struct kvm_vcpu *vcpu, unsigned long gva, u8 ar, int check_gva_range(struct kvm_vcpu *vcpu, unsigned long gva, u8 ar,
unsigned long length, enum gacc_mode mode) unsigned long length, enum gacc_mode mode)
@ -956,6 +966,7 @@ int check_gva_range(struct kvm_vcpu *vcpu, unsigned long gva, u8 ar,
/** /**
* kvm_s390_check_low_addr_prot_real - check for low-address protection * kvm_s390_check_low_addr_prot_real - check for low-address protection
* @vcpu: virtual cpu
* @gra: Guest real address * @gra: Guest real address
* *
* Checks whether an address is subject to low-address protection and set * Checks whether an address is subject to low-address protection and set
@ -979,6 +990,7 @@ int kvm_s390_check_low_addr_prot_real(struct kvm_vcpu *vcpu, unsigned long gra)
* @pgt: pointer to the beginning of the page table for the given address if * @pgt: pointer to the beginning of the page table for the given address if
* successful (return value 0), or to the first invalid DAT entry in * successful (return value 0), or to the first invalid DAT entry in
* case of exceptions (return value > 0) * case of exceptions (return value > 0)
* @dat_protection: referenced memory is write protected
* @fake: pgt references contiguous guest memory block, not a pgtable * @fake: pgt references contiguous guest memory block, not a pgtable
*/ */
static int kvm_s390_shadow_tables(struct gmap *sg, unsigned long saddr, static int kvm_s390_shadow_tables(struct gmap *sg, unsigned long saddr,

@ -269,6 +269,7 @@ 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
* *
* This interception only occurs if the CPUSTAT_EXT_INT bit was set, or if * This interception only occurs if the CPUSTAT_EXT_INT bit was set, or if
* the new PSW does not have external interrupts disabled. In the first case, * the new PSW does not have external interrupts disabled. In the first case,
@ -315,7 +316,8 @@ static int handle_external_interrupt(struct kvm_vcpu *vcpu)
} }
/** /**
* Handle MOVE PAGE partial execution interception. * handle_mvpg_pei - Handle MOVE PAGE partial execution interception.
* @vcpu: virtual cpu
* *
* This interception can only happen for guests with DAT disabled and * This interception can only happen for guests with DAT disabled and
* addresses that are currently not mapped in the host. Thus we try to * addresses that are currently not mapped in the host. Thus we try to

@ -259,14 +259,13 @@ EXPORT_SYMBOL(strcmp);
#ifdef __HAVE_ARCH_STRRCHR #ifdef __HAVE_ARCH_STRRCHR
char *strrchr(const char *s, int c) char *strrchr(const char *s, int c)
{ {
size_t len = __strend(s) - s; ssize_t len = __strend(s) - s;
if (len) do {
do { if (s[len] == (char)c)
if (s[len] == (char) c) return (char *)s + len;
return (char *) s + len; } while (--len >= 0);
} while (--len > 0); return NULL;
return NULL;
} }
EXPORT_SYMBOL(strrchr); EXPORT_SYMBOL(strrchr);
#endif #endif

@ -1525,7 +1525,6 @@ config AMD_MEM_ENCRYPT
config AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT config AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT
bool "Activate AMD Secure Memory Encryption (SME) by default" bool "Activate AMD Secure Memory Encryption (SME) by default"
default y
depends on AMD_MEM_ENCRYPT depends on AMD_MEM_ENCRYPT
help help
Say yes to have system memory encrypted by default if running on Say yes to have system memory encrypted by default if running on

@ -68,6 +68,7 @@ static bool test_intel(int idx, void *data)
case INTEL_FAM6_BROADWELL_D: case INTEL_FAM6_BROADWELL_D:
case INTEL_FAM6_BROADWELL_G: case INTEL_FAM6_BROADWELL_G:
case INTEL_FAM6_BROADWELL_X: case INTEL_FAM6_BROADWELL_X:
case INTEL_FAM6_SAPPHIRERAPIDS_X:
case INTEL_FAM6_ATOM_SILVERMONT: case INTEL_FAM6_ATOM_SILVERMONT:
case INTEL_FAM6_ATOM_SILVERMONT_D: case INTEL_FAM6_ATOM_SILVERMONT_D:

@ -385,7 +385,7 @@ static int __fpu_restore_sig(void __user *buf, void __user *buf_fx,
return -EINVAL; return -EINVAL;
} else { } else {
/* Mask invalid bits out for historical reasons (broken hardware). */ /* Mask invalid bits out for historical reasons (broken hardware). */
fpu->state.fxsave.mxcsr &= ~mxcsr_feature_mask; fpu->state.fxsave.mxcsr &= mxcsr_feature_mask;
} }
/* Enforce XFEATURE_MASK_FPSSE when XSAVE is enabled */ /* Enforce XFEATURE_MASK_FPSSE when XSAVE is enabled */

@ -2321,13 +2321,14 @@ EXPORT_SYMBOL_GPL(kvm_apic_update_apicv);
void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event) void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event)
{ {
struct kvm_lapic *apic = vcpu->arch.apic; struct kvm_lapic *apic = vcpu->arch.apic;
u64 msr_val;
int i; int i;
if (!init_event) { if (!init_event) {
vcpu->arch.apic_base = APIC_DEFAULT_PHYS_BASE | msr_val = APIC_DEFAULT_PHYS_BASE | MSR_IA32_APICBASE_ENABLE;
MSR_IA32_APICBASE_ENABLE;
if (kvm_vcpu_is_reset_bsp(vcpu)) if (kvm_vcpu_is_reset_bsp(vcpu))
vcpu->arch.apic_base |= MSR_IA32_APICBASE_BSP; msr_val |= MSR_IA32_APICBASE_BSP;
kvm_lapic_set_base(vcpu, msr_val);
} }
if (!apic) if (!apic)
@ -2336,11 +2337,9 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event)
/* Stop the timer in case it's a reset to an active apic */ /* Stop the timer in case it's a reset to an active apic */
hrtimer_cancel(&apic->lapic_timer.timer); hrtimer_cancel(&apic->lapic_timer.timer);
if (!init_event) { /* The xAPIC ID is set at RESET even if the APIC was already enabled. */
apic->base_address = APIC_DEFAULT_PHYS_BASE; if (!init_event)
kvm_apic_set_xapic_id(apic, vcpu->vcpu_id); kvm_apic_set_xapic_id(apic, vcpu->vcpu_id);
}
kvm_apic_set_version(apic->vcpu); kvm_apic_set_version(apic->vcpu);
for (i = 0; i < KVM_APIC_LVT_NUM; i++) for (i = 0; i < KVM_APIC_LVT_NUM; i++)
@ -2481,6 +2480,11 @@ int kvm_create_lapic(struct kvm_vcpu *vcpu, int timer_advance_ns)
lapic_timer_advance_dynamic = false; lapic_timer_advance_dynamic = false;
} }
/*
* Stuff the APIC ENABLE bit in lieu of temporarily incrementing
* apic_hw_disabled; the full RESET value is set by kvm_lapic_reset().
*/
vcpu->arch.apic_base = MSR_IA32_APICBASE_ENABLE;
static_branch_inc(&apic_sw_disabled.key); /* sw disabled at reset */ static_branch_inc(&apic_sw_disabled.key); /* sw disabled at reset */
kvm_iodevice_init(&apic->dev, &apic_mmio_ops); kvm_iodevice_init(&apic->dev, &apic_mmio_ops);
@ -2942,5 +2946,7 @@ int kvm_apic_accept_events(struct kvm_vcpu *vcpu)
void kvm_lapic_exit(void) void kvm_lapic_exit(void)
{ {
static_key_deferred_flush(&apic_hw_disabled); static_key_deferred_flush(&apic_hw_disabled);
WARN_ON(static_branch_unlikely(&apic_hw_disabled.key));
static_key_deferred_flush(&apic_sw_disabled); static_key_deferred_flush(&apic_sw_disabled);
WARN_ON(static_branch_unlikely(&apic_sw_disabled.key));
} }

@ -618,7 +618,12 @@ static int __sev_launch_update_vmsa(struct kvm *kvm, struct kvm_vcpu *vcpu,
vmsa.handle = to_kvm_svm(kvm)->sev_info.handle; vmsa.handle = to_kvm_svm(kvm)->sev_info.handle;
vmsa.address = __sme_pa(svm->vmsa); vmsa.address = __sme_pa(svm->vmsa);
vmsa.len = PAGE_SIZE; vmsa.len = PAGE_SIZE;
return sev_issue_cmd(kvm, SEV_CMD_LAUNCH_UPDATE_VMSA, &vmsa, error); ret = sev_issue_cmd(kvm, SEV_CMD_LAUNCH_UPDATE_VMSA, &vmsa, error);
if (ret)
return ret;
vcpu->arch.guest_state_protected = true;
return 0;
} }
static int sev_launch_update_vmsa(struct kvm *kvm, struct kvm_sev_cmd *argp) static int sev_launch_update_vmsa(struct kvm *kvm, struct kvm_sev_cmd *argp)
@ -2583,7 +2588,7 @@ int sev_es_string_io(struct vcpu_svm *svm, int size, unsigned int port, int in)
return -EINVAL; return -EINVAL;
return kvm_sev_es_string_io(&svm->vcpu, size, port, return kvm_sev_es_string_io(&svm->vcpu, size, port,
svm->ghcb_sa, svm->ghcb_sa_len, in); svm->ghcb_sa, svm->ghcb_sa_len / size, in);
} }
void sev_es_init_vmcb(struct vcpu_svm *svm) void sev_es_init_vmcb(struct vcpu_svm *svm)

@ -191,7 +191,7 @@ struct vcpu_svm {
/* SEV-ES scratch area support */ /* SEV-ES scratch area support */
void *ghcb_sa; void *ghcb_sa;
u64 ghcb_sa_len; u32 ghcb_sa_len;
bool ghcb_sa_sync; bool ghcb_sa_sync;
bool ghcb_sa_free; bool ghcb_sa_free;

@ -5562,9 +5562,13 @@ static int handle_encls(struct kvm_vcpu *vcpu)
static int handle_bus_lock_vmexit(struct kvm_vcpu *vcpu) static int handle_bus_lock_vmexit(struct kvm_vcpu *vcpu)
{ {
vcpu->run->exit_reason = KVM_EXIT_X86_BUS_LOCK; /*
vcpu->run->flags |= KVM_RUN_X86_BUS_LOCK; * Hardware may or may not set the BUS_LOCK_DETECTED flag on BUS_LOCK
return 0; * VM-Exits. Unconditionally set the flag here and leave the handling to
* vmx_handle_exit().
*/
to_vmx(vcpu)->exit_reason.bus_lock_detected = true;
return 1;
} }
/* /*
@ -6051,9 +6055,8 @@ static int vmx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath)
int ret = __vmx_handle_exit(vcpu, exit_fastpath); int ret = __vmx_handle_exit(vcpu, exit_fastpath);
/* /*
* Even when current exit reason is handled by KVM internally, we * Exit to user space when bus lock detected to inform that there is
* still need to exit to user space when bus lock detected to inform * a bus lock in guest.
* that there is a bus lock in guest.
*/ */
if (to_vmx(vcpu)->exit_reason.bus_lock_detected) { if (to_vmx(vcpu)->exit_reason.bus_lock_detected) {
if (ret > 0) if (ret > 0)

@ -11392,7 +11392,8 @@ static int memslot_rmap_alloc(struct kvm_memory_slot *slot,
int level = i + 1; int level = i + 1;
int lpages = __kvm_mmu_slot_lpages(slot, npages, level); int lpages = __kvm_mmu_slot_lpages(slot, npages, level);
WARN_ON(slot->arch.rmap[i]); if (slot->arch.rmap[i])
continue;
slot->arch.rmap[i] = kvcalloc(lpages, sz, GFP_KERNEL_ACCOUNT); slot->arch.rmap[i] = kvcalloc(lpages, sz, GFP_KERNEL_ACCOUNT);
if (!slot->arch.rmap[i]) { if (!slot->arch.rmap[i]) {

@ -666,6 +666,12 @@ void bfq_bfqq_move(struct bfq_data *bfqd, struct bfq_queue *bfqq,
bfq_put_idle_entity(bfq_entity_service_tree(entity), entity); bfq_put_idle_entity(bfq_entity_service_tree(entity), entity);
bfqg_and_blkg_put(bfqq_group(bfqq)); bfqg_and_blkg_put(bfqq_group(bfqq));
if (entity->parent &&
entity->parent->last_bfqq_created == bfqq)
entity->parent->last_bfqq_created = NULL;
else if (bfqd->last_bfqq_created == bfqq)
bfqd->last_bfqq_created = NULL;
entity->parent = bfqg->my_entity; entity->parent = bfqg->my_entity;
entity->sched_data = &bfqg->sched_data; entity->sched_data = &bfqg->sched_data;
/* pin down bfqg and its associated blkg */ /* pin down bfqg and its associated blkg */

@ -49,7 +49,6 @@
#include "blk-mq.h" #include "blk-mq.h"
#include "blk-mq-sched.h" #include "blk-mq-sched.h"
#include "blk-pm.h" #include "blk-pm.h"
#include "blk-rq-qos.h"
struct dentry *blk_debugfs_root; struct dentry *blk_debugfs_root;
@ -337,23 +336,25 @@ void blk_put_queue(struct request_queue *q)
} }
EXPORT_SYMBOL(blk_put_queue); EXPORT_SYMBOL(blk_put_queue);
void blk_set_queue_dying(struct request_queue *q) void blk_queue_start_drain(struct request_queue *q)
{ {
blk_queue_flag_set(QUEUE_FLAG_DYING, q);
/* /*
* When queue DYING flag is set, we need to block new req * When queue DYING flag is set, we need to block new req
* entering queue, so we call blk_freeze_queue_start() to * entering queue, so we call blk_freeze_queue_start() to
* prevent I/O from crossing blk_queue_enter(). * prevent I/O from crossing blk_queue_enter().
*/ */
blk_freeze_queue_start(q); blk_freeze_queue_start(q);
if (queue_is_mq(q)) if (queue_is_mq(q))
blk_mq_wake_waiters(q); blk_mq_wake_waiters(q);
/* Make blk_queue_enter() reexamine the DYING flag. */ /* Make blk_queue_enter() reexamine the DYING flag. */
wake_up_all(&q->mq_freeze_wq); wake_up_all(&q->mq_freeze_wq);
} }
void blk_set_queue_dying(struct request_queue *q)
{
blk_queue_flag_set(QUEUE_FLAG_DYING, q);
blk_queue_start_drain(q);
}
EXPORT_SYMBOL_GPL(blk_set_queue_dying); EXPORT_SYMBOL_GPL(blk_set_queue_dying);
/** /**
@ -385,13 +386,8 @@ void blk_cleanup_queue(struct request_queue *q)
*/ */
blk_freeze_queue(q); blk_freeze_queue(q);
rq_qos_exit(q);
blk_queue_flag_set(QUEUE_FLAG_DEAD, q); blk_queue_flag_set(QUEUE_FLAG_DEAD, q);
/* for synchronous bio-based driver finish in-flight integrity i/o */
blk_flush_integrity();
blk_sync_queue(q); blk_sync_queue(q);
if (queue_is_mq(q)) if (queue_is_mq(q))
blk_mq_exit_queue(q); blk_mq_exit_queue(q);
@ -416,6 +412,30 @@ void blk_cleanup_queue(struct request_queue *q)
} }
EXPORT_SYMBOL(blk_cleanup_queue); EXPORT_SYMBOL(blk_cleanup_queue);
static bool blk_try_enter_queue(struct request_queue *q, bool pm)
{
rcu_read_lock();
if (!percpu_ref_tryget_live(&q->q_usage_counter))
goto fail;
/*
* The code that increments the pm_only counter must ensure that the
* counter is globally visible before the queue is unfrozen.
*/
if (blk_queue_pm_only(q) &&
(!pm || queue_rpm_status(q) == RPM_SUSPENDED))
goto fail_put;
rcu_read_unlock();
return true;
fail_put:
percpu_ref_put(&q->q_usage_counter);
fail:
rcu_read_unlock();
return false;
}
/** /**
* blk_queue_enter() - try to increase q->q_usage_counter * blk_queue_enter() - try to increase q->q_usage_counter
* @q: request queue pointer * @q: request queue pointer
@ -425,40 +445,18 @@ int blk_queue_enter(struct request_queue *q, blk_mq_req_flags_t flags)
{ {
const bool pm = flags & BLK_MQ_REQ_PM; const bool pm = flags & BLK_MQ_REQ_PM;
while (true) { while (!blk_try_enter_queue(q, pm)) {
bool success = false;
rcu_read_lock();
if (percpu_ref_tryget_live(&q->q_usage_counter)) {
/*
* The code that increments the pm_only counter is
* responsible for ensuring that that counter is
* globally visible before the queue is unfrozen.
*/
if ((pm && queue_rpm_status(q) != RPM_SUSPENDED) ||
!blk_queue_pm_only(q)) {
success = true;
} else {
percpu_ref_put(&q->q_usage_counter);
}
}
rcu_read_unlock();
if (success)
return 0;
if (flags & BLK_MQ_REQ_NOWAIT) if (flags & BLK_MQ_REQ_NOWAIT)
return -EBUSY; return -EBUSY;
/* /*
* read pair of barrier in blk_freeze_queue_start(), * read pair of barrier in blk_freeze_queue_start(), we need to
* we need to order reading __PERCPU_REF_DEAD flag of * order reading __PERCPU_REF_DEAD flag of .q_usage_counter and
* .q_usage_counter and reading .mq_freeze_depth or * reading .mq_freeze_depth or queue dying flag, otherwise the
* queue dying flag, otherwise the following wait may * following wait may never return if the two reads are
* never return if the two reads are reordered. * reordered.
*/ */
smp_rmb(); smp_rmb();
wait_event(q->mq_freeze_wq, wait_event(q->mq_freeze_wq,
(!q->mq_freeze_depth && (!q->mq_freeze_depth &&
blk_pm_resume_queue(pm, q)) || blk_pm_resume_queue(pm, q)) ||
@ -466,23 +464,43 @@ int blk_queue_enter(struct request_queue *q, blk_mq_req_flags_t flags)
if (blk_queue_dying(q)) if (blk_queue_dying(q))
return -ENODEV; return -ENODEV;
} }
return 0;
} }
static inline int bio_queue_enter(struct bio *bio) static inline int bio_queue_enter(struct bio *bio)
{ {
struct request_queue *q = bio->bi_bdev->bd_disk->queue; struct gendisk *disk = bio->bi_bdev->bd_disk;
bool nowait = bio->bi_opf & REQ_NOWAIT; struct request_queue *q = disk->queue;
int ret;
ret = blk_queue_enter(q, nowait ? BLK_MQ_REQ_NOWAIT : 0); while (!blk_try_enter_queue(q, false)) {
if (unlikely(ret)) { if (bio->bi_opf & REQ_NOWAIT) {
if (nowait && !blk_queue_dying(q)) if (test_bit(GD_DEAD, &disk->state))
goto dead;
bio_wouldblock_error(bio); bio_wouldblock_error(bio);
else return -EBUSY;
bio_io_error(bio); }
/*
* read pair of barrier in blk_freeze_queue_start(), we need to
* order reading __PERCPU_REF_DEAD flag of .q_usage_counter and
* reading .mq_freeze_depth or queue dying flag, otherwise the
* following wait may never return if the two reads are
* reordered.
*/
smp_rmb();
wait_event(q->mq_freeze_wq,
(!q->mq_freeze_depth &&
blk_pm_resume_queue(false, q)) ||
test_bit(GD_DEAD, &disk->state));
if (test_bit(GD_DEAD, &disk->state))
goto dead;
} }
return ret; return 0;
dead:
bio_io_error(bio);
return -ENODEV;
} }
void blk_queue_exit(struct request_queue *q) void blk_queue_exit(struct request_queue *q)
@ -899,11 +917,18 @@ static blk_qc_t __submit_bio(struct bio *bio)
struct gendisk *disk = bio->bi_bdev->bd_disk; struct gendisk *disk = bio->bi_bdev->bd_disk;
blk_qc_t ret = BLK_QC_T_NONE; blk_qc_t ret = BLK_QC_T_NONE;
if (blk_crypto_bio_prep(&bio)) { if (unlikely(bio_queue_enter(bio) != 0))
if (!disk->fops->submit_bio) return BLK_QC_T_NONE;
return blk_mq_submit_bio(bio);
if (!submit_bio_checks(bio) || !blk_crypto_bio_prep(&bio))
goto queue_exit;
if (disk->fops->submit_bio) {
ret = disk->fops->submit_bio(bio); ret = disk->fops->submit_bio(bio);
goto queue_exit;
} }
return blk_mq_submit_bio(bio);
queue_exit:
blk_queue_exit(disk->queue); blk_queue_exit(disk->queue);
return ret; return ret;
} }
@ -941,9 +966,6 @@ static blk_qc_t __submit_bio_noacct(struct bio *bio)
struct request_queue *q = bio->bi_bdev->bd_disk->queue; struct request_queue *q = bio->bi_bdev->bd_disk->queue;
struct bio_list lower, same; struct bio_list lower, same;
if (unlikely(bio_queue_enter(bio) != 0))
continue;
/* /*
* Create a fresh bio_list for all subordinate requests. * Create a fresh bio_list for all subordinate requests.
*/ */
@ -979,23 +1001,12 @@ static blk_qc_t __submit_bio_noacct(struct bio *bio)
static blk_qc_t __submit_bio_noacct_mq(struct bio *bio) static blk_qc_t __submit_bio_noacct_mq(struct bio *bio)
{ {
struct bio_list bio_list[2] = { }; struct bio_list bio_list[2] = { };
blk_qc_t ret = BLK_QC_T_NONE; blk_qc_t ret;
current->bio_list = bio_list; current->bio_list = bio_list;
do { do {
struct gendisk *disk = bio->bi_bdev->bd_disk; ret = __submit_bio(bio);
if (unlikely(bio_queue_enter(bio) != 0))
continue;
if (!blk_crypto_bio_prep(&bio)) {
blk_queue_exit(disk->queue);
ret = BLK_QC_T_NONE;
continue;
}
ret = blk_mq_submit_bio(bio);
} while ((bio = bio_list_pop(&bio_list[0]))); } while ((bio = bio_list_pop(&bio_list[0])));
current->bio_list = NULL; current->bio_list = NULL;
@ -1013,9 +1024,6 @@ static blk_qc_t __submit_bio_noacct_mq(struct bio *bio)
*/ */
blk_qc_t submit_bio_noacct(struct bio *bio) blk_qc_t submit_bio_noacct(struct bio *bio)
{ {
if (!submit_bio_checks(bio))
return BLK_QC_T_NONE;
/* /*
* We only want one ->submit_bio to be active at a time, else stack * We only want one ->submit_bio to be active at a time, else stack
* usage with stacked devices could be a problem. Use current->bio_list * usage with stacked devices could be a problem. Use current->bio_list

@ -188,9 +188,11 @@ void blk_mq_freeze_queue(struct request_queue *q)
} }
EXPORT_SYMBOL_GPL(blk_mq_freeze_queue); EXPORT_SYMBOL_GPL(blk_mq_freeze_queue);
void blk_mq_unfreeze_queue(struct request_queue *q) void __blk_mq_unfreeze_queue(struct request_queue *q, bool force_atomic)
{ {
mutex_lock(&q->mq_freeze_lock); mutex_lock(&q->mq_freeze_lock);
if (force_atomic)
q->q_usage_counter.data->force_atomic = true;
q->mq_freeze_depth--; q->mq_freeze_depth--;
WARN_ON_ONCE(q->mq_freeze_depth < 0); WARN_ON_ONCE(q->mq_freeze_depth < 0);
if (!q->mq_freeze_depth) { if (!q->mq_freeze_depth) {
@ -199,6 +201,11 @@ void blk_mq_unfreeze_queue(struct request_queue *q)
} }
mutex_unlock(&q->mq_freeze_lock); mutex_unlock(&q->mq_freeze_lock);
} }
void blk_mq_unfreeze_queue(struct request_queue *q)
{
__blk_mq_unfreeze_queue(q, false);
}
EXPORT_SYMBOL_GPL(blk_mq_unfreeze_queue); EXPORT_SYMBOL_GPL(blk_mq_unfreeze_queue);
/* /*

@ -51,6 +51,8 @@ struct blk_flush_queue *blk_alloc_flush_queue(int node, int cmd_size,
void blk_free_flush_queue(struct blk_flush_queue *q); void blk_free_flush_queue(struct blk_flush_queue *q);
void blk_freeze_queue(struct request_queue *q); void blk_freeze_queue(struct request_queue *q);
void __blk_mq_unfreeze_queue(struct request_queue *q, bool force_atomic);
void blk_queue_start_drain(struct request_queue *q);
#define BIO_INLINE_VECS 4 #define BIO_INLINE_VECS 4
struct bio_vec *bvec_alloc(mempool_t *pool, unsigned short *nr_vecs, struct bio_vec *bvec_alloc(mempool_t *pool, unsigned short *nr_vecs,

@ -26,6 +26,7 @@
#include <linux/badblocks.h> #include <linux/badblocks.h>
#include "blk.h" #include "blk.h"
#include "blk-rq-qos.h"
static struct kobject *block_depr; static struct kobject *block_depr;
@ -559,6 +560,8 @@ EXPORT_SYMBOL(device_add_disk);
*/ */
void del_gendisk(struct gendisk *disk) void del_gendisk(struct gendisk *disk)
{ {
struct request_queue *q = disk->queue;
might_sleep(); might_sleep();
if (WARN_ON_ONCE(!disk_live(disk) && !(disk->flags & GENHD_FL_HIDDEN))) if (WARN_ON_ONCE(!disk_live(disk) && !(disk->flags & GENHD_FL_HIDDEN)))
@ -575,8 +578,27 @@ void del_gendisk(struct gendisk *disk)
fsync_bdev(disk->part0); fsync_bdev(disk->part0);
__invalidate_device(disk->part0, true); __invalidate_device(disk->part0, true);
/*
* Fail any new I/O.
*/
set_bit(GD_DEAD, &disk->state);
set_capacity(disk, 0); set_capacity(disk, 0);
/*
* Prevent new I/O from crossing bio_queue_enter().
*/
blk_queue_start_drain(q);
blk_mq_freeze_queue_wait(q);
rq_qos_exit(q);
blk_sync_queue(q);
blk_flush_integrity();
/*
* Allow using passthrough request again after the queue is torn down.
*/
blk_queue_flag_clear(QUEUE_FLAG_INIT_DONE, q);
__blk_mq_unfreeze_queue(q, true);
if (!(disk->flags & GENHD_FL_HIDDEN)) { if (!(disk->flags & GENHD_FL_HIDDEN)) {
sysfs_remove_link(&disk_to_dev(disk)->kobj, "bdi"); sysfs_remove_link(&disk_to_dev(disk)->kobj, "bdi");
@ -1056,6 +1078,7 @@ static void disk_release(struct device *dev)
struct gendisk *disk = dev_to_disk(dev); struct gendisk *disk = dev_to_disk(dev);
might_sleep(); might_sleep();
WARN_ON_ONCE(disk_live(disk));
disk_release_events(disk); disk_release_events(disk);
kfree(disk->random); kfree(disk->random);

@ -151,6 +151,7 @@ struct kyber_ctx_queue {
struct kyber_queue_data { struct kyber_queue_data {
struct request_queue *q; struct request_queue *q;
dev_t dev;
/* /*
* Each scheduling domain has a limited number of in-flight requests * Each scheduling domain has a limited number of in-flight requests
@ -257,7 +258,7 @@ static int calculate_percentile(struct kyber_queue_data *kqd,
} }
memset(buckets, 0, sizeof(kqd->latency_buckets[sched_domain][type])); memset(buckets, 0, sizeof(kqd->latency_buckets[sched_domain][type]));
trace_kyber_latency(kqd->q, kyber_domain_names[sched_domain], trace_kyber_latency(kqd->dev, kyber_domain_names[sched_domain],
kyber_latency_type_names[type], percentile, kyber_latency_type_names[type], percentile,
bucket + 1, 1 << KYBER_LATENCY_SHIFT, samples); bucket + 1, 1 << KYBER_LATENCY_SHIFT, samples);
@ -270,7 +271,7 @@ static void kyber_resize_domain(struct kyber_queue_data *kqd,
depth = clamp(depth, 1U, kyber_depth[sched_domain]); depth = clamp(depth, 1U, kyber_depth[sched_domain]);
if (depth != kqd->domain_tokens[sched_domain].sb.depth) { if (depth != kqd->domain_tokens[sched_domain].sb.depth) {
sbitmap_queue_resize(&kqd->domain_tokens[sched_domain], depth); sbitmap_queue_resize(&kqd->domain_tokens[sched_domain], depth);
trace_kyber_adjust(kqd->q, kyber_domain_names[sched_domain], trace_kyber_adjust(kqd->dev, kyber_domain_names[sched_domain],
depth); depth);
} }
} }
@ -366,6 +367,7 @@ static struct kyber_queue_data *kyber_queue_data_alloc(struct request_queue *q)
goto err; goto err;
kqd->q = q; kqd->q = q;
kqd->dev = disk_devt(q->disk);
kqd->cpu_latency = alloc_percpu_gfp(struct kyber_cpu_latency, kqd->cpu_latency = alloc_percpu_gfp(struct kyber_cpu_latency,
GFP_KERNEL | __GFP_ZERO); GFP_KERNEL | __GFP_ZERO);
@ -774,7 +776,7 @@ kyber_dispatch_cur_domain(struct kyber_queue_data *kqd,
list_del_init(&rq->queuelist); list_del_init(&rq->queuelist);
return rq; return rq;
} else { } else {
trace_kyber_throttled(kqd->q, trace_kyber_throttled(kqd->dev,
kyber_domain_names[khd->cur_domain]); kyber_domain_names[khd->cur_domain]);
} }
} else if (sbitmap_any_bit_set(&khd->kcq_map[khd->cur_domain])) { } else if (sbitmap_any_bit_set(&khd->kcq_map[khd->cur_domain])) {
@ -787,7 +789,7 @@ kyber_dispatch_cur_domain(struct kyber_queue_data *kqd,
list_del_init(&rq->queuelist); list_del_init(&rq->queuelist);
return rq; return rq;
} else { } else {
trace_kyber_throttled(kqd->q, trace_kyber_throttled(kqd->dev,
kyber_domain_names[khd->cur_domain]); kyber_domain_names[khd->cur_domain]);
} }
} }

@ -21,6 +21,7 @@
#include <linux/earlycpio.h> #include <linux/earlycpio.h>
#include <linux/initrd.h> #include <linux/initrd.h>
#include <linux/security.h> #include <linux/security.h>
#include <linux/kmemleak.h>
#include "internal.h" #include "internal.h"
#ifdef CONFIG_ACPI_CUSTOM_DSDT #ifdef CONFIG_ACPI_CUSTOM_DSDT
@ -601,6 +602,8 @@ void __init acpi_table_upgrade(void)
*/ */
arch_reserve_mem_area(acpi_tables_addr, all_tables_size); arch_reserve_mem_area(acpi_tables_addr, all_tables_size);
kmemleak_ignore_phys(acpi_tables_addr);
/* /*
* early_ioremap only can remap 256k one time. If we map all * early_ioremap only can remap 256k one time. If we map all
* tables one time, we will hit the limit. Need to map chunks * tables one time, we will hit the limit. Need to map chunks

@ -371,7 +371,7 @@ static int lps0_device_attach(struct acpi_device *adev,
return 0; return 0;
if (acpi_s2idle_vendor_amd()) { if (acpi_s2idle_vendor_amd()) {
/* AMD0004, AMDI0005: /* AMD0004, AMD0005, AMDI0005:
* - Should use rev_id 0x0 * - Should use rev_id 0x0
* - function mask > 0x3: Should use AMD method, but has off by one bug * - function mask > 0x3: Should use AMD method, but has off by one bug
* - function mask = 0x3: Should use Microsoft method * - function mask = 0x3: Should use Microsoft method
@ -390,6 +390,7 @@ static int lps0_device_attach(struct acpi_device *adev,
ACPI_LPS0_DSM_UUID_MICROSOFT, 0, ACPI_LPS0_DSM_UUID_MICROSOFT, 0,
&lps0_dsm_guid_microsoft); &lps0_dsm_guid_microsoft);
if (lps0_dsm_func_mask > 0x3 && (!strcmp(hid, "AMD0004") || if (lps0_dsm_func_mask > 0x3 && (!strcmp(hid, "AMD0004") ||
!strcmp(hid, "AMD0005") ||
!strcmp(hid, "AMDI0005"))) { !strcmp(hid, "AMDI0005"))) {
lps0_dsm_func_mask = (lps0_dsm_func_mask << 1) | 0x1; lps0_dsm_func_mask = (lps0_dsm_func_mask << 1) | 0x1;
acpi_handle_debug(adev->handle, "_DSM UUID %s: Adjusted function mask: 0x%x\n", acpi_handle_debug(adev->handle, "_DSM UUID %s: Adjusted function mask: 0x%x\n",

@ -440,10 +440,7 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
hpriv->phy_regulator = devm_regulator_get(dev, "phy"); hpriv->phy_regulator = devm_regulator_get(dev, "phy");
if (IS_ERR(hpriv->phy_regulator)) { if (IS_ERR(hpriv->phy_regulator)) {
rc = PTR_ERR(hpriv->phy_regulator); rc = PTR_ERR(hpriv->phy_regulator);
if (rc == -EPROBE_DEFER) goto err_out;
goto err_out;
rc = 0;
hpriv->phy_regulator = NULL;
} }
if (flags & AHCI_PLATFORM_GET_RESETS) { if (flags & AHCI_PLATFORM_GET_RESETS) {

@ -352,7 +352,8 @@ static unsigned int pdc_data_xfer_vlb(struct ata_queued_cmd *qc,
iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
if (unlikely(slop)) { if (unlikely(slop)) {
__le32 pad; __le32 pad = 0;
if (rw == READ) { if (rw == READ) {
pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr)); pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr));
memcpy(buf + buflen - slop, &pad, slop); memcpy(buf + buflen - slop, &pad, slop);
@ -742,7 +743,8 @@ static unsigned int vlb32_data_xfer(struct ata_queued_cmd *qc,
ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
if (unlikely(slop)) { if (unlikely(slop)) {
__le32 pad; __le32 pad = 0;
if (rw == WRITE) { if (rw == WRITE) {
memcpy(&pad, buf + buflen - slop, slop); memcpy(&pad, buf + buflen - slop, slop);
iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr); iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);

@ -687,7 +687,8 @@ struct device_link *device_link_add(struct device *consumer,
{ {
struct device_link *link; struct device_link *link;
if (!consumer || !supplier || flags & ~DL_ADD_VALID_FLAGS || if (!consumer || !supplier || consumer == supplier ||
flags & ~DL_ADD_VALID_FLAGS ||
(flags & DL_FLAG_STATELESS && flags & DL_MANAGED_LINK_FLAGS) || (flags & DL_FLAG_STATELESS && flags & DL_MANAGED_LINK_FLAGS) ||
(flags & DL_FLAG_SYNC_STATE_ONLY && (flags & DL_FLAG_SYNC_STATE_ONLY &&
(flags & ~DL_FLAG_INFERRED) != DL_FLAG_SYNC_STATE_ONLY) || (flags & ~DL_FLAG_INFERRED) != DL_FLAG_SYNC_STATE_ONLY) ||

@ -373,10 +373,22 @@ static int brd_alloc(int i)
struct gendisk *disk; struct gendisk *disk;
char buf[DISK_NAME_LEN]; char buf[DISK_NAME_LEN];
mutex_lock(&brd_devices_mutex);
list_for_each_entry(brd, &brd_devices, brd_list) {
if (brd->brd_number == i) {
mutex_unlock(&brd_devices_mutex);
return -EEXIST;
}
}
brd = kzalloc(sizeof(*brd), GFP_KERNEL); brd = kzalloc(sizeof(*brd), GFP_KERNEL);
if (!brd) if (!brd) {
mutex_unlock(&brd_devices_mutex);
return -ENOMEM; return -ENOMEM;
}
brd->brd_number = i; brd->brd_number = i;
list_add_tail(&brd->brd_list, &brd_devices);
mutex_unlock(&brd_devices_mutex);
spin_lock_init(&brd->brd_lock); spin_lock_init(&brd->brd_lock);
INIT_RADIX_TREE(&brd->brd_pages, GFP_ATOMIC); INIT_RADIX_TREE(&brd->brd_pages, GFP_ATOMIC);
@ -411,37 +423,30 @@ static int brd_alloc(int i)
blk_queue_flag_set(QUEUE_FLAG_NONROT, disk->queue); blk_queue_flag_set(QUEUE_FLAG_NONROT, disk->queue);
blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, disk->queue); blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, disk->queue);
add_disk(disk); add_disk(disk);
list_add_tail(&brd->brd_list, &brd_devices);
return 0; return 0;
out_free_dev: out_free_dev:
mutex_lock(&brd_devices_mutex);
list_del(&brd->brd_list);
mutex_unlock(&brd_devices_mutex);
kfree(brd); kfree(brd);
return -ENOMEM; return -ENOMEM;
} }
static void brd_probe(dev_t dev) static void brd_probe(dev_t dev)
{ {
int i = MINOR(dev) / max_part; brd_alloc(MINOR(dev) / max_part);
struct brd_device *brd;
mutex_lock(&brd_devices_mutex);
list_for_each_entry(brd, &brd_devices, brd_list) {
if (brd->brd_number == i)
goto out_unlock;
}
brd_alloc(i);
out_unlock:
mutex_unlock(&brd_devices_mutex);
} }
static void brd_del_one(struct brd_device *brd) static void brd_del_one(struct brd_device *brd)
{ {
list_del(&brd->brd_list);
del_gendisk(brd->brd_disk); del_gendisk(brd->brd_disk);
blk_cleanup_disk(brd->brd_disk); blk_cleanup_disk(brd->brd_disk);
brd_free_pages(brd); brd_free_pages(brd);
mutex_lock(&brd_devices_mutex);
list_del(&brd->brd_list);
mutex_unlock(&brd_devices_mutex);
kfree(brd); kfree(brd);
} }
@ -491,25 +496,21 @@ static int __init brd_init(void)
brd_debugfs_dir = debugfs_create_dir("ramdisk_pages", NULL); brd_debugfs_dir = debugfs_create_dir("ramdisk_pages", NULL);
mutex_lock(&brd_devices_mutex);
for (i = 0; i < rd_nr; i++) { for (i = 0; i < rd_nr; i++) {
err = brd_alloc(i); err = brd_alloc(i);
if (err) if (err)
goto out_free; goto out_free;
} }
mutex_unlock(&brd_devices_mutex);
pr_info("brd: module loaded\n"); pr_info("brd: module loaded\n");
return 0; return 0;
out_free: out_free:
unregister_blkdev(RAMDISK_MAJOR, "ramdisk");
debugfs_remove_recursive(brd_debugfs_dir); debugfs_remove_recursive(brd_debugfs_dir);
list_for_each_entry_safe(brd, next, &brd_devices, brd_list) list_for_each_entry_safe(brd, next, &brd_devices, brd_list)
brd_del_one(brd); brd_del_one(brd);
mutex_unlock(&brd_devices_mutex);
unregister_blkdev(RAMDISK_MAJOR, "ramdisk");
pr_info("brd: module NOT loaded !!!\n"); pr_info("brd: module NOT loaded !!!\n");
return err; return err;
@ -519,13 +520,12 @@ static void __exit brd_exit(void)
{ {
struct brd_device *brd, *next; struct brd_device *brd, *next;
unregister_blkdev(RAMDISK_MAJOR, "ramdisk");
debugfs_remove_recursive(brd_debugfs_dir); debugfs_remove_recursive(brd_debugfs_dir);
list_for_each_entry_safe(brd, next, &brd_devices, brd_list) list_for_each_entry_safe(brd, next, &brd_devices, brd_list)
brd_del_one(brd); brd_del_one(brd);
unregister_blkdev(RAMDISK_MAJOR, "ramdisk");
pr_info("brd: module unloaded\n"); pr_info("brd: module unloaded\n");
} }

@ -71,8 +71,10 @@ static int rnbd_clt_parse_map_options(const char *buf, size_t max_path_cnt,
int opt_mask = 0; int opt_mask = 0;
int token; int token;
int ret = -EINVAL; int ret = -EINVAL;
int i, dest_port, nr_poll_queues; int nr_poll_queues = 0;
int dest_port = 0;
int p_cnt = 0; int p_cnt = 0;
int i;
options = kstrdup(buf, GFP_KERNEL); options = kstrdup(buf, GFP_KERNEL);
if (!options) if (!options)

@ -689,28 +689,6 @@ static const struct blk_mq_ops virtio_mq_ops = {
static unsigned int virtblk_queue_depth; static unsigned int virtblk_queue_depth;
module_param_named(queue_depth, virtblk_queue_depth, uint, 0444); module_param_named(queue_depth, virtblk_queue_depth, uint, 0444);
static int virtblk_validate(struct virtio_device *vdev)
{
u32 blk_size;
if (!vdev->config->get) {
dev_err(&vdev->dev, "%s failure: config access disabled\n",
__func__);
return -EINVAL;
}
if (!virtio_has_feature(vdev, VIRTIO_BLK_F_BLK_SIZE))
return 0;
blk_size = virtio_cread32(vdev,
offsetof(struct virtio_blk_config, blk_size));
if (blk_size < SECTOR_SIZE || blk_size > PAGE_SIZE)
__virtio_clear_bit(vdev, VIRTIO_BLK_F_BLK_SIZE);
return 0;
}
static int virtblk_probe(struct virtio_device *vdev) static int virtblk_probe(struct virtio_device *vdev)
{ {
struct virtio_blk *vblk; struct virtio_blk *vblk;
@ -722,6 +700,12 @@ static int virtblk_probe(struct virtio_device *vdev)
u8 physical_block_exp, alignment_offset; u8 physical_block_exp, alignment_offset;
unsigned int queue_depth; unsigned int queue_depth;
if (!vdev->config->get) {
dev_err(&vdev->dev, "%s failure: config access disabled\n",
__func__);
return -EINVAL;
}
err = ida_simple_get(&vd_index_ida, 0, minor_to_index(1 << MINORBITS), err = ida_simple_get(&vd_index_ida, 0, minor_to_index(1 << MINORBITS),
GFP_KERNEL); GFP_KERNEL);
if (err < 0) if (err < 0)
@ -836,14 +820,6 @@ static int virtblk_probe(struct virtio_device *vdev)
else else
blk_size = queue_logical_block_size(q); blk_size = queue_logical_block_size(q);
if (blk_size < SECTOR_SIZE || blk_size > PAGE_SIZE) {
dev_err(&vdev->dev,
"block size is changed unexpectedly, now is %u\n",
blk_size);
err = -EINVAL;
goto out_cleanup_disk;
}
/* Use topology information if available */ /* Use topology information if available */
err = virtio_cread_feature(vdev, VIRTIO_BLK_F_TOPOLOGY, err = virtio_cread_feature(vdev, VIRTIO_BLK_F_TOPOLOGY,
struct virtio_blk_config, physical_block_exp, struct virtio_blk_config, physical_block_exp,
@ -1009,7 +985,6 @@ static struct virtio_driver virtio_blk = {
.driver.name = KBUILD_MODNAME, .driver.name = KBUILD_MODNAME,
.driver.owner = THIS_MODULE, .driver.owner = THIS_MODULE,
.id_table = id_table, .id_table = id_table,
.validate = virtblk_validate,
.probe = virtblk_probe, .probe = virtblk_probe,
.remove = virtblk_remove, .remove = virtblk_remove,
.config_changed = virtblk_config_changed, .config_changed = virtblk_config_changed,

@ -152,18 +152,6 @@ config QCOM_EBI2
Interface 2, which can be used to connect things like NAND Flash, Interface 2, which can be used to connect things like NAND Flash,
SRAM, ethernet adapters, FPGAs and LCD displays. SRAM, ethernet adapters, FPGAs and LCD displays.
config SIMPLE_PM_BUS
tristate "Simple Power-Managed Bus Driver"
depends on OF && PM
help
Driver for transparent busses that don't need a real driver, but
where the bus controller is part of a PM domain, or under the control
of a functional clock, and thus relies on runtime PM for managing
this PM domain and/or clock.
An example of such a bus controller is the Renesas Bus State
Controller (BSC, sometimes called "LBSC within Bus Bridge", or
"External Bus Interface") as found on several Renesas ARM SoCs.
config SUN50I_DE2_BUS config SUN50I_DE2_BUS
bool "Allwinner A64 DE2 Bus Driver" bool "Allwinner A64 DE2 Bus Driver"
default ARM64 default ARM64

@ -27,7 +27,7 @@ obj-$(CONFIG_OMAP_OCP2SCP) += omap-ocp2scp.o
obj-$(CONFIG_QCOM_EBI2) += qcom-ebi2.o obj-$(CONFIG_QCOM_EBI2) += qcom-ebi2.o
obj-$(CONFIG_SUN50I_DE2_BUS) += sun50i-de2.o obj-$(CONFIG_SUN50I_DE2_BUS) += sun50i-de2.o
obj-$(CONFIG_SUNXI_RSB) += sunxi-rsb.o obj-$(CONFIG_SUNXI_RSB) += sunxi-rsb.o
obj-$(CONFIG_SIMPLE_PM_BUS) += simple-pm-bus.o obj-$(CONFIG_OF) += simple-pm-bus.o
obj-$(CONFIG_TEGRA_ACONNECT) += tegra-aconnect.o obj-$(CONFIG_TEGRA_ACONNECT) += tegra-aconnect.o
obj-$(CONFIG_TEGRA_GMI) += tegra-gmi.o obj-$(CONFIG_TEGRA_GMI) += tegra-gmi.o
obj-$(CONFIG_TI_PWMSS) += ti-pwmss.o obj-$(CONFIG_TI_PWMSS) += ti-pwmss.o

@ -13,11 +13,36 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
static int simple_pm_bus_probe(struct platform_device *pdev) static int simple_pm_bus_probe(struct platform_device *pdev)
{ {
const struct of_dev_auxdata *lookup = dev_get_platdata(&pdev->dev); const struct device *dev = &pdev->dev;
struct device_node *np = pdev->dev.of_node; const struct of_dev_auxdata *lookup = dev_get_platdata(dev);
struct device_node *np = dev->of_node;
const struct of_device_id *match;
/*
* Allow user to use driver_override to bind this driver to a
* transparent bus device which has a different compatible string
* that's not listed in simple_pm_bus_of_match. We don't want to do any
* of the simple-pm-bus tasks for these devices, so return early.
*/
if (pdev->driver_override)
return 0;
match = of_match_device(dev->driver->of_match_table, dev);
/*
* These are transparent bus devices (not simple-pm-bus matches) that
* have their child nodes populated automatically. So, don't need to
* do anything more. We only match with the device if this driver is
* the most specific match because we don't want to incorrectly bind to
* a device that has a more specific driver.
*/
if (match && match->data) {
if (of_property_match_string(np, "compatible", match->compatible) == 0)
return 0;
else
return -ENODEV;
}
dev_dbg(&pdev->dev, "%s\n", __func__); dev_dbg(&pdev->dev, "%s\n", __func__);
@ -31,14 +56,25 @@ static int simple_pm_bus_probe(struct platform_device *pdev)
static int simple_pm_bus_remove(struct platform_device *pdev) static int simple_pm_bus_remove(struct platform_device *pdev)
{ {
const void *data = of_device_get_match_data(&pdev->dev);
if (pdev->driver_override || data)
return 0;
dev_dbg(&pdev->dev, "%s\n", __func__); dev_dbg(&pdev->dev, "%s\n", __func__);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
return 0; return 0;
} }
#define ONLY_BUS ((void *) 1) /* Match if the device is only a bus. */
static const struct of_device_id simple_pm_bus_of_match[] = { static const struct of_device_id simple_pm_bus_of_match[] = {
{ .compatible = "simple-pm-bus", }, { .compatible = "simple-pm-bus", },
{ .compatible = "simple-bus", .data = ONLY_BUS },
{ .compatible = "simple-mfd", .data = ONLY_BUS },
{ .compatible = "isa", .data = ONLY_BUS },
{ .compatible = "arm,amba-bus", .data = ONLY_BUS },
{ /* sentinel */ } { /* sentinel */ }
}; };
MODULE_DEVICE_TABLE(of, simple_pm_bus_of_match); MODULE_DEVICE_TABLE(of, simple_pm_bus_of_match);

@ -564,6 +564,7 @@ config SM_GCC_6125
config SM_GCC_6350 config SM_GCC_6350
tristate "SM6350 Global Clock Controller" tristate "SM6350 Global Clock Controller"
select QCOM_GDSC
help help
Support for the global clock controller on SM6350 devices. Support for the global clock controller on SM6350 devices.
Say Y if you want to use peripheral devices such as UART, Say Y if you want to use peripheral devices such as UART,

@ -3242,7 +3242,7 @@ static struct gdsc hlos1_vote_turing_mmu_tbu1_gdsc = {
}; };
static struct gdsc hlos1_vote_turing_mmu_tbu0_gdsc = { static struct gdsc hlos1_vote_turing_mmu_tbu0_gdsc = {
.gdscr = 0x7d060, .gdscr = 0x7d07c,
.pd = { .pd = {
.name = "hlos1_vote_turing_mmu_tbu0", .name = "hlos1_vote_turing_mmu_tbu0",
}, },

@ -186,6 +186,8 @@ static struct rzg2l_reset r9a07g044_resets[] = {
static const unsigned int r9a07g044_crit_mod_clks[] __initconst = { static const unsigned int r9a07g044_crit_mod_clks[] __initconst = {
MOD_CLK_BASE + R9A07G044_GIC600_GICCLK, MOD_CLK_BASE + R9A07G044_GIC600_GICCLK,
MOD_CLK_BASE + R9A07G044_IA55_CLK,
MOD_CLK_BASE + R9A07G044_DMAC_ACLK,
}; };
const struct rzg2l_cpg_info r9a07g044_cpg_info = { const struct rzg2l_cpg_info r9a07g044_cpg_info = {

@ -391,7 +391,7 @@ static int rzg2l_mod_clock_is_enabled(struct clk_hw *hw)
value = readl(priv->base + CLK_MON_R(clock->off)); value = readl(priv->base + CLK_MON_R(clock->off));
return !(value & bitmask); return value & bitmask;
} }
static const struct clk_ops rzg2l_mod_clock_ops = { static const struct clk_ops rzg2l_mod_clock_ops = {

@ -165,13 +165,6 @@ static const struct clk_parent_data mpu_mux[] = {
.name = "boot_clk", }, .name = "boot_clk", },
}; };
static const struct clk_parent_data s2f_usr0_mux[] = {
{ .fw_name = "f2s-free-clk",
.name = "f2s-free-clk", },
{ .fw_name = "boot_clk",
.name = "boot_clk", },
};
static const struct clk_parent_data emac_mux[] = { static const struct clk_parent_data emac_mux[] = {
{ .fw_name = "emaca_free_clk", { .fw_name = "emaca_free_clk",
.name = "emaca_free_clk", }, .name = "emaca_free_clk", },
@ -312,8 +305,6 @@ static const struct stratix10_gate_clock agilex_gate_clks[] = {
4, 0x44, 28, 1, 0, 0, 0}, 4, 0x44, 28, 1, 0, 0, 0},
{ AGILEX_CS_TIMER_CLK, "cs_timer_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x24, { AGILEX_CS_TIMER_CLK, "cs_timer_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x24,
5, 0, 0, 0, 0x30, 1, 0}, 5, 0, 0, 0, 0x30, 1, 0},
{ AGILEX_S2F_USER0_CLK, "s2f_user0_clk", NULL, s2f_usr0_mux, ARRAY_SIZE(s2f_usr0_mux), 0, 0x24,
6, 0, 0, 0, 0, 0, 0},
{ AGILEX_EMAC0_CLK, "emac0_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0x7C, { AGILEX_EMAC0_CLK, "emac0_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0x7C,
0, 0, 0, 0, 0x94, 26, 0}, 0, 0, 0, 0, 0x94, 26, 0},
{ AGILEX_EMAC1_CLK, "emac1_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0x7C, { AGILEX_EMAC1_CLK, "emac1_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0x7C,

@ -178,7 +178,7 @@ static void axp_mc_check(struct mem_ctl_info *mci)
"details unavailable (multiple errors)"); "details unavailable (multiple errors)");
if (cnt_dbe) if (cnt_dbe)
edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci,
cnt_sbe, /* error count */ cnt_dbe, /* error count */
0, 0, 0, /* pfn, offset, syndrome */ 0, 0, 0, /* pfn, offset, syndrome */
-1, -1, -1, /* top, mid, low layer */ -1, -1, -1, /* top, mid, low layer */
mci->ctl_name, mci->ctl_name,

@ -49,6 +49,13 @@ static int ffa_device_probe(struct device *dev)
return ffa_drv->probe(ffa_dev); return ffa_drv->probe(ffa_dev);
} }
static void ffa_device_remove(struct device *dev)
{
struct ffa_driver *ffa_drv = to_ffa_driver(dev->driver);
ffa_drv->remove(to_ffa_dev(dev));
}
static int ffa_device_uevent(struct device *dev, struct kobj_uevent_env *env) static int ffa_device_uevent(struct device *dev, struct kobj_uevent_env *env)
{ {
struct ffa_device *ffa_dev = to_ffa_dev(dev); struct ffa_device *ffa_dev = to_ffa_dev(dev);
@ -86,6 +93,7 @@ struct bus_type ffa_bus_type = {
.name = "arm_ffa", .name = "arm_ffa",
.match = ffa_device_match, .match = ffa_device_match,
.probe = ffa_device_probe, .probe = ffa_device_probe,
.remove = ffa_device_remove,
.uevent = ffa_device_uevent, .uevent = ffa_device_uevent,
.dev_groups = ffa_device_attributes_groups, .dev_groups = ffa_device_attributes_groups,
}; };
@ -127,7 +135,7 @@ static void ffa_release_device(struct device *dev)
static int __ffa_devices_unregister(struct device *dev, void *data) static int __ffa_devices_unregister(struct device *dev, void *data)
{ {
ffa_release_device(dev); device_unregister(dev);
return 0; return 0;
} }

@ -25,8 +25,6 @@
#include <acpi/ghes.h> #include <acpi/ghes.h>
#include <ras/ras_event.h> #include <ras/ras_event.h>
static char rcd_decode_str[CPER_REC_LEN];
/* /*
* CPER record ID need to be unique even after reboot, because record * CPER record ID need to be unique even after reboot, because record
* ID is used as index for ERST storage, while CPER records from * ID is used as index for ERST storage, while CPER records from
@ -312,6 +310,7 @@ const char *cper_mem_err_unpack(struct trace_seq *p,
struct cper_mem_err_compact *cmem) struct cper_mem_err_compact *cmem)
{ {
const char *ret = trace_seq_buffer_ptr(p); const char *ret = trace_seq_buffer_ptr(p);
char rcd_decode_str[CPER_REC_LEN];
if (cper_mem_err_location(cmem, rcd_decode_str)) if (cper_mem_err_location(cmem, rcd_decode_str))
trace_seq_printf(p, "%s", rcd_decode_str); trace_seq_printf(p, "%s", rcd_decode_str);
@ -326,6 +325,7 @@ static void cper_print_mem(const char *pfx, const struct cper_sec_mem_err *mem,
int len) int len)
{ {
struct cper_mem_err_compact cmem; struct cper_mem_err_compact cmem;
char rcd_decode_str[CPER_REC_LEN];
/* Don't trust UEFI 2.1/2.2 structure with bad validation bits */ /* Don't trust UEFI 2.1/2.2 structure with bad validation bits */
if (len == sizeof(struct cper_sec_mem_err_old) && if (len == sizeof(struct cper_sec_mem_err_old) &&

@ -271,7 +271,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(void *handle,
return status; return status;
} }
efi_info("Exiting boot services and installing virtual address map...\n"); efi_info("Exiting boot services...\n");
map.map = &memory_map; map.map = &memory_map;
status = efi_allocate_pages(MAX_FDT_SIZE, new_fdt_addr, ULONG_MAX); status = efi_allocate_pages(MAX_FDT_SIZE, new_fdt_addr, ULONG_MAX);

@ -414,7 +414,7 @@ static void virt_efi_reset_system(int reset_type,
unsigned long data_size, unsigned long data_size,
efi_char16_t *data) efi_char16_t *data)
{ {
if (down_interruptible(&efi_runtime_lock)) { if (down_trylock(&efi_runtime_lock)) {
pr_warn("failed to invoke the reset_system() runtime service:\n" pr_warn("failed to invoke the reset_system() runtime service:\n"
"could not get exclusive access to the firmware\n"); "could not get exclusive access to the firmware\n");
return; return;

@ -192,12 +192,19 @@ static const struct of_device_id ice40_fpga_of_match[] = {
}; };
MODULE_DEVICE_TABLE(of, ice40_fpga_of_match); MODULE_DEVICE_TABLE(of, ice40_fpga_of_match);
static const struct spi_device_id ice40_fpga_spi_ids[] = {
{ .name = "ice40-fpga-mgr", },
{},
};
MODULE_DEVICE_TABLE(spi, ice40_fpga_spi_ids);
static struct spi_driver ice40_fpga_driver = { static struct spi_driver ice40_fpga_driver = {
.probe = ice40_fpga_probe, .probe = ice40_fpga_probe,
.driver = { .driver = {
.name = "ice40spi", .name = "ice40spi",
.of_match_table = of_match_ptr(ice40_fpga_of_match), .of_match_table = of_match_ptr(ice40_fpga_of_match),
}, },
.id_table = ice40_fpga_spi_ids,
}; };
module_spi_driver(ice40_fpga_driver); module_spi_driver(ice40_fpga_driver);

@ -174,6 +174,13 @@ static int gen_74x164_remove(struct spi_device *spi)
return 0; return 0;
} }
static const struct spi_device_id gen_74x164_spi_ids[] = {
{ .name = "74hc595" },
{ .name = "74lvc594" },
{},
};
MODULE_DEVICE_TABLE(spi, gen_74x164_spi_ids);
static const struct of_device_id gen_74x164_dt_ids[] = { static const struct of_device_id gen_74x164_dt_ids[] = {
{ .compatible = "fairchild,74hc595" }, { .compatible = "fairchild,74hc595" },
{ .compatible = "nxp,74lvc594" }, { .compatible = "nxp,74lvc594" },
@ -188,6 +195,7 @@ static struct spi_driver gen_74x164_driver = {
}, },
.probe = gen_74x164_probe, .probe = gen_74x164_probe,
.remove = gen_74x164_remove, .remove = gen_74x164_remove,
.id_table = gen_74x164_spi_ids,
}; };
module_spi_driver(gen_74x164_driver); module_spi_driver(gen_74x164_driver);

@ -476,10 +476,19 @@ static struct platform_device *gpio_mockup_pdevs[GPIO_MOCKUP_MAX_GC];
static void gpio_mockup_unregister_pdevs(void) static void gpio_mockup_unregister_pdevs(void)
{ {
struct platform_device *pdev;
struct fwnode_handle *fwnode;
int i; int i;
for (i = 0; i < GPIO_MOCKUP_MAX_GC; i++) for (i = 0; i < GPIO_MOCKUP_MAX_GC; i++) {
platform_device_unregister(gpio_mockup_pdevs[i]); pdev = gpio_mockup_pdevs[i];
if (!pdev)
continue;
fwnode = dev_fwnode(&pdev->dev);
platform_device_unregister(pdev);
fwnode_remove_software_node(fwnode);
}
} }
static __init char **gpio_mockup_make_line_names(const char *label, static __init char **gpio_mockup_make_line_names(const char *label,
@ -508,6 +517,7 @@ static int __init gpio_mockup_register_chip(int idx)
struct property_entry properties[GPIO_MOCKUP_MAX_PROP]; struct property_entry properties[GPIO_MOCKUP_MAX_PROP];
struct platform_device_info pdevinfo; struct platform_device_info pdevinfo;
struct platform_device *pdev; struct platform_device *pdev;
struct fwnode_handle *fwnode;
char **line_names = NULL; char **line_names = NULL;
char chip_label[32]; char chip_label[32];
int prop = 0, base; int prop = 0, base;
@ -536,13 +546,18 @@ static int __init gpio_mockup_register_chip(int idx)
"gpio-line-names", line_names, ngpio); "gpio-line-names", line_names, ngpio);
} }
fwnode = fwnode_create_software_node(properties, NULL);
if (IS_ERR(fwnode))
return PTR_ERR(fwnode);
pdevinfo.name = "gpio-mockup"; pdevinfo.name = "gpio-mockup";
pdevinfo.id = idx; pdevinfo.id = idx;
pdevinfo.properties = properties; pdevinfo.fwnode = fwnode;
pdev = platform_device_register_full(&pdevinfo); pdev = platform_device_register_full(&pdevinfo);
kfree_strarray(line_names, ngpio); kfree_strarray(line_names, ngpio);
if (IS_ERR(pdev)) { if (IS_ERR(pdev)) {
fwnode_remove_software_node(fwnode);
pr_err("error registering device"); pr_err("error registering device");
return PTR_ERR(pdev); return PTR_ERR(pdev);
} }

@ -559,21 +559,21 @@ static int pca953x_gpio_set_pull_up_down(struct pca953x_chip *chip,
mutex_lock(&chip->i2c_lock); mutex_lock(&chip->i2c_lock);
/* Disable pull-up/pull-down */
ret = regmap_write_bits(chip->regmap, pull_en_reg, bit, 0);
if (ret)
goto exit;
/* Configure pull-up/pull-down */ /* Configure pull-up/pull-down */
if (config == PIN_CONFIG_BIAS_PULL_UP) if (config == PIN_CONFIG_BIAS_PULL_UP)
ret = regmap_write_bits(chip->regmap, pull_sel_reg, bit, bit); ret = regmap_write_bits(chip->regmap, pull_sel_reg, bit, bit);
else if (config == PIN_CONFIG_BIAS_PULL_DOWN) else if (config == PIN_CONFIG_BIAS_PULL_DOWN)
ret = regmap_write_bits(chip->regmap, pull_sel_reg, bit, 0); ret = regmap_write_bits(chip->regmap, pull_sel_reg, bit, 0);
else
ret = 0;
if (ret) if (ret)
goto exit; goto exit;
/* Enable pull-up/pull-down */ /* Disable/Enable pull-up/pull-down */
ret = regmap_write_bits(chip->regmap, pull_en_reg, bit, bit); if (config == PIN_CONFIG_BIAS_DISABLE)
ret = regmap_write_bits(chip->regmap, pull_en_reg, bit, 0);
else
ret = regmap_write_bits(chip->regmap, pull_en_reg, bit, bit);
exit: exit:
mutex_unlock(&chip->i2c_lock); mutex_unlock(&chip->i2c_lock);
@ -587,7 +587,9 @@ static int pca953x_gpio_set_config(struct gpio_chip *gc, unsigned int offset,
switch (pinconf_to_config_param(config)) { switch (pinconf_to_config_param(config)) {
case PIN_CONFIG_BIAS_PULL_UP: case PIN_CONFIG_BIAS_PULL_UP:
case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
case PIN_CONFIG_BIAS_PULL_DOWN: case PIN_CONFIG_BIAS_PULL_DOWN:
case PIN_CONFIG_BIAS_DISABLE:
return pca953x_gpio_set_pull_up_down(chip, offset, config); return pca953x_gpio_set_pull_up_down(chip, offset, config);
default: default:
return -ENOTSUPP; return -ENOTSUPP;

@ -1300,18 +1300,6 @@ static enum drm_mode_status ast_mode_valid(struct drm_connector *connector,
return flags; return flags;
} }
static enum drm_connector_status ast_connector_detect(struct drm_connector
*connector, bool force)
{
int r;
r = ast_get_modes(connector);
if (r <= 0)
return connector_status_disconnected;
return connector_status_connected;
}
static void ast_connector_destroy(struct drm_connector *connector) static void ast_connector_destroy(struct drm_connector *connector)
{ {
struct ast_connector *ast_connector = to_ast_connector(connector); struct ast_connector *ast_connector = to_ast_connector(connector);
@ -1327,7 +1315,6 @@ static const struct drm_connector_helper_funcs ast_connector_helper_funcs = {
static const struct drm_connector_funcs ast_connector_funcs = { static const struct drm_connector_funcs ast_connector_funcs = {
.reset = drm_atomic_helper_connector_reset, .reset = drm_atomic_helper_connector_reset,
.detect = ast_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes, .fill_modes = drm_helper_probe_single_connector_modes,
.destroy = ast_connector_destroy, .destroy = ast_connector_destroy,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
@ -1355,8 +1342,7 @@ static int ast_connector_init(struct drm_device *dev)
connector->interlace_allowed = 0; connector->interlace_allowed = 0;
connector->doublescan_allowed = 0; connector->doublescan_allowed = 0;
connector->polled = DRM_CONNECTOR_POLL_CONNECT | connector->polled = DRM_CONNECTOR_POLL_CONNECT;
DRM_CONNECTOR_POLL_DISCONNECT;
drm_connector_attach_encoder(connector, encoder); drm_connector_attach_encoder(connector, encoder);
@ -1425,8 +1411,6 @@ int ast_mode_config_init(struct ast_private *ast)
drm_mode_config_reset(dev); drm_mode_config_reset(dev);
drm_kms_helper_poll_init(dev);
return 0; return 0;
} }

@ -1834,11 +1834,20 @@ static void connector_bad_edid(struct drm_connector *connector,
u8 *edid, int num_blocks) u8 *edid, int num_blocks)
{ {
int i; int i;
u8 num_of_ext = edid[0x7e]; u8 last_block;
/*
* 0x7e in the EDID is the number of extension blocks. The EDID
* is 1 (base block) + num_ext_blocks big. That means we can think
* of 0x7e in the EDID of the _index_ of the last block in the
* combined chunk of memory.
*/
last_block = edid[0x7e];
/* Calculate real checksum for the last edid extension block data */ /* Calculate real checksum for the last edid extension block data */
connector->real_edid_checksum = if (last_block < num_blocks)
drm_edid_block_checksum(edid + num_of_ext * EDID_LENGTH); connector->real_edid_checksum =
drm_edid_block_checksum(edid + last_block * EDID_LENGTH);
if (connector->bad_edid_counter++ && !drm_debug_enabled(DRM_UT_KMS)) if (connector->bad_edid_counter++ && !drm_debug_enabled(DRM_UT_KMS))
return; return;

@ -1506,6 +1506,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
{ {
struct drm_client_dev *client = &fb_helper->client; struct drm_client_dev *client = &fb_helper->client;
struct drm_device *dev = fb_helper->dev; struct drm_device *dev = fb_helper->dev;
struct drm_mode_config *config = &dev->mode_config;
int ret = 0; int ret = 0;
int crtc_count = 0; int crtc_count = 0;
struct drm_connector_list_iter conn_iter; struct drm_connector_list_iter conn_iter;
@ -1663,6 +1664,11 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
/* Handle our overallocation */ /* Handle our overallocation */
sizes.surface_height *= drm_fbdev_overalloc; sizes.surface_height *= drm_fbdev_overalloc;
sizes.surface_height /= 100; sizes.surface_height /= 100;
if (sizes.surface_height > config->max_height) {
drm_dbg_kms(dev, "Fbdev over-allocation too large; clamping height to %d\n",
config->max_height);
sizes.surface_height = config->max_height;
}
/* push down into drivers */ /* push down into drivers */
ret = (*fb_helper->funcs->fb_probe)(fb_helper, &sizes); ret = (*fb_helper->funcs->fb_probe)(fb_helper, &sizes);

@ -46,6 +46,7 @@ int hyperv_mode_config_init(struct hyperv_drm_device *hv);
int hyperv_update_vram_location(struct hv_device *hdev, phys_addr_t vram_pp); int hyperv_update_vram_location(struct hv_device *hdev, phys_addr_t vram_pp);
int hyperv_update_situation(struct hv_device *hdev, u8 active, u32 bpp, int hyperv_update_situation(struct hv_device *hdev, u8 active, u32 bpp,
u32 w, u32 h, u32 pitch); u32 w, u32 h, u32 pitch);
int hyperv_hide_hw_ptr(struct hv_device *hdev);
int hyperv_update_dirt(struct hv_device *hdev, struct drm_rect *rect); int hyperv_update_dirt(struct hv_device *hdev, struct drm_rect *rect);
int hyperv_connect_vsp(struct hv_device *hdev); int hyperv_connect_vsp(struct hv_device *hdev);

@ -101,6 +101,7 @@ static void hyperv_pipe_enable(struct drm_simple_display_pipe *pipe,
struct hyperv_drm_device *hv = to_hv(pipe->crtc.dev); struct hyperv_drm_device *hv = to_hv(pipe->crtc.dev);
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
hyperv_hide_hw_ptr(hv->hdev);
hyperv_update_situation(hv->hdev, 1, hv->screen_depth, hyperv_update_situation(hv->hdev, 1, hv->screen_depth,
crtc_state->mode.hdisplay, crtc_state->mode.hdisplay,
crtc_state->mode.vdisplay, crtc_state->mode.vdisplay,

@ -299,6 +299,55 @@ int hyperv_update_situation(struct hv_device *hdev, u8 active, u32 bpp,
return 0; return 0;
} }
/*
* Hyper-V supports a hardware cursor feature. It's not used by Linux VM,
* but the Hyper-V host still draws a point as an extra mouse pointer,
* which is unwanted, especially when Xorg is running.
*
* The hyperv_fb driver uses synthvid_send_ptr() to hide the unwanted
* pointer, by setting msg.ptr_pos.is_visible = 1 and setting the
* msg.ptr_shape.data. Note: setting msg.ptr_pos.is_visible to 0 doesn't
* work in tests.
*
* Copy synthvid_send_ptr() to hyperv_drm and rename it to
* hyperv_hide_hw_ptr(). Note: hyperv_hide_hw_ptr() is also called in the
* handler of the SYNTHVID_FEATURE_CHANGE event, otherwise the host still
* draws an extra unwanted mouse pointer after the VM Connection window is
* closed and reopened.
*/
int hyperv_hide_hw_ptr(struct hv_device *hdev)
{
struct synthvid_msg msg;
memset(&msg, 0, sizeof(struct synthvid_msg));
msg.vid_hdr.type = SYNTHVID_POINTER_POSITION;
msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) +
sizeof(struct synthvid_pointer_position);
msg.ptr_pos.is_visible = 1;
msg.ptr_pos.video_output = 0;
msg.ptr_pos.image_x = 0;
msg.ptr_pos.image_y = 0;
hyperv_sendpacket(hdev, &msg);
memset(&msg, 0, sizeof(struct synthvid_msg));
msg.vid_hdr.type = SYNTHVID_POINTER_SHAPE;
msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) +
sizeof(struct synthvid_pointer_shape);
msg.ptr_shape.part_idx = SYNTHVID_CURSOR_COMPLETE;
msg.ptr_shape.is_argb = 1;
msg.ptr_shape.width = 1;
msg.ptr_shape.height = 1;
msg.ptr_shape.hot_x = 0;
msg.ptr_shape.hot_y = 0;
msg.ptr_shape.data[0] = 0;
msg.ptr_shape.data[1] = 1;
msg.ptr_shape.data[2] = 1;
msg.ptr_shape.data[3] = 1;
hyperv_sendpacket(hdev, &msg);
return 0;
}
int hyperv_update_dirt(struct hv_device *hdev, struct drm_rect *rect) int hyperv_update_dirt(struct hv_device *hdev, struct drm_rect *rect)
{ {
struct hyperv_drm_device *hv = hv_get_drvdata(hdev); struct hyperv_drm_device *hv = hv_get_drvdata(hdev);
@ -392,8 +441,11 @@ static void hyperv_receive_sub(struct hv_device *hdev)
return; return;
} }
if (msg->vid_hdr.type == SYNTHVID_FEATURE_CHANGE) if (msg->vid_hdr.type == SYNTHVID_FEATURE_CHANGE) {
hv->dirt_needed = msg->feature_chg.is_dirt_needed; hv->dirt_needed = msg->feature_chg.is_dirt_needed;
if (hv->dirt_needed)
hyperv_hide_hw_ptr(hv->hdev);
}
} }
static void hyperv_receive(void *ctx) static void hyperv_receive(void *ctx)

@ -186,13 +186,16 @@ void intel_dsm_get_bios_data_funcs_supported(struct drm_i915_private *i915)
{ {
struct pci_dev *pdev = to_pci_dev(i915->drm.dev); struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
acpi_handle dhandle; acpi_handle dhandle;
union acpi_object *obj;
dhandle = ACPI_HANDLE(&pdev->dev); dhandle = ACPI_HANDLE(&pdev->dev);
if (!dhandle) if (!dhandle)
return; return;
acpi_evaluate_dsm(dhandle, &intel_dsm_guid2, INTEL_DSM_REVISION_ID, obj = acpi_evaluate_dsm(dhandle, &intel_dsm_guid2, INTEL_DSM_REVISION_ID,
INTEL_DSM_FN_GET_BIOS_DATA_FUNCS_SUPPORTED, NULL); INTEL_DSM_FN_GET_BIOS_DATA_FUNCS_SUPPORTED, NULL);
if (obj)
ACPI_FREE(obj);
} }
/* /*

@ -937,6 +937,10 @@ static struct i915_gem_engines *user_engines(struct i915_gem_context *ctx,
unsigned int n; unsigned int n;
e = alloc_engines(num_engines); e = alloc_engines(num_engines);
if (!e)
return ERR_PTR(-ENOMEM);
e->num_engines = num_engines;
for (n = 0; n < num_engines; n++) { for (n = 0; n < num_engines; n++) {
struct intel_context *ce; struct intel_context *ce;
int ret; int ret;
@ -970,7 +974,6 @@ static struct i915_gem_engines *user_engines(struct i915_gem_context *ctx,
goto free_engines; goto free_engines;
} }
} }
e->num_engines = num_engines;
return e; return e;

@ -421,6 +421,7 @@ void intel_context_fini(struct intel_context *ce)
mutex_destroy(&ce->pin_mutex); mutex_destroy(&ce->pin_mutex);
i915_active_fini(&ce->active); i915_active_fini(&ce->active);
i915_sw_fence_fini(&ce->guc_blocked);
} }
void i915_context_module_exit(void) void i915_context_module_exit(void)

@ -66,7 +66,8 @@ static const struct drm_crtc_funcs kmb_crtc_funcs = {
.disable_vblank = kmb_crtc_disable_vblank, .disable_vblank = kmb_crtc_disable_vblank,
}; };
static void kmb_crtc_set_mode(struct drm_crtc *crtc) static void kmb_crtc_set_mode(struct drm_crtc *crtc,
struct drm_atomic_state *old_state)
{ {
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
struct drm_display_mode *m = &crtc->state->adjusted_mode; struct drm_display_mode *m = &crtc->state->adjusted_mode;
@ -75,7 +76,7 @@ static void kmb_crtc_set_mode(struct drm_crtc *crtc)
unsigned int val = 0; unsigned int val = 0;
/* Initialize mipi */ /* Initialize mipi */
kmb_dsi_mode_set(kmb->kmb_dsi, m, kmb->sys_clk_mhz); kmb_dsi_mode_set(kmb->kmb_dsi, m, kmb->sys_clk_mhz, old_state);
drm_info(dev, drm_info(dev,
"vfp= %d vbp= %d vsync_len=%d hfp=%d hbp=%d hsync_len=%d\n", "vfp= %d vbp= %d vsync_len=%d hfp=%d hbp=%d hsync_len=%d\n",
m->crtc_vsync_start - m->crtc_vdisplay, m->crtc_vsync_start - m->crtc_vdisplay,
@ -138,7 +139,7 @@ static void kmb_crtc_atomic_enable(struct drm_crtc *crtc,
struct kmb_drm_private *kmb = crtc_to_kmb_priv(crtc); struct kmb_drm_private *kmb = crtc_to_kmb_priv(crtc);
clk_prepare_enable(kmb->kmb_clk.clk_lcd); clk_prepare_enable(kmb->kmb_clk.clk_lcd);
kmb_crtc_set_mode(crtc); kmb_crtc_set_mode(crtc, state);
drm_crtc_vblank_on(crtc); drm_crtc_vblank_on(crtc);
} }
@ -185,11 +186,45 @@ static void kmb_crtc_atomic_flush(struct drm_crtc *crtc,
spin_unlock_irq(&crtc->dev->event_lock); spin_unlock_irq(&crtc->dev->event_lock);
} }
static enum drm_mode_status
kmb_crtc_mode_valid(struct drm_crtc *crtc,
const struct drm_display_mode *mode)
{
int refresh;
struct drm_device *dev = crtc->dev;
int vfp = mode->vsync_start - mode->vdisplay;
if (mode->vdisplay < KMB_CRTC_MAX_HEIGHT) {
drm_dbg(dev, "height = %d less than %d",
mode->vdisplay, KMB_CRTC_MAX_HEIGHT);
return MODE_BAD_VVALUE;
}
if (mode->hdisplay < KMB_CRTC_MAX_WIDTH) {
drm_dbg(dev, "width = %d less than %d",
mode->hdisplay, KMB_CRTC_MAX_WIDTH);
return MODE_BAD_HVALUE;
}
refresh = drm_mode_vrefresh(mode);
if (refresh < KMB_MIN_VREFRESH || refresh > KMB_MAX_VREFRESH) {
drm_dbg(dev, "refresh = %d less than %d or greater than %d",
refresh, KMB_MIN_VREFRESH, KMB_MAX_VREFRESH);
return MODE_BAD;
}
if (vfp < KMB_CRTC_MIN_VFP) {
drm_dbg(dev, "vfp = %d less than %d", vfp, KMB_CRTC_MIN_VFP);
return MODE_BAD;
}
return MODE_OK;
}
static const struct drm_crtc_helper_funcs kmb_crtc_helper_funcs = { static const struct drm_crtc_helper_funcs kmb_crtc_helper_funcs = {
.atomic_begin = kmb_crtc_atomic_begin, .atomic_begin = kmb_crtc_atomic_begin,
.atomic_enable = kmb_crtc_atomic_enable, .atomic_enable = kmb_crtc_atomic_enable,
.atomic_disable = kmb_crtc_atomic_disable, .atomic_disable = kmb_crtc_atomic_disable,
.atomic_flush = kmb_crtc_atomic_flush, .atomic_flush = kmb_crtc_atomic_flush,
.mode_valid = kmb_crtc_mode_valid,
}; };
int kmb_setup_crtc(struct drm_device *drm) int kmb_setup_crtc(struct drm_device *drm)

@ -380,7 +380,7 @@ static irqreturn_t handle_lcd_irq(struct drm_device *dev)
if (val & LAYER3_DMA_FIFO_UNDERFLOW) if (val & LAYER3_DMA_FIFO_UNDERFLOW)
drm_dbg(&kmb->drm, drm_dbg(&kmb->drm,
"LAYER3:GL1 DMA UNDERFLOW val = 0x%lx", val); "LAYER3:GL1 DMA UNDERFLOW val = 0x%lx", val);
if (val & LAYER3_DMA_FIFO_UNDERFLOW) if (val & LAYER3_DMA_FIFO_OVERFLOW)
drm_dbg(&kmb->drm, drm_dbg(&kmb->drm,
"LAYER3:GL1 DMA OVERFLOW val = 0x%lx", val); "LAYER3:GL1 DMA OVERFLOW val = 0x%lx", val);
} }

@ -20,11 +20,18 @@
#define DRIVER_MAJOR 1 #define DRIVER_MAJOR 1
#define DRIVER_MINOR 1 #define DRIVER_MINOR 1
/* Platform definitions */
#define KMB_CRTC_MIN_VFP 4
#define KMB_CRTC_MAX_WIDTH 1920 /* max width in pixels */
#define KMB_CRTC_MAX_HEIGHT 1080 /* max height in pixels */
#define KMB_CRTC_MIN_WIDTH 1920
#define KMB_CRTC_MIN_HEIGHT 1080
#define KMB_FB_MAX_WIDTH 1920 #define KMB_FB_MAX_WIDTH 1920
#define KMB_FB_MAX_HEIGHT 1080 #define KMB_FB_MAX_HEIGHT 1080
#define KMB_FB_MIN_WIDTH 1 #define KMB_FB_MIN_WIDTH 1
#define KMB_FB_MIN_HEIGHT 1 #define KMB_FB_MIN_HEIGHT 1
#define KMB_MIN_VREFRESH 59 /*vertical refresh in Hz */
#define KMB_MAX_VREFRESH 60 /*vertical refresh in Hz */
#define KMB_LCD_DEFAULT_CLK 200000000 #define KMB_LCD_DEFAULT_CLK 200000000
#define KMB_SYS_CLK_MHZ 500 #define KMB_SYS_CLK_MHZ 500
@ -50,6 +57,7 @@ struct kmb_drm_private {
spinlock_t irq_lock; spinlock_t irq_lock;
int irq_lcd; int irq_lcd;
int sys_clk_mhz; int sys_clk_mhz;
struct disp_cfg init_disp_cfg[KMB_MAX_PLANES];
struct layer_status plane_status[KMB_MAX_PLANES]; struct layer_status plane_status[KMB_MAX_PLANES];
int kmb_under_flow; int kmb_under_flow;
int kmb_flush_done; int kmb_flush_done;

@ -482,6 +482,10 @@ static u32 mipi_tx_fg_section_cfg(struct kmb_dsi *kmb_dsi,
return 0; return 0;
} }
#define CLK_DIFF_LOW 50
#define CLK_DIFF_HI 60
#define SYSCLK_500 500
static void mipi_tx_fg_cfg_regs(struct kmb_dsi *kmb_dsi, u8 frame_gen, static void mipi_tx_fg_cfg_regs(struct kmb_dsi *kmb_dsi, u8 frame_gen,
struct mipi_tx_frame_timing_cfg *fg_cfg) struct mipi_tx_frame_timing_cfg *fg_cfg)
{ {
@ -492,7 +496,12 @@ static void mipi_tx_fg_cfg_regs(struct kmb_dsi *kmb_dsi, u8 frame_gen,
/* 500 Mhz system clock minus 50 to account for the difference in /* 500 Mhz system clock minus 50 to account for the difference in
* MIPI clock speed in RTL tests * MIPI clock speed in RTL tests
*/ */
sysclk = kmb_dsi->sys_clk_mhz - 50; if (kmb_dsi->sys_clk_mhz == SYSCLK_500) {
sysclk = kmb_dsi->sys_clk_mhz - CLK_DIFF_LOW;
} else {
/* 700 Mhz clk*/
sysclk = kmb_dsi->sys_clk_mhz - CLK_DIFF_HI;
}
/* PPL-Pixel Packing Layer, LLP-Low Level Protocol /* PPL-Pixel Packing Layer, LLP-Low Level Protocol
* Frame genartor timing parameters are clocked on the system clock, * Frame genartor timing parameters are clocked on the system clock,
@ -1322,7 +1331,8 @@ static u32 mipi_tx_init_dphy(struct kmb_dsi *kmb_dsi,
return 0; return 0;
} }
static void connect_lcd_to_mipi(struct kmb_dsi *kmb_dsi) static void connect_lcd_to_mipi(struct kmb_dsi *kmb_dsi,
struct drm_atomic_state *old_state)
{ {
struct regmap *msscam; struct regmap *msscam;
@ -1331,7 +1341,7 @@ static void connect_lcd_to_mipi(struct kmb_dsi *kmb_dsi)
dev_dbg(kmb_dsi->dev, "failed to get msscam syscon"); dev_dbg(kmb_dsi->dev, "failed to get msscam syscon");
return; return;
} }
drm_atomic_bridge_chain_enable(adv_bridge, old_state);
/* DISABLE MIPI->CIF CONNECTION */ /* DISABLE MIPI->CIF CONNECTION */
regmap_write(msscam, MSS_MIPI_CIF_CFG, 0); regmap_write(msscam, MSS_MIPI_CIF_CFG, 0);
@ -1342,7 +1352,7 @@ static void connect_lcd_to_mipi(struct kmb_dsi *kmb_dsi)
} }
int kmb_dsi_mode_set(struct kmb_dsi *kmb_dsi, struct drm_display_mode *mode, int kmb_dsi_mode_set(struct kmb_dsi *kmb_dsi, struct drm_display_mode *mode,
int sys_clk_mhz) int sys_clk_mhz, struct drm_atomic_state *old_state)
{ {
u64 data_rate; u64 data_rate;
@ -1384,18 +1394,13 @@ int kmb_dsi_mode_set(struct kmb_dsi *kmb_dsi, struct drm_display_mode *mode,
mipi_tx_init_cfg.lane_rate_mbps = data_rate; mipi_tx_init_cfg.lane_rate_mbps = data_rate;
} }
kmb_write_mipi(kmb_dsi, DPHY_ENABLE, 0);
kmb_write_mipi(kmb_dsi, DPHY_INIT_CTRL0, 0);
kmb_write_mipi(kmb_dsi, DPHY_INIT_CTRL1, 0);
kmb_write_mipi(kmb_dsi, DPHY_INIT_CTRL2, 0);
/* Initialize mipi controller */ /* Initialize mipi controller */
mipi_tx_init_cntrl(kmb_dsi, &mipi_tx_init_cfg); mipi_tx_init_cntrl(kmb_dsi, &mipi_tx_init_cfg);
/* Dphy initialization */ /* Dphy initialization */
mipi_tx_init_dphy(kmb_dsi, &mipi_tx_init_cfg); mipi_tx_init_dphy(kmb_dsi, &mipi_tx_init_cfg);
connect_lcd_to_mipi(kmb_dsi); connect_lcd_to_mipi(kmb_dsi, old_state);
dev_info(kmb_dsi->dev, "mipi hw initialized"); dev_info(kmb_dsi->dev, "mipi hw initialized");
return 0; return 0;

@ -380,7 +380,7 @@ int kmb_dsi_host_bridge_init(struct device *dev);
struct kmb_dsi *kmb_dsi_init(struct platform_device *pdev); struct kmb_dsi *kmb_dsi_init(struct platform_device *pdev);
void kmb_dsi_host_unregister(struct kmb_dsi *kmb_dsi); void kmb_dsi_host_unregister(struct kmb_dsi *kmb_dsi);
int kmb_dsi_mode_set(struct kmb_dsi *kmb_dsi, struct drm_display_mode *mode, int kmb_dsi_mode_set(struct kmb_dsi *kmb_dsi, struct drm_display_mode *mode,
int sys_clk_mhz); int sys_clk_mhz, struct drm_atomic_state *old_state);
int kmb_dsi_map_mmio(struct kmb_dsi *kmb_dsi); int kmb_dsi_map_mmio(struct kmb_dsi *kmb_dsi);
int kmb_dsi_clk_init(struct kmb_dsi *kmb_dsi); int kmb_dsi_clk_init(struct kmb_dsi *kmb_dsi);
int kmb_dsi_encoder_init(struct drm_device *dev, struct kmb_dsi *kmb_dsi); int kmb_dsi_encoder_init(struct drm_device *dev, struct kmb_dsi *kmb_dsi);

@ -67,8 +67,21 @@ static const u32 kmb_formats_v[] = {
static unsigned int check_pixel_format(struct drm_plane *plane, u32 format) static unsigned int check_pixel_format(struct drm_plane *plane, u32 format)
{ {
struct kmb_drm_private *kmb;
struct kmb_plane *kmb_plane = to_kmb_plane(plane);
int i; int i;
int plane_id = kmb_plane->id;
struct disp_cfg init_disp_cfg;
kmb = to_kmb(plane->dev);
init_disp_cfg = kmb->init_disp_cfg[plane_id];
/* Due to HW limitations, changing pixel format after initial
* plane configuration is not supported.
*/
if (init_disp_cfg.format && init_disp_cfg.format != format) {
drm_dbg(&kmb->drm, "Cannot change format after initial plane configuration");
return -EINVAL;
}
for (i = 0; i < plane->format_count; i++) { for (i = 0; i < plane->format_count; i++) {
if (plane->format_types[i] == format) if (plane->format_types[i] == format)
return 0; return 0;
@ -81,11 +94,17 @@ static int kmb_plane_atomic_check(struct drm_plane *plane,
{ {
struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
plane); plane);
struct kmb_drm_private *kmb;
struct kmb_plane *kmb_plane = to_kmb_plane(plane);
int plane_id = kmb_plane->id;
struct disp_cfg init_disp_cfg;
struct drm_framebuffer *fb; struct drm_framebuffer *fb;
int ret; int ret;
struct drm_crtc_state *crtc_state; struct drm_crtc_state *crtc_state;
bool can_position; bool can_position;
kmb = to_kmb(plane->dev);
init_disp_cfg = kmb->init_disp_cfg[plane_id];
fb = new_plane_state->fb; fb = new_plane_state->fb;
if (!fb || !new_plane_state->crtc) if (!fb || !new_plane_state->crtc)
return 0; return 0;
@ -99,6 +118,16 @@ static int kmb_plane_atomic_check(struct drm_plane *plane,
new_plane_state->crtc_w < KMB_FB_MIN_WIDTH || new_plane_state->crtc_w < KMB_FB_MIN_WIDTH ||
new_plane_state->crtc_h < KMB_FB_MIN_HEIGHT) new_plane_state->crtc_h < KMB_FB_MIN_HEIGHT)
return -EINVAL; return -EINVAL;
/* Due to HW limitations, changing plane height or width after
* initial plane configuration is not supported.
*/
if ((init_disp_cfg.width && init_disp_cfg.height) &&
(init_disp_cfg.width != fb->width ||
init_disp_cfg.height != fb->height)) {
drm_dbg(&kmb->drm, "Cannot change plane height or width after initial configuration");
return -EINVAL;
}
can_position = (plane->type == DRM_PLANE_TYPE_OVERLAY); can_position = (plane->type == DRM_PLANE_TYPE_OVERLAY);
crtc_state = crtc_state =
drm_atomic_get_existing_crtc_state(state, drm_atomic_get_existing_crtc_state(state,
@ -335,6 +364,7 @@ static void kmb_plane_atomic_update(struct drm_plane *plane,
unsigned char plane_id; unsigned char plane_id;
int num_planes; int num_planes;
static dma_addr_t addr[MAX_SUB_PLANES]; static dma_addr_t addr[MAX_SUB_PLANES];
struct disp_cfg *init_disp_cfg;
if (!plane || !new_plane_state || !old_plane_state) if (!plane || !new_plane_state || !old_plane_state)
return; return;
@ -357,7 +387,8 @@ static void kmb_plane_atomic_update(struct drm_plane *plane,
} }
spin_unlock_irq(&kmb->irq_lock); spin_unlock_irq(&kmb->irq_lock);
src_w = (new_plane_state->src_w >> 16); init_disp_cfg = &kmb->init_disp_cfg[plane_id];
src_w = new_plane_state->src_w >> 16;
src_h = new_plane_state->src_h >> 16; src_h = new_plane_state->src_h >> 16;
crtc_x = new_plane_state->crtc_x; crtc_x = new_plane_state->crtc_x;
crtc_y = new_plane_state->crtc_y; crtc_y = new_plane_state->crtc_y;
@ -500,6 +531,16 @@ static void kmb_plane_atomic_update(struct drm_plane *plane,
/* Enable DMA */ /* Enable DMA */
kmb_write_lcd(kmb, LCD_LAYERn_DMA_CFG(plane_id), dma_cfg); kmb_write_lcd(kmb, LCD_LAYERn_DMA_CFG(plane_id), dma_cfg);
/* Save initial display config */
if (!init_disp_cfg->width ||
!init_disp_cfg->height ||
!init_disp_cfg->format) {
init_disp_cfg->width = width;
init_disp_cfg->height = height;
init_disp_cfg->format = fb->format->format;
}
drm_dbg(&kmb->drm, "dma_cfg=0x%x LCD_DMA_CFG=0x%x\n", dma_cfg, drm_dbg(&kmb->drm, "dma_cfg=0x%x LCD_DMA_CFG=0x%x\n", dma_cfg,
kmb_read_lcd(kmb, LCD_LAYERn_DMA_CFG(plane_id))); kmb_read_lcd(kmb, LCD_LAYERn_DMA_CFG(plane_id)));

@ -63,6 +63,12 @@ struct layer_status {
u32 ctrl; u32 ctrl;
}; };
struct disp_cfg {
unsigned int width;
unsigned int height;
unsigned int format;
};
struct kmb_plane *kmb_plane_init(struct drm_device *drm); struct kmb_plane *kmb_plane_init(struct drm_device *drm);
void kmb_plane_destroy(struct drm_plane *plane); void kmb_plane_destroy(struct drm_plane *plane);
#endif /* __KMB_PLANE_H__ */ #endif /* __KMB_PLANE_H__ */

@ -4,8 +4,6 @@
*/ */
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/dma-mapping.h>
#include <linux/mailbox_controller.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/soc/mediatek/mtk-cmdq.h> #include <linux/soc/mediatek/mtk-cmdq.h>
#include <linux/soc/mediatek/mtk-mmsys.h> #include <linux/soc/mediatek/mtk-mmsys.h>
@ -52,11 +50,8 @@ struct mtk_drm_crtc {
bool pending_async_planes; bool pending_async_planes;
#if IS_REACHABLE(CONFIG_MTK_CMDQ) #if IS_REACHABLE(CONFIG_MTK_CMDQ)
struct mbox_client cmdq_cl; struct cmdq_client *cmdq_client;
struct mbox_chan *cmdq_chan;
struct cmdq_pkt cmdq_handle;
u32 cmdq_event; u32 cmdq_event;
u32 cmdq_vblank_cnt;
#endif #endif
struct device *mmsys_dev; struct device *mmsys_dev;
@ -227,79 +222,9 @@ struct mtk_ddp_comp *mtk_drm_ddp_comp_for_plane(struct drm_crtc *crtc,
} }
#if IS_REACHABLE(CONFIG_MTK_CMDQ) #if IS_REACHABLE(CONFIG_MTK_CMDQ)
static int mtk_drm_cmdq_pkt_create(struct mbox_chan *chan, struct cmdq_pkt *pkt, static void ddp_cmdq_cb(struct cmdq_cb_data data)
size_t size)
{ {
struct device *dev; cmdq_pkt_destroy(data.data);
dma_addr_t dma_addr;
pkt->va_base = kzalloc(size, GFP_KERNEL);
if (!pkt->va_base) {
kfree(pkt);
return -ENOMEM;
}
pkt->buf_size = size;
dev = chan->mbox->dev;
dma_addr = dma_map_single(dev, pkt->va_base, pkt->buf_size,
DMA_TO_DEVICE);
if (dma_mapping_error(dev, dma_addr)) {
dev_err(dev, "dma map failed, size=%u\n", (u32)(u64)size);
kfree(pkt->va_base);
kfree(pkt);
return -ENOMEM;
}
pkt->pa_base = dma_addr;
return 0;
}
static void mtk_drm_cmdq_pkt_destroy(struct mbox_chan *chan, struct cmdq_pkt *pkt)
{
dma_unmap_single(chan->mbox->dev, pkt->pa_base, pkt->buf_size,
DMA_TO_DEVICE);
kfree(pkt->va_base);
kfree(pkt);
}
static void ddp_cmdq_cb(struct mbox_client *cl, void *mssg)
{
struct mtk_drm_crtc *mtk_crtc = container_of(cl, struct mtk_drm_crtc, cmdq_cl);
struct cmdq_cb_data *data = mssg;
struct mtk_crtc_state *state;
unsigned int i;
state = to_mtk_crtc_state(mtk_crtc->base.state);
state->pending_config = false;
if (mtk_crtc->pending_planes) {
for (i = 0; i < mtk_crtc->layer_nr; i++) {
struct drm_plane *plane = &mtk_crtc->planes[i];
struct mtk_plane_state *plane_state;
plane_state = to_mtk_plane_state(plane->state);
plane_state->pending.config = false;
}
mtk_crtc->pending_planes = false;
}
if (mtk_crtc->pending_async_planes) {
for (i = 0; i < mtk_crtc->layer_nr; i++) {
struct drm_plane *plane = &mtk_crtc->planes[i];
struct mtk_plane_state *plane_state;
plane_state = to_mtk_plane_state(plane->state);
plane_state->pending.async_config = false;
}
mtk_crtc->pending_async_planes = false;
}
mtk_crtc->cmdq_vblank_cnt = 0;
mtk_drm_cmdq_pkt_destroy(mtk_crtc->cmdq_chan, data->pkt);
} }
#endif #endif
@ -453,8 +378,7 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc,
state->pending_vrefresh, 0, state->pending_vrefresh, 0,
cmdq_handle); cmdq_handle);
if (!cmdq_handle) state->pending_config = false;
state->pending_config = false;
} }
if (mtk_crtc->pending_planes) { if (mtk_crtc->pending_planes) {
@ -474,12 +398,9 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc,
mtk_ddp_comp_layer_config(comp, local_layer, mtk_ddp_comp_layer_config(comp, local_layer,
plane_state, plane_state,
cmdq_handle); cmdq_handle);
if (!cmdq_handle) plane_state->pending.config = false;
plane_state->pending.config = false;
} }
mtk_crtc->pending_planes = false;
if (!cmdq_handle)
mtk_crtc->pending_planes = false;
} }
if (mtk_crtc->pending_async_planes) { if (mtk_crtc->pending_async_planes) {
@ -499,12 +420,9 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc,
mtk_ddp_comp_layer_config(comp, local_layer, mtk_ddp_comp_layer_config(comp, local_layer,
plane_state, plane_state,
cmdq_handle); cmdq_handle);
if (!cmdq_handle) plane_state->pending.async_config = false;
plane_state->pending.async_config = false;
} }
mtk_crtc->pending_async_planes = false;
if (!cmdq_handle)
mtk_crtc->pending_async_planes = false;
} }
} }
@ -512,7 +430,7 @@ static void mtk_drm_crtc_update_config(struct mtk_drm_crtc *mtk_crtc,
bool needs_vblank) bool needs_vblank)
{ {
#if IS_REACHABLE(CONFIG_MTK_CMDQ) #if IS_REACHABLE(CONFIG_MTK_CMDQ)
struct cmdq_pkt *cmdq_handle = &mtk_crtc->cmdq_handle; struct cmdq_pkt *cmdq_handle;
#endif #endif
struct drm_crtc *crtc = &mtk_crtc->base; struct drm_crtc *crtc = &mtk_crtc->base;
struct mtk_drm_private *priv = crtc->dev->dev_private; struct mtk_drm_private *priv = crtc->dev->dev_private;
@ -550,24 +468,14 @@ static void mtk_drm_crtc_update_config(struct mtk_drm_crtc *mtk_crtc,
mtk_mutex_release(mtk_crtc->mutex); mtk_mutex_release(mtk_crtc->mutex);
} }
#if IS_REACHABLE(CONFIG_MTK_CMDQ) #if IS_REACHABLE(CONFIG_MTK_CMDQ)
if (mtk_crtc->cmdq_chan) { if (mtk_crtc->cmdq_client) {
mbox_flush(mtk_crtc->cmdq_chan, 2000); mbox_flush(mtk_crtc->cmdq_client->chan, 2000);
cmdq_handle->cmd_buf_size = 0; cmdq_handle = cmdq_pkt_create(mtk_crtc->cmdq_client, PAGE_SIZE);
cmdq_pkt_clear_event(cmdq_handle, mtk_crtc->cmdq_event); cmdq_pkt_clear_event(cmdq_handle, mtk_crtc->cmdq_event);
cmdq_pkt_wfe(cmdq_handle, mtk_crtc->cmdq_event, false); cmdq_pkt_wfe(cmdq_handle, mtk_crtc->cmdq_event, false);
mtk_crtc_ddp_config(crtc, cmdq_handle); mtk_crtc_ddp_config(crtc, cmdq_handle);
cmdq_pkt_finalize(cmdq_handle); cmdq_pkt_finalize(cmdq_handle);
dma_sync_single_for_device(mtk_crtc->cmdq_chan->mbox->dev, cmdq_pkt_flush_async(cmdq_handle, ddp_cmdq_cb, cmdq_handle);
cmdq_handle->pa_base,
cmdq_handle->cmd_buf_size,
DMA_TO_DEVICE);
/*
* CMDQ command should execute in next vblank,
* If it fail to execute in next 2 vblank, timeout happen.
*/
mtk_crtc->cmdq_vblank_cnt = 2;
mbox_send_message(mtk_crtc->cmdq_chan, cmdq_handle);
mbox_client_txdone(mtk_crtc->cmdq_chan, 0);
} }
#endif #endif
mtk_crtc->config_updating = false; mtk_crtc->config_updating = false;
@ -581,15 +489,12 @@ static void mtk_crtc_ddp_irq(void *data)
struct mtk_drm_private *priv = crtc->dev->dev_private; struct mtk_drm_private *priv = crtc->dev->dev_private;
#if IS_REACHABLE(CONFIG_MTK_CMDQ) #if IS_REACHABLE(CONFIG_MTK_CMDQ)
if (!priv->data->shadow_register && !mtk_crtc->cmdq_chan) if (!priv->data->shadow_register && !mtk_crtc->cmdq_client)
mtk_crtc_ddp_config(crtc, NULL);
else if (mtk_crtc->cmdq_vblank_cnt > 0 && --mtk_crtc->cmdq_vblank_cnt == 0)
DRM_ERROR("mtk_crtc %d CMDQ execute command timeout!\n",
drm_crtc_index(&mtk_crtc->base));
#else #else
if (!priv->data->shadow_register) if (!priv->data->shadow_register)
mtk_crtc_ddp_config(crtc, NULL);
#endif #endif
mtk_crtc_ddp_config(crtc, NULL);
mtk_drm_finish_page_flip(mtk_crtc); mtk_drm_finish_page_flip(mtk_crtc);
} }
@ -924,20 +829,16 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
mutex_init(&mtk_crtc->hw_lock); mutex_init(&mtk_crtc->hw_lock);
#if IS_REACHABLE(CONFIG_MTK_CMDQ) #if IS_REACHABLE(CONFIG_MTK_CMDQ)
mtk_crtc->cmdq_cl.dev = mtk_crtc->mmsys_dev; mtk_crtc->cmdq_client =
mtk_crtc->cmdq_cl.tx_block = false; cmdq_mbox_create(mtk_crtc->mmsys_dev,
mtk_crtc->cmdq_cl.knows_txdone = true; drm_crtc_index(&mtk_crtc->base));
mtk_crtc->cmdq_cl.rx_callback = ddp_cmdq_cb; if (IS_ERR(mtk_crtc->cmdq_client)) {
mtk_crtc->cmdq_chan =
mbox_request_channel(&mtk_crtc->cmdq_cl,
drm_crtc_index(&mtk_crtc->base));
if (IS_ERR(mtk_crtc->cmdq_chan)) {
dev_dbg(dev, "mtk_crtc %d failed to create mailbox client, writing register by CPU now\n", dev_dbg(dev, "mtk_crtc %d failed to create mailbox client, writing register by CPU now\n",
drm_crtc_index(&mtk_crtc->base)); drm_crtc_index(&mtk_crtc->base));
mtk_crtc->cmdq_chan = NULL; mtk_crtc->cmdq_client = NULL;
} }
if (mtk_crtc->cmdq_chan) { if (mtk_crtc->cmdq_client) {
ret = of_property_read_u32_index(priv->mutex_node, ret = of_property_read_u32_index(priv->mutex_node,
"mediatek,gce-events", "mediatek,gce-events",
drm_crtc_index(&mtk_crtc->base), drm_crtc_index(&mtk_crtc->base),
@ -945,18 +846,8 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
if (ret) { if (ret) {
dev_dbg(dev, "mtk_crtc %d failed to get mediatek,gce-events property\n", dev_dbg(dev, "mtk_crtc %d failed to get mediatek,gce-events property\n",
drm_crtc_index(&mtk_crtc->base)); drm_crtc_index(&mtk_crtc->base));
mbox_free_channel(mtk_crtc->cmdq_chan); cmdq_mbox_destroy(mtk_crtc->cmdq_client);
mtk_crtc->cmdq_chan = NULL; mtk_crtc->cmdq_client = NULL;
} else {
ret = mtk_drm_cmdq_pkt_create(mtk_crtc->cmdq_chan,
&mtk_crtc->cmdq_handle,
PAGE_SIZE);
if (ret) {
dev_dbg(dev, "mtk_crtc %d failed to create cmdq packet\n",
drm_crtc_index(&mtk_crtc->base));
mbox_free_channel(mtk_crtc->cmdq_chan);
mtk_crtc->cmdq_chan = NULL;
}
} }
} }
#endif #endif

@ -571,13 +571,14 @@ struct msm_gpu *a3xx_gpu_init(struct drm_device *dev)
} }
icc_path = devm_of_icc_get(&pdev->dev, "gfx-mem"); icc_path = devm_of_icc_get(&pdev->dev, "gfx-mem");
ret = IS_ERR(icc_path); if (IS_ERR(icc_path)) {
if (ret) ret = PTR_ERR(icc_path);
goto fail; goto fail;
}
ocmem_icc_path = devm_of_icc_get(&pdev->dev, "ocmem"); ocmem_icc_path = devm_of_icc_get(&pdev->dev, "ocmem");
ret = IS_ERR(ocmem_icc_path); if (IS_ERR(ocmem_icc_path)) {
if (ret) { ret = PTR_ERR(ocmem_icc_path);
/* allow -ENODATA, ocmem icc is optional */ /* allow -ENODATA, ocmem icc is optional */
if (ret != -ENODATA) if (ret != -ENODATA)
goto fail; goto fail;

@ -699,13 +699,14 @@ struct msm_gpu *a4xx_gpu_init(struct drm_device *dev)
} }
icc_path = devm_of_icc_get(&pdev->dev, "gfx-mem"); icc_path = devm_of_icc_get(&pdev->dev, "gfx-mem");
ret = IS_ERR(icc_path); if (IS_ERR(icc_path)) {
if (ret) ret = PTR_ERR(icc_path);
goto fail; goto fail;
}
ocmem_icc_path = devm_of_icc_get(&pdev->dev, "ocmem"); ocmem_icc_path = devm_of_icc_get(&pdev->dev, "ocmem");
ret = IS_ERR(ocmem_icc_path); if (IS_ERR(ocmem_icc_path)) {
if (ret) { ret = PTR_ERR(ocmem_icc_path);
/* allow -ENODATA, ocmem icc is optional */ /* allow -ENODATA, ocmem icc is optional */
if (ret != -ENODATA) if (ret != -ENODATA)
goto fail; goto fail;

@ -296,6 +296,8 @@ int a6xx_gmu_set_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state)
u32 val; u32 val;
int request, ack; int request, ack;
WARN_ON_ONCE(!mutex_is_locked(&gmu->lock));
if (state >= ARRAY_SIZE(a6xx_gmu_oob_bits)) if (state >= ARRAY_SIZE(a6xx_gmu_oob_bits))
return -EINVAL; return -EINVAL;
@ -337,6 +339,8 @@ void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state)
{ {
int bit; int bit;
WARN_ON_ONCE(!mutex_is_locked(&gmu->lock));
if (state >= ARRAY_SIZE(a6xx_gmu_oob_bits)) if (state >= ARRAY_SIZE(a6xx_gmu_oob_bits))
return; return;
@ -1482,6 +1486,8 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
if (!pdev) if (!pdev)
return -ENODEV; return -ENODEV;
mutex_init(&gmu->lock);
gmu->dev = &pdev->dev; gmu->dev = &pdev->dev;
of_dma_configure(gmu->dev, node, true); of_dma_configure(gmu->dev, node, true);

@ -44,6 +44,9 @@ struct a6xx_gmu_bo {
struct a6xx_gmu { struct a6xx_gmu {
struct device *dev; struct device *dev;
/* For serializing communication with the GMU: */
struct mutex lock;
struct msm_gem_address_space *aspace; struct msm_gem_address_space *aspace;
void * __iomem mmio; void * __iomem mmio;

@ -106,7 +106,7 @@ static void a6xx_set_pagetable(struct a6xx_gpu *a6xx_gpu,
u32 asid; u32 asid;
u64 memptr = rbmemptr(ring, ttbr0); u64 memptr = rbmemptr(ring, ttbr0);
if (ctx == a6xx_gpu->cur_ctx) if (ctx->seqno == a6xx_gpu->cur_ctx_seqno)
return; return;
if (msm_iommu_pagetable_params(ctx->aspace->mmu, &ttbr, &asid)) if (msm_iommu_pagetable_params(ctx->aspace->mmu, &ttbr, &asid))
@ -139,7 +139,7 @@ static void a6xx_set_pagetable(struct a6xx_gpu *a6xx_gpu,
OUT_PKT7(ring, CP_EVENT_WRITE, 1); OUT_PKT7(ring, CP_EVENT_WRITE, 1);
OUT_RING(ring, 0x31); OUT_RING(ring, 0x31);
a6xx_gpu->cur_ctx = ctx; a6xx_gpu->cur_ctx_seqno = ctx->seqno;
} }
static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
@ -881,7 +881,7 @@ static int a6xx_zap_shader_init(struct msm_gpu *gpu)
A6XX_RBBM_INT_0_MASK_UCHE_OOB_ACCESS | \ A6XX_RBBM_INT_0_MASK_UCHE_OOB_ACCESS | \
A6XX_RBBM_INT_0_MASK_UCHE_TRAP_INTR) A6XX_RBBM_INT_0_MASK_UCHE_TRAP_INTR)
static int a6xx_hw_init(struct msm_gpu *gpu) static int hw_init(struct msm_gpu *gpu)
{ {
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
@ -1081,7 +1081,7 @@ static int a6xx_hw_init(struct msm_gpu *gpu)
/* Always come up on rb 0 */ /* Always come up on rb 0 */
a6xx_gpu->cur_ring = gpu->rb[0]; a6xx_gpu->cur_ring = gpu->rb[0];
a6xx_gpu->cur_ctx = NULL; a6xx_gpu->cur_ctx_seqno = 0;
/* Enable the SQE_to start the CP engine */ /* Enable the SQE_to start the CP engine */
gpu_write(gpu, REG_A6XX_CP_SQE_CNTL, 1); gpu_write(gpu, REG_A6XX_CP_SQE_CNTL, 1);
@ -1135,6 +1135,19 @@ static int a6xx_hw_init(struct msm_gpu *gpu)
return ret; return ret;
} }
static int a6xx_hw_init(struct msm_gpu *gpu)
{
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
int ret;
mutex_lock(&a6xx_gpu->gmu.lock);
ret = hw_init(gpu);
mutex_unlock(&a6xx_gpu->gmu.lock);
return ret;
}
static void a6xx_dump(struct msm_gpu *gpu) static void a6xx_dump(struct msm_gpu *gpu)
{ {
DRM_DEV_INFO(&gpu->pdev->dev, "status: %08x\n", DRM_DEV_INFO(&gpu->pdev->dev, "status: %08x\n",
@ -1509,7 +1522,9 @@ static int a6xx_pm_resume(struct msm_gpu *gpu)
trace_msm_gpu_resume(0); trace_msm_gpu_resume(0);
mutex_lock(&a6xx_gpu->gmu.lock);
ret = a6xx_gmu_resume(a6xx_gpu); ret = a6xx_gmu_resume(a6xx_gpu);
mutex_unlock(&a6xx_gpu->gmu.lock);
if (ret) if (ret)
return ret; return ret;
@ -1532,7 +1547,9 @@ static int a6xx_pm_suspend(struct msm_gpu *gpu)
msm_devfreq_suspend(gpu); msm_devfreq_suspend(gpu);
mutex_lock(&a6xx_gpu->gmu.lock);
ret = a6xx_gmu_stop(a6xx_gpu); ret = a6xx_gmu_stop(a6xx_gpu);
mutex_unlock(&a6xx_gpu->gmu.lock);
if (ret) if (ret)
return ret; return ret;
@ -1547,18 +1564,19 @@ static int a6xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value)
{ {
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
static DEFINE_MUTEX(perfcounter_oob);
mutex_lock(&perfcounter_oob); mutex_lock(&a6xx_gpu->gmu.lock);
/* Force the GPU power on so we can read this register */ /* Force the GPU power on so we can read this register */
a6xx_gmu_set_oob(&a6xx_gpu->gmu, GMU_OOB_PERFCOUNTER_SET); a6xx_gmu_set_oob(&a6xx_gpu->gmu, GMU_OOB_PERFCOUNTER_SET);
*value = gpu_read64(gpu, REG_A6XX_CP_ALWAYS_ON_COUNTER_LO, *value = gpu_read64(gpu, REG_A6XX_CP_ALWAYS_ON_COUNTER_LO,
REG_A6XX_CP_ALWAYS_ON_COUNTER_HI); REG_A6XX_CP_ALWAYS_ON_COUNTER_HI);
a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_PERFCOUNTER_SET); a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_PERFCOUNTER_SET);
mutex_unlock(&perfcounter_oob);
mutex_unlock(&a6xx_gpu->gmu.lock);
return 0; return 0;
} }
@ -1622,6 +1640,16 @@ static unsigned long a6xx_gpu_busy(struct msm_gpu *gpu)
return (unsigned long)busy_time; return (unsigned long)busy_time;
} }
void a6xx_gpu_set_freq(struct msm_gpu *gpu, struct dev_pm_opp *opp)
{
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
mutex_lock(&a6xx_gpu->gmu.lock);
a6xx_gmu_set_freq(gpu, opp);
mutex_unlock(&a6xx_gpu->gmu.lock);
}
static struct msm_gem_address_space * static struct msm_gem_address_space *
a6xx_create_address_space(struct msm_gpu *gpu, struct platform_device *pdev) a6xx_create_address_space(struct msm_gpu *gpu, struct platform_device *pdev)
{ {
@ -1766,7 +1794,7 @@ static const struct adreno_gpu_funcs funcs = {
#endif #endif
.gpu_busy = a6xx_gpu_busy, .gpu_busy = a6xx_gpu_busy,
.gpu_get_freq = a6xx_gmu_get_freq, .gpu_get_freq = a6xx_gmu_get_freq,
.gpu_set_freq = a6xx_gmu_set_freq, .gpu_set_freq = a6xx_gpu_set_freq,
#if defined(CONFIG_DRM_MSM_GPU_STATE) #if defined(CONFIG_DRM_MSM_GPU_STATE)
.gpu_state_get = a6xx_gpu_state_get, .gpu_state_get = a6xx_gpu_state_get,
.gpu_state_put = a6xx_gpu_state_put, .gpu_state_put = a6xx_gpu_state_put,
@ -1810,6 +1838,13 @@ struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
adreno_cmp_rev(ADRENO_REV(6, 3, 5, ANY_ID), info->rev))) adreno_cmp_rev(ADRENO_REV(6, 3, 5, ANY_ID), info->rev)))
adreno_gpu->base.hw_apriv = true; adreno_gpu->base.hw_apriv = true;
/*
* For now only clamp to idle freq for devices where this is known not
* to cause power supply issues:
*/
if (info && (info->revn == 618))
gpu->clamp_to_idle = true;
a6xx_llc_slices_init(pdev, a6xx_gpu); a6xx_llc_slices_init(pdev, a6xx_gpu);
ret = a6xx_set_supported_hw(&pdev->dev, config->rev); ret = a6xx_set_supported_hw(&pdev->dev, config->rev);

@ -19,7 +19,16 @@ struct a6xx_gpu {
uint64_t sqe_iova; uint64_t sqe_iova;
struct msm_ringbuffer *cur_ring; struct msm_ringbuffer *cur_ring;
struct msm_file_private *cur_ctx;
/**
* cur_ctx_seqno:
*
* The ctx->seqno value of the context with current pgtables
* installed. Tracked by seqno rather than pointer value to
* avoid dangling pointers, and cases where a ctx can be freed
* and a new one created with the same address.
*/
int cur_ctx_seqno;
struct a6xx_gmu gmu; struct a6xx_gmu gmu;

@ -794,7 +794,7 @@ static const struct dpu_pingpong_cfg sm8150_pp[] = {
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30),
-1), -1),
PP_BLK("pingpong_5", PINGPONG_5, 0x72800, MERGE_3D_2, sdm845_pp_sblk, PP_BLK("pingpong_5", PINGPONG_5, 0x72800, MERGE_3D_2, sdm845_pp_sblk,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31),
-1), -1),
}; };

@ -1125,6 +1125,20 @@ static void mdp5_crtc_reset(struct drm_crtc *crtc)
__drm_atomic_helper_crtc_reset(crtc, &mdp5_cstate->base); __drm_atomic_helper_crtc_reset(crtc, &mdp5_cstate->base);
} }
static const struct drm_crtc_funcs mdp5_crtc_no_lm_cursor_funcs = {
.set_config = drm_atomic_helper_set_config,
.destroy = mdp5_crtc_destroy,
.page_flip = drm_atomic_helper_page_flip,
.reset = mdp5_crtc_reset,
.atomic_duplicate_state = mdp5_crtc_duplicate_state,
.atomic_destroy_state = mdp5_crtc_destroy_state,
.atomic_print_state = mdp5_crtc_atomic_print_state,
.get_vblank_counter = mdp5_crtc_get_vblank_counter,
.enable_vblank = msm_crtc_enable_vblank,
.disable_vblank = msm_crtc_disable_vblank,
.get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp,
};
static const struct drm_crtc_funcs mdp5_crtc_funcs = { static const struct drm_crtc_funcs mdp5_crtc_funcs = {
.set_config = drm_atomic_helper_set_config, .set_config = drm_atomic_helper_set_config,
.destroy = mdp5_crtc_destroy, .destroy = mdp5_crtc_destroy,
@ -1313,6 +1327,8 @@ struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,
mdp5_crtc->lm_cursor_enabled = cursor_plane ? false : true; mdp5_crtc->lm_cursor_enabled = cursor_plane ? false : true;
drm_crtc_init_with_planes(dev, crtc, plane, cursor_plane, drm_crtc_init_with_planes(dev, crtc, plane, cursor_plane,
cursor_plane ?
&mdp5_crtc_no_lm_cursor_funcs :
&mdp5_crtc_funcs, NULL); &mdp5_crtc_funcs, NULL);
drm_flip_work_init(&mdp5_crtc->unref_cursor_work, drm_flip_work_init(&mdp5_crtc->unref_cursor_work,

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