Merge 304040fb49 ("Merge tag 's390-5.15-6' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux") into android-mainline
Steps on the way to 5.15-rc6 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: Ie72e9e52b9ab4124680950fa129642a8e2303eb3
This commit is contained in:
@@ -21,6 +21,7 @@ select:
|
||||
contains:
|
||||
enum:
|
||||
- snps,dwmac
|
||||
- snps,dwmac-3.40a
|
||||
- snps,dwmac-3.50a
|
||||
- snps,dwmac-3.610
|
||||
- snps,dwmac-3.70a
|
||||
@@ -76,6 +77,7 @@ properties:
|
||||
- rockchip,rk3399-gmac
|
||||
- rockchip,rv1108-gmac
|
||||
- snps,dwmac
|
||||
- snps,dwmac-3.40a
|
||||
- snps,dwmac-3.50a
|
||||
- snps,dwmac-3.610
|
||||
- snps,dwmac-3.70a
|
||||
|
||||
@@ -171,7 +171,7 @@ examples:
|
||||
cs-gpios = <&gpio0 13 0>,
|
||||
<&gpio0 14 0>;
|
||||
rx-sample-delay-ns = <3>;
|
||||
spi-flash@1 {
|
||||
flash@1 {
|
||||
compatible = "spi-nand";
|
||||
reg = <1>;
|
||||
rx-sample-delay-ns = <7>;
|
||||
|
||||
@@ -4,103 +4,112 @@
|
||||
NTFS3
|
||||
=====
|
||||
|
||||
|
||||
Summary and Features
|
||||
====================
|
||||
|
||||
NTFS3 is fully functional NTFS Read-Write driver. The driver works with
|
||||
NTFS versions up to 3.1, normal/compressed/sparse files
|
||||
and journal replaying. File system type to use on mount is 'ntfs3'.
|
||||
NTFS3 is fully functional NTFS Read-Write driver. The driver works with NTFS
|
||||
versions up to 3.1. File system type to use on mount is *ntfs3*.
|
||||
|
||||
- This driver implements NTFS read/write support for normal, sparse and
|
||||
compressed files.
|
||||
- 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 native journal replaying.
|
||||
- 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
|
||||
=============
|
||||
|
||||
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
|
||||
strings and translate them to Unicode and back. If
|
||||
this option is not set, the default codepage will be
|
||||
used (CONFIG_NLS_DEFAULT).
|
||||
Examples:
|
||||
'nls=utf8'
|
||||
* - iocharset=name
|
||||
- This option informs the driver how to interpret path strings and
|
||||
translate them to Unicode and back. If this option is not set, the
|
||||
default codepage will be used (CONFIG_NLS_DEFAULT).
|
||||
|
||||
uid=
|
||||
gid=
|
||||
umask= Controls the default permissions for files/directories created
|
||||
after the NTFS volume is mounted.
|
||||
Example: iocharset=utf8
|
||||
|
||||
fmask=
|
||||
dmask= Instead of specifying umask which applies both to
|
||||
files and directories, fmask applies only to files and
|
||||
dmask only to directories.
|
||||
* - uid=
|
||||
- :rspan:`1`
|
||||
* - gid=
|
||||
|
||||
nohidden Files with the Windows-specific HIDDEN (FILE_ATTRIBUTE_HIDDEN)
|
||||
attribute will not be shown under Linux.
|
||||
* - umask=
|
||||
- Controls the default permissions for files/directories created after
|
||||
the NTFS volume is mounted.
|
||||
|
||||
sys_immutable Files with the Windows-specific SYSTEM
|
||||
(FILE_ATTRIBUTE_SYSTEM) attribute will be marked as system
|
||||
immutable files.
|
||||
* - dmask=
|
||||
- :rspan:`1` Instead of specifying umask which applies both to files and
|
||||
directories, fmask applies only to files and dmask only to directories.
|
||||
* - fmask=
|
||||
|
||||
discard Enable support of the TRIM command for improved performance
|
||||
on delete operations, which is recommended for use with the
|
||||
solid-state drives (SSD).
|
||||
* - noacsrules
|
||||
- "No access rules" mount option sets access rights for files/folders to
|
||||
777 and owner/group to root. This mount option absorbs all other
|
||||
permissions.
|
||||
|
||||
force Forces the driver to mount partitions even if 'dirty' flag
|
||||
(volume dirty) is set. Not recommended for use.
|
||||
- Permissions change for files/folders will be reported as successful,
|
||||
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
|
||||
a mounted NTFS partition.
|
||||
By default, all meta-files are hidden.
|
||||
* - nohidden
|
||||
- Files with the Windows-specific HIDDEN (FILE_ATTRIBUTE_HIDDEN) attribute
|
||||
will not be shown under Linux.
|
||||
|
||||
prealloc Preallocate space for files excessively when file size is
|
||||
increasing on writes. Decreases fragmentation in case of
|
||||
parallel write operations to different files.
|
||||
* - sys_immutable
|
||||
- Files with the Windows-specific SYSTEM (FILE_ATTRIBUTE_SYSTEM) attribute
|
||||
will be marked as system immutable files.
|
||||
|
||||
no_acs_rules "No access rules" mount option sets access rights for
|
||||
files/folders to 777 and owner/group to root. This mount
|
||||
option absorbs all other permissions:
|
||||
- permissions change for files/folders will be reported
|
||||
as successful, but they will remain 777;
|
||||
- owner/group change will be reported as successful, but
|
||||
they will stay as root
|
||||
* - discard
|
||||
- Enable support of the TRIM command for improved performance on delete
|
||||
operations, which is recommended for use with the solid-state drives
|
||||
(SSD).
|
||||
|
||||
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.
|
||||
* - force
|
||||
- Forces the driver to mount partitions even if volume is marked dirty.
|
||||
Not recommended for use.
|
||||
|
||||
noatime All files and directories will not update their last access
|
||||
time attribute if a partition is mounted with this parameter.
|
||||
This option can speed up file system operation.
|
||||
* - sparse
|
||||
- Create new files as sparse.
|
||||
|
||||
===============================================================================
|
||||
* - 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 (currently journal replaying is supported) over JBD.
|
||||
|
||||
- Full journaling support over JBD. Currently journal replaying is supported
|
||||
which is not necessarily as effectice as JBD would be.
|
||||
|
||||
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
|
||||
|
||||
+5
-5
@@ -7440,7 +7440,7 @@ FREESCALE IMX / MXC FEC DRIVER
|
||||
M: Joakim Zhang <qiangqing.zhang@nxp.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/net/fsl-fec.txt
|
||||
F: Documentation/devicetree/bindings/net/fsl,fec.yaml
|
||||
F: drivers/net/ethernet/freescale/fec.h
|
||||
F: drivers/net/ethernet/freescale/fec_main.c
|
||||
F: drivers/net/ethernet/freescale/fec_ptp.c
|
||||
@@ -9636,7 +9636,7 @@ F: include/uapi/linux/isst_if.h
|
||||
F: tools/power/x86/intel-speed-select/
|
||||
|
||||
INTEL STRATIX10 FIRMWARE DRIVERS
|
||||
M: Richard Gong <richard.gong@linux.intel.com>
|
||||
M: Dinh Nguyen <dinguyen@kernel.org>
|
||||
L: linux-kernel@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/ABI/testing/sysfs-devices-platform-stratix10-rsu
|
||||
@@ -10286,7 +10286,6 @@ KERNEL VIRTUAL MACHINE for s390 (KVM/s390)
|
||||
M: Christian Borntraeger <borntraeger@de.ibm.com>
|
||||
M: Janosch Frank <frankja@linux.ibm.com>
|
||||
R: David Hildenbrand <david@redhat.com>
|
||||
R: Cornelia Huck <cohuck@redhat.com>
|
||||
R: Claudio Imbrenda <imbrenda@linux.ibm.com>
|
||||
L: kvm@vger.kernel.org
|
||||
S: Supported
|
||||
@@ -11160,6 +11159,7 @@ S: Maintained
|
||||
F: Documentation/devicetree/bindings/net/dsa/marvell.txt
|
||||
F: Documentation/networking/devlink/mv88e6xxx.rst
|
||||
F: drivers/net/dsa/mv88e6xxx/
|
||||
F: include/linux/dsa/mv88e6xxx.h
|
||||
F: include/linux/platform_data/mv88e6xxx.h
|
||||
|
||||
MARVELL ARMADA 3700 PHY DRIVERS
|
||||
@@ -16314,6 +16314,7 @@ S390
|
||||
M: Heiko Carstens <hca@linux.ibm.com>
|
||||
M: Vasily Gorbik <gor@linux.ibm.com>
|
||||
M: Christian Borntraeger <borntraeger@de.ibm.com>
|
||||
R: Alexander Gordeev <agordeev@linux.ibm.com>
|
||||
L: linux-s390@vger.kernel.org
|
||||
S: Supported
|
||||
W: http://www.ibm.com/developerworks/linux/linux390/
|
||||
@@ -16392,7 +16393,6 @@ F: drivers/s390/crypto/vfio_ap_ops.c
|
||||
F: drivers/s390/crypto/vfio_ap_private.h
|
||||
|
||||
S390 VFIO-CCW DRIVER
|
||||
M: Cornelia Huck <cohuck@redhat.com>
|
||||
M: Eric Farman <farman@linux.ibm.com>
|
||||
M: Matthew Rosato <mjrosato@linux.ibm.com>
|
||||
R: Halil Pasic <pasic@linux.ibm.com>
|
||||
@@ -17999,7 +17999,7 @@ F: net/switchdev/
|
||||
SY8106A REGULATOR DRIVER
|
||||
M: Icenowy Zheng <icenowy@aosc.io>
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/regulator/sy8106a-regulator.txt
|
||||
F: Documentation/devicetree/bindings/regulator/silergy,sy8106a.yaml
|
||||
F: drivers/regulator/sy8106a-regulator.c
|
||||
|
||||
SYNC FILE FRAMEWORK
|
||||
|
||||
@@ -26,11 +26,6 @@ extern char empty_zero_page[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 */
|
||||
#define HAVE_ARCH_UNMAPPED_AREA
|
||||
|
||||
|
||||
@@ -40,8 +40,8 @@
|
||||
regulator-always-on;
|
||||
regulator-settling-time-us = <5000>;
|
||||
gpios = <&expgpio 4 GPIO_ACTIVE_HIGH>;
|
||||
states = <1800000 0x1
|
||||
3300000 0x0>;
|
||||
states = <1800000 0x1>,
|
||||
<3300000 0x0>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
@@ -217,15 +217,16 @@
|
||||
};
|
||||
|
||||
&pcie0 {
|
||||
pci@1,0 {
|
||||
pci@0,0 {
|
||||
device_type = "pci";
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
ranges;
|
||||
|
||||
reg = <0 0 0 0 0>;
|
||||
|
||||
usb@1,0 {
|
||||
reg = <0x10000 0 0 0 0>;
|
||||
usb@0,0 {
|
||||
reg = <0 0 0 0 0>;
|
||||
resets = <&reset RASPBERRYPI_FIRMWARE_RESET_ID_USB>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -300,6 +300,14 @@
|
||||
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 {
|
||||
compatible = "brcm,brcm2711-dvp";
|
||||
reg = <0x7ef00000 0x10>;
|
||||
@@ -532,8 +540,8 @@
|
||||
compatible = "brcm,genet-mdio-v5";
|
||||
reg = <0xe14 0x8>;
|
||||
reg-names = "mdio";
|
||||
#address-cells = <0x0>;
|
||||
#size-cells = <0x1>;
|
||||
#address-cells = <0x1>;
|
||||
#size-cells = <0x0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -106,6 +106,14 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
vec: vec@7e806000 {
|
||||
compatible = "brcm,bcm2835-vec";
|
||||
reg = <0x7e806000 0x1000>;
|
||||
clocks = <&clocks BCM2835_CLOCK_VEC>;
|
||||
interrupts = <2 27>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
pixelvalve@7e807000 {
|
||||
compatible = "brcm,bcm2835-pixelvalve2";
|
||||
reg = <0x7e807000 0x100>;
|
||||
|
||||
@@ -464,14 +464,6 @@
|
||||
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 {
|
||||
compatible = "brcm,bcm2835-usb";
|
||||
reg = <0x7e980000 0x10000>;
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
};
|
||||
|
||||
gmac: eth@e0800000 {
|
||||
compatible = "st,spear600-gmac";
|
||||
compatible = "snps,dwmac-3.40a";
|
||||
reg = <0xe0800000 0x8000>;
|
||||
interrupts = <23 22>;
|
||||
interrupt-names = "macirq", "eth_wake_irq";
|
||||
|
||||
+31
-9
@@ -9,6 +9,7 @@
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/reset-controller.h>
|
||||
#include <linux/smp.h>
|
||||
#include <asm/smp_plat.h>
|
||||
@@ -81,11 +82,6 @@ static const struct reset_control_ops imx_src_ops = {
|
||||
.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)
|
||||
{
|
||||
writel_relaxed(enable, gpc_base + offset);
|
||||
@@ -177,10 +173,6 @@ void __init imx_src_init(void)
|
||||
src_base = of_iomap(np, 0);
|
||||
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
|
||||
* for a more reliable restart
|
||||
@@ -214,3 +206,33 @@ void __init imx7_src_init(void)
|
||||
if (!gpc_base)
|
||||
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);
|
||||
|
||||
+2
-1
@@ -8,7 +8,7 @@ config CSKY
|
||||
select ARCH_HAS_SYNC_DMA_FOR_DEVICE
|
||||
select ARCH_USE_BUILTIN_BSWAP
|
||||
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 COMMON_CLK
|
||||
select CLKSRC_MMIO
|
||||
@@ -241,6 +241,7 @@ endchoice
|
||||
|
||||
menuconfig HAVE_TCM
|
||||
bool "Tightly-Coupled/Sram Memory"
|
||||
depends on !COMPILE_TEST
|
||||
help
|
||||
The implementation are not only used by TCM (Tightly-Coupled Meory)
|
||||
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!!!!
|
||||
*/
|
||||
#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/ext2-atomic.h>
|
||||
|
||||
@@ -99,7 +99,8 @@ static int gpr_set(struct task_struct *target,
|
||||
if (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
|
||||
regs.dcsr = task_pt_regs(target)->dcsr;
|
||||
#endif
|
||||
|
||||
@@ -52,10 +52,14 @@ static long restore_sigcontext(struct pt_regs *regs,
|
||||
struct sigcontext __user *sc)
|
||||
{
|
||||
int err = 0;
|
||||
unsigned long sr = regs->sr;
|
||||
|
||||
/* 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));
|
||||
|
||||
/* BIT(0) of regs->sr is Condition Code/Carry bit */
|
||||
regs->sr = (sr & ~1) | (regs->sr & 1);
|
||||
|
||||
/* Restore the floating-point state. */
|
||||
err |= restore_fpu_state(sc);
|
||||
|
||||
|
||||
@@ -259,14 +259,13 @@ EXPORT_SYMBOL(strcmp);
|
||||
#ifdef __HAVE_ARCH_STRRCHR
|
||||
char *strrchr(const char *s, int c)
|
||||
{
|
||||
size_t len = __strend(s) - s;
|
||||
ssize_t len = __strend(s) - s;
|
||||
|
||||
if (len)
|
||||
do {
|
||||
if (s[len] == (char) c)
|
||||
return (char *) s + len;
|
||||
} while (--len > 0);
|
||||
return NULL;
|
||||
do {
|
||||
if (s[len] == (char)c)
|
||||
return (char *)s + len;
|
||||
} while (--len >= 0);
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(strrchr);
|
||||
#endif
|
||||
|
||||
@@ -371,7 +371,7 @@ static int lps0_device_attach(struct acpi_device *adev,
|
||||
return 0;
|
||||
|
||||
if (acpi_s2idle_vendor_amd()) {
|
||||
/* AMD0004, AMDI0005:
|
||||
/* AMD0004, AMD0005, AMDI0005:
|
||||
* - Should use rev_id 0x0
|
||||
* - function mask > 0x3: Should use AMD method, but has off by one bug
|
||||
* - 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,
|
||||
&lps0_dsm_guid_microsoft);
|
||||
if (lps0_dsm_func_mask > 0x3 && (!strcmp(hid, "AMD0004") ||
|
||||
!strcmp(hid, "AMD0005") ||
|
||||
!strcmp(hid, "AMDI0005"))) {
|
||||
lps0_dsm_func_mask = (lps0_dsm_func_mask << 1) | 0x1;
|
||||
acpi_handle_debug(adev->handle, "_DSM UUID %s: Adjusted function mask: 0x%x\n",
|
||||
|
||||
@@ -49,6 +49,13 @@ static int ffa_device_probe(struct device *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)
|
||||
{
|
||||
struct ffa_device *ffa_dev = to_ffa_dev(dev);
|
||||
@@ -86,6 +93,7 @@ struct bus_type ffa_bus_type = {
|
||||
.name = "arm_ffa",
|
||||
.match = ffa_device_match,
|
||||
.probe = ffa_device_probe,
|
||||
.remove = ffa_device_remove,
|
||||
.uevent = ffa_device_uevent,
|
||||
.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)
|
||||
{
|
||||
ffa_release_device(dev);
|
||||
device_unregister(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -174,6 +174,13 @@ static int gen_74x164_remove(struct spi_device *spi)
|
||||
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[] = {
|
||||
{ .compatible = "fairchild,74hc595" },
|
||||
{ .compatible = "nxp,74lvc594" },
|
||||
@@ -188,6 +195,7 @@ static struct spi_driver gen_74x164_driver = {
|
||||
},
|
||||
.probe = gen_74x164_probe,
|
||||
.remove = gen_74x164_remove,
|
||||
.id_table = gen_74x164_spi_ids,
|
||||
};
|
||||
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)
|
||||
{
|
||||
struct platform_device *pdev;
|
||||
struct fwnode_handle *fwnode;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < GPIO_MOCKUP_MAX_GC; i++)
|
||||
platform_device_unregister(gpio_mockup_pdevs[i]);
|
||||
for (i = 0; i < GPIO_MOCKUP_MAX_GC; 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,
|
||||
@@ -508,6 +517,7 @@ static int __init gpio_mockup_register_chip(int idx)
|
||||
struct property_entry properties[GPIO_MOCKUP_MAX_PROP];
|
||||
struct platform_device_info pdevinfo;
|
||||
struct platform_device *pdev;
|
||||
struct fwnode_handle *fwnode;
|
||||
char **line_names = NULL;
|
||||
char chip_label[32];
|
||||
int prop = 0, base;
|
||||
@@ -536,13 +546,18 @@ static int __init gpio_mockup_register_chip(int idx)
|
||||
"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.id = idx;
|
||||
pdevinfo.properties = properties;
|
||||
pdevinfo.fwnode = fwnode;
|
||||
|
||||
pdev = platform_device_register_full(&pdevinfo);
|
||||
kfree_strarray(line_names, ngpio);
|
||||
if (IS_ERR(pdev)) {
|
||||
fwnode_remove_software_node(fwnode);
|
||||
pr_err("error registering device");
|
||||
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);
|
||||
|
||||
/* 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 */
|
||||
if (config == PIN_CONFIG_BIAS_PULL_UP)
|
||||
ret = regmap_write_bits(chip->regmap, pull_sel_reg, bit, bit);
|
||||
else if (config == PIN_CONFIG_BIAS_PULL_DOWN)
|
||||
ret = regmap_write_bits(chip->regmap, pull_sel_reg, bit, 0);
|
||||
else
|
||||
ret = 0;
|
||||
if (ret)
|
||||
goto exit;
|
||||
|
||||
/* Enable pull-up/pull-down */
|
||||
ret = regmap_write_bits(chip->regmap, pull_en_reg, bit, bit);
|
||||
/* Disable/Enable pull-up/pull-down */
|
||||
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:
|
||||
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)) {
|
||||
case PIN_CONFIG_BIAS_PULL_UP:
|
||||
case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
|
||||
case PIN_CONFIG_BIAS_PULL_DOWN:
|
||||
case PIN_CONFIG_BIAS_DISABLE:
|
||||
return pca953x_gpio_set_pull_up_down(chip, offset, config);
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
|
||||
@@ -1834,11 +1834,20 @@ static void connector_bad_edid(struct drm_connector *connector,
|
||||
u8 *edid, int num_blocks)
|
||||
{
|
||||
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 */
|
||||
connector->real_edid_checksum =
|
||||
drm_edid_block_checksum(edid + num_of_ext * EDID_LENGTH);
|
||||
if (last_block < num_blocks)
|
||||
connector->real_edid_checksum =
|
||||
drm_edid_block_checksum(edid + last_block * EDID_LENGTH);
|
||||
|
||||
if (connector->bad_edid_counter++ && !drm_debug_enabled(DRM_UT_KMS))
|
||||
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_device *dev = fb_helper->dev;
|
||||
struct drm_mode_config *config = &dev->mode_config;
|
||||
int ret = 0;
|
||||
int crtc_count = 0;
|
||||
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 */
|
||||
sizes.surface_height *= drm_fbdev_overalloc;
|
||||
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 */
|
||||
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_situation(struct hv_device *hdev, u8 active, u32 bpp,
|
||||
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_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 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,
|
||||
crtc_state->mode.hdisplay,
|
||||
crtc_state->mode.vdisplay,
|
||||
|
||||
@@ -299,6 +299,55 @@ int hyperv_update_situation(struct hv_device *hdev, u8 active, u32 bpp,
|
||||
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)
|
||||
{
|
||||
struct hyperv_drm_device *hv = hv_get_drvdata(hdev);
|
||||
@@ -392,8 +441,11 @@ static void hyperv_receive_sub(struct hv_device *hdev)
|
||||
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;
|
||||
if (hv->dirt_needed)
|
||||
hyperv_hide_hw_ptr(hv->hdev);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
acpi_handle dhandle;
|
||||
union acpi_object *obj;
|
||||
|
||||
dhandle = ACPI_HANDLE(&pdev->dev);
|
||||
if (!dhandle)
|
||||
return;
|
||||
|
||||
acpi_evaluate_dsm(dhandle, &intel_dsm_guid2, INTEL_DSM_REVISION_ID,
|
||||
INTEL_DSM_FN_GET_BIOS_DATA_FUNCS_SUPPORTED, NULL);
|
||||
obj = acpi_evaluate_dsm(dhandle, &intel_dsm_guid2, INTEL_DSM_REVISION_ID,
|
||||
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;
|
||||
|
||||
e = alloc_engines(num_engines);
|
||||
if (!e)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
e->num_engines = num_engines;
|
||||
|
||||
for (n = 0; n < num_engines; n++) {
|
||||
struct intel_context *ce;
|
||||
int ret;
|
||||
@@ -970,7 +974,6 @@ static struct i915_gem_engines *user_engines(struct i915_gem_context *ctx,
|
||||
goto free_engines;
|
||||
}
|
||||
}
|
||||
e->num_engines = num_engines;
|
||||
|
||||
return e;
|
||||
|
||||
|
||||
@@ -421,6 +421,7 @@ void intel_context_fini(struct intel_context *ce)
|
||||
|
||||
mutex_destroy(&ce->pin_mutex);
|
||||
i915_active_fini(&ce->active);
|
||||
i915_sw_fence_fini(&ce->guc_blocked);
|
||||
}
|
||||
|
||||
void i915_context_module_exit(void)
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/mailbox_controller.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/soc/mediatek/mtk-cmdq.h>
|
||||
#include <linux/soc/mediatek/mtk-mmsys.h>
|
||||
@@ -52,11 +50,8 @@ struct mtk_drm_crtc {
|
||||
bool pending_async_planes;
|
||||
|
||||
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
|
||||
struct mbox_client cmdq_cl;
|
||||
struct mbox_chan *cmdq_chan;
|
||||
struct cmdq_pkt cmdq_handle;
|
||||
struct cmdq_client *cmdq_client;
|
||||
u32 cmdq_event;
|
||||
u32 cmdq_vblank_cnt;
|
||||
#endif
|
||||
|
||||
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)
|
||||
static int mtk_drm_cmdq_pkt_create(struct mbox_chan *chan, struct cmdq_pkt *pkt,
|
||||
size_t size)
|
||||
static void ddp_cmdq_cb(struct cmdq_cb_data data)
|
||||
{
|
||||
struct device *dev;
|
||||
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);
|
||||
cmdq_pkt_destroy(data.data);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -453,8 +378,7 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc,
|
||||
state->pending_vrefresh, 0,
|
||||
cmdq_handle);
|
||||
|
||||
if (!cmdq_handle)
|
||||
state->pending_config = false;
|
||||
state->pending_config = false;
|
||||
}
|
||||
|
||||
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,
|
||||
plane_state,
|
||||
cmdq_handle);
|
||||
if (!cmdq_handle)
|
||||
plane_state->pending.config = false;
|
||||
plane_state->pending.config = false;
|
||||
}
|
||||
|
||||
if (!cmdq_handle)
|
||||
mtk_crtc->pending_planes = false;
|
||||
mtk_crtc->pending_planes = false;
|
||||
}
|
||||
|
||||
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,
|
||||
plane_state,
|
||||
cmdq_handle);
|
||||
if (!cmdq_handle)
|
||||
plane_state->pending.async_config = false;
|
||||
plane_state->pending.async_config = false;
|
||||
}
|
||||
|
||||
if (!cmdq_handle)
|
||||
mtk_crtc->pending_async_planes = false;
|
||||
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)
|
||||
{
|
||||
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
|
||||
struct cmdq_pkt *cmdq_handle = &mtk_crtc->cmdq_handle;
|
||||
struct cmdq_pkt *cmdq_handle;
|
||||
#endif
|
||||
struct drm_crtc *crtc = &mtk_crtc->base;
|
||||
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);
|
||||
}
|
||||
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
|
||||
if (mtk_crtc->cmdq_chan) {
|
||||
mbox_flush(mtk_crtc->cmdq_chan, 2000);
|
||||
cmdq_handle->cmd_buf_size = 0;
|
||||
if (mtk_crtc->cmdq_client) {
|
||||
mbox_flush(mtk_crtc->cmdq_client->chan, 2000);
|
||||
cmdq_handle = cmdq_pkt_create(mtk_crtc->cmdq_client, PAGE_SIZE);
|
||||
cmdq_pkt_clear_event(cmdq_handle, mtk_crtc->cmdq_event);
|
||||
cmdq_pkt_wfe(cmdq_handle, mtk_crtc->cmdq_event, false);
|
||||
mtk_crtc_ddp_config(crtc, cmdq_handle);
|
||||
cmdq_pkt_finalize(cmdq_handle);
|
||||
dma_sync_single_for_device(mtk_crtc->cmdq_chan->mbox->dev,
|
||||
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);
|
||||
cmdq_pkt_flush_async(cmdq_handle, ddp_cmdq_cb, cmdq_handle);
|
||||
}
|
||||
#endif
|
||||
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;
|
||||
|
||||
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
|
||||
if (!priv->data->shadow_register && !mtk_crtc->cmdq_chan)
|
||||
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));
|
||||
if (!priv->data->shadow_register && !mtk_crtc->cmdq_client)
|
||||
#else
|
||||
if (!priv->data->shadow_register)
|
||||
mtk_crtc_ddp_config(crtc, NULL);
|
||||
#endif
|
||||
mtk_crtc_ddp_config(crtc, NULL);
|
||||
|
||||
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);
|
||||
|
||||
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
|
||||
mtk_crtc->cmdq_cl.dev = mtk_crtc->mmsys_dev;
|
||||
mtk_crtc->cmdq_cl.tx_block = false;
|
||||
mtk_crtc->cmdq_cl.knows_txdone = true;
|
||||
mtk_crtc->cmdq_cl.rx_callback = ddp_cmdq_cb;
|
||||
mtk_crtc->cmdq_chan =
|
||||
mbox_request_channel(&mtk_crtc->cmdq_cl,
|
||||
drm_crtc_index(&mtk_crtc->base));
|
||||
if (IS_ERR(mtk_crtc->cmdq_chan)) {
|
||||
mtk_crtc->cmdq_client =
|
||||
cmdq_mbox_create(mtk_crtc->mmsys_dev,
|
||||
drm_crtc_index(&mtk_crtc->base));
|
||||
if (IS_ERR(mtk_crtc->cmdq_client)) {
|
||||
dev_dbg(dev, "mtk_crtc %d failed to create mailbox client, writing register by CPU now\n",
|
||||
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,
|
||||
"mediatek,gce-events",
|
||||
drm_crtc_index(&mtk_crtc->base),
|
||||
@@ -945,18 +846,8 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
|
||||
if (ret) {
|
||||
dev_dbg(dev, "mtk_crtc %d failed to get mediatek,gce-events property\n",
|
||||
drm_crtc_index(&mtk_crtc->base));
|
||||
mbox_free_channel(mtk_crtc->cmdq_chan);
|
||||
mtk_crtc->cmdq_chan = 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;
|
||||
}
|
||||
cmdq_mbox_destroy(mtk_crtc->cmdq_client);
|
||||
mtk_crtc->cmdq_client = NULL;
|
||||
}
|
||||
}
|
||||
#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");
|
||||
ret = IS_ERR(icc_path);
|
||||
if (ret)
|
||||
if (IS_ERR(icc_path)) {
|
||||
ret = PTR_ERR(icc_path);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ocmem_icc_path = devm_of_icc_get(&pdev->dev, "ocmem");
|
||||
ret = IS_ERR(ocmem_icc_path);
|
||||
if (ret) {
|
||||
if (IS_ERR(ocmem_icc_path)) {
|
||||
ret = PTR_ERR(ocmem_icc_path);
|
||||
/* allow -ENODATA, ocmem icc is optional */
|
||||
if (ret != -ENODATA)
|
||||
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");
|
||||
ret = IS_ERR(icc_path);
|
||||
if (ret)
|
||||
if (IS_ERR(icc_path)) {
|
||||
ret = PTR_ERR(icc_path);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ocmem_icc_path = devm_of_icc_get(&pdev->dev, "ocmem");
|
||||
ret = IS_ERR(ocmem_icc_path);
|
||||
if (ret) {
|
||||
if (IS_ERR(ocmem_icc_path)) {
|
||||
ret = PTR_ERR(ocmem_icc_path);
|
||||
/* allow -ENODATA, ocmem icc is optional */
|
||||
if (ret != -ENODATA)
|
||||
goto fail;
|
||||
|
||||
@@ -296,6 +296,8 @@ int a6xx_gmu_set_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state)
|
||||
u32 val;
|
||||
int request, ack;
|
||||
|
||||
WARN_ON_ONCE(!mutex_is_locked(&gmu->lock));
|
||||
|
||||
if (state >= ARRAY_SIZE(a6xx_gmu_oob_bits))
|
||||
return -EINVAL;
|
||||
|
||||
@@ -337,6 +339,8 @@ void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state)
|
||||
{
|
||||
int bit;
|
||||
|
||||
WARN_ON_ONCE(!mutex_is_locked(&gmu->lock));
|
||||
|
||||
if (state >= ARRAY_SIZE(a6xx_gmu_oob_bits))
|
||||
return;
|
||||
|
||||
@@ -1482,6 +1486,8 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
|
||||
if (!pdev)
|
||||
return -ENODEV;
|
||||
|
||||
mutex_init(&gmu->lock);
|
||||
|
||||
gmu->dev = &pdev->dev;
|
||||
|
||||
of_dma_configure(gmu->dev, node, true);
|
||||
|
||||
@@ -44,6 +44,9 @@ struct a6xx_gmu_bo {
|
||||
struct a6xx_gmu {
|
||||
struct device *dev;
|
||||
|
||||
/* For serializing communication with the GMU: */
|
||||
struct mutex lock;
|
||||
|
||||
struct msm_gem_address_space *aspace;
|
||||
|
||||
void * __iomem mmio;
|
||||
|
||||
@@ -106,7 +106,7 @@ static void a6xx_set_pagetable(struct a6xx_gpu *a6xx_gpu,
|
||||
u32 asid;
|
||||
u64 memptr = rbmemptr(ring, ttbr0);
|
||||
|
||||
if (ctx == a6xx_gpu->cur_ctx)
|
||||
if (ctx->seqno == a6xx_gpu->cur_ctx_seqno)
|
||||
return;
|
||||
|
||||
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_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)
|
||||
@@ -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_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 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 */
|
||||
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 */
|
||||
gpu_write(gpu, REG_A6XX_CP_SQE_CNTL, 1);
|
||||
@@ -1135,6 +1135,19 @@ out:
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
mutex_lock(&a6xx_gpu->gmu.lock);
|
||||
ret = a6xx_gmu_resume(a6xx_gpu);
|
||||
mutex_unlock(&a6xx_gpu->gmu.lock);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -1532,7 +1547,9 @@ static int a6xx_pm_suspend(struct msm_gpu *gpu)
|
||||
|
||||
msm_devfreq_suspend(gpu);
|
||||
|
||||
mutex_lock(&a6xx_gpu->gmu.lock);
|
||||
ret = a6xx_gmu_stop(a6xx_gpu);
|
||||
mutex_unlock(&a6xx_gpu->gmu.lock);
|
||||
if (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 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 */
|
||||
a6xx_gmu_set_oob(&a6xx_gpu->gmu, GMU_OOB_PERFCOUNTER_SET);
|
||||
|
||||
*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);
|
||||
mutex_unlock(&perfcounter_oob);
|
||||
|
||||
mutex_unlock(&a6xx_gpu->gmu.lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1622,6 +1640,16 @@ static unsigned long a6xx_gpu_busy(struct msm_gpu *gpu)
|
||||
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 *
|
||||
a6xx_create_address_space(struct msm_gpu *gpu, struct platform_device *pdev)
|
||||
{
|
||||
@@ -1766,7 +1794,7 @@ static const struct adreno_gpu_funcs funcs = {
|
||||
#endif
|
||||
.gpu_busy = a6xx_gpu_busy,
|
||||
.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)
|
||||
.gpu_state_get = a6xx_gpu_state_get,
|
||||
.gpu_state_put = a6xx_gpu_state_put,
|
||||
|
||||
@@ -19,7 +19,16 @@ struct a6xx_gpu {
|
||||
uint64_t sqe_iova;
|
||||
|
||||
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;
|
||||
|
||||
|
||||
@@ -794,7 +794,7 @@ static const struct dpu_pingpong_cfg sm8150_pp[] = {
|
||||
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30),
|
||||
-1),
|
||||
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),
|
||||
};
|
||||
|
||||
|
||||
@@ -1125,6 +1125,20 @@ static void mdp5_crtc_reset(struct drm_crtc *crtc)
|
||||
__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 = {
|
||||
.set_config = drm_atomic_helper_set_config,
|
||||
.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;
|
||||
|
||||
drm_crtc_init_with_planes(dev, crtc, plane, cursor_plane,
|
||||
cursor_plane ?
|
||||
&mdp5_crtc_no_lm_cursor_funcs :
|
||||
&mdp5_crtc_funcs, NULL);
|
||||
|
||||
drm_flip_work_init(&mdp5_crtc->unref_cursor_work,
|
||||
|
||||
@@ -1309,14 +1309,14 @@ static int dp_pm_resume(struct device *dev)
|
||||
* can not declared display is connected unless
|
||||
* HDMI cable is plugged in and sink_count of
|
||||
* dongle become 1
|
||||
* also only signal audio when disconnected
|
||||
*/
|
||||
if (dp->link->sink_count)
|
||||
if (dp->link->sink_count) {
|
||||
dp->dp_display.is_connected = true;
|
||||
else
|
||||
} else {
|
||||
dp->dp_display.is_connected = false;
|
||||
|
||||
dp_display_handle_plugged_change(g_dp_display,
|
||||
dp->dp_display.is_connected);
|
||||
dp_display_handle_plugged_change(g_dp_display, false);
|
||||
}
|
||||
|
||||
DRM_DEBUG_DP("After, sink_count=%d is_connected=%d core_inited=%d power_on=%d\n",
|
||||
dp->link->sink_count, dp->dp_display.is_connected,
|
||||
|
||||
@@ -215,8 +215,10 @@ int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!msm_dsi_manager_validate_current_config(msm_dsi->id))
|
||||
if (!msm_dsi_manager_validate_current_config(msm_dsi->id)) {
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
msm_dsi->encoder = encoder;
|
||||
|
||||
|
||||
@@ -451,7 +451,7 @@ static int dsi_bus_clk_enable(struct msm_dsi_host *msm_host)
|
||||
|
||||
return 0;
|
||||
err:
|
||||
for (; i > 0; i--)
|
||||
while (--i >= 0)
|
||||
clk_disable_unprepare(msm_host->bus_clks[i]);
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -110,14 +110,13 @@ static struct dsi_pll_14nm *pll_14nm_list[DSI_MAX];
|
||||
static bool pll_14nm_poll_for_ready(struct dsi_pll_14nm *pll_14nm,
|
||||
u32 nb_tries, u32 timeout_us)
|
||||
{
|
||||
bool pll_locked = false;
|
||||
bool pll_locked = false, pll_ready = false;
|
||||
void __iomem *base = pll_14nm->phy->pll_base;
|
||||
u32 tries, val;
|
||||
|
||||
tries = nb_tries;
|
||||
while (tries--) {
|
||||
val = dsi_phy_read(base +
|
||||
REG_DSI_14nm_PHY_PLL_RESET_SM_READY_STATUS);
|
||||
val = dsi_phy_read(base + REG_DSI_14nm_PHY_PLL_RESET_SM_READY_STATUS);
|
||||
pll_locked = !!(val & BIT(5));
|
||||
|
||||
if (pll_locked)
|
||||
@@ -126,23 +125,24 @@ static bool pll_14nm_poll_for_ready(struct dsi_pll_14nm *pll_14nm,
|
||||
udelay(timeout_us);
|
||||
}
|
||||
|
||||
if (!pll_locked) {
|
||||
tries = nb_tries;
|
||||
while (tries--) {
|
||||
val = dsi_phy_read(base +
|
||||
REG_DSI_14nm_PHY_PLL_RESET_SM_READY_STATUS);
|
||||
pll_locked = !!(val & BIT(0));
|
||||
if (!pll_locked)
|
||||
goto out;
|
||||
|
||||
if (pll_locked)
|
||||
break;
|
||||
tries = nb_tries;
|
||||
while (tries--) {
|
||||
val = dsi_phy_read(base + REG_DSI_14nm_PHY_PLL_RESET_SM_READY_STATUS);
|
||||
pll_ready = !!(val & BIT(0));
|
||||
|
||||
udelay(timeout_us);
|
||||
}
|
||||
if (pll_ready)
|
||||
break;
|
||||
|
||||
udelay(timeout_us);
|
||||
}
|
||||
|
||||
DBG("DSI PLL is %slocked", pll_locked ? "" : "*not* ");
|
||||
out:
|
||||
DBG("DSI PLL is %slocked, %sready", pll_locked ? "" : "*not* ", pll_ready ? "" : "*not* ");
|
||||
|
||||
return pll_locked;
|
||||
return pll_locked && pll_ready;
|
||||
}
|
||||
|
||||
static void dsi_pll_14nm_config_init(struct dsi_pll_config *pconf)
|
||||
|
||||
@@ -428,7 +428,7 @@ static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm, struct clk_hw **prov
|
||||
bytediv->reg = pll_28nm->phy->pll_base + REG_DSI_28nm_8960_PHY_PLL_CTRL_9;
|
||||
|
||||
snprintf(parent_name, 32, "dsi%dvco_clk", pll_28nm->phy->id);
|
||||
snprintf(clk_name, 32, "dsi%dpllbyte", pll_28nm->phy->id);
|
||||
snprintf(clk_name, 32, "dsi%dpllbyte", pll_28nm->phy->id + 1);
|
||||
|
||||
bytediv_init.name = clk_name;
|
||||
bytediv_init.ops = &clk_bytediv_ops;
|
||||
@@ -442,7 +442,7 @@ static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm, struct clk_hw **prov
|
||||
return ret;
|
||||
provided_clocks[DSI_BYTE_PLL_CLK] = &bytediv->hw;
|
||||
|
||||
snprintf(clk_name, 32, "dsi%dpll", pll_28nm->phy->id);
|
||||
snprintf(clk_name, 32, "dsi%dpll", pll_28nm->phy->id + 1);
|
||||
/* DIV3 */
|
||||
hw = devm_clk_hw_register_divider(dev, clk_name,
|
||||
parent_name, 0, pll_28nm->phy->pll_base +
|
||||
|
||||
@@ -1116,7 +1116,7 @@ void msm_edp_ctrl_power(struct edp_ctrl *ctrl, bool on)
|
||||
int msm_edp_ctrl_init(struct msm_edp *edp)
|
||||
{
|
||||
struct edp_ctrl *ctrl = NULL;
|
||||
struct device *dev = &edp->pdev->dev;
|
||||
struct device *dev;
|
||||
int ret;
|
||||
|
||||
if (!edp) {
|
||||
@@ -1124,6 +1124,7 @@ int msm_edp_ctrl_init(struct msm_edp *edp)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev = &edp->pdev->dev;
|
||||
ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
|
||||
if (!ctrl)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -630,10 +630,11 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv)
|
||||
if (ret)
|
||||
goto err_msm_uninit;
|
||||
|
||||
ret = msm_disp_snapshot_init(ddev);
|
||||
if (ret)
|
||||
DRM_DEV_ERROR(dev, "msm_disp_snapshot_init failed ret = %d\n", ret);
|
||||
|
||||
if (kms) {
|
||||
ret = msm_disp_snapshot_init(ddev);
|
||||
if (ret)
|
||||
DRM_DEV_ERROR(dev, "msm_disp_snapshot_init failed ret = %d\n", ret);
|
||||
}
|
||||
drm_mode_config_reset(ddev);
|
||||
|
||||
#ifdef CONFIG_DRM_FBDEV_EMULATION
|
||||
@@ -682,6 +683,7 @@ static void load_gpu(struct drm_device *dev)
|
||||
|
||||
static int context_init(struct drm_device *dev, struct drm_file *file)
|
||||
{
|
||||
static atomic_t ident = ATOMIC_INIT(0);
|
||||
struct msm_drm_private *priv = dev->dev_private;
|
||||
struct msm_file_private *ctx;
|
||||
|
||||
@@ -689,12 +691,17 @@ static int context_init(struct drm_device *dev, struct drm_file *file)
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
INIT_LIST_HEAD(&ctx->submitqueues);
|
||||
rwlock_init(&ctx->queuelock);
|
||||
|
||||
kref_init(&ctx->ref);
|
||||
msm_submitqueue_init(dev, ctx);
|
||||
|
||||
ctx->aspace = msm_gpu_create_private_address_space(priv->gpu, current);
|
||||
file->driver_priv = ctx;
|
||||
|
||||
ctx->seqno = atomic_inc_return(&ident);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -53,14 +53,6 @@ struct msm_disp_state;
|
||||
|
||||
#define FRAC_16_16(mult, div) (((mult) << 16) / (div))
|
||||
|
||||
struct msm_file_private {
|
||||
rwlock_t queuelock;
|
||||
struct list_head submitqueues;
|
||||
int queueid;
|
||||
struct msm_gem_address_space *aspace;
|
||||
struct kref ref;
|
||||
};
|
||||
|
||||
enum msm_mdp_plane_property {
|
||||
PLANE_PROP_ZPOS,
|
||||
PLANE_PROP_ALPHA,
|
||||
@@ -488,41 +480,6 @@ void msm_writel(u32 data, void __iomem *addr);
|
||||
u32 msm_readl(const void __iomem *addr);
|
||||
void msm_rmw(void __iomem *addr, u32 mask, u32 or);
|
||||
|
||||
struct msm_gpu_submitqueue;
|
||||
int msm_submitqueue_init(struct drm_device *drm, struct msm_file_private *ctx);
|
||||
struct msm_gpu_submitqueue *msm_submitqueue_get(struct msm_file_private *ctx,
|
||||
u32 id);
|
||||
int msm_submitqueue_create(struct drm_device *drm,
|
||||
struct msm_file_private *ctx,
|
||||
u32 prio, u32 flags, u32 *id);
|
||||
int msm_submitqueue_query(struct drm_device *drm, struct msm_file_private *ctx,
|
||||
struct drm_msm_submitqueue_query *args);
|
||||
int msm_submitqueue_remove(struct msm_file_private *ctx, u32 id);
|
||||
void msm_submitqueue_close(struct msm_file_private *ctx);
|
||||
|
||||
void msm_submitqueue_destroy(struct kref *kref);
|
||||
|
||||
static inline void __msm_file_private_destroy(struct kref *kref)
|
||||
{
|
||||
struct msm_file_private *ctx = container_of(kref,
|
||||
struct msm_file_private, ref);
|
||||
|
||||
msm_gem_address_space_put(ctx->aspace);
|
||||
kfree(ctx);
|
||||
}
|
||||
|
||||
static inline void msm_file_private_put(struct msm_file_private *ctx)
|
||||
{
|
||||
kref_put(&ctx->ref, __msm_file_private_destroy);
|
||||
}
|
||||
|
||||
static inline struct msm_file_private *msm_file_private_get(
|
||||
struct msm_file_private *ctx)
|
||||
{
|
||||
kref_get(&ctx->ref);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
#define DBG(fmt, ...) DRM_DEBUG_DRIVER(fmt"\n", ##__VA_ARGS__)
|
||||
#define VERB(fmt, ...) if (0) DRM_DEBUG_DRIVER(fmt"\n", ##__VA_ARGS__)
|
||||
|
||||
@@ -547,7 +504,7 @@ static inline int align_pitch(int width, int bpp)
|
||||
static inline unsigned long timeout_to_jiffies(const ktime_t *timeout)
|
||||
{
|
||||
ktime_t now = ktime_get();
|
||||
unsigned long remaining_jiffies;
|
||||
s64 remaining_jiffies;
|
||||
|
||||
if (ktime_compare(*timeout, now) < 0) {
|
||||
remaining_jiffies = 0;
|
||||
@@ -556,7 +513,7 @@ static inline unsigned long timeout_to_jiffies(const ktime_t *timeout)
|
||||
remaining_jiffies = ktime_divns(rem, NSEC_PER_SEC / HZ);
|
||||
}
|
||||
|
||||
return remaining_jiffies;
|
||||
return clamp(remaining_jiffies, 0LL, (s64)INT_MAX);
|
||||
}
|
||||
|
||||
#endif /* __MSM_DRV_H__ */
|
||||
|
||||
@@ -46,7 +46,7 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev,
|
||||
if (!submit)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
ret = drm_sched_job_init(&submit->base, &queue->entity, queue);
|
||||
ret = drm_sched_job_init(&submit->base, queue->entity, queue);
|
||||
if (ret) {
|
||||
kfree(submit);
|
||||
return ERR_PTR(ret);
|
||||
@@ -171,7 +171,8 @@ out:
|
||||
static int submit_lookup_cmds(struct msm_gem_submit *submit,
|
||||
struct drm_msm_gem_submit *args, struct drm_file *file)
|
||||
{
|
||||
unsigned i, sz;
|
||||
unsigned i;
|
||||
size_t sz;
|
||||
int ret = 0;
|
||||
|
||||
for (i = 0; i < args->nr_cmds; i++) {
|
||||
@@ -907,7 +908,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
|
||||
/* The scheduler owns a ref now: */
|
||||
msm_gem_submit_get(submit);
|
||||
|
||||
drm_sched_entity_push_job(&submit->base, &queue->entity);
|
||||
drm_sched_entity_push_job(&submit->base, queue->entity);
|
||||
|
||||
args->fence = submit->fence_id;
|
||||
|
||||
|
||||
@@ -257,6 +257,39 @@ struct msm_gpu_perfcntr {
|
||||
*/
|
||||
#define NR_SCHED_PRIORITIES (1 + DRM_SCHED_PRIORITY_HIGH - DRM_SCHED_PRIORITY_MIN)
|
||||
|
||||
/**
|
||||
* struct msm_file_private - per-drm_file context
|
||||
*
|
||||
* @queuelock: synchronizes access to submitqueues list
|
||||
* @submitqueues: list of &msm_gpu_submitqueue created by userspace
|
||||
* @queueid: counter incremented each time a submitqueue is created,
|
||||
* used to assign &msm_gpu_submitqueue.id
|
||||
* @aspace: the per-process GPU address-space
|
||||
* @ref: reference count
|
||||
* @seqno: unique per process seqno
|
||||
*/
|
||||
struct msm_file_private {
|
||||
rwlock_t queuelock;
|
||||
struct list_head submitqueues;
|
||||
int queueid;
|
||||
struct msm_gem_address_space *aspace;
|
||||
struct kref ref;
|
||||
int seqno;
|
||||
|
||||
/**
|
||||
* entities:
|
||||
*
|
||||
* Table of per-priority-level sched entities used by submitqueues
|
||||
* associated with this &drm_file. Because some userspace apps
|
||||
* make assumptions about rendering from multiple gl contexts
|
||||
* (of the same priority) within the process happening in FIFO
|
||||
* order without requiring any fencing beyond MakeCurrent(), we
|
||||
* create at most one &drm_sched_entity per-process per-priority-
|
||||
* level.
|
||||
*/
|
||||
struct drm_sched_entity *entities[NR_SCHED_PRIORITIES * MSM_GPU_MAX_RINGS];
|
||||
};
|
||||
|
||||
/**
|
||||
* msm_gpu_convert_priority - Map userspace priority to ring # and sched priority
|
||||
*
|
||||
@@ -304,6 +337,8 @@ static inline int msm_gpu_convert_priority(struct msm_gpu *gpu, int prio,
|
||||
}
|
||||
|
||||
/**
|
||||
* struct msm_gpu_submitqueues - Userspace created context.
|
||||
*
|
||||
* A submitqueue is associated with a gl context or vk queue (or equiv)
|
||||
* in userspace.
|
||||
*
|
||||
@@ -321,7 +356,7 @@ static inline int msm_gpu_convert_priority(struct msm_gpu *gpu, int prio,
|
||||
* seqno, protected by submitqueue lock
|
||||
* @lock: submitqueue lock
|
||||
* @ref: reference count
|
||||
* @entity: the submit job-queue
|
||||
* @entity: the submit job-queue
|
||||
*/
|
||||
struct msm_gpu_submitqueue {
|
||||
int id;
|
||||
@@ -333,7 +368,7 @@ struct msm_gpu_submitqueue {
|
||||
struct idr fence_idr;
|
||||
struct mutex lock;
|
||||
struct kref ref;
|
||||
struct drm_sched_entity entity;
|
||||
struct drm_sched_entity *entity;
|
||||
};
|
||||
|
||||
struct msm_gpu_state_bo {
|
||||
@@ -421,6 +456,33 @@ static inline void gpu_write64(struct msm_gpu *gpu, u32 lo, u32 hi, u64 val)
|
||||
int msm_gpu_pm_suspend(struct msm_gpu *gpu);
|
||||
int msm_gpu_pm_resume(struct msm_gpu *gpu);
|
||||
|
||||
int msm_submitqueue_init(struct drm_device *drm, struct msm_file_private *ctx);
|
||||
struct msm_gpu_submitqueue *msm_submitqueue_get(struct msm_file_private *ctx,
|
||||
u32 id);
|
||||
int msm_submitqueue_create(struct drm_device *drm,
|
||||
struct msm_file_private *ctx,
|
||||
u32 prio, u32 flags, u32 *id);
|
||||
int msm_submitqueue_query(struct drm_device *drm, struct msm_file_private *ctx,
|
||||
struct drm_msm_submitqueue_query *args);
|
||||
int msm_submitqueue_remove(struct msm_file_private *ctx, u32 id);
|
||||
void msm_submitqueue_close(struct msm_file_private *ctx);
|
||||
|
||||
void msm_submitqueue_destroy(struct kref *kref);
|
||||
|
||||
void __msm_file_private_destroy(struct kref *kref);
|
||||
|
||||
static inline void msm_file_private_put(struct msm_file_private *ctx)
|
||||
{
|
||||
kref_put(&ctx->ref, __msm_file_private_destroy);
|
||||
}
|
||||
|
||||
static inline struct msm_file_private *msm_file_private_get(
|
||||
struct msm_file_private *ctx)
|
||||
{
|
||||
kref_get(&ctx->ref);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void msm_devfreq_init(struct msm_gpu *gpu);
|
||||
void msm_devfreq_cleanup(struct msm_gpu *gpu);
|
||||
void msm_devfreq_resume(struct msm_gpu *gpu);
|
||||
|
||||
@@ -151,6 +151,9 @@ void msm_devfreq_active(struct msm_gpu *gpu)
|
||||
unsigned int idle_time;
|
||||
unsigned long target_freq = df->idle_freq;
|
||||
|
||||
if (!df->devfreq)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Hold devfreq lock to synchronize with get_dev_status()/
|
||||
* target() callbacks
|
||||
@@ -186,6 +189,9 @@ void msm_devfreq_idle(struct msm_gpu *gpu)
|
||||
struct msm_gpu_devfreq *df = &gpu->devfreq;
|
||||
unsigned long idle_freq, target_freq = 0;
|
||||
|
||||
if (!df->devfreq)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Hold devfreq lock to synchronize with get_dev_status()/
|
||||
* target() callbacks
|
||||
|
||||
@@ -7,6 +7,24 @@
|
||||
|
||||
#include "msm_gpu.h"
|
||||
|
||||
void __msm_file_private_destroy(struct kref *kref)
|
||||
{
|
||||
struct msm_file_private *ctx = container_of(kref,
|
||||
struct msm_file_private, ref);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ctx->entities); i++) {
|
||||
if (!ctx->entities[i])
|
||||
continue;
|
||||
|
||||
drm_sched_entity_destroy(ctx->entities[i]);
|
||||
kfree(ctx->entities[i]);
|
||||
}
|
||||
|
||||
msm_gem_address_space_put(ctx->aspace);
|
||||
kfree(ctx);
|
||||
}
|
||||
|
||||
void msm_submitqueue_destroy(struct kref *kref)
|
||||
{
|
||||
struct msm_gpu_submitqueue *queue = container_of(kref,
|
||||
@@ -14,8 +32,6 @@ void msm_submitqueue_destroy(struct kref *kref)
|
||||
|
||||
idr_destroy(&queue->fence_idr);
|
||||
|
||||
drm_sched_entity_destroy(&queue->entity);
|
||||
|
||||
msm_file_private_put(queue->ctx);
|
||||
|
||||
kfree(queue);
|
||||
@@ -61,13 +77,47 @@ void msm_submitqueue_close(struct msm_file_private *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
static struct drm_sched_entity *
|
||||
get_sched_entity(struct msm_file_private *ctx, struct msm_ringbuffer *ring,
|
||||
unsigned ring_nr, enum drm_sched_priority sched_prio)
|
||||
{
|
||||
static DEFINE_MUTEX(entity_lock);
|
||||
unsigned idx = (ring_nr * NR_SCHED_PRIORITIES) + sched_prio;
|
||||
|
||||
/* We should have already validated that the requested priority is
|
||||
* valid by the time we get here.
|
||||
*/
|
||||
if (WARN_ON(idx >= ARRAY_SIZE(ctx->entities)))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
mutex_lock(&entity_lock);
|
||||
|
||||
if (!ctx->entities[idx]) {
|
||||
struct drm_sched_entity *entity;
|
||||
struct drm_gpu_scheduler *sched = &ring->sched;
|
||||
int ret;
|
||||
|
||||
entity = kzalloc(sizeof(*ctx->entities[idx]), GFP_KERNEL);
|
||||
|
||||
ret = drm_sched_entity_init(entity, sched_prio, &sched, 1, NULL);
|
||||
if (ret) {
|
||||
kfree(entity);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
ctx->entities[idx] = entity;
|
||||
}
|
||||
|
||||
mutex_unlock(&entity_lock);
|
||||
|
||||
return ctx->entities[idx];
|
||||
}
|
||||
|
||||
int msm_submitqueue_create(struct drm_device *drm, struct msm_file_private *ctx,
|
||||
u32 prio, u32 flags, u32 *id)
|
||||
{
|
||||
struct msm_drm_private *priv = drm->dev_private;
|
||||
struct msm_gpu_submitqueue *queue;
|
||||
struct msm_ringbuffer *ring;
|
||||
struct drm_gpu_scheduler *sched;
|
||||
enum drm_sched_priority sched_prio;
|
||||
unsigned ring_nr;
|
||||
int ret;
|
||||
@@ -91,12 +141,10 @@ int msm_submitqueue_create(struct drm_device *drm, struct msm_file_private *ctx,
|
||||
queue->flags = flags;
|
||||
queue->ring_nr = ring_nr;
|
||||
|
||||
ring = priv->gpu->rb[ring_nr];
|
||||
sched = &ring->sched;
|
||||
|
||||
ret = drm_sched_entity_init(&queue->entity,
|
||||
sched_prio, &sched, 1, NULL);
|
||||
if (ret) {
|
||||
queue->entity = get_sched_entity(ctx, priv->gpu->rb[ring_nr],
|
||||
ring_nr, sched_prio);
|
||||
if (IS_ERR(queue->entity)) {
|
||||
ret = PTR_ERR(queue->entity);
|
||||
kfree(queue);
|
||||
return ret;
|
||||
}
|
||||
@@ -140,10 +188,6 @@ int msm_submitqueue_init(struct drm_device *drm, struct msm_file_private *ctx)
|
||||
*/
|
||||
default_prio = DIV_ROUND_UP(max_priority, 2);
|
||||
|
||||
INIT_LIST_HEAD(&ctx->submitqueues);
|
||||
|
||||
rwlock_init(&ctx->queuelock);
|
||||
|
||||
return msm_submitqueue_create(drm, ctx, default_prio, 0, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ g84_fifo_chan_engine_fini(struct nvkm_fifo_chan *base,
|
||||
if (offset < 0)
|
||||
return 0;
|
||||
|
||||
engn = fifo->base.func->engine_id(&fifo->base, engine);
|
||||
engn = fifo->base.func->engine_id(&fifo->base, engine) - 1;
|
||||
save = nvkm_mask(device, 0x002520, 0x0000003f, 1 << engn);
|
||||
nvkm_wr32(device, 0x0032fc, chan->base.inst->addr >> 12);
|
||||
done = nvkm_msec(device, 2000,
|
||||
|
||||
@@ -295,6 +295,7 @@ config DRM_PANEL_OLIMEX_LCD_OLINUXINO
|
||||
depends on OF
|
||||
depends on I2C
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
select CRC32
|
||||
help
|
||||
The panel is used with different sizes LCDs, from 480x272 to
|
||||
1280x800, and 24 bit per pixel.
|
||||
|
||||
@@ -214,7 +214,7 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
#ifdef CONFIG_X86
|
||||
wbinvd();
|
||||
#else
|
||||
mb();
|
||||
|
||||
@@ -86,12 +86,20 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
|
||||
}
|
||||
|
||||
/*
|
||||
* Create and initialize the encoder. On Gen3 skip the LVDS1 output if
|
||||
* Create and initialize the encoder. On Gen3, skip the LVDS1 output if
|
||||
* the LVDS1 encoder is used as a companion for LVDS0 in dual-link
|
||||
* mode.
|
||||
* mode, or any LVDS output if it isn't connected. The latter may happen
|
||||
* on D3 or E3 as the LVDS encoders are needed to provide the pixel
|
||||
* clock to the DU, even when the LVDS outputs are not used.
|
||||
*/
|
||||
if (rcdu->info->gen >= 3 && output == RCAR_DU_OUTPUT_LVDS1) {
|
||||
if (rcar_lvds_dual_link(bridge))
|
||||
if (rcdu->info->gen >= 3) {
|
||||
if (output == RCAR_DU_OUTPUT_LVDS1 &&
|
||||
rcar_lvds_dual_link(bridge))
|
||||
return -ENOLINK;
|
||||
|
||||
if ((output == RCAR_DU_OUTPUT_LVDS0 ||
|
||||
output == RCAR_DU_OUTPUT_LVDS1) &&
|
||||
!rcar_lvds_is_connected(bridge))
|
||||
return -ENOLINK;
|
||||
}
|
||||
|
||||
|
||||
@@ -576,6 +576,9 @@ static int rcar_lvds_attach(struct drm_bridge *bridge,
|
||||
{
|
||||
struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
|
||||
|
||||
if (!lvds->next_bridge)
|
||||
return 0;
|
||||
|
||||
return drm_bridge_attach(bridge->encoder, lvds->next_bridge, bridge,
|
||||
flags);
|
||||
}
|
||||
@@ -598,6 +601,14 @@ bool rcar_lvds_dual_link(struct drm_bridge *bridge)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rcar_lvds_dual_link);
|
||||
|
||||
bool rcar_lvds_is_connected(struct drm_bridge *bridge)
|
||||
{
|
||||
struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
|
||||
|
||||
return lvds->next_bridge != NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rcar_lvds_is_connected);
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Probe & Remove
|
||||
*/
|
||||
|
||||
@@ -16,6 +16,7 @@ struct drm_bridge;
|
||||
int rcar_lvds_clk_enable(struct drm_bridge *bridge, unsigned long freq);
|
||||
void rcar_lvds_clk_disable(struct drm_bridge *bridge);
|
||||
bool rcar_lvds_dual_link(struct drm_bridge *bridge);
|
||||
bool rcar_lvds_is_connected(struct drm_bridge *bridge);
|
||||
#else
|
||||
static inline int rcar_lvds_clk_enable(struct drm_bridge *bridge,
|
||||
unsigned long freq)
|
||||
@@ -27,6 +28,10 @@ static inline bool rcar_lvds_dual_link(struct drm_bridge *bridge)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
static inline bool rcar_lvds_is_connected(struct drm_bridge *bridge)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif /* CONFIG_DRM_RCAR_LVDS */
|
||||
|
||||
#endif /* __RCAR_LVDS_H__ */
|
||||
|
||||
@@ -355,6 +355,14 @@ config ARM_SMMU_DISABLE_BYPASS_BY_DEFAULT
|
||||
'arm-smmu.disable_bypass' will continue to override this
|
||||
config.
|
||||
|
||||
config ARM_SMMU_QCOM
|
||||
def_tristate y
|
||||
depends on ARM_SMMU && ARCH_QCOM
|
||||
select QCOM_SCM
|
||||
help
|
||||
When running on a Qualcomm platform that has the custom variant
|
||||
of the ARM SMMU, this needs to be built into the SMMU driver.
|
||||
|
||||
config ARM_SMMU_V3
|
||||
tristate "ARM Ltd. System MMU Version 3 (SMMUv3) Support"
|
||||
depends on ARM64
|
||||
|
||||
@@ -480,6 +480,11 @@ int detach_capi_ctr(struct capi_ctr *ctr)
|
||||
|
||||
ctr_down(ctr, CAPI_CTR_DETACHED);
|
||||
|
||||
if (ctr->cnr < 1 || ctr->cnr - 1 >= CAPI_MAXCONTR) {
|
||||
err = -EINVAL;
|
||||
goto unlock_out;
|
||||
}
|
||||
|
||||
if (capi_controller[ctr->cnr - 1] != ctr) {
|
||||
err = -EINVAL;
|
||||
goto unlock_out;
|
||||
|
||||
@@ -949,8 +949,8 @@ nj_release(struct tiger_hw *card)
|
||||
nj_disable_hwirq(card);
|
||||
mode_tiger(&card->bc[0], ISDN_P_NONE);
|
||||
mode_tiger(&card->bc[1], ISDN_P_NONE);
|
||||
card->isac.release(&card->isac);
|
||||
spin_unlock_irqrestore(&card->lock, flags);
|
||||
card->isac.release(&card->isac);
|
||||
release_region(card->base, card->base_s);
|
||||
card->base_s = 0;
|
||||
}
|
||||
|
||||
@@ -1676,13 +1676,17 @@ qcom_nandc_read_cw_raw(struct mtd_info *mtd, struct nand_chip *chip,
|
||||
struct nand_ecc_ctrl *ecc = &chip->ecc;
|
||||
int data_size1, data_size2, oob_size1, oob_size2;
|
||||
int ret, reg_off = FLASH_BUF_ACC, read_loc = 0;
|
||||
int raw_cw = cw;
|
||||
|
||||
nand_read_page_op(chip, page, 0, NULL, 0);
|
||||
host->use_ecc = false;
|
||||
|
||||
if (nandc->props->qpic_v2)
|
||||
raw_cw = ecc->steps - 1;
|
||||
|
||||
clear_bam_transaction(nandc);
|
||||
set_address(host, host->cw_size * cw, page);
|
||||
update_rw_regs(host, 1, true, cw);
|
||||
update_rw_regs(host, 1, true, raw_cw);
|
||||
config_nand_page_read(chip);
|
||||
|
||||
data_size1 = mtd->writesize - host->cw_size * (ecc->steps - 1);
|
||||
@@ -1711,7 +1715,7 @@ qcom_nandc_read_cw_raw(struct mtd_info *mtd, struct nand_chip *chip,
|
||||
nandc_set_read_loc(chip, cw, 3, read_loc, oob_size2, 1);
|
||||
}
|
||||
|
||||
config_nand_cw_read(chip, false, cw);
|
||||
config_nand_cw_read(chip, false, raw_cw);
|
||||
|
||||
read_data_dma(nandc, reg_off, data_buf, data_size1, 0);
|
||||
reg_off += data_size1;
|
||||
|
||||
@@ -449,8 +449,10 @@ EXPORT_SYMBOL(ksz_switch_register);
|
||||
void ksz_switch_remove(struct ksz_device *dev)
|
||||
{
|
||||
/* timer started */
|
||||
if (dev->mib_read_interval)
|
||||
if (dev->mib_read_interval) {
|
||||
dev->mib_read_interval = 0;
|
||||
cancel_delayed_work_sync(&dev->mib_read);
|
||||
}
|
||||
|
||||
dev->dev_ops->exit(dev);
|
||||
dsa_unregister_switch(dev->ds);
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dsa/mv88e6xxx.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/if_bridge.h>
|
||||
@@ -749,7 +750,11 @@ static void mv88e6xxx_mac_link_down(struct dsa_switch *ds, int port,
|
||||
ops = chip->info->ops;
|
||||
|
||||
mv88e6xxx_reg_lock(chip);
|
||||
if ((!mv88e6xxx_port_ppu_updates(chip, port) ||
|
||||
/* Internal PHYs propagate their configuration directly to the MAC.
|
||||
* External PHYs depend on whether the PPU is enabled for this port.
|
||||
*/
|
||||
if (((!mv88e6xxx_phy_is_internal(ds, port) &&
|
||||
!mv88e6xxx_port_ppu_updates(chip, port)) ||
|
||||
mode == MLO_AN_FIXED) && ops->port_sync_link)
|
||||
err = ops->port_sync_link(chip, port, mode, false);
|
||||
mv88e6xxx_reg_unlock(chip);
|
||||
@@ -772,7 +777,12 @@ static void mv88e6xxx_mac_link_up(struct dsa_switch *ds, int port,
|
||||
ops = chip->info->ops;
|
||||
|
||||
mv88e6xxx_reg_lock(chip);
|
||||
if (!mv88e6xxx_port_ppu_updates(chip, port) || mode == MLO_AN_FIXED) {
|
||||
/* Internal PHYs propagate their configuration directly to the MAC.
|
||||
* External PHYs depend on whether the PPU is enabled for this port.
|
||||
*/
|
||||
if ((!mv88e6xxx_phy_is_internal(ds, port) &&
|
||||
!mv88e6xxx_port_ppu_updates(chip, port)) ||
|
||||
mode == MLO_AN_FIXED) {
|
||||
/* FIXME: for an automedia port, should we force the link
|
||||
* down here - what if the link comes up due to "other" media
|
||||
* while we're bringing the port up, how is the exclusivity
|
||||
@@ -1677,6 +1687,30 @@ static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mv88e6xxx_port_commit_pvid(struct mv88e6xxx_chip *chip, int port)
|
||||
{
|
||||
struct dsa_port *dp = dsa_to_port(chip->ds, port);
|
||||
struct mv88e6xxx_port *p = &chip->ports[port];
|
||||
u16 pvid = MV88E6XXX_VID_STANDALONE;
|
||||
bool drop_untagged = false;
|
||||
int err;
|
||||
|
||||
if (dp->bridge_dev) {
|
||||
if (br_vlan_enabled(dp->bridge_dev)) {
|
||||
pvid = p->bridge_pvid.vid;
|
||||
drop_untagged = !p->bridge_pvid.valid;
|
||||
} else {
|
||||
pvid = MV88E6XXX_VID_BRIDGED;
|
||||
}
|
||||
}
|
||||
|
||||
err = mv88e6xxx_port_set_pvid(chip, port, pvid);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return mv88e6xxx_port_drop_untagged(chip, port, drop_untagged);
|
||||
}
|
||||
|
||||
static int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port,
|
||||
bool vlan_filtering,
|
||||
struct netlink_ext_ack *extack)
|
||||
@@ -1690,7 +1724,16 @@ static int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port,
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
mv88e6xxx_reg_lock(chip);
|
||||
|
||||
err = mv88e6xxx_port_set_8021q_mode(chip, port, mode);
|
||||
if (err)
|
||||
goto unlock;
|
||||
|
||||
err = mv88e6xxx_port_commit_pvid(chip, port);
|
||||
if (err)
|
||||
goto unlock;
|
||||
|
||||
unlock:
|
||||
mv88e6xxx_reg_unlock(chip);
|
||||
|
||||
return err;
|
||||
@@ -1725,11 +1768,15 @@ static int mv88e6xxx_port_db_load_purge(struct mv88e6xxx_chip *chip, int port,
|
||||
u16 fid;
|
||||
int err;
|
||||
|
||||
/* Null VLAN ID corresponds to the port private database */
|
||||
/* Ports have two private address databases: one for when the port is
|
||||
* standalone and one for when the port is under a bridge and the
|
||||
* 802.1Q mode is disabled. When the port is standalone, DSA wants its
|
||||
* address database to remain 100% empty, so we never load an ATU entry
|
||||
* into a standalone port's database. Therefore, translate the null
|
||||
* VLAN ID into the port's database used for VLAN-unaware bridging.
|
||||
*/
|
||||
if (vid == 0) {
|
||||
err = mv88e6xxx_port_get_fid(chip, port, &fid);
|
||||
if (err)
|
||||
return err;
|
||||
fid = MV88E6XXX_FID_BRIDGED;
|
||||
} else {
|
||||
err = mv88e6xxx_vtu_get(chip, vid, &vlan);
|
||||
if (err)
|
||||
@@ -2123,6 +2170,7 @@ static int mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port,
|
||||
struct mv88e6xxx_chip *chip = ds->priv;
|
||||
bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
|
||||
bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
|
||||
struct mv88e6xxx_port *p = &chip->ports[port];
|
||||
bool warn;
|
||||
u8 member;
|
||||
int err;
|
||||
@@ -2156,13 +2204,21 @@ static int mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port,
|
||||
}
|
||||
|
||||
if (pvid) {
|
||||
err = mv88e6xxx_port_set_pvid(chip, port, vlan->vid);
|
||||
if (err) {
|
||||
dev_err(ds->dev, "p%d: failed to set PVID %d\n",
|
||||
port, vlan->vid);
|
||||
p->bridge_pvid.vid = vlan->vid;
|
||||
p->bridge_pvid.valid = true;
|
||||
|
||||
err = mv88e6xxx_port_commit_pvid(chip, port);
|
||||
if (err)
|
||||
goto out;
|
||||
} else if (vlan->vid && p->bridge_pvid.vid == vlan->vid) {
|
||||
/* The old pvid was reinstalled as a non-pvid VLAN */
|
||||
p->bridge_pvid.valid = false;
|
||||
|
||||
err = mv88e6xxx_port_commit_pvid(chip, port);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
mv88e6xxx_reg_unlock(chip);
|
||||
|
||||
@@ -2212,6 +2268,7 @@ static int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port,
|
||||
const struct switchdev_obj_port_vlan *vlan)
|
||||
{
|
||||
struct mv88e6xxx_chip *chip = ds->priv;
|
||||
struct mv88e6xxx_port *p = &chip->ports[port];
|
||||
int err = 0;
|
||||
u16 pvid;
|
||||
|
||||
@@ -2229,7 +2286,9 @@ static int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port,
|
||||
goto unlock;
|
||||
|
||||
if (vlan->vid == pvid) {
|
||||
err = mv88e6xxx_port_set_pvid(chip, port, 0);
|
||||
p->bridge_pvid.valid = false;
|
||||
|
||||
err = mv88e6xxx_port_commit_pvid(chip, port);
|
||||
if (err)
|
||||
goto unlock;
|
||||
}
|
||||
@@ -2393,7 +2452,16 @@ static int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port,
|
||||
int err;
|
||||
|
||||
mv88e6xxx_reg_lock(chip);
|
||||
|
||||
err = mv88e6xxx_bridge_map(chip, br);
|
||||
if (err)
|
||||
goto unlock;
|
||||
|
||||
err = mv88e6xxx_port_commit_pvid(chip, port);
|
||||
if (err)
|
||||
goto unlock;
|
||||
|
||||
unlock:
|
||||
mv88e6xxx_reg_unlock(chip);
|
||||
|
||||
return err;
|
||||
@@ -2403,11 +2471,20 @@ static void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port,
|
||||
struct net_device *br)
|
||||
{
|
||||
struct mv88e6xxx_chip *chip = ds->priv;
|
||||
int err;
|
||||
|
||||
mv88e6xxx_reg_lock(chip);
|
||||
|
||||
if (mv88e6xxx_bridge_map(chip, br) ||
|
||||
mv88e6xxx_port_vlan_map(chip, port))
|
||||
dev_err(ds->dev, "failed to remap in-chip Port VLAN\n");
|
||||
|
||||
err = mv88e6xxx_port_commit_pvid(chip, port);
|
||||
if (err)
|
||||
dev_err(ds->dev,
|
||||
"port %d failed to restore standalone pvid: %pe\n",
|
||||
port, ERR_PTR(err));
|
||||
|
||||
mv88e6xxx_reg_unlock(chip);
|
||||
}
|
||||
|
||||
@@ -2853,6 +2930,20 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Associate MV88E6XXX_VID_BRIDGED with MV88E6XXX_FID_BRIDGED in the
|
||||
* ATU by virtue of the fact that mv88e6xxx_atu_new() will pick it as
|
||||
* the first free FID after MV88E6XXX_FID_STANDALONE. This will be used
|
||||
* as the private PVID on ports under a VLAN-unaware bridge.
|
||||
* Shared (DSA and CPU) ports must also be members of it, to translate
|
||||
* the VID from the DSA tag into MV88E6XXX_FID_BRIDGED, instead of
|
||||
* relying on their port default FID.
|
||||
*/
|
||||
err = mv88e6xxx_port_vlan_join(chip, port, MV88E6XXX_VID_BRIDGED,
|
||||
MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_UNTAGGED,
|
||||
false);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (chip->info->ops->port_set_jumbo_size) {
|
||||
err = chip->info->ops->port_set_jumbo_size(chip, port, 10218);
|
||||
if (err)
|
||||
@@ -2925,7 +3016,7 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
|
||||
* database, and allow bidirectional communication between the
|
||||
* CPU and DSA port(s), and the other ports.
|
||||
*/
|
||||
err = mv88e6xxx_port_set_fid(chip, port, 0);
|
||||
err = mv88e6xxx_port_set_fid(chip, port, MV88E6XXX_FID_STANDALONE);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -3115,6 +3206,10 @@ static int mv88e6xxx_setup(struct dsa_switch *ds)
|
||||
}
|
||||
}
|
||||
|
||||
err = mv88e6xxx_vtu_setup(chip);
|
||||
if (err)
|
||||
goto unlock;
|
||||
|
||||
/* Setup Switch Port Registers */
|
||||
for (i = 0; i < mv88e6xxx_num_ports(chip); i++) {
|
||||
if (dsa_is_unused_port(ds, i))
|
||||
@@ -3144,10 +3239,6 @@ static int mv88e6xxx_setup(struct dsa_switch *ds)
|
||||
if (err)
|
||||
goto unlock;
|
||||
|
||||
err = mv88e6xxx_vtu_setup(chip);
|
||||
if (err)
|
||||
goto unlock;
|
||||
|
||||
err = mv88e6xxx_pvt_setup(chip);
|
||||
if (err)
|
||||
goto unlock;
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
#define EDSA_HLEN 8
|
||||
#define MV88E6XXX_N_FID 4096
|
||||
|
||||
#define MV88E6XXX_FID_STANDALONE 0
|
||||
#define MV88E6XXX_FID_BRIDGED 1
|
||||
|
||||
/* PVT limits for 4-bit port and 5-bit switch */
|
||||
#define MV88E6XXX_MAX_PVT_SWITCHES 32
|
||||
#define MV88E6XXX_MAX_PVT_PORTS 16
|
||||
@@ -246,9 +249,15 @@ struct mv88e6xxx_policy {
|
||||
u16 vid;
|
||||
};
|
||||
|
||||
struct mv88e6xxx_vlan {
|
||||
u16 vid;
|
||||
bool valid;
|
||||
};
|
||||
|
||||
struct mv88e6xxx_port {
|
||||
struct mv88e6xxx_chip *chip;
|
||||
int port;
|
||||
struct mv88e6xxx_vlan bridge_pvid;
|
||||
u64 serdes_stats[2];
|
||||
u64 atu_member_violation;
|
||||
u64 atu_miss_violation;
|
||||
|
||||
@@ -1257,6 +1257,27 @@ int mv88e6xxx_port_set_8021q_mode(struct mv88e6xxx_chip *chip, int port,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mv88e6xxx_port_drop_untagged(struct mv88e6xxx_chip *chip, int port,
|
||||
bool drop_untagged)
|
||||
{
|
||||
u16 old, new;
|
||||
int err;
|
||||
|
||||
err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, &old);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (drop_untagged)
|
||||
new = old | MV88E6XXX_PORT_CTL2_DISCARD_UNTAGGED;
|
||||
else
|
||||
new = old & ~MV88E6XXX_PORT_CTL2_DISCARD_UNTAGGED;
|
||||
|
||||
if (new == old)
|
||||
return 0;
|
||||
|
||||
return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, new);
|
||||
}
|
||||
|
||||
int mv88e6xxx_port_set_map_da(struct mv88e6xxx_chip *chip, int port)
|
||||
{
|
||||
u16 reg;
|
||||
|
||||
@@ -423,6 +423,8 @@ int mv88e6393x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
|
||||
phy_interface_t mode);
|
||||
int mv88e6185_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode);
|
||||
int mv88e6352_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode);
|
||||
int mv88e6xxx_port_drop_untagged(struct mv88e6xxx_chip *chip, int port,
|
||||
bool drop_untagged);
|
||||
int mv88e6xxx_port_set_map_da(struct mv88e6xxx_chip *chip, int port);
|
||||
int mv88e6095_port_set_upstream_port(struct mv88e6xxx_chip *chip, int port,
|
||||
int upstream_port);
|
||||
|
||||
+137
-12
@@ -266,12 +266,12 @@ static void felix_8021q_cpu_port_deinit(struct ocelot *ocelot, int port)
|
||||
*/
|
||||
static int felix_setup_mmio_filtering(struct felix *felix)
|
||||
{
|
||||
unsigned long user_ports = 0, cpu_ports = 0;
|
||||
unsigned long user_ports = dsa_user_ports(felix->ds);
|
||||
struct ocelot_vcap_filter *redirect_rule;
|
||||
struct ocelot_vcap_filter *tagging_rule;
|
||||
struct ocelot *ocelot = &felix->ocelot;
|
||||
struct dsa_switch *ds = felix->ds;
|
||||
int port, ret;
|
||||
int cpu = -1, port, ret;
|
||||
|
||||
tagging_rule = kzalloc(sizeof(struct ocelot_vcap_filter), GFP_KERNEL);
|
||||
if (!tagging_rule)
|
||||
@@ -284,12 +284,15 @@ static int felix_setup_mmio_filtering(struct felix *felix)
|
||||
}
|
||||
|
||||
for (port = 0; port < ocelot->num_phys_ports; port++) {
|
||||
if (dsa_is_user_port(ds, port))
|
||||
user_ports |= BIT(port);
|
||||
if (dsa_is_cpu_port(ds, port))
|
||||
cpu_ports |= BIT(port);
|
||||
if (dsa_is_cpu_port(ds, port)) {
|
||||
cpu = port;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cpu < 0)
|
||||
return -EINVAL;
|
||||
|
||||
tagging_rule->key_type = OCELOT_VCAP_KEY_ETYPE;
|
||||
*(__be16 *)tagging_rule->key.etype.etype.value = htons(ETH_P_1588);
|
||||
*(__be16 *)tagging_rule->key.etype.etype.mask = htons(0xffff);
|
||||
@@ -325,7 +328,7 @@ static int felix_setup_mmio_filtering(struct felix *felix)
|
||||
* the CPU port module
|
||||
*/
|
||||
redirect_rule->action.mask_mode = OCELOT_MASK_MODE_REDIRECT;
|
||||
redirect_rule->action.port_mask = cpu_ports;
|
||||
redirect_rule->action.port_mask = BIT(cpu);
|
||||
} else {
|
||||
/* Trap PTP packets only to the CPU port module (which is
|
||||
* redirected to the NPI port)
|
||||
@@ -1074,6 +1077,101 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ocelot_port_purge_txtstamp_skb(struct ocelot *ocelot, int port,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ocelot_port *ocelot_port = ocelot->ports[port];
|
||||
struct sk_buff *clone = OCELOT_SKB_CB(skb)->clone;
|
||||
struct sk_buff *skb_match = NULL, *skb_tmp;
|
||||
unsigned long flags;
|
||||
|
||||
if (!clone)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&ocelot_port->tx_skbs.lock, flags);
|
||||
|
||||
skb_queue_walk_safe(&ocelot_port->tx_skbs, skb, skb_tmp) {
|
||||
if (skb != clone)
|
||||
continue;
|
||||
__skb_unlink(skb, &ocelot_port->tx_skbs);
|
||||
skb_match = skb;
|
||||
break;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&ocelot_port->tx_skbs.lock, flags);
|
||||
|
||||
WARN_ONCE(!skb_match,
|
||||
"Could not find skb clone in TX timestamping list\n");
|
||||
}
|
||||
|
||||
#define work_to_xmit_work(w) \
|
||||
container_of((w), struct felix_deferred_xmit_work, work)
|
||||
|
||||
static void felix_port_deferred_xmit(struct kthread_work *work)
|
||||
{
|
||||
struct felix_deferred_xmit_work *xmit_work = work_to_xmit_work(work);
|
||||
struct dsa_switch *ds = xmit_work->dp->ds;
|
||||
struct sk_buff *skb = xmit_work->skb;
|
||||
u32 rew_op = ocelot_ptp_rew_op(skb);
|
||||
struct ocelot *ocelot = ds->priv;
|
||||
int port = xmit_work->dp->index;
|
||||
int retries = 10;
|
||||
|
||||
do {
|
||||
if (ocelot_can_inject(ocelot, 0))
|
||||
break;
|
||||
|
||||
cpu_relax();
|
||||
} while (--retries);
|
||||
|
||||
if (!retries) {
|
||||
dev_err(ocelot->dev, "port %d failed to inject skb\n",
|
||||
port);
|
||||
ocelot_port_purge_txtstamp_skb(ocelot, port, skb);
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
|
||||
ocelot_port_inject_frame(ocelot, port, 0, rew_op, skb);
|
||||
|
||||
consume_skb(skb);
|
||||
kfree(xmit_work);
|
||||
}
|
||||
|
||||
static int felix_port_setup_tagger_data(struct dsa_switch *ds, int port)
|
||||
{
|
||||
struct dsa_port *dp = dsa_to_port(ds, port);
|
||||
struct ocelot *ocelot = ds->priv;
|
||||
struct felix *felix = ocelot_to_felix(ocelot);
|
||||
struct felix_port *felix_port;
|
||||
|
||||
if (!dsa_port_is_user(dp))
|
||||
return 0;
|
||||
|
||||
felix_port = kzalloc(sizeof(*felix_port), GFP_KERNEL);
|
||||
if (!felix_port)
|
||||
return -ENOMEM;
|
||||
|
||||
felix_port->xmit_worker = felix->xmit_worker;
|
||||
felix_port->xmit_work_fn = felix_port_deferred_xmit;
|
||||
|
||||
dp->priv = felix_port;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void felix_port_teardown_tagger_data(struct dsa_switch *ds, int port)
|
||||
{
|
||||
struct dsa_port *dp = dsa_to_port(ds, port);
|
||||
struct felix_port *felix_port = dp->priv;
|
||||
|
||||
if (!felix_port)
|
||||
return;
|
||||
|
||||
dp->priv = NULL;
|
||||
kfree(felix_port);
|
||||
}
|
||||
|
||||
/* Hardware initialization done here so that we can allocate structures with
|
||||
* devm without fear of dsa_register_switch returning -EPROBE_DEFER and causing
|
||||
* us to allocate structures twice (leak memory) and map PCI memory twice
|
||||
@@ -1102,6 +1200,12 @@ static int felix_setup(struct dsa_switch *ds)
|
||||
}
|
||||
}
|
||||
|
||||
felix->xmit_worker = kthread_create_worker(0, "felix_xmit");
|
||||
if (IS_ERR(felix->xmit_worker)) {
|
||||
err = PTR_ERR(felix->xmit_worker);
|
||||
goto out_deinit_timestamp;
|
||||
}
|
||||
|
||||
for (port = 0; port < ds->num_ports; port++) {
|
||||
if (dsa_is_unused_port(ds, port))
|
||||
continue;
|
||||
@@ -1112,6 +1216,14 @@ static int felix_setup(struct dsa_switch *ds)
|
||||
* bits of vlan tag.
|
||||
*/
|
||||
felix_port_qos_map_init(ocelot, port);
|
||||
|
||||
err = felix_port_setup_tagger_data(ds, port);
|
||||
if (err) {
|
||||
dev_err(ds->dev,
|
||||
"port %d failed to set up tagger data: %pe\n",
|
||||
port, ERR_PTR(err));
|
||||
goto out_deinit_ports;
|
||||
}
|
||||
}
|
||||
|
||||
err = ocelot_devlink_sb_register(ocelot);
|
||||
@@ -1126,6 +1238,7 @@ static int felix_setup(struct dsa_switch *ds)
|
||||
* there's no real point in checking for errors.
|
||||
*/
|
||||
felix_set_tag_protocol(ds, port, felix->tag_proto);
|
||||
break;
|
||||
}
|
||||
|
||||
ds->mtu_enforcement_ingress = true;
|
||||
@@ -1138,9 +1251,13 @@ out_deinit_ports:
|
||||
if (dsa_is_unused_port(ds, port))
|
||||
continue;
|
||||
|
||||
felix_port_teardown_tagger_data(ds, port);
|
||||
ocelot_deinit_port(ocelot, port);
|
||||
}
|
||||
|
||||
kthread_destroy_worker(felix->xmit_worker);
|
||||
|
||||
out_deinit_timestamp:
|
||||
ocelot_deinit_timestamp(ocelot);
|
||||
ocelot_deinit(ocelot);
|
||||
|
||||
@@ -1162,19 +1279,23 @@ static void felix_teardown(struct dsa_switch *ds)
|
||||
continue;
|
||||
|
||||
felix_del_tag_protocol(ds, port, felix->tag_proto);
|
||||
break;
|
||||
}
|
||||
|
||||
ocelot_devlink_sb_unregister(ocelot);
|
||||
ocelot_deinit_timestamp(ocelot);
|
||||
ocelot_deinit(ocelot);
|
||||
|
||||
for (port = 0; port < ocelot->num_phys_ports; port++) {
|
||||
if (dsa_is_unused_port(ds, port))
|
||||
continue;
|
||||
|
||||
felix_port_teardown_tagger_data(ds, port);
|
||||
ocelot_deinit_port(ocelot, port);
|
||||
}
|
||||
|
||||
kthread_destroy_worker(felix->xmit_worker);
|
||||
|
||||
ocelot_devlink_sb_unregister(ocelot);
|
||||
ocelot_deinit_timestamp(ocelot);
|
||||
ocelot_deinit(ocelot);
|
||||
|
||||
if (felix->info->mdio_bus_free)
|
||||
felix->info->mdio_bus_free(ocelot);
|
||||
}
|
||||
@@ -1291,8 +1412,12 @@ static void felix_txtstamp(struct dsa_switch *ds, int port,
|
||||
if (!ocelot->ptp)
|
||||
return;
|
||||
|
||||
if (ocelot_port_txtstamp_request(ocelot, port, skb, &clone))
|
||||
if (ocelot_port_txtstamp_request(ocelot, port, skb, &clone)) {
|
||||
dev_err_ratelimited(ds->dev,
|
||||
"port %d delivering skb without TX timestamp\n",
|
||||
port);
|
||||
return;
|
||||
}
|
||||
|
||||
if (clone)
|
||||
OCELOT_SKB_CB(skb)->clone = clone;
|
||||
|
||||
@@ -62,6 +62,7 @@ struct felix {
|
||||
resource_size_t switch_base;
|
||||
resource_size_t imdio_base;
|
||||
enum dsa_tag_protocol tag_proto;
|
||||
struct kthread_worker *xmit_worker;
|
||||
};
|
||||
|
||||
struct net_device *felix_port_to_netdev(struct ocelot *ocelot, int port);
|
||||
|
||||
@@ -3117,7 +3117,7 @@ static void sja1105_teardown(struct dsa_switch *ds)
|
||||
sja1105_static_config_free(&priv->static_config);
|
||||
}
|
||||
|
||||
const struct dsa_switch_ops sja1105_switch_ops = {
|
||||
static const struct dsa_switch_ops sja1105_switch_ops = {
|
||||
.get_tag_protocol = sja1105_get_tag_protocol,
|
||||
.setup = sja1105_setup,
|
||||
.teardown = sja1105_teardown,
|
||||
@@ -3166,7 +3166,6 @@ const struct dsa_switch_ops sja1105_switch_ops = {
|
||||
.port_bridge_tx_fwd_offload = dsa_tag_8021q_bridge_tx_fwd_offload,
|
||||
.port_bridge_tx_fwd_unoffload = dsa_tag_8021q_bridge_tx_fwd_unoffload,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(sja1105_switch_ops);
|
||||
|
||||
static const struct of_device_id sja1105_dt_ids[];
|
||||
|
||||
|
||||
@@ -64,6 +64,7 @@ enum sja1105_ptp_clk_mode {
|
||||
static int sja1105_change_rxtstamping(struct sja1105_private *priv,
|
||||
bool on)
|
||||
{
|
||||
struct sja1105_tagger_data *tagger_data = &priv->tagger_data;
|
||||
struct sja1105_ptp_data *ptp_data = &priv->ptp_data;
|
||||
struct sja1105_general_params_entry *general_params;
|
||||
struct sja1105_table *table;
|
||||
@@ -79,7 +80,7 @@ static int sja1105_change_rxtstamping(struct sja1105_private *priv,
|
||||
priv->tagger_data.stampable_skb = NULL;
|
||||
}
|
||||
ptp_cancel_worker_sync(ptp_data->clock);
|
||||
skb_queue_purge(&ptp_data->skb_txtstamp_queue);
|
||||
skb_queue_purge(&tagger_data->skb_txtstamp_queue);
|
||||
skb_queue_purge(&ptp_data->skb_rxtstamp_queue);
|
||||
|
||||
return sja1105_static_config_reload(priv, SJA1105_RX_HWTSTAMPING);
|
||||
@@ -452,40 +453,6 @@ bool sja1105_port_rxtstamp(struct dsa_switch *ds, int port,
|
||||
return priv->info->rxtstamp(ds, port, skb);
|
||||
}
|
||||
|
||||
void sja1110_process_meta_tstamp(struct dsa_switch *ds, int port, u8 ts_id,
|
||||
enum sja1110_meta_tstamp dir, u64 tstamp)
|
||||
{
|
||||
struct sja1105_private *priv = ds->priv;
|
||||
struct sja1105_ptp_data *ptp_data = &priv->ptp_data;
|
||||
struct sk_buff *skb, *skb_tmp, *skb_match = NULL;
|
||||
struct skb_shared_hwtstamps shwt = {0};
|
||||
|
||||
/* We don't care about RX timestamps on the CPU port */
|
||||
if (dir == SJA1110_META_TSTAMP_RX)
|
||||
return;
|
||||
|
||||
spin_lock(&ptp_data->skb_txtstamp_queue.lock);
|
||||
|
||||
skb_queue_walk_safe(&ptp_data->skb_txtstamp_queue, skb, skb_tmp) {
|
||||
if (SJA1105_SKB_CB(skb)->ts_id != ts_id)
|
||||
continue;
|
||||
|
||||
__skb_unlink(skb, &ptp_data->skb_txtstamp_queue);
|
||||
skb_match = skb;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
spin_unlock(&ptp_data->skb_txtstamp_queue.lock);
|
||||
|
||||
if (WARN_ON(!skb_match))
|
||||
return;
|
||||
|
||||
shwt.hwtstamp = ns_to_ktime(sja1105_ticks_to_ns(tstamp));
|
||||
skb_complete_tx_timestamp(skb_match, &shwt);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sja1110_process_meta_tstamp);
|
||||
|
||||
/* In addition to cloning the skb which is done by the common
|
||||
* sja1105_port_txtstamp, we need to generate a timestamp ID and save the
|
||||
* packet to the TX timestamping queue.
|
||||
@@ -494,7 +461,6 @@ void sja1110_txtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb)
|
||||
{
|
||||
struct sk_buff *clone = SJA1105_SKB_CB(skb)->clone;
|
||||
struct sja1105_private *priv = ds->priv;
|
||||
struct sja1105_ptp_data *ptp_data = &priv->ptp_data;
|
||||
struct sja1105_port *sp = &priv->ports[port];
|
||||
u8 ts_id;
|
||||
|
||||
@@ -510,7 +476,7 @@ void sja1110_txtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb)
|
||||
|
||||
spin_unlock(&sp->data->meta_lock);
|
||||
|
||||
skb_queue_tail(&ptp_data->skb_txtstamp_queue, clone);
|
||||
skb_queue_tail(&sp->data->skb_txtstamp_queue, clone);
|
||||
}
|
||||
|
||||
/* Called from dsa_skb_tx_timestamp. This callback is just to clone
|
||||
@@ -953,7 +919,7 @@ int sja1105_ptp_clock_register(struct dsa_switch *ds)
|
||||
/* Only used on SJA1105 */
|
||||
skb_queue_head_init(&ptp_data->skb_rxtstamp_queue);
|
||||
/* Only used on SJA1110 */
|
||||
skb_queue_head_init(&ptp_data->skb_txtstamp_queue);
|
||||
skb_queue_head_init(&tagger_data->skb_txtstamp_queue);
|
||||
spin_lock_init(&tagger_data->meta_lock);
|
||||
|
||||
ptp_data->clock = ptp_clock_register(&ptp_data->caps, ds->dev);
|
||||
@@ -971,6 +937,7 @@ int sja1105_ptp_clock_register(struct dsa_switch *ds)
|
||||
void sja1105_ptp_clock_unregister(struct dsa_switch *ds)
|
||||
{
|
||||
struct sja1105_private *priv = ds->priv;
|
||||
struct sja1105_tagger_data *tagger_data = &priv->tagger_data;
|
||||
struct sja1105_ptp_data *ptp_data = &priv->ptp_data;
|
||||
|
||||
if (IS_ERR_OR_NULL(ptp_data->clock))
|
||||
@@ -978,7 +945,7 @@ void sja1105_ptp_clock_unregister(struct dsa_switch *ds)
|
||||
|
||||
del_timer_sync(&ptp_data->extts_timer);
|
||||
ptp_cancel_worker_sync(ptp_data->clock);
|
||||
skb_queue_purge(&ptp_data->skb_txtstamp_queue);
|
||||
skb_queue_purge(&tagger_data->skb_txtstamp_queue);
|
||||
skb_queue_purge(&ptp_data->skb_rxtstamp_queue);
|
||||
ptp_clock_unregister(ptp_data->clock);
|
||||
ptp_data->clock = NULL;
|
||||
|
||||
@@ -8,21 +8,6 @@
|
||||
|
||||
#if IS_ENABLED(CONFIG_NET_DSA_SJA1105_PTP)
|
||||
|
||||
/* Timestamps are in units of 8 ns clock ticks (equivalent to
|
||||
* a fixed 125 MHz clock).
|
||||
*/
|
||||
#define SJA1105_TICK_NS 8
|
||||
|
||||
static inline s64 ns_to_sja1105_ticks(s64 ns)
|
||||
{
|
||||
return ns / SJA1105_TICK_NS;
|
||||
}
|
||||
|
||||
static inline s64 sja1105_ticks_to_ns(s64 ticks)
|
||||
{
|
||||
return ticks * SJA1105_TICK_NS;
|
||||
}
|
||||
|
||||
/* Calculate the first base_time in the future that satisfies this
|
||||
* relationship:
|
||||
*
|
||||
@@ -77,10 +62,6 @@ struct sja1105_ptp_data {
|
||||
struct timer_list extts_timer;
|
||||
/* Used only on SJA1105 to reconstruct partial timestamps */
|
||||
struct sk_buff_head skb_rxtstamp_queue;
|
||||
/* Used on SJA1110 where meta frames are generated only for
|
||||
* 2-step TX timestamps
|
||||
*/
|
||||
struct sk_buff_head skb_txtstamp_queue;
|
||||
struct ptp_clock_info caps;
|
||||
struct ptp_clock *clock;
|
||||
struct sja1105_ptp_cmd cmd;
|
||||
|
||||
@@ -100,6 +100,7 @@ config JME
|
||||
config KORINA
|
||||
tristate "Korina (IDT RC32434) Ethernet support"
|
||||
depends on MIKROTIK_RB532 || COMPILE_TEST
|
||||
select CRC32
|
||||
select MII
|
||||
help
|
||||
If you have a Mikrotik RouterBoard 500 or IDT RC32434
|
||||
|
||||
@@ -21,6 +21,7 @@ config ARC_EMAC_CORE
|
||||
depends on ARC || ARCH_ROCKCHIP || COMPILE_TEST
|
||||
select MII
|
||||
select PHYLIB
|
||||
select CRC32
|
||||
|
||||
config ARC_EMAC
|
||||
tristate "ARC EMAC support"
|
||||
|
||||
@@ -1313,22 +1313,21 @@ ice_ptp_flush_tx_tracker(struct ice_pf *pf, struct ice_ptp_tx *tx)
|
||||
{
|
||||
u8 idx;
|
||||
|
||||
spin_lock(&tx->lock);
|
||||
|
||||
for (idx = 0; idx < tx->len; idx++) {
|
||||
u8 phy_idx = idx + tx->quad_offset;
|
||||
|
||||
/* Clear any potential residual timestamp in the PHY block */
|
||||
if (!pf->hw.reset_ongoing)
|
||||
ice_clear_phy_tstamp(&pf->hw, tx->quad, phy_idx);
|
||||
|
||||
spin_lock(&tx->lock);
|
||||
if (tx->tstamps[idx].skb) {
|
||||
dev_kfree_skb_any(tx->tstamps[idx].skb);
|
||||
tx->tstamps[idx].skb = NULL;
|
||||
}
|
||||
}
|
||||
clear_bit(idx, tx->in_use);
|
||||
spin_unlock(&tx->lock);
|
||||
|
||||
spin_unlock(&tx->lock);
|
||||
/* Clear any potential residual timestamp in the PHY block */
|
||||
if (!pf->hw.reset_ongoing)
|
||||
ice_clear_phy_tstamp(&pf->hw, tx->quad, phy_idx);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -155,6 +155,8 @@ int mlx5_core_destroy_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq)
|
||||
u32 in[MLX5_ST_SZ_DW(destroy_cq_in)] = {};
|
||||
int err;
|
||||
|
||||
mlx5_debug_cq_remove(dev, cq);
|
||||
|
||||
mlx5_eq_del_cq(mlx5_get_async_eq(dev), cq);
|
||||
mlx5_eq_del_cq(&cq->eq->core, cq);
|
||||
|
||||
@@ -162,16 +164,13 @@ int mlx5_core_destroy_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq)
|
||||
MLX5_SET(destroy_cq_in, in, cqn, cq->cqn);
|
||||
MLX5_SET(destroy_cq_in, in, uid, cq->uid);
|
||||
err = mlx5_cmd_exec_in(dev, destroy_cq, in);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
synchronize_irq(cq->irqn);
|
||||
|
||||
mlx5_debug_cq_remove(dev, cq);
|
||||
mlx5_cq_put(cq);
|
||||
wait_for_completion(&cq->free);
|
||||
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(mlx5_core_destroy_cq);
|
||||
|
||||
|
||||
@@ -475,9 +475,6 @@ void mlx5e_rep_bridge_init(struct mlx5e_priv *priv)
|
||||
esw_warn(mdev, "Failed to allocate bridge offloads workqueue\n");
|
||||
goto err_alloc_wq;
|
||||
}
|
||||
INIT_DELAYED_WORK(&br_offloads->update_work, mlx5_esw_bridge_update_work);
|
||||
queue_delayed_work(br_offloads->wq, &br_offloads->update_work,
|
||||
msecs_to_jiffies(MLX5_ESW_BRIDGE_UPDATE_INTERVAL));
|
||||
|
||||
br_offloads->nb.notifier_call = mlx5_esw_bridge_switchdev_event;
|
||||
err = register_switchdev_notifier(&br_offloads->nb);
|
||||
@@ -500,6 +497,9 @@ void mlx5e_rep_bridge_init(struct mlx5e_priv *priv)
|
||||
err);
|
||||
goto err_register_netdev;
|
||||
}
|
||||
INIT_DELAYED_WORK(&br_offloads->update_work, mlx5_esw_bridge_update_work);
|
||||
queue_delayed_work(br_offloads->wq, &br_offloads->update_work,
|
||||
msecs_to_jiffies(MLX5_ESW_BRIDGE_UPDATE_INTERVAL));
|
||||
return;
|
||||
|
||||
err_register_netdev:
|
||||
@@ -523,10 +523,10 @@ void mlx5e_rep_bridge_cleanup(struct mlx5e_priv *priv)
|
||||
if (!br_offloads)
|
||||
return;
|
||||
|
||||
cancel_delayed_work_sync(&br_offloads->update_work);
|
||||
unregister_netdevice_notifier(&br_offloads->netdev_nb);
|
||||
unregister_switchdev_blocking_notifier(&br_offloads->nb_blk);
|
||||
unregister_switchdev_notifier(&br_offloads->nb);
|
||||
cancel_delayed_work(&br_offloads->update_work);
|
||||
destroy_workqueue(br_offloads->wq);
|
||||
rtnl_lock();
|
||||
mlx5_esw_bridge_cleanup(esw);
|
||||
|
||||
@@ -2981,8 +2981,8 @@ static int mlx5e_mqprio_channel_validate(struct mlx5e_priv *priv,
|
||||
agg_count += mqprio->qopt.count[i];
|
||||
}
|
||||
|
||||
if (priv->channels.params.num_channels < agg_count) {
|
||||
netdev_err(netdev, "Num of queues (%d) exceeds available (%d)\n",
|
||||
if (priv->channels.params.num_channels != agg_count) {
|
||||
netdev_err(netdev, "Num of queues (%d) does not match available (%d)\n",
|
||||
agg_count, priv->channels.params.num_channels);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -3325,20 +3325,67 @@ static int set_feature_rx_all(struct net_device *netdev, bool enable)
|
||||
return mlx5_set_port_fcs(mdev, !enable);
|
||||
}
|
||||
|
||||
static int mlx5e_set_rx_port_ts(struct mlx5_core_dev *mdev, bool enable)
|
||||
{
|
||||
u32 in[MLX5_ST_SZ_DW(pcmr_reg)] = {};
|
||||
bool supported, curr_state;
|
||||
int err;
|
||||
|
||||
if (!MLX5_CAP_GEN(mdev, ports_check))
|
||||
return 0;
|
||||
|
||||
err = mlx5_query_ports_check(mdev, in, sizeof(in));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
supported = MLX5_GET(pcmr_reg, in, rx_ts_over_crc_cap);
|
||||
curr_state = MLX5_GET(pcmr_reg, in, rx_ts_over_crc);
|
||||
|
||||
if (!supported || enable == curr_state)
|
||||
return 0;
|
||||
|
||||
MLX5_SET(pcmr_reg, in, local_port, 1);
|
||||
MLX5_SET(pcmr_reg, in, rx_ts_over_crc, enable);
|
||||
|
||||
return mlx5_set_ports_check(mdev, in, sizeof(in));
|
||||
}
|
||||
|
||||
static int set_feature_rx_fcs(struct net_device *netdev, bool enable)
|
||||
{
|
||||
struct mlx5e_priv *priv = netdev_priv(netdev);
|
||||
struct mlx5e_channels *chs = &priv->channels;
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
int err;
|
||||
|
||||
mutex_lock(&priv->state_lock);
|
||||
|
||||
priv->channels.params.scatter_fcs_en = enable;
|
||||
err = mlx5e_modify_channels_scatter_fcs(&priv->channels, enable);
|
||||
if (err)
|
||||
priv->channels.params.scatter_fcs_en = !enable;
|
||||
if (enable) {
|
||||
err = mlx5e_set_rx_port_ts(mdev, false);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
chs->params.scatter_fcs_en = true;
|
||||
err = mlx5e_modify_channels_scatter_fcs(chs, true);
|
||||
if (err) {
|
||||
chs->params.scatter_fcs_en = false;
|
||||
mlx5e_set_rx_port_ts(mdev, true);
|
||||
}
|
||||
} else {
|
||||
chs->params.scatter_fcs_en = false;
|
||||
err = mlx5e_modify_channels_scatter_fcs(chs, false);
|
||||
if (err) {
|
||||
chs->params.scatter_fcs_en = true;
|
||||
goto out;
|
||||
}
|
||||
err = mlx5e_set_rx_port_ts(mdev, true);
|
||||
if (err) {
|
||||
mlx5_core_warn(mdev, "Failed to set RX port timestamp %d\n", err);
|
||||
err = 0;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&priv->state_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@@ -618,6 +618,11 @@ static void mlx5e_build_rep_params(struct net_device *netdev)
|
||||
params->mqprio.num_tc = 1;
|
||||
params->tunneled_offload_en = false;
|
||||
|
||||
/* Set an initial non-zero value, so that mlx5e_select_queue won't
|
||||
* divide by zero if called before first activating channels.
|
||||
*/
|
||||
priv->num_tc_x_num_ch = params->num_channels * params->mqprio.num_tc;
|
||||
|
||||
mlx5_query_min_inline(mdev, ¶ms->tx_min_inline_mode);
|
||||
}
|
||||
|
||||
@@ -643,7 +648,6 @@ static void mlx5e_build_rep_netdev(struct net_device *netdev,
|
||||
netdev->hw_features |= NETIF_F_RXCSUM;
|
||||
|
||||
netdev->features |= netdev->hw_features;
|
||||
netdev->features |= NETIF_F_VLAN_CHALLENGED;
|
||||
netdev->features |= NETIF_F_NETNS_LOCAL;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,16 +24,8 @@
|
||||
#define MLXSW_THERMAL_ZONE_MAX_NAME 16
|
||||
#define MLXSW_THERMAL_TEMP_SCORE_MAX GENMASK(31, 0)
|
||||
#define MLXSW_THERMAL_MAX_STATE 10
|
||||
#define MLXSW_THERMAL_MIN_STATE 2
|
||||
#define MLXSW_THERMAL_MAX_DUTY 255
|
||||
/* Minimum and maximum fan allowed speed in percent: from 20% to 100%. Values
|
||||
* MLXSW_THERMAL_MAX_STATE + x, where x is between 2 and 10 are used for
|
||||
* setting fan speed dynamic minimum. For example, if value is set to 14 (40%)
|
||||
* cooling levels vector will be set to 4, 4, 4, 4, 4, 5, 6, 7, 8, 9, 10 to
|
||||
* introduce PWM speed in percent: 40, 40, 40, 40, 40, 50, 60. 70, 80, 90, 100.
|
||||
*/
|
||||
#define MLXSW_THERMAL_SPEED_MIN (MLXSW_THERMAL_MAX_STATE + 2)
|
||||
#define MLXSW_THERMAL_SPEED_MAX (MLXSW_THERMAL_MAX_STATE * 2)
|
||||
#define MLXSW_THERMAL_SPEED_MIN_LEVEL 2 /* 20% */
|
||||
|
||||
/* External cooling devices, allowed for binding to mlxsw thermal zones. */
|
||||
static char * const mlxsw_thermal_external_allowed_cdev[] = {
|
||||
@@ -646,49 +638,16 @@ static int mlxsw_thermal_set_cur_state(struct thermal_cooling_device *cdev,
|
||||
struct mlxsw_thermal *thermal = cdev->devdata;
|
||||
struct device *dev = thermal->bus_info->dev;
|
||||
char mfsc_pl[MLXSW_REG_MFSC_LEN];
|
||||
unsigned long cur_state, i;
|
||||
int idx;
|
||||
u8 duty;
|
||||
int err;
|
||||
|
||||
if (state > MLXSW_THERMAL_MAX_STATE)
|
||||
return -EINVAL;
|
||||
|
||||
idx = mlxsw_get_cooling_device_idx(thermal, cdev);
|
||||
if (idx < 0)
|
||||
return idx;
|
||||
|
||||
/* Verify if this request is for changing allowed fan dynamical
|
||||
* minimum. If it is - update cooling levels accordingly and update
|
||||
* state, if current state is below the newly requested minimum state.
|
||||
* For example, if current state is 5, and minimal state is to be
|
||||
* changed from 4 to 6, thermal->cooling_levels[0 to 5] will be changed
|
||||
* all from 4 to 6. And state 5 (thermal->cooling_levels[4]) should be
|
||||
* overwritten.
|
||||
*/
|
||||
if (state >= MLXSW_THERMAL_SPEED_MIN &&
|
||||
state <= MLXSW_THERMAL_SPEED_MAX) {
|
||||
state -= MLXSW_THERMAL_MAX_STATE;
|
||||
for (i = 0; i <= MLXSW_THERMAL_MAX_STATE; i++)
|
||||
thermal->cooling_levels[i] = max(state, i);
|
||||
|
||||
mlxsw_reg_mfsc_pack(mfsc_pl, idx, 0);
|
||||
err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
duty = mlxsw_reg_mfsc_pwm_duty_cycle_get(mfsc_pl);
|
||||
cur_state = mlxsw_duty_to_state(duty);
|
||||
|
||||
/* If current fan state is lower than requested dynamical
|
||||
* minimum, increase fan speed up to dynamical minimum.
|
||||
*/
|
||||
if (state < cur_state)
|
||||
return 0;
|
||||
|
||||
state = cur_state;
|
||||
}
|
||||
|
||||
if (state > MLXSW_THERMAL_MAX_STATE)
|
||||
return -EINVAL;
|
||||
|
||||
/* Normalize the state to the valid speed range. */
|
||||
state = thermal->cooling_levels[state];
|
||||
mlxsw_reg_mfsc_pack(mfsc_pl, idx, mlxsw_state_to_duty(state));
|
||||
@@ -998,8 +957,7 @@ int mlxsw_thermal_init(struct mlxsw_core *core,
|
||||
|
||||
/* Initialize cooling levels per PWM state. */
|
||||
for (i = 0; i < MLXSW_THERMAL_MAX_STATE; i++)
|
||||
thermal->cooling_levels[i] = max(MLXSW_THERMAL_SPEED_MIN_LEVEL,
|
||||
i);
|
||||
thermal->cooling_levels[i] = max(MLXSW_THERMAL_MIN_STATE, i);
|
||||
|
||||
thermal->polling_delay = bus_info->low_frequency ?
|
||||
MLXSW_THERMAL_SLOW_POLL_INT :
|
||||
|
||||
@@ -497,13 +497,19 @@ static struct regmap_bus phymap_encx24j600 = {
|
||||
.reg_read = regmap_encx24j600_phy_reg_read,
|
||||
};
|
||||
|
||||
void devm_regmap_init_encx24j600(struct device *dev,
|
||||
struct encx24j600_context *ctx)
|
||||
int devm_regmap_init_encx24j600(struct device *dev,
|
||||
struct encx24j600_context *ctx)
|
||||
{
|
||||
mutex_init(&ctx->mutex);
|
||||
regcfg.lock_arg = ctx;
|
||||
ctx->regmap = devm_regmap_init(dev, ®map_encx24j600, ctx, ®cfg);
|
||||
if (IS_ERR(ctx->regmap))
|
||||
return PTR_ERR(ctx->regmap);
|
||||
ctx->phymap = devm_regmap_init(dev, &phymap_encx24j600, ctx, &phycfg);
|
||||
if (IS_ERR(ctx->phymap))
|
||||
return PTR_ERR(ctx->phymap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_regmap_init_encx24j600);
|
||||
|
||||
|
||||
@@ -1023,10 +1023,13 @@ static int encx24j600_spi_probe(struct spi_device *spi)
|
||||
priv->speed = SPEED_100;
|
||||
|
||||
priv->ctx.spi = spi;
|
||||
devm_regmap_init_encx24j600(&spi->dev, &priv->ctx);
|
||||
ndev->irq = spi->irq;
|
||||
ndev->netdev_ops = &encx24j600_netdev_ops;
|
||||
|
||||
ret = devm_regmap_init_encx24j600(&spi->dev, &priv->ctx);
|
||||
if (ret)
|
||||
goto out_free;
|
||||
|
||||
mutex_init(&priv->lock);
|
||||
|
||||
/* Reset device and check if it is connected */
|
||||
|
||||
@@ -15,8 +15,8 @@ struct encx24j600_context {
|
||||
int bank;
|
||||
};
|
||||
|
||||
void devm_regmap_init_encx24j600(struct device *dev,
|
||||
struct encx24j600_context *ctx);
|
||||
int devm_regmap_init_encx24j600(struct device *dev,
|
||||
struct encx24j600_context *ctx);
|
||||
|
||||
/* Single-byte instructions */
|
||||
#define BANK_SELECT(bank) (0xC0 | ((bank & (BANK_MASK >> BANK_SHIFT)) << 1))
|
||||
|
||||
@@ -1477,8 +1477,10 @@ static struct mana_rxq *mana_create_rxq(struct mana_port_context *apc,
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
if (cq->gdma_id >= gc->max_num_cqs)
|
||||
if (WARN_ON(cq->gdma_id >= gc->max_num_cqs)) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
gc->cq_table[cq->gdma_id] = cq->gdma_cq;
|
||||
|
||||
|
||||
@@ -472,9 +472,9 @@ void ocelot_phylink_mac_link_down(struct ocelot *ocelot, int port,
|
||||
!(quirks & OCELOT_QUIRK_QSGMII_PORTS_MUST_BE_UP))
|
||||
ocelot_port_rmwl(ocelot_port,
|
||||
DEV_CLOCK_CFG_MAC_TX_RST |
|
||||
DEV_CLOCK_CFG_MAC_TX_RST,
|
||||
DEV_CLOCK_CFG_MAC_RX_RST,
|
||||
DEV_CLOCK_CFG_MAC_TX_RST |
|
||||
DEV_CLOCK_CFG_MAC_TX_RST,
|
||||
DEV_CLOCK_CFG_MAC_RX_RST,
|
||||
DEV_CLOCK_CFG);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ocelot_phylink_mac_link_down);
|
||||
@@ -569,49 +569,44 @@ void ocelot_phylink_mac_link_up(struct ocelot *ocelot, int port,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ocelot_phylink_mac_link_up);
|
||||
|
||||
static void ocelot_port_add_txtstamp_skb(struct ocelot *ocelot, int port,
|
||||
struct sk_buff *clone)
|
||||
static int ocelot_port_add_txtstamp_skb(struct ocelot *ocelot, int port,
|
||||
struct sk_buff *clone)
|
||||
{
|
||||
struct ocelot_port *ocelot_port = ocelot->ports[port];
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock(&ocelot_port->ts_id_lock);
|
||||
spin_lock_irqsave(&ocelot->ts_id_lock, flags);
|
||||
|
||||
if (ocelot_port->ptp_skbs_in_flight == OCELOT_MAX_PTP_ID ||
|
||||
ocelot->ptp_skbs_in_flight == OCELOT_PTP_FIFO_SIZE) {
|
||||
spin_unlock_irqrestore(&ocelot->ts_id_lock, flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
skb_shinfo(clone)->tx_flags |= SKBTX_IN_PROGRESS;
|
||||
/* Store timestamp ID in OCELOT_SKB_CB(clone)->ts_id */
|
||||
OCELOT_SKB_CB(clone)->ts_id = ocelot_port->ts_id;
|
||||
ocelot_port->ts_id = (ocelot_port->ts_id + 1) % 4;
|
||||
|
||||
ocelot_port->ts_id++;
|
||||
if (ocelot_port->ts_id == OCELOT_MAX_PTP_ID)
|
||||
ocelot_port->ts_id = 0;
|
||||
|
||||
ocelot_port->ptp_skbs_in_flight++;
|
||||
ocelot->ptp_skbs_in_flight++;
|
||||
|
||||
skb_queue_tail(&ocelot_port->tx_skbs, clone);
|
||||
|
||||
spin_unlock(&ocelot_port->ts_id_lock);
|
||||
spin_unlock_irqrestore(&ocelot->ts_id_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 ocelot_ptp_rew_op(struct sk_buff *skb)
|
||||
{
|
||||
struct sk_buff *clone = OCELOT_SKB_CB(skb)->clone;
|
||||
u8 ptp_cmd = OCELOT_SKB_CB(skb)->ptp_cmd;
|
||||
u32 rew_op = 0;
|
||||
|
||||
if (ptp_cmd == IFH_REW_OP_TWO_STEP_PTP && clone) {
|
||||
rew_op = ptp_cmd;
|
||||
rew_op |= OCELOT_SKB_CB(clone)->ts_id << 3;
|
||||
} else if (ptp_cmd == IFH_REW_OP_ORIGIN_PTP) {
|
||||
rew_op = ptp_cmd;
|
||||
}
|
||||
|
||||
return rew_op;
|
||||
}
|
||||
EXPORT_SYMBOL(ocelot_ptp_rew_op);
|
||||
|
||||
static bool ocelot_ptp_is_onestep_sync(struct sk_buff *skb)
|
||||
static bool ocelot_ptp_is_onestep_sync(struct sk_buff *skb,
|
||||
unsigned int ptp_class)
|
||||
{
|
||||
struct ptp_header *hdr;
|
||||
unsigned int ptp_class;
|
||||
u8 msgtype, twostep;
|
||||
|
||||
ptp_class = ptp_classify_raw(skb);
|
||||
if (ptp_class == PTP_CLASS_NONE)
|
||||
return false;
|
||||
|
||||
hdr = ptp_parse_header(skb, ptp_class);
|
||||
if (!hdr)
|
||||
return false;
|
||||
@@ -631,10 +626,20 @@ int ocelot_port_txtstamp_request(struct ocelot *ocelot, int port,
|
||||
{
|
||||
struct ocelot_port *ocelot_port = ocelot->ports[port];
|
||||
u8 ptp_cmd = ocelot_port->ptp_cmd;
|
||||
unsigned int ptp_class;
|
||||
int err;
|
||||
|
||||
/* Don't do anything if PTP timestamping not enabled */
|
||||
if (!ptp_cmd)
|
||||
return 0;
|
||||
|
||||
ptp_class = ptp_classify_raw(skb);
|
||||
if (ptp_class == PTP_CLASS_NONE)
|
||||
return -EINVAL;
|
||||
|
||||
/* Store ptp_cmd in OCELOT_SKB_CB(skb)->ptp_cmd */
|
||||
if (ptp_cmd == IFH_REW_OP_ORIGIN_PTP) {
|
||||
if (ocelot_ptp_is_onestep_sync(skb)) {
|
||||
if (ocelot_ptp_is_onestep_sync(skb, ptp_class)) {
|
||||
OCELOT_SKB_CB(skb)->ptp_cmd = ptp_cmd;
|
||||
return 0;
|
||||
}
|
||||
@@ -648,8 +653,12 @@ int ocelot_port_txtstamp_request(struct ocelot *ocelot, int port,
|
||||
if (!(*clone))
|
||||
return -ENOMEM;
|
||||
|
||||
ocelot_port_add_txtstamp_skb(ocelot, port, *clone);
|
||||
err = ocelot_port_add_txtstamp_skb(ocelot, port, *clone);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
OCELOT_SKB_CB(skb)->ptp_cmd = ptp_cmd;
|
||||
OCELOT_SKB_CB(*clone)->ptp_class = ptp_class;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -683,6 +692,17 @@ static void ocelot_get_hwtimestamp(struct ocelot *ocelot,
|
||||
spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
|
||||
}
|
||||
|
||||
static bool ocelot_validate_ptp_skb(struct sk_buff *clone, u16 seqid)
|
||||
{
|
||||
struct ptp_header *hdr;
|
||||
|
||||
hdr = ptp_parse_header(clone, OCELOT_SKB_CB(clone)->ptp_class);
|
||||
if (WARN_ON(!hdr))
|
||||
return false;
|
||||
|
||||
return seqid == ntohs(hdr->sequence_id);
|
||||
}
|
||||
|
||||
void ocelot_get_txtstamp(struct ocelot *ocelot)
|
||||
{
|
||||
int budget = OCELOT_PTP_QUEUE_SZ;
|
||||
@@ -690,10 +710,10 @@ void ocelot_get_txtstamp(struct ocelot *ocelot)
|
||||
while (budget--) {
|
||||
struct sk_buff *skb, *skb_tmp, *skb_match = NULL;
|
||||
struct skb_shared_hwtstamps shhwtstamps;
|
||||
u32 val, id, seqid, txport;
|
||||
struct ocelot_port *port;
|
||||
struct timespec64 ts;
|
||||
unsigned long flags;
|
||||
u32 val, id, txport;
|
||||
|
||||
val = ocelot_read(ocelot, SYS_PTP_STATUS);
|
||||
|
||||
@@ -706,10 +726,17 @@ void ocelot_get_txtstamp(struct ocelot *ocelot)
|
||||
/* Retrieve the ts ID and Tx port */
|
||||
id = SYS_PTP_STATUS_PTP_MESS_ID_X(val);
|
||||
txport = SYS_PTP_STATUS_PTP_MESS_TXPORT_X(val);
|
||||
seqid = SYS_PTP_STATUS_PTP_MESS_SEQ_ID(val);
|
||||
|
||||
/* Retrieve its associated skb */
|
||||
port = ocelot->ports[txport];
|
||||
|
||||
spin_lock(&ocelot->ts_id_lock);
|
||||
port->ptp_skbs_in_flight--;
|
||||
ocelot->ptp_skbs_in_flight--;
|
||||
spin_unlock(&ocelot->ts_id_lock);
|
||||
|
||||
/* Retrieve its associated skb */
|
||||
try_again:
|
||||
spin_lock_irqsave(&port->tx_skbs.lock, flags);
|
||||
|
||||
skb_queue_walk_safe(&port->tx_skbs, skb, skb_tmp) {
|
||||
@@ -722,12 +749,20 @@ void ocelot_get_txtstamp(struct ocelot *ocelot)
|
||||
|
||||
spin_unlock_irqrestore(&port->tx_skbs.lock, flags);
|
||||
|
||||
if (WARN_ON(!skb_match))
|
||||
continue;
|
||||
|
||||
if (!ocelot_validate_ptp_skb(skb_match, seqid)) {
|
||||
dev_err_ratelimited(ocelot->dev,
|
||||
"port %d received stale TX timestamp for seqid %d, discarding\n",
|
||||
txport, seqid);
|
||||
dev_kfree_skb_any(skb);
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
/* Get the h/w timestamp */
|
||||
ocelot_get_hwtimestamp(ocelot, &ts);
|
||||
|
||||
if (unlikely(!skb_match))
|
||||
continue;
|
||||
|
||||
/* Set the timestamp into the skb */
|
||||
memset(&shhwtstamps, 0, sizeof(shhwtstamps));
|
||||
shhwtstamps.hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec);
|
||||
@@ -1948,7 +1983,6 @@ void ocelot_init_port(struct ocelot *ocelot, int port)
|
||||
struct ocelot_port *ocelot_port = ocelot->ports[port];
|
||||
|
||||
skb_queue_head_init(&ocelot_port->tx_skbs);
|
||||
spin_lock_init(&ocelot_port->ts_id_lock);
|
||||
|
||||
/* Basic L2 initialization */
|
||||
|
||||
@@ -2081,6 +2115,7 @@ int ocelot_init(struct ocelot *ocelot)
|
||||
mutex_init(&ocelot->stats_lock);
|
||||
mutex_init(&ocelot->ptp_lock);
|
||||
spin_lock_init(&ocelot->ptp_clock_lock);
|
||||
spin_lock_init(&ocelot->ts_id_lock);
|
||||
snprintf(queue_name, sizeof(queue_name), "%s-stats",
|
||||
dev_name(ocelot->dev));
|
||||
ocelot->stats_queue = create_singlethread_workqueue(queue_name);
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* Copyright 2020-2021 NXP
|
||||
*/
|
||||
|
||||
#include <linux/dsa/ocelot.h>
|
||||
#include <linux/if_bridge.h>
|
||||
#include <linux/of_net.h>
|
||||
#include <linux/phy/phy.h>
|
||||
@@ -1625,7 +1626,7 @@ static int ocelot_port_phylink_create(struct ocelot *ocelot, int port,
|
||||
if (phy_mode == PHY_INTERFACE_MODE_QSGMII)
|
||||
ocelot_port_rmwl(ocelot_port, 0,
|
||||
DEV_CLOCK_CFG_MAC_TX_RST |
|
||||
DEV_CLOCK_CFG_MAC_TX_RST,
|
||||
DEV_CLOCK_CFG_MAC_RX_RST,
|
||||
DEV_CLOCK_CFG);
|
||||
|
||||
ocelot_port->phy_mode = phy_mode;
|
||||
|
||||
@@ -8566,7 +8566,7 @@ static void s2io_io_resume(struct pci_dev *pdev)
|
||||
return;
|
||||
}
|
||||
|
||||
if (s2io_set_mac_addr(netdev, netdev->dev_addr) == FAILURE) {
|
||||
if (do_s2io_prog_unicast(netdev, netdev->dev_addr) == FAILURE) {
|
||||
s2io_card_down(sp);
|
||||
pr_err("Can't restore mac addr after reset.\n");
|
||||
return;
|
||||
|
||||
@@ -830,10 +830,6 @@ static int nfp_flower_init(struct nfp_app *app)
|
||||
if (err)
|
||||
goto err_cleanup;
|
||||
|
||||
err = flow_indr_dev_register(nfp_flower_indr_setup_tc_cb, app);
|
||||
if (err)
|
||||
goto err_cleanup;
|
||||
|
||||
if (app_priv->flower_ext_feats & NFP_FL_FEATS_VF_RLIM)
|
||||
nfp_flower_qos_init(app);
|
||||
|
||||
@@ -942,7 +938,20 @@ static int nfp_flower_start(struct nfp_app *app)
|
||||
return err;
|
||||
}
|
||||
|
||||
return nfp_tunnel_config_start(app);
|
||||
err = flow_indr_dev_register(nfp_flower_indr_setup_tc_cb, app);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = nfp_tunnel_config_start(app);
|
||||
if (err)
|
||||
goto err_tunnel_config;
|
||||
|
||||
return 0;
|
||||
|
||||
err_tunnel_config:
|
||||
flow_indr_dev_unregister(nfp_flower_indr_setup_tc_cb, app,
|
||||
nfp_flower_setup_indr_tc_release);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void nfp_flower_stop(struct nfp_app *app)
|
||||
|
||||
@@ -1379,6 +1379,10 @@ static int ionic_addr_add(struct net_device *netdev, const u8 *addr)
|
||||
|
||||
static int ionic_addr_del(struct net_device *netdev, const u8 *addr)
|
||||
{
|
||||
/* Don't delete our own address from the uc list */
|
||||
if (ether_addr_equal(addr, netdev->dev_addr))
|
||||
return 0;
|
||||
|
||||
return ionic_lif_list_addr(netdev_priv(netdev), addr, DEL_ADDR);
|
||||
}
|
||||
|
||||
|
||||
@@ -1299,6 +1299,7 @@ static int qed_slowpath_start(struct qed_dev *cdev,
|
||||
} else {
|
||||
DP_NOTICE(cdev,
|
||||
"Failed to acquire PTT for aRFS\n");
|
||||
rc = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,6 +71,7 @@ err_remove_config_dt:
|
||||
|
||||
static const struct of_device_id dwmac_generic_match[] = {
|
||||
{ .compatible = "st,spear600-gmac"},
|
||||
{ .compatible = "snps,dwmac-3.40a"},
|
||||
{ .compatible = "snps,dwmac-3.50a"},
|
||||
{ .compatible = "snps,dwmac-3.610"},
|
||||
{ .compatible = "snps,dwmac-3.70a"},
|
||||
|
||||
@@ -218,11 +218,18 @@ static void dwmac1000_dump_dma_regs(void __iomem *ioaddr, u32 *reg_space)
|
||||
readl(ioaddr + DMA_BUS_MODE + i * 4);
|
||||
}
|
||||
|
||||
static void dwmac1000_get_hw_feature(void __iomem *ioaddr,
|
||||
struct dma_features *dma_cap)
|
||||
static int dwmac1000_get_hw_feature(void __iomem *ioaddr,
|
||||
struct dma_features *dma_cap)
|
||||
{
|
||||
u32 hw_cap = readl(ioaddr + DMA_HW_FEATURE);
|
||||
|
||||
if (!hw_cap) {
|
||||
/* 0x00000000 is the value read on old hardware that does not
|
||||
* implement this register
|
||||
*/
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
dma_cap->mbps_10_100 = (hw_cap & DMA_HW_FEAT_MIISEL);
|
||||
dma_cap->mbps_1000 = (hw_cap & DMA_HW_FEAT_GMIISEL) >> 1;
|
||||
dma_cap->half_duplex = (hw_cap & DMA_HW_FEAT_HDSEL) >> 2;
|
||||
@@ -252,6 +259,8 @@ static void dwmac1000_get_hw_feature(void __iomem *ioaddr,
|
||||
dma_cap->number_tx_channel = (hw_cap & DMA_HW_FEAT_TXCHCNT) >> 22;
|
||||
/* Alternate (enhanced) DESC mode */
|
||||
dma_cap->enh_desc = (hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dwmac1000_rx_watchdog(void __iomem *ioaddr, u32 riwt,
|
||||
|
||||
@@ -347,8 +347,8 @@ static void dwmac4_dma_tx_chan_op_mode(void __iomem *ioaddr, int mode,
|
||||
writel(mtl_tx_op, ioaddr + MTL_CHAN_TX_OP_MODE(channel));
|
||||
}
|
||||
|
||||
static void dwmac4_get_hw_feature(void __iomem *ioaddr,
|
||||
struct dma_features *dma_cap)
|
||||
static int dwmac4_get_hw_feature(void __iomem *ioaddr,
|
||||
struct dma_features *dma_cap)
|
||||
{
|
||||
u32 hw_cap = readl(ioaddr + GMAC_HW_FEATURE0);
|
||||
|
||||
@@ -437,6 +437,8 @@ static void dwmac4_get_hw_feature(void __iomem *ioaddr,
|
||||
dma_cap->frpbs = (hw_cap & GMAC_HW_FEAT_FRPBS) >> 11;
|
||||
dma_cap->frpsel = (hw_cap & GMAC_HW_FEAT_FRPSEL) >> 10;
|
||||
dma_cap->dvlan = (hw_cap & GMAC_HW_FEAT_DVLAN) >> 5;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Enable/disable TSO feature and set MSS */
|
||||
|
||||
@@ -371,8 +371,8 @@ static int dwxgmac2_dma_interrupt(void __iomem *ioaddr,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void dwxgmac2_get_hw_feature(void __iomem *ioaddr,
|
||||
struct dma_features *dma_cap)
|
||||
static int dwxgmac2_get_hw_feature(void __iomem *ioaddr,
|
||||
struct dma_features *dma_cap)
|
||||
{
|
||||
u32 hw_cap;
|
||||
|
||||
@@ -445,6 +445,8 @@ static void dwxgmac2_get_hw_feature(void __iomem *ioaddr,
|
||||
dma_cap->frpes = (hw_cap & XGMAC_HWFEAT_FRPES) >> 11;
|
||||
dma_cap->frpbs = (hw_cap & XGMAC_HWFEAT_FRPPB) >> 9;
|
||||
dma_cap->frpsel = (hw_cap & XGMAC_HWFEAT_FRPSEL) >> 3;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dwxgmac2_rx_watchdog(void __iomem *ioaddr, u32 riwt, u32 queue)
|
||||
|
||||
@@ -203,8 +203,8 @@ struct stmmac_dma_ops {
|
||||
int (*dma_interrupt) (void __iomem *ioaddr,
|
||||
struct stmmac_extra_stats *x, u32 chan, u32 dir);
|
||||
/* If supported then get the optional core features */
|
||||
void (*get_hw_feature)(void __iomem *ioaddr,
|
||||
struct dma_features *dma_cap);
|
||||
int (*get_hw_feature)(void __iomem *ioaddr,
|
||||
struct dma_features *dma_cap);
|
||||
/* Program the HW RX Watchdog */
|
||||
void (*rx_watchdog)(void __iomem *ioaddr, u32 riwt, u32 queue);
|
||||
void (*set_tx_ring_len)(void __iomem *ioaddr, u32 len, u32 chan);
|
||||
@@ -255,7 +255,7 @@ struct stmmac_dma_ops {
|
||||
#define stmmac_dma_interrupt_status(__priv, __args...) \
|
||||
stmmac_do_callback(__priv, dma, dma_interrupt, __args)
|
||||
#define stmmac_get_hw_feature(__priv, __args...) \
|
||||
stmmac_do_void_callback(__priv, dma, get_hw_feature, __args)
|
||||
stmmac_do_callback(__priv, dma, get_hw_feature, __args)
|
||||
#define stmmac_rx_watchdog(__priv, __args...) \
|
||||
stmmac_do_void_callback(__priv, dma, rx_watchdog, __args)
|
||||
#define stmmac_set_tx_ring_len(__priv, __args...) \
|
||||
|
||||
@@ -508,6 +508,14 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac)
|
||||
plat->pmt = 1;
|
||||
}
|
||||
|
||||
if (of_device_is_compatible(np, "snps,dwmac-3.40a")) {
|
||||
plat->has_gmac = 1;
|
||||
plat->enh_desc = 1;
|
||||
plat->tx_coe = 1;
|
||||
plat->bugged_jumbo = 1;
|
||||
plat->pmt = 1;
|
||||
}
|
||||
|
||||
if (of_device_is_compatible(np, "snps,dwmac-4.00") ||
|
||||
of_device_is_compatible(np, "snps,dwmac-4.10a") ||
|
||||
of_device_is_compatible(np, "snps,dwmac-4.20a") ||
|
||||
|
||||
@@ -3125,6 +3125,9 @@ static void phy_shutdown(struct device *dev)
|
||||
{
|
||||
struct phy_device *phydev = to_phy_device(dev);
|
||||
|
||||
if (phydev->state == PHY_READY || !phydev->attached_dev)
|
||||
return;
|
||||
|
||||
phy_disable_interrupts(phydev);
|
||||
}
|
||||
|
||||
|
||||
@@ -99,6 +99,10 @@ config USB_RTL8150
|
||||
config USB_RTL8152
|
||||
tristate "Realtek RTL8152/RTL8153 Based USB Ethernet Adapters"
|
||||
select MII
|
||||
select CRC32
|
||||
select CRYPTO
|
||||
select CRYPTO_HASH
|
||||
select CRYPTO_SHA256
|
||||
help
|
||||
This option adds support for Realtek RTL8152 based USB 2.0
|
||||
10/100 Ethernet adapters and RTL8153 based USB 3.0 10/100/1000
|
||||
|
||||
@@ -406,7 +406,7 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi,
|
||||
* add_recvbuf_mergeable() + get_mergeable_buf_len()
|
||||
*/
|
||||
truesize = headroom ? PAGE_SIZE : truesize;
|
||||
tailroom = truesize - len - headroom;
|
||||
tailroom = truesize - len - headroom - (hdr_padded_len - hdr_len);
|
||||
buf = p - headroom;
|
||||
|
||||
len -= hdr_len;
|
||||
|
||||
+12
-6
@@ -535,6 +535,7 @@ static int msi_verify_entries(struct pci_dev *dev)
|
||||
static int msi_capability_init(struct pci_dev *dev, int nvec,
|
||||
struct irq_affinity *affd)
|
||||
{
|
||||
const struct attribute_group **groups;
|
||||
struct msi_desc *entry;
|
||||
int ret;
|
||||
|
||||
@@ -558,12 +559,14 @@ static int msi_capability_init(struct pci_dev *dev, int nvec,
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
dev->msi_irq_groups = msi_populate_sysfs(&dev->dev);
|
||||
if (IS_ERR(dev->msi_irq_groups)) {
|
||||
ret = PTR_ERR(dev->msi_irq_groups);
|
||||
groups = msi_populate_sysfs(&dev->dev);
|
||||
if (IS_ERR(groups)) {
|
||||
ret = PTR_ERR(groups);
|
||||
goto err;
|
||||
}
|
||||
|
||||
dev->msi_irq_groups = groups;
|
||||
|
||||
/* Set MSI enabled bits */
|
||||
pci_intx_for_msi(dev, 0);
|
||||
pci_msi_set_enable(dev, 1);
|
||||
@@ -691,6 +694,7 @@ static void msix_mask_all(void __iomem *base, int tsize)
|
||||
static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries,
|
||||
int nvec, struct irq_affinity *affd)
|
||||
{
|
||||
const struct attribute_group **groups;
|
||||
void __iomem *base;
|
||||
int ret, tsize;
|
||||
u16 control;
|
||||
@@ -730,12 +734,14 @@ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries,
|
||||
|
||||
msix_update_entries(dev, entries);
|
||||
|
||||
dev->msi_irq_groups = msi_populate_sysfs(&dev->dev);
|
||||
if (IS_ERR(dev->msi_irq_groups)) {
|
||||
ret = PTR_ERR(dev->msi_irq_groups);
|
||||
groups = msi_populate_sysfs(&dev->dev);
|
||||
if (IS_ERR(groups)) {
|
||||
ret = PTR_ERR(groups);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
dev->msi_irq_groups = groups;
|
||||
|
||||
/* Set MSI-X enabled bits and unmask the function */
|
||||
pci_intx_for_msi(dev, 0);
|
||||
dev->msix_enabled = 1;
|
||||
|
||||
@@ -1301,7 +1301,7 @@ static int atmel_spi_one_transfer(struct spi_master *master,
|
||||
* DMA map early, for performance (empties dcache ASAP) and
|
||||
* better fault reporting.
|
||||
*/
|
||||
if ((!master->cur_msg_mapped)
|
||||
if ((!master->cur_msg->is_dma_mapped)
|
||||
&& as->use_pdc) {
|
||||
if (atmel_spi_dma_map_xfer(as, xfer) < 0)
|
||||
return -ENOMEM;
|
||||
@@ -1381,7 +1381,7 @@ static int atmel_spi_one_transfer(struct spi_master *master,
|
||||
}
|
||||
}
|
||||
|
||||
if (!master->cur_msg_mapped
|
||||
if (!master->cur_msg->is_dma_mapped
|
||||
&& as->use_pdc)
|
||||
atmel_spi_dma_unmap_xfer(master, xfer);
|
||||
|
||||
|
||||
+45
-32
@@ -1250,10 +1250,14 @@ static void bcm_qspi_hw_init(struct bcm_qspi *qspi)
|
||||
|
||||
static void bcm_qspi_hw_uninit(struct bcm_qspi *qspi)
|
||||
{
|
||||
u32 status = bcm_qspi_read(qspi, MSPI, MSPI_MSPI_STATUS);
|
||||
|
||||
bcm_qspi_write(qspi, MSPI, MSPI_SPCR2, 0);
|
||||
if (has_bspi(qspi))
|
||||
bcm_qspi_write(qspi, MSPI, MSPI_WRITE_LOCK, 0);
|
||||
|
||||
/* clear interrupt */
|
||||
bcm_qspi_write(qspi, MSPI, MSPI_MSPI_STATUS, status & ~1);
|
||||
}
|
||||
|
||||
static const struct spi_controller_mem_ops bcm_qspi_mem_ops = {
|
||||
@@ -1397,6 +1401,47 @@ int bcm_qspi_probe(struct platform_device *pdev,
|
||||
if (!qspi->dev_ids)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* Some SoCs integrate spi controller (e.g., its interrupt bits)
|
||||
* in specific ways
|
||||
*/
|
||||
if (soc_intc) {
|
||||
qspi->soc_intc = soc_intc;
|
||||
soc_intc->bcm_qspi_int_set(soc_intc, MSPI_DONE, true);
|
||||
} else {
|
||||
qspi->soc_intc = NULL;
|
||||
}
|
||||
|
||||
if (qspi->clk) {
|
||||
ret = clk_prepare_enable(qspi->clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to prepare clock\n");
|
||||
goto qspi_probe_err;
|
||||
}
|
||||
qspi->base_clk = clk_get_rate(qspi->clk);
|
||||
} else {
|
||||
qspi->base_clk = MSPI_BASE_FREQ;
|
||||
}
|
||||
|
||||
if (data->has_mspi_rev) {
|
||||
rev = bcm_qspi_read(qspi, MSPI, MSPI_REV);
|
||||
/* some older revs do not have a MSPI_REV register */
|
||||
if ((rev & 0xff) == 0xff)
|
||||
rev = 0;
|
||||
}
|
||||
|
||||
qspi->mspi_maj_rev = (rev >> 4) & 0xf;
|
||||
qspi->mspi_min_rev = rev & 0xf;
|
||||
qspi->mspi_spcr3_sysclk = data->has_spcr3_sysclk;
|
||||
|
||||
qspi->max_speed_hz = qspi->base_clk / (bcm_qspi_spbr_min(qspi) * 2);
|
||||
|
||||
/*
|
||||
* On SW resets it is possible to have the mask still enabled
|
||||
* Need to disable the mask and clear the status while we init
|
||||
*/
|
||||
bcm_qspi_hw_uninit(qspi);
|
||||
|
||||
for (val = 0; val < num_irqs; val++) {
|
||||
irq = -1;
|
||||
name = qspi_irq_tab[val].irq_name;
|
||||
@@ -1433,38 +1478,6 @@ int bcm_qspi_probe(struct platform_device *pdev,
|
||||
goto qspi_probe_err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Some SoCs integrate spi controller (e.g., its interrupt bits)
|
||||
* in specific ways
|
||||
*/
|
||||
if (soc_intc) {
|
||||
qspi->soc_intc = soc_intc;
|
||||
soc_intc->bcm_qspi_int_set(soc_intc, MSPI_DONE, true);
|
||||
} else {
|
||||
qspi->soc_intc = NULL;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(qspi->clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to prepare clock\n");
|
||||
goto qspi_probe_err;
|
||||
}
|
||||
|
||||
qspi->base_clk = clk_get_rate(qspi->clk);
|
||||
|
||||
if (data->has_mspi_rev) {
|
||||
rev = bcm_qspi_read(qspi, MSPI, MSPI_REV);
|
||||
/* some older revs do not have a MSPI_REV register */
|
||||
if ((rev & 0xff) == 0xff)
|
||||
rev = 0;
|
||||
}
|
||||
|
||||
qspi->mspi_maj_rev = (rev >> 4) & 0xf;
|
||||
qspi->mspi_min_rev = rev & 0xf;
|
||||
qspi->mspi_spcr3_sysclk = data->has_spcr3_sysclk;
|
||||
|
||||
qspi->max_speed_hz = qspi->base_clk / (bcm_qspi_spbr_min(qspi) * 2);
|
||||
|
||||
bcm_qspi_hw_init(qspi);
|
||||
init_completion(&qspi->mspi_done);
|
||||
init_completion(&qspi->bspi_done);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user