Merge tag 'v6.6-rc4' into android-mainline
Linux 6.6-rc4 Change-Id: I163a55b2f733ef3abee62a85db6a69a59e340e71 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
@@ -92,6 +92,13 @@ Brief summary of control files.
|
||||
memory.oom_control set/show oom controls.
|
||||
memory.numa_stat show the number of memory usage per numa
|
||||
node
|
||||
memory.kmem.limit_in_bytes Deprecated knob to set and read the kernel
|
||||
memory hard limit. Kernel hard limit is not
|
||||
supported since 5.16. Writing any value to
|
||||
do file will not have any effect same as if
|
||||
nokmem kernel parameter was specified.
|
||||
Kernel memory is still charged and reported
|
||||
by memory.kmem.usage_in_bytes.
|
||||
memory.kmem.usage_in_bytes show current kernel memory allocation
|
||||
memory.kmem.failcnt show the number of kernel memory usage
|
||||
hits limits
|
||||
|
||||
@@ -38,6 +38,7 @@ patternProperties:
|
||||
ID number 0 and the slave drive will have ID number 1. The PATA port
|
||||
nodes will be named "ide-port".
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
properties:
|
||||
reg:
|
||||
|
||||
@@ -37,6 +37,9 @@ properties:
|
||||
maxItems: 1
|
||||
|
||||
'#clock-cells':
|
||||
description:
|
||||
The index in the assigned-clocks is mapped to the output clock as below
|
||||
0 - REF, 1 - SE1, 2 - SE2, 3 - SE3, 4 - DIFF1, 5 - DIFF2.
|
||||
const: 1
|
||||
|
||||
clocks:
|
||||
@@ -68,7 +71,7 @@ examples:
|
||||
reg = <0x68>;
|
||||
#clock-cells = <1>;
|
||||
|
||||
clocks = <&x1_x2>;
|
||||
clocks = <&x1>;
|
||||
|
||||
renesas,settings = [
|
||||
80 00 11 19 4c 02 23 7f 83 19 08 a9 5f 25 24 bf
|
||||
@@ -79,8 +82,8 @@ examples:
|
||||
assigned-clocks = <&versa3 0>, <&versa3 1>,
|
||||
<&versa3 2>, <&versa3 3>,
|
||||
<&versa3 4>, <&versa3 5>;
|
||||
assigned-clock-rates = <12288000>, <25000000>,
|
||||
<12000000>, <11289600>,
|
||||
<11289600>, <24000000>;
|
||||
assigned-clock-rates = <24000000>, <11289600>,
|
||||
<11289600>, <12000000>,
|
||||
<25000000>, <12288000>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -9,6 +9,9 @@ title: Freescale MXS Inter IC (I2C) Controller
|
||||
maintainers:
|
||||
- Shawn Guo <shawnguo@kernel.org>
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/i2c/i2c-controller.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
@@ -37,7 +40,7 @@ required:
|
||||
- dmas
|
||||
- dma-names
|
||||
|
||||
additionalProperties: false
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
||||
@@ -11,11 +11,16 @@ maintainers:
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- loongson,ls2k0500-pmc
|
||||
- loongson,ls2k1000-pmc
|
||||
- const: syscon
|
||||
oneOf:
|
||||
- items:
|
||||
- const: loongson,ls2k0500-pmc
|
||||
- const: syscon
|
||||
- items:
|
||||
- enum:
|
||||
- loongson,ls2k1000-pmc
|
||||
- loongson,ls2k2000-pmc
|
||||
- const: loongson,ls2k0500-pmc
|
||||
- const: syscon
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
@@ -32,6 +37,18 @@ properties:
|
||||
addition, the PM need according to it to indicate that current
|
||||
SoC whether support Suspend To RAM.
|
||||
|
||||
syscon-poweroff:
|
||||
$ref: /schemas/power/reset/syscon-poweroff.yaml#
|
||||
type: object
|
||||
description:
|
||||
Node for power off method
|
||||
|
||||
syscon-reboot:
|
||||
$ref: /schemas/power/reset/syscon-reboot.yaml#
|
||||
type: object
|
||||
description:
|
||||
Node for reboot method
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
@@ -44,9 +61,23 @@ examples:
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
power-management@1fe27000 {
|
||||
compatible = "loongson,ls2k1000-pmc", "syscon";
|
||||
compatible = "loongson,ls2k1000-pmc", "loongson,ls2k0500-pmc", "syscon";
|
||||
reg = <0x1fe27000 0x58>;
|
||||
interrupt-parent = <&liointc1>;
|
||||
interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
|
||||
loongson,suspend-address = <0x0 0x1c000500>;
|
||||
|
||||
syscon-reboot {
|
||||
compatible = "syscon-reboot";
|
||||
offset = <0x30>;
|
||||
mask = <0x1>;
|
||||
};
|
||||
|
||||
syscon-poweroff {
|
||||
compatible = "syscon-poweroff";
|
||||
regmap = <&pmc>;
|
||||
offset = <0x14>;
|
||||
mask = <0x3c00>;
|
||||
value = <0x3c00>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -22,6 +22,13 @@ properties:
|
||||
- const: fsl,imx35-cspi
|
||||
- const: fsl,imx51-ecspi
|
||||
- const: fsl,imx53-ecspi
|
||||
- items:
|
||||
- enum:
|
||||
- fsl,imx25-cspi
|
||||
- fsl,imx50-cspi
|
||||
- fsl,imx51-cspi
|
||||
- fsl,imx53-cspi
|
||||
- const: fsl,imx35-cspi
|
||||
- items:
|
||||
- const: fsl,imx8mp-ecspi
|
||||
- const: fsl,imx6ul-ecspi
|
||||
|
||||
@@ -949,3 +949,99 @@ mmap_lock held. All in-tree users have been audited and do not seem to
|
||||
depend on the mmap_lock being held, but out of tree users should verify
|
||||
for themselves. If they do need it, they can return VM_FAULT_RETRY to
|
||||
be called with the mmap_lock held.
|
||||
|
||||
---
|
||||
|
||||
**mandatory**
|
||||
|
||||
The order of opening block devices and matching or creating superblocks has
|
||||
changed.
|
||||
|
||||
The old logic opened block devices first and then tried to find a
|
||||
suitable superblock to reuse based on the block device pointer.
|
||||
|
||||
The new logic tries to find a suitable superblock first based on the device
|
||||
number, and opening the block device afterwards.
|
||||
|
||||
Since opening block devices cannot happen under s_umount because of lock
|
||||
ordering requirements s_umount is now dropped while opening block devices and
|
||||
reacquired before calling fill_super().
|
||||
|
||||
In the old logic concurrent mounters would find the superblock on the list of
|
||||
superblocks for the filesystem type. Since the first opener of the block device
|
||||
would hold s_umount they would wait until the superblock became either born or
|
||||
was discarded due to initialization failure.
|
||||
|
||||
Since the new logic drops s_umount concurrent mounters could grab s_umount and
|
||||
would spin. Instead they are now made to wait using an explicit wait-wake
|
||||
mechanism without having to hold s_umount.
|
||||
|
||||
---
|
||||
|
||||
**mandatory**
|
||||
|
||||
The holder of a block device is now the superblock.
|
||||
|
||||
The holder of a block device used to be the file_system_type which wasn't
|
||||
particularly useful. It wasn't possible to go from block device to owning
|
||||
superblock without matching on the device pointer stored in the superblock.
|
||||
This mechanism would only work for a single device so the block layer couldn't
|
||||
find the owning superblock of any additional devices.
|
||||
|
||||
In the old mechanism reusing or creating a superblock for a racing mount(2) and
|
||||
umount(2) relied on the file_system_type as the holder. This was severly
|
||||
underdocumented however:
|
||||
|
||||
(1) Any concurrent mounter that managed to grab an active reference on an
|
||||
existing superblock was made to wait until the superblock either became
|
||||
ready or until the superblock was removed from the list of superblocks of
|
||||
the filesystem type. If the superblock is ready the caller would simple
|
||||
reuse it.
|
||||
|
||||
(2) If the mounter came after deactivate_locked_super() but before
|
||||
the superblock had been removed from the list of superblocks of the
|
||||
filesystem type the mounter would wait until the superblock was shutdown,
|
||||
reuse the block device and allocate a new superblock.
|
||||
|
||||
(3) If the mounter came after deactivate_locked_super() and after
|
||||
the superblock had been removed from the list of superblocks of the
|
||||
filesystem type the mounter would reuse the block device and allocate a new
|
||||
superblock (the bd_holder point may still be set to the filesystem type).
|
||||
|
||||
Because the holder of the block device was the file_system_type any concurrent
|
||||
mounter could open the block devices of any superblock of the same
|
||||
file_system_type without risking seeing EBUSY because the block device was
|
||||
still in use by another superblock.
|
||||
|
||||
Making the superblock the owner of the block device changes this as the holder
|
||||
is now a unique superblock and thus block devices associated with it cannot be
|
||||
reused by concurrent mounters. So a concurrent mounter in (2) could suddenly
|
||||
see EBUSY when trying to open a block device whose holder was a different
|
||||
superblock.
|
||||
|
||||
The new logic thus waits until the superblock and the devices are shutdown in
|
||||
->kill_sb(). Removal of the superblock from the list of superblocks of the
|
||||
filesystem type is now moved to a later point when the devices are closed:
|
||||
|
||||
(1) Any concurrent mounter managing to grab an active reference on an existing
|
||||
superblock is made to wait until the superblock is either ready or until
|
||||
the superblock and all devices are shutdown in ->kill_sb(). If the
|
||||
superblock is ready the caller will simply reuse it.
|
||||
|
||||
(2) If the mounter comes after deactivate_locked_super() but before
|
||||
the superblock has been removed from the list of superblocks of the
|
||||
filesystem type the mounter is made to wait until the superblock and the
|
||||
devices are shut down in ->kill_sb() and the superblock is removed from the
|
||||
list of superblocks of the filesystem type. The mounter will allocate a new
|
||||
superblock and grab ownership of the block device (the bd_holder pointer of
|
||||
the block device will be set to the newly allocated superblock).
|
||||
|
||||
(3) This case is now collapsed into (2) as the superblock is left on the list
|
||||
of superblocks of the filesystem type until all devices are shutdown in
|
||||
->kill_sb(). In other words, if the superblock isn't on the list of
|
||||
superblock of the filesystem type anymore then it has given up ownership of
|
||||
all associated block devices (the bd_holder pointer is NULL).
|
||||
|
||||
As this is a VFS level change it has no practical consequences for filesystems
|
||||
other than that all of them must use one of the provided kill_litter_super(),
|
||||
kill_anon_super(), or kill_block_super() helpers.
|
||||
|
||||
@@ -573,6 +573,32 @@ above, leading to:
|
||||
bool "Support for foo hardware"
|
||||
depends on ARCH_FOO_VENDOR || COMPILE_TEST
|
||||
|
||||
Optional dependencies
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Some drivers are able to optionally use a feature from another module
|
||||
or build cleanly with that module disabled, but cause a link failure
|
||||
when trying to use that loadable module from a built-in driver.
|
||||
|
||||
The most common way to express this optional dependency in Kconfig logic
|
||||
uses the slightly counterintuitive::
|
||||
|
||||
config FOO
|
||||
tristate "Support for foo hardware"
|
||||
depends on BAR || !BAR
|
||||
|
||||
This means that there is either a dependency on BAR that disallows
|
||||
the combination of FOO=y with BAR=m, or BAR is completely disabled.
|
||||
For a more formalized approach if there are multiple drivers that have
|
||||
the same dependency, a helper symbol can be used, like::
|
||||
|
||||
config FOO
|
||||
tristate "Support for foo hardware"
|
||||
depends on BAR_OPTIONAL
|
||||
|
||||
config BAR_OPTIONAL
|
||||
def_tristate BAR || !BAR
|
||||
|
||||
Kconfig recursive dependency limitations
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
+6
-5
@@ -1963,12 +1963,12 @@ F: drivers/irqchip/irq-aspeed-i2c-ic.c
|
||||
|
||||
ARM/ASPEED MACHINE SUPPORT
|
||||
M: Joel Stanley <joel@jms.id.au>
|
||||
R: Andrew Jeffery <andrew@aj.id.au>
|
||||
R: Andrew Jeffery <andrew@codeconstruct.com.au>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
L: linux-aspeed@lists.ozlabs.org (moderated for non-subscribers)
|
||||
S: Supported
|
||||
Q: https://patchwork.ozlabs.org/project/linux-aspeed/list/
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/joel/aspeed.git
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/joel/bmc.git
|
||||
F: Documentation/devicetree/bindings/arm/aspeed/
|
||||
F: arch/arm/boot/dts/aspeed/
|
||||
F: arch/arm/mach-aspeed/
|
||||
@@ -3058,7 +3058,7 @@ F: Documentation/devicetree/bindings/peci/peci-aspeed.yaml
|
||||
F: drivers/peci/controller/peci-aspeed.c
|
||||
|
||||
ASPEED PINCTRL DRIVERS
|
||||
M: Andrew Jeffery <andrew@aj.id.au>
|
||||
M: Andrew Jeffery <andrew@codeconstruct.com.au>
|
||||
L: linux-aspeed@lists.ozlabs.org (moderated for non-subscribers)
|
||||
L: openbmc@lists.ozlabs.org (moderated for non-subscribers)
|
||||
L: linux-gpio@vger.kernel.org
|
||||
@@ -3075,7 +3075,7 @@ F: drivers/irqchip/irq-aspeed-scu-ic.c
|
||||
F: include/dt-bindings/interrupt-controller/aspeed-scu-ic.h
|
||||
|
||||
ASPEED SD/MMC DRIVER
|
||||
M: Andrew Jeffery <andrew@aj.id.au>
|
||||
M: Andrew Jeffery <andrew@codeconstruct.com.au>
|
||||
L: linux-aspeed@lists.ozlabs.org (moderated for non-subscribers)
|
||||
L: openbmc@lists.ozlabs.org (moderated for non-subscribers)
|
||||
L: linux-mmc@vger.kernel.org
|
||||
@@ -4082,7 +4082,7 @@ F: drivers/net/wireless/broadcom/brcm80211/
|
||||
|
||||
BROADCOM BRCMSTB GPIO DRIVER
|
||||
M: Doug Berger <opendmb@gmail.com>
|
||||
M: Florian Fainelli <florian.fainelli@broadcom>
|
||||
M: Florian Fainelli <florian.fainelli@broadcom.com>
|
||||
R: Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com>
|
||||
S: Supported
|
||||
F: Documentation/devicetree/bindings/gpio/brcm,brcmstb-gpio.yaml
|
||||
@@ -6647,6 +6647,7 @@ F: drivers/gpu/drm/panel/panel-novatek-nt36672a.c
|
||||
DRM DRIVER FOR NVIDIA GEFORCE/QUADRO GPUS
|
||||
M: Karol Herbst <kherbst@redhat.com>
|
||||
M: Lyude Paul <lyude@redhat.com>
|
||||
M: Danilo Krummrich <dakr@redhat.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
L: nouveau@lists.freedesktop.org
|
||||
S: Supported
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
VERSION = 6
|
||||
PATCHLEVEL = 6
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc3
|
||||
EXTRAVERSION = -rc4
|
||||
NAME = Hurr durr I'ma ninja sloth
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
||||
@@ -614,12 +614,12 @@
|
||||
/* Configure pwm clock source for timers 8 & 9 */
|
||||
&timer8 {
|
||||
assigned-clocks = <&abe_clkctrl OMAP4_TIMER8_CLKCTRL 24>;
|
||||
assigned-clock-parents = <&sys_clkin_ck>;
|
||||
assigned-clock-parents = <&sys_32k_ck>;
|
||||
};
|
||||
|
||||
&timer9 {
|
||||
assigned-clocks = <&l4_per_clkctrl OMAP4_TIMER9_CLKCTRL 24>;
|
||||
assigned-clock-parents = <&sys_clkin_ck>;
|
||||
assigned-clock-parents = <&sys_32k_ck>;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -640,6 +640,7 @@
|
||||
&uart3 {
|
||||
interrupts-extended = <&wakeupgen GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH
|
||||
&omap4_pmx_core 0x17c>;
|
||||
overrun-throttle-ms = <500>;
|
||||
};
|
||||
|
||||
&uart4 {
|
||||
|
||||
@@ -12,8 +12,7 @@ cpu_thermal: cpu-thermal {
|
||||
polling-delay = <1000>; /* milliseconds */
|
||||
coefficients = <0 20000>;
|
||||
|
||||
/* sensor ID */
|
||||
thermal-sensors = <&bandgap 0>;
|
||||
thermal-sensors = <&bandgap>;
|
||||
|
||||
cpu_trips: trips {
|
||||
cpu_alert0: cpu_alert {
|
||||
|
||||
@@ -12,7 +12,10 @@ cpu_thermal: cpu_thermal {
|
||||
polling-delay-passive = <250>; /* milliseconds */
|
||||
polling-delay = <1000>; /* milliseconds */
|
||||
|
||||
/* sensor ID */
|
||||
/*
|
||||
* See 44xx files for single sensor addressing, omap5 and dra7 need
|
||||
* also sensor ID for addressing.
|
||||
*/
|
||||
thermal-sensors = <&bandgap 0>;
|
||||
|
||||
cpu_trips: trips {
|
||||
|
||||
@@ -69,6 +69,7 @@
|
||||
};
|
||||
|
||||
&cpu_thermal {
|
||||
thermal-sensors = <&bandgap>;
|
||||
coefficients = <0 20000>;
|
||||
};
|
||||
|
||||
|
||||
@@ -79,6 +79,7 @@
|
||||
};
|
||||
|
||||
&cpu_thermal {
|
||||
thermal-sensors = <&bandgap>;
|
||||
coefficients = <348 (-9301)>;
|
||||
};
|
||||
|
||||
|
||||
@@ -195,7 +195,7 @@ struct locomo_driver {
|
||||
|
||||
#define LOCOMO_DRIVER_NAME(_ldev) ((_ldev)->dev.driver->name)
|
||||
|
||||
void locomo_lcd_power(struct locomo_dev *, int, unsigned int);
|
||||
extern void locomolcd_power(int on);
|
||||
|
||||
int locomo_driver_register(struct locomo_driver *);
|
||||
void locomo_driver_unregister(struct locomo_driver *);
|
||||
|
||||
@@ -99,7 +99,7 @@ static int omap4_pm_suspend(void)
|
||||
* possible causes.
|
||||
* http://www.spinics.net/lists/arm-kernel/msg218641.html
|
||||
*/
|
||||
pr_warn("A possible cause could be an old bootloader - try u-boot >= v2012.07\n");
|
||||
pr_debug("A possible cause could be an old bootloader - try u-boot >= v2012.07\n");
|
||||
} else {
|
||||
pr_info("Successfully put all powerdomains to target state\n");
|
||||
}
|
||||
@@ -257,7 +257,7 @@ int __init omap4_pm_init(void)
|
||||
* http://www.spinics.net/lists/arm-kernel/msg218641.html
|
||||
*/
|
||||
if (cpu_is_omap44xx())
|
||||
pr_warn("OMAP4 PM: u-boot >= v2012.07 is required for full PM support\n");
|
||||
pr_debug("OMAP4 PM: u-boot >= v2012.07 is required for full PM support\n");
|
||||
|
||||
ret = pwrdm_for_each(pwrdms_setup, NULL);
|
||||
if (ret) {
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
#include "hardware.h" /* Gives GPIO_MAX */
|
||||
|
||||
extern void locomolcd_power(int on);
|
||||
|
||||
#define COLLIE_SCOOP_GPIO_BASE (GPIO_MAX + 1)
|
||||
#define COLLIE_GPIO_CHARGE_ON (COLLIE_SCOOP_GPIO_BASE + 0)
|
||||
#define COLLIE_SCP_DIAG_BOOT1 SCOOP_GPCR_PA12
|
||||
|
||||
@@ -58,11 +58,13 @@
|
||||
((op & UNIPHIER_SSCOQM_S_MASK) == UNIPHIER_SSCOQM_S_RANGE)
|
||||
|
||||
/**
|
||||
* uniphier_cache_data - UniPhier outer cache specific data
|
||||
* struct uniphier_cache_data - UniPhier outer cache specific data
|
||||
*
|
||||
* @ctrl_base: virtual base address of control registers
|
||||
* @rev_base: virtual base address of revision registers
|
||||
* @op_base: virtual base address of operation registers
|
||||
* @way_ctrl_base: virtual address of the way control registers for this
|
||||
* SoC revision
|
||||
* @way_mask: each bit specifies if the way is present
|
||||
* @nsets: number of associativity sets
|
||||
* @line_size: line size in bytes
|
||||
|
||||
@@ -66,6 +66,7 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mm-mx8menlo.dtb
|
||||
dtb-$(CONFIG_ARCH_MXC) += imx8mm-nitrogen-r2.dtb
|
||||
dtb-$(CONFIG_ARCH_MXC) += imx8mm-phg.dtb
|
||||
dtb-$(CONFIG_ARCH_MXC) += imx8mm-phyboard-polis-rdk.dtb
|
||||
dtb-$(CONFIG_ARCH_MXC) += imx8mm-prt8mm.dtb
|
||||
dtb-$(CONFIG_ARCH_MXC) += imx8mm-tqma8mqml-mba8mx.dtb
|
||||
dtb-$(CONFIG_ARCH_MXC) += imx8mm-var-som-symphony.dtb
|
||||
dtb-$(CONFIG_ARCH_MXC) += imx8mm-venice-gw71xx-0x.dtb
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
port {
|
||||
hdmi_connector_in: endpoint {
|
||||
remote-endpoint = <&adv7533_out>;
|
||||
remote-endpoint = <&adv7535_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -72,6 +72,13 @@
|
||||
enable-active-high;
|
||||
};
|
||||
|
||||
reg_vddext_3v3: regulator-vddext-3v3 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "VDDEXT_3V3";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
};
|
||||
|
||||
backlight: backlight {
|
||||
compatible = "pwm-backlight";
|
||||
pwms = <&pwm1 0 5000000 0>;
|
||||
@@ -317,15 +324,16 @@
|
||||
|
||||
hdmi@3d {
|
||||
compatible = "adi,adv7535";
|
||||
reg = <0x3d>, <0x3c>, <0x3e>, <0x3f>;
|
||||
reg-names = "main", "cec", "edid", "packet";
|
||||
reg = <0x3d>;
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
|
||||
adi,dsi-lanes = <4>;
|
||||
|
||||
adi,input-depth = <8>;
|
||||
adi,input-colorspace = "rgb";
|
||||
adi,input-clock = "1x";
|
||||
adi,input-style = <1>;
|
||||
adi,input-justification = "evenly";
|
||||
avdd-supply = <&buck5_reg>;
|
||||
dvdd-supply = <&buck5_reg>;
|
||||
pvdd-supply = <&buck5_reg>;
|
||||
a2vdd-supply = <&buck5_reg>;
|
||||
v3p3-supply = <®_vddext_3v3>;
|
||||
v1p2-supply = <&buck5_reg>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
@@ -334,7 +342,7 @@
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
|
||||
adv7533_in: endpoint {
|
||||
adv7535_in: endpoint {
|
||||
remote-endpoint = <&dsi_out>;
|
||||
};
|
||||
};
|
||||
@@ -342,7 +350,7 @@
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
adv7533_out: endpoint {
|
||||
adv7535_out: endpoint {
|
||||
remote-endpoint = <&hdmi_connector_in>;
|
||||
};
|
||||
};
|
||||
@@ -448,7 +456,7 @@
|
||||
reg = <1>;
|
||||
|
||||
dsi_out: endpoint {
|
||||
remote-endpoint = <&adv7533_in>;
|
||||
remote-endpoint = <&adv7535_in>;
|
||||
data-lanes = <1 2 3 4>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -381,9 +381,10 @@
|
||||
&sai3 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_sai3>;
|
||||
assigned-clocks = <&clk IMX8MP_CLK_SAI3>;
|
||||
assigned-clocks = <&clk IMX8MP_CLK_SAI3>,
|
||||
<&clk IMX8MP_AUDIO_PLL2> ;
|
||||
assigned-clock-parents = <&clk IMX8MP_AUDIO_PLL2_OUT>;
|
||||
assigned-clock-rates = <12288000>;
|
||||
assigned-clock-rates = <12288000>, <361267200>;
|
||||
fsl,sai-mclk-direction-output;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
@@ -790,6 +790,12 @@
|
||||
reg = <IMX8MP_POWER_DOMAIN_AUDIOMIX>;
|
||||
clocks = <&clk IMX8MP_CLK_AUDIO_ROOT>,
|
||||
<&clk IMX8MP_CLK_AUDIO_AXI>;
|
||||
assigned-clocks = <&clk IMX8MP_CLK_AUDIO_AHB>,
|
||||
<&clk IMX8MP_CLK_AUDIO_AXI_SRC>;
|
||||
assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_800M>,
|
||||
<&clk IMX8MP_SYS_PLL1_800M>;
|
||||
assigned-clock-rates = <400000000>,
|
||||
<600000000>;
|
||||
};
|
||||
|
||||
pgc_gpu2d: power-domain@6 {
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
&gpio1 {
|
||||
pmic-irq-hog {
|
||||
gpio-hog;
|
||||
gpios = <2 GPIO_ACTIVE_LOW>;
|
||||
gpios = <3 GPIO_ACTIVE_LOW>;
|
||||
input;
|
||||
line-name = "PMIC_IRQ#";
|
||||
};
|
||||
|
||||
@@ -2957,7 +2957,7 @@
|
||||
clock-names = "merge","merge_async";
|
||||
power-domains = <&spm MT8195_POWER_DOMAIN_VDOSYS1>;
|
||||
mediatek,gce-client-reg = <&gce0 SUBSYS_1c10XXXX 0xc000 0x1000>;
|
||||
mediatek,merge-mute = <1>;
|
||||
mediatek,merge-mute;
|
||||
resets = <&vdosys1 MT8195_VDOSYS1_SW0_RST_B_MERGE0_DL_ASYNC>;
|
||||
};
|
||||
|
||||
@@ -2970,7 +2970,7 @@
|
||||
clock-names = "merge","merge_async";
|
||||
power-domains = <&spm MT8195_POWER_DOMAIN_VDOSYS1>;
|
||||
mediatek,gce-client-reg = <&gce0 SUBSYS_1c10XXXX 0xd000 0x1000>;
|
||||
mediatek,merge-mute = <1>;
|
||||
mediatek,merge-mute;
|
||||
resets = <&vdosys1 MT8195_VDOSYS1_SW0_RST_B_MERGE1_DL_ASYNC>;
|
||||
};
|
||||
|
||||
@@ -2983,7 +2983,7 @@
|
||||
clock-names = "merge","merge_async";
|
||||
power-domains = <&spm MT8195_POWER_DOMAIN_VDOSYS1>;
|
||||
mediatek,gce-client-reg = <&gce0 SUBSYS_1c10XXXX 0xe000 0x1000>;
|
||||
mediatek,merge-mute = <1>;
|
||||
mediatek,merge-mute;
|
||||
resets = <&vdosys1 MT8195_VDOSYS1_SW0_RST_B_MERGE2_DL_ASYNC>;
|
||||
};
|
||||
|
||||
@@ -2996,7 +2996,7 @@
|
||||
clock-names = "merge","merge_async";
|
||||
power-domains = <&spm MT8195_POWER_DOMAIN_VDOSYS1>;
|
||||
mediatek,gce-client-reg = <&gce0 SUBSYS_1c10XXXX 0xf000 0x1000>;
|
||||
mediatek,merge-mute = <1>;
|
||||
mediatek,merge-mute;
|
||||
resets = <&vdosys1 MT8195_VDOSYS1_SW0_RST_B_MERGE3_DL_ASYNC>;
|
||||
};
|
||||
|
||||
@@ -3009,7 +3009,7 @@
|
||||
clock-names = "merge","merge_async";
|
||||
power-domains = <&spm MT8195_POWER_DOMAIN_VDOSYS1>;
|
||||
mediatek,gce-client-reg = <&gce0 SUBSYS_1c11XXXX 0x0000 0x1000>;
|
||||
mediatek,merge-fifo-en = <1>;
|
||||
mediatek,merge-fifo-en;
|
||||
resets = <&vdosys1 MT8195_VDOSYS1_SW0_RST_B_MERGE4_DL_ASYNC>;
|
||||
};
|
||||
|
||||
|
||||
@@ -636,6 +636,7 @@ CONFIG_POWER_RESET_MSM=y
|
||||
CONFIG_POWER_RESET_QCOM_PON=m
|
||||
CONFIG_POWER_RESET_XGENE=y
|
||||
CONFIG_POWER_RESET_SYSCON=y
|
||||
CONFIG_POWER_RESET_SYSCON_POWEROFF=y
|
||||
CONFIG_SYSCON_REBOOT_MODE=y
|
||||
CONFIG_NVMEM_REBOOT_MODE=m
|
||||
CONFIG_BATTERY_SBS=m
|
||||
@@ -1175,7 +1176,6 @@ CONFIG_COMMON_CLK_S2MPS11=y
|
||||
CONFIG_COMMON_CLK_PWM=y
|
||||
CONFIG_COMMON_CLK_RS9_PCIE=y
|
||||
CONFIG_COMMON_CLK_VC5=y
|
||||
CONFIG_COMMON_CLK_NPCM8XX=y
|
||||
CONFIG_COMMON_CLK_BD718XX=m
|
||||
CONFIG_CLK_RASPBERRYPI=m
|
||||
CONFIG_CLK_IMX8MM=y
|
||||
|
||||
@@ -28,7 +28,7 @@ pte_t arch_make_huge_pte(pte_t entry, unsigned int shift, vm_flags_t flags);
|
||||
#define arch_make_huge_pte arch_make_huge_pte
|
||||
#define __HAVE_ARCH_HUGE_SET_HUGE_PTE_AT
|
||||
extern void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
|
||||
pte_t *ptep, pte_t pte);
|
||||
pte_t *ptep, pte_t pte, unsigned long sz);
|
||||
#define __HAVE_ARCH_HUGE_PTEP_SET_ACCESS_FLAGS
|
||||
extern int huge_ptep_set_access_flags(struct vm_area_struct *vma,
|
||||
unsigned long addr, pte_t *ptep,
|
||||
|
||||
@@ -241,15 +241,8 @@ static void clear_flush(struct mm_struct *mm,
|
||||
flush_tlb_range(&vma, saddr, addr);
|
||||
}
|
||||
|
||||
static inline struct folio *hugetlb_swap_entry_to_folio(swp_entry_t entry)
|
||||
{
|
||||
VM_BUG_ON(!is_migration_entry(entry) && !is_hwpoison_entry(entry));
|
||||
|
||||
return page_folio(pfn_to_page(swp_offset_pfn(entry)));
|
||||
}
|
||||
|
||||
void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
|
||||
pte_t *ptep, pte_t pte)
|
||||
pte_t *ptep, pte_t pte, unsigned long sz)
|
||||
{
|
||||
size_t pgsize;
|
||||
int i;
|
||||
@@ -257,13 +250,10 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
|
||||
unsigned long pfn, dpfn;
|
||||
pgprot_t hugeprot;
|
||||
|
||||
ncontig = num_contig_ptes(sz, &pgsize);
|
||||
|
||||
if (!pte_present(pte)) {
|
||||
struct folio *folio;
|
||||
|
||||
folio = hugetlb_swap_entry_to_folio(pte_to_swp_entry(pte));
|
||||
ncontig = num_contig_ptes(folio_size(folio), &pgsize);
|
||||
|
||||
for (i = 0; i < ncontig; i++, ptep++)
|
||||
for (i = 0; i < ncontig; i++, ptep++, addr += pgsize)
|
||||
set_pte_at(mm, addr, ptep, pte);
|
||||
return;
|
||||
}
|
||||
@@ -273,7 +263,6 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
|
||||
return;
|
||||
}
|
||||
|
||||
ncontig = find_num_contig(mm, addr, ptep, &pgsize);
|
||||
pfn = pte_pfn(pte);
|
||||
dpfn = pgsize >> PAGE_SHIFT;
|
||||
hugeprot = pte_pgprot(pte);
|
||||
@@ -571,5 +560,7 @@ pte_t huge_ptep_modify_prot_start(struct vm_area_struct *vma, unsigned long addr
|
||||
void huge_ptep_modify_prot_commit(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep,
|
||||
pte_t old_pte, pte_t pte)
|
||||
{
|
||||
set_huge_pte_at(vma->vm_mm, addr, ptep, pte);
|
||||
unsigned long psize = huge_page_size(hstate_vma(vma));
|
||||
|
||||
set_huge_pte_at(vma->vm_mm, addr, ptep, pte, psize);
|
||||
}
|
||||
|
||||
@@ -111,6 +111,15 @@
|
||||
#define R_LARCH_TLS_GD_HI20 98
|
||||
#define R_LARCH_32_PCREL 99
|
||||
#define R_LARCH_RELAX 100
|
||||
#define R_LARCH_DELETE 101
|
||||
#define R_LARCH_ALIGN 102
|
||||
#define R_LARCH_PCREL20_S2 103
|
||||
#define R_LARCH_CFA 104
|
||||
#define R_LARCH_ADD6 105
|
||||
#define R_LARCH_SUB6 106
|
||||
#define R_LARCH_ADD_ULEB128 107
|
||||
#define R_LARCH_SUB_ULEB128 108
|
||||
#define R_LARCH_64_PCREL 109
|
||||
|
||||
#ifndef ELF_ARCH
|
||||
|
||||
|
||||
@@ -367,6 +367,24 @@ static int apply_r_larch_got_pc(struct module *mod,
|
||||
return apply_r_larch_pcala(mod, location, got, rela_stack, rela_stack_top, type);
|
||||
}
|
||||
|
||||
static int apply_r_larch_32_pcrel(struct module *mod, u32 *location, Elf_Addr v,
|
||||
s64 *rela_stack, size_t *rela_stack_top, unsigned int type)
|
||||
{
|
||||
ptrdiff_t offset = (void *)v - (void *)location;
|
||||
|
||||
*(u32 *)location = offset;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int apply_r_larch_64_pcrel(struct module *mod, u32 *location, Elf_Addr v,
|
||||
s64 *rela_stack, size_t *rela_stack_top, unsigned int type)
|
||||
{
|
||||
ptrdiff_t offset = (void *)v - (void *)location;
|
||||
|
||||
*(u64 *)location = offset;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* reloc_handlers_rela() - Apply a particular relocation to a module
|
||||
* @mod: the module to apply the reloc to
|
||||
@@ -382,7 +400,7 @@ typedef int (*reloc_rela_handler)(struct module *mod, u32 *location, Elf_Addr v,
|
||||
|
||||
/* The handlers for known reloc types */
|
||||
static reloc_rela_handler reloc_rela_handlers[] = {
|
||||
[R_LARCH_NONE ... R_LARCH_RELAX] = apply_r_larch_error,
|
||||
[R_LARCH_NONE ... R_LARCH_64_PCREL] = apply_r_larch_error,
|
||||
|
||||
[R_LARCH_NONE] = apply_r_larch_none,
|
||||
[R_LARCH_32] = apply_r_larch_32,
|
||||
@@ -396,6 +414,8 @@ static reloc_rela_handler reloc_rela_handlers[] = {
|
||||
[R_LARCH_SOP_POP_32_S_10_5 ... R_LARCH_SOP_POP_32_U] = apply_r_larch_sop_imm_field,
|
||||
[R_LARCH_ADD32 ... R_LARCH_SUB64] = apply_r_larch_add_sub,
|
||||
[R_LARCH_PCALA_HI20...R_LARCH_PCALA64_HI12] = apply_r_larch_pcala,
|
||||
[R_LARCH_32_PCREL] = apply_r_larch_32_pcrel,
|
||||
[R_LARCH_64_PCREL] = apply_r_larch_64_pcrel,
|
||||
};
|
||||
|
||||
int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
|
||||
|
||||
@@ -436,7 +436,7 @@ void __init paging_init(void)
|
||||
|
||||
void __init mem_init(void)
|
||||
{
|
||||
high_memory = (void *) __va(get_num_physpages() << PAGE_SHIFT);
|
||||
high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT);
|
||||
memblock_free_all();
|
||||
}
|
||||
|
||||
|
||||
@@ -164,6 +164,7 @@ static struct platform_device db1x00_audio_dev = {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#ifdef CONFIG_MMC_AU1X
|
||||
static irqreturn_t db1100_mmc_cd(int irq, void *ptr)
|
||||
{
|
||||
mmc_detect_change(ptr, msecs_to_jiffies(500));
|
||||
@@ -369,6 +370,7 @@ static struct platform_device db1100_mmc1_dev = {
|
||||
.num_resources = ARRAY_SIZE(au1100_mmc1_res),
|
||||
.resource = au1100_mmc1_res,
|
||||
};
|
||||
#endif /* CONFIG_MMC_AU1X */
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
@@ -440,8 +442,10 @@ static struct platform_device *db1x00_devs[] = {
|
||||
|
||||
static struct platform_device *db1100_devs[] = {
|
||||
&au1100_lcd_device,
|
||||
#ifdef CONFIG_MMC_AU1X
|
||||
&db1100_mmc0_dev,
|
||||
&db1100_mmc1_dev,
|
||||
#endif
|
||||
};
|
||||
|
||||
int __init db1000_dev_setup(void)
|
||||
|
||||
@@ -326,6 +326,7 @@ static struct platform_device db1200_ide_dev = {
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
#ifdef CONFIG_MMC_AU1X
|
||||
/* SD carddetects: they're supposed to be edge-triggered, but ack
|
||||
* doesn't seem to work (CPLD Rev 2). Instead, the screaming one
|
||||
* is disabled and its counterpart enabled. The 200ms timeout is
|
||||
@@ -584,6 +585,7 @@ static struct platform_device pb1200_mmc1_dev = {
|
||||
.num_resources = ARRAY_SIZE(au1200_mmc1_res),
|
||||
.resource = au1200_mmc1_res,
|
||||
};
|
||||
#endif /* CONFIG_MMC_AU1X */
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
@@ -751,7 +753,9 @@ static struct platform_device db1200_audiodma_dev = {
|
||||
static struct platform_device *db1200_devs[] __initdata = {
|
||||
NULL, /* PSC0, selected by S6.8 */
|
||||
&db1200_ide_dev,
|
||||
#ifdef CONFIG_MMC_AU1X
|
||||
&db1200_mmc0_dev,
|
||||
#endif
|
||||
&au1200_lcd_dev,
|
||||
&db1200_eth_dev,
|
||||
&db1200_nand_dev,
|
||||
@@ -762,7 +766,9 @@ static struct platform_device *db1200_devs[] __initdata = {
|
||||
};
|
||||
|
||||
static struct platform_device *pb1200_devs[] __initdata = {
|
||||
#ifdef CONFIG_MMC_AU1X
|
||||
&pb1200_mmc1_dev,
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Some peripheral base addresses differ on the PB1200 */
|
||||
|
||||
@@ -450,6 +450,7 @@ static struct platform_device db1300_ide_dev = {
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
#ifdef CONFIG_MMC_AU1X
|
||||
static irqreturn_t db1300_mmc_cd(int irq, void *ptr)
|
||||
{
|
||||
disable_irq_nosync(irq);
|
||||
@@ -632,6 +633,7 @@ static struct platform_device db1300_sd0_dev = {
|
||||
.resource = au1300_sd0_res,
|
||||
.num_resources = ARRAY_SIZE(au1300_sd0_res),
|
||||
};
|
||||
#endif /* CONFIG_MMC_AU1X */
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
@@ -767,8 +769,10 @@ static struct platform_device *db1300_dev[] __initdata = {
|
||||
&db1300_5waysw_dev,
|
||||
&db1300_nand_dev,
|
||||
&db1300_ide_dev,
|
||||
#ifdef CONFIG_MMC_AU1X
|
||||
&db1300_sd0_dev,
|
||||
&db1300_sd1_dev,
|
||||
#endif
|
||||
&db1300_lcd_dev,
|
||||
&db1300_ac97_dev,
|
||||
&db1300_i2s_dev,
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
#define __HAVE_ARCH_HUGE_SET_HUGE_PTE_AT
|
||||
void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
|
||||
pte_t *ptep, pte_t pte);
|
||||
pte_t *ptep, pte_t pte, unsigned long sz);
|
||||
|
||||
#define __HAVE_ARCH_HUGE_PTEP_GET_AND_CLEAR
|
||||
pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
|
||||
|
||||
@@ -140,7 +140,7 @@ static void __set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
|
||||
}
|
||||
|
||||
void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
|
||||
pte_t *ptep, pte_t entry)
|
||||
pte_t *ptep, pte_t entry, unsigned long sz)
|
||||
{
|
||||
__set_huge_pte_at(mm, addr, ptep, entry);
|
||||
}
|
||||
|
||||
@@ -46,7 +46,8 @@ static inline int check_and_get_huge_psize(int shift)
|
||||
}
|
||||
|
||||
#define __HAVE_ARCH_HUGE_SET_HUGE_PTE_AT
|
||||
void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte);
|
||||
void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep,
|
||||
pte_t pte, unsigned long sz);
|
||||
|
||||
#define __HAVE_ARCH_HUGE_PTE_CLEAR
|
||||
static inline void huge_pte_clear(struct mm_struct *mm, unsigned long addr,
|
||||
|
||||
@@ -73,29 +73,12 @@ int __no_sanitize_address arch_stack_walk_reliable(stack_trace_consume_fn consum
|
||||
bool firstframe;
|
||||
|
||||
stack_end = stack_page + THREAD_SIZE;
|
||||
if (!is_idle_task(task)) {
|
||||
/*
|
||||
* For user tasks, this is the SP value loaded on
|
||||
* kernel entry, see "PACAKSAVE(r13)" in _switch() and
|
||||
* system_call_common().
|
||||
*
|
||||
* Likewise for non-swapper kernel threads,
|
||||
* this also happens to be the top of the stack
|
||||
* as setup by copy_thread().
|
||||
*
|
||||
* Note that stack backlinks are not properly setup by
|
||||
* copy_thread() and thus, a forked task() will have
|
||||
* an unreliable stack trace until it's been
|
||||
* _switch()'ed to for the first time.
|
||||
*/
|
||||
stack_end -= STACK_USER_INT_FRAME_SIZE;
|
||||
} else {
|
||||
/*
|
||||
* idle tasks have a custom stack layout,
|
||||
* c.f. cpu_idle_thread_init().
|
||||
*/
|
||||
|
||||
// See copy_thread() for details.
|
||||
if (task->flags & PF_KTHREAD)
|
||||
stack_end -= STACK_FRAME_MIN_SIZE;
|
||||
}
|
||||
else
|
||||
stack_end -= STACK_USER_INT_FRAME_SIZE;
|
||||
|
||||
if (task == current)
|
||||
sp = current_stack_frame();
|
||||
|
||||
@@ -143,11 +143,14 @@ pte_t huge_ptep_modify_prot_start(struct vm_area_struct *vma,
|
||||
void huge_ptep_modify_prot_commit(struct vm_area_struct *vma, unsigned long addr,
|
||||
pte_t *ptep, pte_t old_pte, pte_t pte)
|
||||
{
|
||||
unsigned long psize;
|
||||
|
||||
if (radix_enabled())
|
||||
return radix__huge_ptep_modify_prot_commit(vma, addr, ptep,
|
||||
old_pte, pte);
|
||||
set_huge_pte_at(vma->vm_mm, addr, ptep, pte);
|
||||
|
||||
psize = huge_page_size(hstate_vma(vma));
|
||||
set_huge_pte_at(vma->vm_mm, addr, ptep, pte, psize);
|
||||
}
|
||||
|
||||
void __init hugetlbpage_init_defaultsize(void)
|
||||
|
||||
@@ -47,6 +47,7 @@ void radix__huge_ptep_modify_prot_commit(struct vm_area_struct *vma,
|
||||
pte_t old_pte, pte_t pte)
|
||||
{
|
||||
struct mm_struct *mm = vma->vm_mm;
|
||||
unsigned long psize = huge_page_size(hstate_vma(vma));
|
||||
|
||||
/*
|
||||
* POWER9 NMMU must flush the TLB after clearing the PTE before
|
||||
@@ -58,5 +59,5 @@ void radix__huge_ptep_modify_prot_commit(struct vm_area_struct *vma,
|
||||
atomic_read(&mm->context.copros) > 0)
|
||||
radix__flush_hugetlb_page(vma, addr);
|
||||
|
||||
set_huge_pte_at(vma->vm_mm, addr, ptep, pte);
|
||||
set_huge_pte_at(vma->vm_mm, addr, ptep, pte, psize);
|
||||
}
|
||||
|
||||
@@ -91,7 +91,8 @@ static int __ref __early_map_kernel_hugepage(unsigned long va, phys_addr_t pa,
|
||||
if (new && WARN_ON(pte_present(*ptep) && pgprot_val(prot)))
|
||||
return -EINVAL;
|
||||
|
||||
set_huge_pte_at(&init_mm, va, ptep, pte_mkhuge(pfn_pte(pa >> PAGE_SHIFT, prot)));
|
||||
set_huge_pte_at(&init_mm, va, ptep,
|
||||
pte_mkhuge(pfn_pte(pa >> PAGE_SHIFT, prot)), psize);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -288,7 +288,8 @@ int huge_ptep_set_access_flags(struct vm_area_struct *vma,
|
||||
}
|
||||
|
||||
#if defined(CONFIG_PPC_8xx)
|
||||
void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte)
|
||||
void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep,
|
||||
pte_t pte, unsigned long sz)
|
||||
{
|
||||
pmd_t *pmd = pmd_off(mm, addr);
|
||||
pte_basic_t val;
|
||||
|
||||
@@ -262,7 +262,7 @@
|
||||
reg = <0x100000 0x400000>;
|
||||
};
|
||||
reserved-data@600000 {
|
||||
reg = <0x600000 0x1000000>;
|
||||
reg = <0x600000 0xa00000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -440,30 +440,6 @@
|
||||
};
|
||||
};
|
||||
|
||||
uart0_pins: uart0-0 {
|
||||
tx-pins {
|
||||
pinmux = <GPIOMUX(5, GPOUT_SYS_UART0_TX,
|
||||
GPOEN_ENABLE,
|
||||
GPI_NONE)>;
|
||||
bias-disable;
|
||||
drive-strength = <12>;
|
||||
input-disable;
|
||||
input-schmitt-disable;
|
||||
slew-rate = <0>;
|
||||
};
|
||||
|
||||
rx-pins {
|
||||
pinmux = <GPIOMUX(6, GPOUT_LOW,
|
||||
GPOEN_DISABLE,
|
||||
GPI_SYS_UART0_RX)>;
|
||||
bias-disable; /* external pull-up */
|
||||
drive-strength = <2>;
|
||||
input-enable;
|
||||
input-schmitt-enable;
|
||||
slew-rate = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
tdm_pins: tdm-0 {
|
||||
tx-pins {
|
||||
pinmux = <GPIOMUX(44, GPOUT_SYS_TDM_TXD,
|
||||
@@ -497,6 +473,30 @@
|
||||
input-enable;
|
||||
};
|
||||
};
|
||||
|
||||
uart0_pins: uart0-0 {
|
||||
tx-pins {
|
||||
pinmux = <GPIOMUX(5, GPOUT_SYS_UART0_TX,
|
||||
GPOEN_ENABLE,
|
||||
GPI_NONE)>;
|
||||
bias-disable;
|
||||
drive-strength = <12>;
|
||||
input-disable;
|
||||
input-schmitt-disable;
|
||||
slew-rate = <0>;
|
||||
};
|
||||
|
||||
rx-pins {
|
||||
pinmux = <GPIOMUX(6, GPOUT_LOW,
|
||||
GPOEN_DISABLE,
|
||||
GPI_SYS_UART0_RX)>;
|
||||
bias-disable; /* external pull-up */
|
||||
drive-strength = <2>;
|
||||
input-enable;
|
||||
input-schmitt-enable;
|
||||
slew-rate = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&tdm {
|
||||
@@ -513,6 +513,7 @@
|
||||
|
||||
&usb0 {
|
||||
dr_mode = "peripheral";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&U74_1 {
|
||||
|
||||
@@ -18,7 +18,8 @@ void huge_pte_clear(struct mm_struct *mm, unsigned long addr,
|
||||
|
||||
#define __HAVE_ARCH_HUGE_SET_HUGE_PTE_AT
|
||||
void set_huge_pte_at(struct mm_struct *mm,
|
||||
unsigned long addr, pte_t *ptep, pte_t pte);
|
||||
unsigned long addr, pte_t *ptep, pte_t pte,
|
||||
unsigned long sz);
|
||||
|
||||
#define __HAVE_ARCH_HUGE_PTEP_GET_AND_CLEAR
|
||||
pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
|
||||
|
||||
@@ -180,7 +180,8 @@ pte_t arch_make_huge_pte(pte_t entry, unsigned int shift, vm_flags_t flags)
|
||||
void set_huge_pte_at(struct mm_struct *mm,
|
||||
unsigned long addr,
|
||||
pte_t *ptep,
|
||||
pte_t pte)
|
||||
pte_t pte,
|
||||
unsigned long sz)
|
||||
{
|
||||
int i, pte_num;
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
#define hugepages_supported() (MACHINE_HAS_EDAT1)
|
||||
|
||||
void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
|
||||
pte_t *ptep, pte_t pte, unsigned long sz);
|
||||
void __set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
|
||||
pte_t *ptep, pte_t pte);
|
||||
pte_t huge_ptep_get(pte_t *ptep);
|
||||
pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
|
||||
@@ -65,7 +67,7 @@ static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
|
||||
int changed = !pte_same(huge_ptep_get(ptep), pte);
|
||||
if (changed) {
|
||||
huge_ptep_get_and_clear(vma->vm_mm, addr, ptep);
|
||||
set_huge_pte_at(vma->vm_mm, addr, ptep, pte);
|
||||
__set_huge_pte_at(vma->vm_mm, addr, ptep, pte);
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
@@ -74,7 +76,7 @@ static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
|
||||
unsigned long addr, pte_t *ptep)
|
||||
{
|
||||
pte_t pte = huge_ptep_get_and_clear(mm, addr, ptep);
|
||||
set_huge_pte_at(mm, addr, ptep, pte_wrprotect(pte));
|
||||
__set_huge_pte_at(mm, addr, ptep, pte_wrprotect(pte));
|
||||
}
|
||||
|
||||
static inline pte_t mk_huge_pte(struct page *page, pgprot_t pgprot)
|
||||
|
||||
@@ -142,7 +142,7 @@ static void clear_huge_pte_skeys(struct mm_struct *mm, unsigned long rste)
|
||||
__storage_key_init_range(paddr, paddr + size - 1);
|
||||
}
|
||||
|
||||
void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
|
||||
void __set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
|
||||
pte_t *ptep, pte_t pte)
|
||||
{
|
||||
unsigned long rste;
|
||||
@@ -163,6 +163,12 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
|
||||
set_pte(ptep, __pte(rste));
|
||||
}
|
||||
|
||||
void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
|
||||
pte_t *ptep, pte_t pte, unsigned long sz)
|
||||
{
|
||||
__set_huge_pte_at(mm, addr, ptep, pte);
|
||||
}
|
||||
|
||||
pte_t huge_ptep_get(pte_t *ptep)
|
||||
{
|
||||
return __rste_to_pte(pte_val(*ptep));
|
||||
|
||||
@@ -14,6 +14,8 @@ extern struct pud_huge_patch_entry __pud_huge_patch, __pud_huge_patch_end;
|
||||
|
||||
#define __HAVE_ARCH_HUGE_SET_HUGE_PTE_AT
|
||||
void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
|
||||
pte_t *ptep, pte_t pte, unsigned long sz);
|
||||
void __set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
|
||||
pte_t *ptep, pte_t pte);
|
||||
|
||||
#define __HAVE_ARCH_HUGE_PTEP_GET_AND_CLEAR
|
||||
@@ -32,7 +34,7 @@ static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
|
||||
unsigned long addr, pte_t *ptep)
|
||||
{
|
||||
pte_t old_pte = *ptep;
|
||||
set_huge_pte_at(mm, addr, ptep, pte_wrprotect(old_pte));
|
||||
__set_huge_pte_at(mm, addr, ptep, pte_wrprotect(old_pte));
|
||||
}
|
||||
|
||||
#define __HAVE_ARCH_HUGE_PTEP_SET_ACCESS_FLAGS
|
||||
@@ -42,7 +44,7 @@ static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
|
||||
{
|
||||
int changed = !pte_same(*ptep, pte);
|
||||
if (changed) {
|
||||
set_huge_pte_at(vma->vm_mm, addr, ptep, pte);
|
||||
__set_huge_pte_at(vma->vm_mm, addr, ptep, pte);
|
||||
flush_tlb_page(vma, addr);
|
||||
}
|
||||
return changed;
|
||||
|
||||
@@ -328,7 +328,7 @@ pte_t *huge_pte_offset(struct mm_struct *mm,
|
||||
return pte_offset_huge(pmd, addr);
|
||||
}
|
||||
|
||||
void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
|
||||
void __set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
|
||||
pte_t *ptep, pte_t entry)
|
||||
{
|
||||
unsigned int nptes, orig_shift, shift;
|
||||
@@ -364,6 +364,12 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
|
||||
orig_shift);
|
||||
}
|
||||
|
||||
void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
|
||||
pte_t *ptep, pte_t entry, unsigned long sz)
|
||||
{
|
||||
__set_huge_pte_at(mm, addr, ptep, entry);
|
||||
}
|
||||
|
||||
pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
|
||||
pte_t *ptep)
|
||||
{
|
||||
|
||||
@@ -534,8 +534,12 @@ static void amd_pmu_cpu_reset(int cpu)
|
||||
/* Clear enable bits i.e. PerfCntrGlobalCtl.PerfCntrEn */
|
||||
wrmsrl(MSR_AMD64_PERF_CNTR_GLOBAL_CTL, 0);
|
||||
|
||||
/* Clear overflow bits i.e. PerfCntrGLobalStatus.PerfCntrOvfl */
|
||||
wrmsrl(MSR_AMD64_PERF_CNTR_GLOBAL_STATUS_CLR, amd_pmu_global_cntr_mask);
|
||||
/*
|
||||
* Clear freeze and overflow bits i.e. PerfCntrGLobalStatus.LbrFreeze
|
||||
* and PerfCntrGLobalStatus.PerfCntrOvfl
|
||||
*/
|
||||
wrmsrl(MSR_AMD64_PERF_CNTR_GLOBAL_STATUS_CLR,
|
||||
GLOBAL_STATUS_LBRS_FROZEN | amd_pmu_global_cntr_mask);
|
||||
}
|
||||
|
||||
static int amd_pmu_cpu_prepare(int cpu)
|
||||
@@ -570,6 +574,7 @@ static void amd_pmu_cpu_starting(int cpu)
|
||||
int i, nb_id;
|
||||
|
||||
cpuc->perf_ctr_virt_mask = AMD64_EVENTSEL_HOSTONLY;
|
||||
amd_pmu_cpu_reset(cpu);
|
||||
|
||||
if (!x86_pmu.amd_nb_constraints)
|
||||
return;
|
||||
@@ -591,8 +596,6 @@ static void amd_pmu_cpu_starting(int cpu)
|
||||
|
||||
cpuc->amd_nb->nb_id = nb_id;
|
||||
cpuc->amd_nb->refcnt++;
|
||||
|
||||
amd_pmu_cpu_reset(cpu);
|
||||
}
|
||||
|
||||
static void amd_pmu_cpu_dead(int cpu)
|
||||
@@ -601,6 +604,7 @@ static void amd_pmu_cpu_dead(int cpu)
|
||||
|
||||
kfree(cpuhw->lbr_sel);
|
||||
cpuhw->lbr_sel = NULL;
|
||||
amd_pmu_cpu_reset(cpu);
|
||||
|
||||
if (!x86_pmu.amd_nb_constraints)
|
||||
return;
|
||||
@@ -613,8 +617,6 @@ static void amd_pmu_cpu_dead(int cpu)
|
||||
|
||||
cpuhw->amd_nb = NULL;
|
||||
}
|
||||
|
||||
amd_pmu_cpu_reset(cpu);
|
||||
}
|
||||
|
||||
static inline void amd_pmu_set_global_ctl(u64 ctl)
|
||||
@@ -884,7 +886,7 @@ static int amd_pmu_v2_handle_irq(struct pt_regs *regs)
|
||||
struct hw_perf_event *hwc;
|
||||
struct perf_event *event;
|
||||
int handled = 0, idx;
|
||||
u64 status, mask;
|
||||
u64 reserved, status, mask;
|
||||
bool pmu_enabled;
|
||||
|
||||
/*
|
||||
@@ -909,6 +911,14 @@ static int amd_pmu_v2_handle_irq(struct pt_regs *regs)
|
||||
status &= ~GLOBAL_STATUS_LBRS_FROZEN;
|
||||
}
|
||||
|
||||
reserved = status & ~amd_pmu_global_cntr_mask;
|
||||
if (reserved)
|
||||
pr_warn_once("Reserved PerfCntrGlobalStatus bits are set (0x%llx), please consider updating microcode\n",
|
||||
reserved);
|
||||
|
||||
/* Clear any reserved bits set by buggy microcode */
|
||||
status &= amd_pmu_global_cntr_mask;
|
||||
|
||||
for (idx = 0; idx < x86_pmu.num_counters; idx++) {
|
||||
if (!test_bit(idx, cpuc->active_mask))
|
||||
continue;
|
||||
|
||||
@@ -955,6 +955,14 @@ static inline int pte_same(pte_t a, pte_t b)
|
||||
return a.pte == b.pte;
|
||||
}
|
||||
|
||||
static inline pte_t pte_next_pfn(pte_t pte)
|
||||
{
|
||||
if (__pte_needs_invert(pte_val(pte)))
|
||||
return __pte(pte_val(pte) - (1UL << PFN_PTE_SHIFT));
|
||||
return __pte(pte_val(pte) + (1UL << PFN_PTE_SHIFT));
|
||||
}
|
||||
#define pte_next_pfn pte_next_pfn
|
||||
|
||||
static inline int pte_present(pte_t a)
|
||||
{
|
||||
return pte_flags(a) & (_PAGE_PRESENT | _PAGE_PROTNONE);
|
||||
|
||||
@@ -1303,7 +1303,7 @@ static const struct x86_cpu_id cpu_vuln_blacklist[] __initconst = {
|
||||
VULNBL_AMD(0x15, RETBLEED),
|
||||
VULNBL_AMD(0x16, RETBLEED),
|
||||
VULNBL_AMD(0x17, RETBLEED | SMT_RSB | SRSO),
|
||||
VULNBL_HYGON(0x18, RETBLEED | SMT_RSB),
|
||||
VULNBL_HYGON(0x18, RETBLEED | SMT_RSB | SRSO),
|
||||
VULNBL_AMD(0x19, SRSO),
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -235,6 +235,21 @@ static struct sgx_epc_page *sgx_encl_eldu(struct sgx_encl_page *encl_page,
|
||||
return epc_page;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure the SECS page is not swapped out. Must be called with encl->lock
|
||||
* to protect the enclave states including SECS and ensure the SECS page is
|
||||
* not swapped out again while being used.
|
||||
*/
|
||||
static struct sgx_epc_page *sgx_encl_load_secs(struct sgx_encl *encl)
|
||||
{
|
||||
struct sgx_epc_page *epc_page = encl->secs.epc_page;
|
||||
|
||||
if (!epc_page)
|
||||
epc_page = sgx_encl_eldu(&encl->secs, NULL);
|
||||
|
||||
return epc_page;
|
||||
}
|
||||
|
||||
static struct sgx_encl_page *__sgx_encl_load_page(struct sgx_encl *encl,
|
||||
struct sgx_encl_page *entry)
|
||||
{
|
||||
@@ -248,11 +263,9 @@ static struct sgx_encl_page *__sgx_encl_load_page(struct sgx_encl *encl,
|
||||
return entry;
|
||||
}
|
||||
|
||||
if (!(encl->secs.epc_page)) {
|
||||
epc_page = sgx_encl_eldu(&encl->secs, NULL);
|
||||
if (IS_ERR(epc_page))
|
||||
return ERR_CAST(epc_page);
|
||||
}
|
||||
epc_page = sgx_encl_load_secs(encl);
|
||||
if (IS_ERR(epc_page))
|
||||
return ERR_CAST(epc_page);
|
||||
|
||||
epc_page = sgx_encl_eldu(entry, encl->secs.epc_page);
|
||||
if (IS_ERR(epc_page))
|
||||
@@ -339,6 +352,13 @@ static vm_fault_t sgx_encl_eaug_page(struct vm_area_struct *vma,
|
||||
|
||||
mutex_lock(&encl->lock);
|
||||
|
||||
epc_page = sgx_encl_load_secs(encl);
|
||||
if (IS_ERR(epc_page)) {
|
||||
if (PTR_ERR(epc_page) == -EBUSY)
|
||||
vmret = VM_FAULT_NOPAGE;
|
||||
goto err_out_unlock;
|
||||
}
|
||||
|
||||
epc_page = sgx_alloc_epc_page(encl_page, false);
|
||||
if (IS_ERR(epc_page)) {
|
||||
if (PTR_ERR(epc_page) == -EBUSY)
|
||||
|
||||
@@ -695,7 +695,6 @@ void kgdb_arch_exit(void)
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* kgdb_skipexception - Bail out of KGDB when we've been triggered.
|
||||
* @exception: Exception vector number
|
||||
* @regs: Current &struct pt_regs.
|
||||
|
||||
@@ -9,8 +9,7 @@
|
||||
|
||||
|
||||
# KBUILD_CFLAGS used when building rest of boot (takes effect recursively)
|
||||
KBUILD_CFLAGS += -fno-builtin -Iarch/$(ARCH)/boot/include
|
||||
HOSTFLAGS += -Iarch/$(ARCH)/boot/include
|
||||
KBUILD_CFLAGS += -fno-builtin
|
||||
|
||||
subdir-y := lib
|
||||
targets += vmlinux.bin vmlinux.bin.gz
|
||||
|
||||
@@ -4,13 +4,14 @@
|
||||
/* bits taken from ppc */
|
||||
|
||||
extern void *avail_ram, *end_avail;
|
||||
void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp);
|
||||
|
||||
void exit (void)
|
||||
static void exit(void)
|
||||
{
|
||||
for (;;);
|
||||
}
|
||||
|
||||
void *zalloc(unsigned size)
|
||||
static void *zalloc(unsigned int size)
|
||||
{
|
||||
void *p = avail_ram;
|
||||
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
|
||||
#include <variant/core.h>
|
||||
|
||||
#ifndef XCHAL_HAVE_DIV32
|
||||
#define XCHAL_HAVE_DIV32 0
|
||||
#endif
|
||||
|
||||
#ifndef XCHAL_HAVE_EXCLUSIVE
|
||||
#define XCHAL_HAVE_EXCLUSIVE 0
|
||||
#endif
|
||||
|
||||
@@ -48,6 +48,7 @@ void arch_uninstall_hw_breakpoint(struct perf_event *bp);
|
||||
void hw_breakpoint_pmu_read(struct perf_event *bp);
|
||||
int check_hw_breakpoint(struct pt_regs *regs);
|
||||
void clear_ptrace_hw_breakpoint(struct task_struct *tsk);
|
||||
void restore_dbreak(void);
|
||||
|
||||
#else
|
||||
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/stringify.h>
|
||||
|
||||
#include <asm/bootparam.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/types.h>
|
||||
#include <asm/regs.h>
|
||||
@@ -217,6 +219,9 @@ struct mm_struct;
|
||||
|
||||
extern unsigned long __get_wchan(struct task_struct *p);
|
||||
|
||||
void init_arch(bp_tag_t *bp_start);
|
||||
void do_notify_resume(struct pt_regs *regs);
|
||||
|
||||
#define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc)
|
||||
#define KSTK_ESP(tsk) (task_pt_regs(tsk)->areg[1])
|
||||
|
||||
|
||||
@@ -106,6 +106,9 @@ static inline unsigned long regs_return_value(struct pt_regs *regs)
|
||||
return regs->areg[2];
|
||||
}
|
||||
|
||||
int do_syscall_trace_enter(struct pt_regs *regs);
|
||||
void do_syscall_trace_leave(struct pt_regs *regs);
|
||||
|
||||
#else /* __ASSEMBLY__ */
|
||||
|
||||
# include <asm/asm-offsets.h>
|
||||
|
||||
@@ -23,6 +23,7 @@ struct cpumask;
|
||||
void arch_send_call_function_ipi_mask(const struct cpumask *mask);
|
||||
void arch_send_call_function_single_ipi(int cpu);
|
||||
|
||||
void secondary_start_kernel(void);
|
||||
void smp_init_cpus(void);
|
||||
void secondary_init_irq(void);
|
||||
void ipi_init(void);
|
||||
|
||||
@@ -18,4 +18,6 @@
|
||||
|
||||
#define __pte_free_tlb(tlb, pte, address) pte_free((tlb)->mm, pte)
|
||||
|
||||
void check_tlb_sanity(void);
|
||||
|
||||
#endif /* _XTENSA_TLB_H */
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <linux/percpu.h>
|
||||
#include <linux/perf_event.h>
|
||||
#include <asm/core.h>
|
||||
#include <asm/hw_breakpoint.h>
|
||||
|
||||
/* Breakpoint currently in use for each IBREAKA. */
|
||||
static DEFINE_PER_CPU(struct perf_event *, bp_on_reg[XCHAL_NUM_IBREAK]);
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <asm/mxregs.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/platform.h>
|
||||
#include <asm/traps.h>
|
||||
|
||||
DECLARE_PER_CPU(unsigned long, nmi_count);
|
||||
|
||||
|
||||
@@ -541,7 +541,6 @@ long arch_ptrace(struct task_struct *child, long request,
|
||||
return ret;
|
||||
}
|
||||
|
||||
void do_syscall_trace_leave(struct pt_regs *regs);
|
||||
int do_syscall_trace_enter(struct pt_regs *regs)
|
||||
{
|
||||
if (regs->syscall == NO_SYSCALL)
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/coprocessor.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/syscall.h>
|
||||
#include <asm/unistd.h>
|
||||
|
||||
extern struct task_struct *coproc_owners[];
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <linux/irq.h>
|
||||
#include <linux/kdebug.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/profile.h>
|
||||
#include <linux/sched/mm.h>
|
||||
#include <linux/sched/hotplug.h>
|
||||
#include <linux/sched/task_stack.h>
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/stacktrace.h>
|
||||
|
||||
#include <asm/ftrace.h>
|
||||
#include <asm/stacktrace.h>
|
||||
#include <asm/traps.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched/signal.h>
|
||||
#include <linux/sched/debug.h>
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
#include <asm/asmmacro.h>
|
||||
#include <asm/core.h>
|
||||
|
||||
#if !XCHAL_HAVE_MUL16 && !XCHAL_HAVE_MUL32 && !XCHAL_HAVE_MAC16
|
||||
#if XCHAL_HAVE_MUL16 || XCHAL_HAVE_MUL32 || XCHAL_HAVE_MAC16
|
||||
#define XCHAL_NO_MUL 0
|
||||
#else
|
||||
#define XCHAL_NO_MUL 1
|
||||
#endif
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <asm/mmu_context.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/hardirq.h>
|
||||
#include <asm/traps.h>
|
||||
|
||||
void bad_page_fault(struct pt_regs*, unsigned long, int);
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <linux/mm.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/mmu_context.h>
|
||||
#include <asm/tlb.h>
|
||||
#include <asm/tlbflush.h>
|
||||
#include <asm/cacheflush.h>
|
||||
|
||||
|
||||
@@ -201,7 +201,7 @@ static int tuntap_write(struct iss_net_private *lp, struct sk_buff **skb)
|
||||
return simc_write(lp->tp.info.tuntap.fd, (*skb)->data, (*skb)->len);
|
||||
}
|
||||
|
||||
unsigned short tuntap_protocol(struct sk_buff *skb)
|
||||
static unsigned short tuntap_protocol(struct sk_buff *skb)
|
||||
{
|
||||
return eth_type_trans(skb, skb->dev);
|
||||
}
|
||||
@@ -441,7 +441,7 @@ static int iss_net_change_mtu(struct net_device *dev, int new_mtu)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
void iss_net_user_timer_expire(struct timer_list *unused)
|
||||
static void iss_net_user_timer_expire(struct timer_list *unused)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -270,7 +270,7 @@ void rq_qos_wait(struct rq_wait *rqw, void *private_data,
|
||||
finish_wait(&rqw->wait, &data.wq);
|
||||
|
||||
/*
|
||||
* We raced with wbt_wake_function() getting a token,
|
||||
* We raced with rq_qos_wake_function() getting a token,
|
||||
* which means we now have two. Put our local token
|
||||
* and wake anyone else potentially waiting for one.
|
||||
*/
|
||||
|
||||
@@ -290,7 +290,6 @@ EXPORT_SYMBOL(disk_check_media_change);
|
||||
/**
|
||||
* disk_force_media_change - force a media change event
|
||||
* @disk: the disk which will raise the event
|
||||
* @events: the events to raise
|
||||
*
|
||||
* Should be called when the media changes for @disk. Generates a uevent
|
||||
* and attempts to free all dentries and inodes and invalidates all block
|
||||
|
||||
@@ -327,7 +327,7 @@ static int ivpu_wait_for_ready(struct ivpu_device *vdev)
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
ivpu_info(vdev, "VPU ready message received successfully\n");
|
||||
ivpu_dbg(vdev, PM, "VPU ready message received successfully\n");
|
||||
else
|
||||
ivpu_hw_diagnose_failure(vdev);
|
||||
|
||||
@@ -634,6 +634,7 @@ static void ivpu_dev_fini(struct ivpu_device *vdev)
|
||||
|
||||
static struct pci_device_id ivpu_pci_ids[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_MTL) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_ARL) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_LNL) },
|
||||
{ }
|
||||
};
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#define DRIVER_DATE "20230117"
|
||||
|
||||
#define PCI_DEVICE_ID_MTL 0x7d1d
|
||||
#define PCI_DEVICE_ID_ARL 0xad1d
|
||||
#define PCI_DEVICE_ID_LNL 0x643e
|
||||
|
||||
#define IVPU_HW_37XX 37
|
||||
@@ -165,6 +166,7 @@ static inline int ivpu_hw_gen(struct ivpu_device *vdev)
|
||||
{
|
||||
switch (ivpu_device_id(vdev)) {
|
||||
case PCI_DEVICE_ID_MTL:
|
||||
case PCI_DEVICE_ID_ARL:
|
||||
return IVPU_HW_37XX;
|
||||
case PCI_DEVICE_ID_LNL:
|
||||
return IVPU_HW_40XX;
|
||||
|
||||
@@ -220,7 +220,8 @@ static int ivpu_fw_mem_init(struct ivpu_device *vdev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
fw->mem = ivpu_bo_alloc_internal(vdev, fw->runtime_addr, fw->runtime_size, DRM_IVPU_BO_WC);
|
||||
fw->mem = ivpu_bo_alloc_internal(vdev, fw->runtime_addr, fw->runtime_size,
|
||||
DRM_IVPU_BO_CACHED | DRM_IVPU_BO_NOSNOOP);
|
||||
if (!fw->mem) {
|
||||
ivpu_err(vdev, "Failed to allocate firmware runtime memory\n");
|
||||
return -ENOMEM;
|
||||
@@ -330,7 +331,7 @@ int ivpu_fw_load(struct ivpu_device *vdev)
|
||||
memset(start, 0, size);
|
||||
}
|
||||
|
||||
wmb(); /* Flush WC buffers after writing fw->mem */
|
||||
clflush_cache_range(fw->mem->kvaddr, fw->mem->base.size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -432,6 +433,7 @@ void ivpu_fw_boot_params_setup(struct ivpu_device *vdev, struct vpu_boot_params
|
||||
if (!ivpu_fw_is_cold_boot(vdev)) {
|
||||
boot_params->save_restore_ret_address = 0;
|
||||
vdev->pm->is_warmboot = true;
|
||||
clflush_cache_range(vdev->fw->mem->kvaddr, SZ_4K);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -493,7 +495,7 @@ void ivpu_fw_boot_params_setup(struct ivpu_device *vdev, struct vpu_boot_params
|
||||
boot_params->punit_telemetry_sram_size = ivpu_hw_reg_telemetry_size_get(vdev);
|
||||
boot_params->vpu_telemetry_enable = ivpu_hw_reg_telemetry_enable_get(vdev);
|
||||
|
||||
wmb(); /* Flush WC buffers after writing bootparams */
|
||||
clflush_cache_range(vdev->fw->mem->kvaddr, SZ_4K);
|
||||
|
||||
ivpu_fw_boot_params_print(vdev, boot_params);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include <drm/drm_gem.h>
|
||||
#include <drm/drm_mm.h>
|
||||
|
||||
#define DRM_IVPU_BO_NOSNOOP 0x10000000
|
||||
|
||||
struct dma_buf;
|
||||
struct ivpu_bo_ops;
|
||||
struct ivpu_file_priv;
|
||||
@@ -83,6 +85,9 @@ static inline u32 ivpu_bo_cache_mode(struct ivpu_bo *bo)
|
||||
|
||||
static inline bool ivpu_bo_is_snooped(struct ivpu_bo *bo)
|
||||
{
|
||||
if (bo->flags & DRM_IVPU_BO_NOSNOOP)
|
||||
return false;
|
||||
|
||||
return ivpu_bo_cache_mode(bo) == DRM_IVPU_BO_CACHED;
|
||||
}
|
||||
|
||||
|
||||
@@ -57,8 +57,7 @@
|
||||
|
||||
#define ICB_0_1_IRQ_MASK ((((u64)ICB_1_IRQ_MASK) << 32) | ICB_0_IRQ_MASK)
|
||||
|
||||
#define BUTTRESS_IRQ_MASK ((REG_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, FREQ_CHANGE)) | \
|
||||
(REG_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, ATS_ERR)) | \
|
||||
#define BUTTRESS_IRQ_MASK ((REG_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, ATS_ERR)) | \
|
||||
(REG_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, CFI0_ERR)) | \
|
||||
(REG_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, CFI1_ERR)) | \
|
||||
(REG_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, IMR0_ERR)) | \
|
||||
@@ -196,6 +195,14 @@ static int ivpu_pll_wait_for_status_ready(struct ivpu_device *vdev)
|
||||
return REGB_POLL_FLD(VPU_40XX_BUTTRESS_VPU_STATUS, READY, 1, PLL_TIMEOUT_US);
|
||||
}
|
||||
|
||||
static int ivpu_wait_for_clock_own_resource_ack(struct ivpu_device *vdev)
|
||||
{
|
||||
if (ivpu_is_simics(vdev))
|
||||
return 0;
|
||||
|
||||
return REGB_POLL_FLD(VPU_40XX_BUTTRESS_VPU_STATUS, CLOCK_RESOURCE_OWN_ACK, 1, TIMEOUT_US);
|
||||
}
|
||||
|
||||
static void ivpu_pll_init_frequency_ratios(struct ivpu_device *vdev)
|
||||
{
|
||||
struct ivpu_hw_info *hw = vdev->hw;
|
||||
@@ -556,6 +563,12 @@ static int ivpu_boot_pwr_domain_enable(struct ivpu_device *vdev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ivpu_wait_for_clock_own_resource_ack(vdev);
|
||||
if (ret) {
|
||||
ivpu_err(vdev, "Timed out waiting for clock own resource ACK\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ivpu_boot_pwr_island_trickle_drive(vdev, true);
|
||||
ivpu_boot_pwr_island_drive(vdev, true);
|
||||
|
||||
@@ -1046,9 +1059,6 @@ static irqreturn_t ivpu_hw_40xx_irqb_handler(struct ivpu_device *vdev, int irq)
|
||||
if (status == 0)
|
||||
return IRQ_NONE;
|
||||
|
||||
/* Disable global interrupt before handling local buttress interrupts */
|
||||
REGB_WR32(VPU_40XX_BUTTRESS_GLOBAL_INT_MASK, 0x1);
|
||||
|
||||
if (REG_TEST_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, FREQ_CHANGE, status))
|
||||
ivpu_dbg(vdev, IRQ, "FREQ_CHANGE");
|
||||
|
||||
@@ -1096,9 +1106,6 @@ static irqreturn_t ivpu_hw_40xx_irqb_handler(struct ivpu_device *vdev, int irq)
|
||||
/* This must be done after interrupts are cleared at the source. */
|
||||
REGB_WR32(VPU_40XX_BUTTRESS_INTERRUPT_STAT, status);
|
||||
|
||||
/* Re-enable global interrupt */
|
||||
REGB_WR32(VPU_40XX_BUTTRESS_GLOBAL_INT_MASK, 0x0);
|
||||
|
||||
if (schedule_recovery)
|
||||
ivpu_pm_schedule_recovery(vdev);
|
||||
|
||||
@@ -1110,9 +1117,14 @@ static irqreturn_t ivpu_hw_40xx_irq_handler(int irq, void *ptr)
|
||||
struct ivpu_device *vdev = ptr;
|
||||
irqreturn_t ret = IRQ_NONE;
|
||||
|
||||
REGB_WR32(VPU_40XX_BUTTRESS_GLOBAL_INT_MASK, 0x1);
|
||||
|
||||
ret |= ivpu_hw_40xx_irqv_handler(vdev, irq);
|
||||
ret |= ivpu_hw_40xx_irqb_handler(vdev, irq);
|
||||
|
||||
/* Re-enable global interrupts to re-trigger MSI for pending interrupts */
|
||||
REGB_WR32(VPU_40XX_BUTTRESS_GLOBAL_INT_MASK, 0x0);
|
||||
|
||||
if (ret & IRQ_WAKE_THREAD)
|
||||
return IRQ_WAKE_THREAD;
|
||||
|
||||
|
||||
@@ -70,6 +70,8 @@
|
||||
#define VPU_40XX_BUTTRESS_VPU_STATUS_READY_MASK BIT_MASK(0)
|
||||
#define VPU_40XX_BUTTRESS_VPU_STATUS_IDLE_MASK BIT_MASK(1)
|
||||
#define VPU_40XX_BUTTRESS_VPU_STATUS_DUP_IDLE_MASK BIT_MASK(2)
|
||||
#define VPU_40XX_BUTTRESS_VPU_STATUS_CLOCK_RESOURCE_OWN_ACK_MASK BIT_MASK(6)
|
||||
#define VPU_40XX_BUTTRESS_VPU_STATUS_POWER_RESOURCE_OWN_ACK_MASK BIT_MASK(7)
|
||||
#define VPU_40XX_BUTTRESS_VPU_STATUS_PERF_CLK_MASK BIT_MASK(11)
|
||||
#define VPU_40XX_BUTTRESS_VPU_STATUS_DISABLE_CLK_RELINQUISH_MASK BIT_MASK(12)
|
||||
|
||||
|
||||
@@ -209,10 +209,10 @@ int ivpu_ipc_receive(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons,
|
||||
struct ivpu_ipc_rx_msg *rx_msg;
|
||||
int wait_ret, ret = 0;
|
||||
|
||||
wait_ret = wait_event_interruptible_timeout(cons->rx_msg_wq,
|
||||
(IS_KTHREAD() && kthread_should_stop()) ||
|
||||
!list_empty(&cons->rx_msg_list),
|
||||
msecs_to_jiffies(timeout_ms));
|
||||
wait_ret = wait_event_timeout(cons->rx_msg_wq,
|
||||
(IS_KTHREAD() && kthread_should_stop()) ||
|
||||
!list_empty(&cons->rx_msg_list),
|
||||
msecs_to_jiffies(timeout_ms));
|
||||
|
||||
if (IS_KTHREAD() && kthread_should_stop())
|
||||
return -EINTR;
|
||||
@@ -220,9 +220,6 @@ int ivpu_ipc_receive(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons,
|
||||
if (wait_ret == 0)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
if (wait_ret < 0)
|
||||
return -ERESTARTSYS;
|
||||
|
||||
spin_lock_irq(&cons->rx_msg_lock);
|
||||
rx_msg = list_first_entry_or_null(&cons->rx_msg_list, struct ivpu_ipc_rx_msg, link);
|
||||
if (!rx_msg) {
|
||||
|
||||
@@ -2057,7 +2057,9 @@ static int acpi_video_bus_add(struct acpi_device *device)
|
||||
!auto_detect)
|
||||
acpi_video_bus_register_backlight(video);
|
||||
|
||||
acpi_video_bus_add_notify_handler(video);
|
||||
error = acpi_video_bus_add_notify_handler(video);
|
||||
if (error)
|
||||
goto err_del;
|
||||
|
||||
error = acpi_dev_install_notify_handler(device, ACPI_DEVICE_NOTIFY,
|
||||
acpi_video_bus_notify);
|
||||
@@ -2067,10 +2069,11 @@ static int acpi_video_bus_add(struct acpi_device *device)
|
||||
return 0;
|
||||
|
||||
err_remove:
|
||||
acpi_video_bus_remove_notify_handler(video);
|
||||
err_del:
|
||||
mutex_lock(&video_list_lock);
|
||||
list_del(&video->entry);
|
||||
mutex_unlock(&video_list_lock);
|
||||
acpi_video_bus_remove_notify_handler(video);
|
||||
acpi_video_bus_unregister_backlight(video);
|
||||
err_put_video:
|
||||
acpi_video_bus_put_devices(video);
|
||||
|
||||
+140
-15
@@ -1972,6 +1972,96 @@ retry:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_dev_power_set_standby - Set a device power mode to standby
|
||||
* @dev: target device
|
||||
*
|
||||
* Issue a STANDBY IMMEDIATE command to set a device power mode to standby.
|
||||
* For an HDD device, this spins down the disks.
|
||||
*
|
||||
* LOCKING:
|
||||
* Kernel thread context (may sleep).
|
||||
*/
|
||||
void ata_dev_power_set_standby(struct ata_device *dev)
|
||||
{
|
||||
unsigned long ap_flags = dev->link->ap->flags;
|
||||
struct ata_taskfile tf;
|
||||
unsigned int err_mask;
|
||||
|
||||
/* Issue STANDBY IMMEDIATE command only if supported by the device */
|
||||
if (dev->class != ATA_DEV_ATA && dev->class != ATA_DEV_ZAC)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Some odd clown BIOSes issue spindown on power off (ACPI S4 or S5)
|
||||
* causing some drives to spin up and down again. For these, do nothing
|
||||
* if we are being called on shutdown.
|
||||
*/
|
||||
if ((ap_flags & ATA_FLAG_NO_POWEROFF_SPINDOWN) &&
|
||||
system_state == SYSTEM_POWER_OFF)
|
||||
return;
|
||||
|
||||
if ((ap_flags & ATA_FLAG_NO_HIBERNATE_SPINDOWN) &&
|
||||
system_entering_hibernation())
|
||||
return;
|
||||
|
||||
ata_tf_init(dev, &tf);
|
||||
tf.flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR;
|
||||
tf.protocol = ATA_PROT_NODATA;
|
||||
tf.command = ATA_CMD_STANDBYNOW1;
|
||||
|
||||
ata_dev_notice(dev, "Entering standby power mode\n");
|
||||
|
||||
err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);
|
||||
if (err_mask)
|
||||
ata_dev_err(dev, "STANDBY IMMEDIATE failed (err_mask=0x%x)\n",
|
||||
err_mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_dev_power_set_active - Set a device power mode to active
|
||||
* @dev: target device
|
||||
*
|
||||
* Issue a VERIFY command to enter to ensure that the device is in the
|
||||
* active power mode. For a spun-down HDD (standby or idle power mode),
|
||||
* the VERIFY command will complete after the disk spins up.
|
||||
*
|
||||
* LOCKING:
|
||||
* Kernel thread context (may sleep).
|
||||
*/
|
||||
void ata_dev_power_set_active(struct ata_device *dev)
|
||||
{
|
||||
struct ata_taskfile tf;
|
||||
unsigned int err_mask;
|
||||
|
||||
/*
|
||||
* Issue READ VERIFY SECTORS command for 1 sector at lba=0 only
|
||||
* if supported by the device.
|
||||
*/
|
||||
if (dev->class != ATA_DEV_ATA && dev->class != ATA_DEV_ZAC)
|
||||
return;
|
||||
|
||||
ata_tf_init(dev, &tf);
|
||||
tf.flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR;
|
||||
tf.protocol = ATA_PROT_NODATA;
|
||||
tf.command = ATA_CMD_VERIFY;
|
||||
tf.nsect = 1;
|
||||
if (dev->flags & ATA_DFLAG_LBA) {
|
||||
tf.flags |= ATA_TFLAG_LBA;
|
||||
tf.device |= ATA_LBA;
|
||||
} else {
|
||||
/* CHS */
|
||||
tf.lbal = 0x1; /* sect */
|
||||
}
|
||||
|
||||
ata_dev_notice(dev, "Entering active power mode\n");
|
||||
|
||||
err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);
|
||||
if (err_mask)
|
||||
ata_dev_err(dev, "VERIFY failed (err_mask=0x%x)\n",
|
||||
err_mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_read_log_page - read a specific log page
|
||||
* @dev: target device
|
||||
@@ -2529,7 +2619,7 @@ static int ata_dev_config_lba(struct ata_device *dev)
|
||||
{
|
||||
const u16 *id = dev->id;
|
||||
const char *lba_desc;
|
||||
char ncq_desc[24];
|
||||
char ncq_desc[32];
|
||||
int ret;
|
||||
|
||||
dev->flags |= ATA_DFLAG_LBA;
|
||||
@@ -5037,17 +5127,19 @@ static void ata_port_request_pm(struct ata_port *ap, pm_message_t mesg,
|
||||
struct ata_link *link;
|
||||
unsigned long flags;
|
||||
|
||||
/* Previous resume operation might still be in
|
||||
* progress. Wait for PM_PENDING to clear.
|
||||
*/
|
||||
if (ap->pflags & ATA_PFLAG_PM_PENDING) {
|
||||
ata_port_wait_eh(ap);
|
||||
WARN_ON(ap->pflags & ATA_PFLAG_PM_PENDING);
|
||||
}
|
||||
|
||||
/* request PM ops to EH */
|
||||
spin_lock_irqsave(ap->lock, flags);
|
||||
|
||||
/*
|
||||
* A previous PM operation might still be in progress. Wait for
|
||||
* ATA_PFLAG_PM_PENDING to clear.
|
||||
*/
|
||||
if (ap->pflags & ATA_PFLAG_PM_PENDING) {
|
||||
spin_unlock_irqrestore(ap->lock, flags);
|
||||
ata_port_wait_eh(ap);
|
||||
spin_lock_irqsave(ap->lock, flags);
|
||||
}
|
||||
|
||||
/* Request PM operation to EH */
|
||||
ap->pm_mesg = mesg;
|
||||
ap->pflags |= ATA_PFLAG_PM_PENDING;
|
||||
ata_for_each_link(link, ap, HOST_FIRST) {
|
||||
@@ -5059,10 +5151,8 @@ static void ata_port_request_pm(struct ata_port *ap, pm_message_t mesg,
|
||||
|
||||
spin_unlock_irqrestore(ap->lock, flags);
|
||||
|
||||
if (!async) {
|
||||
if (!async)
|
||||
ata_port_wait_eh(ap);
|
||||
WARN_ON(ap->pflags & ATA_PFLAG_PM_PENDING);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -5078,11 +5168,27 @@ static const unsigned int ata_port_suspend_ehi = ATA_EHI_QUIET
|
||||
|
||||
static void ata_port_suspend(struct ata_port *ap, pm_message_t mesg)
|
||||
{
|
||||
/*
|
||||
* We are about to suspend the port, so we do not care about
|
||||
* scsi_rescan_device() calls scheduled by previous resume operations.
|
||||
* The next resume will schedule the rescan again. So cancel any rescan
|
||||
* that is not done yet.
|
||||
*/
|
||||
cancel_delayed_work_sync(&ap->scsi_rescan_task);
|
||||
|
||||
ata_port_request_pm(ap, mesg, 0, ata_port_suspend_ehi, false);
|
||||
}
|
||||
|
||||
static void ata_port_suspend_async(struct ata_port *ap, pm_message_t mesg)
|
||||
{
|
||||
/*
|
||||
* We are about to suspend the port, so we do not care about
|
||||
* scsi_rescan_device() calls scheduled by previous resume operations.
|
||||
* The next resume will schedule the rescan again. So cancel any rescan
|
||||
* that is not done yet.
|
||||
*/
|
||||
cancel_delayed_work_sync(&ap->scsi_rescan_task);
|
||||
|
||||
ata_port_request_pm(ap, mesg, 0, ata_port_suspend_ehi, true);
|
||||
}
|
||||
|
||||
@@ -5229,7 +5335,7 @@ EXPORT_SYMBOL_GPL(ata_host_resume);
|
||||
#endif
|
||||
|
||||
const struct device_type ata_port_type = {
|
||||
.name = "ata_port",
|
||||
.name = ATA_PORT_TYPE_NAME,
|
||||
#ifdef CONFIG_PM
|
||||
.pm = &ata_port_pm_ops,
|
||||
#endif
|
||||
@@ -5948,11 +6054,30 @@ static void ata_port_detach(struct ata_port *ap)
|
||||
struct ata_link *link;
|
||||
struct ata_device *dev;
|
||||
|
||||
/* tell EH we're leaving & flush EH */
|
||||
/* Wait for any ongoing EH */
|
||||
ata_port_wait_eh(ap);
|
||||
|
||||
mutex_lock(&ap->scsi_scan_mutex);
|
||||
spin_lock_irqsave(ap->lock, flags);
|
||||
|
||||
/* Remove scsi devices */
|
||||
ata_for_each_link(link, ap, HOST_FIRST) {
|
||||
ata_for_each_dev(dev, link, ALL) {
|
||||
if (dev->sdev) {
|
||||
spin_unlock_irqrestore(ap->lock, flags);
|
||||
scsi_remove_device(dev->sdev);
|
||||
spin_lock_irqsave(ap->lock, flags);
|
||||
dev->sdev = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Tell EH to disable all devices */
|
||||
ap->pflags |= ATA_PFLAG_UNLOADING;
|
||||
ata_port_schedule_eh(ap);
|
||||
|
||||
spin_unlock_irqrestore(ap->lock, flags);
|
||||
mutex_unlock(&ap->scsi_scan_mutex);
|
||||
|
||||
/* wait till EH commits suicide */
|
||||
ata_port_wait_eh(ap);
|
||||
|
||||
+46
-2
@@ -147,6 +147,8 @@ ata_eh_cmd_timeout_table[ATA_EH_CMD_TIMEOUT_TABLE_SIZE] = {
|
||||
.timeouts = ata_eh_other_timeouts, },
|
||||
{ .commands = CMDS(ATA_CMD_FLUSH, ATA_CMD_FLUSH_EXT),
|
||||
.timeouts = ata_eh_flush_timeouts },
|
||||
{ .commands = CMDS(ATA_CMD_VERIFY),
|
||||
.timeouts = ata_eh_reset_timeouts },
|
||||
};
|
||||
#undef CMDS
|
||||
|
||||
@@ -498,7 +500,19 @@ static void ata_eh_unload(struct ata_port *ap)
|
||||
struct ata_device *dev;
|
||||
unsigned long flags;
|
||||
|
||||
/* Restore SControl IPM and SPD for the next driver and
|
||||
/*
|
||||
* Unless we are restarting, transition all enabled devices to
|
||||
* standby power mode.
|
||||
*/
|
||||
if (system_state != SYSTEM_RESTART) {
|
||||
ata_for_each_link(link, ap, PMP_FIRST) {
|
||||
ata_for_each_dev(dev, link, ENABLED)
|
||||
ata_dev_power_set_standby(dev);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Restore SControl IPM and SPD for the next driver and
|
||||
* disable attached devices.
|
||||
*/
|
||||
ata_for_each_link(link, ap, PMP_FIRST) {
|
||||
@@ -684,6 +698,10 @@ void ata_scsi_port_error_handler(struct Scsi_Host *host, struct ata_port *ap)
|
||||
ehc->saved_xfer_mode[devno] = dev->xfer_mode;
|
||||
if (ata_ncq_enabled(dev))
|
||||
ehc->saved_ncq_enabled |= 1 << devno;
|
||||
|
||||
/* If we are resuming, wake up the device */
|
||||
if (ap->pflags & ATA_PFLAG_RESUMING)
|
||||
ehc->i.dev_action[devno] |= ATA_EH_SET_ACTIVE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -743,6 +761,8 @@ void ata_scsi_port_error_handler(struct Scsi_Host *host, struct ata_port *ap)
|
||||
/* clean up */
|
||||
spin_lock_irqsave(ap->lock, flags);
|
||||
|
||||
ap->pflags &= ~ATA_PFLAG_RESUMING;
|
||||
|
||||
if (ap->pflags & ATA_PFLAG_LOADING)
|
||||
ap->pflags &= ~ATA_PFLAG_LOADING;
|
||||
else if ((ap->pflags & ATA_PFLAG_SCSI_HOTPLUG) &&
|
||||
@@ -1218,6 +1238,13 @@ void ata_eh_detach_dev(struct ata_device *dev)
|
||||
struct ata_eh_context *ehc = &link->eh_context;
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* If the device is still enabled, transition it to standby power mode
|
||||
* (i.e. spin down HDDs).
|
||||
*/
|
||||
if (ata_dev_enabled(dev))
|
||||
ata_dev_power_set_standby(dev);
|
||||
|
||||
ata_dev_disable(dev);
|
||||
|
||||
spin_lock_irqsave(ap->lock, flags);
|
||||
@@ -2305,7 +2332,7 @@ static void ata_eh_link_report(struct ata_link *link)
|
||||
struct ata_eh_context *ehc = &link->eh_context;
|
||||
struct ata_queued_cmd *qc;
|
||||
const char *frozen, *desc;
|
||||
char tries_buf[6] = "";
|
||||
char tries_buf[16] = "";
|
||||
int tag, nr_failed = 0;
|
||||
|
||||
if (ehc->i.flags & ATA_EHI_QUIET)
|
||||
@@ -3016,6 +3043,15 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
|
||||
if (ehc->i.flags & ATA_EHI_DID_RESET)
|
||||
readid_flags |= ATA_READID_POSTRESET;
|
||||
|
||||
/*
|
||||
* When resuming, before executing any command, make sure to
|
||||
* transition the device to the active power mode.
|
||||
*/
|
||||
if ((action & ATA_EH_SET_ACTIVE) && ata_dev_enabled(dev)) {
|
||||
ata_dev_power_set_active(dev);
|
||||
ata_eh_done(link, dev, ATA_EH_SET_ACTIVE);
|
||||
}
|
||||
|
||||
if ((action & ATA_EH_REVALIDATE) && ata_dev_enabled(dev)) {
|
||||
WARN_ON(dev->class == ATA_DEV_PMP);
|
||||
|
||||
@@ -3989,6 +4025,7 @@ static void ata_eh_handle_port_suspend(struct ata_port *ap)
|
||||
unsigned long flags;
|
||||
int rc = 0;
|
||||
struct ata_device *dev;
|
||||
struct ata_link *link;
|
||||
|
||||
/* are we suspending? */
|
||||
spin_lock_irqsave(ap->lock, flags);
|
||||
@@ -4001,6 +4038,12 @@ static void ata_eh_handle_port_suspend(struct ata_port *ap)
|
||||
|
||||
WARN_ON(ap->pflags & ATA_PFLAG_SUSPENDED);
|
||||
|
||||
/* Set all devices attached to the port in standby mode */
|
||||
ata_for_each_link(link, ap, HOST_FIRST) {
|
||||
ata_for_each_dev(dev, link, ENABLED)
|
||||
ata_dev_power_set_standby(dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have a ZPODD attached, check its zero
|
||||
* power ready status before the port is frozen.
|
||||
@@ -4083,6 +4126,7 @@ static void ata_eh_handle_port_resume(struct ata_port *ap)
|
||||
/* update the flags */
|
||||
spin_lock_irqsave(ap->lock, flags);
|
||||
ap->pflags &= ~(ATA_PFLAG_PM_PENDING | ATA_PFLAG_SUSPENDED);
|
||||
ap->pflags |= ATA_PFLAG_RESUMING;
|
||||
spin_unlock_irqrestore(ap->lock, flags);
|
||||
}
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
+67
-33
@@ -1050,14 +1050,13 @@ int ata_scsi_dev_config(struct scsi_device *sdev, struct ata_device *dev)
|
||||
}
|
||||
} else {
|
||||
sdev->sector_size = ata_id_logical_sector_size(dev->id);
|
||||
|
||||
/*
|
||||
* Stop the drive on suspend but do not issue START STOP UNIT
|
||||
* on resume as this is not necessary and may fail: the device
|
||||
* will be woken up by ata_port_pm_resume() with a port reset
|
||||
* and device revalidation.
|
||||
* Ask the sd driver to issue START STOP UNIT on runtime suspend
|
||||
* and resume only. For system level suspend/resume, devices
|
||||
* power state is handled directly by libata EH.
|
||||
*/
|
||||
sdev->manage_start_stop = 1;
|
||||
sdev->no_start_on_resume = 1;
|
||||
sdev->manage_runtime_start_stop = true;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1089,6 +1088,42 @@ int ata_scsi_dev_config(struct scsi_device *sdev, struct ata_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_scsi_slave_alloc - Early setup of SCSI device
|
||||
* @sdev: SCSI device to examine
|
||||
*
|
||||
* This is called from scsi_alloc_sdev() when the scsi device
|
||||
* associated with an ATA device is scanned on a port.
|
||||
*
|
||||
* LOCKING:
|
||||
* Defined by SCSI layer. We don't really care.
|
||||
*/
|
||||
|
||||
int ata_scsi_slave_alloc(struct scsi_device *sdev)
|
||||
{
|
||||
struct ata_port *ap = ata_shost_to_port(sdev->host);
|
||||
struct device_link *link;
|
||||
|
||||
ata_scsi_sdev_config(sdev);
|
||||
|
||||
/*
|
||||
* Create a link from the ata_port device to the scsi device to ensure
|
||||
* that PM does suspend/resume in the correct order: the scsi device is
|
||||
* consumer (child) and the ata port the supplier (parent).
|
||||
*/
|
||||
link = device_link_add(&sdev->sdev_gendev, &ap->tdev,
|
||||
DL_FLAG_STATELESS |
|
||||
DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE);
|
||||
if (!link) {
|
||||
ata_port_err(ap, "Failed to create link to scsi device %s\n",
|
||||
dev_name(&sdev->sdev_gendev));
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ata_scsi_slave_alloc);
|
||||
|
||||
/**
|
||||
* ata_scsi_slave_config - Set SCSI device attributes
|
||||
* @sdev: SCSI device to examine
|
||||
@@ -1105,14 +1140,11 @@ int ata_scsi_slave_config(struct scsi_device *sdev)
|
||||
{
|
||||
struct ata_port *ap = ata_shost_to_port(sdev->host);
|
||||
struct ata_device *dev = __ata_scsi_find_dev(ap, sdev);
|
||||
int rc = 0;
|
||||
|
||||
ata_scsi_sdev_config(sdev);
|
||||
|
||||
if (dev)
|
||||
rc = ata_scsi_dev_config(sdev, dev);
|
||||
return ata_scsi_dev_config(sdev, dev);
|
||||
|
||||
return rc;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
|
||||
|
||||
@@ -1136,6 +1168,8 @@ void ata_scsi_slave_destroy(struct scsi_device *sdev)
|
||||
unsigned long flags;
|
||||
struct ata_device *dev;
|
||||
|
||||
device_link_remove(&sdev->sdev_gendev, &ap->tdev);
|
||||
|
||||
spin_lock_irqsave(ap->lock, flags);
|
||||
dev = __ata_scsi_find_dev(ap, sdev);
|
||||
if (dev && dev->sdev) {
|
||||
@@ -1195,7 +1229,7 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
|
||||
}
|
||||
|
||||
if (cdb[4] & 0x1) {
|
||||
tf->nsect = 1; /* 1 sector, lba=0 */
|
||||
tf->nsect = 1; /* 1 sector, lba=0 */
|
||||
|
||||
if (qc->dev->flags & ATA_DFLAG_LBA) {
|
||||
tf->flags |= ATA_TFLAG_LBA;
|
||||
@@ -1211,7 +1245,7 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
|
||||
tf->lbah = 0x0; /* cyl high */
|
||||
}
|
||||
|
||||
tf->command = ATA_CMD_VERIFY; /* READ VERIFY */
|
||||
tf->command = ATA_CMD_VERIFY; /* READ VERIFY */
|
||||
} else {
|
||||
/* Some odd clown BIOSen issue spindown on power off (ACPI S4
|
||||
* or S5) causing some drives to spin up and down again.
|
||||
@@ -1221,7 +1255,7 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
|
||||
goto skip;
|
||||
|
||||
if ((qc->ap->flags & ATA_FLAG_NO_HIBERNATE_SPINDOWN) &&
|
||||
system_entering_hibernation())
|
||||
system_entering_hibernation())
|
||||
goto skip;
|
||||
|
||||
/* Issue ATA STANDBY IMMEDIATE command */
|
||||
@@ -1835,6 +1869,9 @@ static unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf)
|
||||
hdr[2] = 0x7; /* claim SPC-5 version compatibility */
|
||||
}
|
||||
|
||||
if (args->dev->flags & ATA_DFLAG_CDL)
|
||||
hdr[2] = 0xd; /* claim SPC-6 version compatibility */
|
||||
|
||||
memcpy(rbuf, hdr, sizeof(hdr));
|
||||
memcpy(&rbuf[8], "ATA ", 8);
|
||||
ata_id_string(args->id, &rbuf[16], ATA_ID_PROD, 16);
|
||||
@@ -4312,7 +4349,7 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd)
|
||||
break;
|
||||
|
||||
case MAINTENANCE_IN:
|
||||
if (scsicmd[1] == MI_REPORT_SUPPORTED_OPERATION_CODES)
|
||||
if ((scsicmd[1] & 0x1f) == MI_REPORT_SUPPORTED_OPERATION_CODES)
|
||||
ata_scsi_rbuf_fill(&args, ata_scsiop_maint_in);
|
||||
else
|
||||
ata_scsi_set_invalid_field(dev, cmd, 1, 0xff);
|
||||
@@ -4722,7 +4759,7 @@ void ata_scsi_dev_rescan(struct work_struct *work)
|
||||
struct ata_link *link;
|
||||
struct ata_device *dev;
|
||||
unsigned long flags;
|
||||
bool delay_rescan = false;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&ap->scsi_scan_mutex);
|
||||
spin_lock_irqsave(ap->lock, flags);
|
||||
@@ -4731,37 +4768,34 @@ void ata_scsi_dev_rescan(struct work_struct *work)
|
||||
ata_for_each_dev(dev, link, ENABLED) {
|
||||
struct scsi_device *sdev = dev->sdev;
|
||||
|
||||
/*
|
||||
* If the port was suspended before this was scheduled,
|
||||
* bail out.
|
||||
*/
|
||||
if (ap->pflags & ATA_PFLAG_SUSPENDED)
|
||||
goto unlock;
|
||||
|
||||
if (!sdev)
|
||||
continue;
|
||||
if (scsi_device_get(sdev))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* If the rescan work was scheduled because of a resume
|
||||
* event, the port is already fully resumed, but the
|
||||
* SCSI device may not yet be fully resumed. In such
|
||||
* case, executing scsi_rescan_device() may cause a
|
||||
* deadlock with the PM code on device_lock(). Prevent
|
||||
* this by giving up and retrying rescan after a short
|
||||
* delay.
|
||||
*/
|
||||
delay_rescan = sdev->sdev_gendev.power.is_suspended;
|
||||
if (delay_rescan) {
|
||||
scsi_device_put(sdev);
|
||||
break;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(ap->lock, flags);
|
||||
scsi_rescan_device(sdev);
|
||||
ret = scsi_rescan_device(sdev);
|
||||
scsi_device_put(sdev);
|
||||
spin_lock_irqsave(ap->lock, flags);
|
||||
|
||||
if (ret)
|
||||
goto unlock;
|
||||
}
|
||||
}
|
||||
|
||||
unlock:
|
||||
spin_unlock_irqrestore(ap->lock, flags);
|
||||
mutex_unlock(&ap->scsi_scan_mutex);
|
||||
|
||||
if (delay_rescan)
|
||||
/* Reschedule with a delay if scsi_rescan_device() returned an error */
|
||||
if (ret)
|
||||
schedule_delayed_work(&ap->scsi_rescan_task,
|
||||
msecs_to_jiffies(5));
|
||||
}
|
||||
|
||||
@@ -266,6 +266,10 @@ void ata_tport_delete(struct ata_port *ap)
|
||||
put_device(dev);
|
||||
}
|
||||
|
||||
static const struct device_type ata_port_sas_type = {
|
||||
.name = ATA_PORT_TYPE_NAME,
|
||||
};
|
||||
|
||||
/** ata_tport_add - initialize a transport ATA port structure
|
||||
*
|
||||
* @parent: parent device
|
||||
@@ -283,7 +287,10 @@ int ata_tport_add(struct device *parent,
|
||||
struct device *dev = &ap->tdev;
|
||||
|
||||
device_initialize(dev);
|
||||
dev->type = &ata_port_type;
|
||||
if (ap->flags & ATA_FLAG_SAS_HOST)
|
||||
dev->type = &ata_port_sas_type;
|
||||
else
|
||||
dev->type = &ata_port_type;
|
||||
|
||||
dev->parent = parent;
|
||||
ata_host_get(ap->host);
|
||||
|
||||
@@ -30,6 +30,8 @@ enum {
|
||||
ATA_DNXFER_QUIET = (1 << 31),
|
||||
};
|
||||
|
||||
#define ATA_PORT_TYPE_NAME "ata_port"
|
||||
|
||||
extern atomic_t ata_print_id;
|
||||
extern int atapi_passthru16;
|
||||
extern int libata_fua;
|
||||
@@ -60,6 +62,8 @@ extern int ata_dev_reread_id(struct ata_device *dev, unsigned int readid_flags);
|
||||
extern int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
|
||||
unsigned int readid_flags);
|
||||
extern int ata_dev_configure(struct ata_device *dev);
|
||||
extern void ata_dev_power_set_standby(struct ata_device *dev);
|
||||
extern void ata_dev_power_set_active(struct ata_device *dev);
|
||||
extern int sata_down_spd_limit(struct ata_link *link, u32 spd_limit);
|
||||
extern int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel);
|
||||
extern unsigned int ata_dev_set_feature(struct ata_device *dev,
|
||||
|
||||
+227
-189
@@ -632,9 +632,8 @@ void rbd_warn(struct rbd_device *rbd_dev, const char *fmt, ...)
|
||||
static void rbd_dev_remove_parent(struct rbd_device *rbd_dev);
|
||||
|
||||
static int rbd_dev_refresh(struct rbd_device *rbd_dev);
|
||||
static int rbd_dev_v2_header_onetime(struct rbd_device *rbd_dev);
|
||||
static int rbd_dev_header_info(struct rbd_device *rbd_dev);
|
||||
static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev);
|
||||
static int rbd_dev_v2_header_onetime(struct rbd_device *rbd_dev,
|
||||
struct rbd_image_header *header);
|
||||
static const char *rbd_dev_v2_snap_name(struct rbd_device *rbd_dev,
|
||||
u64 snap_id);
|
||||
static int _rbd_dev_v2_snap_size(struct rbd_device *rbd_dev, u64 snap_id,
|
||||
@@ -995,15 +994,24 @@ static void rbd_init_layout(struct rbd_device *rbd_dev)
|
||||
RCU_INIT_POINTER(rbd_dev->layout.pool_ns, NULL);
|
||||
}
|
||||
|
||||
static void rbd_image_header_cleanup(struct rbd_image_header *header)
|
||||
{
|
||||
kfree(header->object_prefix);
|
||||
ceph_put_snap_context(header->snapc);
|
||||
kfree(header->snap_sizes);
|
||||
kfree(header->snap_names);
|
||||
|
||||
memset(header, 0, sizeof(*header));
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill an rbd image header with information from the given format 1
|
||||
* on-disk header.
|
||||
*/
|
||||
static int rbd_header_from_disk(struct rbd_device *rbd_dev,
|
||||
struct rbd_image_header_ondisk *ondisk)
|
||||
static int rbd_header_from_disk(struct rbd_image_header *header,
|
||||
struct rbd_image_header_ondisk *ondisk,
|
||||
bool first_time)
|
||||
{
|
||||
struct rbd_image_header *header = &rbd_dev->header;
|
||||
bool first_time = header->object_prefix == NULL;
|
||||
struct ceph_snap_context *snapc;
|
||||
char *object_prefix = NULL;
|
||||
char *snap_names = NULL;
|
||||
@@ -1070,11 +1078,6 @@ static int rbd_header_from_disk(struct rbd_device *rbd_dev,
|
||||
if (first_time) {
|
||||
header->object_prefix = object_prefix;
|
||||
header->obj_order = ondisk->options.order;
|
||||
rbd_init_layout(rbd_dev);
|
||||
} else {
|
||||
ceph_put_snap_context(header->snapc);
|
||||
kfree(header->snap_names);
|
||||
kfree(header->snap_sizes);
|
||||
}
|
||||
|
||||
/* The remaining fields always get updated (when we refresh) */
|
||||
@@ -4859,7 +4862,9 @@ out_req:
|
||||
* return, the rbd_dev->header field will contain up-to-date
|
||||
* information about the image.
|
||||
*/
|
||||
static int rbd_dev_v1_header_info(struct rbd_device *rbd_dev)
|
||||
static int rbd_dev_v1_header_info(struct rbd_device *rbd_dev,
|
||||
struct rbd_image_header *header,
|
||||
bool first_time)
|
||||
{
|
||||
struct rbd_image_header_ondisk *ondisk = NULL;
|
||||
u32 snap_count = 0;
|
||||
@@ -4907,7 +4912,7 @@ static int rbd_dev_v1_header_info(struct rbd_device *rbd_dev)
|
||||
snap_count = le32_to_cpu(ondisk->snap_count);
|
||||
} while (snap_count != want_count);
|
||||
|
||||
ret = rbd_header_from_disk(rbd_dev, ondisk);
|
||||
ret = rbd_header_from_disk(header, ondisk, first_time);
|
||||
out:
|
||||
kfree(ondisk);
|
||||
|
||||
@@ -4931,39 +4936,6 @@ static void rbd_dev_update_size(struct rbd_device *rbd_dev)
|
||||
}
|
||||
}
|
||||
|
||||
static int rbd_dev_refresh(struct rbd_device *rbd_dev)
|
||||
{
|
||||
u64 mapping_size;
|
||||
int ret;
|
||||
|
||||
down_write(&rbd_dev->header_rwsem);
|
||||
mapping_size = rbd_dev->mapping.size;
|
||||
|
||||
ret = rbd_dev_header_info(rbd_dev);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* If there is a parent, see if it has disappeared due to the
|
||||
* mapped image getting flattened.
|
||||
*/
|
||||
if (rbd_dev->parent) {
|
||||
ret = rbd_dev_v2_parent_info(rbd_dev);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
rbd_assert(!rbd_is_snap(rbd_dev));
|
||||
rbd_dev->mapping.size = rbd_dev->header.image_size;
|
||||
|
||||
out:
|
||||
up_write(&rbd_dev->header_rwsem);
|
||||
if (!ret && mapping_size != rbd_dev->mapping.size)
|
||||
rbd_dev_update_size(rbd_dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct blk_mq_ops rbd_mq_ops = {
|
||||
.queue_rq = rbd_queue_rq,
|
||||
};
|
||||
@@ -5503,17 +5475,12 @@ static int _rbd_dev_v2_snap_size(struct rbd_device *rbd_dev, u64 snap_id,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rbd_dev_v2_image_size(struct rbd_device *rbd_dev)
|
||||
{
|
||||
return _rbd_dev_v2_snap_size(rbd_dev, CEPH_NOSNAP,
|
||||
&rbd_dev->header.obj_order,
|
||||
&rbd_dev->header.image_size);
|
||||
}
|
||||
|
||||
static int rbd_dev_v2_object_prefix(struct rbd_device *rbd_dev)
|
||||
static int rbd_dev_v2_object_prefix(struct rbd_device *rbd_dev,
|
||||
char **pobject_prefix)
|
||||
{
|
||||
size_t size;
|
||||
void *reply_buf;
|
||||
char *object_prefix;
|
||||
int ret;
|
||||
void *p;
|
||||
|
||||
@@ -5531,16 +5498,16 @@ static int rbd_dev_v2_object_prefix(struct rbd_device *rbd_dev)
|
||||
goto out;
|
||||
|
||||
p = reply_buf;
|
||||
rbd_dev->header.object_prefix = ceph_extract_encoded_string(&p,
|
||||
p + ret, NULL, GFP_NOIO);
|
||||
object_prefix = ceph_extract_encoded_string(&p, p + ret, NULL,
|
||||
GFP_NOIO);
|
||||
if (IS_ERR(object_prefix)) {
|
||||
ret = PTR_ERR(object_prefix);
|
||||
goto out;
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
if (IS_ERR(rbd_dev->header.object_prefix)) {
|
||||
ret = PTR_ERR(rbd_dev->header.object_prefix);
|
||||
rbd_dev->header.object_prefix = NULL;
|
||||
} else {
|
||||
dout(" object_prefix = %s\n", rbd_dev->header.object_prefix);
|
||||
}
|
||||
*pobject_prefix = object_prefix;
|
||||
dout(" object_prefix = %s\n", object_prefix);
|
||||
out:
|
||||
kfree(reply_buf);
|
||||
|
||||
@@ -5591,13 +5558,6 @@ static int _rbd_dev_v2_snap_features(struct rbd_device *rbd_dev, u64 snap_id,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rbd_dev_v2_features(struct rbd_device *rbd_dev)
|
||||
{
|
||||
return _rbd_dev_v2_snap_features(rbd_dev, CEPH_NOSNAP,
|
||||
rbd_is_ro(rbd_dev),
|
||||
&rbd_dev->header.features);
|
||||
}
|
||||
|
||||
/*
|
||||
* These are generic image flags, but since they are used only for
|
||||
* object map, store them in rbd_dev->object_map_flags.
|
||||
@@ -5634,6 +5594,14 @@ struct parent_image_info {
|
||||
u64 overlap;
|
||||
};
|
||||
|
||||
static void rbd_parent_info_cleanup(struct parent_image_info *pii)
|
||||
{
|
||||
kfree(pii->pool_ns);
|
||||
kfree(pii->image_id);
|
||||
|
||||
memset(pii, 0, sizeof(*pii));
|
||||
}
|
||||
|
||||
/*
|
||||
* The caller is responsible for @pii.
|
||||
*/
|
||||
@@ -5703,6 +5671,9 @@ static int __get_parent_info(struct rbd_device *rbd_dev,
|
||||
if (pii->has_overlap)
|
||||
ceph_decode_64_safe(&p, end, pii->overlap, e_inval);
|
||||
|
||||
dout("%s pool_id %llu pool_ns %s image_id %s snap_id %llu has_overlap %d overlap %llu\n",
|
||||
__func__, pii->pool_id, pii->pool_ns, pii->image_id, pii->snap_id,
|
||||
pii->has_overlap, pii->overlap);
|
||||
return 0;
|
||||
|
||||
e_inval:
|
||||
@@ -5741,14 +5712,17 @@ static int __get_parent_info_legacy(struct rbd_device *rbd_dev,
|
||||
pii->has_overlap = true;
|
||||
ceph_decode_64_safe(&p, end, pii->overlap, e_inval);
|
||||
|
||||
dout("%s pool_id %llu pool_ns %s image_id %s snap_id %llu has_overlap %d overlap %llu\n",
|
||||
__func__, pii->pool_id, pii->pool_ns, pii->image_id, pii->snap_id,
|
||||
pii->has_overlap, pii->overlap);
|
||||
return 0;
|
||||
|
||||
e_inval:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int get_parent_info(struct rbd_device *rbd_dev,
|
||||
struct parent_image_info *pii)
|
||||
static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev,
|
||||
struct parent_image_info *pii)
|
||||
{
|
||||
struct page *req_page, *reply_page;
|
||||
void *p;
|
||||
@@ -5776,7 +5750,7 @@ static int get_parent_info(struct rbd_device *rbd_dev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev)
|
||||
static int rbd_dev_setup_parent(struct rbd_device *rbd_dev)
|
||||
{
|
||||
struct rbd_spec *parent_spec;
|
||||
struct parent_image_info pii = { 0 };
|
||||
@@ -5786,37 +5760,12 @@ static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev)
|
||||
if (!parent_spec)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = get_parent_info(rbd_dev, &pii);
|
||||
ret = rbd_dev_v2_parent_info(rbd_dev, &pii);
|
||||
if (ret)
|
||||
goto out_err;
|
||||
|
||||
dout("%s pool_id %llu pool_ns %s image_id %s snap_id %llu has_overlap %d overlap %llu\n",
|
||||
__func__, pii.pool_id, pii.pool_ns, pii.image_id, pii.snap_id,
|
||||
pii.has_overlap, pii.overlap);
|
||||
|
||||
if (pii.pool_id == CEPH_NOPOOL || !pii.has_overlap) {
|
||||
/*
|
||||
* Either the parent never existed, or we have
|
||||
* record of it but the image got flattened so it no
|
||||
* longer has a parent. When the parent of a
|
||||
* layered image disappears we immediately set the
|
||||
* overlap to 0. The effect of this is that all new
|
||||
* requests will be treated as if the image had no
|
||||
* parent.
|
||||
*
|
||||
* If !pii.has_overlap, the parent image spec is not
|
||||
* applicable. It's there to avoid duplication in each
|
||||
* snapshot record.
|
||||
*/
|
||||
if (rbd_dev->parent_overlap) {
|
||||
rbd_dev->parent_overlap = 0;
|
||||
rbd_dev_parent_put(rbd_dev);
|
||||
pr_info("%s: clone image has been flattened\n",
|
||||
rbd_dev->disk->disk_name);
|
||||
}
|
||||
|
||||
if (pii.pool_id == CEPH_NOPOOL || !pii.has_overlap)
|
||||
goto out; /* No parent? No problem. */
|
||||
}
|
||||
|
||||
/* The ceph file layout needs to fit pool id in 32 bits */
|
||||
|
||||
@@ -5828,58 +5777,46 @@ static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev)
|
||||
}
|
||||
|
||||
/*
|
||||
* The parent won't change (except when the clone is
|
||||
* flattened, already handled that). So we only need to
|
||||
* record the parent spec we have not already done so.
|
||||
* The parent won't change except when the clone is flattened,
|
||||
* so we only need to record the parent image spec once.
|
||||
*/
|
||||
if (!rbd_dev->parent_spec) {
|
||||
parent_spec->pool_id = pii.pool_id;
|
||||
if (pii.pool_ns && *pii.pool_ns) {
|
||||
parent_spec->pool_ns = pii.pool_ns;
|
||||
pii.pool_ns = NULL;
|
||||
}
|
||||
parent_spec->image_id = pii.image_id;
|
||||
pii.image_id = NULL;
|
||||
parent_spec->snap_id = pii.snap_id;
|
||||
|
||||
rbd_dev->parent_spec = parent_spec;
|
||||
parent_spec = NULL; /* rbd_dev now owns this */
|
||||
parent_spec->pool_id = pii.pool_id;
|
||||
if (pii.pool_ns && *pii.pool_ns) {
|
||||
parent_spec->pool_ns = pii.pool_ns;
|
||||
pii.pool_ns = NULL;
|
||||
}
|
||||
parent_spec->image_id = pii.image_id;
|
||||
pii.image_id = NULL;
|
||||
parent_spec->snap_id = pii.snap_id;
|
||||
|
||||
rbd_assert(!rbd_dev->parent_spec);
|
||||
rbd_dev->parent_spec = parent_spec;
|
||||
parent_spec = NULL; /* rbd_dev now owns this */
|
||||
|
||||
/*
|
||||
* We always update the parent overlap. If it's zero we issue
|
||||
* a warning, as we will proceed as if there was no parent.
|
||||
* Record the parent overlap. If it's zero, issue a warning as
|
||||
* we will proceed as if there is no parent.
|
||||
*/
|
||||
if (!pii.overlap) {
|
||||
if (parent_spec) {
|
||||
/* refresh, careful to warn just once */
|
||||
if (rbd_dev->parent_overlap)
|
||||
rbd_warn(rbd_dev,
|
||||
"clone now standalone (overlap became 0)");
|
||||
} else {
|
||||
/* initial probe */
|
||||
rbd_warn(rbd_dev, "clone is standalone (overlap 0)");
|
||||
}
|
||||
}
|
||||
if (!pii.overlap)
|
||||
rbd_warn(rbd_dev, "clone is standalone (overlap 0)");
|
||||
rbd_dev->parent_overlap = pii.overlap;
|
||||
|
||||
out:
|
||||
ret = 0;
|
||||
out_err:
|
||||
kfree(pii.pool_ns);
|
||||
kfree(pii.image_id);
|
||||
rbd_parent_info_cleanup(&pii);
|
||||
rbd_spec_put(parent_spec);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rbd_dev_v2_striping_info(struct rbd_device *rbd_dev)
|
||||
static int rbd_dev_v2_striping_info(struct rbd_device *rbd_dev,
|
||||
u64 *stripe_unit, u64 *stripe_count)
|
||||
{
|
||||
struct {
|
||||
__le64 stripe_unit;
|
||||
__le64 stripe_count;
|
||||
} __attribute__ ((packed)) striping_info_buf = { 0 };
|
||||
size_t size = sizeof (striping_info_buf);
|
||||
void *p;
|
||||
int ret;
|
||||
|
||||
ret = rbd_obj_method_sync(rbd_dev, &rbd_dev->header_oid,
|
||||
@@ -5891,27 +5828,33 @@ static int rbd_dev_v2_striping_info(struct rbd_device *rbd_dev)
|
||||
if (ret < size)
|
||||
return -ERANGE;
|
||||
|
||||
p = &striping_info_buf;
|
||||
rbd_dev->header.stripe_unit = ceph_decode_64(&p);
|
||||
rbd_dev->header.stripe_count = ceph_decode_64(&p);
|
||||
*stripe_unit = le64_to_cpu(striping_info_buf.stripe_unit);
|
||||
*stripe_count = le64_to_cpu(striping_info_buf.stripe_count);
|
||||
dout(" stripe_unit = %llu stripe_count = %llu\n", *stripe_unit,
|
||||
*stripe_count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rbd_dev_v2_data_pool(struct rbd_device *rbd_dev)
|
||||
static int rbd_dev_v2_data_pool(struct rbd_device *rbd_dev, s64 *data_pool_id)
|
||||
{
|
||||
__le64 data_pool_id;
|
||||
__le64 data_pool_buf;
|
||||
int ret;
|
||||
|
||||
ret = rbd_obj_method_sync(rbd_dev, &rbd_dev->header_oid,
|
||||
&rbd_dev->header_oloc, "get_data_pool",
|
||||
NULL, 0, &data_pool_id, sizeof(data_pool_id));
|
||||
NULL, 0, &data_pool_buf,
|
||||
sizeof(data_pool_buf));
|
||||
dout("%s: rbd_obj_method_sync returned %d\n", __func__, ret);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret < sizeof(data_pool_id))
|
||||
if (ret < sizeof(data_pool_buf))
|
||||
return -EBADMSG;
|
||||
|
||||
rbd_dev->header.data_pool_id = le64_to_cpu(data_pool_id);
|
||||
WARN_ON(rbd_dev->header.data_pool_id == CEPH_NOPOOL);
|
||||
*data_pool_id = le64_to_cpu(data_pool_buf);
|
||||
dout(" data_pool_id = %lld\n", *data_pool_id);
|
||||
WARN_ON(*data_pool_id == CEPH_NOPOOL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -6103,7 +6046,8 @@ out_err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rbd_dev_v2_snap_context(struct rbd_device *rbd_dev)
|
||||
static int rbd_dev_v2_snap_context(struct rbd_device *rbd_dev,
|
||||
struct ceph_snap_context **psnapc)
|
||||
{
|
||||
size_t size;
|
||||
int ret;
|
||||
@@ -6164,9 +6108,7 @@ static int rbd_dev_v2_snap_context(struct rbd_device *rbd_dev)
|
||||
for (i = 0; i < snap_count; i++)
|
||||
snapc->snaps[i] = ceph_decode_64(&p);
|
||||
|
||||
ceph_put_snap_context(rbd_dev->header.snapc);
|
||||
rbd_dev->header.snapc = snapc;
|
||||
|
||||
*psnapc = snapc;
|
||||
dout(" snap context seq = %llu, snap_count = %u\n",
|
||||
(unsigned long long)seq, (unsigned int)snap_count);
|
||||
out:
|
||||
@@ -6215,38 +6157,42 @@ out:
|
||||
return snap_name;
|
||||
}
|
||||
|
||||
static int rbd_dev_v2_header_info(struct rbd_device *rbd_dev)
|
||||
static int rbd_dev_v2_header_info(struct rbd_device *rbd_dev,
|
||||
struct rbd_image_header *header,
|
||||
bool first_time)
|
||||
{
|
||||
bool first_time = rbd_dev->header.object_prefix == NULL;
|
||||
int ret;
|
||||
|
||||
ret = rbd_dev_v2_image_size(rbd_dev);
|
||||
ret = _rbd_dev_v2_snap_size(rbd_dev, CEPH_NOSNAP,
|
||||
first_time ? &header->obj_order : NULL,
|
||||
&header->image_size);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (first_time) {
|
||||
ret = rbd_dev_v2_header_onetime(rbd_dev);
|
||||
ret = rbd_dev_v2_header_onetime(rbd_dev, header);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = rbd_dev_v2_snap_context(rbd_dev);
|
||||
if (ret && first_time) {
|
||||
kfree(rbd_dev->header.object_prefix);
|
||||
rbd_dev->header.object_prefix = NULL;
|
||||
}
|
||||
ret = rbd_dev_v2_snap_context(rbd_dev, &header->snapc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rbd_dev_header_info(struct rbd_device *rbd_dev)
|
||||
static int rbd_dev_header_info(struct rbd_device *rbd_dev,
|
||||
struct rbd_image_header *header,
|
||||
bool first_time)
|
||||
{
|
||||
rbd_assert(rbd_image_format_valid(rbd_dev->image_format));
|
||||
rbd_assert(!header->object_prefix && !header->snapc);
|
||||
|
||||
if (rbd_dev->image_format == 1)
|
||||
return rbd_dev_v1_header_info(rbd_dev);
|
||||
return rbd_dev_v1_header_info(rbd_dev, header, first_time);
|
||||
|
||||
return rbd_dev_v2_header_info(rbd_dev);
|
||||
return rbd_dev_v2_header_info(rbd_dev, header, first_time);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -6734,60 +6680,49 @@ out:
|
||||
*/
|
||||
static void rbd_dev_unprobe(struct rbd_device *rbd_dev)
|
||||
{
|
||||
struct rbd_image_header *header;
|
||||
|
||||
rbd_dev_parent_put(rbd_dev);
|
||||
rbd_object_map_free(rbd_dev);
|
||||
rbd_dev_mapping_clear(rbd_dev);
|
||||
|
||||
/* Free dynamic fields from the header, then zero it out */
|
||||
|
||||
header = &rbd_dev->header;
|
||||
ceph_put_snap_context(header->snapc);
|
||||
kfree(header->snap_sizes);
|
||||
kfree(header->snap_names);
|
||||
kfree(header->object_prefix);
|
||||
memset(header, 0, sizeof (*header));
|
||||
rbd_image_header_cleanup(&rbd_dev->header);
|
||||
}
|
||||
|
||||
static int rbd_dev_v2_header_onetime(struct rbd_device *rbd_dev)
|
||||
static int rbd_dev_v2_header_onetime(struct rbd_device *rbd_dev,
|
||||
struct rbd_image_header *header)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = rbd_dev_v2_object_prefix(rbd_dev);
|
||||
ret = rbd_dev_v2_object_prefix(rbd_dev, &header->object_prefix);
|
||||
if (ret)
|
||||
goto out_err;
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Get the and check features for the image. Currently the
|
||||
* features are assumed to never change.
|
||||
*/
|
||||
ret = rbd_dev_v2_features(rbd_dev);
|
||||
ret = _rbd_dev_v2_snap_features(rbd_dev, CEPH_NOSNAP,
|
||||
rbd_is_ro(rbd_dev), &header->features);
|
||||
if (ret)
|
||||
goto out_err;
|
||||
return ret;
|
||||
|
||||
/* If the image supports fancy striping, get its parameters */
|
||||
|
||||
if (rbd_dev->header.features & RBD_FEATURE_STRIPINGV2) {
|
||||
ret = rbd_dev_v2_striping_info(rbd_dev);
|
||||
if (ret < 0)
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
if (rbd_dev->header.features & RBD_FEATURE_DATA_POOL) {
|
||||
ret = rbd_dev_v2_data_pool(rbd_dev);
|
||||
if (header->features & RBD_FEATURE_STRIPINGV2) {
|
||||
ret = rbd_dev_v2_striping_info(rbd_dev, &header->stripe_unit,
|
||||
&header->stripe_count);
|
||||
if (ret)
|
||||
goto out_err;
|
||||
return ret;
|
||||
}
|
||||
|
||||
rbd_init_layout(rbd_dev);
|
||||
return 0;
|
||||
if (header->features & RBD_FEATURE_DATA_POOL) {
|
||||
ret = rbd_dev_v2_data_pool(rbd_dev, &header->data_pool_id);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
out_err:
|
||||
rbd_dev->header.features = 0;
|
||||
kfree(rbd_dev->header.object_prefix);
|
||||
rbd_dev->header.object_prefix = NULL;
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -6982,13 +6917,15 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth)
|
||||
if (!depth)
|
||||
down_write(&rbd_dev->header_rwsem);
|
||||
|
||||
ret = rbd_dev_header_info(rbd_dev);
|
||||
ret = rbd_dev_header_info(rbd_dev, &rbd_dev->header, true);
|
||||
if (ret) {
|
||||
if (ret == -ENOENT && !need_watch)
|
||||
rbd_print_dne(rbd_dev, false);
|
||||
goto err_out_probe;
|
||||
}
|
||||
|
||||
rbd_init_layout(rbd_dev);
|
||||
|
||||
/*
|
||||
* If this image is the one being mapped, we have pool name and
|
||||
* id, image name and id, and snap name - need to fill snap id.
|
||||
@@ -7017,7 +6954,7 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth)
|
||||
}
|
||||
|
||||
if (rbd_dev->header.features & RBD_FEATURE_LAYERING) {
|
||||
ret = rbd_dev_v2_parent_info(rbd_dev);
|
||||
ret = rbd_dev_setup_parent(rbd_dev);
|
||||
if (ret)
|
||||
goto err_out_probe;
|
||||
}
|
||||
@@ -7043,6 +6980,107 @@ err_out_format:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rbd_dev_update_header(struct rbd_device *rbd_dev,
|
||||
struct rbd_image_header *header)
|
||||
{
|
||||
rbd_assert(rbd_image_format_valid(rbd_dev->image_format));
|
||||
rbd_assert(rbd_dev->header.object_prefix); /* !first_time */
|
||||
|
||||
if (rbd_dev->header.image_size != header->image_size) {
|
||||
rbd_dev->header.image_size = header->image_size;
|
||||
|
||||
if (!rbd_is_snap(rbd_dev)) {
|
||||
rbd_dev->mapping.size = header->image_size;
|
||||
rbd_dev_update_size(rbd_dev);
|
||||
}
|
||||
}
|
||||
|
||||
ceph_put_snap_context(rbd_dev->header.snapc);
|
||||
rbd_dev->header.snapc = header->snapc;
|
||||
header->snapc = NULL;
|
||||
|
||||
if (rbd_dev->image_format == 1) {
|
||||
kfree(rbd_dev->header.snap_names);
|
||||
rbd_dev->header.snap_names = header->snap_names;
|
||||
header->snap_names = NULL;
|
||||
|
||||
kfree(rbd_dev->header.snap_sizes);
|
||||
rbd_dev->header.snap_sizes = header->snap_sizes;
|
||||
header->snap_sizes = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void rbd_dev_update_parent(struct rbd_device *rbd_dev,
|
||||
struct parent_image_info *pii)
|
||||
{
|
||||
if (pii->pool_id == CEPH_NOPOOL || !pii->has_overlap) {
|
||||
/*
|
||||
* Either the parent never existed, or we have
|
||||
* record of it but the image got flattened so it no
|
||||
* longer has a parent. When the parent of a
|
||||
* layered image disappears we immediately set the
|
||||
* overlap to 0. The effect of this is that all new
|
||||
* requests will be treated as if the image had no
|
||||
* parent.
|
||||
*
|
||||
* If !pii.has_overlap, the parent image spec is not
|
||||
* applicable. It's there to avoid duplication in each
|
||||
* snapshot record.
|
||||
*/
|
||||
if (rbd_dev->parent_overlap) {
|
||||
rbd_dev->parent_overlap = 0;
|
||||
rbd_dev_parent_put(rbd_dev);
|
||||
pr_info("%s: clone has been flattened\n",
|
||||
rbd_dev->disk->disk_name);
|
||||
}
|
||||
} else {
|
||||
rbd_assert(rbd_dev->parent_spec);
|
||||
|
||||
/*
|
||||
* Update the parent overlap. If it became zero, issue
|
||||
* a warning as we will proceed as if there is no parent.
|
||||
*/
|
||||
if (!pii->overlap && rbd_dev->parent_overlap)
|
||||
rbd_warn(rbd_dev,
|
||||
"clone has become standalone (overlap 0)");
|
||||
rbd_dev->parent_overlap = pii->overlap;
|
||||
}
|
||||
}
|
||||
|
||||
static int rbd_dev_refresh(struct rbd_device *rbd_dev)
|
||||
{
|
||||
struct rbd_image_header header = { 0 };
|
||||
struct parent_image_info pii = { 0 };
|
||||
int ret;
|
||||
|
||||
dout("%s rbd_dev %p\n", __func__, rbd_dev);
|
||||
|
||||
ret = rbd_dev_header_info(rbd_dev, &header, false);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* If there is a parent, see if it has disappeared due to the
|
||||
* mapped image getting flattened.
|
||||
*/
|
||||
if (rbd_dev->parent) {
|
||||
ret = rbd_dev_v2_parent_info(rbd_dev, &pii);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
down_write(&rbd_dev->header_rwsem);
|
||||
rbd_dev_update_header(rbd_dev, &header);
|
||||
if (rbd_dev->parent)
|
||||
rbd_dev_update_parent(rbd_dev, &pii);
|
||||
up_write(&rbd_dev->header_rwsem);
|
||||
|
||||
out:
|
||||
rbd_parent_info_cleanup(&pii);
|
||||
rbd_image_header_cleanup(&header);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t do_rbd_add(const char *buf, size_t count)
|
||||
{
|
||||
struct rbd_device *rbd_dev = NULL;
|
||||
|
||||
+22
-9
@@ -38,6 +38,7 @@ enum sysc_soc {
|
||||
SOC_2420,
|
||||
SOC_2430,
|
||||
SOC_3430,
|
||||
SOC_AM35,
|
||||
SOC_3630,
|
||||
SOC_4430,
|
||||
SOC_4460,
|
||||
@@ -1097,6 +1098,11 @@ static int sysc_enable_module(struct device *dev)
|
||||
if (ddata->cfg.quirks & (SYSC_QUIRK_SWSUP_SIDLE |
|
||||
SYSC_QUIRK_SWSUP_SIDLE_ACT)) {
|
||||
best_mode = SYSC_IDLE_NO;
|
||||
|
||||
/* Clear WAKEUP */
|
||||
if (regbits->enwkup_shift >= 0 &&
|
||||
ddata->cfg.sysc_val & BIT(regbits->enwkup_shift))
|
||||
reg &= ~BIT(regbits->enwkup_shift);
|
||||
} else {
|
||||
best_mode = fls(ddata->cfg.sidlemodes) - 1;
|
||||
if (best_mode > SYSC_IDLE_MASK) {
|
||||
@@ -1224,6 +1230,13 @@ set_sidle:
|
||||
}
|
||||
}
|
||||
|
||||
if (ddata->cfg.quirks & SYSC_QUIRK_SWSUP_SIDLE_ACT) {
|
||||
/* Set WAKEUP */
|
||||
if (regbits->enwkup_shift >= 0 &&
|
||||
ddata->cfg.sysc_val & BIT(regbits->enwkup_shift))
|
||||
reg |= BIT(regbits->enwkup_shift);
|
||||
}
|
||||
|
||||
reg &= ~(SYSC_IDLE_MASK << regbits->sidle_shift);
|
||||
reg |= best_mode << regbits->sidle_shift;
|
||||
if (regbits->autoidle_shift >= 0 &&
|
||||
@@ -1518,16 +1531,16 @@ struct sysc_revision_quirk {
|
||||
static const struct sysc_revision_quirk sysc_revision_quirks[] = {
|
||||
/* These drivers need to be fixed to not use pm_runtime_irq_safe() */
|
||||
SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x00000046, 0xffffffff,
|
||||
SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_LEGACY_IDLE),
|
||||
SYSC_QUIRK_SWSUP_SIDLE_ACT | SYSC_QUIRK_LEGACY_IDLE),
|
||||
SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x00000052, 0xffffffff,
|
||||
SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_LEGACY_IDLE),
|
||||
SYSC_QUIRK_SWSUP_SIDLE_ACT | SYSC_QUIRK_LEGACY_IDLE),
|
||||
/* Uarts on omap4 and later */
|
||||
SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x50411e03, 0xffff00ff,
|
||||
SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_LEGACY_IDLE),
|
||||
SYSC_QUIRK_SWSUP_SIDLE_ACT | SYSC_QUIRK_LEGACY_IDLE),
|
||||
SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x47422e03, 0xffffffff,
|
||||
SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_LEGACY_IDLE),
|
||||
SYSC_QUIRK_SWSUP_SIDLE_ACT | SYSC_QUIRK_LEGACY_IDLE),
|
||||
SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x47424e03, 0xffffffff,
|
||||
SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_LEGACY_IDLE),
|
||||
SYSC_QUIRK_SWSUP_SIDLE_ACT | SYSC_QUIRK_LEGACY_IDLE),
|
||||
|
||||
/* Quirks that need to be set based on the module address */
|
||||
SYSC_QUIRK("mcpdm", 0x40132000, 0, 0x10, -ENODEV, 0x50000800, 0xffffffff,
|
||||
@@ -1862,7 +1875,7 @@ static void sysc_pre_reset_quirk_dss(struct sysc *ddata)
|
||||
dev_warn(ddata->dev, "%s: timed out %08x !+ %08x\n",
|
||||
__func__, val, irq_mask);
|
||||
|
||||
if (sysc_soc->soc == SOC_3430) {
|
||||
if (sysc_soc->soc == SOC_3430 || sysc_soc->soc == SOC_AM35) {
|
||||
/* Clear DSS_SDI_CONTROL */
|
||||
sysc_write(ddata, 0x44, 0);
|
||||
|
||||
@@ -2150,8 +2163,7 @@ static int sysc_reset(struct sysc *ddata)
|
||||
}
|
||||
|
||||
if (ddata->cfg.srst_udelay)
|
||||
usleep_range(ddata->cfg.srst_udelay,
|
||||
ddata->cfg.srst_udelay * 2);
|
||||
fsleep(ddata->cfg.srst_udelay);
|
||||
|
||||
if (ddata->post_reset_quirk)
|
||||
ddata->post_reset_quirk(ddata);
|
||||
@@ -3025,6 +3037,7 @@ static void ti_sysc_idle(struct work_struct *work)
|
||||
static const struct soc_device_attribute sysc_soc_match[] = {
|
||||
SOC_FLAG("OMAP242*", SOC_2420),
|
||||
SOC_FLAG("OMAP243*", SOC_2430),
|
||||
SOC_FLAG("AM35*", SOC_AM35),
|
||||
SOC_FLAG("OMAP3[45]*", SOC_3430),
|
||||
SOC_FLAG("OMAP3[67]*", SOC_3630),
|
||||
SOC_FLAG("OMAP443*", SOC_4430),
|
||||
@@ -3229,7 +3242,7 @@ static int sysc_check_active_timer(struct sysc *ddata)
|
||||
* can be dropped if we stop supporting old beagleboard revisions
|
||||
* A to B4 at some point.
|
||||
*/
|
||||
if (sysc_soc->soc == SOC_3430)
|
||||
if (sysc_soc->soc == SOC_3430 || sysc_soc->soc == SOC_AM35)
|
||||
error = -ENXIO;
|
||||
else
|
||||
error = -EBUSY;
|
||||
|
||||
@@ -96,7 +96,7 @@ static int si521xx_regmap_i2c_write(void *context, unsigned int reg,
|
||||
unsigned int val)
|
||||
{
|
||||
struct i2c_client *i2c = context;
|
||||
const u8 data[3] = { reg, 1, val };
|
||||
const u8 data[2] = { reg, val };
|
||||
const int count = ARRAY_SIZE(data);
|
||||
int ret;
|
||||
|
||||
@@ -146,7 +146,7 @@ static int si521xx_regmap_i2c_read(void *context, unsigned int reg,
|
||||
static const struct regmap_config si521xx_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.cache_type = REGCACHE_NONE,
|
||||
.cache_type = REGCACHE_FLAT,
|
||||
.max_register = SI521XX_REG_DA,
|
||||
.rd_table = &si521xx_readable_table,
|
||||
.wr_table = &si521xx_writeable_table,
|
||||
@@ -281,9 +281,10 @@ static int si521xx_probe(struct i2c_client *client)
|
||||
{
|
||||
const u16 chip_info = (u16)(uintptr_t)device_get_match_data(&client->dev);
|
||||
const struct clk_parent_data clk_parent_data = { .index = 0 };
|
||||
struct si521xx *si;
|
||||
const u8 data[3] = { SI521XX_REG_BC, 1, 1 };
|
||||
unsigned char name[6] = "DIFF0";
|
||||
struct clk_init_data init = {};
|
||||
struct si521xx *si;
|
||||
int i, ret;
|
||||
|
||||
if (!chip_info)
|
||||
@@ -308,7 +309,7 @@ static int si521xx_probe(struct i2c_client *client)
|
||||
"Failed to allocate register map\n");
|
||||
|
||||
/* Always read back 1 Byte via I2C */
|
||||
ret = regmap_write(si->regmap, SI521XX_REG_BC, 1);
|
||||
ret = i2c_master_send(client, data, ARRAY_SIZE(data));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
||||
@@ -118,21 +118,21 @@ enum vc3_div {
|
||||
VC3_DIV5,
|
||||
};
|
||||
|
||||
enum vc3_clk_mux {
|
||||
VC3_DIFF2_MUX,
|
||||
VC3_DIFF1_MUX,
|
||||
VC3_SE3_MUX,
|
||||
VC3_SE2_MUX,
|
||||
VC3_SE1_MUX,
|
||||
enum vc3_clk {
|
||||
VC3_REF,
|
||||
VC3_SE1,
|
||||
VC3_SE2,
|
||||
VC3_SE3,
|
||||
VC3_DIFF1,
|
||||
VC3_DIFF2,
|
||||
};
|
||||
|
||||
enum vc3_clk {
|
||||
VC3_DIFF2,
|
||||
VC3_DIFF1,
|
||||
VC3_SE3,
|
||||
VC3_SE2,
|
||||
VC3_SE1,
|
||||
VC3_REF,
|
||||
enum vc3_clk_mux {
|
||||
VC3_SE1_MUX = VC3_SE1 - 1,
|
||||
VC3_SE2_MUX = VC3_SE2 - 1,
|
||||
VC3_SE3_MUX = VC3_SE3 - 1,
|
||||
VC3_DIFF1_MUX = VC3_DIFF1 - 1,
|
||||
VC3_DIFF2_MUX = VC3_DIFF2 - 1,
|
||||
};
|
||||
|
||||
struct vc3_clk_data {
|
||||
@@ -401,11 +401,10 @@ static long vc3_pll_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
/* Determine best fractional part, which is 16 bit wide */
|
||||
div_frc = rate % *parent_rate;
|
||||
div_frc *= BIT(16) - 1;
|
||||
do_div(div_frc, *parent_rate);
|
||||
|
||||
vc3->div_frc = (u32)div_frc;
|
||||
vc3->div_frc = min_t(u64, div64_ul(div_frc, *parent_rate), U16_MAX);
|
||||
rate = (*parent_rate *
|
||||
(vc3->div_int * VC3_2_POW_16 + div_frc) / VC3_2_POW_16);
|
||||
(vc3->div_int * VC3_2_POW_16 + vc3->div_frc) / VC3_2_POW_16);
|
||||
} else {
|
||||
rate = *parent_rate * vc3->div_int;
|
||||
}
|
||||
@@ -897,48 +896,16 @@ static struct vc3_hw_data clk_div[] = {
|
||||
};
|
||||
|
||||
static struct vc3_hw_data clk_mux[] = {
|
||||
[VC3_DIFF2_MUX] = {
|
||||
[VC3_SE1_MUX] = {
|
||||
.data = &(struct vc3_clk_data) {
|
||||
.offs = VC3_DIFF2_CTRL_REG,
|
||||
.bitmsk = VC3_DIFF2_CTRL_REG_DIFF2_CLK_SEL
|
||||
.offs = VC3_SE1_DIV4_CTRL,
|
||||
.bitmsk = VC3_SE1_DIV4_CTRL_SE1_CLK_SEL
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "diff2_mux",
|
||||
.name = "se1_mux",
|
||||
.ops = &vc3_clk_mux_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) {
|
||||
&clk_div[VC3_DIV1].hw,
|
||||
&clk_div[VC3_DIV3].hw
|
||||
},
|
||||
.num_parents = 2,
|
||||
.flags = CLK_SET_RATE_PARENT
|
||||
}
|
||||
},
|
||||
[VC3_DIFF1_MUX] = {
|
||||
.data = &(struct vc3_clk_data) {
|
||||
.offs = VC3_DIFF1_CTRL_REG,
|
||||
.bitmsk = VC3_DIFF1_CTRL_REG_DIFF1_CLK_SEL
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "diff1_mux",
|
||||
.ops = &vc3_clk_mux_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) {
|
||||
&clk_div[VC3_DIV1].hw,
|
||||
&clk_div[VC3_DIV3].hw
|
||||
},
|
||||
.num_parents = 2,
|
||||
.flags = CLK_SET_RATE_PARENT
|
||||
}
|
||||
},
|
||||
[VC3_SE3_MUX] = {
|
||||
.data = &(struct vc3_clk_data) {
|
||||
.offs = VC3_SE3_DIFF1_CTRL_REG,
|
||||
.bitmsk = VC3_SE3_DIFF1_CTRL_REG_SE3_CLK_SEL
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "se3_mux",
|
||||
.ops = &vc3_clk_mux_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) {
|
||||
&clk_div[VC3_DIV2].hw,
|
||||
&clk_div[VC3_DIV5].hw,
|
||||
&clk_div[VC3_DIV4].hw
|
||||
},
|
||||
.num_parents = 2,
|
||||
@@ -961,21 +928,53 @@ static struct vc3_hw_data clk_mux[] = {
|
||||
.flags = CLK_SET_RATE_PARENT
|
||||
}
|
||||
},
|
||||
[VC3_SE1_MUX] = {
|
||||
[VC3_SE3_MUX] = {
|
||||
.data = &(struct vc3_clk_data) {
|
||||
.offs = VC3_SE1_DIV4_CTRL,
|
||||
.bitmsk = VC3_SE1_DIV4_CTRL_SE1_CLK_SEL
|
||||
.offs = VC3_SE3_DIFF1_CTRL_REG,
|
||||
.bitmsk = VC3_SE3_DIFF1_CTRL_REG_SE3_CLK_SEL
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "se1_mux",
|
||||
.name = "se3_mux",
|
||||
.ops = &vc3_clk_mux_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) {
|
||||
&clk_div[VC3_DIV5].hw,
|
||||
&clk_div[VC3_DIV2].hw,
|
||||
&clk_div[VC3_DIV4].hw
|
||||
},
|
||||
.num_parents = 2,
|
||||
.flags = CLK_SET_RATE_PARENT
|
||||
}
|
||||
},
|
||||
[VC3_DIFF1_MUX] = {
|
||||
.data = &(struct vc3_clk_data) {
|
||||
.offs = VC3_DIFF1_CTRL_REG,
|
||||
.bitmsk = VC3_DIFF1_CTRL_REG_DIFF1_CLK_SEL
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "diff1_mux",
|
||||
.ops = &vc3_clk_mux_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) {
|
||||
&clk_div[VC3_DIV1].hw,
|
||||
&clk_div[VC3_DIV3].hw
|
||||
},
|
||||
.num_parents = 2,
|
||||
.flags = CLK_SET_RATE_PARENT
|
||||
}
|
||||
},
|
||||
[VC3_DIFF2_MUX] = {
|
||||
.data = &(struct vc3_clk_data) {
|
||||
.offs = VC3_DIFF2_CTRL_REG,
|
||||
.bitmsk = VC3_DIFF2_CTRL_REG_DIFF2_CLK_SEL
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "diff2_mux",
|
||||
.ops = &vc3_clk_mux_ops,
|
||||
.parent_hws = (const struct clk_hw *[]) {
|
||||
&clk_div[VC3_DIV1].hw,
|
||||
&clk_div[VC3_DIV3].hw
|
||||
},
|
||||
.num_parents = 2,
|
||||
.flags = CLK_SET_RATE_PARENT
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1110,7 +1109,7 @@ static int vc3_probe(struct i2c_client *client)
|
||||
name, 0, CLK_SET_RATE_PARENT, 1, 1);
|
||||
else
|
||||
clk_out[i] = devm_clk_hw_register_fixed_factor_parent_hw(dev,
|
||||
name, &clk_mux[i].hw, CLK_SET_RATE_PARENT, 1, 1);
|
||||
name, &clk_mux[i - 1].hw, CLK_SET_RATE_PARENT, 1, 1);
|
||||
|
||||
if (IS_ERR(clk_out[i]))
|
||||
return PTR_ERR(clk_out[i]);
|
||||
|
||||
@@ -800,7 +800,7 @@ static SPRD_MUX_CLK_DATA(uart1_clk, "uart1-clk", uart_parents,
|
||||
0x250, 0, 3, UMS512_MUX_FLAG);
|
||||
|
||||
static const struct clk_parent_data thm_parents[] = {
|
||||
{ .fw_name = "ext-32m" },
|
||||
{ .fw_name = "ext-32k" },
|
||||
{ .hw = &clk_250k.hw },
|
||||
};
|
||||
static SPRD_MUX_CLK_DATA(thm0_clk, "thm0-clk", thm_parents,
|
||||
|
||||
@@ -159,7 +159,7 @@ static unsigned long tegra_bpmp_clk_recalc_rate(struct clk_hw *hw,
|
||||
|
||||
err = tegra_bpmp_clk_transfer(clk->bpmp, &msg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
return 0;
|
||||
|
||||
return response.rate;
|
||||
}
|
||||
|
||||
@@ -81,7 +81,8 @@ MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device "
|
||||
*
|
||||
* - power condition
|
||||
* Set the power condition field in the START STOP UNIT commands sent by
|
||||
* sd_mod on suspend, resume, and shutdown (if manage_start_stop is on).
|
||||
* sd_mod on suspend, resume, and shutdown (if manage_system_start_stop or
|
||||
* manage_runtime_start_stop is on).
|
||||
* Some disks need this to spin down or to resume properly.
|
||||
*
|
||||
* - override internal blacklist
|
||||
@@ -1517,8 +1518,10 @@ static int sbp2_scsi_slave_configure(struct scsi_device *sdev)
|
||||
|
||||
sdev->use_10_for_rw = 1;
|
||||
|
||||
if (sbp2_param_exclusive_login)
|
||||
sdev->manage_start_stop = 1;
|
||||
if (sbp2_param_exclusive_login) {
|
||||
sdev->manage_system_start_stop = true;
|
||||
sdev->manage_runtime_start_stop = true;
|
||||
}
|
||||
|
||||
if (sdev->type == TYPE_ROM)
|
||||
sdev->use_10_for_ms = 1;
|
||||
|
||||
@@ -397,6 +397,19 @@ static u32 ffa_get_num_pages_sg(struct scatterlist *sg)
|
||||
return num_pages;
|
||||
}
|
||||
|
||||
static u8 ffa_memory_attributes_get(u32 func_id)
|
||||
{
|
||||
/*
|
||||
* For the memory lend or donate operation, if the receiver is a PE or
|
||||
* a proxy endpoint, the owner/sender must not specify the attributes
|
||||
*/
|
||||
if (func_id == FFA_FN_NATIVE(MEM_LEND) ||
|
||||
func_id == FFA_MEM_LEND)
|
||||
return 0;
|
||||
|
||||
return FFA_MEM_NORMAL | FFA_MEM_WRITE_BACK | FFA_MEM_INNER_SHAREABLE;
|
||||
}
|
||||
|
||||
static int
|
||||
ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize,
|
||||
struct ffa_mem_ops_args *args)
|
||||
@@ -413,8 +426,7 @@ ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize,
|
||||
mem_region->tag = args->tag;
|
||||
mem_region->flags = args->flags;
|
||||
mem_region->sender_id = drv_info->vm_id;
|
||||
mem_region->attributes = FFA_MEM_NORMAL | FFA_MEM_WRITE_BACK |
|
||||
FFA_MEM_INNER_SHAREABLE;
|
||||
mem_region->attributes = ffa_memory_attributes_get(func_id);
|
||||
ep_mem_access = &mem_region->ep_mem_access[0];
|
||||
|
||||
for (idx = 0; idx < args->nattrs; idx++, ep_mem_access++) {
|
||||
|
||||
@@ -1080,6 +1080,8 @@ static int scmi_perf_protocol_init(const struct scmi_protocol_handle *ph)
|
||||
if (!pinfo)
|
||||
return -ENOMEM;
|
||||
|
||||
pinfo->version = version;
|
||||
|
||||
ret = scmi_perf_attributes_get(ph, pinfo);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -1104,8 +1106,6 @@ static int scmi_perf_protocol_init(const struct scmi_protocol_handle *ph)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pinfo->version = version;
|
||||
|
||||
return ph->set_priv(ph, pinfo);
|
||||
}
|
||||
|
||||
|
||||
@@ -114,6 +114,7 @@ static int imx_dsp_setup_channels(struct imx_dsp_ipc *dsp_ipc)
|
||||
dsp_chan->idx = i % 2;
|
||||
dsp_chan->ch = mbox_request_channel_byname(cl, chan_name);
|
||||
if (IS_ERR(dsp_chan->ch)) {
|
||||
kfree(dsp_chan->name);
|
||||
ret = PTR_ERR(dsp_chan->ch);
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(dev, "Failed to request mbox chan %s ret %d\n",
|
||||
|
||||
@@ -352,6 +352,7 @@ static int sprd_pmic_eic_probe(struct platform_device *pdev)
|
||||
pmic_eic->chip.set_config = sprd_pmic_eic_set_config;
|
||||
pmic_eic->chip.set = sprd_pmic_eic_set;
|
||||
pmic_eic->chip.get = sprd_pmic_eic_get;
|
||||
pmic_eic->chip.can_sleep = true;
|
||||
|
||||
irq = &pmic_eic->chip.irq;
|
||||
gpio_irq_chip_set_chip(irq, &pmic_eic_irq_chip);
|
||||
|
||||
@@ -43,9 +43,10 @@ static int timbgpio_update_bit(struct gpio_chip *gpio, unsigned index,
|
||||
unsigned offset, bool enabled)
|
||||
{
|
||||
struct timbgpio *tgpio = gpiochip_get_data(gpio);
|
||||
unsigned long flags;
|
||||
u32 reg;
|
||||
|
||||
spin_lock(&tgpio->lock);
|
||||
spin_lock_irqsave(&tgpio->lock, flags);
|
||||
reg = ioread32(tgpio->membase + offset);
|
||||
|
||||
if (enabled)
|
||||
@@ -54,7 +55,7 @@ static int timbgpio_update_bit(struct gpio_chip *gpio, unsigned index,
|
||||
reg &= ~(1 << index);
|
||||
|
||||
iowrite32(reg, tgpio->membase + offset);
|
||||
spin_unlock(&tgpio->lock);
|
||||
spin_unlock_irqrestore(&tgpio->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user