forked from Minki/linux
Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
drivers/net/ethernet/freescale/fec.h7d650df99d
("net: fec: add pm_qos support on imx6q platform")40c79ce13b
("net: fec: add stop mode support for imx8 platform") Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
commit
9f8f1933dc
@ -23,3 +23,4 @@ Block
|
||||
stat
|
||||
switching-sched
|
||||
writeback_cache_control
|
||||
ublk
|
||||
|
253
Documentation/block/ublk.rst
Normal file
253
Documentation/block/ublk.rst
Normal file
@ -0,0 +1,253 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
===========================================
|
||||
Userspace block device driver (ublk driver)
|
||||
===========================================
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
ublk is a generic framework for implementing block device logic from userspace.
|
||||
The motivation behind it is that moving virtual block drivers into userspace,
|
||||
such as loop, nbd and similar can be very helpful. It can help to implement
|
||||
new virtual block device such as ublk-qcow2 (there are several attempts of
|
||||
implementing qcow2 driver in kernel).
|
||||
|
||||
Userspace block devices are attractive because:
|
||||
|
||||
- They can be written many programming languages.
|
||||
- They can use libraries that are not available in the kernel.
|
||||
- They can be debugged with tools familiar to application developers.
|
||||
- Crashes do not kernel panic the machine.
|
||||
- Bugs are likely to have a lower security impact than bugs in kernel
|
||||
code.
|
||||
- They can be installed and updated independently of the kernel.
|
||||
- They can be used to simulate block device easily with user specified
|
||||
parameters/setting for test/debug purpose
|
||||
|
||||
ublk block device (``/dev/ublkb*``) is added by ublk driver. Any IO request
|
||||
on the device will be forwarded to ublk userspace program. For convenience,
|
||||
in this document, ``ublk server`` refers to generic ublk userspace
|
||||
program. ``ublksrv`` [#userspace]_ is one of such implementation. It
|
||||
provides ``libublksrv`` [#userspace_lib]_ library for developing specific
|
||||
user block device conveniently, while also generic type block device is
|
||||
included, such as loop and null. Richard W.M. Jones wrote userspace nbd device
|
||||
``nbdublk`` [#userspace_nbdublk]_ based on ``libublksrv`` [#userspace_lib]_.
|
||||
|
||||
After the IO is handled by userspace, the result is committed back to the
|
||||
driver, thus completing the request cycle. This way, any specific IO handling
|
||||
logic is totally done by userspace, such as loop's IO handling, NBD's IO
|
||||
communication, or qcow2's IO mapping.
|
||||
|
||||
``/dev/ublkb*`` is driven by blk-mq request-based driver. Each request is
|
||||
assigned by one queue wide unique tag. ublk server assigns unique tag to each
|
||||
IO too, which is 1:1 mapped with IO of ``/dev/ublkb*``.
|
||||
|
||||
Both the IO request forward and IO handling result committing are done via
|
||||
``io_uring`` passthrough command; that is why ublk is also one io_uring based
|
||||
block driver. It has been observed that using io_uring passthrough command can
|
||||
give better IOPS than block IO; which is why ublk is one of high performance
|
||||
implementation of userspace block device: not only IO request communication is
|
||||
done by io_uring, but also the preferred IO handling in ublk server is io_uring
|
||||
based approach too.
|
||||
|
||||
ublk provides control interface to set/get ublk block device parameters.
|
||||
The interface is extendable and kabi compatible: basically any ublk request
|
||||
queue's parameter or ublk generic feature parameters can be set/get via the
|
||||
interface. Thus, ublk is generic userspace block device framework.
|
||||
For example, it is easy to setup a ublk device with specified block
|
||||
parameters from userspace.
|
||||
|
||||
Using ublk
|
||||
==========
|
||||
|
||||
ublk requires userspace ublk server to handle real block device logic.
|
||||
|
||||
Below is example of using ``ublksrv`` to provide ublk-based loop device.
|
||||
|
||||
- add a device::
|
||||
|
||||
ublk add -t loop -f ublk-loop.img
|
||||
|
||||
- format with xfs, then use it::
|
||||
|
||||
mkfs.xfs /dev/ublkb0
|
||||
mount /dev/ublkb0 /mnt
|
||||
# do anything. all IOs are handled by io_uring
|
||||
...
|
||||
umount /mnt
|
||||
|
||||
- list the devices with their info::
|
||||
|
||||
ublk list
|
||||
|
||||
- delete the device::
|
||||
|
||||
ublk del -a
|
||||
ublk del -n $ublk_dev_id
|
||||
|
||||
See usage details in README of ``ublksrv`` [#userspace_readme]_.
|
||||
|
||||
Design
|
||||
======
|
||||
|
||||
Control plane
|
||||
-------------
|
||||
|
||||
ublk driver provides global misc device node (``/dev/ublk-control``) for
|
||||
managing and controlling ublk devices with help of several control commands:
|
||||
|
||||
- ``UBLK_CMD_ADD_DEV``
|
||||
|
||||
Add a ublk char device (``/dev/ublkc*``) which is talked with ublk server
|
||||
WRT IO command communication. Basic device info is sent together with this
|
||||
command. It sets UAPI structure of ``ublksrv_ctrl_dev_info``,
|
||||
such as ``nr_hw_queues``, ``queue_depth``, and max IO request buffer size,
|
||||
for which the info is negotiated with the driver and sent back to the server.
|
||||
When this command is completed, the basic device info is immutable.
|
||||
|
||||
- ``UBLK_CMD_SET_PARAMS`` / ``UBLK_CMD_GET_PARAMS``
|
||||
|
||||
Set or get parameters of the device, which can be either generic feature
|
||||
related, or request queue limit related, but can't be IO logic specific,
|
||||
because the driver does not handle any IO logic. This command has to be
|
||||
sent before sending ``UBLK_CMD_START_DEV``.
|
||||
|
||||
- ``UBLK_CMD_START_DEV``
|
||||
|
||||
After the server prepares userspace resources (such as creating per-queue
|
||||
pthread & io_uring for handling ublk IO), this command is sent to the
|
||||
driver for allocating & exposing ``/dev/ublkb*``. Parameters set via
|
||||
``UBLK_CMD_SET_PARAMS`` are applied for creating the device.
|
||||
|
||||
- ``UBLK_CMD_STOP_DEV``
|
||||
|
||||
Halt IO on ``/dev/ublkb*`` and remove the device. When this command returns,
|
||||
ublk server will release resources (such as destroying per-queue pthread &
|
||||
io_uring).
|
||||
|
||||
- ``UBLK_CMD_DEL_DEV``
|
||||
|
||||
Remove ``/dev/ublkc*``. When this command returns, the allocated ublk device
|
||||
number can be reused.
|
||||
|
||||
- ``UBLK_CMD_GET_QUEUE_AFFINITY``
|
||||
|
||||
When ``/dev/ublkc`` is added, the driver creates block layer tagset, so
|
||||
that each queue's affinity info is available. The server sends
|
||||
``UBLK_CMD_GET_QUEUE_AFFINITY`` to retrieve queue affinity info. It can
|
||||
set up the per-queue context efficiently, such as bind affine CPUs with IO
|
||||
pthread and try to allocate buffers in IO thread context.
|
||||
|
||||
- ``UBLK_CMD_GET_DEV_INFO``
|
||||
|
||||
For retrieving device info via ``ublksrv_ctrl_dev_info``. It is the server's
|
||||
responsibility to save IO target specific info in userspace.
|
||||
|
||||
Data plane
|
||||
----------
|
||||
|
||||
ublk server needs to create per-queue IO pthread & io_uring for handling IO
|
||||
commands via io_uring passthrough. The per-queue IO pthread
|
||||
focuses on IO handling and shouldn't handle any control & management
|
||||
tasks.
|
||||
|
||||
The's IO is assigned by a unique tag, which is 1:1 mapping with IO
|
||||
request of ``/dev/ublkb*``.
|
||||
|
||||
UAPI structure of ``ublksrv_io_desc`` is defined for describing each IO from
|
||||
the driver. A fixed mmaped area (array) on ``/dev/ublkc*`` is provided for
|
||||
exporting IO info to the server; such as IO offset, length, OP/flags and
|
||||
buffer address. Each ``ublksrv_io_desc`` instance can be indexed via queue id
|
||||
and IO tag directly.
|
||||
|
||||
The following IO commands are communicated via io_uring passthrough command,
|
||||
and each command is only for forwarding the IO and committing the result
|
||||
with specified IO tag in the command data:
|
||||
|
||||
- ``UBLK_IO_FETCH_REQ``
|
||||
|
||||
Sent from the server IO pthread for fetching future incoming IO requests
|
||||
destined to ``/dev/ublkb*``. This command is sent only once from the server
|
||||
IO pthread for ublk driver to setup IO forward environment.
|
||||
|
||||
- ``UBLK_IO_COMMIT_AND_FETCH_REQ``
|
||||
|
||||
When an IO request is destined to ``/dev/ublkb*``, the driver stores
|
||||
the IO's ``ublksrv_io_desc`` to the specified mapped area; then the
|
||||
previous received IO command of this IO tag (either ``UBLK_IO_FETCH_REQ``
|
||||
or ``UBLK_IO_COMMIT_AND_FETCH_REQ)`` is completed, so the server gets
|
||||
the IO notification via io_uring.
|
||||
|
||||
After the server handles the IO, its result is committed back to the
|
||||
driver by sending ``UBLK_IO_COMMIT_AND_FETCH_REQ`` back. Once ublkdrv
|
||||
received this command, it parses the result and complete the request to
|
||||
``/dev/ublkb*``. In the meantime setup environment for fetching future
|
||||
requests with the same IO tag. That is, ``UBLK_IO_COMMIT_AND_FETCH_REQ``
|
||||
is reused for both fetching request and committing back IO result.
|
||||
|
||||
- ``UBLK_IO_NEED_GET_DATA``
|
||||
|
||||
With ``UBLK_F_NEED_GET_DATA`` enabled, the WRITE request will be firstly
|
||||
issued to ublk server without data copy. Then, IO backend of ublk server
|
||||
receives the request and it can allocate data buffer and embed its addr
|
||||
inside this new io command. After the kernel driver gets the command,
|
||||
data copy is done from request pages to this backend's buffer. Finally,
|
||||
backend receives the request again with data to be written and it can
|
||||
truly handle the request.
|
||||
|
||||
``UBLK_IO_NEED_GET_DATA`` adds one additional round-trip and one
|
||||
io_uring_enter() syscall. Any user thinks that it may lower performance
|
||||
should not enable UBLK_F_NEED_GET_DATA. ublk server pre-allocates IO
|
||||
buffer for each IO by default. Any new project should try to use this
|
||||
buffer to communicate with ublk driver. However, existing project may
|
||||
break or not able to consume the new buffer interface; that's why this
|
||||
command is added for backwards compatibility so that existing projects
|
||||
can still consume existing buffers.
|
||||
|
||||
- data copy between ublk server IO buffer and ublk block IO request
|
||||
|
||||
The driver needs to copy the block IO request pages into the server buffer
|
||||
(pages) first for WRITE before notifying the server of the coming IO, so
|
||||
that the server can handle WRITE request.
|
||||
|
||||
When the server handles READ request and sends
|
||||
``UBLK_IO_COMMIT_AND_FETCH_REQ`` to the server, ublkdrv needs to copy
|
||||
the server buffer (pages) read to the IO request pages.
|
||||
|
||||
Future development
|
||||
==================
|
||||
|
||||
Container-aware ublk deivice
|
||||
----------------------------
|
||||
|
||||
ublk driver doesn't handle any IO logic. Its function is well defined
|
||||
for now and very limited userspace interfaces are needed, which is also
|
||||
well defined too. It is possible to make ublk devices container-aware block
|
||||
devices in future as Stefan Hajnoczi suggested [#stefan]_, by removing
|
||||
ADMIN privilege.
|
||||
|
||||
Zero copy
|
||||
---------
|
||||
|
||||
Zero copy is a generic requirement for nbd, fuse or similar drivers. A
|
||||
problem [#xiaoguang]_ Xiaoguang mentioned is that pages mapped to userspace
|
||||
can't be remapped any more in kernel with existing mm interfaces. This can
|
||||
occurs when destining direct IO to ``/dev/ublkb*``. Also, he reported that
|
||||
big requests (IO size >= 256 KB) may benefit a lot from zero copy.
|
||||
|
||||
|
||||
References
|
||||
==========
|
||||
|
||||
.. [#userspace] https://github.com/ming1/ubdsrv
|
||||
|
||||
.. [#userspace_lib] https://github.com/ming1/ubdsrv/tree/master/lib
|
||||
|
||||
.. [#userspace_nbdublk] https://gitlab.com/rwmjones/libnbd/-/tree/nbdublk
|
||||
|
||||
.. [#userspace_readme] https://github.com/ming1/ubdsrv/blob/master/README
|
||||
|
||||
.. [#stefan] https://lore.kernel.org/linux-block/YoOr6jBfgVm8GvWg@stefanha-x1.localdomain/
|
||||
|
||||
.. [#xiaoguang] https://lore.kernel.org/linux-block/YoOr6jBfgVm8GvWg@stefanha-x1.localdomain/
|
@ -24,8 +24,10 @@ properties:
|
||||
|
||||
interrupts:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
description:
|
||||
Should be configured with type IRQ_TYPE_EDGE_RISING.
|
||||
If two interrupts are provided, expected order is INT1 and INT2.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
@ -16,6 +16,7 @@ properties:
|
||||
compatible:
|
||||
enum:
|
||||
- goodix,gt1151
|
||||
- goodix,gt1158
|
||||
- goodix,gt5663
|
||||
- goodix,gt5688
|
||||
- goodix,gt911
|
||||
|
@ -24,6 +24,7 @@ properties:
|
||||
- mediatek,mt2712-mtu3
|
||||
- mediatek,mt8173-mtu3
|
||||
- mediatek,mt8183-mtu3
|
||||
- mediatek,mt8188-mtu3
|
||||
- mediatek,mt8192-mtu3
|
||||
- mediatek,mt8195-mtu3
|
||||
- const: mediatek,mtu3
|
||||
|
@ -33,6 +33,7 @@ properties:
|
||||
- qcom,sm6115-dwc3
|
||||
- qcom,sm6125-dwc3
|
||||
- qcom,sm6350-dwc3
|
||||
- qcom,sm6375-dwc3
|
||||
- qcom,sm8150-dwc3
|
||||
- qcom,sm8250-dwc3
|
||||
- qcom,sm8350-dwc3
|
||||
@ -108,12 +109,17 @@ properties:
|
||||
HS/FS/LS modes are supported.
|
||||
type: boolean
|
||||
|
||||
wakeup-source: true
|
||||
|
||||
# Required child node:
|
||||
|
||||
patternProperties:
|
||||
"^usb@[0-9a-f]+$":
|
||||
$ref: snps,dwc3.yaml#
|
||||
|
||||
properties:
|
||||
wakeup-source: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
@ -517,6 +517,7 @@ All I-Force devices are supported by the iforce module. This includes:
|
||||
* AVB Mag Turbo Force
|
||||
* AVB Top Shot Pegasus
|
||||
* AVB Top Shot Force Feedback Racing Wheel
|
||||
* Boeder Force Feedback Wheel
|
||||
* Logitech WingMan Force
|
||||
* Logitech WingMan Force Wheel
|
||||
* Guillemot Race Leader Force Feedback
|
||||
|
@ -1055,17 +1055,6 @@ The kernel interface functions are as follows:
|
||||
first function to change. Note that this must be called in TASK_RUNNING
|
||||
state.
|
||||
|
||||
(#) Get reply timestamp::
|
||||
|
||||
bool rxrpc_kernel_get_reply_time(struct socket *sock,
|
||||
struct rxrpc_call *call,
|
||||
ktime_t *_ts)
|
||||
|
||||
This allows the timestamp on the first DATA packet of the reply of a
|
||||
client call to be queried, provided that it is still in the Rx ring. If
|
||||
successful, the timestamp will be stored into ``*_ts`` and true will be
|
||||
returned; false will be returned otherwise.
|
||||
|
||||
(#) Get remote client epoch::
|
||||
|
||||
u32 rxrpc_kernel_get_epoch(struct socket *sock,
|
||||
|
14
MAINTAINERS
14
MAINTAINERS
@ -10032,6 +10032,7 @@ F: Documentation/devicetree/bindings/input/
|
||||
F: Documentation/devicetree/bindings/serio/
|
||||
F: Documentation/input/
|
||||
F: drivers/input/
|
||||
F: include/dt-bindings/input/
|
||||
F: include/linux/input.h
|
||||
F: include/linux/input/
|
||||
F: include/uapi/linux/input-event-codes.h
|
||||
@ -17531,9 +17532,19 @@ M: Conor Dooley <conor.dooley@microchip.com>
|
||||
M: Daire McNamara <daire.mcnamara@microchip.com>
|
||||
L: linux-riscv@lists.infradead.org
|
||||
S: Supported
|
||||
F: Documentation/devicetree/bindings/clock/microchip,mpfs.yaml
|
||||
F: Documentation/devicetree/bindings/gpio/microchip,mpfs-gpio.yaml
|
||||
F: Documentation/devicetree/bindings/i2c/microchip,corei2c.yaml
|
||||
F: Documentation/devicetree/bindings/mailbox/microchip,mpfs-mailbox.yaml
|
||||
F: Documentation/devicetree/bindings/net/can/microchip,mpfs-can.yaml
|
||||
F: Documentation/devicetree/bindings/pwm/microchip,corepwm.yaml
|
||||
F: Documentation/devicetree/bindings/soc/microchip/microchip,mpfs-sys-controller.yaml
|
||||
F: Documentation/devicetree/bindings/spi/microchip,mpfs-spi.yaml
|
||||
F: Documentation/devicetree/bindings/usb/microchip,mpfs-musb.yaml
|
||||
F: arch/riscv/boot/dts/microchip/
|
||||
F: drivers/char/hw_random/mpfs-rng.c
|
||||
F: drivers/clk/microchip/clk-mpfs.c
|
||||
F: drivers/i2c/busses/i2c-microchip-core.c
|
||||
F: drivers/mailbox/mailbox-mpfs.c
|
||||
F: drivers/pci/controller/pcie-microchip-host.c
|
||||
F: drivers/rtc/rtc-mpfs.c
|
||||
@ -20764,6 +20775,7 @@ UBLK USERSPACE BLOCK DRIVER
|
||||
M: Ming Lei <ming.lei@redhat.com>
|
||||
L: linux-block@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/block/ublk.rst
|
||||
F: drivers/block/ublk_drv.c
|
||||
F: include/uapi/linux/ublk_cmd.h
|
||||
|
||||
@ -22307,7 +22319,7 @@ M: Shubhrajyoti Datta <shubhrajyoti.datta@xilinx.com>
|
||||
R: Srinivas Neeli <srinivas.neeli@xilinx.com>
|
||||
R: Michal Simek <michal.simek@xilinx.com>
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/gpio/gpio-xilinx.txt
|
||||
F: Documentation/devicetree/bindings/gpio/xlnx,gpio-xilinx.yaml
|
||||
F: Documentation/devicetree/bindings/gpio/gpio-zynq.yaml
|
||||
F: drivers/gpio/gpio-xilinx.c
|
||||
F: drivers/gpio/gpio-zynq.c
|
||||
|
2
Makefile
2
Makefile
@ -2,7 +2,7 @@
|
||||
VERSION = 6
|
||||
PATCHLEVEL = 0
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc3
|
||||
EXTRAVERSION = -rc4
|
||||
NAME = Hurr durr I'ma ninja sloth
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
@ -399,7 +399,7 @@
|
||||
compatible = "arm,pl022", "arm,primecell";
|
||||
reg = <0x1000d000 0x1000>;
|
||||
clocks = <&sspclk>, <&pclk>;
|
||||
clock-names = "SSPCLK", "apb_pclk";
|
||||
clock-names = "sspclk", "apb_pclk";
|
||||
};
|
||||
|
||||
wdog: watchdog@10010000 {
|
||||
|
@ -410,7 +410,7 @@
|
||||
interrupt-parent = <&intc_dc1176>;
|
||||
interrupts = <0 17 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&sspclk>, <&pclk>;
|
||||
clock-names = "SSPCLK", "apb_pclk";
|
||||
clock-names = "sspclk", "apb_pclk";
|
||||
};
|
||||
|
||||
pb1176_serial0: serial@1010c000 {
|
||||
|
@ -555,7 +555,7 @@
|
||||
interrupt-parent = <&intc_pb11mp>;
|
||||
interrupts = <0 11 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&sspclk>, <&pclk>;
|
||||
clock-names = "SSPCLK", "apb_pclk";
|
||||
clock-names = "sspclk", "apb_pclk";
|
||||
};
|
||||
|
||||
watchdog@1000f000 {
|
||||
|
@ -390,7 +390,7 @@
|
||||
compatible = "arm,pl022", "arm,primecell";
|
||||
reg = <0x1000d000 0x1000>;
|
||||
clocks = <&sspclk>, <&pclk>;
|
||||
clock-names = "SSPCLK", "apb_pclk";
|
||||
clock-names = "sspclk", "apb_pclk";
|
||||
};
|
||||
|
||||
wdog0: watchdog@1000f000 {
|
||||
|
@ -76,8 +76,8 @@
|
||||
regulators {
|
||||
vdd_3v3: VDD_IO {
|
||||
regulator-name = "VDD_IO";
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <3700000>;
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-initial-mode = <2>;
|
||||
regulator-allowed-modes = <2>, <4>;
|
||||
regulator-always-on;
|
||||
@ -95,8 +95,8 @@
|
||||
|
||||
vddio_ddr: VDD_DDR {
|
||||
regulator-name = "VDD_DDR";
|
||||
regulator-min-microvolt = <600000>;
|
||||
regulator-max-microvolt = <1850000>;
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <1200000>;
|
||||
regulator-initial-mode = <2>;
|
||||
regulator-allowed-modes = <2>, <4>;
|
||||
regulator-always-on;
|
||||
@ -118,8 +118,8 @@
|
||||
|
||||
vdd_core: VDD_CORE {
|
||||
regulator-name = "VDD_CORE";
|
||||
regulator-min-microvolt = <600000>;
|
||||
regulator-max-microvolt = <1850000>;
|
||||
regulator-min-microvolt = <1250000>;
|
||||
regulator-max-microvolt = <1250000>;
|
||||
regulator-initial-mode = <2>;
|
||||
regulator-allowed-modes = <2>, <4>;
|
||||
regulator-always-on;
|
||||
@ -160,8 +160,8 @@
|
||||
|
||||
LDO1 {
|
||||
regulator-name = "LDO1";
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <3700000>;
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-always-on;
|
||||
|
||||
regulator-state-standby {
|
||||
@ -175,9 +175,8 @@
|
||||
|
||||
LDO2 {
|
||||
regulator-name = "LDO2";
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <3700000>;
|
||||
regulator-always-on;
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
|
||||
regulator-state-standby {
|
||||
regulator-on-in-suspend;
|
||||
|
@ -196,8 +196,8 @@
|
||||
regulators {
|
||||
vdd_io_reg: VDD_IO {
|
||||
regulator-name = "VDD_IO";
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <3700000>;
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-initial-mode = <2>;
|
||||
regulator-allowed-modes = <2>, <4>;
|
||||
regulator-always-on;
|
||||
@ -215,8 +215,8 @@
|
||||
|
||||
VDD_DDR {
|
||||
regulator-name = "VDD_DDR";
|
||||
regulator-min-microvolt = <600000>;
|
||||
regulator-max-microvolt = <1850000>;
|
||||
regulator-min-microvolt = <1350000>;
|
||||
regulator-max-microvolt = <1350000>;
|
||||
regulator-initial-mode = <2>;
|
||||
regulator-allowed-modes = <2>, <4>;
|
||||
regulator-always-on;
|
||||
@ -234,8 +234,8 @@
|
||||
|
||||
VDD_CORE {
|
||||
regulator-name = "VDD_CORE";
|
||||
regulator-min-microvolt = <600000>;
|
||||
regulator-max-microvolt = <1850000>;
|
||||
regulator-min-microvolt = <1250000>;
|
||||
regulator-max-microvolt = <1250000>;
|
||||
regulator-initial-mode = <2>;
|
||||
regulator-allowed-modes = <2>, <4>;
|
||||
regulator-always-on;
|
||||
@ -257,7 +257,6 @@
|
||||
regulator-max-microvolt = <1850000>;
|
||||
regulator-initial-mode = <2>;
|
||||
regulator-allowed-modes = <2>, <4>;
|
||||
regulator-always-on;
|
||||
|
||||
regulator-state-standby {
|
||||
regulator-on-in-suspend;
|
||||
@ -272,8 +271,8 @@
|
||||
|
||||
LDO1 {
|
||||
regulator-name = "LDO1";
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <3700000>;
|
||||
regulator-min-microvolt = <2500000>;
|
||||
regulator-max-microvolt = <2500000>;
|
||||
regulator-always-on;
|
||||
|
||||
regulator-state-standby {
|
||||
@ -287,8 +286,8 @@
|
||||
|
||||
LDO2 {
|
||||
regulator-name = "LDO2";
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <3700000>;
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-always-on;
|
||||
|
||||
regulator-state-standby {
|
||||
|
@ -244,8 +244,8 @@
|
||||
regulators {
|
||||
vdd_3v3: VDD_IO {
|
||||
regulator-name = "VDD_IO";
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <3700000>;
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-initial-mode = <2>;
|
||||
regulator-allowed-modes = <2>, <4>;
|
||||
regulator-always-on;
|
||||
@ -264,8 +264,8 @@
|
||||
|
||||
vddioddr: VDD_DDR {
|
||||
regulator-name = "VDD_DDR";
|
||||
regulator-min-microvolt = <1300000>;
|
||||
regulator-max-microvolt = <1450000>;
|
||||
regulator-min-microvolt = <1350000>;
|
||||
regulator-max-microvolt = <1350000>;
|
||||
regulator-initial-mode = <2>;
|
||||
regulator-allowed-modes = <2>, <4>;
|
||||
regulator-always-on;
|
||||
@ -285,8 +285,8 @@
|
||||
|
||||
vddcore: VDD_CORE {
|
||||
regulator-name = "VDD_CORE";
|
||||
regulator-min-microvolt = <1100000>;
|
||||
regulator-max-microvolt = <1850000>;
|
||||
regulator-min-microvolt = <1150000>;
|
||||
regulator-max-microvolt = <1150000>;
|
||||
regulator-initial-mode = <2>;
|
||||
regulator-allowed-modes = <2>, <4>;
|
||||
regulator-always-on;
|
||||
@ -306,7 +306,7 @@
|
||||
vddcpu: VDD_OTHER {
|
||||
regulator-name = "VDD_OTHER";
|
||||
regulator-min-microvolt = <1050000>;
|
||||
regulator-max-microvolt = <1850000>;
|
||||
regulator-max-microvolt = <1250000>;
|
||||
regulator-initial-mode = <2>;
|
||||
regulator-allowed-modes = <2>, <4>;
|
||||
regulator-ramp-delay = <3125>;
|
||||
@ -326,8 +326,8 @@
|
||||
|
||||
vldo1: LDO1 {
|
||||
regulator-name = "LDO1";
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <3700000>;
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
regulator-always-on;
|
||||
|
||||
regulator-state-standby {
|
||||
|
@ -32,6 +32,7 @@
|
||||
next-level-cache = <&L2_0>;
|
||||
enable-method = "psci";
|
||||
};
|
||||
|
||||
CA7_2: cpu@2 {
|
||||
device_type = "cpu";
|
||||
compatible = "arm,cortex-a7";
|
||||
@ -39,6 +40,7 @@
|
||||
next-level-cache = <&L2_0>;
|
||||
enable-method = "psci";
|
||||
};
|
||||
|
||||
L2_0: l2-cache0 {
|
||||
compatible = "cache";
|
||||
};
|
||||
@ -46,10 +48,10 @@
|
||||
|
||||
timer {
|
||||
compatible = "arm,armv7-timer";
|
||||
interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
|
||||
<GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
|
||||
<GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
|
||||
<GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
|
||||
interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(3) | IRQ_TYPE_LEVEL_LOW)>,
|
||||
<GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(3) | IRQ_TYPE_LEVEL_LOW)>,
|
||||
<GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(3) | IRQ_TYPE_LEVEL_LOW)>,
|
||||
<GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(3) | IRQ_TYPE_LEVEL_LOW)>;
|
||||
arm,cpu-registers-not-fw-configured;
|
||||
};
|
||||
|
||||
@ -80,23 +82,23 @@
|
||||
psci {
|
||||
compatible = "arm,psci-0.2";
|
||||
method = "smc";
|
||||
cpu_off = <1>;
|
||||
cpu_on = <2>;
|
||||
};
|
||||
|
||||
axi@81000000 {
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0 0x81000000 0x4000>;
|
||||
ranges = <0 0x81000000 0x8000>;
|
||||
|
||||
gic: interrupt-controller@1000 {
|
||||
compatible = "arm,cortex-a7-gic";
|
||||
#interrupt-cells = <3>;
|
||||
#address-cells = <0>;
|
||||
interrupt-controller;
|
||||
interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(3) | IRQ_TYPE_LEVEL_HIGH)>;
|
||||
reg = <0x1000 0x1000>,
|
||||
<0x2000 0x2000>;
|
||||
<0x2000 0x2000>,
|
||||
<0x4000 0x2000>,
|
||||
<0x6000 0x2000>;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -40,10 +40,10 @@
|
||||
|
||||
timer {
|
||||
compatible = "arm,armv7-timer";
|
||||
interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
|
||||
<GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
|
||||
<GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
|
||||
<GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
|
||||
interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
|
||||
<GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
|
||||
<GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
|
||||
<GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
|
||||
arm,cpu-registers-not-fw-configured;
|
||||
};
|
||||
|
||||
@ -65,23 +65,23 @@
|
||||
psci {
|
||||
compatible = "arm,psci-0.2";
|
||||
method = "smc";
|
||||
cpu_off = <1>;
|
||||
cpu_on = <2>;
|
||||
};
|
||||
|
||||
axi@81000000 {
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0 0x81000000 0x4000>;
|
||||
ranges = <0 0x81000000 0x8000>;
|
||||
|
||||
gic: interrupt-controller@1000 {
|
||||
compatible = "arm,cortex-a7-gic";
|
||||
#interrupt-cells = <3>;
|
||||
#address-cells = <0>;
|
||||
interrupt-controller;
|
||||
interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
|
||||
reg = <0x1000 0x1000>,
|
||||
<0x2000 0x2000>;
|
||||
<0x2000 0x2000>,
|
||||
<0x4000 0x2000>,
|
||||
<0x6000 0x2000>;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
||||
next-level-cache = <&L2_0>;
|
||||
enable-method = "psci";
|
||||
};
|
||||
|
||||
L2_0: l2-cache0 {
|
||||
compatible = "cache";
|
||||
};
|
||||
@ -39,10 +40,10 @@
|
||||
|
||||
timer {
|
||||
compatible = "arm,armv7-timer";
|
||||
interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
|
||||
<GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
|
||||
<GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
|
||||
<GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
|
||||
interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
|
||||
<GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
|
||||
<GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
|
||||
<GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
|
||||
arm,cpu-registers-not-fw-configured;
|
||||
};
|
||||
|
||||
|
@ -51,16 +51,6 @@
|
||||
vin-supply = <®_3p3v_s5>;
|
||||
};
|
||||
|
||||
reg_3p3v_s0: regulator-3p3v-s0 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "V_3V3_S0";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
vin-supply = <®_3p3v_s5>;
|
||||
};
|
||||
|
||||
reg_3p3v_s5: regulator-3p3v-s5 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "V_3V3_S5";
|
||||
@ -259,7 +249,7 @@
|
||||
|
||||
/* default boot source: workaround #1 for errata ERR006282 */
|
||||
smarc_flash: flash@0 {
|
||||
compatible = "winbond,w25q16dw", "jedec,spi-nor";
|
||||
compatible = "jedec,spi-nor";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <20000000>;
|
||||
};
|
||||
|
@ -28,7 +28,7 @@
|
||||
enable-gpios = <&gpio4 28 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
backlight_led: backlight_led {
|
||||
backlight_led: backlight-led {
|
||||
compatible = "pwm-backlight";
|
||||
pwms = <&pwm3 0 5000000 0>;
|
||||
brightness-levels = <0 16 64 255>;
|
||||
|
@ -178,12 +178,12 @@
|
||||
clock-names = "uartclk", "apb_pclk";
|
||||
};
|
||||
|
||||
ssp@300000 {
|
||||
spi@300000 {
|
||||
compatible = "arm,pl022", "arm,primecell";
|
||||
reg = <0x00300000 0x1000>;
|
||||
interrupts-extended = <&impd1_vic 3>;
|
||||
clocks = <&impd1_sspclk>, <&sysclk>;
|
||||
clock-names = "spiclk", "apb_pclk";
|
||||
clock-names = "sspclk", "apb_pclk";
|
||||
};
|
||||
|
||||
impd1_gpio0: gpio@400000 {
|
||||
|
@ -391,7 +391,7 @@
|
||||
reg = <0x101f4000 0x1000>;
|
||||
interrupts = <11>;
|
||||
clocks = <&xtal24mhz>, <&pclk>;
|
||||
clock-names = "SSPCLK", "apb_pclk";
|
||||
clock-names = "sspclk", "apb_pclk";
|
||||
};
|
||||
|
||||
fpga {
|
||||
|
@ -196,7 +196,6 @@ CONFIG_RTC_DRV_AT91SAM9=y
|
||||
CONFIG_DMADEVICES=y
|
||||
CONFIG_AT_HDMAC=y
|
||||
CONFIG_AT_XDMAC=y
|
||||
CONFIG_MICROCHIP_PIT64B=y
|
||||
# CONFIG_IOMMU_SUPPORT is not set
|
||||
CONFIG_IIO=y
|
||||
CONFIG_AT91_ADC=y
|
||||
|
@ -188,7 +188,6 @@ CONFIG_RTC_DRV_AT91SAM9=y
|
||||
CONFIG_DMADEVICES=y
|
||||
CONFIG_AT_XDMAC=y
|
||||
CONFIG_STAGING=y
|
||||
CONFIG_MICROCHIP_PIT64B=y
|
||||
# CONFIG_IOMMU_SUPPORT is not set
|
||||
CONFIG_IIO=y
|
||||
CONFIG_IIO_SW_TRIGGER=y
|
||||
|
@ -541,9 +541,41 @@ extern u32 at91_pm_suspend_in_sram_sz;
|
||||
|
||||
static int at91_suspend_finish(unsigned long val)
|
||||
{
|
||||
unsigned char modified_gray_code[] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05, 0x0c, 0x0d,
|
||||
0x0e, 0x0f, 0x0a, 0x0b, 0x08, 0x09, 0x18, 0x19, 0x1a, 0x1b,
|
||||
0x1e, 0x1f, 0x1c, 0x1d, 0x14, 0x15, 0x16, 0x17, 0x12, 0x13,
|
||||
0x10, 0x11,
|
||||
};
|
||||
unsigned int tmp, index;
|
||||
int i;
|
||||
|
||||
if (soc_pm.data.mode == AT91_PM_BACKUP && soc_pm.data.ramc_phy) {
|
||||
/*
|
||||
* Bootloader will perform DDR recalibration and will try to
|
||||
* restore the ZQ0SR0 with the value saved here. But the
|
||||
* calibration is buggy and restoring some values from ZQ0SR0
|
||||
* is forbidden and risky thus we need to provide processed
|
||||
* values for these (modified gray code values).
|
||||
*/
|
||||
tmp = readl(soc_pm.data.ramc_phy + DDR3PHY_ZQ0SR0);
|
||||
|
||||
/* Store pull-down output impedance select. */
|
||||
index = (tmp >> DDR3PHY_ZQ0SR0_PDO_OFF) & 0x1f;
|
||||
soc_pm.bu->ddr_phy_calibration[0] = modified_gray_code[index];
|
||||
|
||||
/* Store pull-up output impedance select. */
|
||||
index = (tmp >> DDR3PHY_ZQ0SR0_PUO_OFF) & 0x1f;
|
||||
soc_pm.bu->ddr_phy_calibration[0] |= modified_gray_code[index];
|
||||
|
||||
/* Store pull-down on-die termination impedance select. */
|
||||
index = (tmp >> DDR3PHY_ZQ0SR0_PDODT_OFF) & 0x1f;
|
||||
soc_pm.bu->ddr_phy_calibration[0] |= modified_gray_code[index];
|
||||
|
||||
/* Store pull-up on-die termination impedance select. */
|
||||
index = (tmp >> DDR3PHY_ZQ0SRO_PUODT_OFF) & 0x1f;
|
||||
soc_pm.bu->ddr_phy_calibration[0] |= modified_gray_code[index];
|
||||
|
||||
/*
|
||||
* The 1st 8 words of memory might get corrupted in the process
|
||||
* of DDR PHY recalibration; it is saved here in securam and it
|
||||
@ -1066,10 +1098,6 @@ static int __init at91_pm_backup_init(void)
|
||||
of_scan_flat_dt(at91_pm_backup_scan_memcs, &located);
|
||||
if (!located)
|
||||
goto securam_fail;
|
||||
|
||||
/* DDR3PHY_ZQ0SR0 */
|
||||
soc_pm.bu->ddr_phy_calibration[0] = readl(soc_pm.data.ramc_phy +
|
||||
0x188);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -172,9 +172,15 @@ sr_ena_2:
|
||||
/* Put DDR PHY's DLL in bypass mode for non-backup modes. */
|
||||
cmp r7, #AT91_PM_BACKUP
|
||||
beq sr_ena_3
|
||||
ldr tmp1, [r3, #DDR3PHY_PIR]
|
||||
orr tmp1, tmp1, #DDR3PHY_PIR_DLLBYP
|
||||
str tmp1, [r3, #DDR3PHY_PIR]
|
||||
|
||||
/* Disable DX DLLs. */
|
||||
ldr tmp1, [r3, #DDR3PHY_DX0DLLCR]
|
||||
orr tmp1, tmp1, #DDR3PHY_DXDLLCR_DLLDIS
|
||||
str tmp1, [r3, #DDR3PHY_DX0DLLCR]
|
||||
|
||||
ldr tmp1, [r3, #DDR3PHY_DX1DLLCR]
|
||||
orr tmp1, tmp1, #DDR3PHY_DXDLLCR_DLLDIS
|
||||
str tmp1, [r3, #DDR3PHY_DX1DLLCR]
|
||||
|
||||
sr_ena_3:
|
||||
/* Power down DDR PHY data receivers. */
|
||||
@ -221,10 +227,14 @@ sr_ena_3:
|
||||
bic tmp1, tmp1, #DDR3PHY_DSGCR_ODTPDD_ODT0
|
||||
str tmp1, [r3, #DDR3PHY_DSGCR]
|
||||
|
||||
/* Take DDR PHY's DLL out of bypass mode. */
|
||||
ldr tmp1, [r3, #DDR3PHY_PIR]
|
||||
bic tmp1, tmp1, #DDR3PHY_PIR_DLLBYP
|
||||
str tmp1, [r3, #DDR3PHY_PIR]
|
||||
/* Enable DX DLLs. */
|
||||
ldr tmp1, [r3, #DDR3PHY_DX0DLLCR]
|
||||
bic tmp1, tmp1, #DDR3PHY_DXDLLCR_DLLDIS
|
||||
str tmp1, [r3, #DDR3PHY_DX0DLLCR]
|
||||
|
||||
ldr tmp1, [r3, #DDR3PHY_DX1DLLCR]
|
||||
bic tmp1, tmp1, #DDR3PHY_DXDLLCR_DLLDIS
|
||||
str tmp1, [r3, #DDR3PHY_DX1DLLCR]
|
||||
|
||||
/* Enable quasi-dynamic programming. */
|
||||
mov tmp1, #0
|
||||
|
@ -46,7 +46,7 @@ static void __init ixp4xx_of_map_io(void)
|
||||
}
|
||||
|
||||
/*
|
||||
* We handle 4 differen SoC families. These compatible strings are enough
|
||||
* We handle 4 different SoC families. These compatible strings are enough
|
||||
* to provide the core so that different boards can add their more detailed
|
||||
* specifics.
|
||||
*/
|
||||
|
@ -26,7 +26,8 @@
|
||||
compatible = "arm,mhu", "arm,primecell";
|
||||
reg = <0x0 0x2b1f0000 0x0 0x1000>;
|
||||
interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
|
||||
<GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#mbox-cells = <1>;
|
||||
clocks = <&soc_refclk100mhz>;
|
||||
clock-names = "apb_pclk";
|
||||
|
@ -67,7 +67,6 @@
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
csys2_funnel_in_port0: endpoint {
|
||||
slave-mode;
|
||||
remote-endpoint = <&etf0_out_port>;
|
||||
};
|
||||
};
|
||||
@ -75,7 +74,6 @@
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
csys2_funnel_in_port1: endpoint {
|
||||
slave-mode;
|
||||
remote-endpoint = <&etf1_out_port>;
|
||||
};
|
||||
};
|
||||
|
@ -25,7 +25,6 @@
|
||||
&enetc_port0 {
|
||||
phy-handle = <&slot1_sgmii>;
|
||||
phy-mode = "2500base-x";
|
||||
managed = "in-band-status";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
|
@ -626,24 +626,28 @@
|
||||
lan1: port@0 {
|
||||
reg = <0>;
|
||||
label = "lan1";
|
||||
phy-mode = "internal";
|
||||
local-mac-address = [00 00 00 00 00 00];
|
||||
};
|
||||
|
||||
lan2: port@1 {
|
||||
reg = <1>;
|
||||
label = "lan2";
|
||||
phy-mode = "internal";
|
||||
local-mac-address = [00 00 00 00 00 00];
|
||||
};
|
||||
|
||||
lan3: port@2 {
|
||||
reg = <2>;
|
||||
label = "lan3";
|
||||
phy-mode = "internal";
|
||||
local-mac-address = [00 00 00 00 00 00];
|
||||
};
|
||||
|
||||
lan4: port@3 {
|
||||
reg = <3>;
|
||||
label = "lan4";
|
||||
phy-mode = "internal";
|
||||
local-mac-address = [00 00 00 00 00 00];
|
||||
};
|
||||
|
||||
|
@ -32,10 +32,10 @@
|
||||
};
|
||||
|
||||
/* Fixed clock dedicated to SPI CAN controller */
|
||||
clk20m: oscillator {
|
||||
clk40m: oscillator {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <20000000>;
|
||||
clock-frequency = <40000000>;
|
||||
};
|
||||
|
||||
gpio-keys {
|
||||
@ -202,8 +202,8 @@
|
||||
|
||||
can1: can@0 {
|
||||
compatible = "microchip,mcp251xfd";
|
||||
clocks = <&clk20m>;
|
||||
interrupts-extended = <&gpio1 6 IRQ_TYPE_EDGE_FALLING>;
|
||||
clocks = <&clk40m>;
|
||||
interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_LOW>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_can1_int>;
|
||||
reg = <0>;
|
||||
@ -603,7 +603,7 @@
|
||||
pinctrl-0 = <&pinctrl_gpio_9_dsi>, <&pinctrl_i2s_2_bclk_touch_reset>;
|
||||
reg = <0x4a>;
|
||||
/* Verdin I2S_2_BCLK (TOUCH_RESET#, SODIMM 42) */
|
||||
reset-gpios = <&gpio3 23 GPIO_ACTIVE_HIGH>;
|
||||
reset-gpios = <&gpio3 23 GPIO_ACTIVE_LOW>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
@ -745,6 +745,7 @@
|
||||
};
|
||||
|
||||
&usbphynop2 {
|
||||
power-domains = <&pgc_otg2>;
|
||||
vcc-supply = <®_vdd_3v3>;
|
||||
};
|
||||
|
||||
|
@ -70,7 +70,7 @@
|
||||
&ecspi1 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_ecspi1>;
|
||||
cs-gpios = <&gpio5 9 GPIO_ACTIVE_LOW>;
|
||||
cs-gpios = <&gpio5 17 GPIO_ACTIVE_LOW>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
@ -403,8 +403,8 @@
|
||||
pinctrl-names = "default", "gpio";
|
||||
pinctrl-0 = <&pinctrl_i2c5>;
|
||||
pinctrl-1 = <&pinctrl_i2c5_gpio>;
|
||||
scl-gpios = <&gpio5 26 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
sda-gpios = <&gpio5 27 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
scl-gpios = <&gpio3 26 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
sda-gpios = <&gpio3 27 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
@ -648,10 +648,10 @@
|
||||
|
||||
pinctrl_ecspi1: dhcom-ecspi1-grp {
|
||||
fsl,pins = <
|
||||
MX8MP_IOMUXC_ECSPI1_SCLK__ECSPI1_SCLK 0x44
|
||||
MX8MP_IOMUXC_ECSPI1_MOSI__ECSPI1_MOSI 0x44
|
||||
MX8MP_IOMUXC_ECSPI1_MISO__ECSPI1_MISO 0x44
|
||||
MX8MP_IOMUXC_ECSPI1_SS0__GPIO5_IO09 0x40
|
||||
MX8MP_IOMUXC_I2C1_SCL__ECSPI1_SCLK 0x44
|
||||
MX8MP_IOMUXC_I2C1_SDA__ECSPI1_MOSI 0x44
|
||||
MX8MP_IOMUXC_I2C2_SCL__ECSPI1_MISO 0x44
|
||||
MX8MP_IOMUXC_I2C2_SDA__GPIO5_IO17 0x40
|
||||
>;
|
||||
};
|
||||
|
||||
|
@ -770,10 +770,10 @@
|
||||
|
||||
pinctrl_sai2: sai2grp {
|
||||
fsl,pins = <
|
||||
MX8MP_IOMUXC_SAI2_TXFS__AUDIOMIX_SAI2_TX_SYNC
|
||||
MX8MP_IOMUXC_SAI2_TXD0__AUDIOMIX_SAI2_TX_DATA00
|
||||
MX8MP_IOMUXC_SAI2_TXC__AUDIOMIX_SAI2_TX_BCLK
|
||||
MX8MP_IOMUXC_SAI2_MCLK__AUDIOMIX_SAI2_MCLK
|
||||
MX8MP_IOMUXC_SAI2_TXFS__AUDIOMIX_SAI2_TX_SYNC 0xd6
|
||||
MX8MP_IOMUXC_SAI2_TXD0__AUDIOMIX_SAI2_TX_DATA00 0xd6
|
||||
MX8MP_IOMUXC_SAI2_TXC__AUDIOMIX_SAI2_TX_BCLK 0xd6
|
||||
MX8MP_IOMUXC_SAI2_MCLK__AUDIOMIX_SAI2_MCLK 0xd6
|
||||
>;
|
||||
};
|
||||
|
||||
|
@ -628,7 +628,7 @@
|
||||
interrupts = <5 IRQ_TYPE_EDGE_FALLING>;
|
||||
reg = <0x4a>;
|
||||
/* Verdin GPIO_2 (SODIMM 208) */
|
||||
reset-gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>;
|
||||
reset-gpios = <&gpio1 1 GPIO_ACTIVE_LOW>;
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
@ -705,7 +705,7 @@
|
||||
pinctrl-0 = <&pinctrl_gpio_9_dsi>, <&pinctrl_i2s_2_bclk_touch_reset>;
|
||||
reg = <0x4a>;
|
||||
/* Verdin I2S_2_BCLK (TOUCH_RESET#, SODIMM 42) */
|
||||
reset-gpios = <&gpio5 0 GPIO_ACTIVE_HIGH>;
|
||||
reset-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
@ -204,7 +204,6 @@
|
||||
reg = <0x51>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_rtc>;
|
||||
interrupt-names = "irq";
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <1 IRQ_TYPE_EDGE_FALLING>;
|
||||
quartz-load-femtofarads = <7000>;
|
||||
|
@ -85,7 +85,7 @@
|
||||
"renesas,rcar-gen4-hscif",
|
||||
"renesas,hscif";
|
||||
reg = <0 0xe6540000 0 96>;
|
||||
interrupts = <GIC_SPI 245 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupts = <GIC_SPI 246 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&cpg CPG_MOD 514>,
|
||||
<&cpg CPG_CORE R8A779G0_CLK_S0D3_PER>,
|
||||
<&scif_clk>;
|
||||
|
@ -64,28 +64,28 @@
|
||||
#define EARLY_KASLR (0)
|
||||
#endif
|
||||
|
||||
#define EARLY_ENTRIES(vstart, vend, shift) \
|
||||
((((vend) - 1) >> (shift)) - ((vstart) >> (shift)) + 1 + EARLY_KASLR)
|
||||
#define EARLY_ENTRIES(vstart, vend, shift, add) \
|
||||
((((vend) - 1) >> (shift)) - ((vstart) >> (shift)) + 1 + add)
|
||||
|
||||
#define EARLY_PGDS(vstart, vend) (EARLY_ENTRIES(vstart, vend, PGDIR_SHIFT))
|
||||
#define EARLY_PGDS(vstart, vend, add) (EARLY_ENTRIES(vstart, vend, PGDIR_SHIFT, add))
|
||||
|
||||
#if SWAPPER_PGTABLE_LEVELS > 3
|
||||
#define EARLY_PUDS(vstart, vend) (EARLY_ENTRIES(vstart, vend, PUD_SHIFT))
|
||||
#define EARLY_PUDS(vstart, vend, add) (EARLY_ENTRIES(vstart, vend, PUD_SHIFT, add))
|
||||
#else
|
||||
#define EARLY_PUDS(vstart, vend) (0)
|
||||
#define EARLY_PUDS(vstart, vend, add) (0)
|
||||
#endif
|
||||
|
||||
#if SWAPPER_PGTABLE_LEVELS > 2
|
||||
#define EARLY_PMDS(vstart, vend) (EARLY_ENTRIES(vstart, vend, SWAPPER_TABLE_SHIFT))
|
||||
#define EARLY_PMDS(vstart, vend, add) (EARLY_ENTRIES(vstart, vend, SWAPPER_TABLE_SHIFT, add))
|
||||
#else
|
||||
#define EARLY_PMDS(vstart, vend) (0)
|
||||
#define EARLY_PMDS(vstart, vend, add) (0)
|
||||
#endif
|
||||
|
||||
#define EARLY_PAGES(vstart, vend) ( 1 /* PGDIR page */ \
|
||||
+ EARLY_PGDS((vstart), (vend)) /* each PGDIR needs a next level page table */ \
|
||||
+ EARLY_PUDS((vstart), (vend)) /* each PUD needs a next level page table */ \
|
||||
+ EARLY_PMDS((vstart), (vend))) /* each PMD needs a next level page table */
|
||||
#define INIT_DIR_SIZE (PAGE_SIZE * EARLY_PAGES(KIMAGE_VADDR, _end))
|
||||
#define EARLY_PAGES(vstart, vend, add) ( 1 /* PGDIR page */ \
|
||||
+ EARLY_PGDS((vstart), (vend), add) /* each PGDIR needs a next level page table */ \
|
||||
+ EARLY_PUDS((vstart), (vend), add) /* each PUD needs a next level page table */ \
|
||||
+ EARLY_PMDS((vstart), (vend), add)) /* each PMD needs a next level page table */
|
||||
#define INIT_DIR_SIZE (PAGE_SIZE * EARLY_PAGES(KIMAGE_VADDR, _end, EARLY_KASLR))
|
||||
|
||||
/* the initial ID map may need two extra pages if it needs to be extended */
|
||||
#if VA_BITS < 48
|
||||
@ -93,7 +93,7 @@
|
||||
#else
|
||||
#define INIT_IDMAP_DIR_SIZE (INIT_IDMAP_DIR_PAGES * PAGE_SIZE)
|
||||
#endif
|
||||
#define INIT_IDMAP_DIR_PAGES EARLY_PAGES(KIMAGE_VADDR, _end + MAX_FDT_SIZE + SWAPPER_BLOCK_SIZE)
|
||||
#define INIT_IDMAP_DIR_PAGES EARLY_PAGES(KIMAGE_VADDR, _end + MAX_FDT_SIZE + SWAPPER_BLOCK_SIZE, 1)
|
||||
|
||||
/* Initial memory map size */
|
||||
#if ARM64_KERNEL_USES_PMD_MAPS
|
||||
|
@ -371,7 +371,9 @@ SYM_FUNC_END(create_idmap)
|
||||
SYM_FUNC_START_LOCAL(create_kernel_mapping)
|
||||
adrp x0, init_pg_dir
|
||||
mov_q x5, KIMAGE_VADDR // compile time __va(_text)
|
||||
#ifdef CONFIG_RELOCATABLE
|
||||
add x5, x5, x23 // add KASLR displacement
|
||||
#endif
|
||||
adrp x6, _end // runtime __pa(_end)
|
||||
adrp x3, _text // runtime __pa(_text)
|
||||
sub x6, x6, x3 // _end - _text
|
||||
|
@ -47,7 +47,7 @@ static int prepare_elf_headers(void **addr, unsigned long *sz)
|
||||
u64 i;
|
||||
phys_addr_t start, end;
|
||||
|
||||
nr_ranges = 1; /* for exclusion of crashkernel region */
|
||||
nr_ranges = 2; /* for exclusion of crashkernel region */
|
||||
for_each_mem_range(i, &start, &end)
|
||||
nr_ranges++;
|
||||
|
||||
|
@ -39,6 +39,7 @@ config LOONGARCH
|
||||
select ARCH_INLINE_SPIN_UNLOCK_BH if !PREEMPTION
|
||||
select ARCH_INLINE_SPIN_UNLOCK_IRQ if !PREEMPTION
|
||||
select ARCH_INLINE_SPIN_UNLOCK_IRQRESTORE if !PREEMPTION
|
||||
select ARCH_KEEP_MEMBLOCK
|
||||
select ARCH_MIGHT_HAVE_PC_PARPORT
|
||||
select ARCH_MIGHT_HAVE_PC_SERIO
|
||||
select ARCH_SPARSEMEM_ENABLE
|
||||
@ -51,6 +52,7 @@ config LOONGARCH
|
||||
select ARCH_USE_CMPXCHG_LOCKREF
|
||||
select ARCH_USE_QUEUED_RWLOCKS
|
||||
select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT
|
||||
select ARCH_WANT_LD_ORPHAN_WARN
|
||||
select ARCH_WANTS_NO_INSTR
|
||||
select BUILDTIME_TABLE_SORT
|
||||
select COMMON_CLK
|
||||
|
@ -15,7 +15,7 @@ extern int acpi_pci_disabled;
|
||||
extern int acpi_noirq;
|
||||
|
||||
#define acpi_os_ioremap acpi_os_ioremap
|
||||
void __init __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size);
|
||||
void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size);
|
||||
|
||||
static inline void disable_acpi(void)
|
||||
{
|
||||
|
@ -48,7 +48,7 @@ void __init __acpi_unmap_table(void __iomem *map, unsigned long size)
|
||||
early_memunmap(map, size);
|
||||
}
|
||||
|
||||
void __init __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size)
|
||||
void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size)
|
||||
{
|
||||
if (!memblock_is_memory(phys))
|
||||
return ioremap(phys, size);
|
||||
|
@ -529,11 +529,11 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
|
||||
signal_setup_done(ret, ksig, 0);
|
||||
}
|
||||
|
||||
void arch_do_signal_or_restart(struct pt_regs *regs, bool has_signal)
|
||||
void arch_do_signal_or_restart(struct pt_regs *regs)
|
||||
{
|
||||
struct ksignal ksig;
|
||||
|
||||
if (has_signal && get_signal(&ksig)) {
|
||||
if (get_signal(&ksig)) {
|
||||
/* Whee! Actually deliver the signal. */
|
||||
handle_signal(&ksig, regs);
|
||||
return;
|
||||
|
@ -77,6 +77,8 @@ SECTIONS
|
||||
PERCPU_SECTION(1 << CONFIG_L1_CACHE_SHIFT)
|
||||
#endif
|
||||
|
||||
.rela.dyn : ALIGN(8) { *(.rela.dyn) *(.rela*) }
|
||||
|
||||
.init.bss : {
|
||||
*(.init.bss)
|
||||
}
|
||||
|
@ -18,11 +18,11 @@ void dump_tlb_regs(void)
|
||||
{
|
||||
const int field = 2 * sizeof(unsigned long);
|
||||
|
||||
pr_info("Index : %0x\n", read_csr_tlbidx());
|
||||
pr_info("PageSize : %0x\n", read_csr_pagesize());
|
||||
pr_info("EntryHi : %0*llx\n", field, read_csr_entryhi());
|
||||
pr_info("EntryLo0 : %0*llx\n", field, read_csr_entrylo0());
|
||||
pr_info("EntryLo1 : %0*llx\n", field, read_csr_entrylo1());
|
||||
pr_info("Index : 0x%0x\n", read_csr_tlbidx());
|
||||
pr_info("PageSize : 0x%0x\n", read_csr_pagesize());
|
||||
pr_info("EntryHi : 0x%0*llx\n", field, read_csr_entryhi());
|
||||
pr_info("EntryLo0 : 0x%0*llx\n", field, read_csr_entrylo0());
|
||||
pr_info("EntryLo1 : 0x%0*llx\n", field, read_csr_entrylo1());
|
||||
}
|
||||
|
||||
static void dump_tlb(int first, int last)
|
||||
@ -33,8 +33,8 @@ static void dump_tlb(int first, int last)
|
||||
unsigned int s_index, s_asid;
|
||||
unsigned int pagesize, c0, c1, i;
|
||||
unsigned long asidmask = cpu_asid_mask(¤t_cpu_data);
|
||||
int pwidth = 11;
|
||||
int vwidth = 11;
|
||||
int pwidth = 16;
|
||||
int vwidth = 16;
|
||||
int asidwidth = DIV_ROUND_UP(ilog2(asidmask) + 1, 4);
|
||||
|
||||
s_entryhi = read_csr_entryhi();
|
||||
@ -64,22 +64,22 @@ static void dump_tlb(int first, int last)
|
||||
/*
|
||||
* Only print entries in use
|
||||
*/
|
||||
pr_info("Index: %2d pgsize=%x ", i, (1 << pagesize));
|
||||
pr_info("Index: %4d pgsize=0x%x ", i, (1 << pagesize));
|
||||
|
||||
c0 = (entrylo0 & ENTRYLO_C) >> ENTRYLO_C_SHIFT;
|
||||
c1 = (entrylo1 & ENTRYLO_C) >> ENTRYLO_C_SHIFT;
|
||||
|
||||
pr_cont("va=%0*lx asid=%0*lx",
|
||||
pr_cont("va=0x%0*lx asid=0x%0*lx",
|
||||
vwidth, (entryhi & ~0x1fffUL), asidwidth, asid & asidmask);
|
||||
|
||||
/* NR/NX are in awkward places, so mask them off separately */
|
||||
pa = entrylo0 & ~(ENTRYLO_NR | ENTRYLO_NX);
|
||||
pa = pa & PAGE_MASK;
|
||||
pr_cont("\n\t[");
|
||||
pr_cont("ri=%d xi=%d ",
|
||||
pr_cont("nr=%d nx=%d ",
|
||||
(entrylo0 & ENTRYLO_NR) ? 1 : 0,
|
||||
(entrylo0 & ENTRYLO_NX) ? 1 : 0);
|
||||
pr_cont("pa=%0*llx c=%d d=%d v=%d g=%d plv=%lld] [",
|
||||
pr_cont("pa=0x%0*llx c=%d d=%d v=%d g=%d plv=%lld] [",
|
||||
pwidth, pa, c0,
|
||||
(entrylo0 & ENTRYLO_D) ? 1 : 0,
|
||||
(entrylo0 & ENTRYLO_V) ? 1 : 0,
|
||||
@ -88,10 +88,10 @@ static void dump_tlb(int first, int last)
|
||||
/* NR/NX are in awkward places, so mask them off separately */
|
||||
pa = entrylo1 & ~(ENTRYLO_NR | ENTRYLO_NX);
|
||||
pa = pa & PAGE_MASK;
|
||||
pr_cont("ri=%d xi=%d ",
|
||||
pr_cont("nr=%d nx=%d ",
|
||||
(entrylo1 & ENTRYLO_NR) ? 1 : 0,
|
||||
(entrylo1 & ENTRYLO_NX) ? 1 : 0);
|
||||
pr_cont("pa=%0*llx c=%d d=%d v=%d g=%d plv=%lld]\n",
|
||||
pr_cont("pa=0x%0*llx c=%d d=%d v=%d g=%d plv=%lld]\n",
|
||||
pwidth, pa, c1,
|
||||
(entrylo1 & ENTRYLO_D) ? 1 : 0,
|
||||
(entrylo1 & ENTRYLO_V) ? 1 : 0,
|
||||
|
@ -131,18 +131,6 @@ int arch_add_memory(int nid, u64 start, u64 size, struct mhp_params *params)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NUMA
|
||||
int memory_add_physaddr_to_nid(u64 start)
|
||||
{
|
||||
int nid;
|
||||
|
||||
nid = pa_to_nid(start);
|
||||
return nid;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MEMORY_HOTREMOVE
|
||||
void arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap)
|
||||
{
|
||||
unsigned long start_pfn = start >> PAGE_SHIFT;
|
||||
@ -154,6 +142,13 @@ void arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap)
|
||||
page += vmem_altmap_offset(altmap);
|
||||
__remove_pages(start_pfn, nr_pages, altmap);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NUMA
|
||||
int memory_add_physaddr_to_nid(u64 start)
|
||||
{
|
||||
return pa_to_nid(start);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -83,6 +83,8 @@ enum {
|
||||
FW_FEATURE_POWERNV_ALWAYS = 0,
|
||||
FW_FEATURE_PS3_POSSIBLE = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1,
|
||||
FW_FEATURE_PS3_ALWAYS = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1,
|
||||
FW_FEATURE_NATIVE_POSSIBLE = 0,
|
||||
FW_FEATURE_NATIVE_ALWAYS = 0,
|
||||
FW_FEATURE_POSSIBLE =
|
||||
#ifdef CONFIG_PPC_PSERIES
|
||||
FW_FEATURE_PSERIES_POSSIBLE |
|
||||
@ -92,6 +94,9 @@ enum {
|
||||
#endif
|
||||
#ifdef CONFIG_PPC_PS3
|
||||
FW_FEATURE_PS3_POSSIBLE |
|
||||
#endif
|
||||
#ifdef CONFIG_PPC_HASH_MMU_NATIVE
|
||||
FW_FEATURE_NATIVE_ALWAYS |
|
||||
#endif
|
||||
0,
|
||||
FW_FEATURE_ALWAYS =
|
||||
@ -103,6 +108,9 @@ enum {
|
||||
#endif
|
||||
#ifdef CONFIG_PPC_PS3
|
||||
FW_FEATURE_PS3_ALWAYS &
|
||||
#endif
|
||||
#ifdef CONFIG_PPC_HASH_MMU_NATIVE
|
||||
FW_FEATURE_NATIVE_ALWAYS &
|
||||
#endif
|
||||
FW_FEATURE_POSSIBLE,
|
||||
|
||||
|
@ -113,7 +113,14 @@ static inline void __hard_RI_enable(void)
|
||||
|
||||
static inline notrace unsigned long irq_soft_mask_return(void)
|
||||
{
|
||||
return READ_ONCE(local_paca->irq_soft_mask);
|
||||
unsigned long flags;
|
||||
|
||||
asm volatile(
|
||||
"lbz %0,%1(13)"
|
||||
: "=r" (flags)
|
||||
: "i" (offsetof(struct paca_struct, irq_soft_mask)));
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -140,24 +147,46 @@ static inline notrace void irq_soft_mask_set(unsigned long mask)
|
||||
if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG))
|
||||
WARN_ON(mask && !(mask & IRQS_DISABLED));
|
||||
|
||||
WRITE_ONCE(local_paca->irq_soft_mask, mask);
|
||||
barrier();
|
||||
asm volatile(
|
||||
"stb %0,%1(13)"
|
||||
:
|
||||
: "r" (mask),
|
||||
"i" (offsetof(struct paca_struct, irq_soft_mask))
|
||||
: "memory");
|
||||
}
|
||||
|
||||
static inline notrace unsigned long irq_soft_mask_set_return(unsigned long mask)
|
||||
{
|
||||
unsigned long flags = irq_soft_mask_return();
|
||||
unsigned long flags;
|
||||
|
||||
irq_soft_mask_set(mask);
|
||||
#ifdef CONFIG_PPC_IRQ_SOFT_MASK_DEBUG
|
||||
WARN_ON(mask && !(mask & IRQS_DISABLED));
|
||||
#endif
|
||||
|
||||
asm volatile(
|
||||
"lbz %0,%1(13); stb %2,%1(13)"
|
||||
: "=&r" (flags)
|
||||
: "i" (offsetof(struct paca_struct, irq_soft_mask)),
|
||||
"r" (mask)
|
||||
: "memory");
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
static inline notrace unsigned long irq_soft_mask_or_return(unsigned long mask)
|
||||
{
|
||||
unsigned long flags = irq_soft_mask_return();
|
||||
unsigned long flags, tmp;
|
||||
|
||||
irq_soft_mask_set(flags | mask);
|
||||
asm volatile(
|
||||
"lbz %0,%2(13); or %1,%0,%3; stb %1,%2(13)"
|
||||
: "=&r" (flags), "=r" (tmp)
|
||||
: "i" (offsetof(struct paca_struct, irq_soft_mask)),
|
||||
"r" (mask)
|
||||
: "memory");
|
||||
|
||||
#ifdef CONFIG_PPC_IRQ_SOFT_MASK_DEBUG
|
||||
WARN_ON((mask | flags) && !((mask | flags) & IRQS_DISABLED));
|
||||
#endif
|
||||
|
||||
return flags;
|
||||
}
|
||||
@ -282,7 +311,8 @@ static inline bool pmi_irq_pending(void)
|
||||
flags = irq_soft_mask_set_return(IRQS_ALL_DISABLED); \
|
||||
local_paca->irq_happened |= PACA_IRQ_HARD_DIS; \
|
||||
if (!arch_irqs_disabled_flags(flags)) { \
|
||||
WRITE_ONCE(local_paca->saved_r1, current_stack_pointer);\
|
||||
asm volatile("std%X0 %1,%0" : "=m" (local_paca->saved_r1) \
|
||||
: "r" (current_stack_pointer)); \
|
||||
trace_hardirqs_off(); \
|
||||
} \
|
||||
} while(0)
|
||||
|
@ -245,6 +245,15 @@ static int __init pcibios_init(void)
|
||||
|
||||
printk(KERN_INFO "PCI: Probing PCI hardware\n");
|
||||
|
||||
#ifdef CONFIG_PPC_PCI_BUS_NUM_DOMAIN_DEPENDENT
|
||||
/*
|
||||
* Enable PCI domains in /proc when PCI bus numbers are not unique
|
||||
* across all PCI domains to prevent conflicts. And keep PCI domain 0
|
||||
* backward compatible in /proc for video cards.
|
||||
*/
|
||||
pci_add_flags(PCI_ENABLE_PROC_DOMAINS | PCI_COMPAT_DOMAIN_0);
|
||||
#endif
|
||||
|
||||
if (pci_has_flag(PCI_REASSIGN_ALL_BUS))
|
||||
pci_assign_all_buses = 1;
|
||||
|
||||
|
@ -109,8 +109,12 @@ __enter_rtas:
|
||||
* its critical regions (as specified in PAPR+ section 7.2.1). MSR[S]
|
||||
* is not impacted by RFI_TO_KERNEL (only urfid can unset it). So if
|
||||
* MSR[S] is set, it will remain when entering RTAS.
|
||||
* If we're in HV mode, RTAS must also run in HV mode, so extract MSR_HV
|
||||
* from the saved MSR value and insert into the value RTAS will use.
|
||||
*/
|
||||
extrdi r0, r6, 1, 63 - MSR_HV_LG
|
||||
LOAD_REG_IMMEDIATE(r6, MSR_ME | MSR_RI)
|
||||
insrdi r6, r0, 1, 63 - MSR_HV_LG
|
||||
|
||||
li r0,0
|
||||
mtmsrd r0,1 /* disable RI before using SRR0/1 */
|
||||
|
@ -18,6 +18,7 @@
|
||||
.p2align 3
|
||||
#define __SYSCALL(nr, entry) .8byte entry
|
||||
#else
|
||||
.p2align 2
|
||||
#define __SYSCALL(nr, entry) .long entry
|
||||
#endif
|
||||
|
||||
|
@ -124,9 +124,6 @@ struct papr_scm_priv {
|
||||
|
||||
/* The bits which needs to be overridden */
|
||||
u64 health_bitmap_inject_mask;
|
||||
|
||||
/* array to have event_code and stat_id mappings */
|
||||
u8 *nvdimm_events_map;
|
||||
};
|
||||
|
||||
static int papr_scm_pmem_flush(struct nd_region *nd_region,
|
||||
@ -350,6 +347,25 @@ static ssize_t drc_pmem_query_stats(struct papr_scm_priv *p,
|
||||
#ifdef CONFIG_PERF_EVENTS
|
||||
#define to_nvdimm_pmu(_pmu) container_of(_pmu, struct nvdimm_pmu, pmu)
|
||||
|
||||
static const char * const nvdimm_events_map[] = {
|
||||
[1] = "CtlResCt",
|
||||
[2] = "CtlResTm",
|
||||
[3] = "PonSecs ",
|
||||
[4] = "MemLife ",
|
||||
[5] = "CritRscU",
|
||||
[6] = "HostLCnt",
|
||||
[7] = "HostSCnt",
|
||||
[8] = "HostSDur",
|
||||
[9] = "HostLDur",
|
||||
[10] = "MedRCnt ",
|
||||
[11] = "MedWCnt ",
|
||||
[12] = "MedRDur ",
|
||||
[13] = "MedWDur ",
|
||||
[14] = "CchRHCnt",
|
||||
[15] = "CchWHCnt",
|
||||
[16] = "FastWCnt",
|
||||
};
|
||||
|
||||
static int papr_scm_pmu_get_value(struct perf_event *event, struct device *dev, u64 *count)
|
||||
{
|
||||
struct papr_scm_perf_stat *stat;
|
||||
@ -357,11 +373,15 @@ static int papr_scm_pmu_get_value(struct perf_event *event, struct device *dev,
|
||||
struct papr_scm_priv *p = dev_get_drvdata(dev);
|
||||
int rc, size;
|
||||
|
||||
/* Invalid eventcode */
|
||||
if (event->attr.config == 0 || event->attr.config >= ARRAY_SIZE(nvdimm_events_map))
|
||||
return -EINVAL;
|
||||
|
||||
/* Allocate request buffer enough to hold single performance stat */
|
||||
size = sizeof(struct papr_scm_perf_stats) +
|
||||
sizeof(struct papr_scm_perf_stat);
|
||||
|
||||
if (!p || !p->nvdimm_events_map)
|
||||
if (!p)
|
||||
return -EINVAL;
|
||||
|
||||
stats = kzalloc(size, GFP_KERNEL);
|
||||
@ -370,7 +390,7 @@ static int papr_scm_pmu_get_value(struct perf_event *event, struct device *dev,
|
||||
|
||||
stat = &stats->scm_statistic[0];
|
||||
memcpy(&stat->stat_id,
|
||||
&p->nvdimm_events_map[event->attr.config * sizeof(stat->stat_id)],
|
||||
nvdimm_events_map[event->attr.config],
|
||||
sizeof(stat->stat_id));
|
||||
stat->stat_val = 0;
|
||||
|
||||
@ -458,56 +478,6 @@ static void papr_scm_pmu_del(struct perf_event *event, int flags)
|
||||
papr_scm_pmu_read(event);
|
||||
}
|
||||
|
||||
static int papr_scm_pmu_check_events(struct papr_scm_priv *p, struct nvdimm_pmu *nd_pmu)
|
||||
{
|
||||
struct papr_scm_perf_stat *stat;
|
||||
struct papr_scm_perf_stats *stats;
|
||||
u32 available_events;
|
||||
int index, rc = 0;
|
||||
|
||||
if (!p->stat_buffer_len)
|
||||
return -ENOENT;
|
||||
|
||||
available_events = (p->stat_buffer_len - sizeof(struct papr_scm_perf_stats))
|
||||
/ sizeof(struct papr_scm_perf_stat);
|
||||
if (available_events == 0)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* Allocate the buffer for phyp where stats are written */
|
||||
stats = kzalloc(p->stat_buffer_len, GFP_KERNEL);
|
||||
if (!stats) {
|
||||
rc = -ENOMEM;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Called to get list of events supported */
|
||||
rc = drc_pmem_query_stats(p, stats, 0);
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Allocate memory and populate nvdimm_event_map.
|
||||
* Allocate an extra element for NULL entry
|
||||
*/
|
||||
p->nvdimm_events_map = kcalloc(available_events + 1,
|
||||
sizeof(stat->stat_id),
|
||||
GFP_KERNEL);
|
||||
if (!p->nvdimm_events_map) {
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Copy all stat_ids to event map */
|
||||
for (index = 0, stat = stats->scm_statistic;
|
||||
index < available_events; index++, ++stat) {
|
||||
memcpy(&p->nvdimm_events_map[index * sizeof(stat->stat_id)],
|
||||
&stat->stat_id, sizeof(stat->stat_id));
|
||||
}
|
||||
out:
|
||||
kfree(stats);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void papr_scm_pmu_register(struct papr_scm_priv *p)
|
||||
{
|
||||
struct nvdimm_pmu *nd_pmu;
|
||||
@ -519,9 +489,10 @@ static void papr_scm_pmu_register(struct papr_scm_priv *p)
|
||||
goto pmu_err_print;
|
||||
}
|
||||
|
||||
rc = papr_scm_pmu_check_events(p, nd_pmu);
|
||||
if (rc)
|
||||
if (!p->stat_buffer_len) {
|
||||
rc = -ENOENT;
|
||||
goto pmu_check_events_err;
|
||||
}
|
||||
|
||||
nd_pmu->pmu.task_ctx_nr = perf_invalid_context;
|
||||
nd_pmu->pmu.name = nvdimm_name(p->nvdimm);
|
||||
@ -539,7 +510,7 @@ static void papr_scm_pmu_register(struct papr_scm_priv *p)
|
||||
|
||||
rc = register_nvdimm_pmu(nd_pmu, p->pdev);
|
||||
if (rc)
|
||||
goto pmu_register_err;
|
||||
goto pmu_check_events_err;
|
||||
|
||||
/*
|
||||
* Set archdata.priv value to nvdimm_pmu structure, to handle the
|
||||
@ -548,8 +519,6 @@ static void papr_scm_pmu_register(struct papr_scm_priv *p)
|
||||
p->pdev->archdata.priv = nd_pmu;
|
||||
return;
|
||||
|
||||
pmu_register_err:
|
||||
kfree(p->nvdimm_events_map);
|
||||
pmu_check_events_err:
|
||||
kfree(nd_pmu);
|
||||
pmu_err_print:
|
||||
@ -1560,7 +1529,6 @@ static int papr_scm_remove(struct platform_device *pdev)
|
||||
unregister_nvdimm_pmu(pdev->archdata.priv);
|
||||
|
||||
pdev->archdata.priv = NULL;
|
||||
kfree(p->nvdimm_events_map);
|
||||
kfree(p->bus_desc.provider_name);
|
||||
kfree(p);
|
||||
|
||||
|
@ -33,4 +33,16 @@ void kvm_riscv_vcpu_sbi_system_reset(struct kvm_vcpu *vcpu,
|
||||
u32 type, u64 flags);
|
||||
const struct kvm_vcpu_sbi_extension *kvm_vcpu_sbi_find_ext(unsigned long extid);
|
||||
|
||||
#ifdef CONFIG_RISCV_SBI_V01
|
||||
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_v01;
|
||||
#endif
|
||||
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_base;
|
||||
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_time;
|
||||
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_ipi;
|
||||
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_rfence;
|
||||
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_srst;
|
||||
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_hsm;
|
||||
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_experimental;
|
||||
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_vendor;
|
||||
|
||||
#endif /* __RISCV_KVM_VCPU_SBI_H__ */
|
||||
|
@ -32,23 +32,13 @@ static int kvm_linux_err_map_sbi(int err)
|
||||
};
|
||||
}
|
||||
|
||||
#ifdef CONFIG_RISCV_SBI_V01
|
||||
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_v01;
|
||||
#else
|
||||
#ifndef CONFIG_RISCV_SBI_V01
|
||||
static const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_v01 = {
|
||||
.extid_start = -1UL,
|
||||
.extid_end = -1UL,
|
||||
.handler = NULL,
|
||||
};
|
||||
#endif
|
||||
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_base;
|
||||
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_time;
|
||||
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_ipi;
|
||||
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_rfence;
|
||||
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_srst;
|
||||
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_hsm;
|
||||
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_experimental;
|
||||
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_vendor;
|
||||
|
||||
static const struct kvm_vcpu_sbi_extension *sbi_ext[] = {
|
||||
&vcpu_sbi_ext_v01,
|
||||
|
@ -299,7 +299,6 @@ static void kvm_riscv_vcpu_update_timedelta(struct kvm_vcpu *vcpu)
|
||||
|
||||
void kvm_riscv_vcpu_timer_restore(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm_vcpu_csr *csr;
|
||||
struct kvm_vcpu_timer *t = &vcpu->arch.timer;
|
||||
|
||||
kvm_riscv_vcpu_update_timedelta(vcpu);
|
||||
@ -307,7 +306,6 @@ void kvm_riscv_vcpu_timer_restore(struct kvm_vcpu *vcpu)
|
||||
if (!t->sstc_enabled)
|
||||
return;
|
||||
|
||||
csr = &vcpu->arch.guest_csr;
|
||||
#if defined(CONFIG_32BIT)
|
||||
csr_write(CSR_VSTIMECMP, (u32)t->next_cycles);
|
||||
csr_write(CSR_VSTIMECMPH, (u32)(t->next_cycles >> 32));
|
||||
@ -324,13 +322,11 @@ void kvm_riscv_vcpu_timer_restore(struct kvm_vcpu *vcpu)
|
||||
|
||||
void kvm_riscv_vcpu_timer_save(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm_vcpu_csr *csr;
|
||||
struct kvm_vcpu_timer *t = &vcpu->arch.timer;
|
||||
|
||||
if (!t->sstc_enabled)
|
||||
return;
|
||||
|
||||
csr = &vcpu->arch.guest_csr;
|
||||
t = &vcpu->arch.timer;
|
||||
#if defined(CONFIG_32BIT)
|
||||
t->next_cycles = csr_read(CSR_VSTIMECMP);
|
||||
|
@ -118,10 +118,10 @@ static int __set_memory(unsigned long addr, int numpages, pgprot_t set_mask,
|
||||
if (!numpages)
|
||||
return 0;
|
||||
|
||||
mmap_read_lock(&init_mm);
|
||||
mmap_write_lock(&init_mm);
|
||||
ret = walk_page_range_novma(&init_mm, start, end, &pageattr_ops, NULL,
|
||||
&masks);
|
||||
mmap_read_unlock(&init_mm);
|
||||
mmap_write_unlock(&init_mm);
|
||||
|
||||
flush_tlb_kernel_range(start, end);
|
||||
|
||||
|
@ -40,8 +40,6 @@ CONFIG_CHECKPOINT_RESTORE=y
|
||||
CONFIG_SCHED_AUTOGROUP=y
|
||||
CONFIG_EXPERT=y
|
||||
# CONFIG_SYSFS_SYSCALL is not set
|
||||
CONFIG_USERFAULTFD=y
|
||||
# CONFIG_COMPAT_BRK is not set
|
||||
CONFIG_PROFILING=y
|
||||
CONFIG_LIVEPATCH=y
|
||||
CONFIG_MARCH_ZEC12=y
|
||||
@ -74,6 +72,7 @@ CONFIG_MODULES=y
|
||||
CONFIG_MODULE_FORCE_LOAD=y
|
||||
CONFIG_MODULE_UNLOAD=y
|
||||
CONFIG_MODULE_FORCE_UNLOAD=y
|
||||
CONFIG_MODULE_UNLOAD_TAINT_TRACKING=y
|
||||
CONFIG_MODVERSIONS=y
|
||||
CONFIG_MODULE_SRCVERSION_ALL=y
|
||||
CONFIG_MODULE_SIG_SHA256=y
|
||||
@ -93,6 +92,10 @@ CONFIG_UNIXWARE_DISKLABEL=y
|
||||
CONFIG_IOSCHED_BFQ=y
|
||||
CONFIG_BFQ_GROUP_IOSCHED=y
|
||||
CONFIG_BINFMT_MISC=m
|
||||
CONFIG_ZSWAP=y
|
||||
CONFIG_ZSMALLOC_STAT=y
|
||||
CONFIG_SLUB_STATS=y
|
||||
# CONFIG_COMPAT_BRK is not set
|
||||
CONFIG_MEMORY_HOTPLUG=y
|
||||
CONFIG_MEMORY_HOTREMOVE=y
|
||||
CONFIG_KSM=y
|
||||
@ -102,14 +105,12 @@ CONFIG_CMA_DEBUGFS=y
|
||||
CONFIG_CMA_SYSFS=y
|
||||
CONFIG_CMA_AREAS=7
|
||||
CONFIG_MEM_SOFT_DIRTY=y
|
||||
CONFIG_ZSWAP=y
|
||||
CONFIG_ZSMALLOC=y
|
||||
CONFIG_ZSMALLOC_STAT=y
|
||||
CONFIG_DEFERRED_STRUCT_PAGE_INIT=y
|
||||
CONFIG_IDLE_PAGE_TRACKING=y
|
||||
CONFIG_PERCPU_STATS=y
|
||||
CONFIG_GUP_TEST=y
|
||||
CONFIG_ANON_VMA_NAME=y
|
||||
CONFIG_USERFAULTFD=y
|
||||
CONFIG_NET=y
|
||||
CONFIG_PACKET=y
|
||||
CONFIG_PACKET_DIAG=m
|
||||
@ -167,6 +168,7 @@ CONFIG_BRIDGE_NETFILTER=m
|
||||
CONFIG_NETFILTER_NETLINK_HOOK=m
|
||||
CONFIG_NF_CONNTRACK=m
|
||||
CONFIG_NF_CONNTRACK_SECMARK=y
|
||||
CONFIG_NF_CONNTRACK_PROCFS=y
|
||||
CONFIG_NF_CONNTRACK_EVENTS=y
|
||||
CONFIG_NF_CONNTRACK_TIMEOUT=y
|
||||
CONFIG_NF_CONNTRACK_TIMESTAMP=y
|
||||
@ -493,7 +495,6 @@ CONFIG_NLMON=m
|
||||
# CONFIG_NET_VENDOR_ASIX is not set
|
||||
# CONFIG_NET_VENDOR_ATHEROS is not set
|
||||
# CONFIG_NET_VENDOR_BROADCOM is not set
|
||||
# CONFIG_NET_VENDOR_BROCADE is not set
|
||||
# CONFIG_NET_VENDOR_CADENCE is not set
|
||||
# CONFIG_NET_VENDOR_CAVIUM is not set
|
||||
# CONFIG_NET_VENDOR_CHELSIO is not set
|
||||
@ -509,7 +510,7 @@ CONFIG_NLMON=m
|
||||
# CONFIG_NET_VENDOR_GOOGLE is not set
|
||||
# CONFIG_NET_VENDOR_HUAWEI is not set
|
||||
# CONFIG_NET_VENDOR_INTEL is not set
|
||||
# CONFIG_NET_VENDOR_MICROSOFT is not set
|
||||
# CONFIG_NET_VENDOR_WANGXUN is not set
|
||||
# CONFIG_NET_VENDOR_LITEX is not set
|
||||
# CONFIG_NET_VENDOR_MARVELL is not set
|
||||
CONFIG_MLX4_EN=m
|
||||
@ -518,16 +519,18 @@ CONFIG_MLX5_CORE_EN=y
|
||||
# CONFIG_NET_VENDOR_MICREL is not set
|
||||
# CONFIG_NET_VENDOR_MICROCHIP is not set
|
||||
# CONFIG_NET_VENDOR_MICROSEMI is not set
|
||||
# CONFIG_NET_VENDOR_MICROSOFT is not set
|
||||
# CONFIG_NET_VENDOR_MYRI is not set
|
||||
# CONFIG_NET_VENDOR_NI is not set
|
||||
# CONFIG_NET_VENDOR_NATSEMI is not set
|
||||
# CONFIG_NET_VENDOR_NETERION is not set
|
||||
# CONFIG_NET_VENDOR_NETRONOME is not set
|
||||
# CONFIG_NET_VENDOR_NI is not set
|
||||
# CONFIG_NET_VENDOR_NVIDIA is not set
|
||||
# CONFIG_NET_VENDOR_OKI is not set
|
||||
# CONFIG_NET_VENDOR_PACKET_ENGINES is not set
|
||||
# CONFIG_NET_VENDOR_PENSANDO is not set
|
||||
# CONFIG_NET_VENDOR_QLOGIC is not set
|
||||
# CONFIG_NET_VENDOR_BROCADE is not set
|
||||
# CONFIG_NET_VENDOR_QUALCOMM is not set
|
||||
# CONFIG_NET_VENDOR_RDC is not set
|
||||
# CONFIG_NET_VENDOR_REALTEK is not set
|
||||
@ -535,9 +538,9 @@ CONFIG_MLX5_CORE_EN=y
|
||||
# CONFIG_NET_VENDOR_ROCKER is not set
|
||||
# CONFIG_NET_VENDOR_SAMSUNG is not set
|
||||
# CONFIG_NET_VENDOR_SEEQ is not set
|
||||
# CONFIG_NET_VENDOR_SOLARFLARE is not set
|
||||
# CONFIG_NET_VENDOR_SILAN is not set
|
||||
# CONFIG_NET_VENDOR_SIS is not set
|
||||
# CONFIG_NET_VENDOR_SOLARFLARE is not set
|
||||
# CONFIG_NET_VENDOR_SMSC is not set
|
||||
# CONFIG_NET_VENDOR_SOCIONEXT is not set
|
||||
# CONFIG_NET_VENDOR_STMICRO is not set
|
||||
@ -570,6 +573,8 @@ CONFIG_VIRTIO_CONSOLE=m
|
||||
CONFIG_HW_RANDOM_VIRTIO=m
|
||||
CONFIG_HANGCHECK_TIMER=m
|
||||
CONFIG_TN3270_FS=y
|
||||
# CONFIG_RANDOM_TRUST_CPU is not set
|
||||
# CONFIG_RANDOM_TRUST_BOOTLOADER is not set
|
||||
CONFIG_PPS=m
|
||||
# CONFIG_PTP_1588_CLOCK is not set
|
||||
# CONFIG_HWMON is not set
|
||||
@ -727,18 +732,26 @@ CONFIG_CRYPTO_LRW=m
|
||||
CONFIG_CRYPTO_PCBC=m
|
||||
CONFIG_CRYPTO_KEYWRAP=m
|
||||
CONFIG_CRYPTO_ADIANTUM=m
|
||||
CONFIG_CRYPTO_HCTR2=m
|
||||
CONFIG_CRYPTO_XCBC=m
|
||||
CONFIG_CRYPTO_VMAC=m
|
||||
CONFIG_CRYPTO_CRC32=m
|
||||
CONFIG_CRYPTO_BLAKE2S=m
|
||||
CONFIG_CRYPTO_CRC32_S390=y
|
||||
CONFIG_CRYPTO_MD4=m
|
||||
CONFIG_CRYPTO_MD5=y
|
||||
CONFIG_CRYPTO_MICHAEL_MIC=m
|
||||
CONFIG_CRYPTO_RMD160=m
|
||||
CONFIG_CRYPTO_SHA512_S390=m
|
||||
CONFIG_CRYPTO_SHA1_S390=m
|
||||
CONFIG_CRYPTO_SHA256_S390=m
|
||||
CONFIG_CRYPTO_SHA3=m
|
||||
CONFIG_CRYPTO_SM3=m
|
||||
CONFIG_CRYPTO_SHA3_256_S390=m
|
||||
CONFIG_CRYPTO_SHA3_512_S390=m
|
||||
CONFIG_CRYPTO_SM3_GENERIC=m
|
||||
CONFIG_CRYPTO_WP512=m
|
||||
CONFIG_CRYPTO_GHASH_S390=m
|
||||
CONFIG_CRYPTO_AES_TI=m
|
||||
CONFIG_CRYPTO_AES_S390=m
|
||||
CONFIG_CRYPTO_ANUBIS=m
|
||||
CONFIG_CRYPTO_ARC4=m
|
||||
CONFIG_CRYPTO_BLOWFISH=m
|
||||
@ -746,11 +759,14 @@ CONFIG_CRYPTO_CAMELLIA=m
|
||||
CONFIG_CRYPTO_CAST5=m
|
||||
CONFIG_CRYPTO_CAST6=m
|
||||
CONFIG_CRYPTO_DES=m
|
||||
CONFIG_CRYPTO_DES_S390=m
|
||||
CONFIG_CRYPTO_FCRYPT=m
|
||||
CONFIG_CRYPTO_KHAZAD=m
|
||||
CONFIG_CRYPTO_CHACHA_S390=m
|
||||
CONFIG_CRYPTO_SEED=m
|
||||
CONFIG_CRYPTO_ARIA=m
|
||||
CONFIG_CRYPTO_SERPENT=m
|
||||
CONFIG_CRYPTO_SM4=m
|
||||
CONFIG_CRYPTO_SM4_GENERIC=m
|
||||
CONFIG_CRYPTO_TEA=m
|
||||
CONFIG_CRYPTO_TWOFISH=m
|
||||
CONFIG_CRYPTO_842=m
|
||||
@ -766,16 +782,6 @@ CONFIG_CRYPTO_STATS=y
|
||||
CONFIG_ZCRYPT=m
|
||||
CONFIG_PKEY=m
|
||||
CONFIG_CRYPTO_PAES_S390=m
|
||||
CONFIG_CRYPTO_SHA1_S390=m
|
||||
CONFIG_CRYPTO_SHA256_S390=m
|
||||
CONFIG_CRYPTO_SHA512_S390=m
|
||||
CONFIG_CRYPTO_SHA3_256_S390=m
|
||||
CONFIG_CRYPTO_SHA3_512_S390=m
|
||||
CONFIG_CRYPTO_DES_S390=m
|
||||
CONFIG_CRYPTO_AES_S390=m
|
||||
CONFIG_CRYPTO_CHACHA_S390=m
|
||||
CONFIG_CRYPTO_GHASH_S390=m
|
||||
CONFIG_CRYPTO_CRC32_S390=y
|
||||
CONFIG_CRYPTO_DEV_VIRTIO=m
|
||||
CONFIG_CORDIC=m
|
||||
CONFIG_CRYPTO_LIB_CURVE25519=m
|
||||
@ -797,6 +803,7 @@ CONFIG_HEADERS_INSTALL=y
|
||||
CONFIG_DEBUG_SECTION_MISMATCH=y
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
CONFIG_DEBUG_PAGEALLOC=y
|
||||
CONFIG_SLUB_DEBUG_ON=y
|
||||
CONFIG_PAGE_OWNER=y
|
||||
CONFIG_DEBUG_RODATA_TEST=y
|
||||
CONFIG_DEBUG_WX=y
|
||||
@ -808,8 +815,6 @@ CONFIG_DEBUG_OBJECTS_TIMERS=y
|
||||
CONFIG_DEBUG_OBJECTS_WORK=y
|
||||
CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
|
||||
CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y
|
||||
CONFIG_SLUB_DEBUG_ON=y
|
||||
CONFIG_SLUB_STATS=y
|
||||
CONFIG_DEBUG_STACK_USAGE=y
|
||||
CONFIG_DEBUG_VM=y
|
||||
CONFIG_DEBUG_VM_PGFLAGS=y
|
||||
|
@ -38,8 +38,6 @@ CONFIG_CHECKPOINT_RESTORE=y
|
||||
CONFIG_SCHED_AUTOGROUP=y
|
||||
CONFIG_EXPERT=y
|
||||
# CONFIG_SYSFS_SYSCALL is not set
|
||||
CONFIG_USERFAULTFD=y
|
||||
# CONFIG_COMPAT_BRK is not set
|
||||
CONFIG_PROFILING=y
|
||||
CONFIG_LIVEPATCH=y
|
||||
CONFIG_MARCH_ZEC12=y
|
||||
@ -69,6 +67,7 @@ CONFIG_MODULES=y
|
||||
CONFIG_MODULE_FORCE_LOAD=y
|
||||
CONFIG_MODULE_UNLOAD=y
|
||||
CONFIG_MODULE_FORCE_UNLOAD=y
|
||||
CONFIG_MODULE_UNLOAD_TAINT_TRACKING=y
|
||||
CONFIG_MODVERSIONS=y
|
||||
CONFIG_MODULE_SRCVERSION_ALL=y
|
||||
CONFIG_MODULE_SIG_SHA256=y
|
||||
@ -88,6 +87,9 @@ CONFIG_UNIXWARE_DISKLABEL=y
|
||||
CONFIG_IOSCHED_BFQ=y
|
||||
CONFIG_BFQ_GROUP_IOSCHED=y
|
||||
CONFIG_BINFMT_MISC=m
|
||||
CONFIG_ZSWAP=y
|
||||
CONFIG_ZSMALLOC_STAT=y
|
||||
# CONFIG_COMPAT_BRK is not set
|
||||
CONFIG_MEMORY_HOTPLUG=y
|
||||
CONFIG_MEMORY_HOTREMOVE=y
|
||||
CONFIG_KSM=y
|
||||
@ -95,13 +97,11 @@ CONFIG_TRANSPARENT_HUGEPAGE=y
|
||||
CONFIG_CMA_SYSFS=y
|
||||
CONFIG_CMA_AREAS=7
|
||||
CONFIG_MEM_SOFT_DIRTY=y
|
||||
CONFIG_ZSWAP=y
|
||||
CONFIG_ZSMALLOC=y
|
||||
CONFIG_ZSMALLOC_STAT=y
|
||||
CONFIG_DEFERRED_STRUCT_PAGE_INIT=y
|
||||
CONFIG_IDLE_PAGE_TRACKING=y
|
||||
CONFIG_PERCPU_STATS=y
|
||||
CONFIG_ANON_VMA_NAME=y
|
||||
CONFIG_USERFAULTFD=y
|
||||
CONFIG_NET=y
|
||||
CONFIG_PACKET=y
|
||||
CONFIG_PACKET_DIAG=m
|
||||
@ -159,6 +159,7 @@ CONFIG_BRIDGE_NETFILTER=m
|
||||
CONFIG_NETFILTER_NETLINK_HOOK=m
|
||||
CONFIG_NF_CONNTRACK=m
|
||||
CONFIG_NF_CONNTRACK_SECMARK=y
|
||||
CONFIG_NF_CONNTRACK_PROCFS=y
|
||||
CONFIG_NF_CONNTRACK_EVENTS=y
|
||||
CONFIG_NF_CONNTRACK_TIMEOUT=y
|
||||
CONFIG_NF_CONNTRACK_TIMESTAMP=y
|
||||
@ -484,7 +485,6 @@ CONFIG_NLMON=m
|
||||
# CONFIG_NET_VENDOR_ASIX is not set
|
||||
# CONFIG_NET_VENDOR_ATHEROS is not set
|
||||
# CONFIG_NET_VENDOR_BROADCOM is not set
|
||||
# CONFIG_NET_VENDOR_BROCADE is not set
|
||||
# CONFIG_NET_VENDOR_CADENCE is not set
|
||||
# CONFIG_NET_VENDOR_CAVIUM is not set
|
||||
# CONFIG_NET_VENDOR_CHELSIO is not set
|
||||
@ -500,7 +500,7 @@ CONFIG_NLMON=m
|
||||
# CONFIG_NET_VENDOR_GOOGLE is not set
|
||||
# CONFIG_NET_VENDOR_HUAWEI is not set
|
||||
# CONFIG_NET_VENDOR_INTEL is not set
|
||||
# CONFIG_NET_VENDOR_MICROSOFT is not set
|
||||
# CONFIG_NET_VENDOR_WANGXUN is not set
|
||||
# CONFIG_NET_VENDOR_LITEX is not set
|
||||
# CONFIG_NET_VENDOR_MARVELL is not set
|
||||
CONFIG_MLX4_EN=m
|
||||
@ -509,16 +509,18 @@ CONFIG_MLX5_CORE_EN=y
|
||||
# CONFIG_NET_VENDOR_MICREL is not set
|
||||
# CONFIG_NET_VENDOR_MICROCHIP is not set
|
||||
# CONFIG_NET_VENDOR_MICROSEMI is not set
|
||||
# CONFIG_NET_VENDOR_MICROSOFT is not set
|
||||
# CONFIG_NET_VENDOR_MYRI is not set
|
||||
# CONFIG_NET_VENDOR_NI is not set
|
||||
# CONFIG_NET_VENDOR_NATSEMI is not set
|
||||
# CONFIG_NET_VENDOR_NETERION is not set
|
||||
# CONFIG_NET_VENDOR_NETRONOME is not set
|
||||
# CONFIG_NET_VENDOR_NI is not set
|
||||
# CONFIG_NET_VENDOR_NVIDIA is not set
|
||||
# CONFIG_NET_VENDOR_OKI is not set
|
||||
# CONFIG_NET_VENDOR_PACKET_ENGINES is not set
|
||||
# CONFIG_NET_VENDOR_PENSANDO is not set
|
||||
# CONFIG_NET_VENDOR_QLOGIC is not set
|
||||
# CONFIG_NET_VENDOR_BROCADE is not set
|
||||
# CONFIG_NET_VENDOR_QUALCOMM is not set
|
||||
# CONFIG_NET_VENDOR_RDC is not set
|
||||
# CONFIG_NET_VENDOR_REALTEK is not set
|
||||
@ -526,9 +528,9 @@ CONFIG_MLX5_CORE_EN=y
|
||||
# CONFIG_NET_VENDOR_ROCKER is not set
|
||||
# CONFIG_NET_VENDOR_SAMSUNG is not set
|
||||
# CONFIG_NET_VENDOR_SEEQ is not set
|
||||
# CONFIG_NET_VENDOR_SOLARFLARE is not set
|
||||
# CONFIG_NET_VENDOR_SILAN is not set
|
||||
# CONFIG_NET_VENDOR_SIS is not set
|
||||
# CONFIG_NET_VENDOR_SOLARFLARE is not set
|
||||
# CONFIG_NET_VENDOR_SMSC is not set
|
||||
# CONFIG_NET_VENDOR_SOCIONEXT is not set
|
||||
# CONFIG_NET_VENDOR_STMICRO is not set
|
||||
@ -561,6 +563,8 @@ CONFIG_VIRTIO_CONSOLE=m
|
||||
CONFIG_HW_RANDOM_VIRTIO=m
|
||||
CONFIG_HANGCHECK_TIMER=m
|
||||
CONFIG_TN3270_FS=y
|
||||
# CONFIG_RANDOM_TRUST_CPU is not set
|
||||
# CONFIG_RANDOM_TRUST_BOOTLOADER is not set
|
||||
# CONFIG_PTP_1588_CLOCK is not set
|
||||
# CONFIG_HWMON is not set
|
||||
CONFIG_WATCHDOG=y
|
||||
@ -713,18 +717,26 @@ CONFIG_CRYPTO_OFB=m
|
||||
CONFIG_CRYPTO_PCBC=m
|
||||
CONFIG_CRYPTO_KEYWRAP=m
|
||||
CONFIG_CRYPTO_ADIANTUM=m
|
||||
CONFIG_CRYPTO_HCTR2=m
|
||||
CONFIG_CRYPTO_XCBC=m
|
||||
CONFIG_CRYPTO_VMAC=m
|
||||
CONFIG_CRYPTO_CRC32=m
|
||||
CONFIG_CRYPTO_BLAKE2S=m
|
||||
CONFIG_CRYPTO_CRC32_S390=y
|
||||
CONFIG_CRYPTO_MD4=m
|
||||
CONFIG_CRYPTO_MD5=y
|
||||
CONFIG_CRYPTO_MICHAEL_MIC=m
|
||||
CONFIG_CRYPTO_RMD160=m
|
||||
CONFIG_CRYPTO_SHA512_S390=m
|
||||
CONFIG_CRYPTO_SHA1_S390=m
|
||||
CONFIG_CRYPTO_SHA256_S390=m
|
||||
CONFIG_CRYPTO_SHA3=m
|
||||
CONFIG_CRYPTO_SM3=m
|
||||
CONFIG_CRYPTO_SHA3_256_S390=m
|
||||
CONFIG_CRYPTO_SHA3_512_S390=m
|
||||
CONFIG_CRYPTO_SM3_GENERIC=m
|
||||
CONFIG_CRYPTO_WP512=m
|
||||
CONFIG_CRYPTO_GHASH_S390=m
|
||||
CONFIG_CRYPTO_AES_TI=m
|
||||
CONFIG_CRYPTO_AES_S390=m
|
||||
CONFIG_CRYPTO_ANUBIS=m
|
||||
CONFIG_CRYPTO_ARC4=m
|
||||
CONFIG_CRYPTO_BLOWFISH=m
|
||||
@ -732,11 +744,14 @@ CONFIG_CRYPTO_CAMELLIA=m
|
||||
CONFIG_CRYPTO_CAST5=m
|
||||
CONFIG_CRYPTO_CAST6=m
|
||||
CONFIG_CRYPTO_DES=m
|
||||
CONFIG_CRYPTO_DES_S390=m
|
||||
CONFIG_CRYPTO_FCRYPT=m
|
||||
CONFIG_CRYPTO_KHAZAD=m
|
||||
CONFIG_CRYPTO_CHACHA_S390=m
|
||||
CONFIG_CRYPTO_SEED=m
|
||||
CONFIG_CRYPTO_ARIA=m
|
||||
CONFIG_CRYPTO_SERPENT=m
|
||||
CONFIG_CRYPTO_SM4=m
|
||||
CONFIG_CRYPTO_SM4_GENERIC=m
|
||||
CONFIG_CRYPTO_TEA=m
|
||||
CONFIG_CRYPTO_TWOFISH=m
|
||||
CONFIG_CRYPTO_842=m
|
||||
@ -752,16 +767,6 @@ CONFIG_CRYPTO_STATS=y
|
||||
CONFIG_ZCRYPT=m
|
||||
CONFIG_PKEY=m
|
||||
CONFIG_CRYPTO_PAES_S390=m
|
||||
CONFIG_CRYPTO_SHA1_S390=m
|
||||
CONFIG_CRYPTO_SHA256_S390=m
|
||||
CONFIG_CRYPTO_SHA512_S390=m
|
||||
CONFIG_CRYPTO_SHA3_256_S390=m
|
||||
CONFIG_CRYPTO_SHA3_512_S390=m
|
||||
CONFIG_CRYPTO_DES_S390=m
|
||||
CONFIG_CRYPTO_AES_S390=m
|
||||
CONFIG_CRYPTO_CHACHA_S390=m
|
||||
CONFIG_CRYPTO_GHASH_S390=m
|
||||
CONFIG_CRYPTO_CRC32_S390=y
|
||||
CONFIG_CRYPTO_DEV_VIRTIO=m
|
||||
CONFIG_CORDIC=m
|
||||
CONFIG_PRIME_NUMBERS=m
|
||||
|
@ -1,4 +1,3 @@
|
||||
# CONFIG_SWAP is not set
|
||||
CONFIG_NO_HZ_IDLE=y
|
||||
CONFIG_HIGH_RES_TIMERS=y
|
||||
CONFIG_BPF_SYSCALL=y
|
||||
@ -9,7 +8,6 @@ CONFIG_BPF_SYSCALL=y
|
||||
# CONFIG_NET_NS is not set
|
||||
CONFIG_BLK_DEV_INITRD=y
|
||||
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
|
||||
# CONFIG_COMPAT_BRK is not set
|
||||
CONFIG_MARCH_ZEC12=y
|
||||
CONFIG_TUNE_ZEC12=y
|
||||
# CONFIG_COMPAT is not set
|
||||
@ -28,6 +26,8 @@ CONFIG_CRASH_DUMP=y
|
||||
# CONFIG_BLOCK_LEGACY_AUTOLOAD is not set
|
||||
CONFIG_PARTITION_ADVANCED=y
|
||||
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
|
||||
# CONFIG_SWAP is not set
|
||||
# CONFIG_COMPAT_BRK is not set
|
||||
# CONFIG_COMPACTION is not set
|
||||
# CONFIG_MIGRATION is not set
|
||||
CONFIG_NET=y
|
||||
@ -53,10 +53,12 @@ CONFIG_ZFCP=y
|
||||
# CONFIG_HVC_IUCV is not set
|
||||
# CONFIG_HW_RANDOM_S390 is not set
|
||||
# CONFIG_HMC_DRV is not set
|
||||
# CONFIG_S390_UV_UAPI is not set
|
||||
# CONFIG_S390_TAPE is not set
|
||||
# CONFIG_VMCP is not set
|
||||
# CONFIG_MONWRITER is not set
|
||||
# CONFIG_S390_VMUR is not set
|
||||
# CONFIG_RANDOM_TRUST_BOOTLOADER is not set
|
||||
# CONFIG_HID is not set
|
||||
# CONFIG_VIRTIO_MENU is not set
|
||||
# CONFIG_VHOST_MENU is not set
|
||||
|
@ -28,9 +28,11 @@ pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
|
||||
static inline int prepare_hugepage_range(struct file *file,
|
||||
unsigned long addr, unsigned long len)
|
||||
{
|
||||
if (len & ~HPAGE_MASK)
|
||||
struct hstate *h = hstate_file(file);
|
||||
|
||||
if (len & ~huge_page_mask(h))
|
||||
return -EINVAL;
|
||||
if (addr & ~HPAGE_MASK)
|
||||
if (addr & ~huge_page_mask(h))
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
@ -1038,16 +1038,11 @@ static inline void kvm_arch_vcpu_unblocking(struct kvm_vcpu *vcpu) {}
|
||||
#define __KVM_HAVE_ARCH_VM_FREE
|
||||
void kvm_arch_free_vm(struct kvm *kvm);
|
||||
|
||||
#ifdef CONFIG_VFIO_PCI_ZDEV_KVM
|
||||
int kvm_s390_pci_register_kvm(struct zpci_dev *zdev, struct kvm *kvm);
|
||||
void kvm_s390_pci_unregister_kvm(struct zpci_dev *zdev);
|
||||
#else
|
||||
static inline int kvm_s390_pci_register_kvm(struct zpci_dev *dev,
|
||||
struct kvm *kvm)
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
static inline void kvm_s390_pci_unregister_kvm(struct zpci_dev *dev) {}
|
||||
#endif
|
||||
struct zpci_kvm_hook {
|
||||
int (*kvm_register)(void *opaque, struct kvm *kvm);
|
||||
void (*kvm_unregister)(void *opaque);
|
||||
};
|
||||
|
||||
extern struct zpci_kvm_hook zpci_kvm_hook;
|
||||
|
||||
#endif
|
||||
|
@ -131,6 +131,7 @@ SECTIONS
|
||||
/*
|
||||
* Table with the patch locations to undo expolines
|
||||
*/
|
||||
. = ALIGN(4);
|
||||
.nospec_call_table : {
|
||||
__nospec_call_start = . ;
|
||||
*(.s390_indirect*)
|
||||
|
@ -431,8 +431,9 @@ static void kvm_s390_pci_dev_release(struct zpci_dev *zdev)
|
||||
* available, enable them and let userspace indicate whether or not they will
|
||||
* be used (specify SHM bit to disable).
|
||||
*/
|
||||
int kvm_s390_pci_register_kvm(struct zpci_dev *zdev, struct kvm *kvm)
|
||||
static int kvm_s390_pci_register_kvm(void *opaque, struct kvm *kvm)
|
||||
{
|
||||
struct zpci_dev *zdev = opaque;
|
||||
int rc;
|
||||
|
||||
if (!zdev)
|
||||
@ -510,10 +511,10 @@ err:
|
||||
kvm_put_kvm(kvm);
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kvm_s390_pci_register_kvm);
|
||||
|
||||
void kvm_s390_pci_unregister_kvm(struct zpci_dev *zdev)
|
||||
static void kvm_s390_pci_unregister_kvm(void *opaque)
|
||||
{
|
||||
struct zpci_dev *zdev = opaque;
|
||||
struct kvm *kvm;
|
||||
|
||||
if (!zdev)
|
||||
@ -566,7 +567,6 @@ out:
|
||||
|
||||
kvm_put_kvm(kvm);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kvm_s390_pci_unregister_kvm);
|
||||
|
||||
void kvm_s390_pci_init_list(struct kvm *kvm)
|
||||
{
|
||||
@ -678,6 +678,8 @@ int kvm_s390_pci_init(void)
|
||||
|
||||
spin_lock_init(&aift->gait_lock);
|
||||
mutex_init(&aift->aift_lock);
|
||||
zpci_kvm_hook.kvm_register = kvm_s390_pci_register_kvm;
|
||||
zpci_kvm_hook.kvm_unregister = kvm_s390_pci_unregister_kvm;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -685,6 +687,8 @@ int kvm_s390_pci_init(void)
|
||||
void kvm_s390_pci_exit(void)
|
||||
{
|
||||
mutex_destroy(&aift->aift_lock);
|
||||
zpci_kvm_hook.kvm_register = NULL;
|
||||
zpci_kvm_hook.kvm_unregister = NULL;
|
||||
|
||||
kfree(aift);
|
||||
}
|
||||
|
@ -421,8 +421,6 @@ retry:
|
||||
if (unlikely(!(vma->vm_flags & access)))
|
||||
goto out_up;
|
||||
|
||||
if (is_vm_hugetlb_page(vma))
|
||||
address &= HPAGE_MASK;
|
||||
/*
|
||||
* If for any reason at all we couldn't handle the fault,
|
||||
* make sure we exit gracefully rather than endlessly redo
|
||||
|
@ -5,5 +5,5 @@
|
||||
|
||||
obj-$(CONFIG_PCI) += pci.o pci_irq.o pci_dma.o pci_clp.o pci_sysfs.o \
|
||||
pci_event.o pci_debug.o pci_insn.o pci_mmio.o \
|
||||
pci_bus.o
|
||||
pci_bus.o pci_kvm_hook.o
|
||||
obj-$(CONFIG_PCI_IOV) += pci_iov.o
|
||||
|
11
arch/s390/pci/pci_kvm_hook.c
Normal file
11
arch/s390/pci/pci_kvm_hook.c
Normal file
@ -0,0 +1,11 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* VFIO ZPCI devices support
|
||||
*
|
||||
* Copyright (C) IBM Corp. 2022. All rights reserved.
|
||||
* Author(s): Pierre Morel <pmorel@linux.ibm.com>
|
||||
*/
|
||||
#include <linux/kvm_host.h>
|
||||
|
||||
struct zpci_kvm_hook zpci_kvm_hook;
|
||||
EXPORT_SYMBOL_GPL(zpci_kvm_hook);
|
@ -4052,8 +4052,9 @@ static struct perf_guest_switch_msr *intel_guest_get_msrs(int *nr, void *data)
|
||||
/* Disable guest PEBS if host PEBS is enabled. */
|
||||
arr[pebs_enable].guest = 0;
|
||||
} else {
|
||||
/* Disable guest PEBS for cross-mapped PEBS counters. */
|
||||
/* Disable guest PEBS thoroughly for cross-mapped PEBS counters. */
|
||||
arr[pebs_enable].guest &= ~kvm_pmu->host_cross_mapped_mask;
|
||||
arr[global_ctrl].guest &= ~kvm_pmu->host_cross_mapped_mask;
|
||||
/* Set hw GLOBAL_CTRL bits for PEBS counter when it runs for guest */
|
||||
arr[global_ctrl].guest |= arr[pebs_enable].guest;
|
||||
}
|
||||
|
@ -5361,19 +5361,6 @@ void kvm_mmu_free_obsolete_roots(struct kvm_vcpu *vcpu)
|
||||
__kvm_mmu_free_obsolete_roots(vcpu->kvm, &vcpu->arch.guest_mmu);
|
||||
}
|
||||
|
||||
static bool need_remote_flush(u64 old, u64 new)
|
||||
{
|
||||
if (!is_shadow_present_pte(old))
|
||||
return false;
|
||||
if (!is_shadow_present_pte(new))
|
||||
return true;
|
||||
if ((old ^ new) & SPTE_BASE_ADDR_MASK)
|
||||
return true;
|
||||
old ^= shadow_nx_mask;
|
||||
new ^= shadow_nx_mask;
|
||||
return (old & ~new & SPTE_PERM_MASK) != 0;
|
||||
}
|
||||
|
||||
static u64 mmu_pte_write_fetch_gpte(struct kvm_vcpu *vcpu, gpa_t *gpa,
|
||||
int *bytes)
|
||||
{
|
||||
@ -5519,7 +5506,7 @@ static void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
|
||||
mmu_page_zap_pte(vcpu->kvm, sp, spte, NULL);
|
||||
if (gentry && sp->role.level != PG_LEVEL_4K)
|
||||
++vcpu->kvm->stat.mmu_pde_zapped;
|
||||
if (need_remote_flush(entry, *spte))
|
||||
if (is_shadow_present_pte(entry))
|
||||
flush = true;
|
||||
++spte;
|
||||
}
|
||||
@ -6085,47 +6072,18 @@ void kvm_mmu_slot_remove_write_access(struct kvm *kvm,
|
||||
const struct kvm_memory_slot *memslot,
|
||||
int start_level)
|
||||
{
|
||||
bool flush = false;
|
||||
|
||||
if (kvm_memslots_have_rmaps(kvm)) {
|
||||
write_lock(&kvm->mmu_lock);
|
||||
flush = slot_handle_level(kvm, memslot, slot_rmap_write_protect,
|
||||
start_level, KVM_MAX_HUGEPAGE_LEVEL,
|
||||
false);
|
||||
slot_handle_level(kvm, memslot, slot_rmap_write_protect,
|
||||
start_level, KVM_MAX_HUGEPAGE_LEVEL, false);
|
||||
write_unlock(&kvm->mmu_lock);
|
||||
}
|
||||
|
||||
if (is_tdp_mmu_enabled(kvm)) {
|
||||
read_lock(&kvm->mmu_lock);
|
||||
flush |= kvm_tdp_mmu_wrprot_slot(kvm, memslot, start_level);
|
||||
kvm_tdp_mmu_wrprot_slot(kvm, memslot, start_level);
|
||||
read_unlock(&kvm->mmu_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Flush TLBs if any SPTEs had to be write-protected to ensure that
|
||||
* guest writes are reflected in the dirty bitmap before the memslot
|
||||
* update completes, i.e. before enabling dirty logging is visible to
|
||||
* userspace.
|
||||
*
|
||||
* Perform the TLB flush outside the mmu_lock to reduce the amount of
|
||||
* time the lock is held. However, this does mean that another CPU can
|
||||
* now grab mmu_lock and encounter a write-protected SPTE while CPUs
|
||||
* still have a writable mapping for the associated GFN in their TLB.
|
||||
*
|
||||
* This is safe but requires KVM to be careful when making decisions
|
||||
* based on the write-protection status of an SPTE. Specifically, KVM
|
||||
* also write-protects SPTEs to monitor changes to guest page tables
|
||||
* during shadow paging, and must guarantee no CPUs can write to those
|
||||
* page before the lock is dropped. As mentioned in the previous
|
||||
* paragraph, a write-protected SPTE is no guarantee that CPU cannot
|
||||
* perform writes. So to determine if a TLB flush is truly required, KVM
|
||||
* will clear a separate software-only bit (MMU-writable) and skip the
|
||||
* flush if-and-only-if this bit was already clear.
|
||||
*
|
||||
* See is_writable_pte() for more details.
|
||||
*/
|
||||
if (flush)
|
||||
kvm_arch_flush_remote_tlbs_memslot(kvm, memslot);
|
||||
}
|
||||
|
||||
static inline bool need_topup(struct kvm_mmu_memory_cache *cache, int min)
|
||||
@ -6493,32 +6451,30 @@ void kvm_arch_flush_remote_tlbs_memslot(struct kvm *kvm,
|
||||
void kvm_mmu_slot_leaf_clear_dirty(struct kvm *kvm,
|
||||
const struct kvm_memory_slot *memslot)
|
||||
{
|
||||
bool flush = false;
|
||||
|
||||
if (kvm_memslots_have_rmaps(kvm)) {
|
||||
write_lock(&kvm->mmu_lock);
|
||||
/*
|
||||
* Clear dirty bits only on 4k SPTEs since the legacy MMU only
|
||||
* support dirty logging at a 4k granularity.
|
||||
*/
|
||||
flush = slot_handle_level_4k(kvm, memslot, __rmap_clear_dirty, false);
|
||||
slot_handle_level_4k(kvm, memslot, __rmap_clear_dirty, false);
|
||||
write_unlock(&kvm->mmu_lock);
|
||||
}
|
||||
|
||||
if (is_tdp_mmu_enabled(kvm)) {
|
||||
read_lock(&kvm->mmu_lock);
|
||||
flush |= kvm_tdp_mmu_clear_dirty_slot(kvm, memslot);
|
||||
kvm_tdp_mmu_clear_dirty_slot(kvm, memslot);
|
||||
read_unlock(&kvm->mmu_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* The caller will flush the TLBs after this function returns.
|
||||
*
|
||||
* It's also safe to flush TLBs out of mmu lock here as currently this
|
||||
* function is only used for dirty logging, in which case flushing TLB
|
||||
* out of mmu lock also guarantees no dirty pages will be lost in
|
||||
* dirty_bitmap.
|
||||
*/
|
||||
if (flush)
|
||||
kvm_arch_flush_remote_tlbs_memslot(kvm, memslot);
|
||||
}
|
||||
|
||||
void kvm_mmu_zap_all(struct kvm *kvm)
|
||||
|
@ -343,7 +343,7 @@ static __always_inline bool is_rsvd_spte(struct rsvd_bits_validate *rsvd_check,
|
||||
}
|
||||
|
||||
/*
|
||||
* An shadow-present leaf SPTE may be non-writable for 3 possible reasons:
|
||||
* A shadow-present leaf SPTE may be non-writable for 4 possible reasons:
|
||||
*
|
||||
* 1. To intercept writes for dirty logging. KVM write-protects huge pages
|
||||
* so that they can be split be split down into the dirty logging
|
||||
@ -361,8 +361,13 @@ static __always_inline bool is_rsvd_spte(struct rsvd_bits_validate *rsvd_check,
|
||||
* read-only memslot or guest memory backed by a read-only VMA. Writes to
|
||||
* such pages are disallowed entirely.
|
||||
*
|
||||
* To keep track of why a given SPTE is write-protected, KVM uses 2
|
||||
* software-only bits in the SPTE:
|
||||
* 4. To emulate the Accessed bit for SPTEs without A/D bits. Note, in this
|
||||
* case, the SPTE is access-protected, not just write-protected!
|
||||
*
|
||||
* For cases #1 and #4, KVM can safely make such SPTEs writable without taking
|
||||
* mmu_lock as capturing the Accessed/Dirty state doesn't require taking it.
|
||||
* To differentiate #1 and #4 from #2 and #3, KVM uses two software-only bits
|
||||
* in the SPTE:
|
||||
*
|
||||
* shadow_mmu_writable_mask, aka MMU-writable -
|
||||
* Cleared on SPTEs that KVM is currently write-protecting for shadow paging
|
||||
@ -391,7 +396,8 @@ static __always_inline bool is_rsvd_spte(struct rsvd_bits_validate *rsvd_check,
|
||||
* shadow page tables between vCPUs. Write-protecting an SPTE for dirty logging
|
||||
* (which does not clear the MMU-writable bit), does not flush TLBs before
|
||||
* dropping the lock, as it only needs to synchronize guest writes with the
|
||||
* dirty bitmap.
|
||||
* dirty bitmap. Similarly, making the SPTE inaccessible (and non-writable) for
|
||||
* access-tracking via the clear_young() MMU notifier also does not flush TLBs.
|
||||
*
|
||||
* So, there is the problem: clearing the MMU-writable bit can encounter a
|
||||
* write-protected SPTE while CPUs still have writable mappings for that SPTE
|
||||
|
@ -843,8 +843,7 @@ static bool msr_write_intercepted(struct vcpu_vmx *vmx, u32 msr)
|
||||
if (!(exec_controls_get(vmx) & CPU_BASED_USE_MSR_BITMAPS))
|
||||
return true;
|
||||
|
||||
return vmx_test_msr_bitmap_write(vmx->loaded_vmcs->msr_bitmap,
|
||||
MSR_IA32_SPEC_CTRL);
|
||||
return vmx_test_msr_bitmap_write(vmx->loaded_vmcs->msr_bitmap, msr);
|
||||
}
|
||||
|
||||
unsigned int __vmx_vcpu_run_flags(struct vcpu_vmx *vmx)
|
||||
|
@ -1557,12 +1557,32 @@ static const u32 msr_based_features_all[] = {
|
||||
static u32 msr_based_features[ARRAY_SIZE(msr_based_features_all)];
|
||||
static unsigned int num_msr_based_features;
|
||||
|
||||
/*
|
||||
* Some IA32_ARCH_CAPABILITIES bits have dependencies on MSRs that KVM
|
||||
* does not yet virtualize. These include:
|
||||
* 10 - MISC_PACKAGE_CTRLS
|
||||
* 11 - ENERGY_FILTERING_CTL
|
||||
* 12 - DOITM
|
||||
* 18 - FB_CLEAR_CTRL
|
||||
* 21 - XAPIC_DISABLE_STATUS
|
||||
* 23 - OVERCLOCKING_STATUS
|
||||
*/
|
||||
|
||||
#define KVM_SUPPORTED_ARCH_CAP \
|
||||
(ARCH_CAP_RDCL_NO | ARCH_CAP_IBRS_ALL | ARCH_CAP_RSBA | \
|
||||
ARCH_CAP_SKIP_VMENTRY_L1DFLUSH | ARCH_CAP_SSB_NO | ARCH_CAP_MDS_NO | \
|
||||
ARCH_CAP_PSCHANGE_MC_NO | ARCH_CAP_TSX_CTRL_MSR | ARCH_CAP_TAA_NO | \
|
||||
ARCH_CAP_SBDR_SSDP_NO | ARCH_CAP_FBSDP_NO | ARCH_CAP_PSDP_NO | \
|
||||
ARCH_CAP_FB_CLEAR | ARCH_CAP_RRSBA | ARCH_CAP_PBRSB_NO)
|
||||
|
||||
static u64 kvm_get_arch_capabilities(void)
|
||||
{
|
||||
u64 data = 0;
|
||||
|
||||
if (boot_cpu_has(X86_FEATURE_ARCH_CAPABILITIES))
|
||||
if (boot_cpu_has(X86_FEATURE_ARCH_CAPABILITIES)) {
|
||||
rdmsrl(MSR_IA32_ARCH_CAPABILITIES, data);
|
||||
data &= KVM_SUPPORTED_ARCH_CAP;
|
||||
}
|
||||
|
||||
/*
|
||||
* If nx_huge_pages is enabled, KVM's shadow paging will ensure that
|
||||
@ -1610,9 +1630,6 @@ static u64 kvm_get_arch_capabilities(void)
|
||||
*/
|
||||
}
|
||||
|
||||
/* Guests don't need to know "Fill buffer clear control" exists */
|
||||
data &= ~ARCH_CAP_FB_CLEAR_CTRL;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@ -10652,7 +10669,8 @@ static inline int vcpu_block(struct kvm_vcpu *vcpu)
|
||||
case KVM_MP_STATE_INIT_RECEIVED:
|
||||
break;
|
||||
default:
|
||||
return -EINTR;
|
||||
WARN_ON_ONCE(1);
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@ -11093,9 +11111,22 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
|
||||
|
||||
vcpu_load(vcpu);
|
||||
|
||||
if (!lapic_in_kernel(vcpu) &&
|
||||
mp_state->mp_state != KVM_MP_STATE_RUNNABLE)
|
||||
switch (mp_state->mp_state) {
|
||||
case KVM_MP_STATE_UNINITIALIZED:
|
||||
case KVM_MP_STATE_HALTED:
|
||||
case KVM_MP_STATE_AP_RESET_HOLD:
|
||||
case KVM_MP_STATE_INIT_RECEIVED:
|
||||
case KVM_MP_STATE_SIPI_RECEIVED:
|
||||
if (!lapic_in_kernel(vcpu))
|
||||
goto out;
|
||||
break;
|
||||
|
||||
case KVM_MP_STATE_RUNNABLE:
|
||||
break;
|
||||
|
||||
default:
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* KVM_MP_STATE_INIT_RECEIVED means the processor is in
|
||||
@ -11563,7 +11594,7 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
|
||||
vcpu->arch.mci_ctl2_banks = kcalloc(KVM_MAX_MCE_BANKS, sizeof(u64),
|
||||
GFP_KERNEL_ACCOUNT);
|
||||
if (!vcpu->arch.mce_banks || !vcpu->arch.mci_ctl2_banks)
|
||||
goto fail_free_pio_data;
|
||||
goto fail_free_mce_banks;
|
||||
vcpu->arch.mcg_cap = KVM_MAX_MCE_BANKS;
|
||||
|
||||
if (!zalloc_cpumask_var(&vcpu->arch.wbinvd_dirty_mask,
|
||||
@ -11617,7 +11648,6 @@ free_wbinvd_dirty_mask:
|
||||
fail_free_mce_banks:
|
||||
kfree(vcpu->arch.mce_banks);
|
||||
kfree(vcpu->arch.mci_ctl2_banks);
|
||||
fail_free_pio_data:
|
||||
free_page((unsigned long)vcpu->arch.pio_data);
|
||||
fail_free_lapic:
|
||||
kvm_free_lapic(vcpu);
|
||||
@ -12473,6 +12503,50 @@ static void kvm_mmu_slot_apply_flags(struct kvm *kvm,
|
||||
} else {
|
||||
kvm_mmu_slot_remove_write_access(kvm, new, PG_LEVEL_4K);
|
||||
}
|
||||
|
||||
/*
|
||||
* Unconditionally flush the TLBs after enabling dirty logging.
|
||||
* A flush is almost always going to be necessary (see below),
|
||||
* and unconditionally flushing allows the helpers to omit
|
||||
* the subtly complex checks when removing write access.
|
||||
*
|
||||
* Do the flush outside of mmu_lock to reduce the amount of
|
||||
* time mmu_lock is held. Flushing after dropping mmu_lock is
|
||||
* safe as KVM only needs to guarantee the slot is fully
|
||||
* write-protected before returning to userspace, i.e. before
|
||||
* userspace can consume the dirty status.
|
||||
*
|
||||
* Flushing outside of mmu_lock requires KVM to be careful when
|
||||
* making decisions based on writable status of an SPTE, e.g. a
|
||||
* !writable SPTE doesn't guarantee a CPU can't perform writes.
|
||||
*
|
||||
* Specifically, KVM also write-protects guest page tables to
|
||||
* monitor changes when using shadow paging, and must guarantee
|
||||
* no CPUs can write to those page before mmu_lock is dropped.
|
||||
* Because CPUs may have stale TLB entries at this point, a
|
||||
* !writable SPTE doesn't guarantee CPUs can't perform writes.
|
||||
*
|
||||
* KVM also allows making SPTES writable outside of mmu_lock,
|
||||
* e.g. to allow dirty logging without taking mmu_lock.
|
||||
*
|
||||
* To handle these scenarios, KVM uses a separate software-only
|
||||
* bit (MMU-writable) to track if a SPTE is !writable due to
|
||||
* a guest page table being write-protected (KVM clears the
|
||||
* MMU-writable flag when write-protecting for shadow paging).
|
||||
*
|
||||
* The use of MMU-writable is also the primary motivation for
|
||||
* the unconditional flush. Because KVM must guarantee that a
|
||||
* CPU doesn't contain stale, writable TLB entries for a
|
||||
* !MMU-writable SPTE, KVM must flush if it encounters any
|
||||
* MMU-writable SPTE regardless of whether the actual hardware
|
||||
* writable bit was set. I.e. KVM is almost guaranteed to need
|
||||
* to flush, while unconditionally flushing allows the "remove
|
||||
* write access" helpers to ignore MMU-writable entirely.
|
||||
*
|
||||
* See is_writable_pte() for more details (the case involving
|
||||
* access-tracked SPTEs is particularly relevant).
|
||||
*/
|
||||
kvm_arch_flush_remote_tlbs_memslot(kvm, new);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -209,6 +209,7 @@ static int amba_match(struct device *dev, struct device_driver *drv)
|
||||
struct amba_device *pcdev = to_amba_device(dev);
|
||||
struct amba_driver *pcdrv = to_amba_driver(drv);
|
||||
|
||||
mutex_lock(&pcdev->periphid_lock);
|
||||
if (!pcdev->periphid) {
|
||||
int ret = amba_read_periphid(pcdev);
|
||||
|
||||
@ -218,11 +219,14 @@ static int amba_match(struct device *dev, struct device_driver *drv)
|
||||
* permanent failure in reading pid and cid, simply map it to
|
||||
* -EPROBE_DEFER.
|
||||
*/
|
||||
if (ret)
|
||||
if (ret) {
|
||||
mutex_unlock(&pcdev->periphid_lock);
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
dev_set_uevent_suppress(dev, false);
|
||||
kobject_uevent(&dev->kobj, KOBJ_ADD);
|
||||
}
|
||||
mutex_unlock(&pcdev->periphid_lock);
|
||||
|
||||
/* When driver_override is set, only bind to the matching driver */
|
||||
if (pcdev->driver_override)
|
||||
@ -532,6 +536,7 @@ static void amba_device_release(struct device *dev)
|
||||
|
||||
if (d->res.parent)
|
||||
release_resource(&d->res);
|
||||
mutex_destroy(&d->periphid_lock);
|
||||
kfree(d);
|
||||
}
|
||||
|
||||
@ -584,6 +589,7 @@ static void amba_device_initialize(struct amba_device *dev, const char *name)
|
||||
dev->dev.dma_mask = &dev->dev.coherent_dma_mask;
|
||||
dev->dev.dma_parms = &dev->dma_parms;
|
||||
dev->res.name = dev_name(&dev->dev);
|
||||
mutex_init(&dev->periphid_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1385,6 +1385,18 @@ static int binder_inc_ref_for_node(struct binder_proc *proc,
|
||||
}
|
||||
ret = binder_inc_ref_olocked(ref, strong, target_list);
|
||||
*rdata = ref->data;
|
||||
if (ret && ref == new_ref) {
|
||||
/*
|
||||
* Cleanup the failed reference here as the target
|
||||
* could now be dead and have already released its
|
||||
* references by now. Calling on the new reference
|
||||
* with strong=0 and a tmp_refs will not decrement
|
||||
* the node. The new_ref gets kfree'd below.
|
||||
*/
|
||||
binder_cleanup_ref_olocked(new_ref);
|
||||
ref = NULL;
|
||||
}
|
||||
|
||||
binder_proc_unlock(proc);
|
||||
if (new_ref && ref != new_ref)
|
||||
/*
|
||||
|
@ -322,7 +322,6 @@ static inline void binder_alloc_set_vma(struct binder_alloc *alloc,
|
||||
*/
|
||||
if (vma) {
|
||||
vm_start = vma->vm_start;
|
||||
alloc->vma_vm_mm = vma->vm_mm;
|
||||
mmap_assert_write_locked(alloc->vma_vm_mm);
|
||||
} else {
|
||||
mmap_assert_locked(alloc->vma_vm_mm);
|
||||
@ -795,7 +794,6 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc,
|
||||
binder_insert_free_buffer(alloc, buffer);
|
||||
alloc->free_async_space = alloc->buffer_size / 2;
|
||||
binder_alloc_set_vma(alloc, vma);
|
||||
mmgrab(alloc->vma_vm_mm);
|
||||
|
||||
return 0;
|
||||
|
||||
@ -1091,6 +1089,8 @@ static struct shrinker binder_shrinker = {
|
||||
void binder_alloc_init(struct binder_alloc *alloc)
|
||||
{
|
||||
alloc->pid = current->group_leader->pid;
|
||||
alloc->vma_vm_mm = current->mm;
|
||||
mmgrab(alloc->vma_vm_mm);
|
||||
mutex_init(&alloc->mutex);
|
||||
INIT_LIST_HEAD(&alloc->buffers);
|
||||
}
|
||||
|
@ -735,7 +735,7 @@ void update_siblings_masks(unsigned int cpuid)
|
||||
int cpu, ret;
|
||||
|
||||
ret = detect_cache_attributes(cpuid);
|
||||
if (ret)
|
||||
if (ret && ret != -ENOENT)
|
||||
pr_info("Early cacheinfo failed, ret = %d\n", ret);
|
||||
|
||||
/* update core and thread sibling masks */
|
||||
|
@ -274,12 +274,42 @@ static int __init deferred_probe_timeout_setup(char *str)
|
||||
}
|
||||
__setup("deferred_probe_timeout=", deferred_probe_timeout_setup);
|
||||
|
||||
/**
|
||||
* driver_deferred_probe_check_state() - Check deferred probe state
|
||||
* @dev: device to check
|
||||
*
|
||||
* Return:
|
||||
* * -ENODEV if initcalls have completed and modules are disabled.
|
||||
* * -ETIMEDOUT if the deferred probe timeout was set and has expired
|
||||
* and modules are enabled.
|
||||
* * -EPROBE_DEFER in other cases.
|
||||
*
|
||||
* Drivers or subsystems can opt-in to calling this function instead of directly
|
||||
* returning -EPROBE_DEFER.
|
||||
*/
|
||||
int driver_deferred_probe_check_state(struct device *dev)
|
||||
{
|
||||
if (!IS_ENABLED(CONFIG_MODULES) && initcalls_done) {
|
||||
dev_warn(dev, "ignoring dependency for device, assuming no driver\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!driver_deferred_probe_timeout && initcalls_done) {
|
||||
dev_warn(dev, "deferred probe timeout, ignoring dependency\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(driver_deferred_probe_check_state);
|
||||
|
||||
static void deferred_probe_timeout_work_func(struct work_struct *work)
|
||||
{
|
||||
struct device_private *p;
|
||||
|
||||
fw_devlink_drivers_done();
|
||||
|
||||
driver_deferred_probe_timeout = 0;
|
||||
driver_deferred_probe_trigger();
|
||||
flush_work(&deferred_probe_work);
|
||||
|
||||
@ -881,6 +911,11 @@ static int __device_attach_driver(struct device_driver *drv, void *_data)
|
||||
dev_dbg(dev, "Device match requests probe deferral\n");
|
||||
dev->can_match = true;
|
||||
driver_deferred_probe_add(dev);
|
||||
/*
|
||||
* Device can't match with a driver right now, so don't attempt
|
||||
* to match or bind with other drivers on the bus.
|
||||
*/
|
||||
return ret;
|
||||
} else if (ret < 0) {
|
||||
dev_dbg(dev, "Bus failed to match device: %d\n", ret);
|
||||
return ret;
|
||||
@ -1120,6 +1155,11 @@ static int __driver_attach(struct device *dev, void *data)
|
||||
dev_dbg(dev, "Device match requests probe deferral\n");
|
||||
dev->can_match = true;
|
||||
driver_deferred_probe_add(dev);
|
||||
/*
|
||||
* Driver could not match with device, but may match with
|
||||
* another device on the bus.
|
||||
*/
|
||||
return 0;
|
||||
} else if (ret < 0) {
|
||||
dev_dbg(dev, "Bus failed to match device: %d\n", ret);
|
||||
return ret;
|
||||
|
@ -93,10 +93,9 @@ static void fw_dev_release(struct device *dev)
|
||||
{
|
||||
struct fw_sysfs *fw_sysfs = to_fw_sysfs(dev);
|
||||
|
||||
if (fw_sysfs->fw_upload_priv) {
|
||||
free_fw_priv(fw_sysfs->fw_priv);
|
||||
kfree(fw_sysfs->fw_upload_priv);
|
||||
}
|
||||
if (fw_sysfs->fw_upload_priv)
|
||||
fw_upload_free(fw_sysfs);
|
||||
|
||||
kfree(fw_sysfs);
|
||||
}
|
||||
|
||||
|
@ -106,12 +106,17 @@ extern struct device_attribute dev_attr_cancel;
|
||||
extern struct device_attribute dev_attr_remaining_size;
|
||||
|
||||
int fw_upload_start(struct fw_sysfs *fw_sysfs);
|
||||
void fw_upload_free(struct fw_sysfs *fw_sysfs);
|
||||
umode_t fw_upload_is_visible(struct kobject *kobj, struct attribute *attr, int n);
|
||||
#else
|
||||
static inline int fw_upload_start(struct fw_sysfs *fw_sysfs)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void fw_upload_free(struct fw_sysfs *fw_sysfs)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __FIRMWARE_SYSFS_H */
|
||||
|
@ -264,6 +264,15 @@ int fw_upload_start(struct fw_sysfs *fw_sysfs)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void fw_upload_free(struct fw_sysfs *fw_sysfs)
|
||||
{
|
||||
struct fw_upload_priv *fw_upload_priv = fw_sysfs->fw_upload_priv;
|
||||
|
||||
free_fw_priv(fw_sysfs->fw_priv);
|
||||
kfree(fw_upload_priv->fw_upload);
|
||||
kfree(fw_upload_priv);
|
||||
}
|
||||
|
||||
/**
|
||||
* firmware_upload_register() - register for the firmware upload sysfs API
|
||||
* @module: kernel module of this device
|
||||
@ -377,6 +386,7 @@ void firmware_upload_unregister(struct fw_upload *fw_upload)
|
||||
{
|
||||
struct fw_sysfs *fw_sysfs = fw_upload->priv;
|
||||
struct fw_upload_priv *fw_upload_priv = fw_sysfs->fw_upload_priv;
|
||||
struct module *module = fw_upload_priv->module;
|
||||
|
||||
mutex_lock(&fw_upload_priv->lock);
|
||||
if (fw_upload_priv->progress == FW_UPLOAD_PROG_IDLE) {
|
||||
@ -392,6 +402,6 @@ void firmware_upload_unregister(struct fw_upload *fw_upload)
|
||||
|
||||
unregister:
|
||||
device_unregister(&fw_sysfs->dev);
|
||||
module_put(fw_upload_priv->module);
|
||||
module_put(module);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(firmware_upload_unregister);
|
||||
|
@ -2733,7 +2733,7 @@ static int __genpd_dev_pm_attach(struct device *dev, struct device *base_dev,
|
||||
mutex_unlock(&gpd_list_lock);
|
||||
dev_dbg(dev, "%s() failed to find PM domain: %ld\n",
|
||||
__func__, PTR_ERR(pd));
|
||||
return -ENODEV;
|
||||
return driver_deferred_probe_check_state(base_dev);
|
||||
}
|
||||
|
||||
dev_dbg(dev, "adding to PM domain %s\n", pd->name);
|
||||
|
@ -226,6 +226,9 @@ struct xen_vbd {
|
||||
sector_t size;
|
||||
unsigned int flush_support:1;
|
||||
unsigned int discard_secure:1;
|
||||
/* Connect-time cached feature_persistent parameter value */
|
||||
unsigned int feature_gnt_persistent_parm:1;
|
||||
/* Persistent grants feature negotiation result */
|
||||
unsigned int feature_gnt_persistent:1;
|
||||
unsigned int overflow_max_grants:1;
|
||||
};
|
||||
|
@ -907,7 +907,7 @@ again:
|
||||
xen_blkbk_barrier(xbt, be, be->blkif->vbd.flush_support);
|
||||
|
||||
err = xenbus_printf(xbt, dev->nodename, "feature-persistent", "%u",
|
||||
be->blkif->vbd.feature_gnt_persistent);
|
||||
be->blkif->vbd.feature_gnt_persistent_parm);
|
||||
if (err) {
|
||||
xenbus_dev_fatal(dev, err, "writing %s/feature-persistent",
|
||||
dev->nodename);
|
||||
@ -1085,7 +1085,9 @@ static int connect_ring(struct backend_info *be)
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
blkif->vbd.feature_gnt_persistent = feature_persistent &&
|
||||
blkif->vbd.feature_gnt_persistent_parm = feature_persistent;
|
||||
blkif->vbd.feature_gnt_persistent =
|
||||
blkif->vbd.feature_gnt_persistent_parm &&
|
||||
xenbus_read_unsigned(dev->otherend, "feature-persistent", 0);
|
||||
|
||||
blkif->vbd.overflow_max_grants = 0;
|
||||
|
@ -213,6 +213,9 @@ struct blkfront_info
|
||||
unsigned int feature_fua:1;
|
||||
unsigned int feature_discard:1;
|
||||
unsigned int feature_secdiscard:1;
|
||||
/* Connect-time cached feature_persistent parameter */
|
||||
unsigned int feature_persistent_parm:1;
|
||||
/* Persistent grants feature negotiation result */
|
||||
unsigned int feature_persistent:1;
|
||||
unsigned int bounce:1;
|
||||
unsigned int discard_granularity;
|
||||
@ -1756,6 +1759,12 @@ abort_transaction:
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Enable the persistent grants feature. */
|
||||
static bool feature_persistent = true;
|
||||
module_param(feature_persistent, bool, 0644);
|
||||
MODULE_PARM_DESC(feature_persistent,
|
||||
"Enables the persistent grants feature");
|
||||
|
||||
/* Common code used when first setting up, and when resuming. */
|
||||
static int talk_to_blkback(struct xenbus_device *dev,
|
||||
struct blkfront_info *info)
|
||||
@ -1847,8 +1856,9 @@ again:
|
||||
message = "writing protocol";
|
||||
goto abort_transaction;
|
||||
}
|
||||
info->feature_persistent_parm = feature_persistent;
|
||||
err = xenbus_printf(xbt, dev->nodename, "feature-persistent", "%u",
|
||||
info->feature_persistent);
|
||||
info->feature_persistent_parm);
|
||||
if (err)
|
||||
dev_warn(&dev->dev,
|
||||
"writing persistent grants feature to xenbus");
|
||||
@ -1916,12 +1926,6 @@ static int negotiate_mq(struct blkfront_info *info)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Enable the persistent grants feature. */
|
||||
static bool feature_persistent = true;
|
||||
module_param(feature_persistent, bool, 0644);
|
||||
MODULE_PARM_DESC(feature_persistent,
|
||||
"Enables the persistent grants feature");
|
||||
|
||||
/*
|
||||
* Entry point to this code when a new device is created. Allocate the basic
|
||||
* structures and the ring buffer for communication with the backend, and
|
||||
@ -2281,7 +2285,7 @@ static void blkfront_gather_backend_features(struct blkfront_info *info)
|
||||
if (xenbus_read_unsigned(info->xbdev->otherend, "feature-discard", 0))
|
||||
blkfront_setup_discard(info);
|
||||
|
||||
if (feature_persistent)
|
||||
if (info->feature_persistent_parm)
|
||||
info->feature_persistent =
|
||||
!!xenbus_read_unsigned(info->xbdev->otherend,
|
||||
"feature-persistent", 0);
|
||||
|
@ -430,12 +430,25 @@ irqreturn_t mhi_irq_handler(int irq_number, void *dev)
|
||||
{
|
||||
struct mhi_event *mhi_event = dev;
|
||||
struct mhi_controller *mhi_cntrl = mhi_event->mhi_cntrl;
|
||||
struct mhi_event_ctxt *er_ctxt =
|
||||
&mhi_cntrl->mhi_ctxt->er_ctxt[mhi_event->er_index];
|
||||
struct mhi_event_ctxt *er_ctxt;
|
||||
struct mhi_ring *ev_ring = &mhi_event->ring;
|
||||
dma_addr_t ptr = le64_to_cpu(er_ctxt->rp);
|
||||
dma_addr_t ptr;
|
||||
void *dev_rp;
|
||||
|
||||
/*
|
||||
* If CONFIG_DEBUG_SHIRQ is set, the IRQ handler will get invoked during __free_irq()
|
||||
* and by that time mhi_ctxt() would've freed. So check for the existence of mhi_ctxt
|
||||
* before handling the IRQs.
|
||||
*/
|
||||
if (!mhi_cntrl->mhi_ctxt) {
|
||||
dev_dbg(&mhi_cntrl->mhi_dev->dev,
|
||||
"mhi_ctxt has been freed\n");
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
er_ctxt = &mhi_cntrl->mhi_ctxt->er_ctxt[mhi_event->er_index];
|
||||
ptr = le64_to_cpu(er_ctxt->rp);
|
||||
|
||||
if (!is_valid_ring_ptr(ev_ring, ptr)) {
|
||||
dev_err(&mhi_cntrl->mhi_dev->dev,
|
||||
"Event ring rp points outside of the event ring\n");
|
||||
|
@ -203,7 +203,7 @@ static unsigned long raspberrypi_fw_get_rate(struct clk_hw *hw,
|
||||
ret = raspberrypi_clock_property(rpi->firmware, data,
|
||||
RPI_FIRMWARE_GET_CLOCK_RATE, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
return 0;
|
||||
|
||||
return val;
|
||||
}
|
||||
@ -220,7 +220,7 @@ static int raspberrypi_fw_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
ret = raspberrypi_clock_property(rpi->firmware, data,
|
||||
RPI_FIRMWARE_SET_CLOCK_RATE, &_rate);
|
||||
if (ret)
|
||||
dev_err_ratelimited(rpi->dev, "Failed to change %s frequency: %d",
|
||||
dev_err_ratelimited(rpi->dev, "Failed to change %s frequency: %d\n",
|
||||
clk_hw_get_name(hw), ret);
|
||||
|
||||
return ret;
|
||||
@ -288,7 +288,7 @@ static struct clk_hw *raspberrypi_clk_register(struct raspberrypi_clk *rpi,
|
||||
RPI_FIRMWARE_GET_MIN_CLOCK_RATE,
|
||||
&min_rate);
|
||||
if (ret) {
|
||||
dev_err(rpi->dev, "Failed to get clock %d min freq: %d",
|
||||
dev_err(rpi->dev, "Failed to get clock %d min freq: %d\n",
|
||||
id, ret);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
@ -344,8 +344,13 @@ static int raspberrypi_discover_clocks(struct raspberrypi_clk *rpi,
|
||||
struct rpi_firmware_get_clocks_response *clks;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* The firmware doesn't guarantee that the last element of
|
||||
* RPI_FIRMWARE_GET_CLOCKS is zeroed. So allocate an additional
|
||||
* zero element as sentinel.
|
||||
*/
|
||||
clks = devm_kcalloc(rpi->dev,
|
||||
RPI_FIRMWARE_NUM_CLK_ID, sizeof(*clks),
|
||||
RPI_FIRMWARE_NUM_CLK_ID + 1, sizeof(*clks),
|
||||
GFP_KERNEL);
|
||||
if (!clks)
|
||||
return -ENOMEM;
|
||||
@ -360,7 +365,8 @@ static int raspberrypi_discover_clocks(struct raspberrypi_clk *rpi,
|
||||
struct raspberrypi_clk_variant *variant;
|
||||
|
||||
if (clks->id > RPI_FIRMWARE_NUM_CLK_ID) {
|
||||
dev_err(rpi->dev, "Unknown clock id: %u", clks->id);
|
||||
dev_err(rpi->dev, "Unknown clock id: %u (max: %u)\n",
|
||||
clks->id, RPI_FIRMWARE_NUM_CLK_ID);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -840,10 +840,9 @@ static void clk_core_unprepare(struct clk_core *core)
|
||||
if (core->ops->unprepare)
|
||||
core->ops->unprepare(core->hw);
|
||||
|
||||
clk_pm_runtime_put(core);
|
||||
|
||||
trace_clk_unprepare_complete(core);
|
||||
clk_core_unprepare(core->parent);
|
||||
clk_pm_runtime_put(core);
|
||||
}
|
||||
|
||||
static void clk_core_unprepare_lock(struct clk_core *core)
|
||||
|
@ -135,6 +135,7 @@ static struct device_node *ti_find_clock_provider(struct device_node *from,
|
||||
continue;
|
||||
|
||||
if (!strncmp(n, tmp, strlen(tmp))) {
|
||||
of_node_get(np);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
@ -295,7 +295,8 @@ void dma_resv_add_fence(struct dma_resv *obj, struct dma_fence *fence,
|
||||
enum dma_resv_usage old_usage;
|
||||
|
||||
dma_resv_list_entry(fobj, i, obj, &old, &old_usage);
|
||||
if ((old->context == fence->context && old_usage >= usage) ||
|
||||
if ((old->context == fence->context && old_usage >= usage &&
|
||||
dma_fence_is_later(fence, old)) ||
|
||||
dma_fence_is_signaled(old)) {
|
||||
dma_resv_list_set(fobj, i, fence, usage);
|
||||
dma_fence_put(old);
|
||||
|
@ -242,29 +242,6 @@ failed:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* efi_capsule_flush - called by file close or file flush
|
||||
* @file: file pointer
|
||||
* @id: not used
|
||||
*
|
||||
* If a capsule is being partially uploaded then calling this function
|
||||
* will be treated as upload termination and will free those completed
|
||||
* buffer pages and -ECANCELED will be returned.
|
||||
**/
|
||||
static int efi_capsule_flush(struct file *file, fl_owner_t id)
|
||||
{
|
||||
int ret = 0;
|
||||
struct capsule_info *cap_info = file->private_data;
|
||||
|
||||
if (cap_info->index > 0) {
|
||||
pr_err("capsule upload not complete\n");
|
||||
efi_free_all_buff_pages(cap_info);
|
||||
ret = -ECANCELED;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* efi_capsule_release - called by file close
|
||||
* @inode: not used
|
||||
@ -277,6 +254,13 @@ static int efi_capsule_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct capsule_info *cap_info = file->private_data;
|
||||
|
||||
if (cap_info->index > 0 &&
|
||||
(cap_info->header.headersize == 0 ||
|
||||
cap_info->count < cap_info->total_size)) {
|
||||
pr_err("capsule upload not complete\n");
|
||||
efi_free_all_buff_pages(cap_info);
|
||||
}
|
||||
|
||||
kfree(cap_info->pages);
|
||||
kfree(cap_info->phys);
|
||||
kfree(file->private_data);
|
||||
@ -324,7 +308,6 @@ static const struct file_operations efi_capsule_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = efi_capsule_open,
|
||||
.write = efi_capsule_write,
|
||||
.flush = efi_capsule_flush,
|
||||
.release = efi_capsule_release,
|
||||
.llseek = no_llseek,
|
||||
};
|
||||
|
@ -37,6 +37,13 @@ KBUILD_CFLAGS := $(cflags-y) -Os -DDISABLE_BRANCH_PROFILING \
|
||||
$(call cc-option,-fno-addrsig) \
|
||||
-D__DISABLE_EXPORTS
|
||||
|
||||
#
|
||||
# struct randomization only makes sense for Linux internal types, which the EFI
|
||||
# stub code never touches, so let's turn off struct randomization for the stub
|
||||
# altogether
|
||||
#
|
||||
KBUILD_CFLAGS := $(filter-out $(RANDSTRUCT_CFLAGS), $(KBUILD_CFLAGS))
|
||||
|
||||
# remove SCS flags from all objects in this directory
|
||||
KBUILD_CFLAGS := $(filter-out $(CC_FLAGS_SCS), $(KBUILD_CFLAGS))
|
||||
# disable LTO
|
||||
|
@ -220,7 +220,6 @@ adjust_memory_range_protection(unsigned long start, unsigned long size)
|
||||
unsigned long end, next;
|
||||
unsigned long rounded_start, rounded_end;
|
||||
unsigned long unprotect_start, unprotect_size;
|
||||
int has_system_memory = 0;
|
||||
|
||||
if (efi_dxe_table == NULL)
|
||||
return;
|
||||
|
@ -164,6 +164,7 @@ static void dio48e_irq_mask(struct irq_data *data)
|
||||
dio48egpio->irq_mask &= ~BIT(0);
|
||||
else
|
||||
dio48egpio->irq_mask &= ~BIT(1);
|
||||
gpiochip_disable_irq(chip, offset);
|
||||
|
||||
if (!dio48egpio->irq_mask)
|
||||
/* disable interrupts */
|
||||
@ -191,6 +192,7 @@ static void dio48e_irq_unmask(struct irq_data *data)
|
||||
iowrite8(0x00, &dio48egpio->reg->enable_interrupt);
|
||||
}
|
||||
|
||||
gpiochip_enable_irq(chip, offset);
|
||||
if (offset == 19)
|
||||
dio48egpio->irq_mask |= BIT(0);
|
||||
else
|
||||
@ -213,12 +215,14 @@ static int dio48e_irq_set_type(struct irq_data *data, unsigned int flow_type)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_chip dio48e_irqchip = {
|
||||
static const struct irq_chip dio48e_irqchip = {
|
||||
.name = "104-dio-48e",
|
||||
.irq_ack = dio48e_irq_ack,
|
||||
.irq_mask = dio48e_irq_mask,
|
||||
.irq_unmask = dio48e_irq_unmask,
|
||||
.irq_set_type = dio48e_irq_set_type
|
||||
.irq_set_type = dio48e_irq_set_type,
|
||||
.flags = IRQCHIP_IMMUTABLE,
|
||||
GPIOCHIP_IRQ_RESOURCE_HELPERS,
|
||||
};
|
||||
|
||||
static irqreturn_t dio48e_irq_handler(int irq, void *dev_id)
|
||||
@ -322,7 +326,7 @@ static int dio48e_probe(struct device *dev, unsigned int id)
|
||||
dio48egpio->chip.set_multiple = dio48e_gpio_set_multiple;
|
||||
|
||||
girq = &dio48egpio->chip.irq;
|
||||
girq->chip = &dio48e_irqchip;
|
||||
gpio_irq_chip_set_chip(girq, &dio48e_irqchip);
|
||||
/* This will let us handle the parent IRQ in the driver */
|
||||
girq->parent_handler = NULL;
|
||||
girq->num_parents = 0;
|
||||
|
@ -113,6 +113,7 @@ static void idi_48_irq_mask(struct irq_data *data)
|
||||
spin_lock_irqsave(&idi48gpio->lock, flags);
|
||||
|
||||
idi48gpio->irq_mask[boundary] &= ~mask;
|
||||
gpiochip_disable_irq(chip, offset);
|
||||
|
||||
/* Exit early if there are still input lines with IRQ unmasked */
|
||||
if (idi48gpio->irq_mask[boundary])
|
||||
@ -140,6 +141,7 @@ static void idi_48_irq_unmask(struct irq_data *data)
|
||||
|
||||
prev_irq_mask = idi48gpio->irq_mask[boundary];
|
||||
|
||||
gpiochip_enable_irq(chip, offset);
|
||||
idi48gpio->irq_mask[boundary] |= mask;
|
||||
|
||||
/* Exit early if IRQ was already unmasked for this boundary */
|
||||
@ -164,12 +166,14 @@ static int idi_48_irq_set_type(struct irq_data *data, unsigned int flow_type)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_chip idi_48_irqchip = {
|
||||
static const struct irq_chip idi_48_irqchip = {
|
||||
.name = "104-idi-48",
|
||||
.irq_ack = idi_48_irq_ack,
|
||||
.irq_mask = idi_48_irq_mask,
|
||||
.irq_unmask = idi_48_irq_unmask,
|
||||
.irq_set_type = idi_48_irq_set_type
|
||||
.irq_set_type = idi_48_irq_set_type,
|
||||
.flags = IRQCHIP_IMMUTABLE,
|
||||
GPIOCHIP_IRQ_RESOURCE_HELPERS,
|
||||
};
|
||||
|
||||
static irqreturn_t idi_48_irq_handler(int irq, void *dev_id)
|
||||
@ -267,7 +271,7 @@ static int idi_48_probe(struct device *dev, unsigned int id)
|
||||
idi48gpio->chip.get_multiple = idi_48_gpio_get_multiple;
|
||||
|
||||
girq = &idi48gpio->chip.irq;
|
||||
girq->chip = &idi_48_irqchip;
|
||||
gpio_irq_chip_set_chip(girq, &idi_48_irqchip);
|
||||
/* This will let us handle the parent IRQ in the driver */
|
||||
girq->parent_handler = NULL;
|
||||
girq->num_parents = 0;
|
||||
|
@ -174,10 +174,11 @@ static void idio_16_irq_mask(struct irq_data *data)
|
||||
{
|
||||
struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
|
||||
struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
|
||||
const unsigned long mask = BIT(irqd_to_hwirq(data));
|
||||
const unsigned long offset = irqd_to_hwirq(data);
|
||||
unsigned long flags;
|
||||
|
||||
idio16gpio->irq_mask &= ~mask;
|
||||
idio16gpio->irq_mask &= ~BIT(offset);
|
||||
gpiochip_disable_irq(chip, offset);
|
||||
|
||||
if (!idio16gpio->irq_mask) {
|
||||
raw_spin_lock_irqsave(&idio16gpio->lock, flags);
|
||||
@ -192,11 +193,12 @@ static void idio_16_irq_unmask(struct irq_data *data)
|
||||
{
|
||||
struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
|
||||
struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
|
||||
const unsigned long mask = BIT(irqd_to_hwirq(data));
|
||||
const unsigned long offset = irqd_to_hwirq(data);
|
||||
const unsigned long prev_irq_mask = idio16gpio->irq_mask;
|
||||
unsigned long flags;
|
||||
|
||||
idio16gpio->irq_mask |= mask;
|
||||
gpiochip_enable_irq(chip, offset);
|
||||
idio16gpio->irq_mask |= BIT(offset);
|
||||
|
||||
if (!prev_irq_mask) {
|
||||
raw_spin_lock_irqsave(&idio16gpio->lock, flags);
|
||||
@ -217,12 +219,14 @@ static int idio_16_irq_set_type(struct irq_data *data, unsigned int flow_type)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_chip idio_16_irqchip = {
|
||||
static const struct irq_chip idio_16_irqchip = {
|
||||
.name = "104-idio-16",
|
||||
.irq_ack = idio_16_irq_ack,
|
||||
.irq_mask = idio_16_irq_mask,
|
||||
.irq_unmask = idio_16_irq_unmask,
|
||||
.irq_set_type = idio_16_irq_set_type
|
||||
.irq_set_type = idio_16_irq_set_type,
|
||||
.flags = IRQCHIP_IMMUTABLE,
|
||||
GPIOCHIP_IRQ_RESOURCE_HELPERS,
|
||||
};
|
||||
|
||||
static irqreturn_t idio_16_irq_handler(int irq, void *dev_id)
|
||||
@ -299,7 +303,7 @@ static int idio_16_probe(struct device *dev, unsigned int id)
|
||||
idio16gpio->out_state = 0xFFFF;
|
||||
|
||||
girq = &idio16gpio->chip.irq;
|
||||
girq->chip = &idio_16_irqchip;
|
||||
gpio_irq_chip_set_chip(girq, &idio_16_irqchip);
|
||||
/* This will let us handle the parent IRQ in the driver */
|
||||
girq->parent_handler = NULL;
|
||||
girq->num_parents = 0;
|
||||
|
@ -373,6 +373,13 @@ static void gpio_mockup_debugfs_setup(struct device *dev,
|
||||
}
|
||||
}
|
||||
|
||||
static void gpio_mockup_debugfs_cleanup(void *data)
|
||||
{
|
||||
struct gpio_mockup_chip *chip = data;
|
||||
|
||||
debugfs_remove_recursive(chip->dbg_dir);
|
||||
}
|
||||
|
||||
static void gpio_mockup_dispose_mappings(void *data)
|
||||
{
|
||||
struct gpio_mockup_chip *chip = data;
|
||||
@ -455,7 +462,7 @@ static int gpio_mockup_probe(struct platform_device *pdev)
|
||||
|
||||
gpio_mockup_debugfs_setup(dev, chip);
|
||||
|
||||
return 0;
|
||||
return devm_add_action_or_reset(dev, gpio_mockup_debugfs_cleanup, chip);
|
||||
}
|
||||
|
||||
static const struct of_device_id gpio_mockup_of_match[] = {
|
||||
|
@ -1175,7 +1175,9 @@ static int pca953x_suspend(struct device *dev)
|
||||
{
|
||||
struct pca953x_chip *chip = dev_get_drvdata(dev);
|
||||
|
||||
mutex_lock(&chip->i2c_lock);
|
||||
regcache_cache_only(chip->regmap, true);
|
||||
mutex_unlock(&chip->i2c_lock);
|
||||
|
||||
if (atomic_read(&chip->wakeup_path))
|
||||
device_set_wakeup_path(dev);
|
||||
@ -1198,13 +1200,17 @@ static int pca953x_resume(struct device *dev)
|
||||
}
|
||||
}
|
||||
|
||||
mutex_lock(&chip->i2c_lock);
|
||||
regcache_cache_only(chip->regmap, false);
|
||||
regcache_mark_dirty(chip->regmap);
|
||||
ret = pca953x_regcache_sync(dev);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
mutex_unlock(&chip->i2c_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regcache_sync(chip->regmap);
|
||||
mutex_unlock(&chip->i2c_lock);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to restore register map: %d\n", ret);
|
||||
return ret;
|
||||
|
@ -661,24 +661,17 @@ static int pxa_gpio_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(gpio_reg_base))
|
||||
return PTR_ERR(gpio_reg_base);
|
||||
|
||||
clk = clk_get(&pdev->dev, NULL);
|
||||
clk = devm_clk_get_enabled(&pdev->dev, NULL);
|
||||
if (IS_ERR(clk)) {
|
||||
dev_err(&pdev->dev, "Error %ld to get gpio clock\n",
|
||||
PTR_ERR(clk));
|
||||
return PTR_ERR(clk);
|
||||
}
|
||||
ret = clk_prepare_enable(clk);
|
||||
if (ret) {
|
||||
clk_put(clk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Initialize GPIO chips */
|
||||
ret = pxa_init_gpio_chip(pchip, pxa_last_gpio + 1, gpio_reg_base);
|
||||
if (ret) {
|
||||
clk_put(clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* clear all GPIO edge detects */
|
||||
for_each_gpio_bank(gpio, c, pchip) {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user