Commit 6cfae0c2 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'char-misc-5.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc

Pull char/misc driver updates from Greg KH:
 "Here is the big char/misc driver pull request for 5.4-rc1.

  As has been happening in previous releases, more and more individual
  driver subsystem trees are ending up in here. Now if that is good or
  bad I can't tell, but hopefully it makes your life easier as it's more
  of an aggregation of trees together to one merge point for you.

  Anyway, lots of stuff in here:
     - habanalabs driver updates
     - thunderbolt driver updates
     - misc driver updates
     - coresight and intel_th hwtracing driver updates
     - fpga driver updates
     - extcon driver updates
     - some dma driver updates
     - char driver updates
     - android binder driver updates
     - nvmem driver updates
     - phy driver updates
     - parport driver fixes
     - pcmcia driver fix
     - uio driver updates
     - w1 driver updates
     - configfs fixes
     - other assorted driver updates

  All of these have been in linux-next for a long time with no reported
  issues"

* tag 'char-misc-5.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (200 commits)
  misc: mic: Use PTR_ERR_OR_ZERO rather than its implementation
  habanalabs: correctly cast variable to __le32
  habanalabs: show correct id in error print
  habanalabs: stop using the acronym KMD
  habanalabs: display card name as sensors header
  habanalabs: add uapi to retrieve aggregate H/W events
  habanalabs: add uapi to retrieve device utilization
  habanalabs: Make the Coresight timestamp perpetual
  habanalabs: explicitly set the queue-id enumerated numbers
  habanalabs: print to kernel log when reset is finished
  habanalabs: replace __le32_to_cpu with le32_to_cpu
  habanalabs: replace __cpu_to_le32/64 with cpu_to_le32/64
  habanalabs: Handle HW_IP_INFO if device disabled or in reset
  habanalabs: Expose devices after initialization is done
  habanalabs: improve security in Debug IOCTL
  habanalabs: use default structure for user input in Debug IOCTL
  habanalabs: Add descriptive name to PSOC app status register
  habanalabs: Add descriptive names to PSOC scratch-pad registers
  habanalabs: create two char devices per ASIC
  habanalabs: change device_setup_cdev() to be more generic
  ...
parents e6874fc2 16a0f687
......@@ -12,7 +12,8 @@ Description: (RW) Configure MSC operating mode:
- "single", for contiguous buffer mode (high-order alloc);
- "multi", for multiblock mode;
- "ExI", for DCI handler mode;
- "debug", for debug mode.
- "debug", for debug mode;
- any of the currently loaded buffer sinks.
If operating mode changes, existing buffer is deallocated,
provided there are no active users and tracing is not enabled,
otherwise the write will fail.
......
Intel Stratix10 Remote System Update (RSU) device attributes
What: /sys/devices/platform/stratix10-rsu.0/current_image
Date: August 2019
KernelVersion: 5.4
Contact: Richard Gong <richard.gong@linux.intel.com>
Description:
(RO) the address in flash of currently running image.
What: /sys/devices/platform/stratix10-rsu.0/fail_image
Date: August 2019
KernelVersion: 5.4
Contact: Richard Gong <richard.gong@linux.intel.com>
Description:
(RO) the address in flash of failed image.
What: /sys/devices/platform/stratix10-rsu.0/state
Date: August 2019
KernelVersion: 5.4
Contact: Richard Gong <richard.gong@linux.intel.com>
Description:
(RO) the state of RSU system.
The state field has two parts: major error code in
upper 16 bits and minor error code in lower 16 bits.
b[15:0]
Currently used only when major error is 0xF006
(CPU watchdog timeout), in which case the minor
error code is the value reported by CPU to
firmware through the RSU notify command before
the watchdog timeout occurs.
b[31:16]
0xF001 bitstream error
0xF002 hardware access failure
0xF003 bitstream corruption
0xF004 internal error
0xF005 device error
0xF006 CPU watchdog timeout
0xF007 internal unknown error
What: /sys/devices/platform/stratix10-rsu.0/version
Date: August 2019
KernelVersion: 5.4
Contact: Richard Gong <richard.gong@linux.intel.com>
Description:
(RO) the version number of RSU firmware. 19.3 or late
version includes information about the firmware which
reported the error.
pre 19.3:
b[31:0]
0x0 version number
19.3 or late:
b[15:0]
0x1 version number
b[31:16]
0x0 no error
0x0DCF Decision CMF error
0x0ACF Application CMF error
What: /sys/devices/platform/stratix10-rsu.0/error_location
Date: August 2019
KernelVersion: 5.4
Contact: Richard Gong <richard.gong@linux.intel.com>
Description:
(RO) the error offset inside the image that failed.
What: /sys/devices/platform/stratix10-rsu.0/error_details
Date: August 2019
KernelVersion: 5.4
Contact: Richard Gong <richard.gong@linux.intel.com>
Description:
(RO) error code.
What: /sys/devices/platform/stratix10-rsu.0/retry_counter
Date: August 2019
KernelVersion: 5.4
Contact: Richard Gong <richard.gong@linux.intel.com>
Description:
(RO) the current image's retry counter, which is used by
user to know how many times the images is still allowed
to reload itself before giving up and starting RSU
fail-over flow.
What: /sys/devices/platform/stratix10-rsu.0/reboot_image
Date: August 2019
KernelVersion: 5.4
Contact: Richard Gong <richard.gong@linux.intel.com>
Description:
(WO) the address in flash of image to be loaded on next
reboot command.
What: /sys/devices/platform/stratix10-rsu.0/notify
Date: August 2019
KernelVersion: 5.4
Contact: Richard Gong <richard.gong@linux.intel.com>
Description:
(WO) client to notify firmware with different actions.
b[15:0]
inform firmware the current software execution
stage.
0 the first stage bootloader didn't run or
didn't reach the point of launching second
stage bootloader.
1 failed in second bootloader or didn't get
to the point of launching the operating
system.
2 both first and second stage bootloader ran
and the operating system launch was
attempted.
b[16]
1 firmware to reset current image retry
counter.
0 no action.
b[17]
1 firmware to clear RSU log
0 no action.
b[18]
this is negative logic
1 no action
0 firmware record the notify code defined
in b[15:0].
......@@ -57,6 +57,7 @@ KernelVersion: 5.1
Contact: oded.gabbay@gmail.com
Description: Allows the user to set the maximum clock frequency for MME, TPC
and IC when the power management profile is set to "automatic".
This property is valid only for the Goya ASIC family
What: /sys/class/habanalabs/hl<n>/ic_clk
Date: Jan 2019
......@@ -127,8 +128,8 @@ Description: Power management profile. Values are "auto", "manual". In "auto"
the max clock frequency to a low value when there are no user
processes that are opened on the device's file. In "manual"
mode, the user sets the maximum clock frequency by writing to
ic_clk, mme_clk and tpc_clk
ic_clk, mme_clk and tpc_clk. This property is valid only for
the Goya ASIC family
What: /sys/class/habanalabs/hl<n>/preboot_btl_ver
Date: Jan 2019
......@@ -186,11 +187,4 @@ What: /sys/class/habanalabs/hl<n>/uboot_ver
Date: Jan 2019
KernelVersion: 5.1
Contact: oded.gabbay@gmail.com
Description: Version of the u-boot running on the device's CPU
What: /sys/class/habanalabs/hl<n>/write_open_cnt
Date: Jan 2019
KernelVersion: 5.1
Contact: oded.gabbay@gmail.com
Description: Displays the total number of user processes that are currently
opened on the device's file
Description: Version of the u-boot running on the device's CPU
\ No newline at end of file
......@@ -21,3 +21,88 @@ Contact: Wu Hao <hao.wu@intel.com>
Description: Read-only. It returns Bitstream (static FPGA region) meta
data, which includes the synthesis date, seed and other
information of this static FPGA region.
What: /sys/bus/platform/devices/dfl-fme.0/cache_size
Date: August 2019
KernelVersion: 5.4
Contact: Wu Hao <hao.wu@intel.com>
Description: Read-only. It returns cache size of this FPGA device.
What: /sys/bus/platform/devices/dfl-fme.0/fabric_version
Date: August 2019
KernelVersion: 5.4
Contact: Wu Hao <hao.wu@intel.com>
Description: Read-only. It returns fabric version of this FPGA device.
Userspace applications need this information to select
best data channels per different fabric design.
What: /sys/bus/platform/devices/dfl-fme.0/socket_id
Date: August 2019
KernelVersion: 5.4
Contact: Wu Hao <hao.wu@intel.com>
Description: Read-only. It returns socket_id to indicate which socket
this FPGA belongs to, only valid for integrated solution.
User only needs this information, in case standard numa node
can't provide correct information.
What: /sys/bus/platform/devices/dfl-fme.0/errors/pcie0_errors
Date: August 2019
KernelVersion: 5.4
Contact: Wu Hao <hao.wu@intel.com>
Description: Read-Write. Read this file for errors detected on pcie0 link.
Write this file to clear errors logged in pcie0_errors. Write
fails with -EINVAL if input parsing fails or input error code
doesn't match.
What: /sys/bus/platform/devices/dfl-fme.0/errors/pcie1_errors
Date: August 2019
KernelVersion: 5.4
Contact: Wu Hao <hao.wu@intel.com>
Description: Read-Write. Read this file for errors detected on pcie1 link.
Write this file to clear errors logged in pcie1_errors. Write
fails with -EINVAL if input parsing fails or input error code
doesn't match.
What: /sys/bus/platform/devices/dfl-fme.0/errors/nonfatal_errors
Date: August 2019
KernelVersion: 5.4
Contact: Wu Hao <hao.wu@intel.com>
Description: Read-only. It returns non-fatal errors detected.
What: /sys/bus/platform/devices/dfl-fme.0/errors/catfatal_errors
Date: August 2019
KernelVersion: 5.4
Contact: Wu Hao <hao.wu@intel.com>
Description: Read-only. It returns catastrophic and fatal errors detected.
What: /sys/bus/platform/devices/dfl-fme.0/errors/inject_errors
Date: August 2019
KernelVersion: 5.4
Contact: Wu Hao <hao.wu@intel.com>
Description: Read-Write. Read this file to check errors injected. Write this
file to inject errors for testing purpose. Write fails with
-EINVAL if input parsing fails or input inject error code isn't
supported.
What: /sys/bus/platform/devices/dfl-fme.0/errors/fme_errors
Date: August 2019
KernelVersion: 5.4
Contact: Wu Hao <hao.wu@intel.com>
Description: Read-Write. Read this file to get errors detected on FME.
Write this file to clear errors logged in fme_errors. Write
fials with -EINVAL if input parsing fails or input error code
doesn't match.
What: /sys/bus/platform/devices/dfl-fme.0/errors/first_error
Date: August 2019
KernelVersion: 5.4
Contact: Wu Hao <hao.wu@intel.com>
Description: Read-only. Read this file to get the first error detected by
hardware.
What: /sys/bus/platform/devices/dfl-fme.0/errors/next_error
Date: August 2019
KernelVersion: 5.4
Contact: Wu Hao <hao.wu@intel.com>
Description: Read-only. Read this file to get the second error detected by
hardware.
......@@ -14,3 +14,88 @@ Description: Read-only. User can program different PR bitstreams to FPGA
Accelerator Function Unit (AFU) for different functions. It
returns uuid which could be used to identify which PR bitstream
is programmed in this AFU.
What: /sys/bus/platform/devices/dfl-port.0/power_state
Date: August 2019
KernelVersion: 5.4
Contact: Wu Hao <hao.wu@intel.com>
Description: Read-only. It reports the APx (AFU Power) state, different APx
means different throttling level. When reading this file, it
returns "0" - Normal / "1" - AP1 / "2" - AP2 / "6" - AP6.
What: /sys/bus/platform/devices/dfl-port.0/ap1_event
Date: August 2019
KernelVersion: 5.4
Contact: Wu Hao <hao.wu@intel.com>
Description: Read-write. Read this file for AP1 (AFU Power State 1) event.
It's used to indicate transient AP1 state. Write 1 to this
file to clear AP1 event.
What: /sys/bus/platform/devices/dfl-port.0/ap2_event
Date: August 2019
KernelVersion: 5.4
Contact: Wu Hao <hao.wu@intel.com>
Description: Read-write. Read this file for AP2 (AFU Power State 2) event.
It's used to indicate transient AP2 state. Write 1 to this
file to clear AP2 event.
What: /sys/bus/platform/devices/dfl-port.0/ltr
Date: August 2019
KernelVersion: 5.4
Contact: Wu Hao <hao.wu@intel.com>
Description: Read-write. Read or set AFU latency tolerance reporting value.
Set ltr to 1 if the AFU can tolerate latency >= 40us or set it
to 0 if it is latency sensitive.
What: /sys/bus/platform/devices/dfl-port.0/userclk_freqcmd
Date: August 2019
KernelVersion: 5.4
Contact: Wu Hao <hao.wu@intel.com>
Description: Write-only. User writes command to this interface to set
userclock to AFU.
What: /sys/bus/platform/devices/dfl-port.0/userclk_freqsts
Date: August 2019
KernelVersion: 5.4
Contact: Wu Hao <hao.wu@intel.com>
Description: Read-only. Read this file to get the status of issued command
to userclck_freqcmd.
What: /sys/bus/platform/devices/dfl-port.0/userclk_freqcntrcmd
Date: August 2019
KernelVersion: 5.4
Contact: Wu Hao <hao.wu@intel.com>
Description: Write-only. User writes command to this interface to set
userclock counter.
What: /sys/bus/platform/devices/dfl-port.0/userclk_freqcntrsts
Date: August 2019
KernelVersion: 5.4
Contact: Wu Hao <hao.wu@intel.com>
Description: Read-only. Read this file to get the status of issued command
to userclck_freqcntrcmd.
What: /sys/bus/platform/devices/dfl-port.0/errors/errors
Date: August 2019
KernelVersion: 5.4
Contact: Wu Hao <hao.wu@intel.com>
Description: Read-Write. Read this file to get errors detected on port and
Accelerated Function Unit (AFU). Write error code to this file
to clear errors. Write fails with -EINVAL if input parsing
fails or input error code doesn't match. Write fails with
-EBUSY or -ETIMEDOUT if error can't be cleared as hardware
in low power state (-EBUSY) or not respoding (-ETIMEDOUT).
What: /sys/bus/platform/devices/dfl-port.0/errors/first_error
Date: August 2019
KernelVersion: 5.4
Contact: Wu Hao <hao.wu@intel.com>
Description: Read-only. Read this file to get the first error detected by
hardware.
What: /sys/bus/platform/devices/dfl-port.0/errors/first_malformed_req
Date: August 2019
KernelVersion: 5.4
Contact: Wu Hao <hao.wu@intel.com>
Description: Read-only. Read this file to get the first malformed request
captured by hardware.
......@@ -136,7 +136,9 @@ Required properties:
OCOTP bindings based on SCU Message Protocol
------------------------------------------------------------
Required properties:
- compatible: Should be "fsl,imx8qxp-scu-ocotp"
- compatible: Should be one of:
"fsl,imx8qm-scu-ocotp",
"fsl,imx8qxp-scu-ocotp".
- #address-cells: Must be 1. Contains byte index
- #size-cells: Must be 1. Contains byte length
......
......@@ -72,5 +72,5 @@ codec: wm8280@0 {
1 2 1 /* MICDET2 MICBIAS2 GPIO=high */
>;
wlf,gpsw = <0>;
wlf,gpsw = <ARIZONA_GPSW_OPEN>;
};
......@@ -5,7 +5,9 @@ controlled using I2C and enables USB data, stereo and mono audio, video,
microphone, and UART data to use a common connector port.
Required properties:
- compatible : Must be "fcs,fsa9480"
- compatible : Must be one of
"fcs,fsa9480"
"fcs,fsa880"
- reg : Specifies i2c slave address. Must be 0x25.
- interrupts : Should contain one entry specifying interrupt signal of
interrupt parent to which interrupt pin of the chip is connected.
......
......@@ -3,10 +3,7 @@ Altera FPGA To SDRAM Bridge Driver
Required properties:
- compatible : Should contain "altr,socfpga-fpga2sdram-bridge"
Optional properties:
- bridge-enable : 0 if driver should disable bridge at startup
1 if driver should enable bridge at startup
Default is to leave bridge in current state.
See Documentation/devicetree/bindings/fpga/fpga-bridge.txt for generic bindings.
Example:
fpga_bridge3: fpga-bridge@ffc25080 {
......
......@@ -10,10 +10,7 @@ Required properties:
- compatible : Should contain "altr,freeze-bridge-controller"
- regs : base address and size for freeze bridge module
Optional properties:
- bridge-enable : 0 if driver should disable bridge at startup
1 if driver should enable bridge at startup
Default is to leave bridge in current state.
See Documentation/devicetree/bindings/fpga/fpga-bridge.txt for generic bindings.
Example:
freeze-controller@100000450 {
......
......@@ -9,10 +9,7 @@ Required properties:
- resets : Phandle and reset specifier for this bridge's reset
- clocks : Clocks used by this module.
Optional properties:
- bridge-enable : 0 if driver should disable bridge at startup.
1 if driver should enable bridge at startup.
Default is to leave bridge in its current state.
See Documentation/devicetree/bindings/fpga/fpga-bridge.txt for generic bindings.
Example:
fpga_bridge0: fpga-bridge@ff400000 {
......
FPGA Bridge Device Tree Binding
Optional properties:
- bridge-enable : 0 if driver should disable bridge at startup
1 if driver should enable bridge at startup
Default is to leave bridge in current state.
Example:
fpga_bridge3: fpga-bridge@ffc25080 {
compatible = "altr,socfpga-fpga2sdram-bridge";
reg = <0xffc25080 0x4>;
bridge-enable = <0>;
};
......@@ -18,12 +18,8 @@ Required properties:
- clocks : input clock to IP
- clock-names : should contain "aclk"
Optional properties:
- bridge-enable : 0 if driver should disable bridge at startup
1 if driver should enable bridge at startup
Default is to leave bridge in current state.
See Documentation/devicetree/bindings/fpga/fpga-region.txt for generic bindings.
See Documentation/devicetree/bindings/fpga/fpga-region.txt and
Documentation/devicetree/bindings/fpga/fpga-bridge.txt for generic bindings.
Example:
fpga-bridge@100000450 {
......
Qualcomm QCS404 Network-On-Chip interconnect driver binding
-----------------------------------------------------------
Required properties :
- compatible : shall contain only one of the following:
"qcom,qcs404-bimc"
"qcom,qcs404-pcnoc"
"qcom,qcs404-snoc"
- #interconnect-cells : should contain 1
reg : specifies the physical base address and size of registers
clocks : list of phandles and specifiers to all interconnect bus clocks
clock-names : clock names should include both "bus" and "bus_a"
Example:
soc {
...
bimc: interconnect@400000 {
reg = <0x00400000 0x80000>;
compatible = "qcom,qcs404-bimc";
#interconnect-cells = <1>;
clock-names = "bus", "bus_a";
clocks = <&rpmcc RPM_SMD_BIMC_CLK>,
<&rpmcc RPM_SMD_BIMC_A_CLK>;
};
pnoc: interconnect@500000 {
reg = <0x00500000 0x15080>;
compatible = "qcom,qcs404-pcnoc";
#interconnect-cells = <1>;
clock-names = "bus", "bus_a";
clocks = <&rpmcc RPM_SMD_PNOC_CLK>,
<&rpmcc RPM_SMD_PNOC_A_CLK>;
};
snoc: interconnect@580000 {
reg = <0x00580000 0x23080>;
compatible = "qcom,qcs404-snoc";
#interconnect-cells = <1>;
clock-names = "bus", "bus_a";
clocks = <&rpmcc RPM_SMD_SNOC_CLK>,
<&rpmcc RPM_SMD_SNOC_A_CLK>;
};
};
......@@ -2,7 +2,7 @@ Freescale i.MX6 On-Chip OTP Controller (OCOTP) device tree bindings
This binding represents the on-chip eFuse OTP controller found on
i.MX6Q/D, i.MX6DL/S, i.MX6SL, i.MX6SX, i.MX6UL, i.MX6ULL/ULZ, i.MX6SLL,
i.MX7D/S, i.MX7ULP and i.MX8MQ SoCs.
i.MX7D/S, i.MX7ULP, i.MX8MQ, i.MX8MM and i.MX8MN SoCs.
Required properties:
- compatible: should be one of
......@@ -16,6 +16,7 @@ Required properties:
"fsl,imx7ulp-ocotp" (i.MX7ULP),
"fsl,imx8mq-ocotp" (i.MX8MQ),
"fsl,imx8mm-ocotp" (i.MX8MM),
"fsl,imx8mn-ocotp" (i.MX8MN),
followed by "syscon".
- #address-cells : Should be 1
- #size-cells : Should be 1
......
......@@ -17,6 +17,14 @@ Required properties:
name must be "core" for the first clock and "reg" for the second
one
Optional properties:
- phys: phandle(s) to PHY node(s) following the generic PHY bindings.
Either 1, 2 or 4 PHYs might be needed depending on the number of
PCIe lanes.
- phy-names: names of the PHYs corresponding to the number of lanes.
Must be "cp0-pcie0-x4-lane0-phy", "cp0-pcie0-x4-lane1-phy" for
2 PHYs.
Example:
pcie@f2600000 {
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/phy/lantiq,vrx200-pcie-phy.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Lantiq VRX200 and ARX300 PCIe PHY Device Tree Bindings
maintainers:
- Martin Blumenstingl <martin.blumenstingl@googlemail.com>
properties:
"#phy-cells":
const: 1
description: selects the PHY mode as defined in <dt-bindings/phy/phy-lantiq-vrx200-pcie.h>
compatible:
enum:
- lantiq,vrx200-pcie-phy
- lantiq,arx300-pcie-phy
reg:
maxItems: 1
clocks:
items:
- description: PHY module clock
- description: PDI register clock
clock-names:
items:
- const: phy
- const: pdi
resets:
items:
- description: exclusive PHY reset line
- description: shared reset line between the PCIe PHY and PCIe controller
resets-names:
items:
- const: phy
- const: pcie
lantiq,rcu:
$ref: /schemas/types.yaml#/definitions/phandle
description: phandle to the RCU syscon
lantiq,rcu-endian-offset:
$ref: /schemas/types.yaml#/definitions/uint32
description: the offset of the endian registers for this PHY instance in the RCU syscon
lantiq,rcu-big-endian-mask:
$ref: /schemas/types.yaml#/definitions/uint32
description: the mask to set the PDI (PHY) registers for this PHY instance to big endian
big-endian:
description: Configures the PDI (PHY) registers in big-endian mode
type: boolean
little-endian:
description: Configures the PDI (PHY) registers in big-endian mode
type: boolean
required:
- "#phy-cells"
- compatible
- reg
- clocks
- clock-names
- resets
- reset-names
- lantiq,rcu
- lantiq,rcu-endian-offset
- lantiq,rcu-big-endian-mask
additionalProperties: false
examples:
- |
pcie0_phy: phy@106800 {
compatible = "lantiq,vrx200-pcie-phy";
reg = <0x106800 0x100>;
lantiq,rcu = <&rcu0>;
lantiq,rcu-endian-offset = <0x4c>;
lantiq,rcu-big-endian-mask = <0x80>; /* bit 7 */
big-endian;
clocks = <&pmu 32>, <&pmu 36>;
clock-names = "phy", "pdi";
resets = <&reset0 12 24>, <&reset0 22 22>;
reset-names = "phy", "pcie";
#phy-cells = <1>;
};
...
......@@ -25,6 +25,13 @@ Required properties:
- #address-cells: should be 1.
- #size-cells: should be 0.
Optional properlties:
- clocks: pointers to the reference clocks for this device (CP110 only),
consequently: MG clock, MG Core clock, AXI clock.
- clock-names: names of used clocks for CP110 only, must be :
"mg_clk", "mg_core_clk" and "axi_clk".
A sub-node is required for each comphy lane provided by the comphy.
Required properties (child nodes):
......@@ -39,6 +46,9 @@ Examples:
compatible = "marvell,comphy-cp110";
reg = <0x120000 0x6000>;
marvell,system-controller = <&cpm_syscon0>;
clocks = <&CP110_LABEL(clk) 1 5>, <&CP110_LABEL(clk) 1 6>,
<&CP110_LABEL(clk) 1 18>;
clock-names = "mg_clk", "mg_core_clk", "axi_clk";
#address-cells = <1>;
#size-cells = <0>;
......
......@@ -408,6 +408,13 @@ handler code. You also do not need to know anything about the chip's
internal registers to create the kernel part of the driver. All you need
to know is the irq number of the pin the chip is connected to.
When used in a device-tree enabled system, the driver needs to be
probed with the ``"of_id"`` module parameter set to the ``"compatible"``
string of the node the driver is supposed to handle. By default, the
node's name (without the unit address) is exposed as name for the
UIO device in userspace. To set a custom name, a property named
``"linux,uio-name"`` may be specified in the DT node.
Using uio_dmem_genirq for platform devices
------------------------------------------
......
......@@ -87,6 +87,8 @@ The following functions are exposed through ioctls:
- Get driver API version (DFL_FPGA_GET_API_VERSION)
- Check for extensions (DFL_FPGA_CHECK_EXTENSION)
- Program bitstream (DFL_FPGA_FME_PORT_PR)
- Assign port to PF (DFL_FPGA_FME_PORT_ASSIGN)
- Release port from PF (DFL_FPGA_FME_PORT_RELEASE)
More functions are exposed through sysfs
(/sys/class/fpga_region/regionX/dfl-fme.n/):
......@@ -102,6 +104,10 @@ More functions are exposed through sysfs
one FPGA device may have more than one port, this sysfs interface indicates
how many ports the FPGA device has.
Global error reporting management (errors/)
error reporting sysfs interfaces allow user to read errors detected by the
hardware, and clear the logged errors.
FIU - PORT
==========
......@@ -143,6 +149,10 @@ More functions are exposed through sysfs:
Read Accelerator GUID (afu_id)
afu_id indicates which PR bitstream is programmed to this AFU.
Error reporting (errors/)
error reporting sysfs interfaces allow user to read port/afu errors
detected by the hardware, and clear the logged errors.
DFL Framework Overview
======================
......@@ -218,6 +228,101 @@ the compat_id exposed by the target FPGA region. This check is usually done by
userspace before calling the reconfiguration IOCTL.
FPGA virtualization - PCIe SRIOV
================================
This section describes the virtualization support on DFL based FPGA device to
enable accessing an accelerator from applications running in a virtual machine
(VM). This section only describes the PCIe based FPGA device with SRIOV support.
Features supported by the particular FPGA device are exposed through Device
Feature Lists, as illustrated below:
::
+-------------------------------+ +-------------+
| PF | | VF |
+-------------------------------+ +-------------+
^ ^ ^ ^
| | | |
+-----|------------|---------|--------------|-------+
| | | | | |
| +-----+ +-------+ +-------+ +-------+ |
| | FME | | Port0 | | Port1 | | Port2 | |
| +-----+ +-------+ +-------+ +-------+ |
| ^ ^ ^ |
| | | | |
| +-------+ +------+ +-------+ |
| | AFU | | AFU | | AFU | |
| +-------+ +------+ +-------+ |
| |
| DFL based FPGA PCIe Device |
+---------------------------------------------------+
FME is always accessed through the physical function (PF).
Ports (and related AFUs) are accessed via PF by default, but could be exposed
through virtual function (VF) devices via PCIe SRIOV. Each VF only contains
1 Port and 1 AFU for isolation. Users could assign individual VFs (accelerators)
created via PCIe SRIOV interface, to virtual machines.
The driver organization in virtualization case is illustrated below:
::
+-------++------++------+ |
| FME || FME || FME | |
| FPGA || FPGA || FPGA | |
|Manager||Bridge||Region| |
+-------++------++------+ |
+-----------------------+ +--------+ | +--------+
| FME | | AFU | | | AFU |
| Module | | Module | | | Module |
+-----------------------+ +--------+ | +--------+
+-----------------------+ | +-----------------------+
| FPGA Container Device | | | FPGA Container Device |
| (FPGA Base Region) | | | (FPGA Base Region) |
+-----------------------+ | +-----------------------+
+------------------+ | +------------------+
| FPGA PCIE Module | | Virtual | FPGA PCIE Module |
+------------------+ Host | Machine +------------------+
-------------------------------------- | ------------------------------
+---------------+ | +---------------+
| PCI PF Device | | | PCI VF Device |
+---------------+ | +---------------+
FPGA PCIe device driver is always loaded first once a FPGA PCIe PF or VF device
is detected. It:
* Finishes enumeration on both FPGA PCIe PF and VF device using common
interfaces from DFL framework.
* Supports SRIOV.
The FME device driver plays a management role in this driver architecture, it
provides ioctls to release Port from PF and assign Port to PF. After release
a port from PF, then it's safe to expose this port through a VF via PCIe SRIOV
sysfs interface.
To enable accessing an accelerator from applications running in a VM, the
respective AFU's port needs to be assigned to a VF using the following steps:
#. The PF owns all AFU ports by default. Any port that needs to be
reassigned to a VF must first be released through the
DFL_FPGA_FME_PORT_RELEASE ioctl on the FME device.
#. Once N ports are released from PF, then user can use command below
to enable SRIOV and VFs. Each VF owns only one Port with AFU.
::
echo N > $PCI_DEVICE_PATH/sriov_numvfs
#. Pass through the VFs to VMs
#. The AFU under VF is accessible from applications in VM (using the
same driver inside the VF).
Note that an FME can't be assigned to a VF, thus PR and other management
functions are only available via the PF.
Device enumeration
==================
This section introduces how applications enumerate the fpga device from
......
......@@ -20,3 +20,4 @@ fit into other categories.
isl29003
lis3lv02d
max6875
xilinx_sdfec
......@@ -8360,6 +8360,17 @@ F: drivers/platform/x86/intel_speed_select_if/
F: tools/power/x86/intel-speed-select/
F: include/uapi/linux/isst_if.h
INTEL STRATIX10 FIRMWARE DRIVERS
M: Richard Gong <richard.gong@linux.intel.com>
L: linux-kernel@vger.kernel.org
S: Maintained
F: drivers/firmware/stratix10-rsu.c
F: drivers/firmware/stratix10-svc.c
F: include/linux/firmware/intel/stratix10-smc.h
F: include/linux/firmware/intel/stratix10-svc-client.h
F: Documentation/ABI/testing/sysfs-devices-platform-stratix10-rsu
F: Documentation/devicetree/bindings/firmware/intel,stratix10-svc.txt
INTEL TELEMETRY DRIVER
M: Rajneesh Bhardwaj <rajneesh.bhardwaj@linux.intel.com>
M: "David E. Box" <david.e.box@linux.intel.com>
......@@ -8411,6 +8422,7 @@ M: Alexander Shishkin <alexander.shishkin@linux.intel.com>
S: Supported
F: Documentation/trace/intel_th.rst
F: drivers/hwtracing/intel_th/
F: include/linux/intel_th.h
INTEL(R) TRUSTED EXECUTION TECHNOLOGY (TXT)
M: Ning Sun <ning.sun@intel.com>
......@@ -17760,6 +17772,17 @@ F: Documentation/devicetree/bindings/media/xilinx/
F: drivers/media/platform/xilinx/
F: include/uapi/linux/xilinx-v4l2-controls.h
XILINX SD-FEC IP CORES
M: Derek Kiernan <derek.kiernan@xilinx.com>
M: Dragan Cvetic <dragan.cvetic@xilinx.com>
S: Maintained
F: Documentation/devicetree/bindings/misc/xlnx,sd-fec.txt
F: Documentation/misc-devices/xilinx_sdfec.rst
F: drivers/misc/xilinx_sdfec.c
F: drivers/misc/Kconfig
F: drivers/misc/Makefile
F: include/uapi/misc/xilinx_sdfec.h
XILLYBUS DRIVER
M: Eli Billauer <eli.billauer@gmail.com>
L: linux-kernel@vger.kernel.org
......
......@@ -39,6 +39,12 @@ static const guid_t prp_guids[] = {
/* External facing port GUID: efcc06cc-73ac-4bc3-bff0-76143807c389 */
GUID_INIT(0xefcc06cc, 0x73ac, 0x4bc3,
0xbf, 0xf0, 0x76, 0x14, 0x38, 0x07, 0xc3, 0x89),
/* Thunderbolt GUID for IMR_VALID: c44d002f-69f9-4e7d-a904-a7baabdf43f7 */
GUID_INIT(0xc44d002f, 0x69f9, 0x4e7d,
0xa9, 0x04, 0xa7, 0xba, 0xab, 0xdf, 0x43, 0xf7),
/* Thunderbolt GUID for WAKE_SUPPORTED: 6c501103-c189-4296-ba72-9bf5a26ebe5d */
GUID_INIT(0x6c501103, 0xc189, 0x4296,
0xba, 0x72, 0x9b, 0xf5, 0xa2, 0x6e, 0xbe, 0x5d),
};
/* ACPI _DSD data subnodes GUID: dbb8e3e6-5886-4ba6-8795-1319f52a966b */
......
......@@ -122,7 +122,7 @@ static uint32_t binder_debug_mask = BINDER_DEBUG_USER_ERROR |
BINDER_DEBUG_FAILED_TRANSACTION | BINDER_DEBUG_DEAD_TRANSACTION;
module_param_named(debug_mask, binder_debug_mask, uint, 0644);
static char *binder_devices_param = CONFIG_ANDROID_BINDER_DEVICES;
char *binder_devices_param = CONFIG_ANDROID_BINDER_DEVICES;
module_param_named(devices, binder_devices_param, charp, 0444);
static DECLARE_WAIT_QUEUE_HEAD(binder_user_error_wait);
......@@ -196,30 +196,8 @@ static inline void binder_stats_created(enum binder_stat_types type)
atomic_inc(&binder_stats.obj_created[type]);
}
struct binder_transaction_log_entry {
int debug_id;
int debug_id_done;
int call_type;
int from_proc;
int from_thread;
int target_handle;
int to_proc;
int to_thread;
int to_node;
int data_size;
int offsets_size;
int return_error_line;
uint32_t return_error;
uint32_t return_error_param;
const char *context_name;
};
struct binder_transaction_log {
atomic_t cur;
bool full;
struct binder_transaction_log_entry entry[32];
};
static struct binder_transaction_log binder_transaction_log;
static struct binder_transaction_log binder_transaction_log_failed;
struct binder_transaction_log binder_transaction_log;
struct binder_transaction_log binder_transaction_log_failed;
static struct binder_transaction_log_entry *binder_transaction_log_add(
struct binder_transaction_log *log)
......@@ -480,6 +458,7 @@ enum binder_deferred_state {
* @inner_lock: can nest under outer_lock and/or node lock
* @outer_lock: no nesting under innor or node lock
* Lock order: 1) outer, 2) node, 3) inner
* @binderfs_entry: process-specific binderfs log file
*
* Bookkeeping structure for binder processes
*/
......@@ -509,6 +488,7 @@ struct binder_proc {
struct binder_context *context;
spinlock_t inner_lock;
spinlock_t outer_lock;
struct dentry *binderfs_entry;
};
enum {
......@@ -5230,6 +5210,8 @@ static int binder_open(struct inode *nodp, struct file *filp)
{
struct binder_proc *proc;
struct binder_device *binder_dev;
struct binderfs_info *info;
struct dentry *binder_binderfs_dir_entry_proc = NULL;
binder_debug(BINDER_DEBUG_OPEN_CLOSE, "%s: %d:%d\n", __func__,
current->group_leader->pid, current->pid);
......@@ -5244,11 +5226,14 @@ static int binder_open(struct inode *nodp, struct file *filp)
INIT_LIST_HEAD(&proc->todo);
proc->default_priority = task_nice(current);
/* binderfs stashes devices in i_private */
if (is_binderfs_device(nodp))
if (is_binderfs_device(nodp)) {
binder_dev = nodp->i_private;
else
info = nodp->i_sb->s_fs_info;
binder_binderfs_dir_entry_proc = info->proc_log_dir;
} else {
binder_dev = container_of(filp->private_data,
struct binder_device, miscdev);
}
proc->context = &binder_dev->context;
binder_alloc_init(&proc->alloc);
......@@ -5279,6 +5264,35 @@ static int binder_open(struct inode *nodp, struct file *filp)
&proc_fops);
}
if (binder_binderfs_dir_entry_proc) {
char strbuf[11];
struct dentry *binderfs_entry;
snprintf(strbuf, sizeof(strbuf), "%u", proc->pid);
/*
* Similar to debugfs, the process specific log file is shared
* between contexts. If the file has already been created for a
* process, the following binderfs_create_file() call will
* fail with error code EEXIST if another context of the same
* process invoked binder_open(). This is ok since same as
* debugfs, the log file will contain information on all
* contexts of a given PID.
*/
binderfs_entry = binderfs_create_file(binder_binderfs_dir_entry_proc,
strbuf, &proc_fops, (void *)(unsigned long)proc->pid);
if (!IS_ERR(binderfs_entry)) {
proc->binderfs_entry = binderfs_entry;
} else {
int error;
error = PTR_ERR(binderfs_entry);
if (error != -EEXIST) {
pr_warn("Unable to create file %s in binderfs (error %d)\n",
strbuf, error);
}
}
}
return 0;
}
......@@ -5318,6 +5332,12 @@ static int binder_release(struct inode *nodp, struct file *filp)
struct binder_proc *proc = filp->private_data;
debugfs_remove(proc->debugfs_entry);
if (proc->binderfs_entry) {
binderfs_remove_file(proc->binderfs_entry);
proc->binderfs_entry = NULL;
}
binder_defer_work(proc, BINDER_DEFERRED_RELEASE);
return 0;
......@@ -5907,7 +5927,7 @@ static void print_binder_proc_stats(struct seq_file *m,
}
static int state_show(struct seq_file *m, void *unused)
int binder_state_show(struct seq_file *m, void *unused)
{
struct binder_proc *proc;
struct binder_node *node;
......@@ -5946,7 +5966,7 @@ static int state_show(struct seq_file *m, void *unused)
return 0;
}
static int stats_show(struct seq_file *m, void *unused)
int binder_stats_show(struct seq_file *m, void *unused)
{
struct binder_proc *proc;
......@@ -5962,7 +5982,7 @@ static int stats_show(struct seq_file *m, void *unused)
return 0;
}
static int transactions_show(struct seq_file *m, void *unused)
int binder_transactions_show(struct seq_file *m, void *unused)
{
struct binder_proc *proc;
......@@ -6018,7 +6038,7 @@ static void print_binder_transaction_log_entry(struct seq_file *m,
"\n" : " (incomplete)\n");
}
static int transaction_log_show(struct seq_file *m, void *unused)
int binder_transaction_log_show(struct seq_file *m, void *unused)
{
struct binder_transaction_log *log = m->private;
unsigned int log_cur = atomic_read(&log->cur);
......@@ -6050,11 +6070,6 @@ const struct file_operations binder_fops = {
.release = binder_release,
};
DEFINE_SHOW_ATTRIBUTE(state);
DEFINE_SHOW_ATTRIBUTE(stats);
DEFINE_SHOW_ATTRIBUTE(transactions);
DEFINE_SHOW_ATTRIBUTE(transaction_log);
static int __init init_binder_device(const char *name)
{
int ret;
......@@ -6108,30 +6123,31 @@ static int __init binder_init(void)
0444,
binder_debugfs_dir_entry_root,
NULL,
&state_fops);
&binder_state_fops);
debugfs_create_file("stats",
0444,
binder_debugfs_dir_entry_root,
NULL,
&stats_fops);
&binder_stats_fops);
debugfs_create_file("transactions",
0444,
binder_debugfs_dir_entry_root,
NULL,
&transactions_fops);
&binder_transactions_fops);
debugfs_create_file("transaction_log",
0444,
binder_debugfs_dir_entry_root,
&binder_transaction_log,
&transaction_log_fops);
&binder_transaction_log_fops);
debugfs_create_file("failed_transaction_log",
0444,
binder_debugfs_dir_entry_root,
&binder_transaction_log_failed,
&transaction_log_fops);
&binder_transaction_log_fops);
}
if (strcmp(binder_devices_param, "") != 0) {
if (!IS_ENABLED(CONFIG_ANDROID_BINDERFS) &&
strcmp(binder_devices_param, "") != 0) {
/*
* Copy the module_parameter string, because we don't want to
* tokenize it in-place.
......
......@@ -35,15 +35,63 @@ struct binder_device {
struct inode *binderfs_inode;
};
/**
* binderfs_mount_opts - mount options for binderfs
* @max: maximum number of allocatable binderfs binder devices
* @stats_mode: enable binder stats in binderfs.
*/
struct binderfs_mount_opts {
int max;
int stats_mode;
};
/**
* binderfs_info - information about a binderfs mount
* @ipc_ns: The ipc namespace the binderfs mount belongs to.
* @control_dentry: This records the dentry of this binderfs mount
* binder-control device.
* @root_uid: uid that needs to be used when a new binder device is
* created.
* @root_gid: gid that needs to be used when a new binder device is
* created.
* @mount_opts: The mount options in use.
* @device_count: The current number of allocated binder devices.
* @proc_log_dir: Pointer to the directory dentry containing process-specific
* logs.
*/
struct binderfs_info {
struct ipc_namespace *ipc_ns;
struct dentry *control_dentry;
kuid_t root_uid;
kgid_t root_gid;
struct binderfs_mount_opts mount_opts;
int device_count;
struct dentry *proc_log_dir;
};
extern const struct file_operations binder_fops;
extern char *binder_devices_param;
#ifdef CONFIG_ANDROID_BINDERFS
extern bool is_binderfs_device(const struct inode *inode);
extern struct dentry *binderfs_create_file(struct dentry *dir, const char *name,
const struct file_operations *fops,
void *data);
extern void binderfs_remove_file(struct dentry *dentry);
#else
static inline bool is_binderfs_device(const struct inode *inode)
{
return false;
}
static inline struct dentry *binderfs_create_file(struct dentry *dir,
const char *name,
const struct file_operations *fops,
void *data)
{
return NULL;
}
static inline void binderfs_remove_file(struct dentry *dentry) {}
#endif
#ifdef CONFIG_ANDROID_BINDERFS
......@@ -55,4 +103,42 @@ static inline int __init init_binderfs(void)
}
#endif
int binder_stats_show(struct seq_file *m, void *unused);
DEFINE_SHOW_ATTRIBUTE(binder_stats);
int binder_state_show(struct seq_file *m, void *unused);
DEFINE_SHOW_ATTRIBUTE(binder_state);
int binder_transactions_show(struct seq_file *m, void *unused);
DEFINE_SHOW_ATTRIBUTE(binder_transactions);
int binder_transaction_log_show(struct seq_file *m, void *unused);
DEFINE_SHOW_ATTRIBUTE(binder_transaction_log);
struct binder_transaction_log_entry {
int debug_id;
int debug_id_done;
int call_type;
int from_proc;
int from_thread;
int target_handle;
int to_proc;
int to_thread;
int to_node;
int data_size;
int offsets_size;
int return_error_line;
uint32_t return_error;
uint32_t return_error_param;
const char *context_name;
};
struct binder_transaction_log {
atomic_t cur;
bool full;
struct binder_transaction_log_entry entry[32];
};
extern struct binder_transaction_log binder_transaction_log;
extern struct binder_transaction_log binder_transaction_log_failed;
#endif /* _LINUX_BINDER_INTERNAL_H */
......@@ -48,45 +48,23 @@ static dev_t binderfs_dev;
static DEFINE_MUTEX(binderfs_minors_mutex);
static DEFINE_IDA(binderfs_minors);
/**
* binderfs_mount_opts - mount options for binderfs
* @max: maximum number of allocatable binderfs binder devices
*/
struct binderfs_mount_opts {
int max;
};
enum {
Opt_max,
Opt_stats_mode,
Opt_err
};
enum binderfs_stats_mode {
STATS_NONE,
STATS_GLOBAL,
};
static const match_table_t tokens = {
{ Opt_max, "max=%d" },
{ Opt_stats_mode, "stats=%s" },
{ Opt_err, NULL }
};
/**
* binderfs_info - information about a binderfs mount
* @ipc_ns: The ipc namespace the binderfs mount belongs to.
* @control_dentry: This records the dentry of this binderfs mount
* binder-control device.
* @root_uid: uid that needs to be used when a new binder device is
* created.
* @root_gid: gid that needs to be used when a new binder device is
* created.
* @mount_opts: The mount options in use.
* @device_count: The current number of allocated binder devices.
*/
struct binderfs_info {
struct ipc_namespace *ipc_ns;
struct dentry *control_dentry;
kuid_t root_uid;
kgid_t root_gid;
struct binderfs_mount_opts mount_opts;
int device_count;
};
static inline struct binderfs_info *BINDERFS_I(const struct inode *inode)
{
return inode->i_sb->s_fs_info;
......@@ -186,8 +164,7 @@ static int binderfs_binder_device_create(struct inode *ref_inode,
req->major = MAJOR(binderfs_dev);
req->minor = minor;
ret = copy_to_user(userp, req, sizeof(*req));
if (ret) {
if (userp && copy_to_user(userp, req, sizeof(*req))) {
ret = -EFAULT;
goto err;
}
......@@ -272,7 +249,7 @@ static void binderfs_evict_inode(struct inode *inode)
clear_inode(inode);
if (!device)
if (!S_ISCHR(inode->i_mode) || !device)
return;
mutex_lock(&binderfs_minors_mutex);
......@@ -291,8 +268,9 @@ static void binderfs_evict_inode(struct inode *inode)
static int binderfs_parse_mount_opts(char *data,
struct binderfs_mount_opts *opts)
{
char *p;
char *p, *stats;
opts->max = BINDERFS_MAX_MINOR;
opts->stats_mode = STATS_NONE;
while ((p = strsep(&data, ",")) != NULL) {
substring_t args[MAX_OPT_ARGS];
......@@ -312,6 +290,22 @@ static int binderfs_parse_mount_opts(char *data,
opts->max = max_devices;
break;
case Opt_stats_mode:
if (!capable(CAP_SYS_ADMIN))
return -EINVAL;
stats = match_strdup(&args[0]);
if (!stats)
return -ENOMEM;
if (strcmp(stats, "global") != 0) {
kfree(stats);
return -EINVAL;
}
opts->stats_mode = STATS_GLOBAL;
kfree(stats);
break;
default:
pr_err("Invalid mount options\n");
return -EINVAL;
......@@ -323,8 +317,21 @@ static int binderfs_parse_mount_opts(char *data,
static int binderfs_remount(struct super_block *sb, int *flags, char *data)
{
int prev_stats_mode, ret;
struct binderfs_info *info = sb->s_fs_info;
return binderfs_parse_mount_opts(data, &info->mount_opts);
prev_stats_mode = info->mount_opts.stats_mode;
ret = binderfs_parse_mount_opts(data, &info->mount_opts);
if (ret)
return ret;
if (prev_stats_mode != info->mount_opts.stats_mode) {
pr_err("Binderfs stats mode cannot be changed during a remount\n");
info->mount_opts.stats_mode = prev_stats_mode;
return -EINVAL;
}
return 0;
}
static int binderfs_show_mount_opts(struct seq_file *seq, struct dentry *root)
......@@ -334,6 +341,8 @@ static int binderfs_show_mount_opts(struct seq_file *seq, struct dentry *root)
info = root->d_sb->s_fs_info;
if (info->mount_opts.max <= BINDERFS_MAX_MINOR)
seq_printf(seq, ",max=%d", info->mount_opts.max);
if (info->mount_opts.stats_mode == STATS_GLOBAL)
seq_printf(seq, ",stats=global");
return 0;
}
......@@ -462,11 +471,192 @@ static const struct inode_operations binderfs_dir_inode_operations = {
.unlink = binderfs_unlink,
};
static struct inode *binderfs_make_inode(struct super_block *sb, int mode)
{
struct inode *ret;
ret = new_inode(sb);
if (ret) {
ret->i_ino = iunique(sb, BINDERFS_MAX_MINOR + INODE_OFFSET);
ret->i_mode = mode;
ret->i_atime = ret->i_mtime = ret->i_ctime = current_time(ret);
}
return ret;
}
static struct dentry *binderfs_create_dentry(struct dentry *parent,
const char *name)
{
struct dentry *dentry;
dentry = lookup_one_len(name, parent, strlen(name));
if (IS_ERR(dentry))
return dentry;
/* Return error if the file/dir already exists. */
if (d_really_is_positive(dentry)) {
dput(dentry);
return ERR_PTR(-EEXIST);
}
return dentry;
}
void binderfs_remove_file(struct dentry *dentry)
{
struct inode *parent_inode;
parent_inode = d_inode(dentry->d_parent);
inode_lock(parent_inode);
if (simple_positive(dentry)) {
dget(dentry);
simple_unlink(parent_inode, dentry);
d_delete(dentry);
dput(dentry);
}
inode_unlock(parent_inode);
}
struct dentry *binderfs_create_file(struct dentry *parent, const char *name,
const struct file_operations *fops,
void *data)
{
struct dentry *dentry;
struct inode *new_inode, *parent_inode;
struct super_block *sb;
parent_inode = d_inode(parent);
inode_lock(parent_inode);
dentry = binderfs_create_dentry(parent, name);
if (IS_ERR(dentry))
goto out;
sb = parent_inode->i_sb;
new_inode = binderfs_make_inode(sb, S_IFREG | 0444);
if (!new_inode) {
dput(dentry);
dentry = ERR_PTR(-ENOMEM);
goto out;
}
new_inode->i_fop = fops;
new_inode->i_private = data;
d_instantiate(dentry, new_inode);
fsnotify_create(parent_inode, dentry);
out:
inode_unlock(parent_inode);
return dentry;
}
static struct dentry *binderfs_create_dir(struct dentry *parent,
const char *name)
{
struct dentry *dentry;
struct inode *new_inode, *parent_inode;
struct super_block *sb;
parent_inode = d_inode(parent);
inode_lock(parent_inode);
dentry = binderfs_create_dentry(parent, name);
if (IS_ERR(dentry))
goto out;
sb = parent_inode->i_sb;
new_inode = binderfs_make_inode(sb, S_IFDIR | 0755);
if (!new_inode) {
dput(dentry);
dentry = ERR_PTR(-ENOMEM);
goto out;
}
new_inode->i_fop = &simple_dir_operations;
new_inode->i_op = &simple_dir_inode_operations;
set_nlink(new_inode, 2);
d_instantiate(dentry, new_inode);
inc_nlink(parent_inode);
fsnotify_mkdir(parent_inode, dentry);
out:
inode_unlock(parent_inode);
return dentry;
}
static int init_binder_logs(struct super_block *sb)
{
struct dentry *binder_logs_root_dir, *dentry, *proc_log_dir;
struct binderfs_info *info;
int ret = 0;
binder_logs_root_dir = binderfs_create_dir(sb->s_root,
"binder_logs");
if (IS_ERR(binder_logs_root_dir)) {
ret = PTR_ERR(binder_logs_root_dir);
goto out;
}
dentry = binderfs_create_file(binder_logs_root_dir, "stats",
&binder_stats_fops, NULL);
if (IS_ERR(dentry)) {
ret = PTR_ERR(dentry);
goto out;
}
dentry = binderfs_create_file(binder_logs_root_dir, "state",
&binder_state_fops, NULL);
if (IS_ERR(dentry)) {
ret = PTR_ERR(dentry);
goto out;
}
dentry = binderfs_create_file(binder_logs_root_dir, "transactions",
&binder_transactions_fops, NULL);
if (IS_ERR(dentry)) {
ret = PTR_ERR(dentry);
goto out;
}
dentry = binderfs_create_file(binder_logs_root_dir,
"transaction_log",
&binder_transaction_log_fops,
&binder_transaction_log);
if (IS_ERR(dentry)) {
ret = PTR_ERR(dentry);
goto out;
}
dentry = binderfs_create_file(binder_logs_root_dir,
"failed_transaction_log",
&binder_transaction_log_fops,
&binder_transaction_log_failed);
if (IS_ERR(dentry)) {
ret = PTR_ERR(dentry);
goto out;
}
proc_log_dir = binderfs_create_dir(binder_logs_root_dir, "proc");
if (IS_ERR(proc_log_dir)) {
ret = PTR_ERR(proc_log_dir);
goto out;
}
info = sb->s_fs_info;
info->proc_log_dir = proc_log_dir;
out:
return ret;
}
static int binderfs_fill_super(struct super_block *sb, void *data, int silent)
{
int ret;
struct binderfs_info *info;
struct inode *inode = NULL;
struct binderfs_device device_info = { 0 };
const char *name;
size_t len;
sb->s_blocksize = PAGE_SIZE;
sb->s_blocksize_bits = PAGE_SHIFT;
......@@ -521,7 +711,25 @@ static int binderfs_fill_super(struct super_block *sb, void *data, int silent)
if (!sb->s_root)
return -ENOMEM;
return binderfs_binder_ctl_create(sb);
ret = binderfs_binder_ctl_create(sb);
if (ret)
return ret;
name = binder_devices_param;
for (len = strcspn(name, ","); len > 0; len = strcspn(name, ",")) {
strscpy(device_info.name, name, len + 1);
ret = binderfs_binder_device_create(inode, NULL, &device_info);
if (ret)
return ret;
name += len;
if (*name == ',')
name++;
}
if (info->mount_opts.stats_mode == STATS_GLOBAL)
return init_binder_logs(sb);
return 0;
}
static struct dentry *binderfs_mount(struct file_system_type *fs_type,
......@@ -553,6 +761,18 @@ static struct file_system_type binder_fs_type = {
int __init init_binderfs(void)
{
int ret;
const char *name;
size_t len;
/* Verify that the default binderfs device names are valid. */
name = binder_devices_param;
for (len = strcspn(name, ","); len > 0; len = strcspn(name, ",")) {
if (len > BINDERFS_MAX_NAME)
return -E2BIG;
name += len;
if (*name == ',')
name++;
}
/* Allocate new major number for binderfs. */
ret = alloc_chrdev_region(&binderfs_dev, 0, BINDERFS_MAX_MINOR,
......
......@@ -97,6 +97,13 @@ void __weak unxlate_dev_mem_ptr(phys_addr_t phys, void *addr)
}
#endif
static inline bool should_stop_iteration(void)
{
if (need_resched())
cond_resched();
return fatal_signal_pending(current);
}
/*
* This funcion reads the *physical* memory. The f_pos points directly to the
* memory location.
......@@ -175,6 +182,8 @@ static ssize_t read_mem(struct file *file, char __user *buf,
p += sz;
count -= sz;
read += sz;
if (should_stop_iteration())
break;
}
kfree(bounce);
......@@ -251,6 +260,8 @@ static ssize_t write_mem(struct file *file, const char __user *buf,
p += sz;
count -= sz;
written += sz;
if (should_stop_iteration())
break;
}
*ppos += written;
......@@ -468,6 +479,10 @@ static ssize_t read_kmem(struct file *file, char __user *buf,
read += sz;
low_count -= sz;
count -= sz;
if (should_stop_iteration()) {
count = 0;
break;
}
}
}
......@@ -492,6 +507,8 @@ static ssize_t read_kmem(struct file *file, char __user *buf,
buf += sz;
read += sz;
p += sz;
if (should_stop_iteration())
break;
}
free_page((unsigned long)kbuf);
}
......@@ -544,6 +561,8 @@ static ssize_t do_write_kmem(unsigned long p, const char __user *buf,
p += sz;
count -= sz;
written += sz;
if (should_stop_iteration())
break;
}
*ppos += written;
......@@ -595,6 +614,8 @@ static ssize_t write_kmem(struct file *file, const char __user *buf,
buf += sz;
virtr += sz;
p += sz;
if (should_stop_iteration())
break;
}
free_page((unsigned long)kbuf);
}
......
......@@ -737,7 +737,7 @@ static int pp_release(struct inode *inode, struct file *file)
"negotiated back to compatibility mode because user-space forgot\n");
}
if (pp->flags & PP_CLAIMED) {
if ((pp->flags & PP_CLAIMED) && pp->pdev) {
struct ieee1284_info *info;
info = &pp->pdev->port->ieee1284;
......
......@@ -373,7 +373,7 @@ static int tosh_get_machine_id(void __iomem *bios)
value. This has been verified on a Satellite Pro 430CDT,
Tecra 750CDT, Tecra 780DVD and Satellite 310CDT. */
#if TOSH_DEBUG
printk("toshiba: debugging ID ebx=0x%04x\n", regs.ebx);
pr_debug("toshiba: debugging ID ebx=0x%04x\n", regs.ebx);
#endif
bx = 0xe6f5;
......@@ -417,7 +417,7 @@ static int tosh_probe(void)
for (i=0;i<7;i++) {
if (readb(bios+0xe010+i)!=signature[i]) {
printk("toshiba: not a supported Toshiba laptop\n");
pr_err("toshiba: not a supported Toshiba laptop\n");
iounmap(bios);
return -ENODEV;
}
......@@ -433,7 +433,7 @@ static int tosh_probe(void)
/* if this is not a Toshiba laptop carry flag is set and ah=0x86 */
if ((flag==1) || ((regs.eax & 0xff00)==0x8600)) {
printk("toshiba: not a supported Toshiba laptop\n");
pr_err("toshiba: not a supported Toshiba laptop\n");
iounmap(bios);
return -ENODEV;
}
......@@ -486,7 +486,7 @@ static int __init toshiba_init(void)
if (tosh_probe())
return -ENODEV;
printk(KERN_INFO "Toshiba System Management Mode driver v" TOSH_VERSION "\n");
pr_info("Toshiba System Management Mode driver v" TOSH_VERSION "\n");
/* set the port to use for Fn status if not specified as a parameter */
if (tosh_fn==0x00)
......
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
*/
#include <linux/clk-provider.h>
......@@ -12,23 +12,13 @@
#include <linux/platform_device.h>
#include <soc/qcom/cmd-db.h>
#include <soc/qcom/rpmh.h>
#include <soc/qcom/tcs.h>
#include <dt-bindings/clock/qcom,rpmh.h>
#define CLK_RPMH_ARC_EN_OFFSET 0
#define CLK_RPMH_VRM_EN_OFFSET 4
#define BCM_TCS_CMD_COMMIT_MASK 0x40000000
#define BCM_TCS_CMD_VALID_SHIFT 29
#define BCM_TCS_CMD_VOTE_MASK 0x3fff
#define BCM_TCS_CMD_VOTE_SHIFT 0
#define BCM_TCS_CMD(valid, vote) \
(BCM_TCS_CMD_COMMIT_MASK | \
((valid) << BCM_TCS_CMD_VALID_SHIFT) | \
((vote & BCM_TCS_CMD_VOTE_MASK) \
<< BCM_TCS_CMD_VOTE_SHIFT))
/**
* struct bcm_db - Auxiliary data pertaining to each Bus Clock Manager(BCM)
* @unit: divisor used to convert Hz value to an RPMh msg
......@@ -269,7 +259,7 @@ static int clk_rpmh_bcm_send_cmd(struct clk_rpmh *c, bool enable)
}
cmd.addr = c->res_addr;
cmd.data = BCM_TCS_CMD(enable, cmd_state);
cmd.data = BCM_TCS_CMD(1, enable, 0, cmd_state);
ret = rpmh_write_async(c->dev, RPMH_ACTIVE_ONLY_STATE, &cmd, 1);
if (ret) {
......
......@@ -140,10 +140,8 @@ static int adc_jack_probe(struct platform_device *pdev)
return err;
data->irq = platform_get_irq(pdev, 0);
if (data->irq < 0) {
dev_err(&pdev->dev, "platform_get_irq failed\n");
if (data->irq < 0)
return -ENODEV;
}
err = request_any_context_irq(data->irq, adc_jack_irq_thread,
pdata->irq_flags, pdata->name, data);
......
......@@ -1253,7 +1253,7 @@ static int arizona_extcon_get_micd_configs(struct device *dev,
int i, j;
u32 *vals;
nconfs = device_property_read_u32_array(arizona->dev, prop, NULL, 0);
nconfs = device_property_count_u32(arizona->dev, prop);
if (nconfs <= 0)
return 0;
......
......@@ -121,7 +121,6 @@ static const char * const axp288_pwr_up_down_info[] = {
"Last shutdown caused by PMIC UVLO threshold",
"Last shutdown caused by SOC initiated cold off",
"Last shutdown caused by user pressing the power button",
NULL,
};
/*
......@@ -130,18 +129,21 @@ static const char * const axp288_pwr_up_down_info[] = {
*/
static void axp288_extcon_log_rsi(struct axp288_extcon_info *info)
{
const char * const *rsi;
unsigned int val, i, clear_mask = 0;
unsigned long bits;
int ret;
ret = regmap_read(info->regmap, AXP288_PS_BOOT_REASON_REG, &val);
for (i = 0, rsi = axp288_pwr_up_down_info; *rsi; rsi++, i++) {
if (val & BIT(i)) {
dev_dbg(info->dev, "%s\n", *rsi);
clear_mask |= BIT(i);
}
if (ret < 0) {
dev_err(info->dev, "failed to read reset source indicator\n");
return;
}
bits = val & GENMASK(ARRAY_SIZE(axp288_pwr_up_down_info) - 1, 0);
for_each_set_bit(i, &bits, ARRAY_SIZE(axp288_pwr_up_down_info))
dev_dbg(info->dev, "%s\n", axp288_pwr_up_down_info[i]);
clear_mask = bits;
/* Clear the register value for next reboot (write 1 to clear bit) */
regmap_write(info->regmap, AXP288_PS_BOOT_REASON_REG, clear_mask);
}
......
......@@ -363,6 +363,7 @@ MODULE_DEVICE_TABLE(i2c, fsa9480_id);
static const struct of_device_id fsa9480_of_match[] = {
{ .compatible = "fcs,fsa9480", },
{ .compatible = "fcs,fsa880", },
{ },
};
MODULE_DEVICE_TABLE(of, fsa9480_of_match);
......
......@@ -22,26 +22,22 @@
/**
* struct gpio_extcon_data - A simple GPIO-controlled extcon device state container.
* @edev: Extcon device.
* @irq: Interrupt line for the external connector.
* @work: Work fired by the interrupt.
* @debounce_jiffies: Number of jiffies to wait for the GPIO to stabilize, from the debounce
* value.
* @gpiod: GPIO descriptor for this external connector.
* @extcon_id: The unique id of specific external connector.
* @debounce: Debounce time for GPIO IRQ in ms.
* @irq_flags: IRQ Flags (e.g., IRQF_TRIGGER_LOW).
* @check_on_resume: Boolean describing whether to check the state of gpio
* while resuming from sleep.
*/
struct gpio_extcon_data {
struct extcon_dev *edev;
int irq;
struct delayed_work work;
unsigned long debounce_jiffies;
struct gpio_desc *gpiod;
unsigned int extcon_id;
unsigned long debounce;
unsigned long irq_flags;
bool check_on_resume;
};
......@@ -69,6 +65,8 @@ static int gpio_extcon_probe(struct platform_device *pdev)
{
struct gpio_extcon_data *data;
struct device *dev = &pdev->dev;
unsigned long irq_flags;
int irq;
int ret;
data = devm_kzalloc(dev, sizeof(struct gpio_extcon_data), GFP_KERNEL);
......@@ -82,15 +80,26 @@ static int gpio_extcon_probe(struct platform_device *pdev)
* developed to get the extcon id from device-tree or others.
* On later, it have to be solved.
*/
if (!data->irq_flags || data->extcon_id > EXTCON_NONE)
if (data->extcon_id > EXTCON_NONE)
return -EINVAL;
data->gpiod = devm_gpiod_get(dev, "extcon", GPIOD_IN);
if (IS_ERR(data->gpiod))
return PTR_ERR(data->gpiod);
data->irq = gpiod_to_irq(data->gpiod);
if (data->irq <= 0)
return data->irq;
irq = gpiod_to_irq(data->gpiod);
if (irq <= 0)
return irq;
/*
* It is unlikely that this is an acknowledged interrupt that goes
* away after handling, what we are looking for are falling edges
* if the signal is active low, and rising edges if the signal is
* active high.
*/
if (gpiod_is_active_low(data->gpiod))
irq_flags = IRQF_TRIGGER_FALLING;
else
irq_flags = IRQF_TRIGGER_RISING;
/* Allocate the memory of extcon devie and register extcon device */
data->edev = devm_extcon_dev_allocate(dev, &data->extcon_id);
......@@ -109,8 +118,8 @@ static int gpio_extcon_probe(struct platform_device *pdev)
* Request the interrupt of gpio to detect whether external connector
* is attached or detached.
*/
ret = devm_request_any_context_irq(dev, data->irq,
gpio_irq_handler, data->irq_flags,
ret = devm_request_any_context_irq(dev, irq,
gpio_irq_handler, irq_flags,
pdev->name, data);
if (ret < 0)
return ret;
......
......@@ -774,12 +774,12 @@ static int max77843_init_muic_regmap(struct max77693_dev *max77843)
{
int ret;
max77843->i2c_muic = i2c_new_dummy(max77843->i2c->adapter,
max77843->i2c_muic = i2c_new_dummy_device(max77843->i2c->adapter,
I2C_ADDR_MUIC);
if (!max77843->i2c_muic) {
if (IS_ERR(max77843->i2c_muic)) {
dev_err(&max77843->i2c->dev,
"Cannot allocate I2C device for MUIC\n");
return -ENOMEM;
return PTR_ERR(max77843->i2c_muic);
}
i2c_set_clientdata(max77843->i2c_muic, max77843);
......
......@@ -597,7 +597,7 @@ static int sm5022_muic_i2c_probe(struct i2c_client *i2c,
ret = devm_request_threaded_irq(info->dev, virq, NULL,
sm5502_muic_irq_handler,
IRQF_NO_SUSPEND,
IRQF_NO_SUSPEND | IRQF_ONESHOT,
muic_irq->name, info);
if (ret) {
dev_err(info->dev,
......
......@@ -216,6 +216,24 @@ config INTEL_STRATIX10_SERVICE
Say Y here if you want Stratix10 service layer support.
config INTEL_STRATIX10_RSU
tristate "Intel Stratix10 Remote System Update"
depends on INTEL_STRATIX10_SERVICE
help
The Intel Remote System Update (RSU) driver exposes interfaces
access through the Intel Service Layer to user space via sysfs
device attribute nodes. The RSU interfaces report/control some of
the optional RSU features of the Stratix 10 SoC FPGA.
The RSU provides a way for customers to update the boot
configuration of a Stratix 10 SoC device with significantly reduced
risk of corrupting the bitstream storage and bricking the system.
Enable RSU support if you are using an Intel SoC FPGA with the RSU
feature enabled and you want Linux user space control.
Say Y here if you want Intel RSU support.
config QCOM_SCM
bool
depends on ARM || ARM64
......
......@@ -11,6 +11,7 @@ obj-$(CONFIG_EDD) += edd.o
obj-$(CONFIG_EFI_PCDP) += pcdp.o
obj-$(CONFIG_DMIID) += dmi-id.o
obj-$(CONFIG_INTEL_STRATIX10_SERVICE) += stratix10-svc.o
obj-$(CONFIG_INTEL_STRATIX10_RSU) += stratix10-rsu.o
obj-$(CONFIG_ISCSI_IBFT_FIND) += iscsi_ibft_find.o
obj-$(CONFIG_ISCSI_IBFT) += iscsi_ibft.o
obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o
......
......@@ -92,8 +92,8 @@ static int vpd_section_check_key_name(const u8 *key, s32 key_len)
return VPD_OK;
}
static int vpd_section_attrib_add(const u8 *key, s32 key_len,
const u8 *value, s32 value_len,
static int vpd_section_attrib_add(const u8 *key, u32 key_len,
const u8 *value, u32 value_len,
void *arg)
{
int ret;
......
......@@ -9,8 +9,8 @@
#include "vpd_decode.h"
static int vpd_decode_len(const s32 max_len, const u8 *in,
s32 *length, s32 *decoded_len)
static int vpd_decode_len(const u32 max_len, const u8 *in,
u32 *length, u32 *decoded_len)
{
u8 more;
int i = 0;
......@@ -30,18 +30,39 @@ static int vpd_decode_len(const s32 max_len, const u8 *in,
} while (more);
*decoded_len = i;
return VPD_OK;
}
static int vpd_decode_entry(const u32 max_len, const u8 *input_buf,
u32 *_consumed, const u8 **entry, u32 *entry_len)
{
u32 decoded_len;
u32 consumed = *_consumed;
if (vpd_decode_len(max_len - consumed, &input_buf[consumed],
entry_len, &decoded_len) != VPD_OK)
return VPD_FAIL;
if (max_len - consumed < decoded_len)
return VPD_FAIL;
consumed += decoded_len;
*entry = input_buf + consumed;
/* entry_len is untrusted data and must be checked again. */
if (max_len - consumed < *entry_len)
return VPD_FAIL;
consumed += decoded_len;
*_consumed = consumed;
return VPD_OK;
}
int vpd_decode_string(const s32 max_len, const u8 *input_buf, s32 *consumed,
int vpd_decode_string(const u32 max_len, const u8 *input_buf, u32 *consumed,
vpd_decode_callback callback, void *callback_arg)
{
int type;
int res;
s32 key_len;
s32 value_len;
s32 decoded_len;
u32 key_len;
u32 value_len;
const u8 *key;
const u8 *value;
......@@ -56,26 +77,14 @@ int vpd_decode_string(const s32 max_len, const u8 *input_buf, s32 *consumed,
case VPD_TYPE_STRING:
(*consumed)++;
/* key */
res = vpd_decode_len(max_len - *consumed, &input_buf[*consumed],
&key_len, &decoded_len);
if (res != VPD_OK || *consumed + decoded_len >= max_len)
if (vpd_decode_entry(max_len, input_buf, consumed, &key,
&key_len) != VPD_OK)
return VPD_FAIL;
*consumed += decoded_len;
key = &input_buf[*consumed];
*consumed += key_len;
/* value */
res = vpd_decode_len(max_len - *consumed, &input_buf[*consumed],
&value_len, &decoded_len);
if (res != VPD_OK || *consumed + decoded_len > max_len)
if (vpd_decode_entry(max_len, input_buf, consumed, &value,
&value_len) != VPD_OK)
return VPD_FAIL;
*consumed += decoded_len;
value = &input_buf[*consumed];
*consumed += value_len;
if (type == VPD_TYPE_STRING)
return callback(key, key_len, value, value_len,
callback_arg);
......
......@@ -25,8 +25,8 @@ enum {
};
/* Callback for vpd_decode_string to invoke. */
typedef int vpd_decode_callback(const u8 *key, s32 key_len,
const u8 *value, s32 value_len,
typedef int vpd_decode_callback(const u8 *key, u32 key_len,
const u8 *value, u32 value_len,
void *arg);
/*
......@@ -44,7 +44,7 @@ typedef int vpd_decode_callback(const u8 *key, s32 key_len,
* If one entry is successfully decoded, sends it to callback and returns the
* result.
*/
int vpd_decode_string(const s32 max_len, const u8 *input_buf, s32 *consumed,
int vpd_decode_string(const u32 max_len, const u8 *input_buf, u32 *consumed,
vpd_decode_callback callback, void *callback_arg);
#endif /* __VPD_DECODE_H */
This diff is collapsed.
......@@ -38,12 +38,23 @@
#define FPGA_CONFIG_DATA_CLAIM_TIMEOUT_MS 200
#define FPGA_CONFIG_STATUS_TIMEOUT_SEC 30
/* stratix10 service layer clients */
#define STRATIX10_RSU "stratix10-rsu"
typedef void (svc_invoke_fn)(unsigned long, unsigned long, unsigned long,
unsigned long, unsigned long, unsigned long,
unsigned long, unsigned long,
struct arm_smccc_res *);
struct stratix10_svc_chan;
/**
* struct stratix10_svc - svc private data
* @stratix10_svc_rsu: pointer to stratix10 RSU device
*/
struct stratix10_svc {
struct platform_device *stratix10_svc_rsu;
};
/**
* struct stratix10_svc_sh_memory - service shared memory structure
* @sync_complete: state for a completion
......@@ -296,7 +307,12 @@ static void svc_thread_recv_status_ok(struct stratix10_svc_data *p_data,
cb_data->status = BIT(SVC_STATUS_RECONFIG_COMPLETED);
break;
case COMMAND_RSU_UPDATE:
case COMMAND_RSU_NOTIFY:
cb_data->status = BIT(SVC_STATUS_RSU_OK);
break;
case COMMAND_RSU_RETRY:
cb_data->status = BIT(SVC_STATUS_RSU_OK);
cb_data->kaddr1 = &res.a1;
break;
default:
pr_warn("it shouldn't happen\n");
......@@ -386,6 +402,16 @@ static int svc_normal_to_secure_thread(void *data)
a1 = pdata->arg[0];
a2 = 0;
break;
case COMMAND_RSU_NOTIFY:
a0 = INTEL_SIP_SMC_RSU_NOTIFY;
a1 = pdata->arg[0];
a2 = 0;
break;
case COMMAND_RSU_RETRY:
a0 = INTEL_SIP_SMC_RSU_RETRY_COUNTER;
a1 = 0;
a2 = 0;
break;
default:
pr_warn("it shouldn't happen\n");
break;
......@@ -438,7 +464,28 @@ static int svc_normal_to_secure_thread(void *data)
pr_debug("%s: STATUS_REJECTED\n", __func__);
break;
case INTEL_SIP_SMC_FPGA_CONFIG_STATUS_ERROR:
case INTEL_SIP_SMC_RSU_ERROR:
pr_err("%s: STATUS_ERROR\n", __func__);
switch (pdata->command) {
/* for FPGA mgr */
case COMMAND_RECONFIG_DATA_CLAIM:
case COMMAND_RECONFIG:
case COMMAND_RECONFIG_DATA_SUBMIT:
case COMMAND_RECONFIG_STATUS:
cbdata->status =
BIT(SVC_STATUS_RECONFIG_ERROR);
break;
/* for RSU */
case COMMAND_RSU_STATUS:
case COMMAND_RSU_UPDATE:
case COMMAND_RSU_NOTIFY:
case COMMAND_RSU_RETRY:
cbdata->status =
BIT(SVC_STATUS_RSU_ERROR);
break;
}
cbdata->status = BIT(SVC_STATUS_RECONFIG_ERROR);
cbdata->kaddr1 = NULL;
cbdata->kaddr2 = NULL;
......@@ -530,7 +577,7 @@ static int svc_get_sh_memory(struct platform_device *pdev,
if (!sh_memory->addr || !sh_memory->size) {
dev_err(dev,
"fails to get shared memory info from secure world\n");
"failed to get shared memory info from secure world\n");
return -ENOMEM;
}
......@@ -768,7 +815,7 @@ int stratix10_svc_send(struct stratix10_svc_chan *chan, void *msg)
"svc_smc_hvc_thread");
if (IS_ERR(chan->ctrl->task)) {
dev_err(chan->ctrl->dev,
"fails to create svc_smc_hvc_thread\n");
"failed to create svc_smc_hvc_thread\n");
kfree(p_data);
return -EINVAL;
}
......@@ -913,6 +960,8 @@ static int stratix10_svc_drv_probe(struct platform_device *pdev)
struct stratix10_svc_chan *chans;
struct gen_pool *genpool;
struct stratix10_svc_sh_memory *sh_memory;
struct stratix10_svc *svc;
svc_invoke_fn *invoke_fn;
size_t fifo_size;
int ret;
......@@ -957,7 +1006,7 @@ static int stratix10_svc_drv_probe(struct platform_device *pdev)
fifo_size = sizeof(struct stratix10_svc_data) * SVC_NUM_DATA_IN_FIFO;
ret = kfifo_alloc(&controller->svc_fifo, fifo_size, GFP_KERNEL);
if (ret) {
dev_err(dev, "fails to allocate FIFO\n");
dev_err(dev, "failed to allocate FIFO\n");
return ret;
}
spin_lock_init(&controller->svc_fifo_lock);
......@@ -975,6 +1024,24 @@ static int stratix10_svc_drv_probe(struct platform_device *pdev)
list_add_tail(&controller->node, &svc_ctrl);
platform_set_drvdata(pdev, controller);
/* add svc client device(s) */
svc = devm_kzalloc(dev, sizeof(*svc), GFP_KERNEL);
if (!svc)
return -ENOMEM;
svc->stratix10_svc_rsu = platform_device_alloc(STRATIX10_RSU, 0);
if (!svc->stratix10_svc_rsu) {
dev_err(dev, "failed to allocate %s device\n", STRATIX10_RSU);
return -ENOMEM;
}
ret = platform_device_add(svc->stratix10_svc_rsu);
if (ret) {
platform_device_put(svc->stratix10_svc_rsu);
return ret;
}
dev_set_drvdata(dev, svc);
pr_info("Intel Service Layer Driver Initialized\n");
return ret;
......@@ -982,8 +1049,11 @@ static int stratix10_svc_drv_probe(struct platform_device *pdev)
static int stratix10_svc_drv_remove(struct platform_device *pdev)
{
struct stratix10_svc *svc = dev_get_drvdata(&pdev->dev);
struct stratix10_svc_controller *ctrl = platform_get_drvdata(pdev);
platform_device_unregister(svc->stratix10_svc_rsu);
kfifo_free(&ctrl->svc_fifo);
if (ctrl->task) {
kthread_stop(ctrl->task);
......
......@@ -46,11 +46,11 @@ config FPGA_MGR_ALTERA_PS_SPI
using the passive serial interface over SPI.
config FPGA_MGR_ALTERA_CVP
tristate "Altera Arria-V/Cyclone-V/Stratix-V CvP FPGA Manager"
tristate "Altera CvP FPGA Manager"
depends on PCI
help
FPGA manager driver support for Arria-V, Cyclone-V, Stratix-V
and Arria 10 Altera FPGAs using the CvP interface over PCIe.
FPGA manager driver support for Arria-V, Cyclone-V, Stratix-V,
Arria 10 and Stratix10 Altera FPGAs using the CvP interface over PCIe.
config FPGA_MGR_ZYNQ_FPGA
tristate "Xilinx Zynq FPGA"
......
......@@ -39,8 +39,9 @@ obj-$(CONFIG_FPGA_DFL_FME_BRIDGE) += dfl-fme-br.o
obj-$(CONFIG_FPGA_DFL_FME_REGION) += dfl-fme-region.o
obj-$(CONFIG_FPGA_DFL_AFU) += dfl-afu.o
dfl-fme-objs := dfl-fme-main.o dfl-fme-pr.o
dfl-fme-objs := dfl-fme-main.o dfl-fme-pr.o dfl-fme-error.o
dfl-afu-objs := dfl-afu-main.o dfl-afu-region.o dfl-afu-dma-region.o
dfl-afu-objs += dfl-afu-error.o
# Drivers for FPGAs which implement DFL
obj-$(CONFIG_FPGA_DFL_PCI) += dfl-pci.o
This diff is collapsed.
......@@ -32,7 +32,9 @@ static int alt_pr_platform_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
return alt_pr_unregister(dev);
alt_pr_unregister(dev);
return 0;
}
static const struct of_device_id alt_pr_of_match[] = {
......
......@@ -201,15 +201,13 @@ int alt_pr_register(struct device *dev, void __iomem *reg_base)
}
EXPORT_SYMBOL_GPL(alt_pr_register);
int alt_pr_unregister(struct device *dev)
void alt_pr_unregister(struct device *dev)
{
struct fpga_manager *mgr = dev_get_drvdata(dev);
dev_dbg(dev, "%s\n", __func__);
fpga_mgr_unregister(mgr);
return 0;
}
EXPORT_SYMBOL_GPL(alt_pr_unregister);
......
// SPDX-License-Identifier: GPL-2.0
/*
* Driver for FPGA Accelerated Function Unit (AFU) Error Reporting
*
* Copyright 2019 Intel Corporation, Inc.
*
* Authors:
* Wu Hao <hao.wu@linux.intel.com>
* Xiao Guangrong <guangrong.xiao@linux.intel.com>
* Joseph Grecco <joe.grecco@intel.com>
* Enno Luebbers <enno.luebbers@intel.com>
* Tim Whisonant <tim.whisonant@intel.com>
* Ananda Ravuri <ananda.ravuri@intel.com>
* Mitchel Henry <henry.mitchel@intel.com>
*/
#include <linux/uaccess.h>
#include "dfl-afu.h"
#define PORT_ERROR_MASK 0x8
#define PORT_ERROR 0x10
#define PORT_FIRST_ERROR 0x18
#define PORT_MALFORMED_REQ0 0x20
#define PORT_MALFORMED_REQ1 0x28
#define ERROR_MASK GENMASK_ULL(63, 0)
/* mask or unmask port errors by the error mask register. */
static void __afu_port_err_mask(struct device *dev, bool mask)
{
void __iomem *base;
base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_ERROR);
writeq(mask ? ERROR_MASK : 0, base + PORT_ERROR_MASK);
}
static void afu_port_err_mask(struct device *dev, bool mask)
{
struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
mutex_lock(&pdata->lock);
__afu_port_err_mask(dev, mask);
mutex_unlock(&pdata->lock);
}
/* clear port errors. */
static int afu_port_err_clear(struct device *dev, u64 err)
{
struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
struct platform_device *pdev = to_platform_device(dev);
void __iomem *base_err, *base_hdr;
int ret = -EBUSY;
u64 v;
base_err = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_ERROR);
base_hdr = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER);
mutex_lock(&pdata->lock);
/*
* clear Port Errors
*
* - Check for AP6 State
* - Halt Port by keeping Port in reset
* - Set PORT Error mask to all 1 to mask errors
* - Clear all errors
* - Set Port mask to all 0 to enable errors
* - All errors start capturing new errors
* - Enable Port by pulling the port out of reset
*/
/* if device is still in AP6 power state, can not clear any error. */
v = readq(base_hdr + PORT_HDR_STS);
if (FIELD_GET(PORT_STS_PWR_STATE, v) == PORT_STS_PWR_STATE_AP6) {
dev_err(dev, "Could not clear errors, device in AP6 state.\n");
goto done;
}
/* Halt Port by keeping Port in reset */
ret = __afu_port_disable(pdev);
if (ret)
goto done;
/* Mask all errors */
__afu_port_err_mask(dev, true);
/* Clear errors if err input matches with current port errors.*/
v = readq(base_err + PORT_ERROR);
if (v == err) {
writeq(v, base_err + PORT_ERROR);
v = readq(base_err + PORT_FIRST_ERROR);
writeq(v, base_err + PORT_FIRST_ERROR);
} else {
ret = -EINVAL;
}
/* Clear mask */
__afu_port_err_mask(dev, false);
/* Enable the Port by clear the reset */
__afu_port_enable(pdev);
done:
mutex_unlock(&pdata->lock);
return ret;
}
static ssize_t errors_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
void __iomem *base;
u64 error;
base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_ERROR);
mutex_lock(&pdata->lock);
error = readq(base + PORT_ERROR);
mutex_unlock(&pdata->lock);
return sprintf(buf, "0x%llx\n", (unsigned long long)error);
}
static ssize_t errors_store(struct device *dev, struct device_attribute *attr,
const char *buff, size_t count)
{
u64 value;
int ret;
if (kstrtou64(buff, 0, &value))
return -EINVAL;
ret = afu_port_err_clear(dev, value);
return ret ? ret : count;
}
static DEVICE_ATTR_RW(errors);
static ssize_t first_error_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
void __iomem *base;
u64 error;
base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_ERROR);
mutex_lock(&pdata->lock);
error = readq(base + PORT_FIRST_ERROR);
mutex_unlock(&pdata->lock);
return sprintf(buf, "0x%llx\n", (unsigned long long)error);
}
static DEVICE_ATTR_RO(first_error);
static ssize_t first_malformed_req_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
void __iomem *base;
u64 req0, req1;
base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_ERROR);
mutex_lock(&pdata->lock);
req0 = readq(base + PORT_MALFORMED_REQ0);
req1 = readq(base + PORT_MALFORMED_REQ1);
mutex_unlock(&pdata->lock);
return sprintf(buf, "0x%016llx%016llx\n",
(unsigned long long)req1, (unsigned long long)req0);
}
static DEVICE_ATTR_RO(first_malformed_req);
static struct attribute *port_err_attrs[] = {
&dev_attr_errors.attr,
&dev_attr_first_error.attr,
&dev_attr_first_malformed_req.attr,
NULL,
};
static umode_t port_err_attrs_visible(struct kobject *kobj,
struct attribute *attr, int n)
{
struct device *dev = kobj_to_dev(kobj);
/*
* sysfs entries are visible only if related private feature is
* enumerated.
*/
if (!dfl_get_feature_by_id(dev, PORT_FEATURE_ID_ERROR))
return 0;
return attr->mode;
}
const struct attribute_group port_err_group = {
.name = "errors",
.attrs = port_err_attrs,
.is_visible = port_err_attrs_visible,
};
static int port_err_init(struct platform_device *pdev,
struct dfl_feature *feature)
{
afu_port_err_mask(&pdev->dev, false);
return 0;
}
static void port_err_uinit(struct platform_device *pdev,
struct dfl_feature *feature)
{
afu_port_err_mask(&pdev->dev, true);
}
const struct dfl_feature_id port_err_id_table[] = {
{.id = PORT_FEATURE_ID_ERROR,},
{0,}
};
const struct dfl_feature_ops port_err_ops = {
.init = port_err_init,
.uinit = port_err_uinit,
};
This diff is collapsed.
......@@ -79,6 +79,10 @@ struct dfl_afu {
struct dfl_feature_platform_data *pdata;
};
/* hold pdata->lock when call __afu_port_enable/disable */
void __afu_port_enable(struct platform_device *pdev);
int __afu_port_disable(struct platform_device *pdev);
void afu_mmio_region_init(struct dfl_feature_platform_data *pdata);
int afu_mmio_region_add(struct dfl_feature_platform_data *pdata,
u32 region_index, u64 region_size, u64 phys, u32 flags);
......@@ -97,4 +101,9 @@ int afu_dma_unmap_region(struct dfl_feature_platform_data *pdata, u64 iova);
struct dfl_afu_dma_region *
afu_dma_region_find(struct dfl_feature_platform_data *pdata,
u64 iova, u64 size);
extern const struct dfl_feature_ops port_err_ops;
extern const struct dfl_feature_id port_err_id_table[];
extern const struct attribute_group port_err_group;
#endif /* __DFL_AFU_H */
// SPDX-License-Identifier: GPL-2.0
/*
* Driver for FPGA Management Engine Error Management
*
* Copyright 2019 Intel Corporation, Inc.
*
* Authors:
* Kang Luwei <luwei.kang@intel.com>
* Xiao Guangrong <guangrong.xiao@linux.intel.com>
* Wu Hao <hao.wu@intel.com>
* Joseph Grecco <joe.grecco@intel.com>
* Enno Luebbers <enno.luebbers@intel.com>
* Tim Whisonant <tim.whisonant@intel.com>
* Ananda Ravuri <ananda.ravuri@intel.com>
* Mitchel, Henry <henry.mitchel@intel.com>
*/
#include <linux/uaccess.h>
#include "dfl.h"
#include "dfl-fme.h"
#define FME_ERROR_MASK 0x8
#define FME_ERROR 0x10
#define MBP_ERROR BIT_ULL(6)
#define PCIE0_ERROR_MASK 0x18
#define PCIE0_ERROR 0x20
#define PCIE1_ERROR_MASK 0x28
#define PCIE1_ERROR 0x30
#define FME_FIRST_ERROR 0x38
#define FME_NEXT_ERROR 0x40
#define RAS_NONFAT_ERROR_MASK 0x48
#define RAS_NONFAT_ERROR 0x50
#define RAS_CATFAT_ERROR_MASK 0x58
#define RAS_CATFAT_ERROR 0x60
#define RAS_ERROR_INJECT 0x68
#define INJECT_ERROR_MASK GENMASK_ULL(2, 0)
#define ERROR_MASK GENMASK_ULL(63, 0)
static ssize_t pcie0_errors_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
void __iomem *base;
u64 value;
base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
mutex_lock(&pdata->lock);
value = readq(base + PCIE0_ERROR);
mutex_unlock(&pdata->lock);
return sprintf(buf, "0x%llx\n", (unsigned long long)value);
}
static ssize_t pcie0_errors_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
void __iomem *base;
int ret = 0;
u64 v, val;
if (kstrtou64(buf, 0, &val))
return -EINVAL;
base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
mutex_lock(&pdata->lock);
writeq(GENMASK_ULL(63, 0), base + PCIE0_ERROR_MASK);
v = readq(base + PCIE0_ERROR);
if (val == v)
writeq(v, base + PCIE0_ERROR);
else
ret = -EINVAL;
writeq(0ULL, base + PCIE0_ERROR_MASK);
mutex_unlock(&pdata->lock);
return ret ? ret : count;
}
static DEVICE_ATTR_RW(pcie0_errors);
static ssize_t pcie1_errors_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
void __iomem *base;
u64 value;
base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
mutex_lock(&pdata->lock);
value = readq(base + PCIE1_ERROR);
mutex_unlock(&pdata->lock);
return sprintf(buf, "0x%llx\n", (unsigned long long)value);
}
static ssize_t pcie1_errors_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
void __iomem *base;
int ret = 0;
u64 v, val;
if (kstrtou64(buf, 0, &val))
return -EINVAL;
base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
mutex_lock(&pdata->lock);
writeq(GENMASK_ULL(63, 0), base + PCIE1_ERROR_MASK);
v = readq(base + PCIE1_ERROR);
if (val == v)
writeq(v, base + PCIE1_ERROR);
else
ret = -EINVAL;
writeq(0ULL, base + PCIE1_ERROR_MASK);
mutex_unlock(&pdata->lock);
return ret ? ret : count;
}
static DEVICE_ATTR_RW(pcie1_errors);
static ssize_t nonfatal_errors_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
void __iomem *base;
base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
return sprintf(buf, "0x%llx\n",
(unsigned long long)readq(base + RAS_NONFAT_ERROR));
}
static DEVICE_ATTR_RO(nonfatal_errors);
static ssize_t catfatal_errors_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
void __iomem *base;
base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
return sprintf(buf, "0x%llx\n",
(unsigned long long)readq(base + RAS_CATFAT_ERROR));
}
static DEVICE_ATTR_RO(catfatal_errors);
static ssize_t inject_errors_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
void __iomem *base;
u64 v;
base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
mutex_lock(&pdata->lock);
v = readq(base + RAS_ERROR_INJECT);
mutex_unlock(&pdata->lock);
return sprintf(buf, "0x%llx\n",
(unsigned long long)FIELD_GET(INJECT_ERROR_MASK, v));
}
static ssize_t inject_errors_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
void __iomem *base;
u8 inject_error;
u64 v;
if (kstrtou8(buf, 0, &inject_error))
return -EINVAL;
if (inject_error & ~INJECT_ERROR_MASK)
return -EINVAL;
base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
mutex_lock(&pdata->lock);
v = readq(base + RAS_ERROR_INJECT);
v &= ~INJECT_ERROR_MASK;
v |= FIELD_PREP(INJECT_ERROR_MASK, inject_error);
writeq(v, base + RAS_ERROR_INJECT);
mutex_unlock(&pdata->lock);
return count;
}
static DEVICE_ATTR_RW(inject_errors);
static ssize_t fme_errors_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
void __iomem *base;
u64 value;
base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
mutex_lock(&pdata->lock);
value = readq(base + FME_ERROR);
mutex_unlock(&pdata->lock);
return sprintf(buf, "0x%llx\n", (unsigned long long)value);
}
static ssize_t fme_errors_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
void __iomem *base;
u64 v, val;
int ret = 0;
if (kstrtou64(buf, 0, &val))
return -EINVAL;
base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
mutex_lock(&pdata->lock);
writeq(GENMASK_ULL(63, 0), base + FME_ERROR_MASK);
v = readq(base + FME_ERROR);
if (val == v)
writeq(v, base + FME_ERROR);
else
ret = -EINVAL;
/* Workaround: disable MBP_ERROR if feature revision is 0 */
writeq(dfl_feature_revision(base) ? 0ULL : MBP_ERROR,
base + FME_ERROR_MASK);
mutex_unlock(&pdata->lock);
return ret ? ret : count;
}
static DEVICE_ATTR_RW(fme_errors);
static ssize_t first_error_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
void __iomem *base;
u64 value;
base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
mutex_lock(&pdata->lock);
value = readq(base + FME_FIRST_ERROR);
mutex_unlock(&pdata->lock);
return sprintf(buf, "0x%llx\n", (unsigned long long)value);
}
static DEVICE_ATTR_RO(first_error);
static ssize_t next_error_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
void __iomem *base;
u64 value;
base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
mutex_lock(&pdata->lock);
value = readq(base + FME_NEXT_ERROR);
mutex_unlock(&pdata->lock);
return sprintf(buf, "0x%llx\n", (unsigned long long)value);
}
static DEVICE_ATTR_RO(next_error);
static struct attribute *fme_global_err_attrs[] = {
&dev_attr_pcie0_errors.attr,
&dev_attr_pcie1_errors.attr,
&dev_attr_nonfatal_errors.attr,
&dev_attr_catfatal_errors.attr,
&dev_attr_inject_errors.attr,
&dev_attr_fme_errors.attr,
&dev_attr_first_error.attr,
&dev_attr_next_error.attr,
NULL,
};
static umode_t fme_global_err_attrs_visible(struct kobject *kobj,
struct attribute *attr, int n)
{
struct device *dev = kobj_to_dev(kobj);
/*
* sysfs entries are visible only if related private feature is
* enumerated.
*/
if (!dfl_get_feature_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR))
return 0;
return attr->mode;
}
const struct attribute_group fme_global_err_group = {
.name = "errors",
.attrs = fme_global_err_attrs,
.is_visible = fme_global_err_attrs_visible,
};
static void fme_err_mask(struct device *dev, bool mask)
{
struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
void __iomem *base;
base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
mutex_lock(&pdata->lock);
/* Workaround: keep MBP_ERROR always masked if revision is 0 */
if (dfl_feature_revision(base))
writeq(mask ? ERROR_MASK : 0, base + FME_ERROR_MASK);
else
writeq(mask ? ERROR_MASK : MBP_ERROR, base + FME_ERROR_MASK);
writeq(mask ? ERROR_MASK : 0, base + PCIE0_ERROR_MASK);
writeq(mask ? ERROR_MASK : 0, base + PCIE1_ERROR_MASK);
writeq(mask ? ERROR_MASK : 0, base + RAS_NONFAT_ERROR_MASK);
writeq(mask ? ERROR_MASK : 0, base + RAS_CATFAT_ERROR_MASK);
mutex_unlock(&pdata->lock);
}
static int fme_global_err_init(struct platform_device *pdev,
struct dfl_feature *feature)
{
fme_err_mask(&pdev->dev, false);
return 0;
}
static void fme_global_err_uinit(struct platform_device *pdev,
struct dfl_feature *feature)
{
fme_err_mask(&pdev->dev, true);
}
const struct dfl_feature_id fme_global_err_id_table[] = {
{.id = FME_FEATURE_ID_GLOBAL_ERR,},
{0,}
};
const struct dfl_feature_ops fme_global_err_ops = {
.init = fme_global_err_init,
.uinit = fme_global_err_uinit,
};
......@@ -16,6 +16,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/uaccess.h>
#include <linux/fpga-dfl.h>
#include "dfl.h"
......@@ -72,50 +73,126 @@ static ssize_t bitstream_metadata_show(struct device *dev,
}
static DEVICE_ATTR_RO(bitstream_metadata);
static const struct attribute *fme_hdr_attrs[] = {
static ssize_t cache_size_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
void __iomem *base;
u64 v;
base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER);
v = readq(base + FME_HDR_CAP);
return sprintf(buf, "%u\n",
(unsigned int)FIELD_GET(FME_CAP_CACHE_SIZE, v));
}
static DEVICE_ATTR_RO(cache_size);
static ssize_t fabric_version_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
void __iomem *base;
u64 v;
base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER);
v = readq(base + FME_HDR_CAP);
return sprintf(buf, "%u\n",
(unsigned int)FIELD_GET(FME_CAP_FABRIC_VERID, v));
}
static DEVICE_ATTR_RO(fabric_version);
static ssize_t socket_id_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
void __iomem *base;
u64 v;
base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER);
v = readq(base + FME_HDR_CAP);
return sprintf(buf, "%u\n",
(unsigned int)FIELD_GET(FME_CAP_SOCKET_ID, v));
}
static DEVICE_ATTR_RO(socket_id);
static struct attribute *fme_hdr_attrs[] = {
&dev_attr_ports_num.attr,
&dev_attr_bitstream_id.attr,
&dev_attr_bitstream_metadata.attr,
&dev_attr_cache_size.attr,
&dev_attr_fabric_version.attr,
&dev_attr_socket_id.attr,
NULL,
};
static int fme_hdr_init(struct platform_device *pdev,
struct dfl_feature *feature)
static const struct attribute_group fme_hdr_group = {
.attrs = fme_hdr_attrs,
};
static long fme_hdr_ioctl_release_port(struct dfl_feature_platform_data *pdata,
unsigned long arg)
{
void __iomem *base = feature->ioaddr;
int ret;
struct dfl_fpga_cdev *cdev = pdata->dfl_cdev;
int port_id;
dev_dbg(&pdev->dev, "FME HDR Init.\n");
dev_dbg(&pdev->dev, "FME cap %llx.\n",
(unsigned long long)readq(base + FME_HDR_CAP));
if (get_user(port_id, (int __user *)arg))
return -EFAULT;
ret = sysfs_create_files(&pdev->dev.kobj, fme_hdr_attrs);
if (ret)
return ret;
return dfl_fpga_cdev_release_port(cdev, port_id);
}
return 0;
static long fme_hdr_ioctl_assign_port(struct dfl_feature_platform_data *pdata,
unsigned long arg)
{
struct dfl_fpga_cdev *cdev = pdata->dfl_cdev;
int port_id;
if (get_user(port_id, (int __user *)arg))
return -EFAULT;
return dfl_fpga_cdev_assign_port(cdev, port_id);
}
static void fme_hdr_uinit(struct platform_device *pdev,
struct dfl_feature *feature)
static long fme_hdr_ioctl(struct platform_device *pdev,
struct dfl_feature *feature,
unsigned int cmd, unsigned long arg)
{
dev_dbg(&pdev->dev, "FME HDR UInit.\n");
sysfs_remove_files(&pdev->dev.kobj, fme_hdr_attrs);
struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
switch (cmd) {
case DFL_FPGA_FME_PORT_RELEASE:
return fme_hdr_ioctl_release_port(pdata, arg);
case DFL_FPGA_FME_PORT_ASSIGN:
return fme_hdr_ioctl_assign_port(pdata, arg);
}
return -ENODEV;
}
static const struct dfl_feature_id fme_hdr_id_table[] = {
{.id = FME_FEATURE_ID_HEADER,},
{0,}
};
static const struct dfl_feature_ops fme_hdr_ops = {
.init = fme_hdr_init,
.uinit = fme_hdr_uinit,
.ioctl = fme_hdr_ioctl,
};
static struct dfl_feature_driver fme_feature_drvs[] = {
{
.id = FME_FEATURE_ID_HEADER,
.id_table = fme_hdr_id_table,
.ops = &fme_hdr_ops,
},
{
.id = FME_FEATURE_ID_PR_MGMT,
.ops = &pr_mgmt_ops,
.id_table = fme_pr_mgmt_id_table,
.ops = &fme_pr_mgmt_ops,
},
{
.id_table = fme_global_err_id_table,
.ops = &fme_global_err_ops,
},
{
.ops = NULL,
......@@ -263,9 +340,16 @@ static int fme_remove(struct platform_device *pdev)
return 0;
}
static const struct attribute_group *fme_dev_groups[] = {
&fme_hdr_group,
&fme_global_err_group,
NULL
};
static struct platform_driver fme_driver = {
.driver = {
.name = DFL_FPGA_FEATURE_DEV_FME,
.name = DFL_FPGA_FEATURE_DEV_FME,
.dev_groups = fme_dev_groups,
},
.probe = fme_probe,
.remove = fme_remove,
......
......@@ -470,7 +470,12 @@ static long fme_pr_ioctl(struct platform_device *pdev,
return ret;
}
const struct dfl_feature_ops pr_mgmt_ops = {
const struct dfl_feature_id fme_pr_mgmt_id_table[] = {
{.id = FME_FEATURE_ID_PR_MGMT,},
{0}
};
const struct dfl_feature_ops fme_pr_mgmt_ops = {
.init = pr_mgmt_init,
.uinit = pr_mgmt_uinit,
.ioctl = fme_pr_ioctl,
......
......@@ -33,6 +33,10 @@ struct dfl_fme {
struct dfl_feature_platform_data *pdata;
};
extern const struct dfl_feature_ops pr_mgmt_ops;
extern const struct dfl_feature_ops fme_pr_mgmt_ops;
extern const struct dfl_feature_id fme_pr_mgmt_id_table[];
extern const struct dfl_feature_ops fme_global_err_ops;
extern const struct dfl_feature_id fme_global_err_id_table[];
extern const struct attribute_group fme_global_err_group;
#endif /* __DFL_FME_H */
......@@ -223,8 +223,43 @@ int cci_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *pcidevid)
return ret;
}
static int cci_pci_sriov_configure(struct pci_dev *pcidev, int num_vfs)
{
struct cci_drvdata *drvdata = pci_get_drvdata(pcidev);
struct dfl_fpga_cdev *cdev = drvdata->cdev;
int ret = 0;
if (!num_vfs) {
/*
* disable SRIOV and then put released ports back to default
* PF access mode.
*/
pci_disable_sriov(pcidev);
dfl_fpga_cdev_config_ports_pf(cdev);
} else {
/*
* before enable SRIOV, put released ports into VF access mode
* first of all.
*/
ret = dfl_fpga_cdev_config_ports_vf(cdev, num_vfs);
if (ret)
return ret;
ret = pci_enable_sriov(pcidev, num_vfs);
if (ret)
dfl_fpga_cdev_config_ports_pf(cdev);
}
return ret;
}
static void cci_pci_remove(struct pci_dev *pcidev)
{
if (dev_is_pf(&pcidev->dev))
cci_pci_sriov_configure(pcidev, 0);
cci_remove_feature_devs(pcidev);
pci_disable_pcie_error_reporting(pcidev);
}
......@@ -234,6 +269,7 @@ static struct pci_driver cci_pci_driver = {
.id_table = cci_pcie_id_tbl,
.probe = cci_pci_probe,
.remove = cci_pci_remove,
.sriov_configure = cci_pci_sriov_configure,
};
module_pci_driver(cci_pci_driver);
......
......@@ -231,16 +231,20 @@ EXPORT_SYMBOL_GPL(dfl_fpga_port_ops_del);
*/
int dfl_fpga_check_port_id(struct platform_device *pdev, void *pport_id)
{
struct dfl_fpga_port_ops *port_ops = dfl_fpga_port_ops_get(pdev);
int port_id;
struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct dfl_fpga_port_ops *port_ops;
if (pdata->id != FEATURE_DEV_ID_UNUSED)
return pdata->id == *(int *)pport_id;
port_ops = dfl_fpga_port_ops_get(pdev);
if (!port_ops || !port_ops->get_id)
return 0;
port_id = port_ops->get_id(pdev);
pdata->id = port_ops->get_id(pdev);
dfl_fpga_port_ops_put(port_ops);
return port_id == *(int *)pport_id;
return pdata->id == *(int *)pport_id;
}
EXPORT_SYMBOL_GPL(dfl_fpga_check_port_id);
......@@ -255,7 +259,8 @@ void dfl_fpga_dev_feature_uinit(struct platform_device *pdev)
dfl_fpga_dev_for_each_feature(pdata, feature)
if (feature->ops) {
feature->ops->uinit(pdev, feature);
if (feature->ops->uinit)
feature->ops->uinit(pdev, feature);
feature->ops = NULL;
}
}
......@@ -266,17 +271,34 @@ static int dfl_feature_instance_init(struct platform_device *pdev,
struct dfl_feature *feature,
struct dfl_feature_driver *drv)
{
int ret;
int ret = 0;
ret = drv->ops->init(pdev, feature);
if (ret)
return ret;
if (drv->ops->init) {
ret = drv->ops->init(pdev, feature);
if (ret)
return ret;
}
feature->ops = drv->ops;
return ret;
}
static bool dfl_feature_drv_match(struct dfl_feature *feature,
struct dfl_feature_driver *driver)
{
const struct dfl_feature_id *ids = driver->id_table;
if (ids) {
while (ids->id) {
if (ids->id == feature->id)
return true;
ids++;
}
}
return false;
}
/**
* dfl_fpga_dev_feature_init - init for sub features of dfl feature device
* @pdev: feature device.
......@@ -297,8 +319,7 @@ int dfl_fpga_dev_feature_init(struct platform_device *pdev,
while (drv->ops) {
dfl_fpga_dev_for_each_feature(pdata, feature) {
/* match feature and drv using id */
if (feature->id == drv->id) {
if (dfl_feature_drv_match(feature, drv)) {
ret = dfl_feature_instance_init(pdev, pdata,
feature, drv);
if (ret)
......@@ -474,6 +495,7 @@ static int build_info_commit_dev(struct build_feature_devs_info *binfo)
pdata->dev = fdev;
pdata->num = binfo->feature_num;
pdata->dfl_cdev = binfo->cdev;
pdata->id = FEATURE_DEV_ID_UNUSED;
mutex_init(&pdata->lock);
lockdep_set_class_and_name(&pdata->lock, &dfl_pdata_keys[type],
dfl_pdata_key_strings[type]);
......@@ -973,25 +995,27 @@ void dfl_fpga_feature_devs_remove(struct dfl_fpga_cdev *cdev)
{
struct dfl_feature_platform_data *pdata, *ptmp;
remove_feature_devs(cdev);
mutex_lock(&cdev->lock);
if (cdev->fme_dev) {
/* the fme should be unregistered. */
WARN_ON(device_is_registered(cdev->fme_dev));
if (cdev->fme_dev)
put_device(cdev->fme_dev);
}
list_for_each_entry_safe(pdata, ptmp, &cdev->port_dev_list, node) {
struct platform_device *port_dev = pdata->dev;
/* the port should be unregistered. */
WARN_ON(device_is_registered(&port_dev->dev));
/* remove released ports */
if (!device_is_registered(&port_dev->dev)) {
dfl_id_free(feature_dev_id_type(port_dev),
port_dev->id);
platform_device_put(port_dev);
}
list_del(&pdata->node);
put_device(&port_dev->dev);
}
mutex_unlock(&cdev->lock);
remove_feature_devs(cdev);
fpga_region_unregister(cdev->region);
devm_kfree(cdev->parent, cdev);
}
......@@ -1042,6 +1066,170 @@ static int __init dfl_fpga_init(void)
return ret;
}
/**
* dfl_fpga_cdev_release_port - release a port platform device
*
* @cdev: parent container device.
* @port_id: id of the port platform device.
*
* This function allows user to release a port platform device. This is a
* mandatory step before turn a port from PF into VF for SRIOV support.
*
* Return: 0 on success, negative error code otherwise.
*/
int dfl_fpga_cdev_release_port(struct dfl_fpga_cdev *cdev, int port_id)
{
struct platform_device *port_pdev;
int ret = -ENODEV;
mutex_lock(&cdev->lock);
port_pdev = __dfl_fpga_cdev_find_port(cdev, &port_id,
dfl_fpga_check_port_id);
if (!port_pdev)
goto unlock_exit;
if (!device_is_registered(&port_pdev->dev)) {
ret = -EBUSY;
goto put_dev_exit;
}
ret = dfl_feature_dev_use_begin(dev_get_platdata(&port_pdev->dev));
if (ret)
goto put_dev_exit;
platform_device_del(port_pdev);
cdev->released_port_num++;
put_dev_exit:
put_device(&port_pdev->dev);
unlock_exit:
mutex_unlock(&cdev->lock);
return ret;
}
EXPORT_SYMBOL_GPL(dfl_fpga_cdev_release_port);
/**
* dfl_fpga_cdev_assign_port - assign a port platform device back
*
* @cdev: parent container device.
* @port_id: id of the port platform device.
*
* This function allows user to assign a port platform device back. This is
* a mandatory step after disable SRIOV support.
*
* Return: 0 on success, negative error code otherwise.
*/
int dfl_fpga_cdev_assign_port(struct dfl_fpga_cdev *cdev, int port_id)
{
struct platform_device *port_pdev;
int ret = -ENODEV;
mutex_lock(&cdev->lock);
port_pdev = __dfl_fpga_cdev_find_port(cdev, &port_id,
dfl_fpga_check_port_id);
if (!port_pdev)
goto unlock_exit;
if (device_is_registered(&port_pdev->dev)) {
ret = -EBUSY;
goto put_dev_exit;
}
ret = platform_device_add(port_pdev);
if (ret)
goto put_dev_exit;
dfl_feature_dev_use_end(dev_get_platdata(&port_pdev->dev));
cdev->released_port_num--;
put_dev_exit:
put_device(&port_pdev->dev);
unlock_exit:
mutex_unlock(&cdev->lock);
return ret;
}
EXPORT_SYMBOL_GPL(dfl_fpga_cdev_assign_port);
static void config_port_access_mode(struct device *fme_dev, int port_id,
bool is_vf)
{
void __iomem *base;
u64 v;
base = dfl_get_feature_ioaddr_by_id(fme_dev, FME_FEATURE_ID_HEADER);
v = readq(base + FME_HDR_PORT_OFST(port_id));
v &= ~FME_PORT_OFST_ACC_CTRL;
v |= FIELD_PREP(FME_PORT_OFST_ACC_CTRL,
is_vf ? FME_PORT_OFST_ACC_VF : FME_PORT_OFST_ACC_PF);
writeq(v, base + FME_HDR_PORT_OFST(port_id));
}
#define config_port_vf_mode(dev, id) config_port_access_mode(dev, id, true)
#define config_port_pf_mode(dev, id) config_port_access_mode(dev, id, false)
/**
* dfl_fpga_cdev_config_ports_pf - configure ports to PF access mode
*
* @cdev: parent container device.
*
* This function is needed in sriov configuration routine. It could be used to
* configure the all released ports from VF access mode to PF.
*/
void dfl_fpga_cdev_config_ports_pf(struct dfl_fpga_cdev *cdev)
{
struct dfl_feature_platform_data *pdata;
mutex_lock(&cdev->lock);
list_for_each_entry(pdata, &cdev->port_dev_list, node) {
if (device_is_registered(&pdata->dev->dev))
continue;
config_port_pf_mode(cdev->fme_dev, pdata->id);
}
mutex_unlock(&cdev->lock);
}
EXPORT_SYMBOL_GPL(dfl_fpga_cdev_config_ports_pf);
/**
* dfl_fpga_cdev_config_ports_vf - configure ports to VF access mode
*
* @cdev: parent container device.
* @num_vfs: VF device number.
*
* This function is needed in sriov configuration routine. It could be used to
* configure the released ports from PF access mode to VF.
*
* Return: 0 on success, negative error code otherwise.
*/
int dfl_fpga_cdev_config_ports_vf(struct dfl_fpga_cdev *cdev, int num_vfs)
{
struct dfl_feature_platform_data *pdata;
int ret = 0;
mutex_lock(&cdev->lock);
/*
* can't turn multiple ports into 1 VF device, only 1 port for 1 VF
* device, so if released port number doesn't match VF device number,
* then reject the request with -EINVAL error code.
*/
if (cdev->released_port_num != num_vfs) {
ret = -EINVAL;
goto done;
}
list_for_each_entry(pdata, &cdev->port_dev_list, node) {
if (device_is_registered(&pdata->dev->dev))
continue;
config_port_vf_mode(cdev->fme_dev, pdata->id);
}
done:
mutex_unlock(&cdev->lock);
return ret;
}
EXPORT_SYMBOL_GPL(dfl_fpga_cdev_config_ports_vf);
static void __exit dfl_fpga_exit(void)
{
dfl_chardev_uinit();
......
......@@ -30,8 +30,8 @@
/* plus one for fme device */
#define MAX_DFL_FEATURE_DEV_NUM (MAX_DFL_FPGA_PORT_NUM + 1)
/* Reserved 0x0 for Header Group Register and 0xff for AFU */
#define FEATURE_ID_FIU_HEADER 0x0
/* Reserved 0xfe for Header Group Register and 0xff for AFU */
#define FEATURE_ID_FIU_HEADER 0xfe
#define FEATURE_ID_AFU 0xff
#define FME_FEATURE_ID_HEADER FEATURE_ID_FIU_HEADER
......@@ -119,6 +119,11 @@
#define PORT_HDR_NEXT_AFU NEXT_AFU
#define PORT_HDR_CAP 0x30
#define PORT_HDR_CTRL 0x38
#define PORT_HDR_STS 0x40
#define PORT_HDR_USRCLK_CMD0 0x50
#define PORT_HDR_USRCLK_CMD1 0x58
#define PORT_HDR_USRCLK_STS0 0x60
#define PORT_HDR_USRCLK_STS1 0x68
/* Port Capability Register Bitfield */
#define PORT_CAP_PORT_NUM GENMASK_ULL(1, 0) /* ID of this port */
......@@ -130,6 +135,16 @@
/* Latency tolerance reporting. '1' >= 40us, '0' < 40us.*/
#define PORT_CTRL_LATENCY BIT_ULL(2)
#define PORT_CTRL_SFTRST_ACK BIT_ULL(4) /* HW ack for reset */
/* Port Status Register Bitfield */
#define PORT_STS_AP2_EVT BIT_ULL(13) /* AP2 event detected */
#define PORT_STS_AP1_EVT BIT_ULL(12) /* AP1 event detected */
#define PORT_STS_PWR_STATE GENMASK_ULL(11, 8) /* AFU power states */
#define PORT_STS_PWR_STATE_NORM 0
#define PORT_STS_PWR_STATE_AP1 1 /* 50% throttling */
#define PORT_STS_PWR_STATE_AP2 2 /* 90% throttling */
#define PORT_STS_PWR_STATE_AP6 6 /* 100% throttling */
/**
* struct dfl_fpga_port_ops - port ops
*
......@@ -154,13 +169,22 @@ void dfl_fpga_port_ops_put(struct dfl_fpga_port_ops *ops);
int dfl_fpga_check_port_id(struct platform_device *pdev, void *pport_id);
/**
* struct dfl_feature_driver - sub feature's driver
* struct dfl_feature_id - dfl private feature id
*
* @id: sub feature id.
* @ops: ops of this sub feature.
* @id: unique dfl private feature id.
*/
struct dfl_feature_driver {
struct dfl_feature_id {
u64 id;
};
/**
* struct dfl_feature_driver - dfl private feature driver
*
* @id_table: id_table for dfl private features supported by this driver.
* @ops: ops of this dfl private feature driver.
*/
struct dfl_feature_driver {
const struct dfl_feature_id *id_table;
const struct dfl_feature_ops *ops;
};
......@@ -183,6 +207,8 @@ struct dfl_feature {
#define DEV_STATUS_IN_USE 0
#define FEATURE_DEV_ID_UNUSED (-1)
/**
* struct dfl_feature_platform_data - platform data for feature devices
*
......@@ -191,6 +217,7 @@ struct dfl_feature {
* @cdev: cdev of feature dev.
* @dev: ptr to platform device linked with this platform data.
* @dfl_cdev: ptr to container device.
* @id: id used for this feature device.
* @disable_count: count for port disable.
* @num: number for sub features.
* @dev_status: dev status (e.g. DEV_STATUS_IN_USE).
......@@ -203,6 +230,7 @@ struct dfl_feature_platform_data {
struct cdev cdev;
struct platform_device *dev;
struct dfl_fpga_cdev *dfl_cdev;
int id;
unsigned int disable_count;
unsigned long dev_status;
void *private;
......@@ -331,6 +359,11 @@ static inline bool dfl_feature_is_port(void __iomem *base)
(FIELD_GET(DFH_ID, v) == DFH_ID_FIU_PORT);
}
static inline u8 dfl_feature_revision(void __iomem *base)
{
return (u8)FIELD_GET(DFH_REVISION, readq(base + DFH));
}
/**
* struct dfl_fpga_enum_info - DFL FPGA enumeration information
*
......@@ -373,6 +406,7 @@ void dfl_fpga_enum_info_free(struct dfl_fpga_enum_info *info);
* @fme_dev: FME feature device under this container device.
* @lock: mutex lock to protect the port device list.
* @port_dev_list: list of all port feature devices under this container device.
* @released_port_num: released port number under this container device.
*/
struct dfl_fpga_cdev {
struct device *parent;
......@@ -380,6 +414,7 @@ struct dfl_fpga_cdev {
struct device *fme_dev;
struct mutex lock;
struct list_head port_dev_list;
int released_port_num;
};
struct dfl_fpga_cdev *
......@@ -407,4 +442,9 @@ dfl_fpga_cdev_find_port(struct dfl_fpga_cdev *cdev, void *data,
return pdev;
}
int dfl_fpga_cdev_release_port(struct dfl_fpga_cdev *cdev, int port_id);
int dfl_fpga_cdev_assign_port(struct dfl_fpga_cdev *cdev, int port_id);
void dfl_fpga_cdev_config_ports_pf(struct dfl_fpga_cdev *cdev);
int dfl_fpga_cdev_config_ports_vf(struct dfl_fpga_cdev *cdev, int num_vf);
#endif /* __FPGA_DFL_H */
......@@ -646,24 +646,23 @@ static int debug_remove(struct amba_device *adev)
return 0;
}
static const struct amba_cs_uci_id uci_id_debug[] = {
{
/* CPU Debug UCI data */
.devarch = 0x47706a15,
.devarch_mask = 0xfff0ffff,
.devtype = 0x00000015,
}
};
static const struct amba_id debug_ids[] = {
{ /* Debug for Cortex-A53 */
.id = 0x000bbd03,
.mask = 0x000fffff,
},
{ /* Debug for Cortex-A57 */
.id = 0x000bbd07,
.mask = 0x000fffff,
},
{ /* Debug for Cortex-A72 */
.id = 0x000bbd08,
.mask = 0x000fffff,
},
{ /* Debug for Cortex-A73 */
.id = 0x000bbd09,
.mask = 0x000fffff,
},
{ 0, 0 },
CS_AMBA_ID(0x000bbd03), /* Cortex-A53 */
CS_AMBA_ID(0x000bbd07), /* Cortex-A57 */
CS_AMBA_ID(0x000bbd08), /* Cortex-A72 */
CS_AMBA_ID(0x000bbd09), /* Cortex-A73 */
CS_AMBA_UCI_ID(0x000f0205, uci_id_debug), /* Qualcomm Kryo */
CS_AMBA_UCI_ID(0x000f0211, uci_id_debug), /* Qualcomm Kryo */
{},
};
static struct amba_driver debug_driver = {
......
......@@ -296,11 +296,8 @@ static ssize_t mode_store(struct device *dev,
spin_lock(&drvdata->spinlock);
config->mode = val & ETMv4_MODE_ALL;
if (config->mode & ETM_MODE_EXCLUDE)
etm4_set_mode_exclude(drvdata, true);
else
etm4_set_mode_exclude(drvdata, false);
etm4_set_mode_exclude(drvdata,
config->mode & ETM_MODE_EXCLUDE ? true : false);
if (drvdata->instrp0 == true) {
/* start by clearing instruction P0 field */
......@@ -999,10 +996,8 @@ static ssize_t addr_range_store(struct device *dev,
* Program include or exclude control bits for vinst or vdata
* whenever we change addr comparators to ETM_ADDR_TYPE_RANGE
*/
if (config->mode & ETM_MODE_EXCLUDE)
etm4_set_mode_exclude(drvdata, true);
else
etm4_set_mode_exclude(drvdata, false);
etm4_set_mode_exclude(drvdata,
config->mode & ETM_MODE_EXCLUDE ? true : false);
spin_unlock(&drvdata->spinlock);
return size;
......
......@@ -5,6 +5,7 @@
* Description: CoreSight Funnel driver
*/
#include <linux/acpi.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/types.h>
......@@ -192,7 +193,7 @@ static int funnel_probe(struct device *dev, struct resource *res)
if (is_of_node(dev_fwnode(dev)) &&
of_device_is_compatible(dev->of_node, "arm,coresight-funnel"))
pr_warn_once("Uses OBSOLETE CoreSight funnel binding\n");
dev_warn_once(dev, "Uses OBSOLETE CoreSight funnel binding\n");
desc.name = coresight_alloc_device_name(&funnel_devs, dev);
if (!desc.name)
......@@ -302,11 +303,19 @@ static const struct of_device_id static_funnel_match[] = {
{}
};
#ifdef CONFIG_ACPI
static const struct acpi_device_id static_funnel_ids[] = {
{"ARMHC9FE", 0},
{},
};
#endif
static struct platform_driver static_funnel_driver = {
.probe = static_funnel_probe,
.driver = {
.name = "coresight-static-funnel",
.of_match_table = static_funnel_match,
.acpi_match_table = ACPI_PTR(static_funnel_ids),
.pm = &funnel_dev_pm_ops,
.suppress_bind_attrs = true,
},
......
......@@ -185,11 +185,11 @@ static inline int etm_writel_cp14(u32 off, u32 val) { return 0; }
}
/* coresight AMBA ID, full UCI structure: id table entry. */
#define CS_AMBA_UCI_ID(pid, uci_ptr) \
{ \
.id = pid, \
.mask = 0x000fffff, \
.data = uci_ptr \
#define CS_AMBA_UCI_ID(pid, uci_ptr) \
{ \
.id = pid, \
.mask = 0x000fffff, \
.data = (void *)uci_ptr \
}
/* extract the data value from a UCI structure given amba_id pointer. */
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment