diff options
335 files changed, 10559 insertions, 2044 deletions
diff --git a/.get_maintainer.ignore b/.get_maintainer.ignore index cca6d870f7a5..a64d21913745 100644 --- a/.get_maintainer.ignore +++ b/.get_maintainer.ignore | |||
| @@ -1 +1,2 @@ | |||
| 1 | Christoph Hellwig <hch@lst.de> | 1 | Christoph Hellwig <hch@lst.de> |
| 2 | Marc Gonzalez <marc.w.gonzalez@free.fr> | ||
diff --git a/.gitignore b/.gitignore index d263ca9a276c..7587ef56b92d 100644 --- a/.gitignore +++ b/.gitignore | |||
| @@ -81,12 +81,14 @@ modules.builtin | |||
| 81 | /tar-install/ | 81 | /tar-install/ |
| 82 | 82 | ||
| 83 | # | 83 | # |
| 84 | # git files that we don't want to ignore even if they are dot-files | 84 | # We don't want to ignore the following even if they are dot-files |
| 85 | # | 85 | # |
| 86 | !.clang-format | ||
| 87 | !.cocciconfig | ||
| 88 | !.get_maintainer.ignore | ||
| 89 | !.gitattributes | ||
| 86 | !.gitignore | 90 | !.gitignore |
| 87 | !.mailmap | 91 | !.mailmap |
| 88 | !.cocciconfig | ||
| 89 | !.clang-format | ||
| 90 | 92 | ||
| 91 | # | 93 | # |
| 92 | # Generated include files | 94 | # Generated include files |
diff --git a/Documentation/devicetree/bindings/arm/atmel-at91.txt b/Documentation/devicetree/bindings/arm/atmel-at91.txt index 4bf1b4da7659..99dee23c74a4 100644 --- a/Documentation/devicetree/bindings/arm/atmel-at91.txt +++ b/Documentation/devicetree/bindings/arm/atmel-at91.txt | |||
| @@ -25,6 +25,7 @@ compatible: must be one of: | |||
| 25 | o "atmel,at91sam9n12" | 25 | o "atmel,at91sam9n12" |
| 26 | o "atmel,at91sam9rl" | 26 | o "atmel,at91sam9rl" |
| 27 | o "atmel,at91sam9xe" | 27 | o "atmel,at91sam9xe" |
| 28 | o "microchip,sam9x60" | ||
| 28 | * "atmel,sama5" for SoCs using a Cortex-A5, shall be extended with the specific | 29 | * "atmel,sama5" for SoCs using a Cortex-A5, shall be extended with the specific |
| 29 | SoC family: | 30 | SoC family: |
| 30 | o "atmel,sama5d2" shall be extended with the specific SoC compatible: | 31 | o "atmel,sama5d2" shall be extended with the specific SoC compatible: |
diff --git a/Documentation/devicetree/bindings/arm/keystone/ti,sci.txt b/Documentation/devicetree/bindings/arm/keystone/ti,sci.txt index b56a02c10ae6..6f0cd31c1520 100644 --- a/Documentation/devicetree/bindings/arm/keystone/ti,sci.txt +++ b/Documentation/devicetree/bindings/arm/keystone/ti,sci.txt | |||
| @@ -24,7 +24,8 @@ relationship between the TI-SCI parent node to the child node. | |||
| 24 | 24 | ||
| 25 | Required properties: | 25 | Required properties: |
| 26 | ------------------- | 26 | ------------------- |
| 27 | - compatible: should be "ti,k2g-sci" | 27 | - compatible: should be "ti,k2g-sci" for TI 66AK2G SoC |
| 28 | should be "ti,am654-sci" for for TI AM654 SoC | ||
| 28 | - mbox-names: | 29 | - mbox-names: |
| 29 | "rx" - Mailbox corresponding to receive path | 30 | "rx" - Mailbox corresponding to receive path |
| 30 | "tx" - Mailbox corresponding to transmit path | 31 | "tx" - Mailbox corresponding to transmit path |
diff --git a/Documentation/devicetree/bindings/interrupt-controller/ti,sci-inta.txt b/Documentation/devicetree/bindings/interrupt-controller/ti,sci-inta.txt new file mode 100644 index 000000000000..7841cb099e13 --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/ti,sci-inta.txt | |||
| @@ -0,0 +1,66 @@ | |||
| 1 | Texas Instruments K3 Interrupt Aggregator | ||
| 2 | ========================================= | ||
| 3 | |||
| 4 | The Interrupt Aggregator (INTA) provides a centralized machine | ||
| 5 | which handles the termination of system events to that they can | ||
| 6 | be coherently processed by the host(s) in the system. A maximum | ||
| 7 | of 64 events can be mapped to a single interrupt. | ||
| 8 | |||
| 9 | |||
| 10 | Interrupt Aggregator | ||
| 11 | +-----------------------------------------+ | ||
| 12 | | Intmap VINT | | ||
| 13 | | +--------------+ +------------+ | | ||
| 14 | m ------>| | vint | bit | | 0 |.....|63| vint0 | | ||
| 15 | . | +--------------+ +------------+ | +------+ | ||
| 16 | . | . . | | HOST | | ||
| 17 | Globalevents ------>| . . |------>| IRQ | | ||
| 18 | . | . . | | CTRL | | ||
| 19 | . | . . | +------+ | ||
| 20 | n ------>| +--------------+ +------------+ | | ||
| 21 | | | vint | bit | | 0 |.....|63| vintx | | ||
| 22 | | +--------------+ +------------+ | | ||
| 23 | | | | ||
| 24 | +-----------------------------------------+ | ||
| 25 | |||
| 26 | Configuration of these Intmap registers that maps global events to vint is done | ||
| 27 | by a system controller (like the Device Memory and Security Controller on K3 | ||
| 28 | AM654 SoC). Driver should request the system controller to get the range | ||
| 29 | of global events and vints assigned to the requesting host. Management | ||
| 30 | of these requested resources should be handled by driver and requests | ||
| 31 | system controller to map specific global event to vint, bit pair. | ||
| 32 | |||
| 33 | Communication between the host processor running an OS and the system | ||
| 34 | controller happens through a protocol called TI System Control Interface | ||
| 35 | (TISCI protocol). For more details refer: | ||
| 36 | Documentation/devicetree/bindings/arm/keystone/ti,sci.txt | ||
| 37 | |||
| 38 | TISCI Interrupt Aggregator Node: | ||
| 39 | ------------------------------- | ||
| 40 | - compatible: Must be "ti,sci-inta". | ||
| 41 | - reg: Should contain registers location and length. | ||
| 42 | - interrupt-controller: Identifies the node as an interrupt controller | ||
| 43 | - msi-controller: Identifies the node as an MSI controller. | ||
| 44 | - interrupt-parent: phandle of irq parent. | ||
| 45 | - ti,sci: Phandle to TI-SCI compatible System controller node. | ||
| 46 | - ti,sci-dev-id: TISCI device ID of the Interrupt Aggregator. | ||
| 47 | - ti,sci-rm-range-vint: Array of TISCI subtype ids representing vints(inta | ||
| 48 | outputs) range within this INTA, assigned to the | ||
| 49 | requesting host context. | ||
| 50 | - ti,sci-rm-range-global-event: Array of TISCI subtype ids representing the | ||
| 51 | global events range reaching this IA and are assigned | ||
| 52 | to the requesting host context. | ||
| 53 | |||
| 54 | Example: | ||
| 55 | -------- | ||
| 56 | main_udmass_inta: interrupt-controller@33d00000 { | ||
| 57 | compatible = "ti,sci-inta"; | ||
| 58 | reg = <0x0 0x33d00000 0x0 0x100000>; | ||
| 59 | interrupt-controller; | ||
| 60 | msi-controller; | ||
| 61 | interrupt-parent = <&main_navss_intr>; | ||
| 62 | ti,sci = <&dmsc>; | ||
| 63 | ti,sci-dev-id = <179>; | ||
| 64 | ti,sci-rm-range-vint = <0x0>; | ||
| 65 | ti,sci-rm-range-global-event = <0x1>; | ||
| 66 | }; | ||
diff --git a/Documentation/devicetree/bindings/interrupt-controller/ti,sci-intr.txt b/Documentation/devicetree/bindings/interrupt-controller/ti,sci-intr.txt new file mode 100644 index 000000000000..1a8718f8855d --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/ti,sci-intr.txt | |||
| @@ -0,0 +1,82 @@ | |||
| 1 | Texas Instruments K3 Interrupt Router | ||
| 2 | ===================================== | ||
| 3 | |||
| 4 | The Interrupt Router (INTR) module provides a mechanism to mux M | ||
| 5 | interrupt inputs to N interrupt outputs, where all M inputs are selectable | ||
| 6 | to be driven per N output. An Interrupt Router can either handle edge triggered | ||
| 7 | or level triggered interrupts and that is fixed in hardware. | ||
| 8 | |||
| 9 | Interrupt Router | ||
| 10 | +----------------------+ | ||
| 11 | | Inputs Outputs | | ||
| 12 | +-------+ | +------+ +-----+ | | ||
| 13 | | GPIO |----------->| | irq0 | | 0 | | Host IRQ | ||
| 14 | +-------+ | +------+ +-----+ | controller | ||
| 15 | | . . | +-------+ | ||
| 16 | +-------+ | . . |----->| IRQ | | ||
| 17 | | INTA |----------->| . . | +-------+ | ||
| 18 | +-------+ | . +-----+ | | ||
| 19 | | +------+ | N | | | ||
| 20 | | | irqM | +-----+ | | ||
| 21 | | +------+ | | ||
| 22 | | | | ||
| 23 | +----------------------+ | ||
| 24 | |||
| 25 | There is one register per output (MUXCNTL_N) that controls the selection. | ||
| 26 | Configuration of these MUXCNTL_N registers is done by a system controller | ||
| 27 | (like the Device Memory and Security Controller on K3 AM654 SoC). System | ||
| 28 | controller will keep track of the used and unused registers within the Router. | ||
| 29 | Driver should request the system controller to get the range of GIC IRQs | ||
| 30 | assigned to the requesting hosts. It is the drivers responsibility to keep | ||
| 31 | track of Host IRQs. | ||
| 32 | |||
| 33 | Communication between the host processor running an OS and the system | ||
| 34 | controller happens through a protocol called TI System Control Interface | ||
| 35 | (TISCI protocol). For more details refer: | ||
| 36 | Documentation/devicetree/bindings/arm/keystone/ti,sci.txt | ||
| 37 | |||
| 38 | TISCI Interrupt Router Node: | ||
| 39 | ---------------------------- | ||
| 40 | Required Properties: | ||
| 41 | - compatible: Must be "ti,sci-intr". | ||
| 42 | - ti,intr-trigger-type: Should be one of the following: | ||
| 43 | 1: If intr supports edge triggered interrupts. | ||
| 44 | 4: If intr supports level triggered interrupts. | ||
| 45 | - interrupt-controller: Identifies the node as an interrupt controller | ||
| 46 | - #interrupt-cells: Specifies the number of cells needed to encode an | ||
| 47 | interrupt source. The value should be 2. | ||
| 48 | First cell should contain the TISCI device ID of source | ||
| 49 | Second cell should contain the interrupt source offset | ||
| 50 | within the device. | ||
| 51 | - ti,sci: Phandle to TI-SCI compatible System controller node. | ||
| 52 | - ti,sci-dst-id: TISCI device ID of the destination IRQ controller. | ||
| 53 | - ti,sci-rm-range-girq: Array of TISCI subtype ids representing the host irqs | ||
| 54 | assigned to this interrupt router. Each subtype id | ||
| 55 | corresponds to a range of host irqs. | ||
| 56 | |||
| 57 | For more details on TISCI IRQ resource management refer: | ||
| 58 | http://downloads.ti.com/tisci/esd/latest/2_tisci_msgs/rm/rm_irq.html | ||
| 59 | |||
| 60 | Example: | ||
| 61 | -------- | ||
| 62 | The following example demonstrates both interrupt router node and the consumer | ||
| 63 | node(main gpio) on the AM654 SoC: | ||
| 64 | |||
| 65 | main_intr: interrupt-controller0 { | ||
| 66 | compatible = "ti,sci-intr"; | ||
| 67 | ti,intr-trigger-type = <1>; | ||
| 68 | interrupt-controller; | ||
| 69 | interrupt-parent = <&gic500>; | ||
| 70 | #interrupt-cells = <2>; | ||
| 71 | ti,sci = <&dmsc>; | ||
| 72 | ti,sci-dst-id = <56>; | ||
| 73 | ti,sci-rm-range-girq = <0x1>; | ||
| 74 | }; | ||
| 75 | |||
| 76 | main_gpio0: gpio@600000 { | ||
| 77 | ... | ||
| 78 | interrupt-parent = <&main_intr>; | ||
| 79 | interrupts = <57 256>, <57 257>, <57 258>, | ||
| 80 | <57 259>, <57 260>, <57 261>; | ||
| 81 | ... | ||
| 82 | }; | ||
diff --git a/Documentation/devicetree/bindings/riscv/sifive-l2-cache.txt b/Documentation/devicetree/bindings/riscv/sifive-l2-cache.txt new file mode 100644 index 000000000000..73d8f19c3bd9 --- /dev/null +++ b/Documentation/devicetree/bindings/riscv/sifive-l2-cache.txt | |||
| @@ -0,0 +1,51 @@ | |||
| 1 | SiFive L2 Cache Controller | ||
| 2 | -------------------------- | ||
| 3 | The SiFive Level 2 Cache Controller is used to provide access to fast copies | ||
| 4 | of memory for masters in a Core Complex. The Level 2 Cache Controller also | ||
| 5 | acts as directory-based coherency manager. | ||
| 6 | All the properties in ePAPR/DeviceTree specification applies for this platform | ||
| 7 | |||
| 8 | Required Properties: | ||
| 9 | -------------------- | ||
| 10 | - compatible: Should be "sifive,fu540-c000-ccache" and "cache" | ||
| 11 | |||
| 12 | - cache-block-size: Specifies the block size in bytes of the cache. | ||
| 13 | Should be 64 | ||
| 14 | |||
| 15 | - cache-level: Should be set to 2 for a level 2 cache | ||
| 16 | |||
| 17 | - cache-sets: Specifies the number of associativity sets of the cache. | ||
| 18 | Should be 1024 | ||
| 19 | |||
| 20 | - cache-size: Specifies the size in bytes of the cache. Should be 2097152 | ||
| 21 | |||
| 22 | - cache-unified: Specifies the cache is a unified cache | ||
| 23 | |||
| 24 | - interrupts: Must contain 3 entries (DirError, DataError and DataFail signals) | ||
| 25 | |||
| 26 | - reg: Physical base address and size of L2 cache controller registers map | ||
| 27 | |||
| 28 | Optional Properties: | ||
| 29 | -------------------- | ||
| 30 | - next-level-cache: phandle to the next level cache if present. | ||
| 31 | |||
| 32 | - memory-region: reference to the reserved-memory for the L2 Loosely Integrated | ||
| 33 | Memory region. The reserved memory node should be defined as per the bindings | ||
| 34 | in reserved-memory.txt | ||
| 35 | |||
| 36 | |||
| 37 | Example: | ||
| 38 | |||
| 39 | cache-controller@2010000 { | ||
| 40 | compatible = "sifive,fu540-c000-ccache", "cache"; | ||
| 41 | cache-block-size = <64>; | ||
| 42 | cache-level = <2>; | ||
| 43 | cache-sets = <1024>; | ||
| 44 | cache-size = <2097152>; | ||
| 45 | cache-unified; | ||
| 46 | interrupt-parent = <&plic0>; | ||
| 47 | interrupts = <1 2 3>; | ||
| 48 | reg = <0x0 0x2010000 0x0 0x1000>; | ||
| 49 | next-level-cache = <&L25 &L40 &L36>; | ||
| 50 | memory-region = <&l2_lim>; | ||
| 51 | }; | ||
diff --git a/Documentation/devicetree/bindings/timer/allwinner,sun4i-timer.txt b/Documentation/devicetree/bindings/timer/allwinner,sun4i-timer.txt index 5c2e23574ca0..3da9d515c03a 100644 --- a/Documentation/devicetree/bindings/timer/allwinner,sun4i-timer.txt +++ b/Documentation/devicetree/bindings/timer/allwinner,sun4i-timer.txt | |||
| @@ -2,7 +2,9 @@ Allwinner A1X SoCs Timer Controller | |||
| 2 | 2 | ||
| 3 | Required properties: | 3 | Required properties: |
| 4 | 4 | ||
| 5 | - compatible : should be "allwinner,sun4i-a10-timer" | 5 | - compatible : should be one of the following: |
| 6 | "allwinner,sun4i-a10-timer" | ||
| 7 | "allwinner,suniv-f1c100s-timer" | ||
| 6 | - reg : Specifies base physical address and size of the registers. | 8 | - reg : Specifies base physical address and size of the registers. |
| 7 | - interrupts : The interrupt of the first timer | 9 | - interrupts : The interrupt of the first timer |
| 8 | - clocks: phandle to the source clock (usually a 24 MHz fixed clock) | 10 | - clocks: phandle to the source clock (usually a 24 MHz fixed clock) |
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt index 99994a461359..69c7fa7f616c 100644 --- a/Documentation/driver-model/devres.txt +++ b/Documentation/driver-model/devres.txt | |||
| @@ -271,6 +271,9 @@ GPIO | |||
| 271 | devm_gpio_request_one() | 271 | devm_gpio_request_one() |
| 272 | devm_gpio_free() | 272 | devm_gpio_free() |
| 273 | 273 | ||
| 274 | I2C | ||
| 275 | devm_i2c_new_dummy_device() | ||
| 276 | |||
| 274 | IIO | 277 | IIO |
| 275 | devm_iio_device_alloc() | 278 | devm_iio_device_alloc() |
| 276 | devm_iio_device_free() | 279 | devm_iio_device_free() |
diff --git a/MAINTAINERS b/MAINTAINERS index 9cc6767e1b12..5cfbea4ce575 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -8542,6 +8542,7 @@ F: scripts/Kbuild* | |||
| 8542 | F: scripts/Makefile* | 8542 | F: scripts/Makefile* |
| 8543 | F: scripts/basic/ | 8543 | F: scripts/basic/ |
| 8544 | F: scripts/mk* | 8544 | F: scripts/mk* |
| 8545 | F: scripts/*vmlinux* | ||
| 8545 | F: scripts/mod/ | 8546 | F: scripts/mod/ |
| 8546 | F: scripts/package/ | 8547 | F: scripts/package/ |
| 8547 | 8548 | ||
| @@ -15547,6 +15548,12 @@ F: Documentation/devicetree/bindings/reset/ti,sci-reset.txt | |||
| 15547 | F: Documentation/devicetree/bindings/clock/ti,sci-clk.txt | 15548 | F: Documentation/devicetree/bindings/clock/ti,sci-clk.txt |
| 15548 | F: drivers/clk/keystone/sci-clk.c | 15549 | F: drivers/clk/keystone/sci-clk.c |
| 15549 | F: drivers/reset/reset-ti-sci.c | 15550 | F: drivers/reset/reset-ti-sci.c |
| 15551 | F: Documentation/devicetree/bindings/interrupt-controller/ti,sci-intr.txt | ||
| 15552 | F: Documentation/devicetree/bindings/interrupt-controller/ti,sci-inta.txt | ||
| 15553 | F: drivers/irqchip/irq-ti-sci-intr.c | ||
| 15554 | F: drivers/irqchip/irq-ti-sci-inta.c | ||
| 15555 | F: include/linux/soc/ti/ti_sci_inta_msi.h | ||
| 15556 | F: drivers/soc/ti/ti_sci_inta_msi.c | ||
| 15550 | 15557 | ||
| 15551 | Texas Instruments ASoC drivers | 15558 | Texas Instruments ASoC drivers |
| 15552 | M: Peter Ujfalusi <peter.ujfalusi@ti.com> | 15559 | M: Peter Ujfalusi <peter.ujfalusi@ti.com> |
| @@ -537,7 +537,7 @@ endif | |||
| 537 | # Some architectures define CROSS_COMPILE in arch/$(SRCARCH)/Makefile. | 537 | # Some architectures define CROSS_COMPILE in arch/$(SRCARCH)/Makefile. |
| 538 | # CC_VERSION_TEXT is referenced from Kconfig (so it needs export), | 538 | # CC_VERSION_TEXT is referenced from Kconfig (so it needs export), |
| 539 | # and from include/config/auto.conf.cmd to detect the compiler upgrade. | 539 | # and from include/config/auto.conf.cmd to detect the compiler upgrade. |
| 540 | CC_VERSION_TEXT = $(shell $(CC) --version | head -n 1) | 540 | CC_VERSION_TEXT = $(shell $(CC) --version 2>/dev/null | head -n 1) |
| 541 | 541 | ||
| 542 | ifeq ($(config-targets),1) | 542 | ifeq ($(config-targets),1) |
| 543 | # =========================================================================== | 543 | # =========================================================================== |
| @@ -651,7 +651,7 @@ ifeq ($(may-sync-config),1) | |||
| 651 | # Read in dependencies to all Kconfig* files, make sure to run syncconfig if | 651 | # Read in dependencies to all Kconfig* files, make sure to run syncconfig if |
| 652 | # changes are detected. This should be included after arch/$(SRCARCH)/Makefile | 652 | # changes are detected. This should be included after arch/$(SRCARCH)/Makefile |
| 653 | # because some architectures define CROSS_COMPILE there. | 653 | # because some architectures define CROSS_COMPILE there. |
| 654 | -include include/config/auto.conf.cmd | 654 | include include/config/auto.conf.cmd |
| 655 | 655 | ||
| 656 | $(KCONFIG_CONFIG): | 656 | $(KCONFIG_CONFIG): |
| 657 | @echo >&2 '***' | 657 | @echo >&2 '***' |
| @@ -692,7 +692,6 @@ KBUILD_CFLAGS += $(call cc-option,-fno-delete-null-pointer-checks,) | |||
| 692 | KBUILD_CFLAGS += $(call cc-disable-warning,frame-address,) | 692 | KBUILD_CFLAGS += $(call cc-disable-warning,frame-address,) |
| 693 | KBUILD_CFLAGS += $(call cc-disable-warning, format-truncation) | 693 | KBUILD_CFLAGS += $(call cc-disable-warning, format-truncation) |
| 694 | KBUILD_CFLAGS += $(call cc-disable-warning, format-overflow) | 694 | KBUILD_CFLAGS += $(call cc-disable-warning, format-overflow) |
| 695 | KBUILD_CFLAGS += $(call cc-disable-warning, int-in-bool-context) | ||
| 696 | KBUILD_CFLAGS += $(call cc-disable-warning, address-of-packed-member) | 695 | KBUILD_CFLAGS += $(call cc-disable-warning, address-of-packed-member) |
| 697 | 696 | ||
| 698 | ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE | 697 | ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE |
| @@ -732,16 +731,15 @@ stackp-flags-$(CONFIG_STACKPROTECTOR_STRONG) := -fstack-protector-strong | |||
| 732 | KBUILD_CFLAGS += $(stackp-flags-y) | 731 | KBUILD_CFLAGS += $(stackp-flags-y) |
| 733 | 732 | ||
| 734 | ifdef CONFIG_CC_IS_CLANG | 733 | ifdef CONFIG_CC_IS_CLANG |
| 735 | KBUILD_CPPFLAGS += $(call cc-option,-Qunused-arguments,) | 734 | KBUILD_CPPFLAGS += -Qunused-arguments |
| 736 | KBUILD_CFLAGS += $(call cc-disable-warning, format-invalid-specifier) | 735 | KBUILD_CFLAGS += -Wno-format-invalid-specifier |
| 737 | KBUILD_CFLAGS += $(call cc-disable-warning, gnu) | 736 | KBUILD_CFLAGS += -Wno-gnu |
| 738 | # Quiet clang warning: comparison of unsigned expression < 0 is always false | 737 | # Quiet clang warning: comparison of unsigned expression < 0 is always false |
| 739 | KBUILD_CFLAGS += $(call cc-disable-warning, tautological-compare) | 738 | KBUILD_CFLAGS += -Wno-tautological-compare |
| 740 | # CLANG uses a _MergedGlobals as optimization, but this breaks modpost, as the | 739 | # CLANG uses a _MergedGlobals as optimization, but this breaks modpost, as the |
| 741 | # source of a reference will be _MergedGlobals and not on of the whitelisted names. | 740 | # source of a reference will be _MergedGlobals and not on of the whitelisted names. |
| 742 | # See modpost pattern 2 | 741 | # See modpost pattern 2 |
| 743 | KBUILD_CFLAGS += $(call cc-option, -mno-global-merge,) | 742 | KBUILD_CFLAGS += -mno-global-merge |
| 744 | KBUILD_CFLAGS += $(call cc-option, -fcatch-undefined-behavior) | ||
| 745 | else | 743 | else |
| 746 | 744 | ||
| 747 | # These warnings generated too much noise in a regular build. | 745 | # These warnings generated too much noise in a regular build. |
| @@ -842,7 +840,7 @@ NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include) | |||
| 842 | KBUILD_CFLAGS += -Wdeclaration-after-statement | 840 | KBUILD_CFLAGS += -Wdeclaration-after-statement |
| 843 | 841 | ||
| 844 | # Variable Length Arrays (VLAs) should not be used anywhere in the kernel | 842 | # Variable Length Arrays (VLAs) should not be used anywhere in the kernel |
| 845 | KBUILD_CFLAGS += $(call cc-option,-Wvla) | 843 | KBUILD_CFLAGS += -Wvla |
| 846 | 844 | ||
| 847 | # disable pointer signed / unsigned warnings in gcc 4.0 | 845 | # disable pointer signed / unsigned warnings in gcc 4.0 |
| 848 | KBUILD_CFLAGS += -Wno-pointer-sign | 846 | KBUILD_CFLAGS += -Wno-pointer-sign |
| @@ -1018,7 +1016,7 @@ export KBUILD_VMLINUX_LIBS := $(libs-y1) | |||
| 1018 | export KBUILD_LDS := arch/$(SRCARCH)/kernel/vmlinux.lds | 1016 | export KBUILD_LDS := arch/$(SRCARCH)/kernel/vmlinux.lds |
| 1019 | export LDFLAGS_vmlinux | 1017 | export LDFLAGS_vmlinux |
| 1020 | # used by scripts/package/Makefile | 1018 | # used by scripts/package/Makefile |
| 1021 | export KBUILD_ALLDIRS := $(sort $(filter-out arch/%,$(vmlinux-alldirs)) arch include scripts tools) | 1019 | export KBUILD_ALLDIRS := $(sort $(filter-out arch/%,$(vmlinux-alldirs)) LICENSES arch include scripts tools) |
| 1022 | 1020 | ||
| 1023 | vmlinux-deps := $(KBUILD_LDS) $(KBUILD_VMLINUX_OBJS) $(KBUILD_VMLINUX_LIBS) | 1021 | vmlinux-deps := $(KBUILD_LDS) $(KBUILD_VMLINUX_OBJS) $(KBUILD_VMLINUX_LIBS) |
| 1024 | 1022 | ||
| @@ -1290,6 +1288,7 @@ modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) modules.builtin | |||
| 1290 | $(Q)$(AWK) '!x[$$0]++' $(vmlinux-dirs:%=$(objtree)/%/modules.order) > $(objtree)/modules.order | 1288 | $(Q)$(AWK) '!x[$$0]++' $(vmlinux-dirs:%=$(objtree)/%/modules.order) > $(objtree)/modules.order |
| 1291 | @$(kecho) ' Building modules, stage 2.'; | 1289 | @$(kecho) ' Building modules, stage 2.'; |
| 1292 | $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost | 1290 | $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost |
| 1291 | $(Q)$(CONFIG_SHELL) $(srctree)/scripts/modules-check.sh | ||
| 1293 | 1292 | ||
| 1294 | modules.builtin: $(vmlinux-dirs:%=%/modules.builtin) | 1293 | modules.builtin: $(vmlinux-dirs:%=%/modules.builtin) |
| 1295 | $(Q)$(AWK) '!x[$$0]++' $^ > $(objtree)/modules.builtin | 1294 | $(Q)$(AWK) '!x[$$0]++' $^ > $(objtree)/modules.builtin |
diff --git a/arch/alpha/Makefile b/arch/alpha/Makefile index 12dee59b011c..b3314e0dcb6f 100644 --- a/arch/alpha/Makefile +++ b/arch/alpha/Makefile | |||
| @@ -8,6 +8,8 @@ | |||
| 8 | # Copyright (C) 1994 by Linus Torvalds | 8 | # Copyright (C) 1994 by Linus Torvalds |
| 9 | # | 9 | # |
| 10 | 10 | ||
| 11 | KBUILD_DEFCONFIG := defconfig | ||
| 12 | |||
| 11 | NM := $(NM) -B | 13 | NM := $(NM) -B |
| 12 | 14 | ||
| 13 | LDFLAGS_vmlinux := -static -N #-relax | 15 | LDFLAGS_vmlinux := -static -N #-relax |
diff --git a/arch/alpha/defconfig b/arch/alpha/configs/defconfig index f4ec420d7f2d..f4ec420d7f2d 100644 --- a/arch/alpha/defconfig +++ b/arch/alpha/configs/defconfig | |||
diff --git a/arch/arm/boot/dts/logicpd-som-lv-baseboard.dtsi b/arch/arm/boot/dts/logicpd-som-lv-baseboard.dtsi index 4990ed90dcea..3e39b9a1f35d 100644 --- a/arch/arm/boot/dts/logicpd-som-lv-baseboard.dtsi +++ b/arch/arm/boot/dts/logicpd-som-lv-baseboard.dtsi | |||
| @@ -153,7 +153,7 @@ | |||
| 153 | pinctrl-names = "default"; | 153 | pinctrl-names = "default"; |
| 154 | pinctrl-0 = <&mmc1_pins>; | 154 | pinctrl-0 = <&mmc1_pins>; |
| 155 | wp-gpios = <&gpio4 30 GPIO_ACTIVE_HIGH>; /* gpio_126 */ | 155 | wp-gpios = <&gpio4 30 GPIO_ACTIVE_HIGH>; /* gpio_126 */ |
| 156 | cd-gpios = <&gpio4 14 IRQ_TYPE_LEVEL_LOW>; /* gpio_110 */ | 156 | cd-gpios = <&gpio4 14 GPIO_ACTIVE_LOW>; /* gpio_110 */ |
| 157 | vmmc-supply = <&vmmc1>; | 157 | vmmc-supply = <&vmmc1>; |
| 158 | bus-width = <4>; | 158 | bus-width = <4>; |
| 159 | cap-power-off-card; | 159 | cap-power-off-card; |
diff --git a/arch/arm/configs/sama5_defconfig b/arch/arm/configs/sama5_defconfig index 515cb37eeab6..d5341b0bd88d 100644 --- a/arch/arm/configs/sama5_defconfig +++ b/arch/arm/configs/sama5_defconfig | |||
| @@ -150,7 +150,7 @@ CONFIG_MEDIA_CAMERA_SUPPORT=y | |||
| 150 | CONFIG_V4L_PLATFORM_DRIVERS=y | 150 | CONFIG_V4L_PLATFORM_DRIVERS=y |
| 151 | CONFIG_SOC_CAMERA=y | 151 | CONFIG_SOC_CAMERA=y |
| 152 | CONFIG_VIDEO_ATMEL_ISI=y | 152 | CONFIG_VIDEO_ATMEL_ISI=y |
| 153 | CONFIG_SOC_CAMERA_OV2640=y | 153 | CONFIG_SOC_CAMERA_OV2640=m |
| 154 | CONFIG_DRM=y | 154 | CONFIG_DRM=y |
| 155 | CONFIG_DRM_ATMEL_HLCDC=y | 155 | CONFIG_DRM_ATMEL_HLCDC=y |
| 156 | CONFIG_DRM_PANEL_SIMPLE=y | 156 | CONFIG_DRM_PANEL_SIMPLE=y |
diff --git a/arch/arm/configs/socfpga_defconfig b/arch/arm/configs/socfpga_defconfig index 9d42cfe85f5b..6701a975e785 100644 --- a/arch/arm/configs/socfpga_defconfig +++ b/arch/arm/configs/socfpga_defconfig | |||
| @@ -21,7 +21,6 @@ CONFIG_NEON=y | |||
| 21 | CONFIG_OPROFILE=y | 21 | CONFIG_OPROFILE=y |
| 22 | CONFIG_MODULES=y | 22 | CONFIG_MODULES=y |
| 23 | CONFIG_MODULE_UNLOAD=y | 23 | CONFIG_MODULE_UNLOAD=y |
| 24 | # CONFIG_LBDAF is not set | ||
| 25 | # CONFIG_BLK_DEV_BSG is not set | 24 | # CONFIG_BLK_DEV_BSG is not set |
| 26 | CONFIG_NET=y | 25 | CONFIG_NET=y |
| 27 | CONFIG_PACKET=y | 26 | CONFIG_PACKET=y |
| @@ -128,6 +127,8 @@ CONFIG_RTC_DRV_DS1307=y | |||
| 128 | CONFIG_DMADEVICES=y | 127 | CONFIG_DMADEVICES=y |
| 129 | CONFIG_PL330_DMA=y | 128 | CONFIG_PL330_DMA=y |
| 130 | CONFIG_DMATEST=m | 129 | CONFIG_DMATEST=m |
| 130 | CONFIG_IIO=y | ||
| 131 | CONFIG_LTC2497=y | ||
| 131 | CONFIG_FPGA=y | 132 | CONFIG_FPGA=y |
| 132 | CONFIG_FPGA_MGR_SOCFPGA=y | 133 | CONFIG_FPGA_MGR_SOCFPGA=y |
| 133 | CONFIG_FPGA_MGR_SOCFPGA_A10=y | 134 | CONFIG_FPGA_MGR_SOCFPGA_A10=y |
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 903f23c309df..a2220e522f62 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig | |||
| @@ -21,7 +21,6 @@ config SOC_SAMA5D2 | |||
| 21 | depends on ARCH_MULTI_V7 | 21 | depends on ARCH_MULTI_V7 |
| 22 | select SOC_SAMA5 | 22 | select SOC_SAMA5 |
| 23 | select CACHE_L2X0 | 23 | select CACHE_L2X0 |
| 24 | select HAVE_FB_ATMEL | ||
| 25 | select HAVE_AT91_UTMI | 24 | select HAVE_AT91_UTMI |
| 26 | select HAVE_AT91_USB_CLK | 25 | select HAVE_AT91_USB_CLK |
| 27 | select HAVE_AT91_H32MX | 26 | select HAVE_AT91_H32MX |
| @@ -36,7 +35,6 @@ config SOC_SAMA5D3 | |||
| 36 | bool "SAMA5D3 family" | 35 | bool "SAMA5D3 family" |
| 37 | depends on ARCH_MULTI_V7 | 36 | depends on ARCH_MULTI_V7 |
| 38 | select SOC_SAMA5 | 37 | select SOC_SAMA5 |
| 39 | select HAVE_FB_ATMEL | ||
| 40 | select HAVE_AT91_UTMI | 38 | select HAVE_AT91_UTMI |
| 41 | select HAVE_AT91_SMD | 39 | select HAVE_AT91_SMD |
| 42 | select HAVE_AT91_USB_CLK | 40 | select HAVE_AT91_USB_CLK |
| @@ -50,7 +48,6 @@ config SOC_SAMA5D4 | |||
| 50 | depends on ARCH_MULTI_V7 | 48 | depends on ARCH_MULTI_V7 |
| 51 | select SOC_SAMA5 | 49 | select SOC_SAMA5 |
| 52 | select CACHE_L2X0 | 50 | select CACHE_L2X0 |
| 53 | select HAVE_FB_ATMEL | ||
| 54 | select HAVE_AT91_UTMI | 51 | select HAVE_AT91_UTMI |
| 55 | select HAVE_AT91_SMD | 52 | select HAVE_AT91_SMD |
| 56 | select HAVE_AT91_USB_CLK | 53 | select HAVE_AT91_USB_CLK |
| @@ -107,6 +104,29 @@ config SOC_AT91SAM9 | |||
| 107 | AT91SAM9X35 | 104 | AT91SAM9X35 |
| 108 | AT91SAM9XE | 105 | AT91SAM9XE |
| 109 | 106 | ||
| 107 | comment "Clocksource driver selection" | ||
| 108 | |||
| 109 | config ATMEL_CLOCKSOURCE_PIT | ||
| 110 | bool "Periodic Interval Timer (PIT) support" | ||
| 111 | depends on SOC_AT91SAM9 || SOC_SAMA5 | ||
| 112 | default SOC_AT91SAM9 || SOC_SAMA5 | ||
| 113 | select ATMEL_PIT | ||
| 114 | help | ||
| 115 | Select this to get a clocksource based on the Atmel Periodic Interval | ||
| 116 | Timer. It has a relatively low resolution and the TC Block clocksource | ||
| 117 | should be preferred. | ||
| 118 | |||
| 119 | config ATMEL_CLOCKSOURCE_TCB | ||
| 120 | bool "Timer Counter Blocks (TCB) support" | ||
| 121 | default SOC_AT91RM9200 || SOC_AT91SAM9 || SOC_SAMA5 | ||
| 122 | select ATMEL_TCB_CLKSRC | ||
| 123 | help | ||
| 124 | Select this to get a high precision clocksource based on a | ||
| 125 | TC block with a 5+ MHz base clock rate. | ||
| 126 | On platforms with 16-bit counters, two timer channels are combined | ||
| 127 | to make a single 32-bit timer. | ||
| 128 | It can also be used as a clock event device supporting oneshot mode. | ||
| 129 | |||
| 110 | config HAVE_AT91_UTMI | 130 | config HAVE_AT91_UTMI |
| 111 | bool | 131 | bool |
| 112 | 132 | ||
diff --git a/arch/arm/mach-at91/at91sam9.c b/arch/arm/mach-at91/at91sam9.c index 3dbdef4d3cbf..c12563b09656 100644 --- a/arch/arm/mach-at91/at91sam9.c +++ b/arch/arm/mach-at91/at91sam9.c | |||
| @@ -32,3 +32,21 @@ DT_MACHINE_START(at91sam_dt, "Atmel AT91SAM9") | |||
| 32 | .init_machine = at91sam9_init, | 32 | .init_machine = at91sam9_init, |
| 33 | .dt_compat = at91_dt_board_compat, | 33 | .dt_compat = at91_dt_board_compat, |
| 34 | MACHINE_END | 34 | MACHINE_END |
| 35 | |||
| 36 | static void __init sam9x60_init(void) | ||
| 37 | { | ||
| 38 | of_platform_default_populate(NULL, NULL, NULL); | ||
| 39 | |||
| 40 | sam9x60_pm_init(); | ||
| 41 | } | ||
| 42 | |||
| 43 | static const char *const sam9x60_dt_board_compat[] __initconst = { | ||
| 44 | "microchip,sam9x60", | ||
| 45 | NULL | ||
| 46 | }; | ||
| 47 | |||
| 48 | DT_MACHINE_START(sam9x60_dt, "Microchip SAM9X60") | ||
| 49 | /* Maintainer: Microchip */ | ||
| 50 | .init_machine = sam9x60_init, | ||
| 51 | .dt_compat = sam9x60_dt_board_compat, | ||
| 52 | MACHINE_END | ||
diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h index e2bd17237964..72b45accfa0f 100644 --- a/arch/arm/mach-at91/generic.h +++ b/arch/arm/mach-at91/generic.h | |||
| @@ -14,11 +14,13 @@ | |||
| 14 | #ifdef CONFIG_PM | 14 | #ifdef CONFIG_PM |
| 15 | extern void __init at91rm9200_pm_init(void); | 15 | extern void __init at91rm9200_pm_init(void); |
| 16 | extern void __init at91sam9_pm_init(void); | 16 | extern void __init at91sam9_pm_init(void); |
| 17 | extern void __init sam9x60_pm_init(void); | ||
| 17 | extern void __init sama5_pm_init(void); | 18 | extern void __init sama5_pm_init(void); |
| 18 | extern void __init sama5d2_pm_init(void); | 19 | extern void __init sama5d2_pm_init(void); |
| 19 | #else | 20 | #else |
| 20 | static inline void __init at91rm9200_pm_init(void) { } | 21 | static inline void __init at91rm9200_pm_init(void) { } |
| 21 | static inline void __init at91sam9_pm_init(void) { } | 22 | static inline void __init at91sam9_pm_init(void) { } |
| 23 | static inline void __init sam9x60_pm_init(void) { } | ||
| 22 | static inline void __init sama5_pm_init(void) { } | 24 | static inline void __init sama5_pm_init(void) { } |
| 23 | static inline void __init sama5d2_pm_init(void) { } | 25 | static inline void __init sama5d2_pm_init(void) { } |
| 24 | #endif | 26 | #endif |
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index 2a757dcaa1a5..6c8147536f3d 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c | |||
| @@ -39,6 +39,20 @@ extern void at91_pinctrl_gpio_suspend(void); | |||
| 39 | extern void at91_pinctrl_gpio_resume(void); | 39 | extern void at91_pinctrl_gpio_resume(void); |
| 40 | #endif | 40 | #endif |
| 41 | 41 | ||
| 42 | struct at91_soc_pm { | ||
| 43 | int (*config_shdwc_ws)(void __iomem *shdwc, u32 *mode, u32 *polarity); | ||
| 44 | int (*config_pmc_ws)(void __iomem *pmc, u32 mode, u32 polarity); | ||
| 45 | const struct of_device_id *ws_ids; | ||
| 46 | struct at91_pm_data data; | ||
| 47 | }; | ||
| 48 | |||
| 49 | static struct at91_soc_pm soc_pm = { | ||
| 50 | .data = { | ||
| 51 | .standby_mode = AT91_PM_STANDBY, | ||
| 52 | .suspend_mode = AT91_PM_ULP0, | ||
| 53 | }, | ||
| 54 | }; | ||
| 55 | |||
| 42 | static const match_table_t pm_modes __initconst = { | 56 | static const match_table_t pm_modes __initconst = { |
| 43 | { AT91_PM_STANDBY, "standby" }, | 57 | { AT91_PM_STANDBY, "standby" }, |
| 44 | { AT91_PM_ULP0, "ulp0" }, | 58 | { AT91_PM_ULP0, "ulp0" }, |
| @@ -47,16 +61,11 @@ static const match_table_t pm_modes __initconst = { | |||
| 47 | { -1, NULL }, | 61 | { -1, NULL }, |
| 48 | }; | 62 | }; |
| 49 | 63 | ||
| 50 | static struct at91_pm_data pm_data = { | ||
| 51 | .standby_mode = AT91_PM_STANDBY, | ||
| 52 | .suspend_mode = AT91_PM_ULP0, | ||
| 53 | }; | ||
| 54 | |||
| 55 | #define at91_ramc_read(id, field) \ | 64 | #define at91_ramc_read(id, field) \ |
| 56 | __raw_readl(pm_data.ramc[id] + field) | 65 | __raw_readl(soc_pm.data.ramc[id] + field) |
| 57 | 66 | ||
| 58 | #define at91_ramc_write(id, field, value) \ | 67 | #define at91_ramc_write(id, field, value) \ |
| 59 | __raw_writel(value, pm_data.ramc[id] + field) | 68 | __raw_writel(value, soc_pm.data.ramc[id] + field) |
| 60 | 69 | ||
| 61 | static int at91_pm_valid_state(suspend_state_t state) | 70 | static int at91_pm_valid_state(suspend_state_t state) |
| 62 | { | 71 | { |
| @@ -91,6 +100,8 @@ static const struct wakeup_source_info ws_info[] = { | |||
| 91 | { .pmc_fsmr_bit = AT91_PMC_RTCAL, .shdwc_mr_bit = BIT(17) }, | 100 | { .pmc_fsmr_bit = AT91_PMC_RTCAL, .shdwc_mr_bit = BIT(17) }, |
| 92 | { .pmc_fsmr_bit = AT91_PMC_USBAL }, | 101 | { .pmc_fsmr_bit = AT91_PMC_USBAL }, |
| 93 | { .pmc_fsmr_bit = AT91_PMC_SDMMC_CD }, | 102 | { .pmc_fsmr_bit = AT91_PMC_SDMMC_CD }, |
| 103 | { .pmc_fsmr_bit = AT91_PMC_RTTAL }, | ||
| 104 | { .pmc_fsmr_bit = AT91_PMC_RXLP_MCE }, | ||
| 94 | }; | 105 | }; |
| 95 | 106 | ||
| 96 | static const struct of_device_id sama5d2_ws_ids[] = { | 107 | static const struct of_device_id sama5d2_ws_ids[] = { |
| @@ -105,6 +116,17 @@ static const struct of_device_id sama5d2_ws_ids[] = { | |||
| 105 | { /* sentinel */ } | 116 | { /* sentinel */ } |
| 106 | }; | 117 | }; |
| 107 | 118 | ||
| 119 | static const struct of_device_id sam9x60_ws_ids[] = { | ||
| 120 | { .compatible = "atmel,at91sam9x5-rtc", .data = &ws_info[1] }, | ||
| 121 | { .compatible = "atmel,at91rm9200-ohci", .data = &ws_info[2] }, | ||
| 122 | { .compatible = "usb-ohci", .data = &ws_info[2] }, | ||
| 123 | { .compatible = "atmel,at91sam9g45-ehci", .data = &ws_info[2] }, | ||
| 124 | { .compatible = "usb-ehci", .data = &ws_info[2] }, | ||
| 125 | { .compatible = "atmel,at91sam9260-rtt", .data = &ws_info[4] }, | ||
| 126 | { .compatible = "cdns,sam9x60-macb", .data = &ws_info[5] }, | ||
| 127 | { /* sentinel */ } | ||
| 128 | }; | ||
| 129 | |||
| 108 | static int at91_pm_config_ws(unsigned int pm_mode, bool set) | 130 | static int at91_pm_config_ws(unsigned int pm_mode, bool set) |
| 109 | { | 131 | { |
| 110 | const struct wakeup_source_info *wsi; | 132 | const struct wakeup_source_info *wsi; |
| @@ -116,24 +138,22 @@ static int at91_pm_config_ws(unsigned int pm_mode, bool set) | |||
| 116 | if (pm_mode != AT91_PM_ULP1) | 138 | if (pm_mode != AT91_PM_ULP1) |
| 117 | return 0; | 139 | return 0; |
| 118 | 140 | ||
| 119 | if (!pm_data.pmc || !pm_data.shdwc) | 141 | if (!soc_pm.data.pmc || !soc_pm.data.shdwc || !soc_pm.ws_ids) |
| 120 | return -EPERM; | 142 | return -EPERM; |
| 121 | 143 | ||
| 122 | if (!set) { | 144 | if (!set) { |
| 123 | writel(mode, pm_data.pmc + AT91_PMC_FSMR); | 145 | writel(mode, soc_pm.data.pmc + AT91_PMC_FSMR); |
| 124 | return 0; | 146 | return 0; |
| 125 | } | 147 | } |
| 126 | 148 | ||
| 127 | /* SHDWC.WUIR */ | 149 | if (soc_pm.config_shdwc_ws) |
| 128 | val = readl(pm_data.shdwc + 0x0c); | 150 | soc_pm.config_shdwc_ws(soc_pm.data.shdwc, &mode, &polarity); |
| 129 | mode |= (val & 0x3ff); | ||
| 130 | polarity |= ((val >> 16) & 0x3ff); | ||
| 131 | 151 | ||
| 132 | /* SHDWC.MR */ | 152 | /* SHDWC.MR */ |
| 133 | val = readl(pm_data.shdwc + 0x04); | 153 | val = readl(soc_pm.data.shdwc + 0x04); |
| 134 | 154 | ||
| 135 | /* Loop through defined wakeup sources. */ | 155 | /* Loop through defined wakeup sources. */ |
| 136 | for_each_matching_node_and_match(np, sama5d2_ws_ids, &match) { | 156 | for_each_matching_node_and_match(np, soc_pm.ws_ids, &match) { |
| 137 | pdev = of_find_device_by_node(np); | 157 | pdev = of_find_device_by_node(np); |
| 138 | if (!pdev) | 158 | if (!pdev) |
| 139 | continue; | 159 | continue; |
| @@ -155,8 +175,8 @@ put_device: | |||
| 155 | } | 175 | } |
| 156 | 176 | ||
| 157 | if (mode) { | 177 | if (mode) { |
| 158 | writel(mode, pm_data.pmc + AT91_PMC_FSMR); | 178 | if (soc_pm.config_pmc_ws) |
| 159 | writel(polarity, pm_data.pmc + AT91_PMC_FSPR); | 179 | soc_pm.config_pmc_ws(soc_pm.data.pmc, mode, polarity); |
| 160 | } else { | 180 | } else { |
| 161 | pr_err("AT91: PM: no ULP1 wakeup sources found!"); | 181 | pr_err("AT91: PM: no ULP1 wakeup sources found!"); |
| 162 | } | 182 | } |
| @@ -164,6 +184,34 @@ put_device: | |||
| 164 | return mode ? 0 : -EPERM; | 184 | return mode ? 0 : -EPERM; |
| 165 | } | 185 | } |
| 166 | 186 | ||
| 187 | static int at91_sama5d2_config_shdwc_ws(void __iomem *shdwc, u32 *mode, | ||
| 188 | u32 *polarity) | ||
| 189 | { | ||
| 190 | u32 val; | ||
| 191 | |||
| 192 | /* SHDWC.WUIR */ | ||
| 193 | val = readl(shdwc + 0x0c); | ||
| 194 | *mode |= (val & 0x3ff); | ||
| 195 | *polarity |= ((val >> 16) & 0x3ff); | ||
| 196 | |||
| 197 | return 0; | ||
| 198 | } | ||
| 199 | |||
| 200 | static int at91_sama5d2_config_pmc_ws(void __iomem *pmc, u32 mode, u32 polarity) | ||
| 201 | { | ||
| 202 | writel(mode, pmc + AT91_PMC_FSMR); | ||
| 203 | writel(polarity, pmc + AT91_PMC_FSPR); | ||
| 204 | |||
| 205 | return 0; | ||
| 206 | } | ||
| 207 | |||
| 208 | static int at91_sam9x60_config_pmc_ws(void __iomem *pmc, u32 mode, u32 polarity) | ||
| 209 | { | ||
| 210 | writel(mode, pmc + AT91_PMC_FSMR); | ||
| 211 | |||
| 212 | return 0; | ||
| 213 | } | ||
| 214 | |||
| 167 | /* | 215 | /* |
| 168 | * Called after processes are frozen, but before we shutdown devices. | 216 | * Called after processes are frozen, but before we shutdown devices. |
| 169 | */ | 217 | */ |
| @@ -171,18 +219,18 @@ static int at91_pm_begin(suspend_state_t state) | |||
| 171 | { | 219 | { |
| 172 | switch (state) { | 220 | switch (state) { |
| 173 | case PM_SUSPEND_MEM: | 221 | case PM_SUSPEND_MEM: |
| 174 | pm_data.mode = pm_data.suspend_mode; | 222 | soc_pm.data.mode = soc_pm.data.suspend_mode; |
| 175 | break; | 223 | break; |
| 176 | 224 | ||
| 177 | case PM_SUSPEND_STANDBY: | 225 | case PM_SUSPEND_STANDBY: |
| 178 | pm_data.mode = pm_data.standby_mode; | 226 | soc_pm.data.mode = soc_pm.data.standby_mode; |
| 179 | break; | 227 | break; |
| 180 | 228 | ||
| 181 | default: | 229 | default: |
| 182 | pm_data.mode = -1; | 230 | soc_pm.data.mode = -1; |
| 183 | } | 231 | } |
| 184 | 232 | ||
| 185 | return at91_pm_config_ws(pm_data.mode, true); | 233 | return at91_pm_config_ws(soc_pm.data.mode, true); |
| 186 | } | 234 | } |
| 187 | 235 | ||
| 188 | /* | 236 | /* |
| @@ -194,10 +242,10 @@ static int at91_pm_verify_clocks(void) | |||
| 194 | unsigned long scsr; | 242 | unsigned long scsr; |
| 195 | int i; | 243 | int i; |
| 196 | 244 | ||
| 197 | scsr = readl(pm_data.pmc + AT91_PMC_SCSR); | 245 | scsr = readl(soc_pm.data.pmc + AT91_PMC_SCSR); |
| 198 | 246 | ||
| 199 | /* USB must not be using PLLB */ | 247 | /* USB must not be using PLLB */ |
| 200 | if ((scsr & pm_data.uhp_udp_mask) != 0) { | 248 | if ((scsr & soc_pm.data.uhp_udp_mask) != 0) { |
| 201 | pr_err("AT91: PM - Suspend-to-RAM with USB still active\n"); | 249 | pr_err("AT91: PM - Suspend-to-RAM with USB still active\n"); |
| 202 | return 0; | 250 | return 0; |
| 203 | } | 251 | } |
| @@ -208,7 +256,7 @@ static int at91_pm_verify_clocks(void) | |||
| 208 | 256 | ||
| 209 | if ((scsr & (AT91_PMC_PCK0 << i)) == 0) | 257 | if ((scsr & (AT91_PMC_PCK0 << i)) == 0) |
| 210 | continue; | 258 | continue; |
| 211 | css = readl(pm_data.pmc + AT91_PMC_PCKR(i)) & AT91_PMC_CSS; | 259 | css = readl(soc_pm.data.pmc + AT91_PMC_PCKR(i)) & AT91_PMC_CSS; |
| 212 | if (css != AT91_PMC_CSS_SLOW) { | 260 | if (css != AT91_PMC_CSS_SLOW) { |
| 213 | pr_err("AT91: PM - Suspend-to-RAM with PCK%d src %d\n", i, css); | 261 | pr_err("AT91: PM - Suspend-to-RAM with PCK%d src %d\n", i, css); |
| 214 | return 0; | 262 | return 0; |
| @@ -230,7 +278,7 @@ static int at91_pm_verify_clocks(void) | |||
| 230 | */ | 278 | */ |
| 231 | int at91_suspend_entering_slow_clock(void) | 279 | int at91_suspend_entering_slow_clock(void) |
| 232 | { | 280 | { |
| 233 | return (pm_data.mode >= AT91_PM_ULP0); | 281 | return (soc_pm.data.mode >= AT91_PM_ULP0); |
| 234 | } | 282 | } |
| 235 | EXPORT_SYMBOL(at91_suspend_entering_slow_clock); | 283 | EXPORT_SYMBOL(at91_suspend_entering_slow_clock); |
| 236 | 284 | ||
| @@ -243,14 +291,14 @@ static int at91_suspend_finish(unsigned long val) | |||
| 243 | flush_cache_all(); | 291 | flush_cache_all(); |
| 244 | outer_disable(); | 292 | outer_disable(); |
| 245 | 293 | ||
| 246 | at91_suspend_sram_fn(&pm_data); | 294 | at91_suspend_sram_fn(&soc_pm.data); |
| 247 | 295 | ||
| 248 | return 0; | 296 | return 0; |
| 249 | } | 297 | } |
| 250 | 298 | ||
| 251 | static void at91_pm_suspend(suspend_state_t state) | 299 | static void at91_pm_suspend(suspend_state_t state) |
| 252 | { | 300 | { |
| 253 | if (pm_data.mode == AT91_PM_BACKUP) { | 301 | if (soc_pm.data.mode == AT91_PM_BACKUP) { |
| 254 | pm_bu->suspended = 1; | 302 | pm_bu->suspended = 1; |
| 255 | 303 | ||
| 256 | cpu_suspend(0, at91_suspend_finish); | 304 | cpu_suspend(0, at91_suspend_finish); |
| @@ -289,7 +337,7 @@ static int at91_pm_enter(suspend_state_t state) | |||
| 289 | /* | 337 | /* |
| 290 | * Ensure that clocks are in a valid state. | 338 | * Ensure that clocks are in a valid state. |
| 291 | */ | 339 | */ |
| 292 | if (pm_data.mode >= AT91_PM_ULP0 && | 340 | if (soc_pm.data.mode >= AT91_PM_ULP0 && |
| 293 | !at91_pm_verify_clocks()) | 341 | !at91_pm_verify_clocks()) |
| 294 | goto error; | 342 | goto error; |
| 295 | 343 | ||
| @@ -318,7 +366,7 @@ error: | |||
| 318 | */ | 366 | */ |
| 319 | static void at91_pm_end(void) | 367 | static void at91_pm_end(void) |
| 320 | { | 368 | { |
| 321 | at91_pm_config_ws(pm_data.mode, false); | 369 | at91_pm_config_ws(soc_pm.data.mode, false); |
| 322 | } | 370 | } |
| 323 | 371 | ||
| 324 | 372 | ||
| @@ -351,7 +399,7 @@ static void at91rm9200_standby(void) | |||
| 351 | " str %2, [%1, %3]\n\t" | 399 | " str %2, [%1, %3]\n\t" |
| 352 | " mcr p15, 0, %0, c7, c0, 4\n\t" | 400 | " mcr p15, 0, %0, c7, c0, 4\n\t" |
| 353 | : | 401 | : |
| 354 | : "r" (0), "r" (pm_data.ramc[0]), | 402 | : "r" (0), "r" (soc_pm.data.ramc[0]), |
| 355 | "r" (1), "r" (AT91_MC_SDRAMC_SRR)); | 403 | "r" (1), "r" (AT91_MC_SDRAMC_SRR)); |
| 356 | } | 404 | } |
| 357 | 405 | ||
| @@ -374,7 +422,7 @@ static void at91_ddr_standby(void) | |||
| 374 | at91_ramc_write(0, AT91_DDRSDRC_MDR, mdr); | 422 | at91_ramc_write(0, AT91_DDRSDRC_MDR, mdr); |
| 375 | } | 423 | } |
| 376 | 424 | ||
| 377 | if (pm_data.ramc[1]) { | 425 | if (soc_pm.data.ramc[1]) { |
| 378 | saved_lpr1 = at91_ramc_read(1, AT91_DDRSDRC_LPR); | 426 | saved_lpr1 = at91_ramc_read(1, AT91_DDRSDRC_LPR); |
| 379 | lpr1 = saved_lpr1 & ~AT91_DDRSDRC_LPCB; | 427 | lpr1 = saved_lpr1 & ~AT91_DDRSDRC_LPCB; |
| 380 | lpr1 |= AT91_DDRSDRC_LPCB_SELF_REFRESH; | 428 | lpr1 |= AT91_DDRSDRC_LPCB_SELF_REFRESH; |
| @@ -392,14 +440,14 @@ static void at91_ddr_standby(void) | |||
| 392 | 440 | ||
| 393 | /* self-refresh mode now */ | 441 | /* self-refresh mode now */ |
| 394 | at91_ramc_write(0, AT91_DDRSDRC_LPR, lpr0); | 442 | at91_ramc_write(0, AT91_DDRSDRC_LPR, lpr0); |
| 395 | if (pm_data.ramc[1]) | 443 | if (soc_pm.data.ramc[1]) |
| 396 | at91_ramc_write(1, AT91_DDRSDRC_LPR, lpr1); | 444 | at91_ramc_write(1, AT91_DDRSDRC_LPR, lpr1); |
| 397 | 445 | ||
| 398 | cpu_do_idle(); | 446 | cpu_do_idle(); |
| 399 | 447 | ||
| 400 | at91_ramc_write(0, AT91_DDRSDRC_MDR, saved_mdr0); | 448 | at91_ramc_write(0, AT91_DDRSDRC_MDR, saved_mdr0); |
| 401 | at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr0); | 449 | at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr0); |
| 402 | if (pm_data.ramc[1]) { | 450 | if (soc_pm.data.ramc[1]) { |
| 403 | at91_ramc_write(0, AT91_DDRSDRC_MDR, saved_mdr1); | 451 | at91_ramc_write(0, AT91_DDRSDRC_MDR, saved_mdr1); |
| 404 | at91_ramc_write(1, AT91_DDRSDRC_LPR, saved_lpr1); | 452 | at91_ramc_write(1, AT91_DDRSDRC_LPR, saved_lpr1); |
| 405 | } | 453 | } |
| @@ -429,7 +477,7 @@ static void at91sam9_sdram_standby(void) | |||
| 429 | u32 lpr0, lpr1 = 0; | 477 | u32 lpr0, lpr1 = 0; |
| 430 | u32 saved_lpr0, saved_lpr1 = 0; | 478 | u32 saved_lpr0, saved_lpr1 = 0; |
| 431 | 479 | ||
| 432 | if (pm_data.ramc[1]) { | 480 | if (soc_pm.data.ramc[1]) { |
| 433 | saved_lpr1 = at91_ramc_read(1, AT91_SDRAMC_LPR); | 481 | saved_lpr1 = at91_ramc_read(1, AT91_SDRAMC_LPR); |
| 434 | lpr1 = saved_lpr1 & ~AT91_SDRAMC_LPCB; | 482 | lpr1 = saved_lpr1 & ~AT91_SDRAMC_LPCB; |
| 435 | lpr1 |= AT91_SDRAMC_LPCB_SELF_REFRESH; | 483 | lpr1 |= AT91_SDRAMC_LPCB_SELF_REFRESH; |
| @@ -441,13 +489,13 @@ static void at91sam9_sdram_standby(void) | |||
| 441 | 489 | ||
| 442 | /* self-refresh mode now */ | 490 | /* self-refresh mode now */ |
| 443 | at91_ramc_write(0, AT91_SDRAMC_LPR, lpr0); | 491 | at91_ramc_write(0, AT91_SDRAMC_LPR, lpr0); |
| 444 | if (pm_data.ramc[1]) | 492 | if (soc_pm.data.ramc[1]) |
| 445 | at91_ramc_write(1, AT91_SDRAMC_LPR, lpr1); | 493 | at91_ramc_write(1, AT91_SDRAMC_LPR, lpr1); |
| 446 | 494 | ||
| 447 | cpu_do_idle(); | 495 | cpu_do_idle(); |
| 448 | 496 | ||
| 449 | at91_ramc_write(0, AT91_SDRAMC_LPR, saved_lpr0); | 497 | at91_ramc_write(0, AT91_SDRAMC_LPR, saved_lpr0); |
| 450 | if (pm_data.ramc[1]) | 498 | if (soc_pm.data.ramc[1]) |
| 451 | at91_ramc_write(1, AT91_SDRAMC_LPR, saved_lpr1); | 499 | at91_ramc_write(1, AT91_SDRAMC_LPR, saved_lpr1); |
| 452 | } | 500 | } |
| 453 | 501 | ||
| @@ -480,14 +528,14 @@ static __init void at91_dt_ramc(void) | |||
| 480 | const struct ramc_info *ramc; | 528 | const struct ramc_info *ramc; |
| 481 | 529 | ||
| 482 | for_each_matching_node_and_match(np, ramc_ids, &of_id) { | 530 | for_each_matching_node_and_match(np, ramc_ids, &of_id) { |
| 483 | pm_data.ramc[idx] = of_iomap(np, 0); | 531 | soc_pm.data.ramc[idx] = of_iomap(np, 0); |
| 484 | if (!pm_data.ramc[idx]) | 532 | if (!soc_pm.data.ramc[idx]) |
| 485 | panic(pr_fmt("unable to map ramc[%d] cpu registers\n"), idx); | 533 | panic(pr_fmt("unable to map ramc[%d] cpu registers\n"), idx); |
| 486 | 534 | ||
| 487 | ramc = of_id->data; | 535 | ramc = of_id->data; |
| 488 | if (!standby) | 536 | if (!standby) |
| 489 | standby = ramc->idle; | 537 | standby = ramc->idle; |
| 490 | pm_data.memctrl = ramc->memctrl; | 538 | soc_pm.data.memctrl = ramc->memctrl; |
| 491 | 539 | ||
| 492 | idx++; | 540 | idx++; |
| 493 | } | 541 | } |
| @@ -509,12 +557,17 @@ static void at91rm9200_idle(void) | |||
| 509 | * Disable the processor clock. The processor will be automatically | 557 | * Disable the processor clock. The processor will be automatically |
| 510 | * re-enabled by an interrupt or by a reset. | 558 | * re-enabled by an interrupt or by a reset. |
| 511 | */ | 559 | */ |
| 512 | writel(AT91_PMC_PCK, pm_data.pmc + AT91_PMC_SCDR); | 560 | writel(AT91_PMC_PCK, soc_pm.data.pmc + AT91_PMC_SCDR); |
| 561 | } | ||
| 562 | |||
| 563 | static void at91sam9x60_idle(void) | ||
| 564 | { | ||
| 565 | cpu_do_idle(); | ||
| 513 | } | 566 | } |
| 514 | 567 | ||
| 515 | static void at91sam9_idle(void) | 568 | static void at91sam9_idle(void) |
| 516 | { | 569 | { |
| 517 | writel(AT91_PMC_PCK, pm_data.pmc + AT91_PMC_SCDR); | 570 | writel(AT91_PMC_PCK, soc_pm.data.pmc + AT91_PMC_SCDR); |
| 518 | cpu_do_idle(); | 571 | cpu_do_idle(); |
| 519 | } | 572 | } |
| 520 | 573 | ||
| @@ -566,8 +619,8 @@ static void __init at91_pm_sram_init(void) | |||
| 566 | 619 | ||
| 567 | static bool __init at91_is_pm_mode_active(int pm_mode) | 620 | static bool __init at91_is_pm_mode_active(int pm_mode) |
| 568 | { | 621 | { |
| 569 | return (pm_data.standby_mode == pm_mode || | 622 | return (soc_pm.data.standby_mode == pm_mode || |
| 570 | pm_data.suspend_mode == pm_mode); | 623 | soc_pm.data.suspend_mode == pm_mode); |
| 571 | } | 624 | } |
| 572 | 625 | ||
| 573 | static int __init at91_pm_backup_init(void) | 626 | static int __init at91_pm_backup_init(void) |
| @@ -577,6 +630,9 @@ static int __init at91_pm_backup_init(void) | |||
| 577 | struct platform_device *pdev = NULL; | 630 | struct platform_device *pdev = NULL; |
| 578 | int ret = -ENODEV; | 631 | int ret = -ENODEV; |
| 579 | 632 | ||
| 633 | if (!IS_ENABLED(CONFIG_SOC_SAMA5D2)) | ||
| 634 | return -EPERM; | ||
| 635 | |||
| 580 | if (!at91_is_pm_mode_active(AT91_PM_BACKUP)) | 636 | if (!at91_is_pm_mode_active(AT91_PM_BACKUP)) |
| 581 | return 0; | 637 | return 0; |
| 582 | 638 | ||
| @@ -586,7 +642,7 @@ static int __init at91_pm_backup_init(void) | |||
| 586 | return ret; | 642 | return ret; |
| 587 | } | 643 | } |
| 588 | 644 | ||
| 589 | pm_data.sfrbu = of_iomap(np, 0); | 645 | soc_pm.data.sfrbu = of_iomap(np, 0); |
| 590 | of_node_put(np); | 646 | of_node_put(np); |
| 591 | 647 | ||
| 592 | np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-securam"); | 648 | np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-securam"); |
| @@ -622,8 +678,8 @@ static int __init at91_pm_backup_init(void) | |||
| 622 | securam_fail: | 678 | securam_fail: |
| 623 | put_device(&pdev->dev); | 679 | put_device(&pdev->dev); |
| 624 | securam_fail_no_ref_dev: | 680 | securam_fail_no_ref_dev: |
| 625 | iounmap(pm_data.sfrbu); | 681 | iounmap(soc_pm.data.sfrbu); |
| 626 | pm_data.sfrbu = NULL; | 682 | soc_pm.data.sfrbu = NULL; |
| 627 | return ret; | 683 | return ret; |
| 628 | } | 684 | } |
| 629 | 685 | ||
| @@ -632,10 +688,10 @@ static void __init at91_pm_use_default_mode(int pm_mode) | |||
| 632 | if (pm_mode != AT91_PM_ULP1 && pm_mode != AT91_PM_BACKUP) | 688 | if (pm_mode != AT91_PM_ULP1 && pm_mode != AT91_PM_BACKUP) |
| 633 | return; | 689 | return; |
| 634 | 690 | ||
| 635 | if (pm_data.standby_mode == pm_mode) | 691 | if (soc_pm.data.standby_mode == pm_mode) |
| 636 | pm_data.standby_mode = AT91_PM_ULP0; | 692 | soc_pm.data.standby_mode = AT91_PM_ULP0; |
| 637 | if (pm_data.suspend_mode == pm_mode) | 693 | if (soc_pm.data.suspend_mode == pm_mode) |
| 638 | pm_data.suspend_mode = AT91_PM_ULP0; | 694 | soc_pm.data.suspend_mode = AT91_PM_ULP0; |
| 639 | } | 695 | } |
| 640 | 696 | ||
| 641 | static void __init at91_pm_modes_init(void) | 697 | static void __init at91_pm_modes_init(void) |
| @@ -653,7 +709,7 @@ static void __init at91_pm_modes_init(void) | |||
| 653 | goto ulp1_default; | 709 | goto ulp1_default; |
| 654 | } | 710 | } |
| 655 | 711 | ||
| 656 | pm_data.shdwc = of_iomap(np, 0); | 712 | soc_pm.data.shdwc = of_iomap(np, 0); |
| 657 | of_node_put(np); | 713 | of_node_put(np); |
| 658 | 714 | ||
| 659 | ret = at91_pm_backup_init(); | 715 | ret = at91_pm_backup_init(); |
| @@ -667,8 +723,8 @@ static void __init at91_pm_modes_init(void) | |||
| 667 | return; | 723 | return; |
| 668 | 724 | ||
| 669 | unmap: | 725 | unmap: |
| 670 | iounmap(pm_data.shdwc); | 726 | iounmap(soc_pm.data.shdwc); |
| 671 | pm_data.shdwc = NULL; | 727 | soc_pm.data.shdwc = NULL; |
| 672 | ulp1_default: | 728 | ulp1_default: |
| 673 | at91_pm_use_default_mode(AT91_PM_ULP1); | 729 | at91_pm_use_default_mode(AT91_PM_ULP1); |
| 674 | backup_default: | 730 | backup_default: |
| @@ -711,14 +767,14 @@ static void __init at91_pm_init(void (*pm_idle)(void)) | |||
| 711 | platform_device_register(&at91_cpuidle_device); | 767 | platform_device_register(&at91_cpuidle_device); |
| 712 | 768 | ||
| 713 | pmc_np = of_find_matching_node_and_match(NULL, atmel_pmc_ids, &of_id); | 769 | pmc_np = of_find_matching_node_and_match(NULL, atmel_pmc_ids, &of_id); |
| 714 | pm_data.pmc = of_iomap(pmc_np, 0); | 770 | soc_pm.data.pmc = of_iomap(pmc_np, 0); |
| 715 | if (!pm_data.pmc) { | 771 | if (!soc_pm.data.pmc) { |
| 716 | pr_err("AT91: PM not supported, PMC not found\n"); | 772 | pr_err("AT91: PM not supported, PMC not found\n"); |
| 717 | return; | 773 | return; |
| 718 | } | 774 | } |
| 719 | 775 | ||
| 720 | pmc = of_id->data; | 776 | pmc = of_id->data; |
| 721 | pm_data.uhp_udp_mask = pmc->uhp_udp_mask; | 777 | soc_pm.data.uhp_udp_mask = pmc->uhp_udp_mask; |
| 722 | 778 | ||
| 723 | if (pm_idle) | 779 | if (pm_idle) |
| 724 | arm_pm_idle = pm_idle; | 780 | arm_pm_idle = pm_idle; |
| @@ -728,8 +784,8 @@ static void __init at91_pm_init(void (*pm_idle)(void)) | |||
| 728 | if (at91_suspend_sram_fn) { | 784 | if (at91_suspend_sram_fn) { |
| 729 | suspend_set_ops(&at91_pm_ops); | 785 | suspend_set_ops(&at91_pm_ops); |
| 730 | pr_info("AT91: PM: standby: %s, suspend: %s\n", | 786 | pr_info("AT91: PM: standby: %s, suspend: %s\n", |
| 731 | pm_modes[pm_data.standby_mode].pattern, | 787 | pm_modes[soc_pm.data.standby_mode].pattern, |
| 732 | pm_modes[pm_data.suspend_mode].pattern); | 788 | pm_modes[soc_pm.data.suspend_mode].pattern); |
| 733 | } else { | 789 | } else { |
| 734 | pr_info("AT91: PM not supported, due to no SRAM allocated\n"); | 790 | pr_info("AT91: PM not supported, due to no SRAM allocated\n"); |
| 735 | } | 791 | } |
| @@ -750,6 +806,19 @@ void __init at91rm9200_pm_init(void) | |||
| 750 | at91_pm_init(at91rm9200_idle); | 806 | at91_pm_init(at91rm9200_idle); |
| 751 | } | 807 | } |
| 752 | 808 | ||
| 809 | void __init sam9x60_pm_init(void) | ||
| 810 | { | ||
| 811 | if (!IS_ENABLED(CONFIG_SOC_AT91SAM9)) | ||
| 812 | return; | ||
| 813 | |||
| 814 | at91_pm_modes_init(); | ||
| 815 | at91_dt_ramc(); | ||
| 816 | at91_pm_init(at91sam9x60_idle); | ||
| 817 | |||
| 818 | soc_pm.ws_ids = sam9x60_ws_ids; | ||
| 819 | soc_pm.config_pmc_ws = at91_sam9x60_config_pmc_ws; | ||
| 820 | } | ||
| 821 | |||
| 753 | void __init at91sam9_pm_init(void) | 822 | void __init at91sam9_pm_init(void) |
| 754 | { | 823 | { |
| 755 | if (!IS_ENABLED(CONFIG_SOC_AT91SAM9)) | 824 | if (!IS_ENABLED(CONFIG_SOC_AT91SAM9)) |
| @@ -775,6 +844,10 @@ void __init sama5d2_pm_init(void) | |||
| 775 | 844 | ||
| 776 | at91_pm_modes_init(); | 845 | at91_pm_modes_init(); |
| 777 | sama5_pm_init(); | 846 | sama5_pm_init(); |
| 847 | |||
| 848 | soc_pm.ws_ids = sama5d2_ws_ids; | ||
| 849 | soc_pm.config_shdwc_ws = at91_sama5d2_config_shdwc_ws; | ||
| 850 | soc_pm.config_pmc_ws = at91_sama5d2_config_pmc_ws; | ||
| 778 | } | 851 | } |
| 779 | 852 | ||
| 780 | static int __init at91_pm_modes_select(char *str) | 853 | static int __init at91_pm_modes_select(char *str) |
| @@ -795,8 +868,8 @@ static int __init at91_pm_modes_select(char *str) | |||
| 795 | if (suspend < 0) | 868 | if (suspend < 0) |
| 796 | return 0; | 869 | return 0; |
| 797 | 870 | ||
| 798 | pm_data.standby_mode = standby; | 871 | soc_pm.data.standby_mode = standby; |
| 799 | pm_data.suspend_mode = suspend; | 872 | soc_pm.data.suspend_mode = suspend; |
| 800 | 873 | ||
| 801 | return 0; | 874 | return 0; |
| 802 | } | 875 | } |
diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S index bfe1c4d06901..77e29309cc6e 100644 --- a/arch/arm/mach-at91/pm_suspend.S +++ b/arch/arm/mach-at91/pm_suspend.S | |||
| @@ -51,15 +51,6 @@ tmp2 .req r5 | |||
| 51 | .endm | 51 | .endm |
| 52 | 52 | ||
| 53 | /* | 53 | /* |
| 54 | * Wait until PLLA has locked. | ||
| 55 | */ | ||
| 56 | .macro wait_pllalock | ||
| 57 | 1: ldr tmp1, [pmc, #AT91_PMC_SR] | ||
| 58 | tst tmp1, #AT91_PMC_LOCKA | ||
| 59 | beq 1b | ||
| 60 | .endm | ||
| 61 | |||
| 62 | /* | ||
| 63 | * Put the processor to enter the idle state | 54 | * Put the processor to enter the idle state |
| 64 | */ | 55 | */ |
| 65 | .macro at91_cpu_idle | 56 | .macro at91_cpu_idle |
| @@ -178,11 +169,46 @@ ENDPROC(at91_backup_mode) | |||
| 178 | orr tmp1, tmp1, #AT91_PMC_KEY | 169 | orr tmp1, tmp1, #AT91_PMC_KEY |
| 179 | str tmp1, [pmc, #AT91_CKGR_MOR] | 170 | str tmp1, [pmc, #AT91_CKGR_MOR] |
| 180 | 171 | ||
| 172 | /* Save RC oscillator state */ | ||
| 173 | ldr tmp1, [pmc, #AT91_PMC_SR] | ||
| 174 | str tmp1, .saved_osc_status | ||
| 175 | tst tmp1, #AT91_PMC_MOSCRCS | ||
| 176 | bne 1f | ||
| 177 | |||
| 178 | /* Turn off RC oscillator */ | ||
| 179 | ldr tmp1, [pmc, #AT91_CKGR_MOR] | ||
| 180 | bic tmp1, tmp1, #AT91_PMC_MOSCRCEN | ||
| 181 | bic tmp1, tmp1, #AT91_PMC_KEY_MASK | ||
| 182 | orr tmp1, tmp1, #AT91_PMC_KEY | ||
| 183 | str tmp1, [pmc, #AT91_CKGR_MOR] | ||
| 184 | |||
| 185 | /* Wait main RC disabled done */ | ||
| 186 | 2: ldr tmp1, [pmc, #AT91_PMC_SR] | ||
| 187 | tst tmp1, #AT91_PMC_MOSCRCS | ||
| 188 | bne 2b | ||
| 189 | |||
| 181 | /* Wait for interrupt */ | 190 | /* Wait for interrupt */ |
| 182 | at91_cpu_idle | 191 | 1: at91_cpu_idle |
| 183 | 192 | ||
| 184 | /* Turn on the crystal oscillator */ | 193 | /* Restore RC oscillator state */ |
| 194 | ldr tmp1, .saved_osc_status | ||
| 195 | tst tmp1, #AT91_PMC_MOSCRCS | ||
| 196 | beq 4f | ||
| 197 | |||
| 198 | /* Turn on RC oscillator */ | ||
| 185 | ldr tmp1, [pmc, #AT91_CKGR_MOR] | 199 | ldr tmp1, [pmc, #AT91_CKGR_MOR] |
| 200 | orr tmp1, tmp1, #AT91_PMC_MOSCRCEN | ||
| 201 | bic tmp1, tmp1, #AT91_PMC_KEY_MASK | ||
| 202 | orr tmp1, tmp1, #AT91_PMC_KEY | ||
| 203 | str tmp1, [pmc, #AT91_CKGR_MOR] | ||
| 204 | |||
| 205 | /* Wait main RC stabilization */ | ||
| 206 | 3: ldr tmp1, [pmc, #AT91_PMC_SR] | ||
| 207 | tst tmp1, #AT91_PMC_MOSCRCS | ||
| 208 | beq 3b | ||
| 209 | |||
| 210 | /* Turn on the crystal oscillator */ | ||
| 211 | 4: ldr tmp1, [pmc, #AT91_CKGR_MOR] | ||
| 186 | orr tmp1, tmp1, #AT91_PMC_MOSCEN | 212 | orr tmp1, tmp1, #AT91_PMC_MOSCEN |
| 187 | orr tmp1, tmp1, #AT91_PMC_KEY | 213 | orr tmp1, tmp1, #AT91_PMC_KEY |
| 188 | str tmp1, [pmc, #AT91_CKGR_MOR] | 214 | str tmp1, [pmc, #AT91_CKGR_MOR] |
| @@ -197,8 +223,26 @@ ENDPROC(at91_backup_mode) | |||
| 197 | .macro at91_pm_ulp1_mode | 223 | .macro at91_pm_ulp1_mode |
| 198 | ldr pmc, .pmc_base | 224 | ldr pmc, .pmc_base |
| 199 | 225 | ||
| 200 | /* Switch the main clock source to 12-MHz RC oscillator */ | 226 | /* Save RC oscillator state and check if it is enabled. */ |
| 227 | ldr tmp1, [pmc, #AT91_PMC_SR] | ||
| 228 | str tmp1, .saved_osc_status | ||
| 229 | tst tmp1, #AT91_PMC_MOSCRCS | ||
| 230 | bne 2f | ||
| 231 | |||
| 232 | /* Enable RC oscillator */ | ||
| 201 | ldr tmp1, [pmc, #AT91_CKGR_MOR] | 233 | ldr tmp1, [pmc, #AT91_CKGR_MOR] |
| 234 | orr tmp1, tmp1, #AT91_PMC_MOSCRCEN | ||
| 235 | bic tmp1, tmp1, #AT91_PMC_KEY_MASK | ||
| 236 | orr tmp1, tmp1, #AT91_PMC_KEY | ||
| 237 | str tmp1, [pmc, #AT91_CKGR_MOR] | ||
| 238 | |||
| 239 | /* Wait main RC stabilization */ | ||
| 240 | 1: ldr tmp1, [pmc, #AT91_PMC_SR] | ||
| 241 | tst tmp1, #AT91_PMC_MOSCRCS | ||
| 242 | beq 1b | ||
| 243 | |||
| 244 | /* Switch the main clock source to 12-MHz RC oscillator */ | ||
| 245 | 2: ldr tmp1, [pmc, #AT91_CKGR_MOR] | ||
| 202 | bic tmp1, tmp1, #AT91_PMC_MOSCSEL | 246 | bic tmp1, tmp1, #AT91_PMC_MOSCSEL |
| 203 | bic tmp1, tmp1, #AT91_PMC_KEY_MASK | 247 | bic tmp1, tmp1, #AT91_PMC_KEY_MASK |
| 204 | orr tmp1, tmp1, #AT91_PMC_KEY | 248 | orr tmp1, tmp1, #AT91_PMC_KEY |
| @@ -262,6 +306,25 @@ ENDPROC(at91_backup_mode) | |||
| 262 | str tmp1, [pmc, #AT91_PMC_MCKR] | 306 | str tmp1, [pmc, #AT91_PMC_MCKR] |
| 263 | 307 | ||
| 264 | wait_mckrdy | 308 | wait_mckrdy |
| 309 | |||
| 310 | /* Restore RC oscillator state */ | ||
| 311 | ldr tmp1, .saved_osc_status | ||
| 312 | tst tmp1, #AT91_PMC_MOSCRCS | ||
| 313 | bne 3f | ||
| 314 | |||
| 315 | /* Disable RC oscillator */ | ||
| 316 | ldr tmp1, [pmc, #AT91_CKGR_MOR] | ||
| 317 | bic tmp1, tmp1, #AT91_PMC_MOSCRCEN | ||
| 318 | bic tmp1, tmp1, #AT91_PMC_KEY_MASK | ||
| 319 | orr tmp1, tmp1, #AT91_PMC_KEY | ||
| 320 | str tmp1, [pmc, #AT91_CKGR_MOR] | ||
| 321 | |||
| 322 | /* Wait RC oscillator disable done */ | ||
| 323 | 4: ldr tmp1, [pmc, #AT91_PMC_SR] | ||
| 324 | tst tmp1, #AT91_PMC_MOSCRCS | ||
| 325 | bne 4b | ||
| 326 | |||
| 327 | 3: | ||
| 265 | .endm | 328 | .endm |
| 266 | 329 | ||
| 267 | ENTRY(at91_ulp_mode) | 330 | ENTRY(at91_ulp_mode) |
| @@ -279,14 +342,6 @@ ENTRY(at91_ulp_mode) | |||
| 279 | 342 | ||
| 280 | wait_mckrdy | 343 | wait_mckrdy |
| 281 | 344 | ||
| 282 | /* Save PLLA setting and disable it */ | ||
| 283 | ldr tmp1, [pmc, #AT91_CKGR_PLLAR] | ||
| 284 | str tmp1, .saved_pllar | ||
| 285 | |||
| 286 | mov tmp1, #AT91_PMC_PLLCOUNT | ||
| 287 | orr tmp1, tmp1, #(1 << 29) /* bit 29 always set */ | ||
| 288 | str tmp1, [pmc, #AT91_CKGR_PLLAR] | ||
| 289 | |||
| 290 | ldr r0, .pm_mode | 345 | ldr r0, .pm_mode |
| 291 | cmp r0, #AT91_PM_ULP1 | 346 | cmp r0, #AT91_PM_ULP1 |
| 292 | beq ulp1_mode | 347 | beq ulp1_mode |
| @@ -301,18 +356,6 @@ ulp1_mode: | |||
| 301 | ulp_exit: | 356 | ulp_exit: |
| 302 | ldr pmc, .pmc_base | 357 | ldr pmc, .pmc_base |
| 303 | 358 | ||
| 304 | /* Restore PLLA setting */ | ||
| 305 | ldr tmp1, .saved_pllar | ||
| 306 | str tmp1, [pmc, #AT91_CKGR_PLLAR] | ||
| 307 | |||
| 308 | tst tmp1, #(AT91_PMC_MUL & 0xff0000) | ||
| 309 | bne 3f | ||
| 310 | tst tmp1, #(AT91_PMC_MUL & ~0xff0000) | ||
| 311 | beq 4f | ||
| 312 | 3: | ||
| 313 | wait_pllalock | ||
| 314 | 4: | ||
| 315 | |||
| 316 | /* | 359 | /* |
| 317 | * Restore master clock setting | 360 | * Restore master clock setting |
| 318 | */ | 361 | */ |
| @@ -465,8 +508,6 @@ ENDPROC(at91_sramc_self_refresh) | |||
| 465 | .word 0 | 508 | .word 0 |
| 466 | .saved_mckr: | 509 | .saved_mckr: |
| 467 | .word 0 | 510 | .word 0 |
| 468 | .saved_pllar: | ||
| 469 | .word 0 | ||
| 470 | .saved_sam9_lpr: | 511 | .saved_sam9_lpr: |
| 471 | .word 0 | 512 | .word 0 |
| 472 | .saved_sam9_lpr1: | 513 | .saved_sam9_lpr1: |
| @@ -475,6 +516,8 @@ ENDPROC(at91_sramc_self_refresh) | |||
| 475 | .word 0 | 516 | .word 0 |
| 476 | .saved_sam9_mdr1: | 517 | .saved_sam9_mdr1: |
| 477 | .word 0 | 518 | .word 0 |
| 519 | .saved_osc_status: | ||
| 520 | .word 0 | ||
| 478 | 521 | ||
| 479 | ENTRY(at91_pm_suspend_in_sram_sz) | 522 | ENTRY(at91_pm_suspend_in_sram_sz) |
| 480 | .word .-at91_pm_suspend_in_sram | 523 | .word .-at91_pm_suspend_in_sram |
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index cc5f15679d29..381f452de28d 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c | |||
| @@ -27,7 +27,6 @@ | |||
| 27 | #include <linux/cpu.h> | 27 | #include <linux/cpu.h> |
| 28 | #include <linux/pci.h> | 28 | #include <linux/pci.h> |
| 29 | #include <linux/sched_clock.h> | 29 | #include <linux/sched_clock.h> |
| 30 | #include <linux/bitops.h> | ||
| 31 | #include <linux/irqchip/irq-ixp4xx.h> | 30 | #include <linux/irqchip/irq-ixp4xx.h> |
| 32 | #include <linux/platform_data/timer-ixp4xx.h> | 31 | #include <linux/platform_data/timer-ixp4xx.h> |
| 33 | #include <mach/udc.h> | 32 | #include <mach/udc.h> |
diff --git a/arch/arm/mach-mvebu/board-v7.c b/arch/arm/mach-mvebu/board-v7.c index 0b10acd7d1b9..d2df5ef9382b 100644 --- a/arch/arm/mach-mvebu/board-v7.c +++ b/arch/arm/mach-mvebu/board-v7.c | |||
| @@ -136,7 +136,6 @@ static void __init i2c_quirk(void) | |||
| 136 | 136 | ||
| 137 | of_update_property(np, new_compat); | 137 | of_update_property(np, new_compat); |
| 138 | } | 138 | } |
| 139 | return; | ||
| 140 | } | 139 | } |
| 141 | 140 | ||
| 142 | static void __init mvebu_dt_init(void) | 141 | static void __init mvebu_dt_init(void) |
diff --git a/arch/arm/mach-mvebu/coherency_ll.S b/arch/arm/mach-mvebu/coherency_ll.S index 8b2fbc8b6bc6..2d962fe48821 100644 --- a/arch/arm/mach-mvebu/coherency_ll.S +++ b/arch/arm/mach-mvebu/coherency_ll.S | |||
| @@ -66,7 +66,7 @@ ENDPROC(ll_get_coherency_base) | |||
| 66 | * fabric registers | 66 | * fabric registers |
| 67 | */ | 67 | */ |
| 68 | ENTRY(ll_get_coherency_cpumask) | 68 | ENTRY(ll_get_coherency_cpumask) |
| 69 | mrc 15, 0, r3, cr0, cr0, 5 | 69 | mrc p15, 0, r3, cr0, cr0, 5 |
| 70 | and r3, r3, #15 | 70 | and r3, r3, #15 |
| 71 | mov r2, #(1 << 24) | 71 | mov r2, #(1 << 24) |
| 72 | lsl r3, r2, r3 | 72 | lsl r3, r2, r3 |
diff --git a/arch/arm/mach-mvebu/kirkwood.c b/arch/arm/mach-mvebu/kirkwood.c index 9b5f4d665374..ceaad6d5927e 100644 --- a/arch/arm/mach-mvebu/kirkwood.c +++ b/arch/arm/mach-mvebu/kirkwood.c | |||
| @@ -108,8 +108,6 @@ static void __init kirkwood_dt_eth_fixup(void) | |||
| 108 | clk_prepare_enable(clk); | 108 | clk_prepare_enable(clk); |
| 109 | 109 | ||
| 110 | /* store MAC address register contents in local-mac-address */ | 110 | /* store MAC address register contents in local-mac-address */ |
| 111 | pr_err(FW_INFO "%pOF: local-mac-address is not set\n", np); | ||
| 112 | |||
| 113 | pmac = kzalloc(sizeof(*pmac) + 6, GFP_KERNEL); | 111 | pmac = kzalloc(sizeof(*pmac) + 6, GFP_KERNEL); |
| 114 | if (!pmac) | 112 | if (!pmac) |
| 115 | goto eth_fixup_no_mem; | 113 | goto eth_fixup_no_mem; |
diff --git a/arch/arm/mach-mvebu/pm-board.c b/arch/arm/mach-mvebu/pm-board.c index db17121d7d63..070552511699 100644 --- a/arch/arm/mach-mvebu/pm-board.c +++ b/arch/arm/mach-mvebu/pm-board.c | |||
| @@ -79,7 +79,7 @@ static void mvebu_armada_pm_enter(void __iomem *sdram_reg, u32 srcmd) | |||
| 79 | static int __init mvebu_armada_pm_init(void) | 79 | static int __init mvebu_armada_pm_init(void) |
| 80 | { | 80 | { |
| 81 | struct device_node *np; | 81 | struct device_node *np; |
| 82 | struct device_node *gpio_ctrl_np; | 82 | struct device_node *gpio_ctrl_np = NULL; |
| 83 | int ret = 0, i; | 83 | int ret = 0, i; |
| 84 | 84 | ||
| 85 | if (!of_machine_is_compatible("marvell,axp-gp")) | 85 | if (!of_machine_is_compatible("marvell,axp-gp")) |
| @@ -126,18 +126,23 @@ static int __init mvebu_armada_pm_init(void) | |||
| 126 | goto out; | 126 | goto out; |
| 127 | } | 127 | } |
| 128 | 128 | ||
| 129 | if (gpio_ctrl_np) | ||
| 130 | of_node_put(gpio_ctrl_np); | ||
| 129 | gpio_ctrl_np = args.np; | 131 | gpio_ctrl_np = args.np; |
| 130 | pic_raw_gpios[i] = args.args[0]; | 132 | pic_raw_gpios[i] = args.args[0]; |
| 131 | } | 133 | } |
| 132 | 134 | ||
| 133 | gpio_ctrl = of_iomap(gpio_ctrl_np, 0); | 135 | gpio_ctrl = of_iomap(gpio_ctrl_np, 0); |
| 134 | if (!gpio_ctrl) | 136 | if (!gpio_ctrl) { |
| 135 | return -ENOMEM; | 137 | ret = -ENOMEM; |
| 138 | goto out; | ||
| 139 | } | ||
| 136 | 140 | ||
| 137 | mvebu_pm_suspend_init(mvebu_armada_pm_enter); | 141 | mvebu_pm_suspend_init(mvebu_armada_pm_enter); |
| 138 | 142 | ||
| 139 | out: | 143 | out: |
| 140 | of_node_put(np); | 144 | of_node_put(np); |
| 145 | of_node_put(gpio_ctrl_np); | ||
| 141 | return ret; | 146 | return ret; |
| 142 | } | 147 | } |
| 143 | 148 | ||
diff --git a/arch/arm/mach-mvebu/pmsu_ll.S b/arch/arm/mach-mvebu/pmsu_ll.S index 88651221dbdd..7aae9a25cfeb 100644 --- a/arch/arm/mach-mvebu/pmsu_ll.S +++ b/arch/arm/mach-mvebu/pmsu_ll.S | |||
| @@ -16,7 +16,7 @@ | |||
| 16 | ENTRY(armada_38x_scu_power_up) | 16 | ENTRY(armada_38x_scu_power_up) |
| 17 | mrc p15, 4, r1, c15, c0 @ get SCU base address | 17 | mrc p15, 4, r1, c15, c0 @ get SCU base address |
| 18 | orr r1, r1, #0x8 @ SCU CPU Power Status Register | 18 | orr r1, r1, #0x8 @ SCU CPU Power Status Register |
| 19 | mrc 15, 0, r0, cr0, cr0, 5 @ get the CPU ID | 19 | mrc p15, 0, r0, cr0, cr0, 5 @ get the CPU ID |
| 20 | and r0, r0, #15 | 20 | and r0, r0, #15 |
| 21 | add r1, r1, r0 | 21 | add r1, r1, r0 |
| 22 | mov r0, #0x0 | 22 | mov r0, #0x0 |
| @@ -56,7 +56,6 @@ ENDPROC(armada_38x_cpu_resume) | |||
| 56 | 56 | ||
| 57 | /* The following code will be executed from SRAM */ | 57 | /* The following code will be executed from SRAM */ |
| 58 | ENTRY(mvebu_boot_wa_start) | 58 | ENTRY(mvebu_boot_wa_start) |
| 59 | mvebu_boot_wa_start: | ||
| 60 | ARM_BE8(setend be) | 59 | ARM_BE8(setend be) |
| 61 | adr r0, 1f | 60 | adr r0, 1f |
| 62 | ldr r0, [r0] @ load the address of the | 61 | ldr r0, [r0] @ load the address of the |
diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c index 1b15d593837e..b6e814166ee0 100644 --- a/arch/arm/mach-omap1/board-ams-delta.c +++ b/arch/arm/mach-omap1/board-ams-delta.c | |||
| @@ -749,7 +749,7 @@ static void __init ams_delta_init(void) | |||
| 749 | ARRAY_SIZE(ams_delta_gpio_tables)); | 749 | ARRAY_SIZE(ams_delta_gpio_tables)); |
| 750 | 750 | ||
| 751 | leds_pdev = gpio_led_register_device(PLATFORM_DEVID_NONE, &leds_pdata); | 751 | leds_pdev = gpio_led_register_device(PLATFORM_DEVID_NONE, &leds_pdata); |
| 752 | if (!IS_ERR(leds_pdev)) { | 752 | if (!IS_ERR_OR_NULL(leds_pdev)) { |
| 753 | leds_gpio_table.dev_id = dev_name(&leds_pdev->dev); | 753 | leds_gpio_table.dev_id = dev_name(&leds_pdev->dev); |
| 754 | gpiod_add_lookup_table(&leds_gpio_table); | 754 | gpiod_add_lookup_table(&leds_gpio_table); |
| 755 | } | 755 | } |
diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms index 0f4d91824e4b..42eca656faa8 100644 --- a/arch/arm64/Kconfig.platforms +++ b/arch/arm64/Kconfig.platforms | |||
| @@ -87,6 +87,11 @@ config ARCH_EXYNOS | |||
| 87 | config ARCH_K3 | 87 | config ARCH_K3 |
| 88 | bool "Texas Instruments Inc. K3 multicore SoC architecture" | 88 | bool "Texas Instruments Inc. K3 multicore SoC architecture" |
| 89 | select PM_GENERIC_DOMAINS if PM | 89 | select PM_GENERIC_DOMAINS if PM |
| 90 | select MAILBOX | ||
| 91 | select TI_MESSAGE_MANAGER | ||
| 92 | select TI_SCI_PROTOCOL | ||
| 93 | select TI_SCI_INTR_IRQCHIP | ||
| 94 | select TI_SCI_INTA_IRQCHIP | ||
| 90 | help | 95 | help |
| 91 | This enables support for Texas Instruments' K3 multicore SoC | 96 | This enables support for Texas Instruments' K3 multicore SoC |
| 92 | architecture. | 97 | architecture. |
| @@ -215,6 +220,7 @@ config ARCH_SYNQUACER | |||
| 215 | config ARCH_TEGRA | 220 | config ARCH_TEGRA |
| 216 | bool "NVIDIA Tegra SoC Family" | 221 | bool "NVIDIA Tegra SoC Family" |
| 217 | select ARCH_HAS_RESET_CONTROLLER | 222 | select ARCH_HAS_RESET_CONTROLLER |
| 223 | select ARM_GIC_PM | ||
| 218 | select CLKDEV_LOOKUP | 224 | select CLKDEV_LOOKUP |
| 219 | select CLKSRC_MMIO | 225 | select CLKSRC_MMIO |
| 220 | select TIMER_OF | 226 | select TIMER_OF |
diff --git a/arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts b/arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts index 75ee6cf1e1b4..14d7fea82daf 100644 --- a/arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts +++ b/arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts | |||
| @@ -59,7 +59,7 @@ | |||
| 59 | }; | 59 | }; |
| 60 | 60 | ||
| 61 | padctl@3520000 { | 61 | padctl@3520000 { |
| 62 | status = "okay"; | 62 | status = "disabled"; |
| 63 | 63 | ||
| 64 | avdd-pll-erefeut-supply = <&vdd_1v8_pll>; | 64 | avdd-pll-erefeut-supply = <&vdd_1v8_pll>; |
| 65 | avdd-usb-supply = <&vdd_3v3_sys>; | 65 | avdd-usb-supply = <&vdd_3v3_sys>; |
| @@ -137,7 +137,7 @@ | |||
| 137 | }; | 137 | }; |
| 138 | 138 | ||
| 139 | usb@3530000 { | 139 | usb@3530000 { |
| 140 | status = "okay"; | 140 | status = "disabled"; |
| 141 | 141 | ||
| 142 | phys = <&{/padctl@3520000/pads/usb2/lanes/usb2-0}>, | 142 | phys = <&{/padctl@3520000/pads/usb2/lanes/usb2-0}>, |
| 143 | <&{/padctl@3520000/pads/usb2/lanes/usb2-1}>, | 143 | <&{/padctl@3520000/pads/usb2/lanes/usb2-1}>, |
diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi b/arch/arm64/boot/dts/nvidia/tegra186.dtsi index f0bb6ced4976..426ac0bdf6a6 100644 --- a/arch/arm64/boot/dts/nvidia/tegra186.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi | |||
| @@ -60,6 +60,7 @@ | |||
| 60 | clock-names = "master_bus", "slave_bus", "rx", "tx", "ptp_ref"; | 60 | clock-names = "master_bus", "slave_bus", "rx", "tx", "ptp_ref"; |
| 61 | resets = <&bpmp TEGRA186_RESET_EQOS>; | 61 | resets = <&bpmp TEGRA186_RESET_EQOS>; |
| 62 | reset-names = "eqos"; | 62 | reset-names = "eqos"; |
| 63 | iommus = <&smmu TEGRA186_SID_EQOS>; | ||
| 63 | status = "disabled"; | 64 | status = "disabled"; |
| 64 | 65 | ||
| 65 | snps,write-requests = <1>; | 66 | snps,write-requests = <1>; |
| @@ -338,6 +339,7 @@ | |||
| 338 | <&bpmp TEGRA186_RESET_HDA2CODEC_2X>; | 339 | <&bpmp TEGRA186_RESET_HDA2CODEC_2X>; |
| 339 | reset-names = "hda", "hda2hdmi", "hda2codec_2x"; | 340 | reset-names = "hda", "hda2hdmi", "hda2codec_2x"; |
| 340 | power-domains = <&bpmp TEGRA186_POWER_DOMAIN_DISP>; | 341 | power-domains = <&bpmp TEGRA186_POWER_DOMAIN_DISP>; |
| 342 | iommus = <&smmu TEGRA186_SID_HDA>; | ||
| 341 | status = "disabled"; | 343 | status = "disabled"; |
| 342 | }; | 344 | }; |
| 343 | 345 | ||
| @@ -671,6 +673,10 @@ | |||
| 671 | <&bpmp TEGRA186_RESET_PCIEXCLK>; | 673 | <&bpmp TEGRA186_RESET_PCIEXCLK>; |
| 672 | reset-names = "afi", "pex", "pcie_x"; | 674 | reset-names = "afi", "pex", "pcie_x"; |
| 673 | 675 | ||
| 676 | iommus = <&smmu TEGRA186_SID_AFI>; | ||
| 677 | iommu-map = <0x0 &smmu TEGRA186_SID_AFI 0x1000>; | ||
| 678 | iommu-map-mask = <0x0>; | ||
| 679 | |||
| 674 | status = "disabled"; | 680 | status = "disabled"; |
| 675 | 681 | ||
| 676 | pci@1,0 { | 682 | pci@1,0 { |
| @@ -1158,6 +1164,7 @@ | |||
| 1158 | 1164 | ||
| 1159 | bpmp: bpmp { | 1165 | bpmp: bpmp { |
| 1160 | compatible = "nvidia,tegra186-bpmp"; | 1166 | compatible = "nvidia,tegra186-bpmp"; |
| 1167 | iommus = <&smmu TEGRA186_SID_BPMP>; | ||
| 1161 | mboxes = <&hsp_top0 TEGRA_HSP_MBOX_TYPE_DB | 1168 | mboxes = <&hsp_top0 TEGRA_HSP_MBOX_TYPE_DB |
| 1162 | TEGRA_HSP_DB_MASTER_BPMP>; | 1169 | TEGRA_HSP_DB_MASTER_BPMP>; |
| 1163 | shmem = <&cpu_bpmp_tx &cpu_bpmp_rx>; | 1170 | shmem = <&cpu_bpmp_tx &cpu_bpmp_rx>; |
diff --git a/arch/arm64/boot/dts/sprd/whale2.dtsi b/arch/arm64/boot/dts/sprd/whale2.dtsi index eb6be5675f79..4bb862c6b083 100644 --- a/arch/arm64/boot/dts/sprd/whale2.dtsi +++ b/arch/arm64/boot/dts/sprd/whale2.dtsi | |||
| @@ -75,7 +75,9 @@ | |||
| 75 | "sprd,sc9836-uart"; | 75 | "sprd,sc9836-uart"; |
| 76 | reg = <0x0 0x100>; | 76 | reg = <0x0 0x100>; |
| 77 | interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>; | 77 | interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>; |
| 78 | clocks = <&ext_26m>; | 78 | clock-names = "enable", "uart", "source"; |
| 79 | clocks = <&apapb_gate CLK_UART0_EB>, | ||
| 80 | <&ap_clk CLK_UART0>, <&ext_26m>; | ||
| 79 | status = "disabled"; | 81 | status = "disabled"; |
| 80 | }; | 82 | }; |
| 81 | 83 | ||
| @@ -84,7 +86,9 @@ | |||
| 84 | "sprd,sc9836-uart"; | 86 | "sprd,sc9836-uart"; |
| 85 | reg = <0x100000 0x100>; | 87 | reg = <0x100000 0x100>; |
| 86 | interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>; | 88 | interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>; |
| 87 | clocks = <&ext_26m>; | 89 | clock-names = "enable", "uart", "source"; |
| 90 | clocks = <&apapb_gate CLK_UART1_EB>, | ||
| 91 | <&ap_clk CLK_UART1>, <&ext_26m>; | ||
| 88 | status = "disabled"; | 92 | status = "disabled"; |
| 89 | }; | 93 | }; |
| 90 | 94 | ||
| @@ -93,7 +97,9 @@ | |||
| 93 | "sprd,sc9836-uart"; | 97 | "sprd,sc9836-uart"; |
| 94 | reg = <0x200000 0x100>; | 98 | reg = <0x200000 0x100>; |
| 95 | interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>; | 99 | interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>; |
| 96 | clocks = <&ext_26m>; | 100 | clock-names = "enable", "uart", "source"; |
| 101 | clocks = <&apapb_gate CLK_UART2_EB>, | ||
| 102 | <&ap_clk CLK_UART2>, <&ext_26m>; | ||
| 97 | status = "disabled"; | 103 | status = "disabled"; |
| 98 | }; | 104 | }; |
| 99 | 105 | ||
| @@ -102,7 +108,9 @@ | |||
| 102 | "sprd,sc9836-uart"; | 108 | "sprd,sc9836-uart"; |
| 103 | reg = <0x300000 0x100>; | 109 | reg = <0x300000 0x100>; |
| 104 | interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>; | 110 | interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>; |
| 105 | clocks = <&ext_26m>; | 111 | clock-names = "enable", "uart", "source"; |
| 112 | clocks = <&apapb_gate CLK_UART3_EB>, | ||
| 113 | <&ap_clk CLK_UART3>, <&ext_26m>; | ||
| 106 | status = "disabled"; | 114 | status = "disabled"; |
| 107 | }; | 115 | }; |
| 108 | }; | 116 | }; |
diff --git a/arch/csky/boot/dts/include/dt-bindings b/arch/csky/boot/dts/include/dt-bindings deleted file mode 120000 index 08c00e4972fa..000000000000 --- a/arch/csky/boot/dts/include/dt-bindings +++ /dev/null | |||
| @@ -1 +0,0 @@ | |||
| 1 | ../../../../../include/dt-bindings \ No newline at end of file | ||
diff --git a/arch/csky/include/asm/Kbuild b/arch/csky/include/asm/Kbuild index a9b63efef416..c1a6c0f31150 100644 --- a/arch/csky/include/asm/Kbuild +++ b/arch/csky/include/asm/Kbuild | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | generic-y += asm-offsets.h | 1 | generic-y += asm-offsets.h |
| 2 | generic-y += bugs.h | 2 | generic-y += bugs.h |
| 3 | generic-y += clkdev.h | ||
| 4 | generic-y += compat.h | 3 | generic-y += compat.h |
| 5 | generic-y += current.h | 4 | generic-y += current.h |
| 6 | generic-y += delay.h | 5 | generic-y += delay.h |
| @@ -29,15 +28,12 @@ generic-y += local64.h | |||
| 29 | generic-y += mm-arch-hooks.h | 28 | generic-y += mm-arch-hooks.h |
| 30 | generic-y += mmiowb.h | 29 | generic-y += mmiowb.h |
| 31 | generic-y += module.h | 30 | generic-y += module.h |
| 32 | generic-y += mutex.h | ||
| 33 | generic-y += pci.h | 31 | generic-y += pci.h |
| 34 | generic-y += percpu.h | 32 | generic-y += percpu.h |
| 35 | generic-y += preempt.h | 33 | generic-y += preempt.h |
| 36 | generic-y += qrwlock.h | 34 | generic-y += qrwlock.h |
| 37 | generic-y += scatterlist.h | ||
| 38 | generic-y += sections.h | 35 | generic-y += sections.h |
| 39 | generic-y += serial.h | 36 | generic-y += serial.h |
| 40 | generic-y += shm.h | ||
| 41 | generic-y += timex.h | 37 | generic-y += timex.h |
| 42 | generic-y += topology.h | 38 | generic-y += topology.h |
| 43 | generic-y += trace_clock.h | 39 | generic-y += trace_clock.h |
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild index 79cd1e605ec4..789214ac99bf 100644 --- a/arch/h8300/include/asm/Kbuild +++ b/arch/h8300/include/asm/Kbuild | |||
| @@ -38,7 +38,6 @@ generic-y += pci.h | |||
| 38 | generic-y += percpu.h | 38 | generic-y += percpu.h |
| 39 | generic-y += pgalloc.h | 39 | generic-y += pgalloc.h |
| 40 | generic-y += preempt.h | 40 | generic-y += preempt.h |
| 41 | generic-y += scatterlist.h | ||
| 42 | generic-y += sections.h | 41 | generic-y += sections.h |
| 43 | generic-y += serial.h | 42 | generic-y += serial.h |
| 44 | generic-y += shmparam.h | 43 | generic-y += shmparam.h |
diff --git a/arch/ia64/kernel/Makefile.gate b/arch/ia64/kernel/Makefile.gate index f53faf48b7ce..846867bff6d6 100644 --- a/arch/ia64/kernel/Makefile.gate +++ b/arch/ia64/kernel/Makefile.gate | |||
| @@ -11,7 +11,7 @@ quiet_cmd_gate = GATE $@ | |||
| 11 | cmd_gate = $(CC) -nostdlib $(GATECFLAGS_$(@F)) -Wl,-T,$(filter-out FORCE,$^) -o $@ | 11 | cmd_gate = $(CC) -nostdlib $(GATECFLAGS_$(@F)) -Wl,-T,$(filter-out FORCE,$^) -o $@ |
| 12 | 12 | ||
| 13 | GATECFLAGS_gate.so = -shared -s -Wl,-soname=linux-gate.so.1 \ | 13 | GATECFLAGS_gate.so = -shared -s -Wl,-soname=linux-gate.so.1 \ |
| 14 | $(call cc-ldoption, -Wl$(comma)--hash-style=sysv) | 14 | -Wl,--hash-style=sysv |
| 15 | $(obj)/gate.so: $(obj)/gate.lds $(obj)/gate.o FORCE | 15 | $(obj)/gate.so: $(obj)/gate.lds $(obj)/gate.o FORCE |
| 16 | $(call if_changed,gate) | 16 | $(call if_changed,gate) |
| 17 | 17 | ||
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 677e5bfeff47..70d3200476bf 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig | |||
| @@ -674,7 +674,10 @@ config SGI_IP27 | |||
| 674 | select SYS_HAS_EARLY_PRINTK | 674 | select SYS_HAS_EARLY_PRINTK |
| 675 | select HAVE_PCI | 675 | select HAVE_PCI |
| 676 | select IRQ_MIPS_CPU | 676 | select IRQ_MIPS_CPU |
| 677 | select IRQ_DOMAIN_HIERARCHY | ||
| 677 | select NR_CPUS_DEFAULT_64 | 678 | select NR_CPUS_DEFAULT_64 |
| 679 | select PCI_DRIVERS_GENERIC | ||
| 680 | select PCI_XTALK_BRIDGE | ||
| 678 | select SYS_HAS_CPU_R10000 | 681 | select SYS_HAS_CPU_R10000 |
| 679 | select SYS_SUPPORTS_64BIT_KERNEL | 682 | select SYS_SUPPORTS_64BIT_KERNEL |
| 680 | select SYS_SUPPORTS_BIG_ENDIAN | 683 | select SYS_SUPPORTS_BIG_ENDIAN |
| @@ -1241,6 +1244,9 @@ config IRQ_GT641XX | |||
| 1241 | config PCI_GT64XXX_PCI0 | 1244 | config PCI_GT64XXX_PCI0 |
| 1242 | bool | 1245 | bool |
| 1243 | 1246 | ||
| 1247 | config PCI_XTALK_BRIDGE | ||
| 1248 | bool | ||
| 1249 | |||
| 1244 | config NO_EXCEPT_FILL | 1250 | config NO_EXCEPT_FILL |
| 1245 | bool | 1251 | bool |
| 1246 | 1252 | ||
diff --git a/arch/mips/alchemy/common/platform.c b/arch/mips/alchemy/common/platform.c index 1454d9f6ab2d..b8f3397c59c9 100644 --- a/arch/mips/alchemy/common/platform.c +++ b/arch/mips/alchemy/common/platform.c | |||
| @@ -131,9 +131,7 @@ static void __init alchemy_setup_uarts(int ctype) | |||
| 131 | } | 131 | } |
| 132 | 132 | ||
| 133 | 133 | ||
| 134 | /* The dmamask must be set for OHCI/EHCI to work */ | 134 | static u64 alchemy_all_dmamask = DMA_BIT_MASK(32); |
| 135 | static u64 alchemy_ohci_dmamask = DMA_BIT_MASK(32); | ||
| 136 | static u64 __maybe_unused alchemy_ehci_dmamask = DMA_BIT_MASK(32); | ||
| 137 | 135 | ||
| 138 | /* Power on callback for the ehci platform driver */ | 136 | /* Power on callback for the ehci platform driver */ |
| 139 | static int alchemy_ehci_power_on(struct platform_device *pdev) | 137 | static int alchemy_ehci_power_on(struct platform_device *pdev) |
| @@ -231,7 +229,7 @@ static void __init alchemy_setup_usb(int ctype) | |||
| 231 | res[1].flags = IORESOURCE_IRQ; | 229 | res[1].flags = IORESOURCE_IRQ; |
| 232 | pdev->name = "ohci-platform"; | 230 | pdev->name = "ohci-platform"; |
| 233 | pdev->id = 0; | 231 | pdev->id = 0; |
| 234 | pdev->dev.dma_mask = &alchemy_ohci_dmamask; | 232 | pdev->dev.dma_mask = &alchemy_all_dmamask; |
| 235 | pdev->dev.platform_data = &alchemy_ohci_pdata; | 233 | pdev->dev.platform_data = &alchemy_ohci_pdata; |
| 236 | 234 | ||
| 237 | if (platform_device_register(pdev)) | 235 | if (platform_device_register(pdev)) |
| @@ -251,7 +249,7 @@ static void __init alchemy_setup_usb(int ctype) | |||
| 251 | res[1].flags = IORESOURCE_IRQ; | 249 | res[1].flags = IORESOURCE_IRQ; |
| 252 | pdev->name = "ehci-platform"; | 250 | pdev->name = "ehci-platform"; |
| 253 | pdev->id = 0; | 251 | pdev->id = 0; |
| 254 | pdev->dev.dma_mask = &alchemy_ehci_dmamask; | 252 | pdev->dev.dma_mask = &alchemy_all_dmamask; |
| 255 | pdev->dev.platform_data = &alchemy_ehci_pdata; | 253 | pdev->dev.platform_data = &alchemy_ehci_pdata; |
| 256 | 254 | ||
| 257 | if (platform_device_register(pdev)) | 255 | if (platform_device_register(pdev)) |
| @@ -271,7 +269,7 @@ static void __init alchemy_setup_usb(int ctype) | |||
| 271 | res[1].flags = IORESOURCE_IRQ; | 269 | res[1].flags = IORESOURCE_IRQ; |
| 272 | pdev->name = "ohci-platform"; | 270 | pdev->name = "ohci-platform"; |
| 273 | pdev->id = 1; | 271 | pdev->id = 1; |
| 274 | pdev->dev.dma_mask = &alchemy_ohci_dmamask; | 272 | pdev->dev.dma_mask = &alchemy_all_dmamask; |
| 275 | pdev->dev.platform_data = &alchemy_ohci_pdata; | 273 | pdev->dev.platform_data = &alchemy_ohci_pdata; |
| 276 | 274 | ||
| 277 | if (platform_device_register(pdev)) | 275 | if (platform_device_register(pdev)) |
| @@ -338,7 +336,11 @@ static struct platform_device au1xxx_eth0_device = { | |||
| 338 | .name = "au1000-eth", | 336 | .name = "au1000-eth", |
| 339 | .id = 0, | 337 | .id = 0, |
| 340 | .num_resources = MAC_RES_COUNT, | 338 | .num_resources = MAC_RES_COUNT, |
| 341 | .dev.platform_data = &au1xxx_eth0_platform_data, | 339 | .dev = { |
| 340 | .dma_mask = &alchemy_all_dmamask, | ||
| 341 | .coherent_dma_mask = DMA_BIT_MASK(32), | ||
| 342 | .platform_data = &au1xxx_eth0_platform_data, | ||
| 343 | }, | ||
| 342 | }; | 344 | }; |
| 343 | 345 | ||
| 344 | static struct resource au1xxx_eth1_resources[][MAC_RES_COUNT] __initdata = { | 346 | static struct resource au1xxx_eth1_resources[][MAC_RES_COUNT] __initdata = { |
| @@ -370,7 +372,11 @@ static struct platform_device au1xxx_eth1_device = { | |||
| 370 | .name = "au1000-eth", | 372 | .name = "au1000-eth", |
| 371 | .id = 1, | 373 | .id = 1, |
| 372 | .num_resources = MAC_RES_COUNT, | 374 | .num_resources = MAC_RES_COUNT, |
| 373 | .dev.platform_data = &au1xxx_eth1_platform_data, | 375 | .dev = { |
| 376 | .dma_mask = &alchemy_all_dmamask, | ||
| 377 | .coherent_dma_mask = DMA_BIT_MASK(32), | ||
| 378 | .platform_data = &au1xxx_eth1_platform_data, | ||
| 379 | }, | ||
| 374 | }; | 380 | }; |
| 375 | 381 | ||
| 376 | void __init au1xxx_override_eth_cfg(unsigned int port, | 382 | void __init au1xxx_override_eth_cfg(unsigned int port, |
diff --git a/arch/mips/generic/init.c b/arch/mips/generic/init.c index a106f8113842..a84475f1924f 100644 --- a/arch/mips/generic/init.c +++ b/arch/mips/generic/init.c | |||
| @@ -43,14 +43,14 @@ void __init *plat_get_fdt(void) | |||
| 43 | /* Already set up */ | 43 | /* Already set up */ |
| 44 | return (void *)fdt; | 44 | return (void *)fdt; |
| 45 | 45 | ||
| 46 | if ((fw_arg0 == -2) && !fdt_check_header((void *)fw_arg1)) { | 46 | if ((fw_arg0 == -2) && !fdt_check_header((void *)fw_passed_dtb)) { |
| 47 | /* | 47 | /* |
| 48 | * We booted using the UHI boot protocol, so we have been | 48 | * We booted using the UHI boot protocol, so we have been |
| 49 | * provided with the appropriate device tree for the board. | 49 | * provided with the appropriate device tree for the board. |
| 50 | * Make use of it & search for any machine struct based upon | 50 | * Make use of it & search for any machine struct based upon |
| 51 | * the root compatible string. | 51 | * the root compatible string. |
| 52 | */ | 52 | */ |
| 53 | fdt = (void *)fw_arg1; | 53 | fdt = (void *)fw_passed_dtb; |
| 54 | 54 | ||
| 55 | for_each_mips_machine(check_mach) { | 55 | for_each_mips_machine(check_mach) { |
| 56 | match = mips_machine_is_compatible(check_mach, fdt); | 56 | match = mips_machine_is_compatible(check_mach, fdt); |
diff --git a/arch/mips/include/asm/mach-ip27/topology.h b/arch/mips/include/asm/mach-ip27/topology.h index 42ea1313626c..965f0793a5f9 100644 --- a/arch/mips/include/asm/mach-ip27/topology.h +++ b/arch/mips/include/asm/mach-ip27/topology.h | |||
| @@ -7,18 +7,9 @@ | |||
| 7 | #include <asm/mmzone.h> | 7 | #include <asm/mmzone.h> |
| 8 | 8 | ||
| 9 | struct cpuinfo_ip27 { | 9 | struct cpuinfo_ip27 { |
| 10 | // cpuid_t p_cpuid; /* PROM assigned cpuid */ | ||
| 11 | cnodeid_t p_nodeid; /* my node ID in compact-id-space */ | 10 | cnodeid_t p_nodeid; /* my node ID in compact-id-space */ |
| 12 | nasid_t p_nasid; /* my node ID in numa-as-id-space */ | 11 | nasid_t p_nasid; /* my node ID in numa-as-id-space */ |
| 13 | unsigned char p_slice; /* Physical position on node board */ | 12 | unsigned char p_slice; /* Physical position on node board */ |
| 14 | #if 0 | ||
| 15 | unsigned long loops_per_sec; | ||
| 16 | unsigned long ipi_count; | ||
| 17 | unsigned long irq_attempt[NR_IRQS]; | ||
| 18 | unsigned long smp_local_irq_count; | ||
| 19 | unsigned long prof_multiplier; | ||
| 20 | unsigned long prof_counter; | ||
| 21 | #endif | ||
| 22 | }; | 13 | }; |
| 23 | 14 | ||
| 24 | extern struct cpuinfo_ip27 sn_cpu_info[NR_CPUS]; | 15 | extern struct cpuinfo_ip27 sn_cpu_info[NR_CPUS]; |
| @@ -30,7 +21,7 @@ extern struct cpuinfo_ip27 sn_cpu_info[NR_CPUS]; | |||
| 30 | struct pci_bus; | 21 | struct pci_bus; |
| 31 | extern int pcibus_to_node(struct pci_bus *); | 22 | extern int pcibus_to_node(struct pci_bus *); |
| 32 | 23 | ||
| 33 | #define cpumask_of_pcibus(bus) (cpu_online_mask) | 24 | #define cpumask_of_pcibus(bus) (cpumask_of_node(pcibus_to_node(bus))) |
| 34 | 25 | ||
| 35 | extern unsigned char __node_distances[MAX_COMPACT_NODES][MAX_COMPACT_NODES]; | 26 | extern unsigned char __node_distances[MAX_COMPACT_NODES][MAX_COMPACT_NODES]; |
| 36 | 27 | ||
diff --git a/arch/mips/include/asm/pci/bridge.h b/arch/mips/include/asm/pci/bridge.h index 23574c27eb40..a92cd30b48c9 100644 --- a/arch/mips/include/asm/pci/bridge.h +++ b/arch/mips/include/asm/pci/bridge.h | |||
| @@ -801,15 +801,13 @@ struct bridge_err_cmdword { | |||
| 801 | #define PCI64_ATTR_RMF_SHFT 48 | 801 | #define PCI64_ATTR_RMF_SHFT 48 |
| 802 | 802 | ||
| 803 | struct bridge_controller { | 803 | struct bridge_controller { |
| 804 | struct pci_controller pc; | ||
| 805 | struct resource mem; | ||
| 806 | struct resource io; | ||
| 807 | struct resource busn; | 804 | struct resource busn; |
| 808 | struct bridge_regs *base; | 805 | struct bridge_regs *base; |
| 809 | nasid_t nasid; | 806 | unsigned long baddr; |
| 810 | unsigned int widget_id; | 807 | unsigned long intr_addr; |
| 811 | u64 baddr; | 808 | struct irq_domain *domain; |
| 812 | unsigned int pci_int[8]; | 809 | unsigned int pci_int[8]; |
| 810 | nasid_t nasid; | ||
| 813 | }; | 811 | }; |
| 814 | 812 | ||
| 815 | #define BRIDGE_CONTROLLER(bus) \ | 813 | #define BRIDGE_CONTROLLER(bus) \ |
| @@ -822,8 +820,4 @@ struct bridge_controller { | |||
| 822 | #define bridge_clr(bc, reg, val) \ | 820 | #define bridge_clr(bc, reg, val) \ |
| 823 | __raw_writel(__raw_readl(&bc->base->reg) & ~(val), &bc->base->reg) | 821 | __raw_writel(__raw_readl(&bc->base->reg) & ~(val), &bc->base->reg) |
| 824 | 822 | ||
| 825 | extern int request_bridge_irq(struct bridge_controller *bc, int pin); | ||
| 826 | |||
| 827 | extern struct pci_ops bridge_pci_ops; | ||
| 828 | |||
| 829 | #endif /* _ASM_PCI_BRIDGE_H */ | 823 | #endif /* _ASM_PCI_BRIDGE_H */ |
diff --git a/arch/mips/include/asm/sn/irq_alloc.h b/arch/mips/include/asm/sn/irq_alloc.h new file mode 100644 index 000000000000..09b89cecff56 --- /dev/null +++ b/arch/mips/include/asm/sn/irq_alloc.h | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | #ifndef __ASM_SN_IRQ_ALLOC_H | ||
| 3 | #define __ASM_SN_IRQ_ALLOC_H | ||
| 4 | |||
| 5 | struct irq_alloc_info { | ||
| 6 | void *ctrl; | ||
| 7 | nasid_t nasid; | ||
| 8 | int pin; | ||
| 9 | }; | ||
| 10 | |||
| 11 | #endif /* __ASM_SN_IRQ_ALLOC_H */ | ||
diff --git a/arch/mips/include/asm/xtalk/xtalk.h b/arch/mips/include/asm/xtalk/xtalk.h index 26d2ed1fa917..680e7efebbaf 100644 --- a/arch/mips/include/asm/xtalk/xtalk.h +++ b/arch/mips/include/asm/xtalk/xtalk.h | |||
| @@ -47,15 +47,6 @@ typedef struct xtalk_piomap_s *xtalk_piomap_t; | |||
| 47 | #define XIO_PORT(x) ((xwidgetnum_t)(((x)&XIO_PORT_BITS) >> XIO_PORT_SHIFT)) | 47 | #define XIO_PORT(x) ((xwidgetnum_t)(((x)&XIO_PORT_BITS) >> XIO_PORT_SHIFT)) |
| 48 | #define XIO_PACK(p, o) ((((uint64_t)(p))<<XIO_PORT_SHIFT) | ((o)&XIO_ADDR_BITS)) | 48 | #define XIO_PACK(p, o) ((((uint64_t)(p))<<XIO_PORT_SHIFT) | ((o)&XIO_ADDR_BITS)) |
| 49 | 49 | ||
| 50 | #ifdef CONFIG_PCI | ||
| 51 | extern int bridge_probe(nasid_t nasid, int widget, int masterwid); | ||
| 52 | #else | ||
| 53 | static inline int bridge_probe(nasid_t nasid, int widget, int masterwid) | ||
| 54 | { | ||
| 55 | return 0; | ||
| 56 | } | ||
| 57 | #endif | ||
| 58 | |||
| 59 | #endif /* !__ASSEMBLY__ */ | 50 | #endif /* !__ASSEMBLY__ */ |
| 60 | 51 | ||
| 61 | #endif /* _ASM_XTALK_XTALK_H */ | 52 | #endif /* _ASM_XTALK_XTALK_H */ |
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index d5e335e6846a..6126b77d5a62 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c | |||
| @@ -1973,6 +1973,14 @@ static inline void cpu_probe_ingenic(struct cpuinfo_mips *c, unsigned int cpu) | |||
| 1973 | panic("Unknown Ingenic Processor ID!"); | 1973 | panic("Unknown Ingenic Processor ID!"); |
| 1974 | break; | 1974 | break; |
| 1975 | } | 1975 | } |
| 1976 | |||
| 1977 | /* | ||
| 1978 | * The config0 register in the Xburst CPUs with a processor ID of | ||
| 1979 | * PRID_COMP_INGENIC_D0 report themselves as MIPS32r2 compatible, | ||
| 1980 | * but they don't actually support this ISA. | ||
| 1981 | */ | ||
| 1982 | if ((c->processor_id & PRID_COMP_MASK) == PRID_COMP_INGENIC_D0) | ||
| 1983 | c->isa_level &= ~MIPS_CPU_ISA_M32R2; | ||
| 1976 | } | 1984 | } |
| 1977 | 1985 | ||
| 1978 | static inline void cpu_probe_netlogic(struct cpuinfo_mips *c, int cpu) | 1986 | static inline void cpu_probe_netlogic(struct cpuinfo_mips *c, int cpu) |
diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c index 413863508f6f..d67fb64e908c 100644 --- a/arch/mips/kernel/perf_event_mipsxx.c +++ b/arch/mips/kernel/perf_event_mipsxx.c | |||
| @@ -64,17 +64,11 @@ struct mips_perf_event { | |||
| 64 | #define CNTR_EVEN 0x55555555 | 64 | #define CNTR_EVEN 0x55555555 |
| 65 | #define CNTR_ODD 0xaaaaaaaa | 65 | #define CNTR_ODD 0xaaaaaaaa |
| 66 | #define CNTR_ALL 0xffffffff | 66 | #define CNTR_ALL 0xffffffff |
| 67 | #ifdef CONFIG_MIPS_MT_SMP | ||
| 68 | enum { | 67 | enum { |
| 69 | T = 0, | 68 | T = 0, |
| 70 | V = 1, | 69 | V = 1, |
| 71 | P = 2, | 70 | P = 2, |
| 72 | } range; | 71 | } range; |
| 73 | #else | ||
| 74 | #define T | ||
| 75 | #define V | ||
| 76 | #define P | ||
| 77 | #endif | ||
| 78 | }; | 72 | }; |
| 79 | 73 | ||
| 80 | static struct mips_perf_event raw_event; | 74 | static struct mips_perf_event raw_event; |
| @@ -325,9 +319,7 @@ static void mipsxx_pmu_enable_event(struct hw_perf_event *evt, int idx) | |||
| 325 | { | 319 | { |
| 326 | struct perf_event *event = container_of(evt, struct perf_event, hw); | 320 | struct perf_event *event = container_of(evt, struct perf_event, hw); |
| 327 | struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); | 321 | struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); |
| 328 | #ifdef CONFIG_MIPS_MT_SMP | ||
| 329 | unsigned int range = evt->event_base >> 24; | 322 | unsigned int range = evt->event_base >> 24; |
| 330 | #endif /* CONFIG_MIPS_MT_SMP */ | ||
| 331 | 323 | ||
| 332 | WARN_ON(idx < 0 || idx >= mipspmu.num_counters); | 324 | WARN_ON(idx < 0 || idx >= mipspmu.num_counters); |
| 333 | 325 | ||
| @@ -336,21 +328,15 @@ static void mipsxx_pmu_enable_event(struct hw_perf_event *evt, int idx) | |||
| 336 | /* Make sure interrupt enabled. */ | 328 | /* Make sure interrupt enabled. */ |
| 337 | MIPS_PERFCTRL_IE; | 329 | MIPS_PERFCTRL_IE; |
| 338 | 330 | ||
| 339 | #ifdef CONFIG_CPU_BMIPS5000 | 331 | if (IS_ENABLED(CONFIG_CPU_BMIPS5000)) { |
| 340 | { | ||
| 341 | /* enable the counter for the calling thread */ | 332 | /* enable the counter for the calling thread */ |
| 342 | cpuc->saved_ctrl[idx] |= | 333 | cpuc->saved_ctrl[idx] |= |
| 343 | (1 << (12 + vpe_id())) | BRCM_PERFCTRL_TC; | 334 | (1 << (12 + vpe_id())) | BRCM_PERFCTRL_TC; |
| 344 | } | 335 | } else if (IS_ENABLED(CONFIG_MIPS_MT_SMP) && range > V) { |
| 345 | #else | ||
| 346 | #ifdef CONFIG_MIPS_MT_SMP | ||
| 347 | if (range > V) { | ||
| 348 | /* The counter is processor wide. Set it up to count all TCs. */ | 336 | /* The counter is processor wide. Set it up to count all TCs. */ |
| 349 | pr_debug("Enabling perf counter for all TCs\n"); | 337 | pr_debug("Enabling perf counter for all TCs\n"); |
| 350 | cpuc->saved_ctrl[idx] |= M_TC_EN_ALL; | 338 | cpuc->saved_ctrl[idx] |= M_TC_EN_ALL; |
| 351 | } else | 339 | } else { |
| 352 | #endif /* CONFIG_MIPS_MT_SMP */ | ||
| 353 | { | ||
| 354 | unsigned int cpu, ctrl; | 340 | unsigned int cpu, ctrl; |
| 355 | 341 | ||
| 356 | /* | 342 | /* |
| @@ -365,7 +351,6 @@ static void mipsxx_pmu_enable_event(struct hw_perf_event *evt, int idx) | |||
| 365 | cpuc->saved_ctrl[idx] |= ctrl; | 351 | cpuc->saved_ctrl[idx] |= ctrl; |
| 366 | pr_debug("Enabling perf counter for CPU%d\n", cpu); | 352 | pr_debug("Enabling perf counter for CPU%d\n", cpu); |
| 367 | } | 353 | } |
| 368 | #endif /* CONFIG_CPU_BMIPS5000 */ | ||
| 369 | /* | 354 | /* |
| 370 | * We do not actually let the counter run. Leave it until start(). | 355 | * We do not actually let the counter run. Leave it until start(). |
| 371 | */ | 356 | */ |
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile index c4f976593061..d6de4cb2e31c 100644 --- a/arch/mips/pci/Makefile +++ b/arch/mips/pci/Makefile | |||
| @@ -26,6 +26,7 @@ obj-$(CONFIG_PCI_AR2315) += pci-ar2315.o | |||
| 26 | obj-$(CONFIG_SOC_AR71XX) += pci-ar71xx.o | 26 | obj-$(CONFIG_SOC_AR71XX) += pci-ar71xx.o |
| 27 | obj-$(CONFIG_PCI_AR724X) += pci-ar724x.o | 27 | obj-$(CONFIG_PCI_AR724X) += pci-ar724x.o |
| 28 | obj-$(CONFIG_MIPS_PCI_VIRTIO) += pci-virtio-guest.o | 28 | obj-$(CONFIG_MIPS_PCI_VIRTIO) += pci-virtio-guest.o |
| 29 | obj-$(CONFIG_PCI_XTALK_BRIDGE) += pci-xtalk-bridge.o | ||
| 29 | # | 30 | # |
| 30 | # These are still pretty much in the old state, watch, go blind. | 31 | # These are still pretty much in the old state, watch, go blind. |
| 31 | # | 32 | # |
| @@ -39,7 +40,7 @@ obj-$(CONFIG_MIPS_MALTA) += fixup-malta.o pci-malta.o | |||
| 39 | obj-$(CONFIG_PMC_MSP7120_GW) += fixup-pmcmsp.o ops-pmcmsp.o | 40 | obj-$(CONFIG_PMC_MSP7120_GW) += fixup-pmcmsp.o ops-pmcmsp.o |
| 40 | obj-$(CONFIG_PMC_MSP7120_EVAL) += fixup-pmcmsp.o ops-pmcmsp.o | 41 | obj-$(CONFIG_PMC_MSP7120_EVAL) += fixup-pmcmsp.o ops-pmcmsp.o |
| 41 | obj-$(CONFIG_PMC_MSP7120_FPGA) += fixup-pmcmsp.o ops-pmcmsp.o | 42 | obj-$(CONFIG_PMC_MSP7120_FPGA) += fixup-pmcmsp.o ops-pmcmsp.o |
| 42 | obj-$(CONFIG_SGI_IP27) += ops-bridge.o pci-ip27.o | 43 | obj-$(CONFIG_SGI_IP27) += pci-ip27.o |
| 43 | obj-$(CONFIG_SGI_IP32) += fixup-ip32.o ops-mace.o pci-ip32.o | 44 | obj-$(CONFIG_SGI_IP32) += fixup-ip32.o ops-mace.o pci-ip32.o |
| 44 | obj-$(CONFIG_SIBYTE_SB1250) += fixup-sb1250.o pci-sb1250.o | 45 | obj-$(CONFIG_SIBYTE_SB1250) += fixup-sb1250.o pci-sb1250.o |
| 45 | obj-$(CONFIG_SIBYTE_BCM112X) += fixup-sb1250.o pci-sb1250.o | 46 | obj-$(CONFIG_SIBYTE_BCM112X) += fixup-sb1250.o pci-sb1250.o |
diff --git a/arch/mips/pci/ops-bridge.c b/arch/mips/pci/ops-bridge.c deleted file mode 100644 index df95b0da08f2..000000000000 --- a/arch/mips/pci/ops-bridge.c +++ /dev/null | |||
| @@ -1,302 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 3 | * License. See the file "COPYING" in the main directory of this archive | ||
| 4 | * for more details. | ||
| 5 | * | ||
| 6 | * Copyright (C) 1999, 2000, 04, 06 Ralf Baechle (ralf@linux-mips.org) | ||
| 7 | * Copyright (C) 1999, 2000 Silicon Graphics, Inc. | ||
| 8 | */ | ||
| 9 | #include <linux/pci.h> | ||
| 10 | #include <asm/paccess.h> | ||
| 11 | #include <asm/pci/bridge.h> | ||
| 12 | #include <asm/sn/arch.h> | ||
| 13 | #include <asm/sn/intr.h> | ||
| 14 | #include <asm/sn/sn0/hub.h> | ||
| 15 | |||
| 16 | /* | ||
| 17 | * Most of the IOC3 PCI config register aren't present | ||
| 18 | * we emulate what is needed for a normal PCI enumeration | ||
| 19 | */ | ||
| 20 | static u32 emulate_ioc3_cfg(int where, int size) | ||
| 21 | { | ||
| 22 | if (size == 1 && where == 0x3d) | ||
| 23 | return 0x01; | ||
| 24 | else if (size == 2 && where == 0x3c) | ||
| 25 | return 0x0100; | ||
| 26 | else if (size == 4 && where == 0x3c) | ||
| 27 | return 0x00000100; | ||
| 28 | |||
| 29 | return 0; | ||
| 30 | } | ||
| 31 | |||
| 32 | /* | ||
| 33 | * The Bridge ASIC supports both type 0 and type 1 access. Type 1 is | ||
| 34 | * not really documented, so right now I can't write code which uses it. | ||
| 35 | * Therefore we use type 0 accesses for now even though they won't work | ||
| 36 | * correctly for PCI-to-PCI bridges. | ||
| 37 | * | ||
| 38 | * The function is complicated by the ultimate brokenness of the IOC3 chip | ||
| 39 | * which is used in SGI systems. The IOC3 can only handle 32-bit PCI | ||
| 40 | * accesses and does only decode parts of it's address space. | ||
| 41 | */ | ||
| 42 | |||
| 43 | static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn, | ||
| 44 | int where, int size, u32 * value) | ||
| 45 | { | ||
| 46 | struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); | ||
| 47 | struct bridge_regs *bridge = bc->base; | ||
| 48 | int slot = PCI_SLOT(devfn); | ||
| 49 | int fn = PCI_FUNC(devfn); | ||
| 50 | volatile void *addr; | ||
| 51 | u32 cf, shift, mask; | ||
| 52 | int res; | ||
| 53 | |||
| 54 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID]; | ||
| 55 | if (get_dbe(cf, (u32 *) addr)) | ||
| 56 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 57 | |||
| 58 | /* | ||
| 59 | * IOC3 is broken beyond belief ... Don't even give the | ||
| 60 | * generic PCI code a chance to look at it for real ... | ||
| 61 | */ | ||
| 62 | if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) | ||
| 63 | goto is_ioc3; | ||
| 64 | |||
| 65 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)]; | ||
| 66 | |||
| 67 | if (size == 1) | ||
| 68 | res = get_dbe(*value, (u8 *) addr); | ||
| 69 | else if (size == 2) | ||
| 70 | res = get_dbe(*value, (u16 *) addr); | ||
| 71 | else | ||
| 72 | res = get_dbe(*value, (u32 *) addr); | ||
| 73 | |||
| 74 | return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; | ||
| 75 | |||
| 76 | is_ioc3: | ||
| 77 | |||
| 78 | /* | ||
| 79 | * IOC3 special handling | ||
| 80 | */ | ||
| 81 | if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) { | ||
| 82 | *value = emulate_ioc3_cfg(where, size); | ||
| 83 | return PCIBIOS_SUCCESSFUL; | ||
| 84 | } | ||
| 85 | |||
| 86 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; | ||
| 87 | |||
| 88 | if (get_dbe(cf, (u32 *) addr)) | ||
| 89 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 90 | |||
| 91 | shift = ((where & 3) << 3); | ||
| 92 | mask = (0xffffffffU >> ((4 - size) << 3)); | ||
| 93 | *value = (cf >> shift) & mask; | ||
| 94 | |||
| 95 | return PCIBIOS_SUCCESSFUL; | ||
| 96 | } | ||
| 97 | |||
| 98 | static int pci_conf1_read_config(struct pci_bus *bus, unsigned int devfn, | ||
| 99 | int where, int size, u32 * value) | ||
| 100 | { | ||
| 101 | struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); | ||
| 102 | struct bridge_regs *bridge = bc->base; | ||
| 103 | int busno = bus->number; | ||
| 104 | int slot = PCI_SLOT(devfn); | ||
| 105 | int fn = PCI_FUNC(devfn); | ||
| 106 | volatile void *addr; | ||
| 107 | u32 cf, shift, mask; | ||
| 108 | int res; | ||
| 109 | |||
| 110 | bridge_write(bc, b_pci_cfg, (busno << 16) | (slot << 11)); | ||
| 111 | addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID]; | ||
| 112 | if (get_dbe(cf, (u32 *) addr)) | ||
| 113 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 114 | |||
| 115 | /* | ||
| 116 | * IOC3 is broken beyond belief ... Don't even give the | ||
| 117 | * generic PCI code a chance to look at it for real ... | ||
| 118 | */ | ||
| 119 | if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) | ||
| 120 | goto is_ioc3; | ||
| 121 | |||
| 122 | bridge_write(bc, b_pci_cfg, (busno << 16) | (slot << 11)); | ||
| 123 | addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))]; | ||
| 124 | |||
| 125 | if (size == 1) | ||
| 126 | res = get_dbe(*value, (u8 *) addr); | ||
| 127 | else if (size == 2) | ||
| 128 | res = get_dbe(*value, (u16 *) addr); | ||
| 129 | else | ||
| 130 | res = get_dbe(*value, (u32 *) addr); | ||
| 131 | |||
| 132 | return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; | ||
| 133 | |||
| 134 | is_ioc3: | ||
| 135 | |||
| 136 | /* | ||
| 137 | * IOC3 special handling | ||
| 138 | */ | ||
| 139 | if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) { | ||
| 140 | *value = emulate_ioc3_cfg(where, size); | ||
| 141 | return PCIBIOS_SUCCESSFUL; | ||
| 142 | } | ||
| 143 | |||
| 144 | bridge_write(bc, b_pci_cfg, (busno << 16) | (slot << 11)); | ||
| 145 | addr = &bridge->b_type1_cfg.c[(fn << 8) | where]; | ||
| 146 | |||
| 147 | if (get_dbe(cf, (u32 *) addr)) | ||
| 148 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 149 | |||
| 150 | shift = ((where & 3) << 3); | ||
| 151 | mask = (0xffffffffU >> ((4 - size) << 3)); | ||
| 152 | *value = (cf >> shift) & mask; | ||
| 153 | |||
| 154 | return PCIBIOS_SUCCESSFUL; | ||
| 155 | } | ||
| 156 | |||
| 157 | static int pci_read_config(struct pci_bus *bus, unsigned int devfn, | ||
| 158 | int where, int size, u32 * value) | ||
| 159 | { | ||
| 160 | if (!pci_is_root_bus(bus)) | ||
| 161 | return pci_conf1_read_config(bus, devfn, where, size, value); | ||
| 162 | |||
| 163 | return pci_conf0_read_config(bus, devfn, where, size, value); | ||
| 164 | } | ||
| 165 | |||
| 166 | static int pci_conf0_write_config(struct pci_bus *bus, unsigned int devfn, | ||
| 167 | int where, int size, u32 value) | ||
| 168 | { | ||
| 169 | struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); | ||
| 170 | struct bridge_regs *bridge = bc->base; | ||
| 171 | int slot = PCI_SLOT(devfn); | ||
| 172 | int fn = PCI_FUNC(devfn); | ||
| 173 | volatile void *addr; | ||
| 174 | u32 cf, shift, mask, smask; | ||
| 175 | int res; | ||
| 176 | |||
| 177 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID]; | ||
| 178 | if (get_dbe(cf, (u32 *) addr)) | ||
| 179 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 180 | |||
| 181 | /* | ||
| 182 | * IOC3 is broken beyond belief ... Don't even give the | ||
| 183 | * generic PCI code a chance to look at it for real ... | ||
| 184 | */ | ||
| 185 | if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) | ||
| 186 | goto is_ioc3; | ||
| 187 | |||
| 188 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)]; | ||
| 189 | |||
| 190 | if (size == 1) { | ||
| 191 | res = put_dbe(value, (u8 *) addr); | ||
| 192 | } else if (size == 2) { | ||
| 193 | res = put_dbe(value, (u16 *) addr); | ||
| 194 | } else { | ||
| 195 | res = put_dbe(value, (u32 *) addr); | ||
| 196 | } | ||
| 197 | |||
| 198 | if (res) | ||
| 199 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 200 | |||
| 201 | return PCIBIOS_SUCCESSFUL; | ||
| 202 | |||
| 203 | is_ioc3: | ||
| 204 | |||
| 205 | /* | ||
| 206 | * IOC3 special handling | ||
| 207 | */ | ||
| 208 | if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) | ||
| 209 | return PCIBIOS_SUCCESSFUL; | ||
| 210 | |||
| 211 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; | ||
| 212 | |||
| 213 | if (get_dbe(cf, (u32 *) addr)) | ||
| 214 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 215 | |||
| 216 | shift = ((where & 3) << 3); | ||
| 217 | mask = (0xffffffffU >> ((4 - size) << 3)); | ||
| 218 | smask = mask << shift; | ||
| 219 | |||
| 220 | cf = (cf & ~smask) | ((value & mask) << shift); | ||
| 221 | if (put_dbe(cf, (u32 *) addr)) | ||
| 222 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 223 | |||
| 224 | return PCIBIOS_SUCCESSFUL; | ||
| 225 | } | ||
| 226 | |||
| 227 | static int pci_conf1_write_config(struct pci_bus *bus, unsigned int devfn, | ||
| 228 | int where, int size, u32 value) | ||
| 229 | { | ||
| 230 | struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); | ||
| 231 | struct bridge_regs *bridge = bc->base; | ||
| 232 | int slot = PCI_SLOT(devfn); | ||
| 233 | int fn = PCI_FUNC(devfn); | ||
| 234 | int busno = bus->number; | ||
| 235 | volatile void *addr; | ||
| 236 | u32 cf, shift, mask, smask; | ||
| 237 | int res; | ||
| 238 | |||
| 239 | bridge_write(bc, b_pci_cfg, (busno << 16) | (slot << 11)); | ||
| 240 | addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID]; | ||
| 241 | if (get_dbe(cf, (u32 *) addr)) | ||
| 242 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 243 | |||
| 244 | /* | ||
| 245 | * IOC3 is broken beyond belief ... Don't even give the | ||
| 246 | * generic PCI code a chance to look at it for real ... | ||
| 247 | */ | ||
| 248 | if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) | ||
| 249 | goto is_ioc3; | ||
| 250 | |||
| 251 | addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))]; | ||
| 252 | |||
| 253 | if (size == 1) { | ||
| 254 | res = put_dbe(value, (u8 *) addr); | ||
| 255 | } else if (size == 2) { | ||
| 256 | res = put_dbe(value, (u16 *) addr); | ||
| 257 | } else { | ||
| 258 | res = put_dbe(value, (u32 *) addr); | ||
| 259 | } | ||
| 260 | |||
| 261 | if (res) | ||
| 262 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 263 | |||
| 264 | return PCIBIOS_SUCCESSFUL; | ||
| 265 | |||
| 266 | is_ioc3: | ||
| 267 | |||
| 268 | /* | ||
| 269 | * IOC3 special handling | ||
| 270 | */ | ||
| 271 | if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) | ||
| 272 | return PCIBIOS_SUCCESSFUL; | ||
| 273 | |||
| 274 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; | ||
| 275 | |||
| 276 | if (get_dbe(cf, (u32 *) addr)) | ||
| 277 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 278 | |||
| 279 | shift = ((where & 3) << 3); | ||
| 280 | mask = (0xffffffffU >> ((4 - size) << 3)); | ||
| 281 | smask = mask << shift; | ||
| 282 | |||
| 283 | cf = (cf & ~smask) | ((value & mask) << shift); | ||
| 284 | if (put_dbe(cf, (u32 *) addr)) | ||
| 285 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 286 | |||
| 287 | return PCIBIOS_SUCCESSFUL; | ||
| 288 | } | ||
| 289 | |||
| 290 | static int pci_write_config(struct pci_bus *bus, unsigned int devfn, | ||
| 291 | int where, int size, u32 value) | ||
| 292 | { | ||
| 293 | if (!pci_is_root_bus(bus)) | ||
| 294 | return pci_conf1_write_config(bus, devfn, where, size, value); | ||
| 295 | |||
| 296 | return pci_conf0_write_config(bus, devfn, where, size, value); | ||
| 297 | } | ||
| 298 | |||
| 299 | struct pci_ops bridge_pci_ops = { | ||
| 300 | .read = pci_read_config, | ||
| 301 | .write = pci_write_config, | ||
| 302 | }; | ||
diff --git a/arch/mips/pci/pci-ip27.c b/arch/mips/pci/pci-ip27.c index 3c177b4d0609..441eb9383b20 100644 --- a/arch/mips/pci/pci-ip27.c +++ b/arch/mips/pci/pci-ip27.c | |||
| @@ -7,162 +7,7 @@ | |||
| 7 | * Copyright (C) 1999, 2000, 04 Ralf Baechle (ralf@linux-mips.org) | 7 | * Copyright (C) 1999, 2000, 04 Ralf Baechle (ralf@linux-mips.org) |
| 8 | * Copyright (C) 1999, 2000 Silicon Graphics, Inc. | 8 | * Copyright (C) 1999, 2000 Silicon Graphics, Inc. |
| 9 | */ | 9 | */ |
| 10 | #include <linux/kernel.h> | ||
| 11 | #include <linux/export.h> | ||
| 12 | #include <linux/pci.h> | ||
| 13 | #include <linux/smp.h> | ||
| 14 | #include <linux/dma-direct.h> | ||
| 15 | #include <asm/sn/arch.h> | ||
| 16 | #include <asm/pci/bridge.h> | 10 | #include <asm/pci/bridge.h> |
| 17 | #include <asm/paccess.h> | ||
| 18 | #include <asm/sn/intr.h> | ||
| 19 | #include <asm/sn/sn0/hub.h> | ||
| 20 | |||
| 21 | /* | ||
| 22 | * Max #PCI busses we can handle; ie, max #PCI bridges. | ||
| 23 | */ | ||
| 24 | #define MAX_PCI_BUSSES 40 | ||
| 25 | |||
| 26 | /* | ||
| 27 | * XXX: No kmalloc available when we do our crosstalk scan, | ||
| 28 | * we should try to move it later in the boot process. | ||
| 29 | */ | ||
| 30 | static struct bridge_controller bridges[MAX_PCI_BUSSES]; | ||
| 31 | |||
| 32 | extern struct pci_ops bridge_pci_ops; | ||
| 33 | |||
| 34 | int bridge_probe(nasid_t nasid, int widget_id, int masterwid) | ||
| 35 | { | ||
| 36 | unsigned long offset = NODE_OFFSET(nasid); | ||
| 37 | struct bridge_controller *bc; | ||
| 38 | static int num_bridges = 0; | ||
| 39 | int slot; | ||
| 40 | |||
| 41 | pci_set_flags(PCI_PROBE_ONLY); | ||
| 42 | |||
| 43 | printk("a bridge\n"); | ||
| 44 | |||
| 45 | /* XXX: kludge alert.. */ | ||
| 46 | if (!num_bridges) | ||
| 47 | ioport_resource.end = ~0UL; | ||
| 48 | |||
| 49 | bc = &bridges[num_bridges]; | ||
| 50 | |||
| 51 | bc->pc.pci_ops = &bridge_pci_ops; | ||
| 52 | bc->pc.mem_resource = &bc->mem; | ||
| 53 | bc->pc.io_resource = &bc->io; | ||
| 54 | |||
| 55 | bc->pc.index = num_bridges; | ||
| 56 | |||
| 57 | bc->mem.name = "Bridge PCI MEM"; | ||
| 58 | bc->pc.mem_offset = offset; | ||
| 59 | bc->mem.start = 0; | ||
| 60 | bc->mem.end = ~0UL; | ||
| 61 | bc->mem.flags = IORESOURCE_MEM; | ||
| 62 | |||
| 63 | bc->io.name = "Bridge IO MEM"; | ||
| 64 | bc->pc.io_offset = offset; | ||
| 65 | bc->io.start = 0UL; | ||
| 66 | bc->io.end = ~0UL; | ||
| 67 | bc->io.flags = IORESOURCE_IO; | ||
| 68 | |||
| 69 | bc->widget_id = widget_id; | ||
| 70 | bc->nasid = nasid; | ||
| 71 | |||
| 72 | bc->baddr = (u64)masterwid << 60 | PCI64_ATTR_BAR; | ||
| 73 | |||
| 74 | /* | ||
| 75 | * point to this bridge | ||
| 76 | */ | ||
| 77 | bc->base = (struct bridge_regs *)RAW_NODE_SWIN_BASE(nasid, widget_id); | ||
| 78 | |||
| 79 | /* | ||
| 80 | * Clear all pending interrupts. | ||
| 81 | */ | ||
| 82 | bridge_write(bc, b_int_rst_stat, BRIDGE_IRR_ALL_CLR); | ||
| 83 | |||
| 84 | /* | ||
| 85 | * Until otherwise set up, assume all interrupts are from slot 0 | ||
| 86 | */ | ||
| 87 | bridge_write(bc, b_int_device, 0x0); | ||
| 88 | |||
| 89 | /* | ||
| 90 | * swap pio's to pci mem and io space (big windows) | ||
| 91 | */ | ||
| 92 | bridge_set(bc, b_wid_control, BRIDGE_CTRL_IO_SWAP | | ||
| 93 | BRIDGE_CTRL_MEM_SWAP); | ||
| 94 | #ifdef CONFIG_PAGE_SIZE_4KB | ||
| 95 | bridge_clr(bc, b_wid_control, BRIDGE_CTRL_PAGE_SIZE); | ||
| 96 | #else /* 16kB or larger */ | ||
| 97 | bridge_set(bc, b_wid_control, BRIDGE_CTRL_PAGE_SIZE); | ||
| 98 | #endif | ||
| 99 | |||
| 100 | /* | ||
| 101 | * Hmm... IRIX sets additional bits in the address which | ||
| 102 | * are documented as reserved in the bridge docs. | ||
| 103 | */ | ||
| 104 | bridge_write(bc, b_wid_int_upper, 0x8000 | (masterwid << 16)); | ||
| 105 | bridge_write(bc, b_wid_int_lower, 0x01800090); /* PI_INT_PEND_MOD off*/ | ||
| 106 | bridge_write(bc, b_dir_map, (masterwid << 20)); /* DMA */ | ||
| 107 | bridge_write(bc, b_int_enable, 0); | ||
| 108 | |||
| 109 | for (slot = 0; slot < 8; slot ++) { | ||
| 110 | bridge_set(bc, b_device[slot].reg, BRIDGE_DEV_SWAP_DIR); | ||
| 111 | bc->pci_int[slot] = -1; | ||
| 112 | } | ||
| 113 | bridge_read(bc, b_wid_tflush); /* wait until Bridge PIO complete */ | ||
| 114 | |||
| 115 | register_pci_controller(&bc->pc); | ||
| 116 | |||
| 117 | num_bridges++; | ||
| 118 | |||
| 119 | return 0; | ||
| 120 | } | ||
| 121 | |||
| 122 | /* | ||
| 123 | * All observed requests have pin == 1. We could have a global here, that | ||
| 124 | * gets incremented and returned every time - unfortunately, pci_map_irq | ||
| 125 | * may be called on the same device over and over, and need to return the | ||
| 126 | * same value. On O2000, pin can be 0 or 1, and PCI slots can be [0..7]. | ||
| 127 | * | ||
| 128 | * A given PCI device, in general, should be able to intr any of the cpus | ||
| 129 | * on any one of the hubs connected to its xbow. | ||
| 130 | */ | ||
| 131 | int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) | ||
| 132 | { | ||
| 133 | return 0; | ||
| 134 | } | ||
| 135 | |||
| 136 | static inline struct pci_dev *bridge_root_dev(struct pci_dev *dev) | ||
| 137 | { | ||
| 138 | while (dev->bus->parent) { | ||
| 139 | /* Move up the chain of bridges. */ | ||
| 140 | dev = dev->bus->self; | ||
| 141 | } | ||
| 142 | |||
| 143 | return dev; | ||
| 144 | } | ||
| 145 | |||
| 146 | /* Do platform specific device initialization at pci_enable_device() time */ | ||
| 147 | int pcibios_plat_dev_init(struct pci_dev *dev) | ||
| 148 | { | ||
| 149 | struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus); | ||
| 150 | struct pci_dev *rdev = bridge_root_dev(dev); | ||
| 151 | int slot = PCI_SLOT(rdev->devfn); | ||
| 152 | int irq; | ||
| 153 | |||
| 154 | irq = bc->pci_int[slot]; | ||
| 155 | if (irq == -1) { | ||
| 156 | irq = request_bridge_irq(bc, slot); | ||
| 157 | if (irq < 0) | ||
| 158 | return irq; | ||
| 159 | |||
| 160 | bc->pci_int[slot] = irq; | ||
| 161 | } | ||
| 162 | dev->irq = irq; | ||
| 163 | |||
| 164 | return 0; | ||
| 165 | } | ||
| 166 | 11 | ||
| 167 | dma_addr_t __phys_to_dma(struct device *dev, phys_addr_t paddr) | 12 | dma_addr_t __phys_to_dma(struct device *dev, phys_addr_t paddr) |
| 168 | { | 13 | { |
| @@ -177,29 +22,6 @@ phys_addr_t __dma_to_phys(struct device *dev, dma_addr_t dma_addr) | |||
| 177 | return dma_addr & ~(0xffUL << 56); | 22 | return dma_addr & ~(0xffUL << 56); |
| 178 | } | 23 | } |
| 179 | 24 | ||
| 180 | /* | ||
| 181 | * Device might live on a subordinate PCI bus. XXX Walk up the chain of buses | ||
| 182 | * to find the slot number in sense of the bridge device register. | ||
| 183 | * XXX This also means multiple devices might rely on conflicting bridge | ||
| 184 | * settings. | ||
| 185 | */ | ||
| 186 | |||
| 187 | static inline void pci_disable_swapping(struct pci_dev *dev) | ||
| 188 | { | ||
| 189 | struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus); | ||
| 190 | struct bridge_regs *bridge = bc->base; | ||
| 191 | int slot = PCI_SLOT(dev->devfn); | ||
| 192 | |||
| 193 | /* Turn off byte swapping */ | ||
| 194 | bridge->b_device[slot].reg &= ~BRIDGE_DEV_SWAP_DIR; | ||
| 195 | bridge->b_widget.w_tflush; /* Flush */ | ||
| 196 | } | ||
| 197 | |||
| 198 | static void pci_fixup_ioc3(struct pci_dev *d) | ||
| 199 | { | ||
| 200 | pci_disable_swapping(d); | ||
| 201 | } | ||
| 202 | |||
| 203 | #ifdef CONFIG_NUMA | 25 | #ifdef CONFIG_NUMA |
| 204 | int pcibus_to_node(struct pci_bus *bus) | 26 | int pcibus_to_node(struct pci_bus *bus) |
| 205 | { | 27 | { |
| @@ -209,6 +31,3 @@ int pcibus_to_node(struct pci_bus *bus) | |||
| 209 | } | 31 | } |
| 210 | EXPORT_SYMBOL(pcibus_to_node); | 32 | EXPORT_SYMBOL(pcibus_to_node); |
| 211 | #endif /* CONFIG_NUMA */ | 33 | #endif /* CONFIG_NUMA */ |
| 212 | |||
| 213 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3, | ||
| 214 | pci_fixup_ioc3); | ||
diff --git a/arch/mips/pci/pci-xtalk-bridge.c b/arch/mips/pci/pci-xtalk-bridge.c new file mode 100644 index 000000000000..bcf7f559789a --- /dev/null +++ b/arch/mips/pci/pci-xtalk-bridge.c | |||
| @@ -0,0 +1,610 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2003 Christoph Hellwig (hch@lst.de) | ||
| 4 | * Copyright (C) 1999, 2000, 04 Ralf Baechle (ralf@linux-mips.org) | ||
| 5 | * Copyright (C) 1999, 2000 Silicon Graphics, Inc. | ||
| 6 | */ | ||
| 7 | #include <linux/kernel.h> | ||
| 8 | #include <linux/export.h> | ||
| 9 | #include <linux/pci.h> | ||
| 10 | #include <linux/smp.h> | ||
| 11 | #include <linux/dma-direct.h> | ||
| 12 | #include <linux/platform_device.h> | ||
| 13 | #include <linux/platform_data/xtalk-bridge.h> | ||
| 14 | |||
| 15 | #include <asm/pci/bridge.h> | ||
| 16 | #include <asm/paccess.h> | ||
| 17 | #include <asm/sn/irq_alloc.h> | ||
| 18 | |||
| 19 | /* | ||
| 20 | * Most of the IOC3 PCI config register aren't present | ||
| 21 | * we emulate what is needed for a normal PCI enumeration | ||
| 22 | */ | ||
| 23 | static u32 emulate_ioc3_cfg(int where, int size) | ||
| 24 | { | ||
| 25 | if (size == 1 && where == 0x3d) | ||
| 26 | return 0x01; | ||
| 27 | else if (size == 2 && where == 0x3c) | ||
| 28 | return 0x0100; | ||
| 29 | else if (size == 4 && where == 0x3c) | ||
| 30 | return 0x00000100; | ||
| 31 | |||
| 32 | return 0; | ||
| 33 | } | ||
| 34 | |||
| 35 | static void bridge_disable_swapping(struct pci_dev *dev) | ||
| 36 | { | ||
| 37 | struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus); | ||
| 38 | int slot = PCI_SLOT(dev->devfn); | ||
| 39 | |||
| 40 | /* Turn off byte swapping */ | ||
| 41 | bridge_clr(bc, b_device[slot].reg, BRIDGE_DEV_SWAP_DIR); | ||
| 42 | bridge_read(bc, b_widget.w_tflush); /* Flush */ | ||
| 43 | } | ||
| 44 | |||
| 45 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3, | ||
| 46 | bridge_disable_swapping); | ||
| 47 | |||
| 48 | |||
| 49 | /* | ||
| 50 | * The Bridge ASIC supports both type 0 and type 1 access. Type 1 is | ||
| 51 | * not really documented, so right now I can't write code which uses it. | ||
| 52 | * Therefore we use type 0 accesses for now even though they won't work | ||
| 53 | * correctly for PCI-to-PCI bridges. | ||
| 54 | * | ||
| 55 | * The function is complicated by the ultimate brokenness of the IOC3 chip | ||
| 56 | * which is used in SGI systems. The IOC3 can only handle 32-bit PCI | ||
| 57 | * accesses and does only decode parts of it's address space. | ||
| 58 | */ | ||
| 59 | static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn, | ||
| 60 | int where, int size, u32 *value) | ||
| 61 | { | ||
| 62 | struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); | ||
| 63 | struct bridge_regs *bridge = bc->base; | ||
| 64 | int slot = PCI_SLOT(devfn); | ||
| 65 | int fn = PCI_FUNC(devfn); | ||
| 66 | void *addr; | ||
| 67 | u32 cf, shift, mask; | ||
| 68 | int res; | ||
| 69 | |||
| 70 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID]; | ||
| 71 | if (get_dbe(cf, (u32 *)addr)) | ||
| 72 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 73 | |||
| 74 | /* | ||
| 75 | * IOC3 is broken beyond belief ... Don't even give the | ||
| 76 | * generic PCI code a chance to look at it for real ... | ||
| 77 | */ | ||
| 78 | if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) | ||
| 79 | goto is_ioc3; | ||
| 80 | |||
| 81 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)]; | ||
| 82 | |||
| 83 | if (size == 1) | ||
| 84 | res = get_dbe(*value, (u8 *)addr); | ||
| 85 | else if (size == 2) | ||
| 86 | res = get_dbe(*value, (u16 *)addr); | ||
| 87 | else | ||
| 88 | res = get_dbe(*value, (u32 *)addr); | ||
| 89 | |||
| 90 | return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; | ||
| 91 | |||
| 92 | is_ioc3: | ||
| 93 | |||
| 94 | /* | ||
| 95 | * IOC3 special handling | ||
| 96 | */ | ||
| 97 | if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) { | ||
| 98 | *value = emulate_ioc3_cfg(where, size); | ||
| 99 | return PCIBIOS_SUCCESSFUL; | ||
| 100 | } | ||
| 101 | |||
| 102 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; | ||
| 103 | if (get_dbe(cf, (u32 *)addr)) | ||
| 104 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 105 | |||
| 106 | shift = ((where & 3) << 3); | ||
| 107 | mask = (0xffffffffU >> ((4 - size) << 3)); | ||
| 108 | *value = (cf >> shift) & mask; | ||
| 109 | |||
| 110 | return PCIBIOS_SUCCESSFUL; | ||
| 111 | } | ||
| 112 | |||
| 113 | static int pci_conf1_read_config(struct pci_bus *bus, unsigned int devfn, | ||
| 114 | int where, int size, u32 *value) | ||
| 115 | { | ||
| 116 | struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); | ||
| 117 | struct bridge_regs *bridge = bc->base; | ||
| 118 | int busno = bus->number; | ||
| 119 | int slot = PCI_SLOT(devfn); | ||
| 120 | int fn = PCI_FUNC(devfn); | ||
| 121 | void *addr; | ||
| 122 | u32 cf, shift, mask; | ||
| 123 | int res; | ||
| 124 | |||
| 125 | bridge_write(bc, b_pci_cfg, (busno << 16) | (slot << 11)); | ||
| 126 | addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID]; | ||
| 127 | if (get_dbe(cf, (u32 *)addr)) | ||
| 128 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 129 | |||
| 130 | /* | ||
| 131 | * IOC3 is broken beyond belief ... Don't even give the | ||
| 132 | * generic PCI code a chance to look at it for real ... | ||
| 133 | */ | ||
| 134 | if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) | ||
| 135 | goto is_ioc3; | ||
| 136 | |||
| 137 | addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))]; | ||
| 138 | |||
| 139 | if (size == 1) | ||
| 140 | res = get_dbe(*value, (u8 *)addr); | ||
| 141 | else if (size == 2) | ||
| 142 | res = get_dbe(*value, (u16 *)addr); | ||
| 143 | else | ||
| 144 | res = get_dbe(*value, (u32 *)addr); | ||
| 145 | |||
| 146 | return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; | ||
| 147 | |||
| 148 | is_ioc3: | ||
| 149 | |||
| 150 | /* | ||
| 151 | * IOC3 special handling | ||
| 152 | */ | ||
| 153 | if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) { | ||
| 154 | *value = emulate_ioc3_cfg(where, size); | ||
| 155 | return PCIBIOS_SUCCESSFUL; | ||
| 156 | } | ||
| 157 | |||
| 158 | addr = &bridge->b_type1_cfg.c[(fn << 8) | where]; | ||
| 159 | if (get_dbe(cf, (u32 *)addr)) | ||
| 160 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 161 | |||
| 162 | shift = ((where & 3) << 3); | ||
| 163 | mask = (0xffffffffU >> ((4 - size) << 3)); | ||
| 164 | *value = (cf >> shift) & mask; | ||
| 165 | |||
| 166 | return PCIBIOS_SUCCESSFUL; | ||
| 167 | } | ||
| 168 | |||
| 169 | static int pci_read_config(struct pci_bus *bus, unsigned int devfn, | ||
| 170 | int where, int size, u32 *value) | ||
| 171 | { | ||
| 172 | if (!pci_is_root_bus(bus)) | ||
| 173 | return pci_conf1_read_config(bus, devfn, where, size, value); | ||
| 174 | |||
| 175 | return pci_conf0_read_config(bus, devfn, where, size, value); | ||
| 176 | } | ||
| 177 | |||
| 178 | static int pci_conf0_write_config(struct pci_bus *bus, unsigned int devfn, | ||
| 179 | int where, int size, u32 value) | ||
| 180 | { | ||
| 181 | struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); | ||
| 182 | struct bridge_regs *bridge = bc->base; | ||
| 183 | int slot = PCI_SLOT(devfn); | ||
| 184 | int fn = PCI_FUNC(devfn); | ||
| 185 | void *addr; | ||
| 186 | u32 cf, shift, mask, smask; | ||
| 187 | int res; | ||
| 188 | |||
| 189 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID]; | ||
| 190 | if (get_dbe(cf, (u32 *)addr)) | ||
| 191 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 192 | |||
| 193 | /* | ||
| 194 | * IOC3 is broken beyond belief ... Don't even give the | ||
| 195 | * generic PCI code a chance to look at it for real ... | ||
| 196 | */ | ||
| 197 | if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) | ||
| 198 | goto is_ioc3; | ||
| 199 | |||
| 200 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)]; | ||
| 201 | |||
| 202 | if (size == 1) | ||
| 203 | res = put_dbe(value, (u8 *)addr); | ||
| 204 | else if (size == 2) | ||
| 205 | res = put_dbe(value, (u16 *)addr); | ||
| 206 | else | ||
| 207 | res = put_dbe(value, (u32 *)addr); | ||
| 208 | |||
| 209 | if (res) | ||
| 210 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 211 | |||
| 212 | return PCIBIOS_SUCCESSFUL; | ||
| 213 | |||
| 214 | is_ioc3: | ||
| 215 | |||
| 216 | /* | ||
| 217 | * IOC3 special handling | ||
| 218 | */ | ||
| 219 | if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) | ||
| 220 | return PCIBIOS_SUCCESSFUL; | ||
| 221 | |||
| 222 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; | ||
| 223 | |||
| 224 | if (get_dbe(cf, (u32 *)addr)) | ||
| 225 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 226 | |||
| 227 | shift = ((where & 3) << 3); | ||
| 228 | mask = (0xffffffffU >> ((4 - size) << 3)); | ||
| 229 | smask = mask << shift; | ||
| 230 | |||
| 231 | cf = (cf & ~smask) | ((value & mask) << shift); | ||
| 232 | if (put_dbe(cf, (u32 *)addr)) | ||
| 233 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 234 | |||
| 235 | return PCIBIOS_SUCCESSFUL; | ||
| 236 | } | ||
| 237 | |||
| 238 | static int pci_conf1_write_config(struct pci_bus *bus, unsigned int devfn, | ||
| 239 | int where, int size, u32 value) | ||
| 240 | { | ||
| 241 | struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); | ||
| 242 | struct bridge_regs *bridge = bc->base; | ||
| 243 | int slot = PCI_SLOT(devfn); | ||
| 244 | int fn = PCI_FUNC(devfn); | ||
| 245 | int busno = bus->number; | ||
| 246 | void *addr; | ||
| 247 | u32 cf, shift, mask, smask; | ||
| 248 | int res; | ||
| 249 | |||
| 250 | bridge_write(bc, b_pci_cfg, (busno << 16) | (slot << 11)); | ||
| 251 | addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID]; | ||
| 252 | if (get_dbe(cf, (u32 *)addr)) | ||
| 253 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 254 | |||
| 255 | /* | ||
| 256 | * IOC3 is broken beyond belief ... Don't even give the | ||
| 257 | * generic PCI code a chance to look at it for real ... | ||
| 258 | */ | ||
| 259 | if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) | ||
| 260 | goto is_ioc3; | ||
| 261 | |||
| 262 | addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))]; | ||
| 263 | |||
| 264 | if (size == 1) | ||
| 265 | res = put_dbe(value, (u8 *)addr); | ||
| 266 | else if (size == 2) | ||
| 267 | res = put_dbe(value, (u16 *)addr); | ||
| 268 | else | ||
| 269 | res = put_dbe(value, (u32 *)addr); | ||
| 270 | |||
| 271 | if (res) | ||
| 272 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 273 | |||
| 274 | return PCIBIOS_SUCCESSFUL; | ||
| 275 | |||
| 276 | is_ioc3: | ||
| 277 | |||
| 278 | /* | ||
| 279 | * IOC3 special handling | ||
| 280 | */ | ||
| 281 | if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) | ||
| 282 | return PCIBIOS_SUCCESSFUL; | ||
| 283 | |||
| 284 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; | ||
| 285 | if (get_dbe(cf, (u32 *)addr)) | ||
| 286 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 287 | |||
| 288 | shift = ((where & 3) << 3); | ||
| 289 | mask = (0xffffffffU >> ((4 - size) << 3)); | ||
| 290 | smask = mask << shift; | ||
| 291 | |||
| 292 | cf = (cf & ~smask) | ((value & mask) << shift); | ||
| 293 | if (put_dbe(cf, (u32 *)addr)) | ||
| 294 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 295 | |||
| 296 | return PCIBIOS_SUCCESSFUL; | ||
| 297 | } | ||
| 298 | |||
| 299 | static int pci_write_config(struct pci_bus *bus, unsigned int devfn, | ||
| 300 | int where, int size, u32 value) | ||
| 301 | { | ||
| 302 | if (!pci_is_root_bus(bus)) | ||
| 303 | return pci_conf1_write_config(bus, devfn, where, size, value); | ||
| 304 | |||
| 305 | return pci_conf0_write_config(bus, devfn, where, size, value); | ||
| 306 | } | ||
| 307 | |||
| 308 | static struct pci_ops bridge_pci_ops = { | ||
| 309 | .read = pci_read_config, | ||
| 310 | .write = pci_write_config, | ||
| 311 | }; | ||
| 312 | |||
| 313 | struct bridge_irq_chip_data { | ||
| 314 | struct bridge_controller *bc; | ||
| 315 | nasid_t nasid; | ||
| 316 | }; | ||
| 317 | |||
| 318 | static int bridge_set_affinity(struct irq_data *d, const struct cpumask *mask, | ||
| 319 | bool force) | ||
| 320 | { | ||
| 321 | #ifdef CONFIG_NUMA | ||
| 322 | struct bridge_irq_chip_data *data = d->chip_data; | ||
| 323 | int bit = d->parent_data->hwirq; | ||
| 324 | int pin = d->hwirq; | ||
| 325 | nasid_t nasid; | ||
| 326 | int ret, cpu; | ||
| 327 | |||
| 328 | ret = irq_chip_set_affinity_parent(d, mask, force); | ||
| 329 | if (ret >= 0) { | ||
| 330 | cpu = cpumask_first_and(mask, cpu_online_mask); | ||
| 331 | nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu)); | ||
| 332 | bridge_write(data->bc, b_int_addr[pin].addr, | ||
| 333 | (((data->bc->intr_addr >> 30) & 0x30000) | | ||
| 334 | bit | (nasid << 8))); | ||
| 335 | bridge_read(data->bc, b_wid_tflush); | ||
| 336 | } | ||
| 337 | return ret; | ||
| 338 | #else | ||
| 339 | return irq_chip_set_affinity_parent(d, mask, force); | ||
| 340 | #endif | ||
| 341 | } | ||
| 342 | |||
| 343 | struct irq_chip bridge_irq_chip = { | ||
| 344 | .name = "BRIDGE", | ||
| 345 | .irq_mask = irq_chip_mask_parent, | ||
| 346 | .irq_unmask = irq_chip_unmask_parent, | ||
| 347 | .irq_set_affinity = bridge_set_affinity | ||
| 348 | }; | ||
| 349 | |||
| 350 | static int bridge_domain_alloc(struct irq_domain *domain, unsigned int virq, | ||
| 351 | unsigned int nr_irqs, void *arg) | ||
| 352 | { | ||
| 353 | struct bridge_irq_chip_data *data; | ||
| 354 | struct irq_alloc_info *info = arg; | ||
| 355 | int ret; | ||
| 356 | |||
| 357 | if (nr_irqs > 1 || !info) | ||
| 358 | return -EINVAL; | ||
| 359 | |||
| 360 | data = kzalloc(sizeof(*data), GFP_KERNEL); | ||
| 361 | if (!data) | ||
| 362 | return -ENOMEM; | ||
| 363 | |||
| 364 | ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, arg); | ||
| 365 | if (ret >= 0) { | ||
| 366 | data->bc = info->ctrl; | ||
| 367 | data->nasid = info->nasid; | ||
| 368 | irq_domain_set_info(domain, virq, info->pin, &bridge_irq_chip, | ||
| 369 | data, handle_level_irq, NULL, NULL); | ||
| 370 | } else { | ||
| 371 | kfree(data); | ||
| 372 | } | ||
| 373 | |||
| 374 | return ret; | ||
| 375 | } | ||
| 376 | |||
| 377 | static void bridge_domain_free(struct irq_domain *domain, unsigned int virq, | ||
| 378 | unsigned int nr_irqs) | ||
| 379 | { | ||
| 380 | struct irq_data *irqd = irq_domain_get_irq_data(domain, virq); | ||
| 381 | |||
| 382 | if (nr_irqs) | ||
| 383 | return; | ||
| 384 | |||
| 385 | kfree(irqd->chip_data); | ||
| 386 | irq_domain_free_irqs_top(domain, virq, nr_irqs); | ||
| 387 | } | ||
| 388 | |||
| 389 | static int bridge_domain_activate(struct irq_domain *domain, | ||
| 390 | struct irq_data *irqd, bool reserve) | ||
| 391 | { | ||
| 392 | struct bridge_irq_chip_data *data = irqd->chip_data; | ||
| 393 | struct bridge_controller *bc = data->bc; | ||
| 394 | int bit = irqd->parent_data->hwirq; | ||
| 395 | int pin = irqd->hwirq; | ||
| 396 | u32 device; | ||
| 397 | |||
| 398 | bridge_write(bc, b_int_addr[pin].addr, | ||
| 399 | (((bc->intr_addr >> 30) & 0x30000) | | ||
| 400 | bit | (data->nasid << 8))); | ||
| 401 | bridge_set(bc, b_int_enable, (1 << pin)); | ||
| 402 | bridge_set(bc, b_int_enable, 0x7ffffe00); /* more stuff in int_enable */ | ||
| 403 | |||
| 404 | /* | ||
| 405 | * Enable sending of an interrupt clear packt to the hub on a high to | ||
| 406 | * low transition of the interrupt pin. | ||
| 407 | * | ||
| 408 | * IRIX sets additional bits in the address which are documented as | ||
| 409 | * reserved in the bridge docs. | ||
| 410 | */ | ||
| 411 | bridge_set(bc, b_int_mode, (1UL << pin)); | ||
| 412 | |||
| 413 | /* | ||
| 414 | * We assume the bridge to have a 1:1 mapping between devices | ||
| 415 | * (slots) and intr pins. | ||
| 416 | */ | ||
| 417 | device = bridge_read(bc, b_int_device); | ||
| 418 | device &= ~(7 << (pin*3)); | ||
| 419 | device |= (pin << (pin*3)); | ||
| 420 | bridge_write(bc, b_int_device, device); | ||
| 421 | |||
| 422 | bridge_read(bc, b_wid_tflush); | ||
| 423 | return 0; | ||
| 424 | } | ||
| 425 | |||
| 426 | static void bridge_domain_deactivate(struct irq_domain *domain, | ||
| 427 | struct irq_data *irqd) | ||
| 428 | { | ||
| 429 | struct bridge_irq_chip_data *data = irqd->chip_data; | ||
| 430 | |||
| 431 | bridge_clr(data->bc, b_int_enable, (1 << irqd->hwirq)); | ||
| 432 | bridge_read(data->bc, b_wid_tflush); | ||
| 433 | } | ||
| 434 | |||
| 435 | static const struct irq_domain_ops bridge_domain_ops = { | ||
| 436 | .alloc = bridge_domain_alloc, | ||
| 437 | .free = bridge_domain_free, | ||
| 438 | .activate = bridge_domain_activate, | ||
| 439 | .deactivate = bridge_domain_deactivate | ||
| 440 | }; | ||
| 441 | |||
| 442 | /* | ||
| 443 | * All observed requests have pin == 1. We could have a global here, that | ||
| 444 | * gets incremented and returned every time - unfortunately, pci_map_irq | ||
| 445 | * may be called on the same device over and over, and need to return the | ||
| 446 | * same value. On O2000, pin can be 0 or 1, and PCI slots can be [0..7]. | ||
| 447 | * | ||
| 448 | * A given PCI device, in general, should be able to intr any of the cpus | ||
| 449 | * on any one of the hubs connected to its xbow. | ||
| 450 | */ | ||
| 451 | static int bridge_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) | ||
| 452 | { | ||
| 453 | struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus); | ||
| 454 | struct irq_alloc_info info; | ||
| 455 | int irq; | ||
| 456 | |||
| 457 | irq = bc->pci_int[slot]; | ||
| 458 | if (irq == -1) { | ||
| 459 | info.ctrl = bc; | ||
| 460 | info.nasid = bc->nasid; | ||
| 461 | info.pin = slot; | ||
| 462 | |||
| 463 | irq = irq_domain_alloc_irqs(bc->domain, 1, bc->nasid, &info); | ||
| 464 | if (irq < 0) | ||
| 465 | return irq; | ||
| 466 | |||
| 467 | bc->pci_int[slot] = irq; | ||
| 468 | } | ||
| 469 | return irq; | ||
| 470 | } | ||
| 471 | |||
| 472 | static int bridge_probe(struct platform_device *pdev) | ||
| 473 | { | ||
| 474 | struct xtalk_bridge_platform_data *bd = dev_get_platdata(&pdev->dev); | ||
| 475 | struct device *dev = &pdev->dev; | ||
| 476 | struct bridge_controller *bc; | ||
| 477 | struct pci_host_bridge *host; | ||
| 478 | struct irq_domain *domain, *parent; | ||
| 479 | struct fwnode_handle *fn; | ||
| 480 | int slot; | ||
| 481 | int err; | ||
| 482 | |||
| 483 | parent = irq_get_default_host(); | ||
| 484 | if (!parent) | ||
| 485 | return -ENODEV; | ||
| 486 | fn = irq_domain_alloc_named_fwnode("BRIDGE"); | ||
| 487 | if (!fn) | ||
| 488 | return -ENOMEM; | ||
| 489 | domain = irq_domain_create_hierarchy(parent, 0, 8, fn, | ||
| 490 | &bridge_domain_ops, NULL); | ||
| 491 | irq_domain_free_fwnode(fn); | ||
| 492 | if (!domain) | ||
| 493 | return -ENOMEM; | ||
| 494 | |||
| 495 | pci_set_flags(PCI_PROBE_ONLY); | ||
| 496 | |||
| 497 | host = devm_pci_alloc_host_bridge(dev, sizeof(*bc)); | ||
| 498 | if (!host) { | ||
| 499 | err = -ENOMEM; | ||
| 500 | goto err_remove_domain; | ||
| 501 | } | ||
| 502 | |||
| 503 | bc = pci_host_bridge_priv(host); | ||
| 504 | |||
| 505 | bc->busn.name = "Bridge PCI busn"; | ||
| 506 | bc->busn.start = 0; | ||
| 507 | bc->busn.end = 0xff; | ||
| 508 | bc->busn.flags = IORESOURCE_BUS; | ||
| 509 | |||
| 510 | bc->domain = domain; | ||
| 511 | |||
| 512 | pci_add_resource_offset(&host->windows, &bd->mem, bd->mem_offset); | ||
| 513 | pci_add_resource_offset(&host->windows, &bd->io, bd->io_offset); | ||
| 514 | pci_add_resource(&host->windows, &bc->busn); | ||
| 515 | |||
| 516 | err = devm_request_pci_bus_resources(dev, &host->windows); | ||
| 517 | if (err < 0) | ||
| 518 | goto err_free_resource; | ||
| 519 | |||
| 520 | bc->nasid = bd->nasid; | ||
| 521 | |||
| 522 | bc->baddr = (u64)bd->masterwid << 60 | PCI64_ATTR_BAR; | ||
| 523 | bc->base = (struct bridge_regs *)bd->bridge_addr; | ||
| 524 | bc->intr_addr = bd->intr_addr; | ||
| 525 | |||
| 526 | /* | ||
| 527 | * Clear all pending interrupts. | ||
| 528 | */ | ||
| 529 | bridge_write(bc, b_int_rst_stat, BRIDGE_IRR_ALL_CLR); | ||
| 530 | |||
| 531 | /* | ||
| 532 | * Until otherwise set up, assume all interrupts are from slot 0 | ||
| 533 | */ | ||
| 534 | bridge_write(bc, b_int_device, 0x0); | ||
| 535 | |||
| 536 | /* | ||
| 537 | * disable swapping for big windows | ||
| 538 | */ | ||
| 539 | bridge_clr(bc, b_wid_control, | ||
| 540 | BRIDGE_CTRL_IO_SWAP | BRIDGE_CTRL_MEM_SWAP); | ||
| 541 | #ifdef CONFIG_PAGE_SIZE_4KB | ||
| 542 | bridge_clr(bc, b_wid_control, BRIDGE_CTRL_PAGE_SIZE); | ||
| 543 | #else /* 16kB or larger */ | ||
| 544 | bridge_set(bc, b_wid_control, BRIDGE_CTRL_PAGE_SIZE); | ||
| 545 | #endif | ||
| 546 | |||
| 547 | /* | ||
| 548 | * Hmm... IRIX sets additional bits in the address which | ||
| 549 | * are documented as reserved in the bridge docs. | ||
| 550 | */ | ||
| 551 | bridge_write(bc, b_wid_int_upper, | ||
| 552 | ((bc->intr_addr >> 32) & 0xffff) | (bd->masterwid << 16)); | ||
| 553 | bridge_write(bc, b_wid_int_lower, bc->intr_addr & 0xffffffff); | ||
| 554 | bridge_write(bc, b_dir_map, (bd->masterwid << 20)); /* DMA */ | ||
| 555 | bridge_write(bc, b_int_enable, 0); | ||
| 556 | |||
| 557 | for (slot = 0; slot < 8; slot++) { | ||
| 558 | bridge_set(bc, b_device[slot].reg, BRIDGE_DEV_SWAP_DIR); | ||
| 559 | bc->pci_int[slot] = -1; | ||
| 560 | } | ||
| 561 | bridge_read(bc, b_wid_tflush); /* wait until Bridge PIO complete */ | ||
| 562 | |||
| 563 | host->dev.parent = dev; | ||
| 564 | host->sysdata = bc; | ||
| 565 | host->busnr = 0; | ||
| 566 | host->ops = &bridge_pci_ops; | ||
| 567 | host->map_irq = bridge_map_irq; | ||
| 568 | host->swizzle_irq = pci_common_swizzle; | ||
| 569 | |||
| 570 | err = pci_scan_root_bus_bridge(host); | ||
| 571 | if (err < 0) | ||
| 572 | goto err_free_resource; | ||
| 573 | |||
| 574 | pci_bus_claim_resources(host->bus); | ||
| 575 | pci_bus_add_devices(host->bus); | ||
| 576 | |||
| 577 | platform_set_drvdata(pdev, host->bus); | ||
| 578 | |||
| 579 | return 0; | ||
| 580 | |||
| 581 | err_free_resource: | ||
| 582 | pci_free_resource_list(&host->windows); | ||
| 583 | err_remove_domain: | ||
| 584 | irq_domain_remove(domain); | ||
| 585 | return err; | ||
| 586 | } | ||
| 587 | |||
| 588 | static int bridge_remove(struct platform_device *pdev) | ||
| 589 | { | ||
| 590 | struct pci_bus *bus = platform_get_drvdata(pdev); | ||
| 591 | struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); | ||
| 592 | |||
| 593 | irq_domain_remove(bc->domain); | ||
| 594 | pci_lock_rescan_remove(); | ||
| 595 | pci_stop_root_bus(bus); | ||
| 596 | pci_remove_root_bus(bus); | ||
| 597 | pci_unlock_rescan_remove(); | ||
| 598 | |||
| 599 | return 0; | ||
| 600 | } | ||
| 601 | |||
| 602 | static struct platform_driver bridge_driver = { | ||
| 603 | .probe = bridge_probe, | ||
| 604 | .remove = bridge_remove, | ||
| 605 | .driver = { | ||
| 606 | .name = "xtalk-bridge", | ||
| 607 | } | ||
| 608 | }; | ||
| 609 | |||
| 610 | builtin_platform_driver(bridge_driver); | ||
diff --git a/arch/mips/pnx833x/Platform b/arch/mips/pnx833x/Platform index 794526caab12..6b1a847d593f 100644 --- a/arch/mips/pnx833x/Platform +++ b/arch/mips/pnx833x/Platform | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | # NXP STB225 | 1 | # NXP STB225 |
| 2 | platform-$(CONFIG_SOC_PNX833X) += pnx833x/ | 2 | platform-$(CONFIG_SOC_PNX833X) += pnx833x/ |
| 3 | cflags-$(CONFIG_SOC_PNX833X) += -Iarch/mips/include/asm/mach-pnx833x | 3 | cflags-$(CONFIG_SOC_PNX833X) += -I $(srctree)/arch/mips/include/asm/mach-pnx833x |
| 4 | load-$(CONFIG_NXP_STB220) += 0xffffffff80001000 | 4 | load-$(CONFIG_NXP_STB220) += 0xffffffff80001000 |
| 5 | load-$(CONFIG_NXP_STB225) += 0xffffffff80001000 | 5 | load-$(CONFIG_NXP_STB225) += 0xffffffff80001000 |
diff --git a/arch/mips/sgi-ip22/ip22-platform.c b/arch/mips/sgi-ip22/ip22-platform.c index 37ad26716579..0b2002e02a47 100644 --- a/arch/mips/sgi-ip22/ip22-platform.c +++ b/arch/mips/sgi-ip22/ip22-platform.c | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | #include <linux/if_ether.h> | 3 | #include <linux/if_ether.h> |
| 4 | #include <linux/kernel.h> | 4 | #include <linux/kernel.h> |
| 5 | #include <linux/platform_device.h> | 5 | #include <linux/platform_device.h> |
| 6 | #include <linux/dma-mapping.h> | ||
| 6 | 7 | ||
| 7 | #include <asm/paccess.h> | 8 | #include <asm/paccess.h> |
| 8 | #include <asm/sgi/ip22.h> | 9 | #include <asm/sgi/ip22.h> |
| @@ -25,6 +26,8 @@ static struct sgiwd93_platform_data sgiwd93_0_pd = { | |||
| 25 | .irq = SGI_WD93_0_IRQ, | 26 | .irq = SGI_WD93_0_IRQ, |
| 26 | }; | 27 | }; |
| 27 | 28 | ||
| 29 | static u64 sgiwd93_0_dma_mask = DMA_BIT_MASK(32); | ||
| 30 | |||
| 28 | static struct platform_device sgiwd93_0_device = { | 31 | static struct platform_device sgiwd93_0_device = { |
| 29 | .name = "sgiwd93", | 32 | .name = "sgiwd93", |
| 30 | .id = 0, | 33 | .id = 0, |
| @@ -32,6 +35,8 @@ static struct platform_device sgiwd93_0_device = { | |||
| 32 | .resource = sgiwd93_0_resources, | 35 | .resource = sgiwd93_0_resources, |
| 33 | .dev = { | 36 | .dev = { |
| 34 | .platform_data = &sgiwd93_0_pd, | 37 | .platform_data = &sgiwd93_0_pd, |
| 38 | .dma_mask = &sgiwd93_0_dma_mask, | ||
| 39 | .coherent_dma_mask = DMA_BIT_MASK(32), | ||
| 35 | }, | 40 | }, |
| 36 | }; | 41 | }; |
| 37 | 42 | ||
| @@ -49,6 +54,8 @@ static struct sgiwd93_platform_data sgiwd93_1_pd = { | |||
| 49 | .irq = SGI_WD93_1_IRQ, | 54 | .irq = SGI_WD93_1_IRQ, |
| 50 | }; | 55 | }; |
| 51 | 56 | ||
| 57 | static u64 sgiwd93_1_dma_mask = DMA_BIT_MASK(32); | ||
| 58 | |||
| 52 | static struct platform_device sgiwd93_1_device = { | 59 | static struct platform_device sgiwd93_1_device = { |
| 53 | .name = "sgiwd93", | 60 | .name = "sgiwd93", |
| 54 | .id = 1, | 61 | .id = 1, |
| @@ -56,6 +63,8 @@ static struct platform_device sgiwd93_1_device = { | |||
| 56 | .resource = sgiwd93_1_resources, | 63 | .resource = sgiwd93_1_resources, |
| 57 | .dev = { | 64 | .dev = { |
| 58 | .platform_data = &sgiwd93_1_pd, | 65 | .platform_data = &sgiwd93_1_pd, |
| 66 | .dma_mask = &sgiwd93_1_dma_mask, | ||
| 67 | .coherent_dma_mask = DMA_BIT_MASK(32), | ||
| 59 | }, | 68 | }, |
| 60 | }; | 69 | }; |
| 61 | 70 | ||
| @@ -96,6 +105,8 @@ static struct resource sgiseeq_0_resources[] = { | |||
| 96 | 105 | ||
| 97 | static struct sgiseeq_platform_data eth0_pd; | 106 | static struct sgiseeq_platform_data eth0_pd; |
| 98 | 107 | ||
| 108 | static u64 sgiseeq_dma_mask = DMA_BIT_MASK(32); | ||
| 109 | |||
| 99 | static struct platform_device eth0_device = { | 110 | static struct platform_device eth0_device = { |
| 100 | .name = "sgiseeq", | 111 | .name = "sgiseeq", |
| 101 | .id = 0, | 112 | .id = 0, |
| @@ -103,6 +114,8 @@ static struct platform_device eth0_device = { | |||
| 103 | .resource = sgiseeq_0_resources, | 114 | .resource = sgiseeq_0_resources, |
| 104 | .dev = { | 115 | .dev = { |
| 105 | .platform_data = ð0_pd, | 116 | .platform_data = ð0_pd, |
| 117 | .dma_mask = &sgiseeq_dma_mask, | ||
| 118 | .coherent_dma_mask = DMA_BIT_MASK(32), | ||
| 106 | }, | 119 | }, |
| 107 | }; | 120 | }; |
| 108 | 121 | ||
diff --git a/arch/mips/sgi-ip27/ip27-init.c b/arch/mips/sgi-ip27/ip27-init.c index 6074efeff894..066b33f50bcc 100644 --- a/arch/mips/sgi-ip27/ip27-init.c +++ b/arch/mips/sgi-ip27/ip27-init.c | |||
| @@ -184,5 +184,7 @@ void __init plat_mem_setup(void) | |||
| 184 | 184 | ||
| 185 | ioc3_eth_init(); | 185 | ioc3_eth_init(); |
| 186 | 186 | ||
| 187 | ioport_resource.start = 0; | ||
| 188 | ioport_resource.end = ~0UL; | ||
| 187 | set_io_port_base(IO_BASE); | 189 | set_io_port_base(IO_BASE); |
| 188 | } | 190 | } |
diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c index a32f843cdbe0..37be04975831 100644 --- a/arch/mips/sgi-ip27/ip27-irq.c +++ b/arch/mips/sgi-ip27/ip27-irq.c | |||
| @@ -12,22 +12,20 @@ | |||
| 12 | #include <linux/ioport.h> | 12 | #include <linux/ioport.h> |
| 13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
| 14 | #include <linux/bitops.h> | 14 | #include <linux/bitops.h> |
| 15 | #include <linux/sched.h> | ||
| 15 | 16 | ||
| 16 | #include <asm/io.h> | 17 | #include <asm/io.h> |
| 17 | #include <asm/irq_cpu.h> | 18 | #include <asm/irq_cpu.h> |
| 18 | #include <asm/pci/bridge.h> | ||
| 19 | #include <asm/sn/addrs.h> | 19 | #include <asm/sn/addrs.h> |
| 20 | #include <asm/sn/agent.h> | 20 | #include <asm/sn/agent.h> |
| 21 | #include <asm/sn/arch.h> | 21 | #include <asm/sn/arch.h> |
| 22 | #include <asm/sn/hub.h> | 22 | #include <asm/sn/hub.h> |
| 23 | #include <asm/sn/intr.h> | 23 | #include <asm/sn/intr.h> |
| 24 | #include <asm/sn/irq_alloc.h> | ||
| 24 | 25 | ||
| 25 | struct hub_irq_data { | 26 | struct hub_irq_data { |
| 26 | struct bridge_controller *bc; | ||
| 27 | u64 *irq_mask[2]; | 27 | u64 *irq_mask[2]; |
| 28 | cpuid_t cpu; | 28 | cpuid_t cpu; |
| 29 | int bit; | ||
| 30 | int pin; | ||
| 31 | }; | 29 | }; |
| 32 | 30 | ||
| 33 | static DECLARE_BITMAP(hub_irq_map, IP27_HUB_IRQ_COUNT); | 31 | static DECLARE_BITMAP(hub_irq_map, IP27_HUB_IRQ_COUNT); |
| @@ -54,7 +52,7 @@ static void enable_hub_irq(struct irq_data *d) | |||
| 54 | struct hub_irq_data *hd = irq_data_get_irq_chip_data(d); | 52 | struct hub_irq_data *hd = irq_data_get_irq_chip_data(d); |
| 55 | unsigned long *mask = per_cpu(irq_enable_mask, hd->cpu); | 53 | unsigned long *mask = per_cpu(irq_enable_mask, hd->cpu); |
| 56 | 54 | ||
| 57 | set_bit(hd->bit, mask); | 55 | set_bit(d->hwirq, mask); |
| 58 | __raw_writeq(mask[0], hd->irq_mask[0]); | 56 | __raw_writeq(mask[0], hd->irq_mask[0]); |
| 59 | __raw_writeq(mask[1], hd->irq_mask[1]); | 57 | __raw_writeq(mask[1], hd->irq_mask[1]); |
| 60 | } | 58 | } |
| @@ -64,71 +62,11 @@ static void disable_hub_irq(struct irq_data *d) | |||
| 64 | struct hub_irq_data *hd = irq_data_get_irq_chip_data(d); | 62 | struct hub_irq_data *hd = irq_data_get_irq_chip_data(d); |
| 65 | unsigned long *mask = per_cpu(irq_enable_mask, hd->cpu); | 63 | unsigned long *mask = per_cpu(irq_enable_mask, hd->cpu); |
| 66 | 64 | ||
| 67 | clear_bit(hd->bit, mask); | 65 | clear_bit(d->hwirq, mask); |
| 68 | __raw_writeq(mask[0], hd->irq_mask[0]); | 66 | __raw_writeq(mask[0], hd->irq_mask[0]); |
| 69 | __raw_writeq(mask[1], hd->irq_mask[1]); | 67 | __raw_writeq(mask[1], hd->irq_mask[1]); |
| 70 | } | 68 | } |
| 71 | 69 | ||
| 72 | static unsigned int startup_bridge_irq(struct irq_data *d) | ||
| 73 | { | ||
| 74 | struct hub_irq_data *hd = irq_data_get_irq_chip_data(d); | ||
| 75 | struct bridge_controller *bc; | ||
| 76 | nasid_t nasid; | ||
| 77 | u32 device; | ||
| 78 | int pin; | ||
| 79 | |||
| 80 | if (!hd) | ||
| 81 | return -EINVAL; | ||
| 82 | |||
| 83 | pin = hd->pin; | ||
| 84 | bc = hd->bc; | ||
| 85 | |||
| 86 | nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(hd->cpu)); | ||
| 87 | bridge_write(bc, b_int_addr[pin].addr, | ||
| 88 | (0x20000 | hd->bit | (nasid << 8))); | ||
| 89 | bridge_set(bc, b_int_enable, (1 << pin)); | ||
| 90 | bridge_set(bc, b_int_enable, 0x7ffffe00); /* more stuff in int_enable */ | ||
| 91 | |||
| 92 | /* | ||
| 93 | * Enable sending of an interrupt clear packt to the hub on a high to | ||
| 94 | * low transition of the interrupt pin. | ||
| 95 | * | ||
| 96 | * IRIX sets additional bits in the address which are documented as | ||
| 97 | * reserved in the bridge docs. | ||
| 98 | */ | ||
| 99 | bridge_set(bc, b_int_mode, (1UL << pin)); | ||
| 100 | |||
| 101 | /* | ||
| 102 | * We assume the bridge to have a 1:1 mapping between devices | ||
| 103 | * (slots) and intr pins. | ||
| 104 | */ | ||
| 105 | device = bridge_read(bc, b_int_device); | ||
| 106 | device &= ~(7 << (pin*3)); | ||
| 107 | device |= (pin << (pin*3)); | ||
| 108 | bridge_write(bc, b_int_device, device); | ||
| 109 | |||
| 110 | bridge_read(bc, b_wid_tflush); | ||
| 111 | |||
| 112 | enable_hub_irq(d); | ||
| 113 | |||
| 114 | return 0; /* Never anything pending. */ | ||
| 115 | } | ||
| 116 | |||
| 117 | static void shutdown_bridge_irq(struct irq_data *d) | ||
| 118 | { | ||
| 119 | struct hub_irq_data *hd = irq_data_get_irq_chip_data(d); | ||
| 120 | struct bridge_controller *bc; | ||
| 121 | |||
| 122 | if (!hd) | ||
| 123 | return; | ||
| 124 | |||
| 125 | disable_hub_irq(d); | ||
| 126 | |||
| 127 | bc = hd->bc; | ||
| 128 | bridge_clr(bc, b_int_enable, (1 << hd->pin)); | ||
| 129 | bridge_read(bc, b_wid_tflush); | ||
| 130 | } | ||
| 131 | |||
| 132 | static void setup_hub_mask(struct hub_irq_data *hd, const struct cpumask *mask) | 70 | static void setup_hub_mask(struct hub_irq_data *hd, const struct cpumask *mask) |
| 133 | { | 71 | { |
| 134 | nasid_t nasid; | 72 | nasid_t nasid; |
| @@ -144,9 +82,6 @@ static void setup_hub_mask(struct hub_irq_data *hd, const struct cpumask *mask) | |||
| 144 | hd->irq_mask[0] = REMOTE_HUB_PTR(nasid, PI_INT_MASK0_B); | 82 | hd->irq_mask[0] = REMOTE_HUB_PTR(nasid, PI_INT_MASK0_B); |
| 145 | hd->irq_mask[1] = REMOTE_HUB_PTR(nasid, PI_INT_MASK1_B); | 83 | hd->irq_mask[1] = REMOTE_HUB_PTR(nasid, PI_INT_MASK1_B); |
| 146 | } | 84 | } |
| 147 | |||
| 148 | /* Make sure it's not already pending when we connect it. */ | ||
| 149 | REMOTE_HUB_CLR_INTR(nasid, hd->bit); | ||
| 150 | } | 85 | } |
| 151 | 86 | ||
| 152 | static int set_affinity_hub_irq(struct irq_data *d, const struct cpumask *mask, | 87 | static int set_affinity_hub_irq(struct irq_data *d, const struct cpumask *mask, |
| @@ -163,7 +98,7 @@ static int set_affinity_hub_irq(struct irq_data *d, const struct cpumask *mask, | |||
| 163 | setup_hub_mask(hd, mask); | 98 | setup_hub_mask(hd, mask); |
| 164 | 99 | ||
| 165 | if (irqd_is_started(d)) | 100 | if (irqd_is_started(d)) |
| 166 | startup_bridge_irq(d); | 101 | enable_hub_irq(d); |
| 167 | 102 | ||
| 168 | irq_data_update_effective_affinity(d, cpumask_of(hd->cpu)); | 103 | irq_data_update_effective_affinity(d, cpumask_of(hd->cpu)); |
| 169 | 104 | ||
| @@ -172,20 +107,22 @@ static int set_affinity_hub_irq(struct irq_data *d, const struct cpumask *mask, | |||
| 172 | 107 | ||
| 173 | static struct irq_chip hub_irq_type = { | 108 | static struct irq_chip hub_irq_type = { |
| 174 | .name = "HUB", | 109 | .name = "HUB", |
| 175 | .irq_startup = startup_bridge_irq, | ||
| 176 | .irq_shutdown = shutdown_bridge_irq, | ||
| 177 | .irq_mask = disable_hub_irq, | 110 | .irq_mask = disable_hub_irq, |
| 178 | .irq_unmask = enable_hub_irq, | 111 | .irq_unmask = enable_hub_irq, |
| 179 | .irq_set_affinity = set_affinity_hub_irq, | 112 | .irq_set_affinity = set_affinity_hub_irq, |
| 180 | }; | 113 | }; |
| 181 | 114 | ||
| 182 | int request_bridge_irq(struct bridge_controller *bc, int pin) | 115 | static int hub_domain_alloc(struct irq_domain *domain, unsigned int virq, |
| 116 | unsigned int nr_irqs, void *arg) | ||
| 183 | { | 117 | { |
| 118 | struct irq_alloc_info *info = arg; | ||
| 184 | struct hub_irq_data *hd; | 119 | struct hub_irq_data *hd; |
| 185 | struct hub_data *hub; | 120 | struct hub_data *hub; |
| 186 | struct irq_desc *desc; | 121 | struct irq_desc *desc; |
| 187 | int swlevel; | 122 | int swlevel; |
| 188 | int irq; | 123 | |
| 124 | if (nr_irqs > 1 || !info) | ||
| 125 | return -EINVAL; | ||
| 189 | 126 | ||
| 190 | hd = kzalloc(sizeof(*hd), GFP_KERNEL); | 127 | hd = kzalloc(sizeof(*hd), GFP_KERNEL); |
| 191 | if (!hd) | 128 | if (!hd) |
| @@ -196,46 +133,41 @@ int request_bridge_irq(struct bridge_controller *bc, int pin) | |||
| 196 | kfree(hd); | 133 | kfree(hd); |
| 197 | return -EAGAIN; | 134 | return -EAGAIN; |
| 198 | } | 135 | } |
| 199 | irq = swlevel + IP27_HUB_IRQ_BASE; | 136 | irq_domain_set_info(domain, virq, swlevel, &hub_irq_type, hd, |
| 200 | 137 | handle_level_irq, NULL, NULL); | |
| 201 | hd->bc = bc; | ||
| 202 | hd->bit = swlevel; | ||
| 203 | hd->pin = pin; | ||
| 204 | irq_set_chip_data(irq, hd); | ||
| 205 | 138 | ||
| 206 | /* use CPU connected to nearest hub */ | 139 | /* use CPU connected to nearest hub */ |
| 207 | hub = hub_data(NASID_TO_COMPACT_NODEID(bc->nasid)); | 140 | hub = hub_data(NASID_TO_COMPACT_NODEID(info->nasid)); |
| 208 | setup_hub_mask(hd, &hub->h_cpus); | 141 | setup_hub_mask(hd, &hub->h_cpus); |
| 209 | 142 | ||
| 210 | desc = irq_to_desc(irq); | 143 | /* Make sure it's not already pending when we connect it. */ |
| 211 | desc->irq_common_data.node = bc->nasid; | 144 | REMOTE_HUB_CLR_INTR(info->nasid, swlevel); |
| 145 | |||
| 146 | desc = irq_to_desc(virq); | ||
| 147 | desc->irq_common_data.node = info->nasid; | ||
| 212 | cpumask_copy(desc->irq_common_data.affinity, &hub->h_cpus); | 148 | cpumask_copy(desc->irq_common_data.affinity, &hub->h_cpus); |
| 213 | 149 | ||
| 214 | return irq; | 150 | return 0; |
| 215 | } | 151 | } |
| 216 | 152 | ||
| 217 | void ip27_hub_irq_init(void) | 153 | static void hub_domain_free(struct irq_domain *domain, |
| 154 | unsigned int virq, unsigned int nr_irqs) | ||
| 218 | { | 155 | { |
| 219 | int i; | 156 | struct irq_data *irqd; |
| 220 | 157 | ||
| 221 | for (i = IP27_HUB_IRQ_BASE; | 158 | if (nr_irqs > 1) |
| 222 | i < (IP27_HUB_IRQ_BASE + IP27_HUB_IRQ_COUNT); i++) | 159 | return; |
| 223 | irq_set_chip_and_handler(i, &hub_irq_type, handle_level_irq); | ||
| 224 | |||
| 225 | /* | ||
| 226 | * Some interrupts are reserved by hardware or by software convention. | ||
| 227 | * Mark these as reserved right away so they won't be used accidentally | ||
| 228 | * later. | ||
| 229 | */ | ||
| 230 | for (i = 0; i <= BASE_PCI_IRQ; i++) | ||
| 231 | set_bit(i, hub_irq_map); | ||
| 232 | |||
| 233 | set_bit(IP_PEND0_6_63, hub_irq_map); | ||
| 234 | 160 | ||
| 235 | for (i = NI_BRDCAST_ERR_A; i <= MSC_PANIC_INTR; i++) | 161 | irqd = irq_domain_get_irq_data(domain, virq); |
| 236 | set_bit(i, hub_irq_map); | 162 | if (irqd && irqd->chip_data) |
| 163 | kfree(irqd->chip_data); | ||
| 237 | } | 164 | } |
| 238 | 165 | ||
| 166 | static const struct irq_domain_ops hub_domain_ops = { | ||
| 167 | .alloc = hub_domain_alloc, | ||
| 168 | .free = hub_domain_free, | ||
| 169 | }; | ||
| 170 | |||
| 239 | /* | 171 | /* |
| 240 | * This code is unnecessarily complex, because we do | 172 | * This code is unnecessarily complex, because we do |
| 241 | * intr enabling. Basically, once we grab the set of intrs we need | 173 | * intr enabling. Basically, once we grab the set of intrs we need |
| @@ -252,7 +184,9 @@ static void ip27_do_irq_mask0(struct irq_desc *desc) | |||
| 252 | { | 184 | { |
| 253 | cpuid_t cpu = smp_processor_id(); | 185 | cpuid_t cpu = smp_processor_id(); |
| 254 | unsigned long *mask = per_cpu(irq_enable_mask, cpu); | 186 | unsigned long *mask = per_cpu(irq_enable_mask, cpu); |
| 187 | struct irq_domain *domain; | ||
| 255 | u64 pend0; | 188 | u64 pend0; |
| 189 | int irq; | ||
| 256 | 190 | ||
| 257 | /* copied from Irix intpend0() */ | 191 | /* copied from Irix intpend0() */ |
| 258 | pend0 = LOCAL_HUB_L(PI_INT_PEND0); | 192 | pend0 = LOCAL_HUB_L(PI_INT_PEND0); |
| @@ -276,7 +210,14 @@ static void ip27_do_irq_mask0(struct irq_desc *desc) | |||
| 276 | generic_smp_call_function_interrupt(); | 210 | generic_smp_call_function_interrupt(); |
| 277 | } else | 211 | } else |
| 278 | #endif | 212 | #endif |
| 279 | generic_handle_irq(__ffs(pend0) + IP27_HUB_IRQ_BASE); | 213 | { |
| 214 | domain = irq_desc_get_handler_data(desc); | ||
| 215 | irq = irq_linear_revmap(domain, __ffs(pend0)); | ||
| 216 | if (irq) | ||
| 217 | generic_handle_irq(irq); | ||
| 218 | else | ||
| 219 | spurious_interrupt(); | ||
| 220 | } | ||
| 280 | 221 | ||
| 281 | LOCAL_HUB_L(PI_INT_PEND0); | 222 | LOCAL_HUB_L(PI_INT_PEND0); |
| 282 | } | 223 | } |
| @@ -285,7 +226,9 @@ static void ip27_do_irq_mask1(struct irq_desc *desc) | |||
| 285 | { | 226 | { |
| 286 | cpuid_t cpu = smp_processor_id(); | 227 | cpuid_t cpu = smp_processor_id(); |
| 287 | unsigned long *mask = per_cpu(irq_enable_mask, cpu); | 228 | unsigned long *mask = per_cpu(irq_enable_mask, cpu); |
| 229 | struct irq_domain *domain; | ||
| 288 | u64 pend1; | 230 | u64 pend1; |
| 231 | int irq; | ||
| 289 | 232 | ||
| 290 | /* copied from Irix intpend0() */ | 233 | /* copied from Irix intpend0() */ |
| 291 | pend1 = LOCAL_HUB_L(PI_INT_PEND1); | 234 | pend1 = LOCAL_HUB_L(PI_INT_PEND1); |
| @@ -294,7 +237,12 @@ static void ip27_do_irq_mask1(struct irq_desc *desc) | |||
| 294 | if (!pend1) | 237 | if (!pend1) |
| 295 | return; | 238 | return; |
| 296 | 239 | ||
| 297 | generic_handle_irq(__ffs(pend1) + IP27_HUB_IRQ_BASE + 64); | 240 | domain = irq_desc_get_handler_data(desc); |
| 241 | irq = irq_linear_revmap(domain, __ffs(pend1) + 64); | ||
| 242 | if (irq) | ||
| 243 | generic_handle_irq(irq); | ||
| 244 | else | ||
| 245 | spurious_interrupt(); | ||
| 298 | 246 | ||
| 299 | LOCAL_HUB_L(PI_INT_PEND1); | 247 | LOCAL_HUB_L(PI_INT_PEND1); |
| 300 | } | 248 | } |
| @@ -325,11 +273,41 @@ void install_ipi(void) | |||
| 325 | 273 | ||
| 326 | void __init arch_init_irq(void) | 274 | void __init arch_init_irq(void) |
| 327 | { | 275 | { |
| 276 | struct irq_domain *domain; | ||
| 277 | struct fwnode_handle *fn; | ||
| 278 | int i; | ||
| 279 | |||
| 328 | mips_cpu_irq_init(); | 280 | mips_cpu_irq_init(); |
| 329 | ip27_hub_irq_init(); | 281 | |
| 282 | /* | ||
| 283 | * Some interrupts are reserved by hardware or by software convention. | ||
| 284 | * Mark these as reserved right away so they won't be used accidentally | ||
| 285 | * later. | ||
| 286 | */ | ||
| 287 | for (i = 0; i <= BASE_PCI_IRQ; i++) | ||
| 288 | set_bit(i, hub_irq_map); | ||
| 289 | |||
| 290 | set_bit(IP_PEND0_6_63, hub_irq_map); | ||
| 291 | |||
| 292 | for (i = NI_BRDCAST_ERR_A; i <= MSC_PANIC_INTR; i++) | ||
| 293 | set_bit(i, hub_irq_map); | ||
| 294 | |||
| 295 | fn = irq_domain_alloc_named_fwnode("HUB"); | ||
| 296 | WARN_ON(fn == NULL); | ||
| 297 | if (!fn) | ||
| 298 | return; | ||
| 299 | domain = irq_domain_create_linear(fn, IP27_HUB_IRQ_COUNT, | ||
| 300 | &hub_domain_ops, NULL); | ||
| 301 | WARN_ON(domain == NULL); | ||
| 302 | if (!domain) | ||
| 303 | return; | ||
| 304 | |||
| 305 | irq_set_default_host(domain); | ||
| 330 | 306 | ||
| 331 | irq_set_percpu_devid(IP27_HUB_PEND0_IRQ); | 307 | irq_set_percpu_devid(IP27_HUB_PEND0_IRQ); |
| 332 | irq_set_chained_handler(IP27_HUB_PEND0_IRQ, ip27_do_irq_mask0); | 308 | irq_set_chained_handler_and_data(IP27_HUB_PEND0_IRQ, ip27_do_irq_mask0, |
| 309 | domain); | ||
| 333 | irq_set_percpu_devid(IP27_HUB_PEND1_IRQ); | 310 | irq_set_percpu_devid(IP27_HUB_PEND1_IRQ); |
| 334 | irq_set_chained_handler(IP27_HUB_PEND1_IRQ, ip27_do_irq_mask1); | 311 | irq_set_chained_handler_and_data(IP27_HUB_PEND1_IRQ, ip27_do_irq_mask1, |
| 312 | domain); | ||
| 335 | } | 313 | } |
diff --git a/arch/mips/sgi-ip27/ip27-xtalk.c b/arch/mips/sgi-ip27/ip27-xtalk.c index ce06aaa115ae..bd5cb855c6e5 100644 --- a/arch/mips/sgi-ip27/ip27-xtalk.c +++ b/arch/mips/sgi-ip27/ip27-xtalk.c | |||
| @@ -9,6 +9,9 @@ | |||
| 9 | 9 | ||
| 10 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
| 11 | #include <linux/smp.h> | 11 | #include <linux/smp.h> |
| 12 | #include <linux/platform_device.h> | ||
| 13 | #include <linux/platform_data/xtalk-bridge.h> | ||
| 14 | #include <asm/sn/addrs.h> | ||
| 12 | #include <asm/sn/types.h> | 15 | #include <asm/sn/types.h> |
| 13 | #include <asm/sn/klconfig.h> | 16 | #include <asm/sn/klconfig.h> |
| 14 | #include <asm/sn/hub.h> | 17 | #include <asm/sn/hub.h> |
| @@ -20,7 +23,48 @@ | |||
| 20 | #define XXBOW_WIDGET_PART_NUM 0xd000 /* Xbow in Xbridge */ | 23 | #define XXBOW_WIDGET_PART_NUM 0xd000 /* Xbow in Xbridge */ |
| 21 | #define BASE_XBOW_PORT 8 /* Lowest external port */ | 24 | #define BASE_XBOW_PORT 8 /* Lowest external port */ |
| 22 | 25 | ||
| 23 | extern int bridge_probe(nasid_t nasid, int widget, int masterwid); | 26 | static void bridge_platform_create(nasid_t nasid, int widget, int masterwid) |
| 27 | { | ||
| 28 | struct xtalk_bridge_platform_data *bd; | ||
| 29 | struct platform_device *pdev; | ||
| 30 | unsigned long offset; | ||
| 31 | |||
| 32 | bd = kzalloc(sizeof(*bd), GFP_KERNEL); | ||
| 33 | if (!bd) | ||
| 34 | goto no_mem; | ||
| 35 | pdev = platform_device_alloc("xtalk-bridge", PLATFORM_DEVID_AUTO); | ||
| 36 | if (!pdev) { | ||
| 37 | kfree(bd); | ||
| 38 | goto no_mem; | ||
| 39 | } | ||
| 40 | |||
| 41 | offset = NODE_OFFSET(nasid); | ||
| 42 | |||
| 43 | bd->bridge_addr = RAW_NODE_SWIN_BASE(nasid, widget); | ||
| 44 | bd->intr_addr = BIT_ULL(47) + 0x01800000 + PI_INT_PEND_MOD; | ||
| 45 | bd->nasid = nasid; | ||
| 46 | bd->masterwid = masterwid; | ||
| 47 | |||
| 48 | bd->mem.name = "Bridge PCI MEM"; | ||
| 49 | bd->mem.start = offset + (widget << SWIN_SIZE_BITS); | ||
| 50 | bd->mem.end = bd->mem.start + SWIN_SIZE - 1; | ||
| 51 | bd->mem.flags = IORESOURCE_MEM; | ||
| 52 | bd->mem_offset = offset; | ||
| 53 | |||
| 54 | bd->io.name = "Bridge PCI IO"; | ||
| 55 | bd->io.start = offset + (widget << SWIN_SIZE_BITS); | ||
| 56 | bd->io.end = bd->io.start + SWIN_SIZE - 1; | ||
| 57 | bd->io.flags = IORESOURCE_IO; | ||
| 58 | bd->io_offset = offset; | ||
| 59 | |||
| 60 | platform_device_add_data(pdev, bd, sizeof(*bd)); | ||
| 61 | platform_device_add(pdev); | ||
| 62 | pr_info("xtalk:n%d/%x bridge widget\n", nasid, widget); | ||
| 63 | return; | ||
| 64 | |||
| 65 | no_mem: | ||
| 66 | pr_warn("xtalk:n%d/%x bridge create out of memory\n", nasid, widget); | ||
| 67 | } | ||
| 24 | 68 | ||
| 25 | static int probe_one_port(nasid_t nasid, int widget, int masterwid) | 69 | static int probe_one_port(nasid_t nasid, int widget, int masterwid) |
| 26 | { | 70 | { |
| @@ -31,13 +75,10 @@ static int probe_one_port(nasid_t nasid, int widget, int masterwid) | |||
| 31 | (RAW_NODE_SWIN_BASE(nasid, widget) + WIDGET_ID); | 75 | (RAW_NODE_SWIN_BASE(nasid, widget) + WIDGET_ID); |
| 32 | partnum = XWIDGET_PART_NUM(widget_id); | 76 | partnum = XWIDGET_PART_NUM(widget_id); |
| 33 | 77 | ||
| 34 | printk(KERN_INFO "Cpu %d, Nasid 0x%x, widget 0x%x (partnum 0x%x) is ", | ||
| 35 | smp_processor_id(), nasid, widget, partnum); | ||
| 36 | |||
| 37 | switch (partnum) { | 78 | switch (partnum) { |
| 38 | case BRIDGE_WIDGET_PART_NUM: | 79 | case BRIDGE_WIDGET_PART_NUM: |
| 39 | case XBRIDGE_WIDGET_PART_NUM: | 80 | case XBRIDGE_WIDGET_PART_NUM: |
| 40 | bridge_probe(nasid, widget, masterwid); | 81 | bridge_platform_create(nasid, widget, masterwid); |
| 41 | break; | 82 | break; |
| 42 | default: | 83 | default: |
| 43 | break; | 84 | break; |
| @@ -52,8 +93,6 @@ static int xbow_probe(nasid_t nasid) | |||
| 52 | klxbow_t *xbow_p; | 93 | klxbow_t *xbow_p; |
| 53 | unsigned masterwid, i; | 94 | unsigned masterwid, i; |
| 54 | 95 | ||
| 55 | printk("is xbow\n"); | ||
| 56 | |||
| 57 | /* | 96 | /* |
| 58 | * found xbow, so may have multiple bridges | 97 | * found xbow, so may have multiple bridges |
| 59 | * need to probe xbow | 98 | * need to probe xbow |
| @@ -117,19 +156,17 @@ static void xtalk_probe_node(cnodeid_t nid) | |||
| 117 | (RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID); | 156 | (RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID); |
| 118 | partnum = XWIDGET_PART_NUM(widget_id); | 157 | partnum = XWIDGET_PART_NUM(widget_id); |
| 119 | 158 | ||
| 120 | printk(KERN_INFO "Cpu %d, Nasid 0x%x: partnum 0x%x is ", | ||
| 121 | smp_processor_id(), nasid, partnum); | ||
| 122 | |||
| 123 | switch (partnum) { | 159 | switch (partnum) { |
| 124 | case BRIDGE_WIDGET_PART_NUM: | 160 | case BRIDGE_WIDGET_PART_NUM: |
| 125 | bridge_probe(nasid, 0x8, 0xa); | 161 | bridge_platform_create(nasid, 0x8, 0xa); |
| 126 | break; | 162 | break; |
| 127 | case XBOW_WIDGET_PART_NUM: | 163 | case XBOW_WIDGET_PART_NUM: |
| 128 | case XXBOW_WIDGET_PART_NUM: | 164 | case XXBOW_WIDGET_PART_NUM: |
| 165 | pr_info("xtalk:n%d/0 xbow widget\n", nasid); | ||
| 129 | xbow_probe(nasid); | 166 | xbow_probe(nasid); |
| 130 | break; | 167 | break; |
| 131 | default: | 168 | default: |
| 132 | printk(" unknown widget??\n"); | 169 | pr_info("xtalk:n%d/0 unknown widget (0x%x)\n", nasid, partnum); |
| 133 | break; | 170 | break; |
| 134 | } | 171 | } |
| 135 | } | 172 | } |
diff --git a/arch/nds32/include/asm/Kbuild b/arch/nds32/include/asm/Kbuild index f43b44d692ca..f37d5004a01c 100644 --- a/arch/nds32/include/asm/Kbuild +++ b/arch/nds32/include/asm/Kbuild | |||
| @@ -4,10 +4,8 @@ generic-y += bitops.h | |||
| 4 | generic-y += bug.h | 4 | generic-y += bug.h |
| 5 | generic-y += bugs.h | 5 | generic-y += bugs.h |
| 6 | generic-y += checksum.h | 6 | generic-y += checksum.h |
| 7 | generic-y += clkdev.h | ||
| 8 | generic-y += cmpxchg.h | 7 | generic-y += cmpxchg.h |
| 9 | generic-y += compat.h | 8 | generic-y += compat.h |
| 10 | generic-y += cputime.h | ||
| 11 | generic-y += device.h | 9 | generic-y += device.h |
| 12 | generic-y += div64.h | 10 | generic-y += div64.h |
| 13 | generic-y += dma.h | 11 | generic-y += dma.h |
| @@ -26,7 +24,6 @@ generic-y += kdebug.h | |||
| 26 | generic-y += kmap_types.h | 24 | generic-y += kmap_types.h |
| 27 | generic-y += kprobes.h | 25 | generic-y += kprobes.h |
| 28 | generic-y += kvm_para.h | 26 | generic-y += kvm_para.h |
| 29 | generic-y += limits.h | ||
| 30 | generic-y += local.h | 27 | generic-y += local.h |
| 31 | generic-y += local64.h | 28 | generic-y += local64.h |
| 32 | generic-y += mm-arch-hooks.h | 29 | generic-y += mm-arch-hooks.h |
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index 258ea6b2f2e7..c345b79414a9 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile | |||
| @@ -211,7 +211,7 @@ endif | |||
| 211 | 211 | ||
| 212 | asinstr := $(call as-instr,lis 9$(comma)foo@high,-DHAVE_AS_ATHIGH=1) | 212 | asinstr := $(call as-instr,lis 9$(comma)foo@high,-DHAVE_AS_ATHIGH=1) |
| 213 | 213 | ||
| 214 | KBUILD_CPPFLAGS += -Iarch/$(ARCH) $(asinstr) | 214 | KBUILD_CPPFLAGS += -I $(srctree)/arch/$(ARCH) $(asinstr) |
| 215 | KBUILD_AFLAGS += $(AFLAGS-y) | 215 | KBUILD_AFLAGS += $(AFLAGS-y) |
| 216 | KBUILD_CFLAGS += $(call cc-option,-msoft-float) | 216 | KBUILD_CFLAGS += $(call cc-option,-msoft-float) |
| 217 | KBUILD_CFLAGS += -pipe $(CFLAGS-y) | 217 | KBUILD_CFLAGS += -pipe $(CFLAGS-y) |
diff --git a/arch/powerpc/include/asm/book3s/64/hash.h b/arch/powerpc/include/asm/book3s/64/hash.h index 1d1183048cfd..2781ebf6add4 100644 --- a/arch/powerpc/include/asm/book3s/64/hash.h +++ b/arch/powerpc/include/asm/book3s/64/hash.h | |||
| @@ -93,6 +93,7 @@ | |||
| 93 | #define VMALLOC_REGION_ID NON_LINEAR_REGION_ID(H_VMALLOC_START) | 93 | #define VMALLOC_REGION_ID NON_LINEAR_REGION_ID(H_VMALLOC_START) |
| 94 | #define IO_REGION_ID NON_LINEAR_REGION_ID(H_KERN_IO_START) | 94 | #define IO_REGION_ID NON_LINEAR_REGION_ID(H_KERN_IO_START) |
| 95 | #define VMEMMAP_REGION_ID NON_LINEAR_REGION_ID(H_VMEMMAP_START) | 95 | #define VMEMMAP_REGION_ID NON_LINEAR_REGION_ID(H_VMEMMAP_START) |
| 96 | #define INVALID_REGION_ID (VMEMMAP_REGION_ID + 1) | ||
| 96 | 97 | ||
| 97 | /* | 98 | /* |
| 98 | * Defines the address of the vmemap area, in its own region on | 99 | * Defines the address of the vmemap area, in its own region on |
| @@ -119,14 +120,15 @@ static inline int get_region_id(unsigned long ea) | |||
| 119 | if (id == 0) | 120 | if (id == 0) |
| 120 | return USER_REGION_ID; | 121 | return USER_REGION_ID; |
| 121 | 122 | ||
| 123 | if (id != (PAGE_OFFSET >> 60)) | ||
| 124 | return INVALID_REGION_ID; | ||
| 125 | |||
| 122 | if (ea < H_KERN_VIRT_START) | 126 | if (ea < H_KERN_VIRT_START) |
| 123 | return LINEAR_MAP_REGION_ID; | 127 | return LINEAR_MAP_REGION_ID; |
| 124 | 128 | ||
| 125 | VM_BUG_ON(id != 0xc); | ||
| 126 | BUILD_BUG_ON(NON_LINEAR_REGION_ID(H_VMALLOC_START) != 2); | 129 | BUILD_BUG_ON(NON_LINEAR_REGION_ID(H_VMALLOC_START) != 2); |
| 127 | 130 | ||
| 128 | region_id = NON_LINEAR_REGION_ID(ea); | 131 | region_id = NON_LINEAR_REGION_ID(ea); |
| 129 | VM_BUG_ON(region_id > VMEMMAP_REGION_ID); | ||
| 130 | return region_id; | 132 | return region_id; |
| 131 | } | 133 | } |
| 132 | 134 | ||
diff --git a/arch/powerpc/include/asm/mmu_context.h b/arch/powerpc/include/asm/mmu_context.h index 611204e588b9..58efca934311 100644 --- a/arch/powerpc/include/asm/mmu_context.h +++ b/arch/powerpc/include/asm/mmu_context.h | |||
| @@ -232,7 +232,6 @@ static inline void enter_lazy_tlb(struct mm_struct *mm, | |||
| 232 | extern void arch_exit_mmap(struct mm_struct *mm); | 232 | extern void arch_exit_mmap(struct mm_struct *mm); |
| 233 | 233 | ||
| 234 | static inline void arch_unmap(struct mm_struct *mm, | 234 | static inline void arch_unmap(struct mm_struct *mm, |
| 235 | struct vm_area_struct *vma, | ||
| 236 | unsigned long start, unsigned long end) | 235 | unsigned long start, unsigned long end) |
| 237 | { | 236 | { |
| 238 | if (start <= mm->context.vdso_base && mm->context.vdso_base < end) | 237 | if (start <= mm->context.vdso_base && mm->context.vdso_base < end) |
diff --git a/arch/powerpc/kernel/cacheinfo.c b/arch/powerpc/kernel/cacheinfo.c index f2ed3ef4b129..862e2890bd3d 100644 --- a/arch/powerpc/kernel/cacheinfo.c +++ b/arch/powerpc/kernel/cacheinfo.c | |||
| @@ -767,7 +767,6 @@ static void cacheinfo_create_index_dir(struct cache *cache, int index, | |||
| 767 | cache_dir->kobj, "index%d", index); | 767 | cache_dir->kobj, "index%d", index); |
| 768 | if (rc) { | 768 | if (rc) { |
| 769 | kobject_put(&index_dir->kobj); | 769 | kobject_put(&index_dir->kobj); |
| 770 | kfree(index_dir); | ||
| 771 | return; | 770 | return; |
| 772 | } | 771 | } |
| 773 | 772 | ||
diff --git a/arch/powerpc/mm/book3s32/hash_low.S b/arch/powerpc/mm/book3s32/hash_low.S index e27792d0b744..8366c2abeafc 100644 --- a/arch/powerpc/mm/book3s32/hash_low.S +++ b/arch/powerpc/mm/book3s32/hash_low.S | |||
| @@ -539,7 +539,8 @@ _GLOBAL(flush_hash_pages) | |||
| 539 | #ifdef CONFIG_SMP | 539 | #ifdef CONFIG_SMP |
| 540 | lis r9, (mmu_hash_lock - PAGE_OFFSET)@ha | 540 | lis r9, (mmu_hash_lock - PAGE_OFFSET)@ha |
| 541 | addi r9, r9, (mmu_hash_lock - PAGE_OFFSET)@l | 541 | addi r9, r9, (mmu_hash_lock - PAGE_OFFSET)@l |
| 542 | lwz r8,TASK_CPU(r2) | 542 | tophys (r8, r2) |
| 543 | lwz r8, TASK_CPU(r8) | ||
| 543 | oris r8,r8,9 | 544 | oris r8,r8,9 |
| 544 | 10: lwarx r0,0,r9 | 545 | 10: lwarx r0,0,r9 |
| 545 | cmpi 0,r0,0 | 546 | cmpi 0,r0,0 |
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index c5c9ff2d7afc..b5d92dc32844 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c | |||
| @@ -556,7 +556,7 @@ static int __init add_huge_page_size(unsigned long long size) | |||
| 556 | if (size <= PAGE_SIZE || !is_power_of_2(size)) | 556 | if (size <= PAGE_SIZE || !is_power_of_2(size)) |
| 557 | return -EINVAL; | 557 | return -EINVAL; |
| 558 | 558 | ||
| 559 | mmu_psize = check_and_get_huge_psize(size); | 559 | mmu_psize = check_and_get_huge_psize(shift); |
| 560 | if (mmu_psize < 0) | 560 | if (mmu_psize < 0) |
| 561 | return -EINVAL; | 561 | return -EINVAL; |
| 562 | 562 | ||
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index e66745decea1..ee32c66e1af3 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig | |||
| @@ -27,7 +27,7 @@ config RISCV | |||
| 27 | select GENERIC_STRNCPY_FROM_USER | 27 | select GENERIC_STRNCPY_FROM_USER |
| 28 | select GENERIC_STRNLEN_USER | 28 | select GENERIC_STRNLEN_USER |
| 29 | select GENERIC_SMP_IDLE_THREAD | 29 | select GENERIC_SMP_IDLE_THREAD |
| 30 | select GENERIC_ATOMIC64 if !64BIT || !RISCV_ISA_A | 30 | select GENERIC_ATOMIC64 if !64BIT |
| 31 | select HAVE_ARCH_AUDITSYSCALL | 31 | select HAVE_ARCH_AUDITSYSCALL |
| 32 | select HAVE_MEMBLOCK_NODE_MAP | 32 | select HAVE_MEMBLOCK_NODE_MAP |
| 33 | select HAVE_DMA_CONTIGUOUS | 33 | select HAVE_DMA_CONTIGUOUS |
| @@ -35,7 +35,6 @@ config RISCV | |||
| 35 | select HAVE_PERF_EVENTS | 35 | select HAVE_PERF_EVENTS |
| 36 | select HAVE_SYSCALL_TRACEPOINTS | 36 | select HAVE_SYSCALL_TRACEPOINTS |
| 37 | select IRQ_DOMAIN | 37 | select IRQ_DOMAIN |
| 38 | select RISCV_ISA_A if SMP | ||
| 39 | select SPARSE_IRQ | 38 | select SPARSE_IRQ |
| 40 | select SYSCTL_EXCEPTION_TRACE | 39 | select SYSCTL_EXCEPTION_TRACE |
| 41 | select HAVE_ARCH_TRACEHOOK | 40 | select HAVE_ARCH_TRACEHOOK |
| @@ -195,9 +194,6 @@ config RISCV_ISA_C | |||
| 195 | 194 | ||
| 196 | If you don't know what to do here, say Y. | 195 | If you don't know what to do here, say Y. |
| 197 | 196 | ||
| 198 | config RISCV_ISA_A | ||
| 199 | def_bool y | ||
| 200 | |||
| 201 | menu "supported PMU type" | 197 | menu "supported PMU type" |
| 202 | depends on PERF_EVENTS | 198 | depends on PERF_EVENTS |
| 203 | 199 | ||
diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile index c6342e638ef7..6b0741c9f348 100644 --- a/arch/riscv/Makefile +++ b/arch/riscv/Makefile | |||
| @@ -39,9 +39,8 @@ endif | |||
| 39 | KBUILD_CFLAGS += -Wall | 39 | KBUILD_CFLAGS += -Wall |
| 40 | 40 | ||
| 41 | # ISA string setting | 41 | # ISA string setting |
| 42 | riscv-march-$(CONFIG_ARCH_RV32I) := rv32im | 42 | riscv-march-$(CONFIG_ARCH_RV32I) := rv32ima |
| 43 | riscv-march-$(CONFIG_ARCH_RV64I) := rv64im | 43 | riscv-march-$(CONFIG_ARCH_RV64I) := rv64ima |
| 44 | riscv-march-$(CONFIG_RISCV_ISA_A) := $(riscv-march-y)a | ||
| 45 | riscv-march-$(CONFIG_FPU) := $(riscv-march-y)fd | 44 | riscv-march-$(CONFIG_FPU) := $(riscv-march-y)fd |
| 46 | riscv-march-$(CONFIG_RISCV_ISA_C) := $(riscv-march-y)c | 45 | riscv-march-$(CONFIG_RISCV_ISA_C) := $(riscv-march-y)c |
| 47 | KBUILD_CFLAGS += -march=$(subst fd,,$(riscv-march-y)) | 46 | KBUILD_CFLAGS += -march=$(subst fd,,$(riscv-march-y)) |
diff --git a/arch/riscv/include/asm/Kbuild b/arch/riscv/include/asm/Kbuild index cccd12cf27d4..3d019e062c6f 100644 --- a/arch/riscv/include/asm/Kbuild +++ b/arch/riscv/include/asm/Kbuild | |||
| @@ -1,9 +1,9 @@ | |||
| 1 | generic-y += bugs.h | 1 | generic-y += bugs.h |
| 2 | generic-y += checksum.h | 2 | generic-y += checksum.h |
| 3 | generic-y += compat.h | 3 | generic-y += compat.h |
| 4 | generic-y += cputime.h | ||
| 5 | generic-y += device.h | 4 | generic-y += device.h |
| 6 | generic-y += div64.h | 5 | generic-y += div64.h |
| 6 | generic-y += extable.h | ||
| 7 | generic-y += dma.h | 7 | generic-y += dma.h |
| 8 | generic-y += dma-contiguous.h | 8 | generic-y += dma-contiguous.h |
| 9 | generic-y += dma-mapping.h | 9 | generic-y += dma-mapping.h |
| @@ -11,7 +11,6 @@ generic-y += emergency-restart.h | |||
| 11 | generic-y += exec.h | 11 | generic-y += exec.h |
| 12 | generic-y += fb.h | 12 | generic-y += fb.h |
| 13 | generic-y += hardirq.h | 13 | generic-y += hardirq.h |
| 14 | generic-y += hash.h | ||
| 15 | generic-y += hw_irq.h | 14 | generic-y += hw_irq.h |
| 16 | generic-y += irq_regs.h | 15 | generic-y += irq_regs.h |
| 17 | generic-y += irq_work.h | 16 | generic-y += irq_work.h |
| @@ -21,10 +20,8 @@ generic-y += kvm_para.h | |||
| 21 | generic-y += local.h | 20 | generic-y += local.h |
| 22 | generic-y += local64.h | 21 | generic-y += local64.h |
| 23 | generic-y += mm-arch-hooks.h | 22 | generic-y += mm-arch-hooks.h |
| 24 | generic-y += mutex.h | ||
| 25 | generic-y += percpu.h | 23 | generic-y += percpu.h |
| 26 | generic-y += preempt.h | 24 | generic-y += preempt.h |
| 27 | generic-y += scatterlist.h | ||
| 28 | generic-y += sections.h | 25 | generic-y += sections.h |
| 29 | generic-y += serial.h | 26 | generic-y += serial.h |
| 30 | generic-y += shmparam.h | 27 | generic-y += shmparam.h |
diff --git a/arch/riscv/include/asm/bug.h b/arch/riscv/include/asm/bug.h index bfc7f099ab1f..52a1fbdeab3b 100644 --- a/arch/riscv/include/asm/bug.h +++ b/arch/riscv/include/asm/bug.h | |||
| @@ -21,7 +21,12 @@ | |||
| 21 | #include <asm/asm.h> | 21 | #include <asm/asm.h> |
| 22 | 22 | ||
| 23 | #ifdef CONFIG_GENERIC_BUG | 23 | #ifdef CONFIG_GENERIC_BUG |
| 24 | #define __BUG_INSN _AC(0x00100073, UL) /* ebreak */ | 24 | #define __INSN_LENGTH_MASK _UL(0x3) |
| 25 | #define __INSN_LENGTH_32 _UL(0x3) | ||
| 26 | #define __COMPRESSED_INSN_MASK _UL(0xffff) | ||
| 27 | |||
| 28 | #define __BUG_INSN_32 _UL(0x00100073) /* ebreak */ | ||
| 29 | #define __BUG_INSN_16 _UL(0x9002) /* c.ebreak */ | ||
| 25 | 30 | ||
| 26 | #ifndef __ASSEMBLY__ | 31 | #ifndef __ASSEMBLY__ |
| 27 | typedef u32 bug_insn_t; | 32 | typedef u32 bug_insn_t; |
| @@ -38,38 +43,46 @@ typedef u32 bug_insn_t; | |||
| 38 | #define __BUG_ENTRY \ | 43 | #define __BUG_ENTRY \ |
| 39 | __BUG_ENTRY_ADDR "\n\t" \ | 44 | __BUG_ENTRY_ADDR "\n\t" \ |
| 40 | __BUG_ENTRY_FILE "\n\t" \ | 45 | __BUG_ENTRY_FILE "\n\t" \ |
| 41 | RISCV_SHORT " %1" | 46 | RISCV_SHORT " %1\n\t" \ |
| 47 | RISCV_SHORT " %2" | ||
| 42 | #else | 48 | #else |
| 43 | #define __BUG_ENTRY \ | 49 | #define __BUG_ENTRY \ |
| 44 | __BUG_ENTRY_ADDR | 50 | __BUG_ENTRY_ADDR "\n\t" \ |
| 51 | RISCV_SHORT " %2" | ||
| 45 | #endif | 52 | #endif |
| 46 | 53 | ||
| 47 | #define BUG() \ | 54 | #define __BUG_FLAGS(flags) \ |
| 48 | do { \ | 55 | do { \ |
| 49 | __asm__ __volatile__ ( \ | 56 | __asm__ __volatile__ ( \ |
| 50 | "1:\n\t" \ | 57 | "1:\n\t" \ |
| 51 | "ebreak\n" \ | 58 | "ebreak\n" \ |
| 52 | ".pushsection __bug_table,\"a\"\n\t" \ | 59 | ".pushsection __bug_table,\"aw\"\n\t" \ |
| 53 | "2:\n\t" \ | 60 | "2:\n\t" \ |
| 54 | __BUG_ENTRY "\n\t" \ | 61 | __BUG_ENTRY "\n\t" \ |
| 55 | ".org 2b + %2\n\t" \ | 62 | ".org 2b + %3\n\t" \ |
| 56 | ".popsection" \ | 63 | ".popsection" \ |
| 57 | : \ | 64 | : \ |
| 58 | : "i" (__FILE__), "i" (__LINE__), \ | 65 | : "i" (__FILE__), "i" (__LINE__), \ |
| 59 | "i" (sizeof(struct bug_entry))); \ | 66 | "i" (flags), \ |
| 60 | unreachable(); \ | 67 | "i" (sizeof(struct bug_entry))); \ |
| 61 | } while (0) | 68 | } while (0) |
| 69 | |||
| 62 | #endif /* !__ASSEMBLY__ */ | 70 | #endif /* !__ASSEMBLY__ */ |
| 63 | #else /* CONFIG_GENERIC_BUG */ | 71 | #else /* CONFIG_GENERIC_BUG */ |
| 64 | #ifndef __ASSEMBLY__ | 72 | #ifndef __ASSEMBLY__ |
| 65 | #define BUG() \ | 73 | #define __BUG_FLAGS(flags) do { \ |
| 66 | do { \ | ||
| 67 | __asm__ __volatile__ ("ebreak\n"); \ | 74 | __asm__ __volatile__ ("ebreak\n"); \ |
| 68 | unreachable(); \ | ||
| 69 | } while (0) | 75 | } while (0) |
| 70 | #endif /* !__ASSEMBLY__ */ | 76 | #endif /* !__ASSEMBLY__ */ |
| 71 | #endif /* CONFIG_GENERIC_BUG */ | 77 | #endif /* CONFIG_GENERIC_BUG */ |
| 72 | 78 | ||
| 79 | #define BUG() do { \ | ||
| 80 | __BUG_FLAGS(0); \ | ||
| 81 | unreachable(); \ | ||
| 82 | } while (0) | ||
| 83 | |||
| 84 | #define __WARN_FLAGS(flags) __BUG_FLAGS(BUGFLAG_WARNING|(flags)) | ||
| 85 | |||
| 73 | #define HAVE_ARCH_BUG | 86 | #define HAVE_ARCH_BUG |
| 74 | 87 | ||
| 75 | #include <asm-generic/bug.h> | 88 | #include <asm-generic/bug.h> |
diff --git a/arch/riscv/include/asm/cacheflush.h b/arch/riscv/include/asm/cacheflush.h index 8f13074413a7..1f4ba68ab9aa 100644 --- a/arch/riscv/include/asm/cacheflush.h +++ b/arch/riscv/include/asm/cacheflush.h | |||
| @@ -47,7 +47,7 @@ static inline void flush_dcache_page(struct page *page) | |||
| 47 | 47 | ||
| 48 | #else /* CONFIG_SMP */ | 48 | #else /* CONFIG_SMP */ |
| 49 | 49 | ||
| 50 | #define flush_icache_all() sbi_remote_fence_i(NULL) | 50 | void flush_icache_all(void); |
| 51 | void flush_icache_mm(struct mm_struct *mm, bool local); | 51 | void flush_icache_mm(struct mm_struct *mm, bool local); |
| 52 | 52 | ||
| 53 | #endif /* CONFIG_SMP */ | 53 | #endif /* CONFIG_SMP */ |
diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h index 28a0d1cb374c..3c3c26c3a1f1 100644 --- a/arch/riscv/include/asm/csr.h +++ b/arch/riscv/include/asm/csr.h | |||
| @@ -14,64 +14,95 @@ | |||
| 14 | #ifndef _ASM_RISCV_CSR_H | 14 | #ifndef _ASM_RISCV_CSR_H |
| 15 | #define _ASM_RISCV_CSR_H | 15 | #define _ASM_RISCV_CSR_H |
| 16 | 16 | ||
| 17 | #include <asm/asm.h> | ||
| 17 | #include <linux/const.h> | 18 | #include <linux/const.h> |
| 18 | 19 | ||
| 19 | /* Status register flags */ | 20 | /* Status register flags */ |
| 20 | #define SR_SIE _AC(0x00000002, UL) /* Supervisor Interrupt Enable */ | 21 | #define SR_SIE _AC(0x00000002, UL) /* Supervisor Interrupt Enable */ |
| 21 | #define SR_SPIE _AC(0x00000020, UL) /* Previous Supervisor IE */ | 22 | #define SR_SPIE _AC(0x00000020, UL) /* Previous Supervisor IE */ |
| 22 | #define SR_SPP _AC(0x00000100, UL) /* Previously Supervisor */ | 23 | #define SR_SPP _AC(0x00000100, UL) /* Previously Supervisor */ |
| 23 | #define SR_SUM _AC(0x00040000, UL) /* Supervisor may access User Memory */ | 24 | #define SR_SUM _AC(0x00040000, UL) /* Supervisor User Memory Access */ |
| 24 | 25 | ||
| 25 | #define SR_FS _AC(0x00006000, UL) /* Floating-point Status */ | 26 | #define SR_FS _AC(0x00006000, UL) /* Floating-point Status */ |
| 26 | #define SR_FS_OFF _AC(0x00000000, UL) | 27 | #define SR_FS_OFF _AC(0x00000000, UL) |
| 27 | #define SR_FS_INITIAL _AC(0x00002000, UL) | 28 | #define SR_FS_INITIAL _AC(0x00002000, UL) |
| 28 | #define SR_FS_CLEAN _AC(0x00004000, UL) | 29 | #define SR_FS_CLEAN _AC(0x00004000, UL) |
| 29 | #define SR_FS_DIRTY _AC(0x00006000, UL) | 30 | #define SR_FS_DIRTY _AC(0x00006000, UL) |
| 30 | 31 | ||
| 31 | #define SR_XS _AC(0x00018000, UL) /* Extension Status */ | 32 | #define SR_XS _AC(0x00018000, UL) /* Extension Status */ |
| 32 | #define SR_XS_OFF _AC(0x00000000, UL) | 33 | #define SR_XS_OFF _AC(0x00000000, UL) |
| 33 | #define SR_XS_INITIAL _AC(0x00008000, UL) | 34 | #define SR_XS_INITIAL _AC(0x00008000, UL) |
| 34 | #define SR_XS_CLEAN _AC(0x00010000, UL) | 35 | #define SR_XS_CLEAN _AC(0x00010000, UL) |
| 35 | #define SR_XS_DIRTY _AC(0x00018000, UL) | 36 | #define SR_XS_DIRTY _AC(0x00018000, UL) |
| 36 | 37 | ||
| 37 | #ifndef CONFIG_64BIT | 38 | #ifndef CONFIG_64BIT |
| 38 | #define SR_SD _AC(0x80000000, UL) /* FS/XS dirty */ | 39 | #define SR_SD _AC(0x80000000, UL) /* FS/XS dirty */ |
| 39 | #else | 40 | #else |
| 40 | #define SR_SD _AC(0x8000000000000000, UL) /* FS/XS dirty */ | 41 | #define SR_SD _AC(0x8000000000000000, UL) /* FS/XS dirty */ |
| 41 | #endif | 42 | #endif |
| 42 | 43 | ||
| 43 | /* SATP flags */ | 44 | /* SATP flags */ |
| 44 | #if __riscv_xlen == 32 | 45 | #ifndef CONFIG_64BIT |
| 45 | #define SATP_PPN _AC(0x003FFFFF, UL) | 46 | #define SATP_PPN _AC(0x003FFFFF, UL) |
| 46 | #define SATP_MODE_32 _AC(0x80000000, UL) | 47 | #define SATP_MODE_32 _AC(0x80000000, UL) |
| 47 | #define SATP_MODE SATP_MODE_32 | 48 | #define SATP_MODE SATP_MODE_32 |
| 48 | #else | 49 | #else |
| 49 | #define SATP_PPN _AC(0x00000FFFFFFFFFFF, UL) | 50 | #define SATP_PPN _AC(0x00000FFFFFFFFFFF, UL) |
| 50 | #define SATP_MODE_39 _AC(0x8000000000000000, UL) | 51 | #define SATP_MODE_39 _AC(0x8000000000000000, UL) |
| 51 | #define SATP_MODE SATP_MODE_39 | 52 | #define SATP_MODE SATP_MODE_39 |
| 52 | #endif | 53 | #endif |
| 53 | 54 | ||
| 54 | /* Interrupt Enable and Interrupt Pending flags */ | 55 | /* SCAUSE */ |
| 55 | #define SIE_SSIE _AC(0x00000002, UL) /* Software Interrupt Enable */ | 56 | #define SCAUSE_IRQ_FLAG (_AC(1, UL) << (__riscv_xlen - 1)) |
| 56 | #define SIE_STIE _AC(0x00000020, UL) /* Timer Interrupt Enable */ | 57 | |
| 57 | #define SIE_SEIE _AC(0x00000200, UL) /* External Interrupt Enable */ | 58 | #define IRQ_U_SOFT 0 |
| 58 | 59 | #define IRQ_S_SOFT 1 | |
| 59 | #define EXC_INST_MISALIGNED 0 | 60 | #define IRQ_M_SOFT 3 |
| 60 | #define EXC_INST_ACCESS 1 | 61 | #define IRQ_U_TIMER 4 |
| 61 | #define EXC_BREAKPOINT 3 | 62 | #define IRQ_S_TIMER 5 |
| 62 | #define EXC_LOAD_ACCESS 5 | 63 | #define IRQ_M_TIMER 7 |
| 63 | #define EXC_STORE_ACCESS 7 | 64 | #define IRQ_U_EXT 8 |
| 64 | #define EXC_SYSCALL 8 | 65 | #define IRQ_S_EXT 9 |
| 65 | #define EXC_INST_PAGE_FAULT 12 | 66 | #define IRQ_M_EXT 11 |
| 66 | #define EXC_LOAD_PAGE_FAULT 13 | 67 | |
| 67 | #define EXC_STORE_PAGE_FAULT 15 | 68 | #define EXC_INST_MISALIGNED 0 |
| 69 | #define EXC_INST_ACCESS 1 | ||
| 70 | #define EXC_BREAKPOINT 3 | ||
| 71 | #define EXC_LOAD_ACCESS 5 | ||
| 72 | #define EXC_STORE_ACCESS 7 | ||
| 73 | #define EXC_SYSCALL 8 | ||
| 74 | #define EXC_INST_PAGE_FAULT 12 | ||
| 75 | #define EXC_LOAD_PAGE_FAULT 13 | ||
| 76 | #define EXC_STORE_PAGE_FAULT 15 | ||
| 77 | |||
| 78 | /* SIE (Interrupt Enable) and SIP (Interrupt Pending) flags */ | ||
| 79 | #define SIE_SSIE (_AC(0x1, UL) << IRQ_S_SOFT) | ||
| 80 | #define SIE_STIE (_AC(0x1, UL) << IRQ_S_TIMER) | ||
| 81 | #define SIE_SEIE (_AC(0x1, UL) << IRQ_S_EXT) | ||
| 82 | |||
| 83 | #define CSR_CYCLE 0xc00 | ||
| 84 | #define CSR_TIME 0xc01 | ||
| 85 | #define CSR_INSTRET 0xc02 | ||
| 86 | #define CSR_SSTATUS 0x100 | ||
| 87 | #define CSR_SIE 0x104 | ||
| 88 | #define CSR_STVEC 0x105 | ||
| 89 | #define CSR_SCOUNTEREN 0x106 | ||
| 90 | #define CSR_SSCRATCH 0x140 | ||
| 91 | #define CSR_SEPC 0x141 | ||
| 92 | #define CSR_SCAUSE 0x142 | ||
| 93 | #define CSR_STVAL 0x143 | ||
| 94 | #define CSR_SIP 0x144 | ||
| 95 | #define CSR_SATP 0x180 | ||
| 96 | #define CSR_CYCLEH 0xc80 | ||
| 97 | #define CSR_TIMEH 0xc81 | ||
| 98 | #define CSR_INSTRETH 0xc82 | ||
| 68 | 99 | ||
| 69 | #ifndef __ASSEMBLY__ | 100 | #ifndef __ASSEMBLY__ |
| 70 | 101 | ||
| 71 | #define csr_swap(csr, val) \ | 102 | #define csr_swap(csr, val) \ |
| 72 | ({ \ | 103 | ({ \ |
| 73 | unsigned long __v = (unsigned long)(val); \ | 104 | unsigned long __v = (unsigned long)(val); \ |
| 74 | __asm__ __volatile__ ("csrrw %0, " #csr ", %1" \ | 105 | __asm__ __volatile__ ("csrrw %0, " __ASM_STR(csr) ", %1"\ |
| 75 | : "=r" (__v) : "rK" (__v) \ | 106 | : "=r" (__v) : "rK" (__v) \ |
| 76 | : "memory"); \ | 107 | : "memory"); \ |
| 77 | __v; \ | 108 | __v; \ |
| @@ -80,7 +111,7 @@ | |||
| 80 | #define csr_read(csr) \ | 111 | #define csr_read(csr) \ |
| 81 | ({ \ | 112 | ({ \ |
| 82 | register unsigned long __v; \ | 113 | register unsigned long __v; \ |
| 83 | __asm__ __volatile__ ("csrr %0, " #csr \ | 114 | __asm__ __volatile__ ("csrr %0, " __ASM_STR(csr) \ |
| 84 | : "=r" (__v) : \ | 115 | : "=r" (__v) : \ |
| 85 | : "memory"); \ | 116 | : "memory"); \ |
| 86 | __v; \ | 117 | __v; \ |
| @@ -89,7 +120,7 @@ | |||
| 89 | #define csr_write(csr, val) \ | 120 | #define csr_write(csr, val) \ |
| 90 | ({ \ | 121 | ({ \ |
| 91 | unsigned long __v = (unsigned long)(val); \ | 122 | unsigned long __v = (unsigned long)(val); \ |
| 92 | __asm__ __volatile__ ("csrw " #csr ", %0" \ | 123 | __asm__ __volatile__ ("csrw " __ASM_STR(csr) ", %0" \ |
| 93 | : : "rK" (__v) \ | 124 | : : "rK" (__v) \ |
| 94 | : "memory"); \ | 125 | : "memory"); \ |
| 95 | }) | 126 | }) |
| @@ -97,7 +128,7 @@ | |||
| 97 | #define csr_read_set(csr, val) \ | 128 | #define csr_read_set(csr, val) \ |
| 98 | ({ \ | 129 | ({ \ |
| 99 | unsigned long __v = (unsigned long)(val); \ | 130 | unsigned long __v = (unsigned long)(val); \ |
| 100 | __asm__ __volatile__ ("csrrs %0, " #csr ", %1" \ | 131 | __asm__ __volatile__ ("csrrs %0, " __ASM_STR(csr) ", %1"\ |
| 101 | : "=r" (__v) : "rK" (__v) \ | 132 | : "=r" (__v) : "rK" (__v) \ |
| 102 | : "memory"); \ | 133 | : "memory"); \ |
| 103 | __v; \ | 134 | __v; \ |
| @@ -106,7 +137,7 @@ | |||
| 106 | #define csr_set(csr, val) \ | 137 | #define csr_set(csr, val) \ |
| 107 | ({ \ | 138 | ({ \ |
| 108 | unsigned long __v = (unsigned long)(val); \ | 139 | unsigned long __v = (unsigned long)(val); \ |
| 109 | __asm__ __volatile__ ("csrs " #csr ", %0" \ | 140 | __asm__ __volatile__ ("csrs " __ASM_STR(csr) ", %0" \ |
| 110 | : : "rK" (__v) \ | 141 | : : "rK" (__v) \ |
| 111 | : "memory"); \ | 142 | : "memory"); \ |
| 112 | }) | 143 | }) |
| @@ -114,7 +145,7 @@ | |||
| 114 | #define csr_read_clear(csr, val) \ | 145 | #define csr_read_clear(csr, val) \ |
| 115 | ({ \ | 146 | ({ \ |
| 116 | unsigned long __v = (unsigned long)(val); \ | 147 | unsigned long __v = (unsigned long)(val); \ |
| 117 | __asm__ __volatile__ ("csrrc %0, " #csr ", %1" \ | 148 | __asm__ __volatile__ ("csrrc %0, " __ASM_STR(csr) ", %1"\ |
| 118 | : "=r" (__v) : "rK" (__v) \ | 149 | : "=r" (__v) : "rK" (__v) \ |
| 119 | : "memory"); \ | 150 | : "memory"); \ |
| 120 | __v; \ | 151 | __v; \ |
| @@ -123,7 +154,7 @@ | |||
| 123 | #define csr_clear(csr, val) \ | 154 | #define csr_clear(csr, val) \ |
| 124 | ({ \ | 155 | ({ \ |
| 125 | unsigned long __v = (unsigned long)(val); \ | 156 | unsigned long __v = (unsigned long)(val); \ |
| 126 | __asm__ __volatile__ ("csrc " #csr ", %0" \ | 157 | __asm__ __volatile__ ("csrc " __ASM_STR(csr) ", %0" \ |
| 127 | : : "rK" (__v) \ | 158 | : : "rK" (__v) \ |
| 128 | : "memory"); \ | 159 | : "memory"); \ |
| 129 | }) | 160 | }) |
diff --git a/arch/riscv/include/asm/elf.h b/arch/riscv/include/asm/elf.h index 697fc23b0d5a..ce0cd7d77eb0 100644 --- a/arch/riscv/include/asm/elf.h +++ b/arch/riscv/include/asm/elf.h | |||
| @@ -27,13 +27,7 @@ | |||
| 27 | #define ELF_CLASS ELFCLASS32 | 27 | #define ELF_CLASS ELFCLASS32 |
| 28 | #endif | 28 | #endif |
| 29 | 29 | ||
| 30 | #if defined(__LITTLE_ENDIAN) | ||
| 31 | #define ELF_DATA ELFDATA2LSB | 30 | #define ELF_DATA ELFDATA2LSB |
| 32 | #elif defined(__BIG_ENDIAN) | ||
| 33 | #define ELF_DATA ELFDATA2MSB | ||
| 34 | #else | ||
| 35 | #error "Unknown endianness" | ||
| 36 | #endif | ||
| 37 | 31 | ||
| 38 | /* | 32 | /* |
| 39 | * This is used to ensure we don't load something for the wrong architecture. | 33 | * This is used to ensure we don't load something for the wrong architecture. |
diff --git a/arch/riscv/include/asm/futex.h b/arch/riscv/include/asm/futex.h index 66641624d8a5..4ad6409c4647 100644 --- a/arch/riscv/include/asm/futex.h +++ b/arch/riscv/include/asm/futex.h | |||
| @@ -7,18 +7,6 @@ | |||
| 7 | #ifndef _ASM_FUTEX_H | 7 | #ifndef _ASM_FUTEX_H |
| 8 | #define _ASM_FUTEX_H | 8 | #define _ASM_FUTEX_H |
| 9 | 9 | ||
| 10 | #ifndef CONFIG_RISCV_ISA_A | ||
| 11 | /* | ||
| 12 | * Use the generic interrupt disabling versions if the A extension | ||
| 13 | * is not supported. | ||
| 14 | */ | ||
| 15 | #ifdef CONFIG_SMP | ||
| 16 | #error "Can't support generic futex calls without A extension on SMP" | ||
| 17 | #endif | ||
| 18 | #include <asm-generic/futex.h> | ||
| 19 | |||
| 20 | #else /* CONFIG_RISCV_ISA_A */ | ||
| 21 | |||
| 22 | #include <linux/futex.h> | 10 | #include <linux/futex.h> |
| 23 | #include <linux/uaccess.h> | 11 | #include <linux/uaccess.h> |
| 24 | #include <linux/errno.h> | 12 | #include <linux/errno.h> |
| @@ -124,5 +112,4 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, | |||
| 124 | return ret; | 112 | return ret; |
| 125 | } | 113 | } |
| 126 | 114 | ||
| 127 | #endif /* CONFIG_RISCV_ISA_A */ | ||
| 128 | #endif /* _ASM_FUTEX_H */ | 115 | #endif /* _ASM_FUTEX_H */ |
diff --git a/arch/riscv/include/asm/irqflags.h b/arch/riscv/include/asm/irqflags.h index 07a3c6d5706f..1a69b3bcd371 100644 --- a/arch/riscv/include/asm/irqflags.h +++ b/arch/riscv/include/asm/irqflags.h | |||
| @@ -21,25 +21,25 @@ | |||
| 21 | /* read interrupt enabled status */ | 21 | /* read interrupt enabled status */ |
| 22 | static inline unsigned long arch_local_save_flags(void) | 22 | static inline unsigned long arch_local_save_flags(void) |
| 23 | { | 23 | { |
| 24 | return csr_read(sstatus); | 24 | return csr_read(CSR_SSTATUS); |
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | /* unconditionally enable interrupts */ | 27 | /* unconditionally enable interrupts */ |
| 28 | static inline void arch_local_irq_enable(void) | 28 | static inline void arch_local_irq_enable(void) |
| 29 | { | 29 | { |
| 30 | csr_set(sstatus, SR_SIE); | 30 | csr_set(CSR_SSTATUS, SR_SIE); |
| 31 | } | 31 | } |
| 32 | 32 | ||
| 33 | /* unconditionally disable interrupts */ | 33 | /* unconditionally disable interrupts */ |
| 34 | static inline void arch_local_irq_disable(void) | 34 | static inline void arch_local_irq_disable(void) |
| 35 | { | 35 | { |
| 36 | csr_clear(sstatus, SR_SIE); | 36 | csr_clear(CSR_SSTATUS, SR_SIE); |
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | /* get status and disable interrupts */ | 39 | /* get status and disable interrupts */ |
| 40 | static inline unsigned long arch_local_irq_save(void) | 40 | static inline unsigned long arch_local_irq_save(void) |
| 41 | { | 41 | { |
| 42 | return csr_read_clear(sstatus, SR_SIE); | 42 | return csr_read_clear(CSR_SSTATUS, SR_SIE); |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | /* test flags */ | 45 | /* test flags */ |
| @@ -57,7 +57,7 @@ static inline int arch_irqs_disabled(void) | |||
| 57 | /* set interrupt enabled status */ | 57 | /* set interrupt enabled status */ |
| 58 | static inline void arch_local_irq_restore(unsigned long flags) | 58 | static inline void arch_local_irq_restore(unsigned long flags) |
| 59 | { | 59 | { |
| 60 | csr_set(sstatus, flags & SR_SIE); | 60 | csr_set(CSR_SSTATUS, flags & SR_SIE); |
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | #endif /* _ASM_RISCV_IRQFLAGS_H */ | 63 | #endif /* _ASM_RISCV_IRQFLAGS_H */ |
diff --git a/arch/riscv/include/asm/mmu_context.h b/arch/riscv/include/asm/mmu_context.h index 336d60ec5698..bf4f097a9051 100644 --- a/arch/riscv/include/asm/mmu_context.h +++ b/arch/riscv/include/asm/mmu_context.h | |||
| @@ -20,8 +20,6 @@ | |||
| 20 | 20 | ||
| 21 | #include <linux/mm.h> | 21 | #include <linux/mm.h> |
| 22 | #include <linux/sched.h> | 22 | #include <linux/sched.h> |
| 23 | #include <asm/tlbflush.h> | ||
| 24 | #include <asm/cacheflush.h> | ||
| 25 | 23 | ||
| 26 | static inline void enter_lazy_tlb(struct mm_struct *mm, | 24 | static inline void enter_lazy_tlb(struct mm_struct *mm, |
| 27 | struct task_struct *task) | 25 | struct task_struct *task) |
| @@ -39,61 +37,8 @@ static inline void destroy_context(struct mm_struct *mm) | |||
| 39 | { | 37 | { |
| 40 | } | 38 | } |
| 41 | 39 | ||
| 42 | /* | 40 | void switch_mm(struct mm_struct *prev, struct mm_struct *next, |
| 43 | * When necessary, performs a deferred icache flush for the given MM context, | 41 | struct task_struct *task); |
| 44 | * on the local CPU. RISC-V has no direct mechanism for instruction cache | ||
| 45 | * shoot downs, so instead we send an IPI that informs the remote harts they | ||
| 46 | * need to flush their local instruction caches. To avoid pathologically slow | ||
| 47 | * behavior in a common case (a bunch of single-hart processes on a many-hart | ||
| 48 | * machine, ie 'make -j') we avoid the IPIs for harts that are not currently | ||
| 49 | * executing a MM context and instead schedule a deferred local instruction | ||
| 50 | * cache flush to be performed before execution resumes on each hart. This | ||
| 51 | * actually performs that local instruction cache flush, which implicitly only | ||
| 52 | * refers to the current hart. | ||
| 53 | */ | ||
| 54 | static inline void flush_icache_deferred(struct mm_struct *mm) | ||
| 55 | { | ||
| 56 | #ifdef CONFIG_SMP | ||
| 57 | unsigned int cpu = smp_processor_id(); | ||
| 58 | cpumask_t *mask = &mm->context.icache_stale_mask; | ||
| 59 | |||
| 60 | if (cpumask_test_cpu(cpu, mask)) { | ||
| 61 | cpumask_clear_cpu(cpu, mask); | ||
| 62 | /* | ||
| 63 | * Ensure the remote hart's writes are visible to this hart. | ||
| 64 | * This pairs with a barrier in flush_icache_mm. | ||
| 65 | */ | ||
| 66 | smp_mb(); | ||
| 67 | local_flush_icache_all(); | ||
| 68 | } | ||
| 69 | #endif | ||
| 70 | } | ||
| 71 | |||
| 72 | static inline void switch_mm(struct mm_struct *prev, | ||
| 73 | struct mm_struct *next, struct task_struct *task) | ||
| 74 | { | ||
| 75 | if (likely(prev != next)) { | ||
| 76 | /* | ||
| 77 | * Mark the current MM context as inactive, and the next as | ||
| 78 | * active. This is at least used by the icache flushing | ||
| 79 | * routines in order to determine who should | ||
| 80 | */ | ||
| 81 | unsigned int cpu = smp_processor_id(); | ||
| 82 | |||
| 83 | cpumask_clear_cpu(cpu, mm_cpumask(prev)); | ||
| 84 | cpumask_set_cpu(cpu, mm_cpumask(next)); | ||
| 85 | |||
| 86 | /* | ||
| 87 | * Use the old spbtr name instead of using the current satp | ||
| 88 | * name to support binutils 2.29 which doesn't know about the | ||
| 89 | * privileged ISA 1.10 yet. | ||
| 90 | */ | ||
| 91 | csr_write(sptbr, virt_to_pfn(next->pgd) | SATP_MODE); | ||
| 92 | local_flush_tlb_all(); | ||
| 93 | |||
| 94 | flush_icache_deferred(next); | ||
| 95 | } | ||
| 96 | } | ||
| 97 | 42 | ||
| 98 | static inline void activate_mm(struct mm_struct *prev, | 43 | static inline void activate_mm(struct mm_struct *prev, |
| 99 | struct mm_struct *next) | 44 | struct mm_struct *next) |
diff --git a/arch/riscv/include/asm/ptrace.h b/arch/riscv/include/asm/ptrace.h index d35ec2f41381..9c867a4bac83 100644 --- a/arch/riscv/include/asm/ptrace.h +++ b/arch/riscv/include/asm/ptrace.h | |||
| @@ -70,47 +70,38 @@ struct pt_regs { | |||
| 70 | 70 | ||
| 71 | 71 | ||
| 72 | /* Helpers for working with the instruction pointer */ | 72 | /* Helpers for working with the instruction pointer */ |
| 73 | #define GET_IP(regs) ((regs)->sepc) | ||
| 74 | #define SET_IP(regs, val) (GET_IP(regs) = (val)) | ||
| 75 | |||
| 76 | static inline unsigned long instruction_pointer(struct pt_regs *regs) | 73 | static inline unsigned long instruction_pointer(struct pt_regs *regs) |
| 77 | { | 74 | { |
| 78 | return GET_IP(regs); | 75 | return regs->sepc; |
| 79 | } | 76 | } |
| 80 | static inline void instruction_pointer_set(struct pt_regs *regs, | 77 | static inline void instruction_pointer_set(struct pt_regs *regs, |
| 81 | unsigned long val) | 78 | unsigned long val) |
| 82 | { | 79 | { |
| 83 | SET_IP(regs, val); | 80 | regs->sepc = val; |
| 84 | } | 81 | } |
| 85 | 82 | ||
| 86 | #define profile_pc(regs) instruction_pointer(regs) | 83 | #define profile_pc(regs) instruction_pointer(regs) |
| 87 | 84 | ||
| 88 | /* Helpers for working with the user stack pointer */ | 85 | /* Helpers for working with the user stack pointer */ |
| 89 | #define GET_USP(regs) ((regs)->sp) | ||
| 90 | #define SET_USP(regs, val) (GET_USP(regs) = (val)) | ||
| 91 | |||
| 92 | static inline unsigned long user_stack_pointer(struct pt_regs *regs) | 86 | static inline unsigned long user_stack_pointer(struct pt_regs *regs) |
| 93 | { | 87 | { |
| 94 | return GET_USP(regs); | 88 | return regs->sp; |
| 95 | } | 89 | } |
| 96 | static inline void user_stack_pointer_set(struct pt_regs *regs, | 90 | static inline void user_stack_pointer_set(struct pt_regs *regs, |
| 97 | unsigned long val) | 91 | unsigned long val) |
| 98 | { | 92 | { |
| 99 | SET_USP(regs, val); | 93 | regs->sp = val; |
| 100 | } | 94 | } |
| 101 | 95 | ||
| 102 | /* Helpers for working with the frame pointer */ | 96 | /* Helpers for working with the frame pointer */ |
| 103 | #define GET_FP(regs) ((regs)->s0) | ||
| 104 | #define SET_FP(regs, val) (GET_FP(regs) = (val)) | ||
| 105 | |||
| 106 | static inline unsigned long frame_pointer(struct pt_regs *regs) | 97 | static inline unsigned long frame_pointer(struct pt_regs *regs) |
| 107 | { | 98 | { |
| 108 | return GET_FP(regs); | 99 | return regs->s0; |
| 109 | } | 100 | } |
| 110 | static inline void frame_pointer_set(struct pt_regs *regs, | 101 | static inline void frame_pointer_set(struct pt_regs *regs, |
| 111 | unsigned long val) | 102 | unsigned long val) |
| 112 | { | 103 | { |
| 113 | SET_FP(regs, val); | 104 | regs->s0 = val; |
| 114 | } | 105 | } |
| 115 | 106 | ||
| 116 | static inline unsigned long regs_return_value(struct pt_regs *regs) | 107 | static inline unsigned long regs_return_value(struct pt_regs *regs) |
diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h index b6bb10b92fe2..19f231615510 100644 --- a/arch/riscv/include/asm/sbi.h +++ b/arch/riscv/include/asm/sbi.h | |||
| @@ -26,22 +26,27 @@ | |||
| 26 | #define SBI_REMOTE_SFENCE_VMA_ASID 7 | 26 | #define SBI_REMOTE_SFENCE_VMA_ASID 7 |
| 27 | #define SBI_SHUTDOWN 8 | 27 | #define SBI_SHUTDOWN 8 |
| 28 | 28 | ||
| 29 | #define SBI_CALL(which, arg0, arg1, arg2) ({ \ | 29 | #define SBI_CALL(which, arg0, arg1, arg2, arg3) ({ \ |
| 30 | register uintptr_t a0 asm ("a0") = (uintptr_t)(arg0); \ | 30 | register uintptr_t a0 asm ("a0") = (uintptr_t)(arg0); \ |
| 31 | register uintptr_t a1 asm ("a1") = (uintptr_t)(arg1); \ | 31 | register uintptr_t a1 asm ("a1") = (uintptr_t)(arg1); \ |
| 32 | register uintptr_t a2 asm ("a2") = (uintptr_t)(arg2); \ | 32 | register uintptr_t a2 asm ("a2") = (uintptr_t)(arg2); \ |
| 33 | register uintptr_t a3 asm ("a3") = (uintptr_t)(arg3); \ | ||
| 33 | register uintptr_t a7 asm ("a7") = (uintptr_t)(which); \ | 34 | register uintptr_t a7 asm ("a7") = (uintptr_t)(which); \ |
| 34 | asm volatile ("ecall" \ | 35 | asm volatile ("ecall" \ |
| 35 | : "+r" (a0) \ | 36 | : "+r" (a0) \ |
| 36 | : "r" (a1), "r" (a2), "r" (a7) \ | 37 | : "r" (a1), "r" (a2), "r" (a3), "r" (a7) \ |
| 37 | : "memory"); \ | 38 | : "memory"); \ |
| 38 | a0; \ | 39 | a0; \ |
| 39 | }) | 40 | }) |
| 40 | 41 | ||
| 41 | /* Lazy implementations until SBI is finalized */ | 42 | /* Lazy implementations until SBI is finalized */ |
| 42 | #define SBI_CALL_0(which) SBI_CALL(which, 0, 0, 0) | 43 | #define SBI_CALL_0(which) SBI_CALL(which, 0, 0, 0, 0) |
| 43 | #define SBI_CALL_1(which, arg0) SBI_CALL(which, arg0, 0, 0) | 44 | #define SBI_CALL_1(which, arg0) SBI_CALL(which, arg0, 0, 0, 0) |
| 44 | #define SBI_CALL_2(which, arg0, arg1) SBI_CALL(which, arg0, arg1, 0) | 45 | #define SBI_CALL_2(which, arg0, arg1) SBI_CALL(which, arg0, arg1, 0, 0) |
| 46 | #define SBI_CALL_3(which, arg0, arg1, arg2) \ | ||
| 47 | SBI_CALL(which, arg0, arg1, arg2, 0) | ||
| 48 | #define SBI_CALL_4(which, arg0, arg1, arg2, arg3) \ | ||
| 49 | SBI_CALL(which, arg0, arg1, arg2, arg3) | ||
| 45 | 50 | ||
| 46 | static inline void sbi_console_putchar(int ch) | 51 | static inline void sbi_console_putchar(int ch) |
| 47 | { | 52 | { |
| @@ -86,7 +91,7 @@ static inline void sbi_remote_sfence_vma(const unsigned long *hart_mask, | |||
| 86 | unsigned long start, | 91 | unsigned long start, |
| 87 | unsigned long size) | 92 | unsigned long size) |
| 88 | { | 93 | { |
| 89 | SBI_CALL_1(SBI_REMOTE_SFENCE_VMA, hart_mask); | 94 | SBI_CALL_3(SBI_REMOTE_SFENCE_VMA, hart_mask, start, size); |
| 90 | } | 95 | } |
| 91 | 96 | ||
| 92 | static inline void sbi_remote_sfence_vma_asid(const unsigned long *hart_mask, | 97 | static inline void sbi_remote_sfence_vma_asid(const unsigned long *hart_mask, |
| @@ -94,7 +99,7 @@ static inline void sbi_remote_sfence_vma_asid(const unsigned long *hart_mask, | |||
| 94 | unsigned long size, | 99 | unsigned long size, |
| 95 | unsigned long asid) | 100 | unsigned long asid) |
| 96 | { | 101 | { |
| 97 | SBI_CALL_1(SBI_REMOTE_SFENCE_VMA_ASID, hart_mask); | 102 | SBI_CALL_4(SBI_REMOTE_SFENCE_VMA_ASID, hart_mask, start, size, asid); |
| 98 | } | 103 | } |
| 99 | 104 | ||
| 100 | #endif | 105 | #endif |
diff --git a/arch/riscv/include/asm/sifive_l2_cache.h b/arch/riscv/include/asm/sifive_l2_cache.h new file mode 100644 index 000000000000..04f6748fc50b --- /dev/null +++ b/arch/riscv/include/asm/sifive_l2_cache.h | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | /* | ||
| 3 | * SiFive L2 Cache Controller header file | ||
| 4 | * | ||
| 5 | */ | ||
| 6 | |||
| 7 | #ifndef _ASM_RISCV_SIFIVE_L2_CACHE_H | ||
| 8 | #define _ASM_RISCV_SIFIVE_L2_CACHE_H | ||
| 9 | |||
| 10 | extern int register_sifive_l2_error_notifier(struct notifier_block *nb); | ||
| 11 | extern int unregister_sifive_l2_error_notifier(struct notifier_block *nb); | ||
| 12 | |||
| 13 | #define SIFIVE_L2_ERR_TYPE_CE 0 | ||
| 14 | #define SIFIVE_L2_ERR_TYPE_UE 1 | ||
| 15 | |||
| 16 | #endif /* _ASM_RISCV_SIFIVE_L2_CACHE_H */ | ||
diff --git a/arch/riscv/include/asm/thread_info.h b/arch/riscv/include/asm/thread_info.h index 1c9cc8389928..9c039870019b 100644 --- a/arch/riscv/include/asm/thread_info.h +++ b/arch/riscv/include/asm/thread_info.h | |||
| @@ -28,7 +28,9 @@ | |||
| 28 | #include <asm/processor.h> | 28 | #include <asm/processor.h> |
| 29 | #include <asm/csr.h> | 29 | #include <asm/csr.h> |
| 30 | 30 | ||
| 31 | typedef unsigned long mm_segment_t; | 31 | typedef struct { |
| 32 | unsigned long seg; | ||
| 33 | } mm_segment_t; | ||
| 32 | 34 | ||
| 33 | /* | 35 | /* |
| 34 | * low level task data that entry.S needs immediate access to | 36 | * low level task data that entry.S needs immediate access to |
diff --git a/arch/riscv/include/asm/uaccess.h b/arch/riscv/include/asm/uaccess.h index fb53a8089e76..b26f407be5c8 100644 --- a/arch/riscv/include/asm/uaccess.h +++ b/arch/riscv/include/asm/uaccess.h | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/compiler.h> | 23 | #include <linux/compiler.h> |
| 24 | #include <linux/thread_info.h> | 24 | #include <linux/thread_info.h> |
| 25 | #include <asm/byteorder.h> | 25 | #include <asm/byteorder.h> |
| 26 | #include <asm/extable.h> | ||
| 26 | #include <asm/asm.h> | 27 | #include <asm/asm.h> |
| 27 | 28 | ||
| 28 | #define __enable_user_access() \ | 29 | #define __enable_user_access() \ |
| @@ -38,8 +39,10 @@ | |||
| 38 | * For historical reasons, these macros are grossly misnamed. | 39 | * For historical reasons, these macros are grossly misnamed. |
| 39 | */ | 40 | */ |
| 40 | 41 | ||
| 41 | #define KERNEL_DS (~0UL) | 42 | #define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) |
| 42 | #define USER_DS (TASK_SIZE) | 43 | |
| 44 | #define KERNEL_DS MAKE_MM_SEG(~0UL) | ||
| 45 | #define USER_DS MAKE_MM_SEG(TASK_SIZE) | ||
| 43 | 46 | ||
| 44 | #define get_fs() (current_thread_info()->addr_limit) | 47 | #define get_fs() (current_thread_info()->addr_limit) |
| 45 | 48 | ||
| @@ -48,9 +51,9 @@ static inline void set_fs(mm_segment_t fs) | |||
| 48 | current_thread_info()->addr_limit = fs; | 51 | current_thread_info()->addr_limit = fs; |
| 49 | } | 52 | } |
| 50 | 53 | ||
| 51 | #define segment_eq(a, b) ((a) == (b)) | 54 | #define segment_eq(a, b) ((a).seg == (b).seg) |
| 52 | 55 | ||
| 53 | #define user_addr_max() (get_fs()) | 56 | #define user_addr_max() (get_fs().seg) |
| 54 | 57 | ||
| 55 | 58 | ||
| 56 | /** | 59 | /** |
| @@ -82,7 +85,7 @@ static inline int __access_ok(unsigned long addr, unsigned long size) | |||
| 82 | { | 85 | { |
| 83 | const mm_segment_t fs = get_fs(); | 86 | const mm_segment_t fs = get_fs(); |
| 84 | 87 | ||
| 85 | return (size <= fs) && (addr <= (fs - size)); | 88 | return size <= fs.seg && addr <= fs.seg - size; |
| 86 | } | 89 | } |
| 87 | 90 | ||
| 88 | /* | 91 | /* |
| @@ -98,21 +101,8 @@ static inline int __access_ok(unsigned long addr, unsigned long size) | |||
| 98 | * on our cache or tlb entries. | 101 | * on our cache or tlb entries. |
| 99 | */ | 102 | */ |
| 100 | 103 | ||
| 101 | struct exception_table_entry { | ||
| 102 | unsigned long insn, fixup; | ||
| 103 | }; | ||
| 104 | |||
| 105 | extern int fixup_exception(struct pt_regs *state); | ||
| 106 | |||
| 107 | #if defined(__LITTLE_ENDIAN) | ||
| 108 | #define __MSW 1 | ||
| 109 | #define __LSW 0 | 104 | #define __LSW 0 |
| 110 | #elif defined(__BIG_ENDIAN) | 105 | #define __MSW 1 |
| 111 | #define __MSW 0 | ||
| 112 | #define __LSW 1 | ||
| 113 | #else | ||
| 114 | #error "Unknown endianness" | ||
| 115 | #endif | ||
| 116 | 106 | ||
| 117 | /* | 107 | /* |
| 118 | * The "__xxx" versions of the user access functions do not verify the address | 108 | * The "__xxx" versions of the user access functions do not verify the address |
diff --git a/arch/riscv/kernel/asm-offsets.c b/arch/riscv/kernel/asm-offsets.c index dac98348c6a3..578bb5efc085 100644 --- a/arch/riscv/kernel/asm-offsets.c +++ b/arch/riscv/kernel/asm-offsets.c | |||
| @@ -312,9 +312,6 @@ void asm_offsets(void) | |||
| 312 | - offsetof(struct task_struct, thread.fstate.f[0]) | 312 | - offsetof(struct task_struct, thread.fstate.f[0]) |
| 313 | ); | 313 | ); |
| 314 | 314 | ||
| 315 | /* The assembler needs access to THREAD_SIZE as well. */ | ||
| 316 | DEFINE(ASM_THREAD_SIZE, THREAD_SIZE); | ||
| 317 | |||
| 318 | /* | 315 | /* |
| 319 | * We allocate a pt_regs on the stack when entering the kernel. This | 316 | * We allocate a pt_regs on the stack when entering the kernel. This |
| 320 | * ensures the alignment is sane. | 317 | * ensures the alignment is sane. |
diff --git a/arch/riscv/kernel/cpu.c b/arch/riscv/kernel/cpu.c index cf2fca12414a..c8d2a3223099 100644 --- a/arch/riscv/kernel/cpu.c +++ b/arch/riscv/kernel/cpu.c | |||
| @@ -136,8 +136,7 @@ static void c_stop(struct seq_file *m, void *v) | |||
| 136 | static int c_show(struct seq_file *m, void *v) | 136 | static int c_show(struct seq_file *m, void *v) |
| 137 | { | 137 | { |
| 138 | unsigned long cpu_id = (unsigned long)v - 1; | 138 | unsigned long cpu_id = (unsigned long)v - 1; |
| 139 | struct device_node *node = of_get_cpu_node(cpuid_to_hartid_map(cpu_id), | 139 | struct device_node *node = of_get_cpu_node(cpu_id, NULL); |
| 140 | NULL); | ||
| 141 | const char *compat, *isa, *mmu; | 140 | const char *compat, *isa, *mmu; |
| 142 | 141 | ||
| 143 | seq_printf(m, "processor\t: %lu\n", cpu_id); | 142 | seq_printf(m, "processor\t: %lu\n", cpu_id); |
diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S index fd9b57c8b4ce..1c1ecc238cfa 100644 --- a/arch/riscv/kernel/entry.S +++ b/arch/riscv/kernel/entry.S | |||
| @@ -37,11 +37,11 @@ | |||
| 37 | * the kernel thread pointer. If we came from the kernel, sscratch | 37 | * the kernel thread pointer. If we came from the kernel, sscratch |
| 38 | * will contain 0, and we should continue on the current TP. | 38 | * will contain 0, and we should continue on the current TP. |
| 39 | */ | 39 | */ |
| 40 | csrrw tp, sscratch, tp | 40 | csrrw tp, CSR_SSCRATCH, tp |
| 41 | bnez tp, _save_context | 41 | bnez tp, _save_context |
| 42 | 42 | ||
| 43 | _restore_kernel_tpsp: | 43 | _restore_kernel_tpsp: |
| 44 | csrr tp, sscratch | 44 | csrr tp, CSR_SSCRATCH |
| 45 | REG_S sp, TASK_TI_KERNEL_SP(tp) | 45 | REG_S sp, TASK_TI_KERNEL_SP(tp) |
| 46 | _save_context: | 46 | _save_context: |
| 47 | REG_S sp, TASK_TI_USER_SP(tp) | 47 | REG_S sp, TASK_TI_USER_SP(tp) |
| @@ -87,11 +87,11 @@ _save_context: | |||
| 87 | li t0, SR_SUM | SR_FS | 87 | li t0, SR_SUM | SR_FS |
| 88 | 88 | ||
| 89 | REG_L s0, TASK_TI_USER_SP(tp) | 89 | REG_L s0, TASK_TI_USER_SP(tp) |
| 90 | csrrc s1, sstatus, t0 | 90 | csrrc s1, CSR_SSTATUS, t0 |
| 91 | csrr s2, sepc | 91 | csrr s2, CSR_SEPC |
| 92 | csrr s3, sbadaddr | 92 | csrr s3, CSR_STVAL |
| 93 | csrr s4, scause | 93 | csrr s4, CSR_SCAUSE |
| 94 | csrr s5, sscratch | 94 | csrr s5, CSR_SSCRATCH |
| 95 | REG_S s0, PT_SP(sp) | 95 | REG_S s0, PT_SP(sp) |
| 96 | REG_S s1, PT_SSTATUS(sp) | 96 | REG_S s1, PT_SSTATUS(sp) |
| 97 | REG_S s2, PT_SEPC(sp) | 97 | REG_S s2, PT_SEPC(sp) |
| @@ -107,8 +107,8 @@ _save_context: | |||
| 107 | .macro RESTORE_ALL | 107 | .macro RESTORE_ALL |
| 108 | REG_L a0, PT_SSTATUS(sp) | 108 | REG_L a0, PT_SSTATUS(sp) |
| 109 | REG_L a2, PT_SEPC(sp) | 109 | REG_L a2, PT_SEPC(sp) |
| 110 | csrw sstatus, a0 | 110 | csrw CSR_SSTATUS, a0 |
| 111 | csrw sepc, a2 | 111 | csrw CSR_SEPC, a2 |
| 112 | 112 | ||
| 113 | REG_L x1, PT_RA(sp) | 113 | REG_L x1, PT_RA(sp) |
| 114 | REG_L x3, PT_GP(sp) | 114 | REG_L x3, PT_GP(sp) |
| @@ -155,7 +155,7 @@ ENTRY(handle_exception) | |||
| 155 | * Set sscratch register to 0, so that if a recursive exception | 155 | * Set sscratch register to 0, so that if a recursive exception |
| 156 | * occurs, the exception vector knows it came from the kernel | 156 | * occurs, the exception vector knows it came from the kernel |
| 157 | */ | 157 | */ |
| 158 | csrw sscratch, x0 | 158 | csrw CSR_SSCRATCH, x0 |
| 159 | 159 | ||
| 160 | /* Load the global pointer */ | 160 | /* Load the global pointer */ |
| 161 | .option push | 161 | .option push |
| @@ -248,7 +248,7 @@ resume_userspace: | |||
| 248 | * Save TP into sscratch, so we can find the kernel data structures | 248 | * Save TP into sscratch, so we can find the kernel data structures |
| 249 | * again. | 249 | * again. |
| 250 | */ | 250 | */ |
| 251 | csrw sscratch, tp | 251 | csrw CSR_SSCRATCH, tp |
| 252 | 252 | ||
| 253 | restore_all: | 253 | restore_all: |
| 254 | RESTORE_ALL | 254 | RESTORE_ALL |
diff --git a/arch/riscv/kernel/head.S b/arch/riscv/kernel/head.S index fe884cd69abd..370c66ce187a 100644 --- a/arch/riscv/kernel/head.S +++ b/arch/riscv/kernel/head.S | |||
| @@ -23,7 +23,8 @@ | |||
| 23 | __INIT | 23 | __INIT |
| 24 | ENTRY(_start) | 24 | ENTRY(_start) |
| 25 | /* Mask all interrupts */ | 25 | /* Mask all interrupts */ |
| 26 | csrw sie, zero | 26 | csrw CSR_SIE, zero |
| 27 | csrw CSR_SIP, zero | ||
| 27 | 28 | ||
| 28 | /* Load the global pointer */ | 29 | /* Load the global pointer */ |
| 29 | .option push | 30 | .option push |
| @@ -68,14 +69,10 @@ clear_bss_done: | |||
| 68 | /* Restore C environment */ | 69 | /* Restore C environment */ |
| 69 | la tp, init_task | 70 | la tp, init_task |
| 70 | sw zero, TASK_TI_CPU(tp) | 71 | sw zero, TASK_TI_CPU(tp) |
| 71 | 72 | la sp, init_thread_union + THREAD_SIZE | |
| 72 | la sp, init_thread_union | ||
| 73 | li a0, ASM_THREAD_SIZE | ||
| 74 | add sp, sp, a0 | ||
| 75 | 73 | ||
| 76 | /* Start the kernel */ | 74 | /* Start the kernel */ |
| 77 | mv a0, s0 | 75 | mv a0, s1 |
| 78 | mv a1, s1 | ||
| 79 | call parse_dtb | 76 | call parse_dtb |
| 80 | tail start_kernel | 77 | tail start_kernel |
| 81 | 78 | ||
| @@ -89,7 +86,7 @@ relocate: | |||
| 89 | /* Point stvec to virtual address of intruction after satp write */ | 86 | /* Point stvec to virtual address of intruction after satp write */ |
| 90 | la a0, 1f | 87 | la a0, 1f |
| 91 | add a0, a0, a1 | 88 | add a0, a0, a1 |
| 92 | csrw stvec, a0 | 89 | csrw CSR_STVEC, a0 |
| 93 | 90 | ||
| 94 | /* Compute satp for kernel page tables, but don't load it yet */ | 91 | /* Compute satp for kernel page tables, but don't load it yet */ |
| 95 | la a2, swapper_pg_dir | 92 | la a2, swapper_pg_dir |
| @@ -99,18 +96,20 @@ relocate: | |||
| 99 | 96 | ||
| 100 | /* | 97 | /* |
| 101 | * Load trampoline page directory, which will cause us to trap to | 98 | * Load trampoline page directory, which will cause us to trap to |
| 102 | * stvec if VA != PA, or simply fall through if VA == PA | 99 | * stvec if VA != PA, or simply fall through if VA == PA. We need a |
| 100 | * full fence here because setup_vm() just wrote these PTEs and we need | ||
| 101 | * to ensure the new translations are in use. | ||
| 103 | */ | 102 | */ |
| 104 | la a0, trampoline_pg_dir | 103 | la a0, trampoline_pg_dir |
| 105 | srl a0, a0, PAGE_SHIFT | 104 | srl a0, a0, PAGE_SHIFT |
| 106 | or a0, a0, a1 | 105 | or a0, a0, a1 |
| 107 | sfence.vma | 106 | sfence.vma |
| 108 | csrw sptbr, a0 | 107 | csrw CSR_SATP, a0 |
| 109 | .align 2 | 108 | .align 2 |
| 110 | 1: | 109 | 1: |
| 111 | /* Set trap vector to spin forever to help debug */ | 110 | /* Set trap vector to spin forever to help debug */ |
| 112 | la a0, .Lsecondary_park | 111 | la a0, .Lsecondary_park |
| 113 | csrw stvec, a0 | 112 | csrw CSR_STVEC, a0 |
| 114 | 113 | ||
| 115 | /* Reload the global pointer */ | 114 | /* Reload the global pointer */ |
| 116 | .option push | 115 | .option push |
| @@ -118,8 +117,14 @@ relocate: | |||
| 118 | la gp, __global_pointer$ | 117 | la gp, __global_pointer$ |
| 119 | .option pop | 118 | .option pop |
| 120 | 119 | ||
| 121 | /* Switch to kernel page tables */ | 120 | /* |
| 122 | csrw sptbr, a2 | 121 | * Switch to kernel page tables. A full fence is necessary in order to |
| 122 | * avoid using the trampoline translations, which are only correct for | ||
| 123 | * the first superpage. Fetching the fence is guarnteed to work | ||
| 124 | * because that first superpage is translated the same way. | ||
| 125 | */ | ||
| 126 | csrw CSR_SATP, a2 | ||
| 127 | sfence.vma | ||
| 123 | 128 | ||
| 124 | ret | 129 | ret |
| 125 | 130 | ||
| @@ -130,7 +135,7 @@ relocate: | |||
| 130 | 135 | ||
| 131 | /* Set trap vector to spin forever to help debug */ | 136 | /* Set trap vector to spin forever to help debug */ |
| 132 | la a3, .Lsecondary_park | 137 | la a3, .Lsecondary_park |
| 133 | csrw stvec, a3 | 138 | csrw CSR_STVEC, a3 |
| 134 | 139 | ||
| 135 | slli a3, a0, LGREG | 140 | slli a3, a0, LGREG |
| 136 | la a1, __cpu_up_stack_pointer | 141 | la a1, __cpu_up_stack_pointer |
diff --git a/arch/riscv/kernel/irq.c b/arch/riscv/kernel/irq.c index 48e6b7db83a1..6d8659388c49 100644 --- a/arch/riscv/kernel/irq.c +++ b/arch/riscv/kernel/irq.c | |||
| @@ -14,17 +14,9 @@ | |||
| 14 | /* | 14 | /* |
| 15 | * Possible interrupt causes: | 15 | * Possible interrupt causes: |
| 16 | */ | 16 | */ |
| 17 | #define INTERRUPT_CAUSE_SOFTWARE 1 | 17 | #define INTERRUPT_CAUSE_SOFTWARE IRQ_S_SOFT |
| 18 | #define INTERRUPT_CAUSE_TIMER 5 | 18 | #define INTERRUPT_CAUSE_TIMER IRQ_S_TIMER |
| 19 | #define INTERRUPT_CAUSE_EXTERNAL 9 | 19 | #define INTERRUPT_CAUSE_EXTERNAL IRQ_S_EXT |
| 20 | |||
| 21 | /* | ||
| 22 | * The high order bit of the trap cause register is always set for | ||
| 23 | * interrupts, which allows us to differentiate them from exceptions | ||
| 24 | * quickly. The INTERRUPT_CAUSE_* macros don't contain that bit, so we | ||
| 25 | * need to mask it off. | ||
| 26 | */ | ||
| 27 | #define INTERRUPT_CAUSE_FLAG (1UL << (__riscv_xlen - 1)) | ||
| 28 | 20 | ||
| 29 | int arch_show_interrupts(struct seq_file *p, int prec) | 21 | int arch_show_interrupts(struct seq_file *p, int prec) |
| 30 | { | 22 | { |
| @@ -37,7 +29,7 @@ asmlinkage void __irq_entry do_IRQ(struct pt_regs *regs) | |||
| 37 | struct pt_regs *old_regs = set_irq_regs(regs); | 29 | struct pt_regs *old_regs = set_irq_regs(regs); |
| 38 | 30 | ||
| 39 | irq_enter(); | 31 | irq_enter(); |
| 40 | switch (regs->scause & ~INTERRUPT_CAUSE_FLAG) { | 32 | switch (regs->scause & ~SCAUSE_IRQ_FLAG) { |
| 41 | case INTERRUPT_CAUSE_TIMER: | 33 | case INTERRUPT_CAUSE_TIMER: |
| 42 | riscv_timer_interrupt(); | 34 | riscv_timer_interrupt(); |
| 43 | break; | 35 | break; |
| @@ -54,7 +46,8 @@ asmlinkage void __irq_entry do_IRQ(struct pt_regs *regs) | |||
| 54 | handle_arch_irq(regs); | 46 | handle_arch_irq(regs); |
| 55 | break; | 47 | break; |
| 56 | default: | 48 | default: |
| 57 | panic("unexpected interrupt cause"); | 49 | pr_alert("unexpected interrupt cause 0x%lx", regs->scause); |
| 50 | BUG(); | ||
| 58 | } | 51 | } |
| 59 | irq_exit(); | 52 | irq_exit(); |
| 60 | 53 | ||
diff --git a/arch/riscv/kernel/perf_event.c b/arch/riscv/kernel/perf_event.c index 667ee70defea..91626d9ae5f2 100644 --- a/arch/riscv/kernel/perf_event.c +++ b/arch/riscv/kernel/perf_event.c | |||
| @@ -185,10 +185,10 @@ static inline u64 read_counter(int idx) | |||
| 185 | 185 | ||
| 186 | switch (idx) { | 186 | switch (idx) { |
| 187 | case RISCV_PMU_CYCLE: | 187 | case RISCV_PMU_CYCLE: |
| 188 | val = csr_read(cycle); | 188 | val = csr_read(CSR_CYCLE); |
| 189 | break; | 189 | break; |
| 190 | case RISCV_PMU_INSTRET: | 190 | case RISCV_PMU_INSTRET: |
| 191 | val = csr_read(instret); | 191 | val = csr_read(CSR_INSTRET); |
| 192 | break; | 192 | break; |
| 193 | default: | 193 | default: |
| 194 | WARN_ON_ONCE(idx < 0 || idx > RISCV_MAX_COUNTERS); | 194 | WARN_ON_ONCE(idx < 0 || idx > RISCV_MAX_COUNTERS); |
diff --git a/arch/riscv/kernel/reset.c b/arch/riscv/kernel/reset.c index 2a53d26ffdd6..ed637aee514b 100644 --- a/arch/riscv/kernel/reset.c +++ b/arch/riscv/kernel/reset.c | |||
| @@ -12,11 +12,15 @@ | |||
| 12 | */ | 12 | */ |
| 13 | 13 | ||
| 14 | #include <linux/reboot.h> | 14 | #include <linux/reboot.h> |
| 15 | #include <linux/export.h> | ||
| 16 | #include <asm/sbi.h> | 15 | #include <asm/sbi.h> |
| 17 | 16 | ||
| 18 | void (*pm_power_off)(void) = machine_power_off; | 17 | static void default_power_off(void) |
| 19 | EXPORT_SYMBOL(pm_power_off); | 18 | { |
| 19 | sbi_shutdown(); | ||
| 20 | while (1); | ||
| 21 | } | ||
| 22 | |||
| 23 | void (*pm_power_off)(void) = default_power_off; | ||
| 20 | 24 | ||
| 21 | void machine_restart(char *cmd) | 25 | void machine_restart(char *cmd) |
| 22 | { | 26 | { |
| @@ -26,11 +30,10 @@ void machine_restart(char *cmd) | |||
| 26 | 30 | ||
| 27 | void machine_halt(void) | 31 | void machine_halt(void) |
| 28 | { | 32 | { |
| 29 | machine_power_off(); | 33 | pm_power_off(); |
| 30 | } | 34 | } |
| 31 | 35 | ||
| 32 | void machine_power_off(void) | 36 | void machine_power_off(void) |
| 33 | { | 37 | { |
| 34 | sbi_shutdown(); | 38 | pm_power_off(); |
| 35 | while (1); | ||
| 36 | } | 39 | } |
diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c index 540a331d1376..d93bcce004e3 100644 --- a/arch/riscv/kernel/setup.c +++ b/arch/riscv/kernel/setup.c | |||
| @@ -52,9 +52,11 @@ struct screen_info screen_info = { | |||
| 52 | atomic_t hart_lottery; | 52 | atomic_t hart_lottery; |
| 53 | unsigned long boot_cpu_hartid; | 53 | unsigned long boot_cpu_hartid; |
| 54 | 54 | ||
| 55 | void __init parse_dtb(unsigned int hartid, void *dtb) | 55 | void __init parse_dtb(phys_addr_t dtb_phys) |
| 56 | { | 56 | { |
| 57 | if (early_init_dt_scan(__va(dtb))) | 57 | void *dtb = __va(dtb_phys); |
| 58 | |||
| 59 | if (early_init_dt_scan(dtb)) | ||
| 58 | return; | 60 | return; |
| 59 | 61 | ||
| 60 | pr_err("No DTB passed to the kernel\n"); | 62 | pr_err("No DTB passed to the kernel\n"); |
diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c index 837e1646091a..804d6ee4f3c5 100644 --- a/arch/riscv/kernel/signal.c +++ b/arch/riscv/kernel/signal.c | |||
| @@ -234,6 +234,9 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) | |||
| 234 | 234 | ||
| 235 | /* Are we from a system call? */ | 235 | /* Are we from a system call? */ |
| 236 | if (regs->scause == EXC_SYSCALL) { | 236 | if (regs->scause == EXC_SYSCALL) { |
| 237 | /* Avoid additional syscall restarting via ret_from_exception */ | ||
| 238 | regs->scause = -1UL; | ||
| 239 | |||
| 237 | /* If so, check system call restarting.. */ | 240 | /* If so, check system call restarting.. */ |
| 238 | switch (regs->a0) { | 241 | switch (regs->a0) { |
| 239 | case -ERESTART_RESTARTBLOCK: | 242 | case -ERESTART_RESTARTBLOCK: |
| @@ -272,6 +275,9 @@ static void do_signal(struct pt_regs *regs) | |||
| 272 | 275 | ||
| 273 | /* Did we come from a system call? */ | 276 | /* Did we come from a system call? */ |
| 274 | if (regs->scause == EXC_SYSCALL) { | 277 | if (regs->scause == EXC_SYSCALL) { |
| 278 | /* Avoid additional syscall restarting via ret_from_exception */ | ||
| 279 | regs->scause = -1UL; | ||
| 280 | |||
| 275 | /* Restart the system call - no handlers present */ | 281 | /* Restart the system call - no handlers present */ |
| 276 | switch (regs->a0) { | 282 | switch (regs->a0) { |
| 277 | case -ERESTARTNOHAND: | 283 | case -ERESTARTNOHAND: |
diff --git a/arch/riscv/kernel/smp.c b/arch/riscv/kernel/smp.c index 0c41d07ec281..b2537ffa855c 100644 --- a/arch/riscv/kernel/smp.c +++ b/arch/riscv/kernel/smp.c | |||
| @@ -42,7 +42,7 @@ unsigned long __cpuid_to_hartid_map[NR_CPUS] = { | |||
| 42 | 42 | ||
| 43 | void __init smp_setup_processor_id(void) | 43 | void __init smp_setup_processor_id(void) |
| 44 | { | 44 | { |
| 45 | cpuid_to_hartid_map(0) = boot_cpu_hartid; | 45 | cpuid_to_hartid_map(0) = boot_cpu_hartid; |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | /* A collection of single bit ipi messages. */ | 48 | /* A collection of single bit ipi messages. */ |
| @@ -53,7 +53,7 @@ static struct { | |||
| 53 | 53 | ||
| 54 | int riscv_hartid_to_cpuid(int hartid) | 54 | int riscv_hartid_to_cpuid(int hartid) |
| 55 | { | 55 | { |
| 56 | int i = -1; | 56 | int i; |
| 57 | 57 | ||
| 58 | for (i = 0; i < NR_CPUS; i++) | 58 | for (i = 0; i < NR_CPUS; i++) |
| 59 | if (cpuid_to_hartid_map(i) == hartid) | 59 | if (cpuid_to_hartid_map(i) == hartid) |
| @@ -70,6 +70,12 @@ void riscv_cpuid_to_hartid_mask(const struct cpumask *in, struct cpumask *out) | |||
| 70 | for_each_cpu(cpu, in) | 70 | for_each_cpu(cpu, in) |
| 71 | cpumask_set_cpu(cpuid_to_hartid_map(cpu), out); | 71 | cpumask_set_cpu(cpuid_to_hartid_map(cpu), out); |
| 72 | } | 72 | } |
| 73 | |||
| 74 | bool arch_match_cpu_phys_id(int cpu, u64 phys_id) | ||
| 75 | { | ||
| 76 | return phys_id == cpuid_to_hartid_map(cpu); | ||
| 77 | } | ||
| 78 | |||
| 73 | /* Unsupported */ | 79 | /* Unsupported */ |
| 74 | int setup_profiling_timer(unsigned int multiplier) | 80 | int setup_profiling_timer(unsigned int multiplier) |
| 75 | { | 81 | { |
| @@ -89,7 +95,7 @@ void riscv_software_interrupt(void) | |||
| 89 | unsigned long *stats = ipi_data[smp_processor_id()].stats; | 95 | unsigned long *stats = ipi_data[smp_processor_id()].stats; |
| 90 | 96 | ||
| 91 | /* Clear pending IPI */ | 97 | /* Clear pending IPI */ |
| 92 | csr_clear(sip, SIE_SSIE); | 98 | csr_clear(CSR_SIP, SIE_SSIE); |
| 93 | 99 | ||
| 94 | while (true) { | 100 | while (true) { |
| 95 | unsigned long ops; | 101 | unsigned long ops; |
| @@ -199,52 +205,3 @@ void smp_send_reschedule(int cpu) | |||
| 199 | send_ipi_message(cpumask_of(cpu), IPI_RESCHEDULE); | 205 | send_ipi_message(cpumask_of(cpu), IPI_RESCHEDULE); |
| 200 | } | 206 | } |
| 201 | 207 | ||
| 202 | /* | ||
| 203 | * Performs an icache flush for the given MM context. RISC-V has no direct | ||
| 204 | * mechanism for instruction cache shoot downs, so instead we send an IPI that | ||
| 205 | * informs the remote harts they need to flush their local instruction caches. | ||
| 206 | * To avoid pathologically slow behavior in a common case (a bunch of | ||
| 207 | * single-hart processes on a many-hart machine, ie 'make -j') we avoid the | ||
| 208 | * IPIs for harts that are not currently executing a MM context and instead | ||
| 209 | * schedule a deferred local instruction cache flush to be performed before | ||
| 210 | * execution resumes on each hart. | ||
| 211 | */ | ||
| 212 | void flush_icache_mm(struct mm_struct *mm, bool local) | ||
| 213 | { | ||
| 214 | unsigned int cpu; | ||
| 215 | cpumask_t others, hmask, *mask; | ||
| 216 | |||
| 217 | preempt_disable(); | ||
| 218 | |||
| 219 | /* Mark every hart's icache as needing a flush for this MM. */ | ||
| 220 | mask = &mm->context.icache_stale_mask; | ||
| 221 | cpumask_setall(mask); | ||
| 222 | /* Flush this hart's I$ now, and mark it as flushed. */ | ||
| 223 | cpu = smp_processor_id(); | ||
| 224 | cpumask_clear_cpu(cpu, mask); | ||
| 225 | local_flush_icache_all(); | ||
| 226 | |||
| 227 | /* | ||
| 228 | * Flush the I$ of other harts concurrently executing, and mark them as | ||
| 229 | * flushed. | ||
| 230 | */ | ||
| 231 | cpumask_andnot(&others, mm_cpumask(mm), cpumask_of(cpu)); | ||
| 232 | local |= cpumask_empty(&others); | ||
| 233 | if (mm != current->active_mm || !local) { | ||
| 234 | cpumask_clear(&hmask); | ||
| 235 | riscv_cpuid_to_hartid_mask(&others, &hmask); | ||
| 236 | sbi_remote_fence_i(hmask.bits); | ||
| 237 | } else { | ||
| 238 | /* | ||
| 239 | * It's assumed that at least one strongly ordered operation is | ||
| 240 | * performed on this hart between setting a hart's cpumask bit | ||
| 241 | * and scheduling this MM context on that hart. Sending an SBI | ||
| 242 | * remote message will do this, but in the case where no | ||
| 243 | * messages are sent we still need to order this hart's writes | ||
| 244 | * with flush_icache_deferred(). | ||
| 245 | */ | ||
| 246 | smp_mb(); | ||
| 247 | } | ||
| 248 | |||
| 249 | preempt_enable(); | ||
| 250 | } | ||
diff --git a/arch/riscv/kernel/smpboot.c b/arch/riscv/kernel/smpboot.c index eb533b5c2c8c..7a0b62252524 100644 --- a/arch/riscv/kernel/smpboot.c +++ b/arch/riscv/kernel/smpboot.c | |||
| @@ -47,6 +47,17 @@ void __init smp_prepare_boot_cpu(void) | |||
| 47 | 47 | ||
| 48 | void __init smp_prepare_cpus(unsigned int max_cpus) | 48 | void __init smp_prepare_cpus(unsigned int max_cpus) |
| 49 | { | 49 | { |
| 50 | int cpuid; | ||
| 51 | |||
| 52 | /* This covers non-smp usecase mandated by "nosmp" option */ | ||
| 53 | if (max_cpus == 0) | ||
| 54 | return; | ||
| 55 | |||
| 56 | for_each_possible_cpu(cpuid) { | ||
| 57 | if (cpuid == smp_processor_id()) | ||
| 58 | continue; | ||
| 59 | set_cpu_present(cpuid, true); | ||
| 60 | } | ||
| 50 | } | 61 | } |
| 51 | 62 | ||
| 52 | void __init setup_smp(void) | 63 | void __init setup_smp(void) |
| @@ -73,12 +84,19 @@ void __init setup_smp(void) | |||
| 73 | } | 84 | } |
| 74 | 85 | ||
| 75 | cpuid_to_hartid_map(cpuid) = hart; | 86 | cpuid_to_hartid_map(cpuid) = hart; |
| 76 | set_cpu_possible(cpuid, true); | ||
| 77 | set_cpu_present(cpuid, true); | ||
| 78 | cpuid++; | 87 | cpuid++; |
| 79 | } | 88 | } |
| 80 | 89 | ||
| 81 | BUG_ON(!found_boot_cpu); | 90 | BUG_ON(!found_boot_cpu); |
| 91 | |||
| 92 | if (cpuid > nr_cpu_ids) | ||
| 93 | pr_warn("Total number of cpus [%d] is greater than nr_cpus option value [%d]\n", | ||
| 94 | cpuid, nr_cpu_ids); | ||
| 95 | |||
| 96 | for (cpuid = 1; cpuid < nr_cpu_ids; cpuid++) { | ||
| 97 | if (cpuid_to_hartid_map(cpuid) != INVALID_HARTID) | ||
| 98 | set_cpu_possible(cpuid, true); | ||
| 99 | } | ||
| 82 | } | 100 | } |
| 83 | 101 | ||
| 84 | int __cpu_up(unsigned int cpu, struct task_struct *tidle) | 102 | int __cpu_up(unsigned int cpu, struct task_struct *tidle) |
diff --git a/arch/riscv/kernel/stacktrace.c b/arch/riscv/kernel/stacktrace.c index 4d403274c2e8..e80a5e8da119 100644 --- a/arch/riscv/kernel/stacktrace.c +++ b/arch/riscv/kernel/stacktrace.c | |||
| @@ -33,9 +33,9 @@ static void notrace walk_stackframe(struct task_struct *task, | |||
| 33 | unsigned long fp, sp, pc; | 33 | unsigned long fp, sp, pc; |
| 34 | 34 | ||
| 35 | if (regs) { | 35 | if (regs) { |
| 36 | fp = GET_FP(regs); | 36 | fp = frame_pointer(regs); |
| 37 | sp = GET_USP(regs); | 37 | sp = user_stack_pointer(regs); |
| 38 | pc = GET_IP(regs); | 38 | pc = instruction_pointer(regs); |
| 39 | } else if (task == NULL || task == current) { | 39 | } else if (task == NULL || task == current) { |
| 40 | const register unsigned long current_sp __asm__ ("sp"); | 40 | const register unsigned long current_sp __asm__ ("sp"); |
| 41 | fp = (unsigned long)__builtin_frame_address(0); | 41 | fp = (unsigned long)__builtin_frame_address(0); |
| @@ -64,12 +64,8 @@ static void notrace walk_stackframe(struct task_struct *task, | |||
| 64 | frame = (struct stackframe *)fp - 1; | 64 | frame = (struct stackframe *)fp - 1; |
| 65 | sp = fp; | 65 | sp = fp; |
| 66 | fp = frame->fp; | 66 | fp = frame->fp; |
| 67 | #ifdef HAVE_FUNCTION_GRAPH_RET_ADDR_PTR | ||
| 68 | pc = ftrace_graph_ret_addr(current, NULL, frame->ra, | 67 | pc = ftrace_graph_ret_addr(current, NULL, frame->ra, |
| 69 | (unsigned long *)(fp - 8)); | 68 | (unsigned long *)(fp - 8)); |
| 70 | #else | ||
| 71 | pc = frame->ra - 0x4; | ||
| 72 | #endif | ||
| 73 | } | 69 | } |
| 74 | } | 70 | } |
| 75 | 71 | ||
| @@ -82,8 +78,8 @@ static void notrace walk_stackframe(struct task_struct *task, | |||
| 82 | unsigned long *ksp; | 78 | unsigned long *ksp; |
| 83 | 79 | ||
| 84 | if (regs) { | 80 | if (regs) { |
| 85 | sp = GET_USP(regs); | 81 | sp = user_stack_pointer(regs); |
| 86 | pc = GET_IP(regs); | 82 | pc = instruction_pointer(regs); |
| 87 | } else if (task == NULL || task == current) { | 83 | } else if (task == NULL || task == current) { |
| 88 | const register unsigned long current_sp __asm__ ("sp"); | 84 | const register unsigned long current_sp __asm__ ("sp"); |
| 89 | sp = current_sp; | 85 | sp = current_sp; |
diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c index 24a9333dda2c..3d1a651dc54c 100644 --- a/arch/riscv/kernel/traps.c +++ b/arch/riscv/kernel/traps.c | |||
| @@ -70,7 +70,7 @@ void do_trap(struct pt_regs *regs, int signo, int code, | |||
| 70 | && printk_ratelimit()) { | 70 | && printk_ratelimit()) { |
| 71 | pr_info("%s[%d]: unhandled signal %d code 0x%x at 0x" REG_FMT, | 71 | pr_info("%s[%d]: unhandled signal %d code 0x%x at 0x" REG_FMT, |
| 72 | tsk->comm, task_pid_nr(tsk), signo, code, addr); | 72 | tsk->comm, task_pid_nr(tsk), signo, code, addr); |
| 73 | print_vma_addr(KERN_CONT " in ", GET_IP(regs)); | 73 | print_vma_addr(KERN_CONT " in ", instruction_pointer(regs)); |
| 74 | pr_cont("\n"); | 74 | pr_cont("\n"); |
| 75 | show_regs(regs); | 75 | show_regs(regs); |
| 76 | } | 76 | } |
| @@ -118,6 +118,17 @@ DO_ERROR_INFO(do_trap_ecall_s, | |||
| 118 | DO_ERROR_INFO(do_trap_ecall_m, | 118 | DO_ERROR_INFO(do_trap_ecall_m, |
| 119 | SIGILL, ILL_ILLTRP, "environment call from M-mode"); | 119 | SIGILL, ILL_ILLTRP, "environment call from M-mode"); |
| 120 | 120 | ||
| 121 | #ifdef CONFIG_GENERIC_BUG | ||
| 122 | static inline unsigned long get_break_insn_length(unsigned long pc) | ||
| 123 | { | ||
| 124 | bug_insn_t insn; | ||
| 125 | |||
| 126 | if (probe_kernel_address((bug_insn_t *)pc, insn)) | ||
| 127 | return 0; | ||
| 128 | return (((insn & __INSN_LENGTH_MASK) == __INSN_LENGTH_32) ? 4UL : 2UL); | ||
| 129 | } | ||
| 130 | #endif /* CONFIG_GENERIC_BUG */ | ||
| 131 | |||
| 121 | asmlinkage void do_trap_break(struct pt_regs *regs) | 132 | asmlinkage void do_trap_break(struct pt_regs *regs) |
| 122 | { | 133 | { |
| 123 | #ifdef CONFIG_GENERIC_BUG | 134 | #ifdef CONFIG_GENERIC_BUG |
| @@ -129,8 +140,8 @@ asmlinkage void do_trap_break(struct pt_regs *regs) | |||
| 129 | case BUG_TRAP_TYPE_NONE: | 140 | case BUG_TRAP_TYPE_NONE: |
| 130 | break; | 141 | break; |
| 131 | case BUG_TRAP_TYPE_WARN: | 142 | case BUG_TRAP_TYPE_WARN: |
| 132 | regs->sepc += sizeof(bug_insn_t); | 143 | regs->sepc += get_break_insn_length(regs->sepc); |
| 133 | return; | 144 | break; |
| 134 | case BUG_TRAP_TYPE_BUG: | 145 | case BUG_TRAP_TYPE_BUG: |
| 135 | die(regs, "Kernel BUG"); | 146 | die(regs, "Kernel BUG"); |
| 136 | } | 147 | } |
| @@ -145,11 +156,14 @@ int is_valid_bugaddr(unsigned long pc) | |||
| 145 | { | 156 | { |
| 146 | bug_insn_t insn; | 157 | bug_insn_t insn; |
| 147 | 158 | ||
| 148 | if (pc < PAGE_OFFSET) | 159 | if (pc < VMALLOC_START) |
| 149 | return 0; | 160 | return 0; |
| 150 | if (probe_kernel_address((bug_insn_t *)pc, insn)) | 161 | if (probe_kernel_address((bug_insn_t *)pc, insn)) |
| 151 | return 0; | 162 | return 0; |
| 152 | return (insn == __BUG_INSN); | 163 | if ((insn & __INSN_LENGTH_MASK) == __INSN_LENGTH_32) |
| 164 | return (insn == __BUG_INSN_32); | ||
| 165 | else | ||
| 166 | return ((insn & __COMPRESSED_INSN_MASK) == __BUG_INSN_16); | ||
| 153 | } | 167 | } |
| 154 | #endif /* CONFIG_GENERIC_BUG */ | 168 | #endif /* CONFIG_GENERIC_BUG */ |
| 155 | 169 | ||
| @@ -159,9 +173,9 @@ void __init trap_init(void) | |||
| 159 | * Set sup0 scratch register to 0, indicating to exception vector | 173 | * Set sup0 scratch register to 0, indicating to exception vector |
| 160 | * that we are presently executing in the kernel | 174 | * that we are presently executing in the kernel |
| 161 | */ | 175 | */ |
| 162 | csr_write(sscratch, 0); | 176 | csr_write(CSR_SSCRATCH, 0); |
| 163 | /* Set the exception vector address */ | 177 | /* Set the exception vector address */ |
| 164 | csr_write(stvec, &handle_exception); | 178 | csr_write(CSR_STVEC, &handle_exception); |
| 165 | /* Enable all interrupts */ | 179 | /* Enable all interrupts */ |
| 166 | csr_write(sie, -1); | 180 | csr_write(CSR_SIE, -1); |
| 167 | } | 181 | } |
diff --git a/arch/riscv/kernel/vdso/Makefile b/arch/riscv/kernel/vdso/Makefile index fec62b24df89..b07b765f312a 100644 --- a/arch/riscv/kernel/vdso/Makefile +++ b/arch/riscv/kernel/vdso/Makefile | |||
| @@ -36,7 +36,7 @@ $(obj)/vdso.so.dbg: $(src)/vdso.lds $(obj-vdso) FORCE | |||
| 36 | # these symbols in the kernel code rather than hand-coded addresses. | 36 | # these symbols in the kernel code rather than hand-coded addresses. |
| 37 | 37 | ||
| 38 | SYSCFLAGS_vdso.so.dbg = -shared -s -Wl,-soname=linux-vdso.so.1 \ | 38 | SYSCFLAGS_vdso.so.dbg = -shared -s -Wl,-soname=linux-vdso.so.1 \ |
| 39 | $(call cc-ldoption, -Wl$(comma)--hash-style=both) | 39 | -Wl,--hash-style=both |
| 40 | $(obj)/vdso-dummy.o: $(src)/vdso.lds $(obj)/rt_sigreturn.o FORCE | 40 | $(obj)/vdso-dummy.o: $(src)/vdso.lds $(obj)/rt_sigreturn.o FORCE |
| 41 | $(call if_changed,vdsold) | 41 | $(call if_changed,vdsold) |
| 42 | 42 | ||
diff --git a/arch/riscv/mm/Makefile b/arch/riscv/mm/Makefile index b68aac701803..8db569141485 100644 --- a/arch/riscv/mm/Makefile +++ b/arch/riscv/mm/Makefile | |||
| @@ -9,3 +9,5 @@ obj-y += fault.o | |||
| 9 | obj-y += extable.o | 9 | obj-y += extable.o |
| 10 | obj-y += ioremap.o | 10 | obj-y += ioremap.o |
| 11 | obj-y += cacheflush.o | 11 | obj-y += cacheflush.o |
| 12 | obj-y += context.o | ||
| 13 | obj-y += sifive_l2_cache.o | ||
diff --git a/arch/riscv/mm/cacheflush.c b/arch/riscv/mm/cacheflush.c index 498c0a0814fe..497b7d07af0c 100644 --- a/arch/riscv/mm/cacheflush.c +++ b/arch/riscv/mm/cacheflush.c | |||
| @@ -14,6 +14,67 @@ | |||
| 14 | #include <asm/pgtable.h> | 14 | #include <asm/pgtable.h> |
| 15 | #include <asm/cacheflush.h> | 15 | #include <asm/cacheflush.h> |
| 16 | 16 | ||
| 17 | #ifdef CONFIG_SMP | ||
| 18 | |||
| 19 | #include <asm/sbi.h> | ||
| 20 | |||
| 21 | void flush_icache_all(void) | ||
| 22 | { | ||
| 23 | sbi_remote_fence_i(NULL); | ||
| 24 | } | ||
| 25 | |||
| 26 | /* | ||
| 27 | * Performs an icache flush for the given MM context. RISC-V has no direct | ||
| 28 | * mechanism for instruction cache shoot downs, so instead we send an IPI that | ||
| 29 | * informs the remote harts they need to flush their local instruction caches. | ||
| 30 | * To avoid pathologically slow behavior in a common case (a bunch of | ||
| 31 | * single-hart processes on a many-hart machine, ie 'make -j') we avoid the | ||
| 32 | * IPIs for harts that are not currently executing a MM context and instead | ||
| 33 | * schedule a deferred local instruction cache flush to be performed before | ||
| 34 | * execution resumes on each hart. | ||
| 35 | */ | ||
| 36 | void flush_icache_mm(struct mm_struct *mm, bool local) | ||
| 37 | { | ||
| 38 | unsigned int cpu; | ||
| 39 | cpumask_t others, hmask, *mask; | ||
| 40 | |||
| 41 | preempt_disable(); | ||
| 42 | |||
| 43 | /* Mark every hart's icache as needing a flush for this MM. */ | ||
| 44 | mask = &mm->context.icache_stale_mask; | ||
| 45 | cpumask_setall(mask); | ||
| 46 | /* Flush this hart's I$ now, and mark it as flushed. */ | ||
| 47 | cpu = smp_processor_id(); | ||
| 48 | cpumask_clear_cpu(cpu, mask); | ||
| 49 | local_flush_icache_all(); | ||
| 50 | |||
| 51 | /* | ||
| 52 | * Flush the I$ of other harts concurrently executing, and mark them as | ||
| 53 | * flushed. | ||
| 54 | */ | ||
| 55 | cpumask_andnot(&others, mm_cpumask(mm), cpumask_of(cpu)); | ||
| 56 | local |= cpumask_empty(&others); | ||
| 57 | if (mm != current->active_mm || !local) { | ||
| 58 | cpumask_clear(&hmask); | ||
| 59 | riscv_cpuid_to_hartid_mask(&others, &hmask); | ||
| 60 | sbi_remote_fence_i(hmask.bits); | ||
| 61 | } else { | ||
| 62 | /* | ||
| 63 | * It's assumed that at least one strongly ordered operation is | ||
| 64 | * performed on this hart between setting a hart's cpumask bit | ||
| 65 | * and scheduling this MM context on that hart. Sending an SBI | ||
| 66 | * remote message will do this, but in the case where no | ||
| 67 | * messages are sent we still need to order this hart's writes | ||
| 68 | * with flush_icache_deferred(). | ||
| 69 | */ | ||
| 70 | smp_mb(); | ||
| 71 | } | ||
| 72 | |||
| 73 | preempt_enable(); | ||
| 74 | } | ||
| 75 | |||
| 76 | #endif /* CONFIG_SMP */ | ||
| 77 | |||
| 17 | void flush_icache_pte(pte_t pte) | 78 | void flush_icache_pte(pte_t pte) |
| 18 | { | 79 | { |
| 19 | struct page *page = pte_page(pte); | 80 | struct page *page = pte_page(pte); |
diff --git a/arch/riscv/mm/context.c b/arch/riscv/mm/context.c new file mode 100644 index 000000000000..89ceb3cbe218 --- /dev/null +++ b/arch/riscv/mm/context.c | |||
| @@ -0,0 +1,69 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2012 Regents of the University of California | ||
| 4 | * Copyright (C) 2017 SiFive | ||
| 5 | */ | ||
| 6 | |||
| 7 | #include <linux/mm.h> | ||
| 8 | #include <asm/tlbflush.h> | ||
| 9 | #include <asm/cacheflush.h> | ||
| 10 | |||
| 11 | /* | ||
| 12 | * When necessary, performs a deferred icache flush for the given MM context, | ||
| 13 | * on the local CPU. RISC-V has no direct mechanism for instruction cache | ||
| 14 | * shoot downs, so instead we send an IPI that informs the remote harts they | ||
| 15 | * need to flush their local instruction caches. To avoid pathologically slow | ||
| 16 | * behavior in a common case (a bunch of single-hart processes on a many-hart | ||
| 17 | * machine, ie 'make -j') we avoid the IPIs for harts that are not currently | ||
| 18 | * executing a MM context and instead schedule a deferred local instruction | ||
| 19 | * cache flush to be performed before execution resumes on each hart. This | ||
| 20 | * actually performs that local instruction cache flush, which implicitly only | ||
| 21 | * refers to the current hart. | ||
| 22 | */ | ||
| 23 | static inline void flush_icache_deferred(struct mm_struct *mm) | ||
| 24 | { | ||
| 25 | #ifdef CONFIG_SMP | ||
| 26 | unsigned int cpu = smp_processor_id(); | ||
| 27 | cpumask_t *mask = &mm->context.icache_stale_mask; | ||
| 28 | |||
| 29 | if (cpumask_test_cpu(cpu, mask)) { | ||
| 30 | cpumask_clear_cpu(cpu, mask); | ||
| 31 | /* | ||
| 32 | * Ensure the remote hart's writes are visible to this hart. | ||
| 33 | * This pairs with a barrier in flush_icache_mm. | ||
| 34 | */ | ||
| 35 | smp_mb(); | ||
| 36 | local_flush_icache_all(); | ||
| 37 | } | ||
| 38 | |||
| 39 | #endif | ||
| 40 | } | ||
| 41 | |||
| 42 | void switch_mm(struct mm_struct *prev, struct mm_struct *next, | ||
| 43 | struct task_struct *task) | ||
| 44 | { | ||
| 45 | unsigned int cpu; | ||
| 46 | |||
| 47 | if (unlikely(prev == next)) | ||
| 48 | return; | ||
| 49 | |||
| 50 | /* | ||
| 51 | * Mark the current MM context as inactive, and the next as | ||
| 52 | * active. This is at least used by the icache flushing | ||
| 53 | * routines in order to determine who should be flushed. | ||
| 54 | */ | ||
| 55 | cpu = smp_processor_id(); | ||
| 56 | |||
| 57 | cpumask_clear_cpu(cpu, mm_cpumask(prev)); | ||
| 58 | cpumask_set_cpu(cpu, mm_cpumask(next)); | ||
| 59 | |||
| 60 | /* | ||
| 61 | * Use the old spbtr name instead of using the current satp | ||
| 62 | * name to support binutils 2.29 which doesn't know about the | ||
| 63 | * privileged ISA 1.10 yet. | ||
| 64 | */ | ||
| 65 | csr_write(sptbr, virt_to_pfn(next->pgd) | SATP_MODE); | ||
| 66 | local_flush_tlb_all(); | ||
| 67 | |||
| 68 | flush_icache_deferred(next); | ||
| 69 | } | ||
diff --git a/arch/riscv/mm/fault.c b/arch/riscv/mm/fault.c index 88401d5125bc..cec8be9e2d6a 100644 --- a/arch/riscv/mm/fault.c +++ b/arch/riscv/mm/fault.c | |||
| @@ -229,8 +229,9 @@ vmalloc_fault: | |||
| 229 | pte_t *pte_k; | 229 | pte_t *pte_k; |
| 230 | int index; | 230 | int index; |
| 231 | 231 | ||
| 232 | /* User mode accesses just cause a SIGSEGV */ | ||
| 232 | if (user_mode(regs)) | 233 | if (user_mode(regs)) |
| 233 | goto bad_area; | 234 | return do_trap(regs, SIGSEGV, code, addr, tsk); |
| 234 | 235 | ||
| 235 | /* | 236 | /* |
| 236 | * Synchronize this task's top level page-table | 237 | * Synchronize this task's top level page-table |
| @@ -239,13 +240,9 @@ vmalloc_fault: | |||
| 239 | * Do _not_ use "tsk->active_mm->pgd" here. | 240 | * Do _not_ use "tsk->active_mm->pgd" here. |
| 240 | * We might be inside an interrupt in the middle | 241 | * We might be inside an interrupt in the middle |
| 241 | * of a task switch. | 242 | * of a task switch. |
| 242 | * | ||
| 243 | * Note: Use the old spbtr name instead of using the current | ||
| 244 | * satp name to support binutils 2.29 which doesn't know about | ||
| 245 | * the privileged ISA 1.10 yet. | ||
| 246 | */ | 243 | */ |
| 247 | index = pgd_index(addr); | 244 | index = pgd_index(addr); |
| 248 | pgd = (pgd_t *)pfn_to_virt(csr_read(sptbr)) + index; | 245 | pgd = (pgd_t *)pfn_to_virt(csr_read(CSR_SATP)) + index; |
| 249 | pgd_k = init_mm.pgd + index; | 246 | pgd_k = init_mm.pgd + index; |
| 250 | 247 | ||
| 251 | if (!pgd_present(*pgd_k)) | 248 | if (!pgd_present(*pgd_k)) |
diff --git a/arch/riscv/mm/sifive_l2_cache.c b/arch/riscv/mm/sifive_l2_cache.c new file mode 100644 index 000000000000..4eb64619b3f4 --- /dev/null +++ b/arch/riscv/mm/sifive_l2_cache.c | |||
| @@ -0,0 +1,175 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * SiFive L2 cache controller Driver | ||
| 4 | * | ||
| 5 | * Copyright (C) 2018-2019 SiFive, Inc. | ||
| 6 | * | ||
| 7 | */ | ||
| 8 | #include <linux/debugfs.h> | ||
| 9 | #include <linux/interrupt.h> | ||
| 10 | #include <linux/of_irq.h> | ||
| 11 | #include <linux/of_address.h> | ||
| 12 | #include <asm/sifive_l2_cache.h> | ||
| 13 | |||
| 14 | #define SIFIVE_L2_DIRECCFIX_LOW 0x100 | ||
| 15 | #define SIFIVE_L2_DIRECCFIX_HIGH 0x104 | ||
| 16 | #define SIFIVE_L2_DIRECCFIX_COUNT 0x108 | ||
| 17 | |||
| 18 | #define SIFIVE_L2_DATECCFIX_LOW 0x140 | ||
| 19 | #define SIFIVE_L2_DATECCFIX_HIGH 0x144 | ||
| 20 | #define SIFIVE_L2_DATECCFIX_COUNT 0x148 | ||
| 21 | |||
| 22 | #define SIFIVE_L2_DATECCFAIL_LOW 0x160 | ||
| 23 | #define SIFIVE_L2_DATECCFAIL_HIGH 0x164 | ||
| 24 | #define SIFIVE_L2_DATECCFAIL_COUNT 0x168 | ||
| 25 | |||
| 26 | #define SIFIVE_L2_CONFIG 0x00 | ||
| 27 | #define SIFIVE_L2_WAYENABLE 0x08 | ||
| 28 | #define SIFIVE_L2_ECCINJECTERR 0x40 | ||
| 29 | |||
| 30 | #define SIFIVE_L2_MAX_ECCINTR 3 | ||
| 31 | |||
| 32 | static void __iomem *l2_base; | ||
| 33 | static int g_irq[SIFIVE_L2_MAX_ECCINTR]; | ||
| 34 | |||
| 35 | enum { | ||
| 36 | DIR_CORR = 0, | ||
| 37 | DATA_CORR, | ||
| 38 | DATA_UNCORR, | ||
| 39 | }; | ||
| 40 | |||
| 41 | #ifdef CONFIG_DEBUG_FS | ||
| 42 | static struct dentry *sifive_test; | ||
| 43 | |||
| 44 | static ssize_t l2_write(struct file *file, const char __user *data, | ||
| 45 | size_t count, loff_t *ppos) | ||
| 46 | { | ||
| 47 | unsigned int val; | ||
| 48 | |||
| 49 | if (kstrtouint_from_user(data, count, 0, &val)) | ||
| 50 | return -EINVAL; | ||
| 51 | if ((val >= 0 && val < 0xFF) || (val >= 0x10000 && val < 0x100FF)) | ||
| 52 | writel(val, l2_base + SIFIVE_L2_ECCINJECTERR); | ||
| 53 | else | ||
| 54 | return -EINVAL; | ||
| 55 | return count; | ||
| 56 | } | ||
| 57 | |||
| 58 | static const struct file_operations l2_fops = { | ||
| 59 | .owner = THIS_MODULE, | ||
| 60 | .open = simple_open, | ||
| 61 | .write = l2_write | ||
| 62 | }; | ||
| 63 | |||
| 64 | static void setup_sifive_debug(void) | ||
| 65 | { | ||
| 66 | sifive_test = debugfs_create_dir("sifive_l2_cache", NULL); | ||
| 67 | |||
| 68 | debugfs_create_file("sifive_debug_inject_error", 0200, | ||
| 69 | sifive_test, NULL, &l2_fops); | ||
| 70 | } | ||
| 71 | #endif | ||
| 72 | |||
| 73 | static void l2_config_read(void) | ||
| 74 | { | ||
| 75 | u32 regval, val; | ||
| 76 | |||
| 77 | regval = readl(l2_base + SIFIVE_L2_CONFIG); | ||
| 78 | val = regval & 0xFF; | ||
| 79 | pr_info("L2CACHE: No. of Banks in the cache: %d\n", val); | ||
| 80 | val = (regval & 0xFF00) >> 8; | ||
| 81 | pr_info("L2CACHE: No. of ways per bank: %d\n", val); | ||
| 82 | val = (regval & 0xFF0000) >> 16; | ||
| 83 | pr_info("L2CACHE: Sets per bank: %llu\n", (uint64_t)1 << val); | ||
| 84 | val = (regval & 0xFF000000) >> 24; | ||
| 85 | pr_info("L2CACHE: Bytes per cache block: %llu\n", (uint64_t)1 << val); | ||
| 86 | |||
| 87 | regval = readl(l2_base + SIFIVE_L2_WAYENABLE); | ||
| 88 | pr_info("L2CACHE: Index of the largest way enabled: %d\n", regval); | ||
| 89 | } | ||
| 90 | |||
| 91 | static const struct of_device_id sifive_l2_ids[] = { | ||
| 92 | { .compatible = "sifive,fu540-c000-ccache" }, | ||
| 93 | { /* end of table */ }, | ||
| 94 | }; | ||
| 95 | |||
| 96 | static ATOMIC_NOTIFIER_HEAD(l2_err_chain); | ||
| 97 | |||
| 98 | int register_sifive_l2_error_notifier(struct notifier_block *nb) | ||
| 99 | { | ||
| 100 | return atomic_notifier_chain_register(&l2_err_chain, nb); | ||
| 101 | } | ||
| 102 | EXPORT_SYMBOL_GPL(register_sifive_l2_error_notifier); | ||
| 103 | |||
| 104 | int unregister_sifive_l2_error_notifier(struct notifier_block *nb) | ||
| 105 | { | ||
| 106 | return atomic_notifier_chain_unregister(&l2_err_chain, nb); | ||
| 107 | } | ||
| 108 | EXPORT_SYMBOL_GPL(unregister_sifive_l2_error_notifier); | ||
| 109 | |||
| 110 | static irqreturn_t l2_int_handler(int irq, void *device) | ||
| 111 | { | ||
| 112 | unsigned int regval, add_h, add_l; | ||
| 113 | |||
| 114 | if (irq == g_irq[DIR_CORR]) { | ||
| 115 | add_h = readl(l2_base + SIFIVE_L2_DIRECCFIX_HIGH); | ||
| 116 | add_l = readl(l2_base + SIFIVE_L2_DIRECCFIX_LOW); | ||
| 117 | pr_err("L2CACHE: DirError @ 0x%08X.%08X\n", add_h, add_l); | ||
| 118 | regval = readl(l2_base + SIFIVE_L2_DIRECCFIX_COUNT); | ||
| 119 | atomic_notifier_call_chain(&l2_err_chain, SIFIVE_L2_ERR_TYPE_CE, | ||
| 120 | "DirECCFix"); | ||
| 121 | } | ||
| 122 | if (irq == g_irq[DATA_CORR]) { | ||
| 123 | add_h = readl(l2_base + SIFIVE_L2_DATECCFIX_HIGH); | ||
| 124 | add_l = readl(l2_base + SIFIVE_L2_DATECCFIX_LOW); | ||
| 125 | pr_err("L2CACHE: DataError @ 0x%08X.%08X\n", add_h, add_l); | ||
| 126 | regval = readl(l2_base + SIFIVE_L2_DATECCFIX_COUNT); | ||
| 127 | atomic_notifier_call_chain(&l2_err_chain, SIFIVE_L2_ERR_TYPE_CE, | ||
| 128 | "DatECCFix"); | ||
| 129 | } | ||
| 130 | if (irq == g_irq[DATA_UNCORR]) { | ||
| 131 | add_h = readl(l2_base + SIFIVE_L2_DATECCFAIL_HIGH); | ||
| 132 | add_l = readl(l2_base + SIFIVE_L2_DATECCFAIL_LOW); | ||
| 133 | pr_err("L2CACHE: DataFail @ 0x%08X.%08X\n", add_h, add_l); | ||
| 134 | regval = readl(l2_base + SIFIVE_L2_DATECCFAIL_COUNT); | ||
| 135 | atomic_notifier_call_chain(&l2_err_chain, SIFIVE_L2_ERR_TYPE_UE, | ||
| 136 | "DatECCFail"); | ||
| 137 | } | ||
| 138 | |||
| 139 | return IRQ_HANDLED; | ||
| 140 | } | ||
| 141 | |||
| 142 | int __init sifive_l2_init(void) | ||
| 143 | { | ||
| 144 | struct device_node *np; | ||
| 145 | struct resource res; | ||
| 146 | int i, rc; | ||
| 147 | |||
| 148 | np = of_find_matching_node(NULL, sifive_l2_ids); | ||
| 149 | if (!np) | ||
| 150 | return -ENODEV; | ||
| 151 | |||
| 152 | if (of_address_to_resource(np, 0, &res)) | ||
| 153 | return -ENODEV; | ||
| 154 | |||
| 155 | l2_base = ioremap(res.start, resource_size(&res)); | ||
| 156 | if (!l2_base) | ||
| 157 | return -ENOMEM; | ||
| 158 | |||
| 159 | for (i = 0; i < SIFIVE_L2_MAX_ECCINTR; i++) { | ||
| 160 | g_irq[i] = irq_of_parse_and_map(np, i); | ||
| 161 | rc = request_irq(g_irq[i], l2_int_handler, 0, "l2_ecc", NULL); | ||
| 162 | if (rc) { | ||
| 163 | pr_err("L2CACHE: Could not request IRQ %d\n", g_irq[i]); | ||
| 164 | return rc; | ||
| 165 | } | ||
| 166 | } | ||
| 167 | |||
| 168 | l2_config_read(); | ||
| 169 | |||
| 170 | #ifdef CONFIG_DEBUG_FS | ||
| 171 | setup_sifive_debug(); | ||
| 172 | #endif | ||
| 173 | return 0; | ||
| 174 | } | ||
| 175 | device_initcall(sifive_l2_init); | ||
diff --git a/arch/sh/Makefile b/arch/sh/Makefile index 4009bef62fe9..b4a86f27e048 100644 --- a/arch/sh/Makefile +++ b/arch/sh/Makefile | |||
| @@ -191,8 +191,8 @@ cpuincdir-y += cpu-common # Must be last | |||
| 191 | drivers-y += arch/sh/drivers/ | 191 | drivers-y += arch/sh/drivers/ |
| 192 | drivers-$(CONFIG_OPROFILE) += arch/sh/oprofile/ | 192 | drivers-$(CONFIG_OPROFILE) += arch/sh/oprofile/ |
| 193 | 193 | ||
| 194 | cflags-y += $(foreach d, $(cpuincdir-y), -Iarch/sh/include/$(d)) \ | 194 | cflags-y += $(foreach d, $(cpuincdir-y), -I $(srctree)/arch/sh/include/$(d)) \ |
| 195 | $(foreach d, $(machdir-y), -Iarch/sh/include/$(d)) | 195 | $(foreach d, $(machdir-y), -I $(srctree)/arch/sh/include/$(d)) |
| 196 | 196 | ||
| 197 | KBUILD_CFLAGS += -pipe $(cflags-y) | 197 | KBUILD_CFLAGS += -pipe $(cflags-y) |
| 198 | KBUILD_CPPFLAGS += $(cflags-y) | 198 | KBUILD_CPPFLAGS += $(cflags-y) |
diff --git a/arch/sh/boot/.gitignore b/arch/sh/boot/.gitignore index 541087d2029c..f50fdd9975c5 100644 --- a/arch/sh/boot/.gitignore +++ b/arch/sh/boot/.gitignore | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | zImage | 1 | zImage |
| 2 | vmlinux* | 2 | vmlinux* |
| 3 | uImage* | 3 | uImage* |
| 4 | !vmlinux.scr | ||
diff --git a/arch/sh/kernel/vsyscall/Makefile b/arch/sh/kernel/vsyscall/Makefile index 5db6579bc44c..6e8664448048 100644 --- a/arch/sh/kernel/vsyscall/Makefile +++ b/arch/sh/kernel/vsyscall/Makefile | |||
| @@ -15,8 +15,7 @@ quiet_cmd_syscall = SYSCALL $@ | |||
| 15 | 15 | ||
| 16 | export CPPFLAGS_vsyscall.lds += -P -C -Ush | 16 | export CPPFLAGS_vsyscall.lds += -P -C -Ush |
| 17 | 17 | ||
| 18 | vsyscall-flags = -shared -s -Wl,-soname=linux-gate.so.1 \ | 18 | vsyscall-flags = -shared -s -Wl,-soname=linux-gate.so.1 -Wl,--hash-style=sysv |
| 19 | $(call cc-ldoption, -Wl$(comma)--hash-style=sysv) | ||
| 20 | 19 | ||
| 21 | SYSCFLAGS_vsyscall-trapa.so = $(vsyscall-flags) | 20 | SYSCFLAGS_vsyscall-trapa.so = $(vsyscall-flags) |
| 22 | 21 | ||
diff --git a/arch/um/include/asm/mmu_context.h b/arch/um/include/asm/mmu_context.h index fca34b2177e2..9f4b4bb78120 100644 --- a/arch/um/include/asm/mmu_context.h +++ b/arch/um/include/asm/mmu_context.h | |||
| @@ -22,7 +22,6 @@ static inline int arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm) | |||
| 22 | } | 22 | } |
| 23 | extern void arch_exit_mmap(struct mm_struct *mm); | 23 | extern void arch_exit_mmap(struct mm_struct *mm); |
| 24 | static inline void arch_unmap(struct mm_struct *mm, | 24 | static inline void arch_unmap(struct mm_struct *mm, |
| 25 | struct vm_area_struct *vma, | ||
| 26 | unsigned long start, unsigned long end) | 25 | unsigned long start, unsigned long end) |
| 27 | { | 26 | { |
| 28 | } | 27 | } |
diff --git a/arch/unicore32/include/asm/mmu_context.h b/arch/unicore32/include/asm/mmu_context.h index 5c205a9cb5a6..9f06ea5466dd 100644 --- a/arch/unicore32/include/asm/mmu_context.h +++ b/arch/unicore32/include/asm/mmu_context.h | |||
| @@ -88,7 +88,6 @@ static inline int arch_dup_mmap(struct mm_struct *oldmm, | |||
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | static inline void arch_unmap(struct mm_struct *mm, | 90 | static inline void arch_unmap(struct mm_struct *mm, |
| 91 | struct vm_area_struct *vma, | ||
| 92 | unsigned long start, unsigned long end) | 91 | unsigned long start, unsigned long end) |
| 93 | { | 92 | { |
| 94 | } | 93 | } |
diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h index 93dff1963337..9024236693d2 100644 --- a/arch/x86/include/asm/mmu_context.h +++ b/arch/x86/include/asm/mmu_context.h | |||
| @@ -278,8 +278,8 @@ static inline void arch_bprm_mm_init(struct mm_struct *mm, | |||
| 278 | mpx_mm_init(mm); | 278 | mpx_mm_init(mm); |
| 279 | } | 279 | } |
| 280 | 280 | ||
| 281 | static inline void arch_unmap(struct mm_struct *mm, struct vm_area_struct *vma, | 281 | static inline void arch_unmap(struct mm_struct *mm, unsigned long start, |
| 282 | unsigned long start, unsigned long end) | 282 | unsigned long end) |
| 283 | { | 283 | { |
| 284 | /* | 284 | /* |
| 285 | * mpx_notify_unmap() goes and reads a rarely-hot | 285 | * mpx_notify_unmap() goes and reads a rarely-hot |
| @@ -299,7 +299,7 @@ static inline void arch_unmap(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 299 | * consistently wrong. | 299 | * consistently wrong. |
| 300 | */ | 300 | */ |
| 301 | if (unlikely(cpu_feature_enabled(X86_FEATURE_MPX))) | 301 | if (unlikely(cpu_feature_enabled(X86_FEATURE_MPX))) |
| 302 | mpx_notify_unmap(mm, vma, start, end); | 302 | mpx_notify_unmap(mm, start, end); |
| 303 | } | 303 | } |
| 304 | 304 | ||
| 305 | /* | 305 | /* |
diff --git a/arch/x86/include/asm/mpx.h b/arch/x86/include/asm/mpx.h index d0b1434fb0b6..143a5c193ed3 100644 --- a/arch/x86/include/asm/mpx.h +++ b/arch/x86/include/asm/mpx.h | |||
| @@ -64,12 +64,15 @@ struct mpx_fault_info { | |||
| 64 | }; | 64 | }; |
| 65 | 65 | ||
| 66 | #ifdef CONFIG_X86_INTEL_MPX | 66 | #ifdef CONFIG_X86_INTEL_MPX |
| 67 | int mpx_fault_info(struct mpx_fault_info *info, struct pt_regs *regs); | 67 | |
| 68 | int mpx_handle_bd_fault(void); | 68 | extern int mpx_fault_info(struct mpx_fault_info *info, struct pt_regs *regs); |
| 69 | extern int mpx_handle_bd_fault(void); | ||
| 70 | |||
| 69 | static inline int kernel_managing_mpx_tables(struct mm_struct *mm) | 71 | static inline int kernel_managing_mpx_tables(struct mm_struct *mm) |
| 70 | { | 72 | { |
| 71 | return (mm->context.bd_addr != MPX_INVALID_BOUNDS_DIR); | 73 | return (mm->context.bd_addr != MPX_INVALID_BOUNDS_DIR); |
| 72 | } | 74 | } |
| 75 | |||
| 73 | static inline void mpx_mm_init(struct mm_struct *mm) | 76 | static inline void mpx_mm_init(struct mm_struct *mm) |
| 74 | { | 77 | { |
| 75 | /* | 78 | /* |
| @@ -78,11 +81,10 @@ static inline void mpx_mm_init(struct mm_struct *mm) | |||
| 78 | */ | 81 | */ |
| 79 | mm->context.bd_addr = MPX_INVALID_BOUNDS_DIR; | 82 | mm->context.bd_addr = MPX_INVALID_BOUNDS_DIR; |
| 80 | } | 83 | } |
| 81 | void mpx_notify_unmap(struct mm_struct *mm, struct vm_area_struct *vma, | ||
| 82 | unsigned long start, unsigned long end); | ||
| 83 | 84 | ||
| 84 | unsigned long mpx_unmapped_area_check(unsigned long addr, unsigned long len, | 85 | extern void mpx_notify_unmap(struct mm_struct *mm, unsigned long start, unsigned long end); |
| 85 | unsigned long flags); | 86 | extern unsigned long mpx_unmapped_area_check(unsigned long addr, unsigned long len, unsigned long flags); |
| 87 | |||
| 86 | #else | 88 | #else |
| 87 | static inline int mpx_fault_info(struct mpx_fault_info *info, struct pt_regs *regs) | 89 | static inline int mpx_fault_info(struct mpx_fault_info *info, struct pt_regs *regs) |
| 88 | { | 90 | { |
| @@ -100,7 +102,6 @@ static inline void mpx_mm_init(struct mm_struct *mm) | |||
| 100 | { | 102 | { |
| 101 | } | 103 | } |
| 102 | static inline void mpx_notify_unmap(struct mm_struct *mm, | 104 | static inline void mpx_notify_unmap(struct mm_struct *mm, |
| 103 | struct vm_area_struct *vma, | ||
| 104 | unsigned long start, unsigned long end) | 105 | unsigned long start, unsigned long end) |
| 105 | { | 106 | { |
| 106 | } | 107 | } |
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 00b7e27bc2b7..ce1b5cc360a2 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile | |||
| @@ -42,7 +42,7 @@ endif | |||
| 42 | # non-deterministic coverage. | 42 | # non-deterministic coverage. |
| 43 | KCOV_INSTRUMENT := n | 43 | KCOV_INSTRUMENT := n |
| 44 | 44 | ||
| 45 | CFLAGS_irq.o := -I$(src)/../include/asm/trace | 45 | CFLAGS_irq.o := -I $(srctree)/$(src)/../include/asm/trace |
| 46 | 46 | ||
| 47 | obj-y := process_$(BITS).o signal.o | 47 | obj-y := process_$(BITS).o signal.o |
| 48 | obj-$(CONFIG_COMPAT) += signal_compat.o | 48 | obj-$(CONFIG_COMPAT) += signal_compat.o |
diff --git a/arch/x86/mm/Makefile b/arch/x86/mm/Makefile index 4b101dd6e52f..84373dc9b341 100644 --- a/arch/x86/mm/Makefile +++ b/arch/x86/mm/Makefile | |||
| @@ -21,7 +21,7 @@ CFLAGS_physaddr.o := $(nostackp) | |||
| 21 | CFLAGS_setup_nx.o := $(nostackp) | 21 | CFLAGS_setup_nx.o := $(nostackp) |
| 22 | CFLAGS_mem_encrypt_identity.o := $(nostackp) | 22 | CFLAGS_mem_encrypt_identity.o := $(nostackp) |
| 23 | 23 | ||
| 24 | CFLAGS_fault.o := -I$(src)/../include/asm/trace | 24 | CFLAGS_fault.o := -I $(srctree)/$(src)/../include/asm/trace |
| 25 | 25 | ||
| 26 | obj-$(CONFIG_X86_PAT) += pat_rbtree.o | 26 | obj-$(CONFIG_X86_PAT) += pat_rbtree.o |
| 27 | 27 | ||
diff --git a/arch/x86/mm/mpx.c b/arch/x86/mm/mpx.c index 59726aaf4671..0d1c47cbbdd6 100644 --- a/arch/x86/mm/mpx.c +++ b/arch/x86/mm/mpx.c | |||
| @@ -881,9 +881,10 @@ static int mpx_unmap_tables(struct mm_struct *mm, | |||
| 881 | * the virtual address region start...end have already been split if | 881 | * the virtual address region start...end have already been split if |
| 882 | * necessary, and the 'vma' is the first vma in this range (start -> end). | 882 | * necessary, and the 'vma' is the first vma in this range (start -> end). |
| 883 | */ | 883 | */ |
| 884 | void mpx_notify_unmap(struct mm_struct *mm, struct vm_area_struct *vma, | 884 | void mpx_notify_unmap(struct mm_struct *mm, unsigned long start, |
| 885 | unsigned long start, unsigned long end) | 885 | unsigned long end) |
| 886 | { | 886 | { |
| 887 | struct vm_area_struct *vma; | ||
| 887 | int ret; | 888 | int ret; |
| 888 | 889 | ||
| 889 | /* | 890 | /* |
| @@ -902,11 +903,12 @@ void mpx_notify_unmap(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 902 | * which should not occur normally. Being strict about it here | 903 | * which should not occur normally. Being strict about it here |
| 903 | * helps ensure that we do not have an exploitable stack overflow. | 904 | * helps ensure that we do not have an exploitable stack overflow. |
| 904 | */ | 905 | */ |
| 905 | do { | 906 | vma = find_vma(mm, start); |
| 907 | while (vma && vma->vm_start < end) { | ||
| 906 | if (vma->vm_flags & VM_MPX) | 908 | if (vma->vm_flags & VM_MPX) |
| 907 | return; | 909 | return; |
| 908 | vma = vma->vm_next; | 910 | vma = vma->vm_next; |
| 909 | } while (vma && vma->vm_start < end); | 911 | } |
| 910 | 912 | ||
| 911 | ret = mpx_unmap_tables(mm, start, end); | 913 | ret = mpx_unmap_tables(mm, start, end); |
| 912 | if (ret) | 914 | if (ret) |
diff --git a/arch/xtensa/boot/lib/Makefile b/arch/xtensa/boot/lib/Makefile index 355127faade1..e3d717c7bfa1 100644 --- a/arch/xtensa/boot/lib/Makefile +++ b/arch/xtensa/boot/lib/Makefile | |||
| @@ -7,7 +7,7 @@ zlib := inffast.c inflate.c inftrees.c | |||
| 7 | 7 | ||
| 8 | lib-y += $(zlib:.c=.o) zmem.o | 8 | lib-y += $(zlib:.c=.o) zmem.o |
| 9 | 9 | ||
| 10 | ccflags-y := -Ilib/zlib_inflate | 10 | ccflags-y := -I $(srctree)/lib/zlib_inflate |
| 11 | ifdef CONFIG_FUNCTION_TRACER | 11 | ifdef CONFIG_FUNCTION_TRACER |
| 12 | CFLAGS_REMOVE_inflate.o = -pg | 12 | CFLAGS_REMOVE_inflate.o = -pg |
| 13 | CFLAGS_REMOVE_zmem.o = -pg | 13 | CFLAGS_REMOVE_zmem.o = -pg |
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild index 35f83c4bf239..f1686d919178 100644 --- a/arch/xtensa/include/asm/Kbuild +++ b/arch/xtensa/include/asm/Kbuild | |||
| @@ -27,7 +27,6 @@ generic-y += preempt.h | |||
| 27 | generic-y += qrwlock.h | 27 | generic-y += qrwlock.h |
| 28 | generic-y += qspinlock.h | 28 | generic-y += qspinlock.h |
| 29 | generic-y += sections.h | 29 | generic-y += sections.h |
| 30 | generic-y += socket.h | ||
| 31 | generic-y += topology.h | 30 | generic-y += topology.h |
| 32 | generic-y += trace_clock.h | 31 | generic-y += trace_clock.h |
| 33 | generic-y += vga.h | 32 | generic-y += vga.h |
diff --git a/drivers/amba/tegra-ahb.c b/drivers/amba/tegra-ahb.c index b0b688c481e8..3751d811be39 100644 --- a/drivers/amba/tegra-ahb.c +++ b/drivers/amba/tegra-ahb.c | |||
| @@ -170,8 +170,7 @@ int tegra_ahb_enable_smmu(struct device_node *dn) | |||
| 170 | EXPORT_SYMBOL(tegra_ahb_enable_smmu); | 170 | EXPORT_SYMBOL(tegra_ahb_enable_smmu); |
| 171 | #endif | 171 | #endif |
| 172 | 172 | ||
| 173 | #ifdef CONFIG_PM | 173 | static int __maybe_unused tegra_ahb_suspend(struct device *dev) |
| 174 | static int tegra_ahb_suspend(struct device *dev) | ||
| 175 | { | 174 | { |
| 176 | int i; | 175 | int i; |
| 177 | struct tegra_ahb *ahb = dev_get_drvdata(dev); | 176 | struct tegra_ahb *ahb = dev_get_drvdata(dev); |
| @@ -181,7 +180,7 @@ static int tegra_ahb_suspend(struct device *dev) | |||
| 181 | return 0; | 180 | return 0; |
| 182 | } | 181 | } |
| 183 | 182 | ||
| 184 | static int tegra_ahb_resume(struct device *dev) | 183 | static int __maybe_unused tegra_ahb_resume(struct device *dev) |
| 185 | { | 184 | { |
| 186 | int i; | 185 | int i; |
| 187 | struct tegra_ahb *ahb = dev_get_drvdata(dev); | 186 | struct tegra_ahb *ahb = dev_get_drvdata(dev); |
| @@ -190,7 +189,6 @@ static int tegra_ahb_resume(struct device *dev) | |||
| 190 | gizmo_writel(ahb, ahb->ctx[i], tegra_ahb_gizmo[i]); | 189 | gizmo_writel(ahb, ahb->ctx[i], tegra_ahb_gizmo[i]); |
| 191 | return 0; | 190 | return 0; |
| 192 | } | 191 | } |
| 193 | #endif | ||
| 194 | 192 | ||
| 195 | static UNIVERSAL_DEV_PM_OPS(tegra_ahb_pm, | 193 | static UNIVERSAL_DEV_PM_OPS(tegra_ahb_pm, |
| 196 | tegra_ahb_suspend, | 194 | tegra_ahb_suspend, |
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 48321488f0fd..6bcaa4e2e72c 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig | |||
| @@ -387,7 +387,7 @@ config ARM_GLOBAL_TIMER | |||
| 387 | This options enables support for the ARM global timer unit | 387 | This options enables support for the ARM global timer unit |
| 388 | 388 | ||
| 389 | config ARM_TIMER_SP804 | 389 | config ARM_TIMER_SP804 |
| 390 | bool "Support for Dual Timer SP804 module" | 390 | bool "Support for Dual Timer SP804 module" if COMPILE_TEST |
| 391 | depends on GENERIC_SCHED_CLOCK && CLKDEV_LOOKUP | 391 | depends on GENERIC_SCHED_CLOCK && CLKDEV_LOOKUP |
| 392 | select CLKSRC_MMIO | 392 | select CLKSRC_MMIO |
| 393 | select TIMER_OF if OF | 393 | select TIMER_OF if OF |
| @@ -407,8 +407,11 @@ config ARMV7M_SYSTICK | |||
| 407 | This options enables support for the ARMv7M system timer unit | 407 | This options enables support for the ARMv7M system timer unit |
| 408 | 408 | ||
| 409 | config ATMEL_PIT | 409 | config ATMEL_PIT |
| 410 | bool "Atmel PIT support" if COMPILE_TEST | ||
| 411 | depends on HAS_IOMEM | ||
| 410 | select TIMER_OF if OF | 412 | select TIMER_OF if OF |
| 411 | def_bool SOC_AT91SAM9 || SOC_SAMA5 | 413 | help |
| 414 | Support for the Periodic Interval Timer found on Atmel SoCs. | ||
| 412 | 415 | ||
| 413 | config ATMEL_ST | 416 | config ATMEL_ST |
| 414 | bool "Atmel ST timer support" if COMPILE_TEST | 417 | bool "Atmel ST timer support" if COMPILE_TEST |
| @@ -418,6 +421,13 @@ config ATMEL_ST | |||
| 418 | help | 421 | help |
| 419 | Support for the Atmel ST timer. | 422 | Support for the Atmel ST timer. |
| 420 | 423 | ||
| 424 | config ATMEL_TCB_CLKSRC | ||
| 425 | bool "Atmel TC Block timer driver" if COMPILE_TEST | ||
| 426 | depends on HAS_IOMEM | ||
| 427 | select TIMER_OF if OF | ||
| 428 | help | ||
| 429 | Support for Timer Counter Blocks on Atmel SoCs. | ||
| 430 | |||
| 421 | config CLKSRC_EXYNOS_MCT | 431 | config CLKSRC_EXYNOS_MCT |
| 422 | bool "Exynos multi core timer driver" if COMPILE_TEST | 432 | bool "Exynos multi core timer driver" if COMPILE_TEST |
| 423 | depends on ARM || ARM64 | 433 | depends on ARM || ARM64 |
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index dba4eff880de..236858fa7fbf 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile | |||
| @@ -3,7 +3,7 @@ obj-$(CONFIG_TIMER_OF) += timer-of.o | |||
| 3 | obj-$(CONFIG_TIMER_PROBE) += timer-probe.o | 3 | obj-$(CONFIG_TIMER_PROBE) += timer-probe.o |
| 4 | obj-$(CONFIG_ATMEL_PIT) += timer-atmel-pit.o | 4 | obj-$(CONFIG_ATMEL_PIT) += timer-atmel-pit.o |
| 5 | obj-$(CONFIG_ATMEL_ST) += timer-atmel-st.o | 5 | obj-$(CONFIG_ATMEL_ST) += timer-atmel-st.o |
| 6 | obj-$(CONFIG_ATMEL_TCB_CLKSRC) += tcb_clksrc.o | 6 | obj-$(CONFIG_ATMEL_TCB_CLKSRC) += timer-atmel-tcb.o |
| 7 | obj-$(CONFIG_X86_PM_TIMER) += acpi_pm.o | 7 | obj-$(CONFIG_X86_PM_TIMER) += acpi_pm.o |
| 8 | obj-$(CONFIG_SCx200HR_TIMER) += scx200_hrt.o | 8 | obj-$(CONFIG_SCx200HR_TIMER) += scx200_hrt.o |
| 9 | obj-$(CONFIG_CS5535_CLOCK_EVENT_SRC) += timer-cs5535.o | 9 | obj-$(CONFIG_CS5535_CLOCK_EVENT_SRC) += timer-cs5535.o |
diff --git a/drivers/clocksource/tcb_clksrc.c b/drivers/clocksource/timer-atmel-tcb.c index f987027ca566..6ed31f9def7e 100644 --- a/drivers/clocksource/tcb_clksrc.c +++ b/drivers/clocksource/timer-atmel-tcb.c | |||
| @@ -9,9 +9,11 @@ | |||
| 9 | #include <linux/err.h> | 9 | #include <linux/err.h> |
| 10 | #include <linux/ioport.h> | 10 | #include <linux/ioport.h> |
| 11 | #include <linux/io.h> | 11 | #include <linux/io.h> |
| 12 | #include <linux/platform_device.h> | 12 | #include <linux/of_address.h> |
| 13 | #include <linux/of_irq.h> | ||
| 14 | #include <linux/sched_clock.h> | ||
| 13 | #include <linux/syscore_ops.h> | 15 | #include <linux/syscore_ops.h> |
| 14 | #include <linux/atmel_tc.h> | 16 | #include <soc/at91/atmel_tcb.h> |
| 15 | 17 | ||
| 16 | 18 | ||
| 17 | /* | 19 | /* |
| @@ -28,13 +30,6 @@ | |||
| 28 | * source, used in either periodic or oneshot mode. This runs | 30 | * source, used in either periodic or oneshot mode. This runs |
| 29 | * at 32 KiHZ, and can handle delays of up to two seconds. | 31 | * at 32 KiHZ, and can handle delays of up to two seconds. |
| 30 | * | 32 | * |
| 31 | * A boot clocksource and clockevent source are also currently needed, | ||
| 32 | * unless the relevant platforms (ARM/AT91, AVR32/AT32) are changed so | ||
| 33 | * this code can be used when init_timers() is called, well before most | ||
| 34 | * devices are set up. (Some low end AT91 parts, which can run uClinux, | ||
| 35 | * have only the timers in one TC block... they currently don't support | ||
| 36 | * the tclib code, because of that initialization issue.) | ||
| 37 | * | ||
| 38 | * REVISIT behavior during system suspend states... we should disable | 33 | * REVISIT behavior during system suspend states... we should disable |
| 39 | * all clocks and save the power. Easily done for clockevent devices, | 34 | * all clocks and save the power. Easily done for clockevent devices, |
| 40 | * but clocksources won't necessarily get the needed notifications. | 35 | * but clocksources won't necessarily get the needed notifications. |
| @@ -112,7 +107,6 @@ static void tc_clksrc_resume(struct clocksource *cs) | |||
| 112 | } | 107 | } |
| 113 | 108 | ||
| 114 | static struct clocksource clksrc = { | 109 | static struct clocksource clksrc = { |
| 115 | .name = "tcb_clksrc", | ||
| 116 | .rating = 200, | 110 | .rating = 200, |
| 117 | .read = tc_get_cycles, | 111 | .read = tc_get_cycles, |
| 118 | .mask = CLOCKSOURCE_MASK(32), | 112 | .mask = CLOCKSOURCE_MASK(32), |
| @@ -121,6 +115,16 @@ static struct clocksource clksrc = { | |||
| 121 | .resume = tc_clksrc_resume, | 115 | .resume = tc_clksrc_resume, |
| 122 | }; | 116 | }; |
| 123 | 117 | ||
| 118 | static u64 notrace tc_sched_clock_read(void) | ||
| 119 | { | ||
| 120 | return tc_get_cycles(&clksrc); | ||
| 121 | } | ||
| 122 | |||
| 123 | static u64 notrace tc_sched_clock_read32(void) | ||
| 124 | { | ||
| 125 | return tc_get_cycles32(&clksrc); | ||
| 126 | } | ||
| 127 | |||
| 124 | #ifdef CONFIG_GENERIC_CLOCKEVENTS | 128 | #ifdef CONFIG_GENERIC_CLOCKEVENTS |
| 125 | 129 | ||
| 126 | struct tc_clkevt_device { | 130 | struct tc_clkevt_device { |
| @@ -214,7 +218,6 @@ static int tc_next_event(unsigned long delta, struct clock_event_device *d) | |||
| 214 | 218 | ||
| 215 | static struct tc_clkevt_device clkevt = { | 219 | static struct tc_clkevt_device clkevt = { |
| 216 | .clkevt = { | 220 | .clkevt = { |
| 217 | .name = "tc_clkevt", | ||
| 218 | .features = CLOCK_EVT_FEAT_PERIODIC | | 221 | .features = CLOCK_EVT_FEAT_PERIODIC | |
| 219 | CLOCK_EVT_FEAT_ONESHOT, | 222 | CLOCK_EVT_FEAT_ONESHOT, |
| 220 | /* Should be lower than at91rm9200's system timer */ | 223 | /* Should be lower than at91rm9200's system timer */ |
| @@ -330,39 +333,74 @@ static void __init tcb_setup_single_chan(struct atmel_tc *tc, int mck_divisor_id | |||
| 330 | writel(ATMEL_TC_SYNC, tcaddr + ATMEL_TC_BCR); | 333 | writel(ATMEL_TC_SYNC, tcaddr + ATMEL_TC_BCR); |
| 331 | } | 334 | } |
| 332 | 335 | ||
| 333 | static int __init tcb_clksrc_init(void) | 336 | static const u8 atmel_tcb_divisors[5] = { 2, 8, 32, 128, 0, }; |
| 334 | { | 337 | |
| 335 | static char bootinfo[] __initdata | 338 | static const struct of_device_id atmel_tcb_of_match[] = { |
| 336 | = KERN_DEBUG "%s: tc%d at %d.%03d MHz\n"; | 339 | { .compatible = "atmel,at91rm9200-tcb", .data = (void *)16, }, |
| 340 | { .compatible = "atmel,at91sam9x5-tcb", .data = (void *)32, }, | ||
| 341 | { /* sentinel */ } | ||
| 342 | }; | ||
| 337 | 343 | ||
| 338 | struct platform_device *pdev; | 344 | static int __init tcb_clksrc_init(struct device_node *node) |
| 339 | struct atmel_tc *tc; | 345 | { |
| 346 | struct atmel_tc tc; | ||
| 340 | struct clk *t0_clk; | 347 | struct clk *t0_clk; |
| 348 | const struct of_device_id *match; | ||
| 349 | u64 (*tc_sched_clock)(void); | ||
| 341 | u32 rate, divided_rate = 0; | 350 | u32 rate, divided_rate = 0; |
| 342 | int best_divisor_idx = -1; | 351 | int best_divisor_idx = -1; |
| 343 | int clk32k_divisor_idx = -1; | 352 | int clk32k_divisor_idx = -1; |
| 353 | int bits; | ||
| 344 | int i; | 354 | int i; |
| 345 | int ret; | 355 | int ret; |
| 346 | 356 | ||
| 347 | tc = atmel_tc_alloc(CONFIG_ATMEL_TCB_CLKSRC_BLOCK); | 357 | /* Protect against multiple calls */ |
| 348 | if (!tc) { | 358 | if (tcaddr) |
| 349 | pr_debug("can't alloc TC for clocksource\n"); | 359 | return 0; |
| 350 | return -ENODEV; | 360 | |
| 361 | tc.regs = of_iomap(node->parent, 0); | ||
| 362 | if (!tc.regs) | ||
| 363 | return -ENXIO; | ||
| 364 | |||
| 365 | t0_clk = of_clk_get_by_name(node->parent, "t0_clk"); | ||
| 366 | if (IS_ERR(t0_clk)) | ||
| 367 | return PTR_ERR(t0_clk); | ||
| 368 | |||
| 369 | tc.slow_clk = of_clk_get_by_name(node->parent, "slow_clk"); | ||
| 370 | if (IS_ERR(tc.slow_clk)) | ||
| 371 | return PTR_ERR(tc.slow_clk); | ||
| 372 | |||
| 373 | tc.clk[0] = t0_clk; | ||
| 374 | tc.clk[1] = of_clk_get_by_name(node->parent, "t1_clk"); | ||
| 375 | if (IS_ERR(tc.clk[1])) | ||
| 376 | tc.clk[1] = t0_clk; | ||
| 377 | tc.clk[2] = of_clk_get_by_name(node->parent, "t2_clk"); | ||
| 378 | if (IS_ERR(tc.clk[2])) | ||
| 379 | tc.clk[2] = t0_clk; | ||
| 380 | |||
| 381 | tc.irq[2] = of_irq_get(node->parent, 2); | ||
| 382 | if (tc.irq[2] <= 0) { | ||
| 383 | tc.irq[2] = of_irq_get(node->parent, 0); | ||
| 384 | if (tc.irq[2] <= 0) | ||
| 385 | return -EINVAL; | ||
| 351 | } | 386 | } |
| 352 | tcaddr = tc->regs; | ||
| 353 | pdev = tc->pdev; | ||
| 354 | 387 | ||
| 355 | t0_clk = tc->clk[0]; | 388 | match = of_match_node(atmel_tcb_of_match, node->parent); |
| 389 | bits = (uintptr_t)match->data; | ||
| 390 | |||
| 391 | for (i = 0; i < ARRAY_SIZE(tc.irq); i++) | ||
| 392 | writel(ATMEL_TC_ALL_IRQ, tc.regs + ATMEL_TC_REG(i, IDR)); | ||
| 393 | |||
| 356 | ret = clk_prepare_enable(t0_clk); | 394 | ret = clk_prepare_enable(t0_clk); |
| 357 | if (ret) { | 395 | if (ret) { |
| 358 | pr_debug("can't enable T0 clk\n"); | 396 | pr_debug("can't enable T0 clk\n"); |
| 359 | goto err_free_tc; | 397 | return ret; |
| 360 | } | 398 | } |
| 361 | 399 | ||
| 362 | /* How fast will we be counting? Pick something over 5 MHz. */ | 400 | /* How fast will we be counting? Pick something over 5 MHz. */ |
| 363 | rate = (u32) clk_get_rate(t0_clk); | 401 | rate = (u32) clk_get_rate(t0_clk); |
| 364 | for (i = 0; i < 5; i++) { | 402 | for (i = 0; i < ARRAY_SIZE(atmel_tcb_divisors); i++) { |
| 365 | unsigned divisor = atmel_tc_divisors[i]; | 403 | unsigned divisor = atmel_tcb_divisors[i]; |
| 366 | unsigned tmp; | 404 | unsigned tmp; |
| 367 | 405 | ||
| 368 | /* remember 32 KiHz clock for later */ | 406 | /* remember 32 KiHz clock for later */ |
| @@ -381,27 +419,31 @@ static int __init tcb_clksrc_init(void) | |||
| 381 | best_divisor_idx = i; | 419 | best_divisor_idx = i; |
| 382 | } | 420 | } |
| 383 | 421 | ||
| 384 | 422 | clksrc.name = kbasename(node->parent->full_name); | |
| 385 | printk(bootinfo, clksrc.name, CONFIG_ATMEL_TCB_CLKSRC_BLOCK, | 423 | clkevt.clkevt.name = kbasename(node->parent->full_name); |
| 386 | divided_rate / 1000000, | 424 | pr_debug("%s at %d.%03d MHz\n", clksrc.name, divided_rate / 1000000, |
| 387 | ((divided_rate % 1000000) + 500) / 1000); | 425 | ((divided_rate % 1000000) + 500) / 1000); |
| 388 | 426 | ||
| 389 | if (tc->tcb_config && tc->tcb_config->counter_width == 32) { | 427 | tcaddr = tc.regs; |
| 428 | |||
| 429 | if (bits == 32) { | ||
| 390 | /* use apropriate function to read 32 bit counter */ | 430 | /* use apropriate function to read 32 bit counter */ |
| 391 | clksrc.read = tc_get_cycles32; | 431 | clksrc.read = tc_get_cycles32; |
| 392 | /* setup ony channel 0 */ | 432 | /* setup ony channel 0 */ |
| 393 | tcb_setup_single_chan(tc, best_divisor_idx); | 433 | tcb_setup_single_chan(&tc, best_divisor_idx); |
| 434 | tc_sched_clock = tc_sched_clock_read32; | ||
| 394 | } else { | 435 | } else { |
| 395 | /* tclib will give us three clocks no matter what the | 436 | /* we have three clocks no matter what the |
| 396 | * underlying platform supports. | 437 | * underlying platform supports. |
| 397 | */ | 438 | */ |
| 398 | ret = clk_prepare_enable(tc->clk[1]); | 439 | ret = clk_prepare_enable(tc.clk[1]); |
| 399 | if (ret) { | 440 | if (ret) { |
| 400 | pr_debug("can't enable T1 clk\n"); | 441 | pr_debug("can't enable T1 clk\n"); |
| 401 | goto err_disable_t0; | 442 | goto err_disable_t0; |
| 402 | } | 443 | } |
| 403 | /* setup both channel 0 & 1 */ | 444 | /* setup both channel 0 & 1 */ |
| 404 | tcb_setup_dual_chan(tc, best_divisor_idx); | 445 | tcb_setup_dual_chan(&tc, best_divisor_idx); |
| 446 | tc_sched_clock = tc_sched_clock_read; | ||
| 405 | } | 447 | } |
| 406 | 448 | ||
| 407 | /* and away we go! */ | 449 | /* and away we go! */ |
| @@ -410,24 +452,26 @@ static int __init tcb_clksrc_init(void) | |||
| 410 | goto err_disable_t1; | 452 | goto err_disable_t1; |
| 411 | 453 | ||
| 412 | /* channel 2: periodic and oneshot timer support */ | 454 | /* channel 2: periodic and oneshot timer support */ |
| 413 | ret = setup_clkevents(tc, clk32k_divisor_idx); | 455 | ret = setup_clkevents(&tc, clk32k_divisor_idx); |
| 414 | if (ret) | 456 | if (ret) |
| 415 | goto err_unregister_clksrc; | 457 | goto err_unregister_clksrc; |
| 416 | 458 | ||
| 459 | sched_clock_register(tc_sched_clock, 32, divided_rate); | ||
| 460 | |||
| 417 | return 0; | 461 | return 0; |
| 418 | 462 | ||
| 419 | err_unregister_clksrc: | 463 | err_unregister_clksrc: |
| 420 | clocksource_unregister(&clksrc); | 464 | clocksource_unregister(&clksrc); |
| 421 | 465 | ||
| 422 | err_disable_t1: | 466 | err_disable_t1: |
| 423 | if (!tc->tcb_config || tc->tcb_config->counter_width != 32) | 467 | if (bits != 32) |
| 424 | clk_disable_unprepare(tc->clk[1]); | 468 | clk_disable_unprepare(tc.clk[1]); |
| 425 | 469 | ||
| 426 | err_disable_t0: | 470 | err_disable_t0: |
| 427 | clk_disable_unprepare(t0_clk); | 471 | clk_disable_unprepare(t0_clk); |
| 428 | 472 | ||
| 429 | err_free_tc: | 473 | tcaddr = NULL; |
| 430 | atmel_tc_free(tc); | 474 | |
| 431 | return ret; | 475 | return ret; |
| 432 | } | 476 | } |
| 433 | arch_initcall(tcb_clksrc_init); | 477 | TIMER_OF_DECLARE(atmel_tcb_clksrc, "atmel,tcb-timer", tcb_clksrc_init); |
diff --git a/drivers/clocksource/timer-milbeaut.c b/drivers/clocksource/timer-milbeaut.c index f2019a88e3ee..fa9fb4eacade 100644 --- a/drivers/clocksource/timer-milbeaut.c +++ b/drivers/clocksource/timer-milbeaut.c | |||
| @@ -26,8 +26,8 @@ | |||
| 26 | #define MLB_TMR_TMCSR_CSL_DIV2 0 | 26 | #define MLB_TMR_TMCSR_CSL_DIV2 0 |
| 27 | #define MLB_TMR_DIV_CNT 2 | 27 | #define MLB_TMR_DIV_CNT 2 |
| 28 | 28 | ||
| 29 | #define MLB_TMR_SRC_CH (1) | 29 | #define MLB_TMR_SRC_CH 1 |
| 30 | #define MLB_TMR_EVT_CH (0) | 30 | #define MLB_TMR_EVT_CH 0 |
| 31 | 31 | ||
| 32 | #define MLB_TMR_SRC_CH_OFS (MLB_TMR_REGSZPCH * MLB_TMR_SRC_CH) | 32 | #define MLB_TMR_SRC_CH_OFS (MLB_TMR_REGSZPCH * MLB_TMR_SRC_CH) |
| 33 | #define MLB_TMR_EVT_CH_OFS (MLB_TMR_REGSZPCH * MLB_TMR_EVT_CH) | 33 | #define MLB_TMR_EVT_CH_OFS (MLB_TMR_REGSZPCH * MLB_TMR_EVT_CH) |
| @@ -43,6 +43,8 @@ | |||
| 43 | #define MLB_TMR_EVT_TMRLR2_OFS (MLB_TMR_EVT_CH_OFS + MLB_TMR_TMRLR2_OFS) | 43 | #define MLB_TMR_EVT_TMRLR2_OFS (MLB_TMR_EVT_CH_OFS + MLB_TMR_TMRLR2_OFS) |
| 44 | 44 | ||
| 45 | #define MLB_TIMER_RATING 500 | 45 | #define MLB_TIMER_RATING 500 |
| 46 | #define MLB_TIMER_ONESHOT 0 | ||
| 47 | #define MLB_TIMER_PERIODIC 1 | ||
| 46 | 48 | ||
| 47 | static irqreturn_t mlb_timer_interrupt(int irq, void *dev_id) | 49 | static irqreturn_t mlb_timer_interrupt(int irq, void *dev_id) |
| 48 | { | 50 | { |
| @@ -59,27 +61,53 @@ static irqreturn_t mlb_timer_interrupt(int irq, void *dev_id) | |||
| 59 | return IRQ_HANDLED; | 61 | return IRQ_HANDLED; |
| 60 | } | 62 | } |
| 61 | 63 | ||
| 62 | static int mlb_set_state_periodic(struct clock_event_device *clk) | 64 | static void mlb_evt_timer_start(struct timer_of *to, bool periodic) |
| 63 | { | 65 | { |
| 64 | struct timer_of *to = to_timer_of(clk); | ||
| 65 | u32 val = MLB_TMR_TMCSR_CSL_DIV2; | 66 | u32 val = MLB_TMR_TMCSR_CSL_DIV2; |
| 66 | 67 | ||
| 68 | val |= MLB_TMR_TMCSR_CNTE | MLB_TMR_TMCSR_TRG | MLB_TMR_TMCSR_INTE; | ||
| 69 | if (periodic) | ||
| 70 | val |= MLB_TMR_TMCSR_RELD; | ||
| 67 | writel_relaxed(val, timer_of_base(to) + MLB_TMR_EVT_TMCSR_OFS); | 71 | writel_relaxed(val, timer_of_base(to) + MLB_TMR_EVT_TMCSR_OFS); |
| 72 | } | ||
| 68 | 73 | ||
| 69 | writel_relaxed(to->of_clk.period, timer_of_base(to) + | 74 | static void mlb_evt_timer_stop(struct timer_of *to) |
| 70 | MLB_TMR_EVT_TMRLR1_OFS); | 75 | { |
| 71 | val |= MLB_TMR_TMCSR_RELD | MLB_TMR_TMCSR_CNTE | | 76 | u32 val = readl_relaxed(timer_of_base(to) + MLB_TMR_EVT_TMCSR_OFS); |
| 72 | MLB_TMR_TMCSR_TRG | MLB_TMR_TMCSR_INTE; | 77 | |
| 78 | val &= ~MLB_TMR_TMCSR_CNTE; | ||
| 73 | writel_relaxed(val, timer_of_base(to) + MLB_TMR_EVT_TMCSR_OFS); | 79 | writel_relaxed(val, timer_of_base(to) + MLB_TMR_EVT_TMCSR_OFS); |
| 80 | } | ||
| 81 | |||
| 82 | static void mlb_evt_timer_register_count(struct timer_of *to, unsigned long cnt) | ||
| 83 | { | ||
| 84 | writel_relaxed(cnt, timer_of_base(to) + MLB_TMR_EVT_TMRLR1_OFS); | ||
| 85 | } | ||
| 86 | |||
| 87 | static int mlb_set_state_periodic(struct clock_event_device *clk) | ||
| 88 | { | ||
| 89 | struct timer_of *to = to_timer_of(clk); | ||
| 90 | |||
| 91 | mlb_evt_timer_stop(to); | ||
| 92 | mlb_evt_timer_register_count(to, to->of_clk.period); | ||
| 93 | mlb_evt_timer_start(to, MLB_TIMER_PERIODIC); | ||
| 74 | return 0; | 94 | return 0; |
| 75 | } | 95 | } |
| 76 | 96 | ||
| 77 | static int mlb_set_state_oneshot(struct clock_event_device *clk) | 97 | static int mlb_set_state_oneshot(struct clock_event_device *clk) |
| 78 | { | 98 | { |
| 79 | struct timer_of *to = to_timer_of(clk); | 99 | struct timer_of *to = to_timer_of(clk); |
| 80 | u32 val = MLB_TMR_TMCSR_CSL_DIV2; | ||
| 81 | 100 | ||
| 82 | writel_relaxed(val, timer_of_base(to) + MLB_TMR_EVT_TMCSR_OFS); | 101 | mlb_evt_timer_stop(to); |
| 102 | mlb_evt_timer_start(to, MLB_TIMER_ONESHOT); | ||
| 103 | return 0; | ||
| 104 | } | ||
| 105 | |||
| 106 | static int mlb_set_state_shutdown(struct clock_event_device *clk) | ||
| 107 | { | ||
| 108 | struct timer_of *to = to_timer_of(clk); | ||
| 109 | |||
| 110 | mlb_evt_timer_stop(to); | ||
| 83 | return 0; | 111 | return 0; |
| 84 | } | 112 | } |
| 85 | 113 | ||
| @@ -88,22 +116,21 @@ static int mlb_clkevt_next_event(unsigned long event, | |||
| 88 | { | 116 | { |
| 89 | struct timer_of *to = to_timer_of(clk); | 117 | struct timer_of *to = to_timer_of(clk); |
| 90 | 118 | ||
| 91 | writel_relaxed(event, timer_of_base(to) + MLB_TMR_EVT_TMRLR1_OFS); | 119 | mlb_evt_timer_stop(to); |
| 92 | writel_relaxed(MLB_TMR_TMCSR_CSL_DIV2 | | 120 | mlb_evt_timer_register_count(to, event); |
| 93 | MLB_TMR_TMCSR_CNTE | MLB_TMR_TMCSR_INTE | | 121 | mlb_evt_timer_start(to, MLB_TIMER_ONESHOT); |
| 94 | MLB_TMR_TMCSR_TRG, timer_of_base(to) + | ||
| 95 | MLB_TMR_EVT_TMCSR_OFS); | ||
| 96 | return 0; | 122 | return 0; |
| 97 | } | 123 | } |
| 98 | 124 | ||
| 99 | static int mlb_config_clock_source(struct timer_of *to) | 125 | static int mlb_config_clock_source(struct timer_of *to) |
| 100 | { | 126 | { |
| 101 | writel_relaxed(0, timer_of_base(to) + MLB_TMR_SRC_TMCSR_OFS); | 127 | u32 val = MLB_TMR_TMCSR_CSL_DIV2; |
| 102 | writel_relaxed(~0, timer_of_base(to) + MLB_TMR_SRC_TMR_OFS); | 128 | |
| 129 | writel_relaxed(val, timer_of_base(to) + MLB_TMR_SRC_TMCSR_OFS); | ||
| 103 | writel_relaxed(~0, timer_of_base(to) + MLB_TMR_SRC_TMRLR1_OFS); | 130 | writel_relaxed(~0, timer_of_base(to) + MLB_TMR_SRC_TMRLR1_OFS); |
| 104 | writel_relaxed(~0, timer_of_base(to) + MLB_TMR_SRC_TMRLR2_OFS); | 131 | writel_relaxed(~0, timer_of_base(to) + MLB_TMR_SRC_TMRLR2_OFS); |
| 105 | writel_relaxed(BIT(4) | BIT(1) | BIT(0), timer_of_base(to) + | 132 | val |= MLB_TMR_TMCSR_RELD | MLB_TMR_TMCSR_CNTE | MLB_TMR_TMCSR_TRG; |
| 106 | MLB_TMR_SRC_TMCSR_OFS); | 133 | writel_relaxed(val, timer_of_base(to) + MLB_TMR_SRC_TMCSR_OFS); |
| 107 | return 0; | 134 | return 0; |
| 108 | } | 135 | } |
| 109 | 136 | ||
| @@ -123,6 +150,7 @@ static struct timer_of to = { | |||
| 123 | .features = CLOCK_EVT_FEAT_DYNIRQ | CLOCK_EVT_FEAT_ONESHOT, | 150 | .features = CLOCK_EVT_FEAT_DYNIRQ | CLOCK_EVT_FEAT_ONESHOT, |
| 124 | .set_state_oneshot = mlb_set_state_oneshot, | 151 | .set_state_oneshot = mlb_set_state_oneshot, |
| 125 | .set_state_periodic = mlb_set_state_periodic, | 152 | .set_state_periodic = mlb_set_state_periodic, |
| 153 | .set_state_shutdown = mlb_set_state_shutdown, | ||
| 126 | .set_next_event = mlb_clkevt_next_event, | 154 | .set_next_event = mlb_clkevt_next_event, |
| 127 | }, | 155 | }, |
| 128 | 156 | ||
diff --git a/drivers/clocksource/timer-sun4i.c b/drivers/clocksource/timer-sun4i.c index 6e0180aaf784..65f38f6ca714 100644 --- a/drivers/clocksource/timer-sun4i.c +++ b/drivers/clocksource/timer-sun4i.c | |||
| @@ -186,7 +186,8 @@ static int __init sun4i_timer_init(struct device_node *node) | |||
| 186 | */ | 186 | */ |
| 187 | if (of_machine_is_compatible("allwinner,sun4i-a10") || | 187 | if (of_machine_is_compatible("allwinner,sun4i-a10") || |
| 188 | of_machine_is_compatible("allwinner,sun5i-a13") || | 188 | of_machine_is_compatible("allwinner,sun5i-a13") || |
| 189 | of_machine_is_compatible("allwinner,sun5i-a10s")) | 189 | of_machine_is_compatible("allwinner,sun5i-a10s") || |
| 190 | of_machine_is_compatible("allwinner,suniv-f1c100s")) | ||
| 190 | sched_clock_register(sun4i_timer_sched_read, 32, | 191 | sched_clock_register(sun4i_timer_sched_read, 32, |
| 191 | timer_of_rate(&to)); | 192 | timer_of_rate(&to)); |
| 192 | 193 | ||
| @@ -218,3 +219,5 @@ static int __init sun4i_timer_init(struct device_node *node) | |||
| 218 | } | 219 | } |
| 219 | TIMER_OF_DECLARE(sun4i, "allwinner,sun4i-a10-timer", | 220 | TIMER_OF_DECLARE(sun4i, "allwinner,sun4i-a10-timer", |
| 220 | sun4i_timer_init); | 221 | sun4i_timer_init); |
| 222 | TIMER_OF_DECLARE(suniv, "allwinner,suniv-f1c100s-timer", | ||
| 223 | sun4i_timer_init); | ||
diff --git a/drivers/clocksource/timer-tegra20.c b/drivers/clocksource/timer-tegra20.c index fdb3d795a409..919b3568c495 100644 --- a/drivers/clocksource/timer-tegra20.c +++ b/drivers/clocksource/timer-tegra20.c | |||
| @@ -60,9 +60,6 @@ | |||
| 60 | static u32 usec_config; | 60 | static u32 usec_config; |
| 61 | static void __iomem *timer_reg_base; | 61 | static void __iomem *timer_reg_base; |
| 62 | #ifdef CONFIG_ARM | 62 | #ifdef CONFIG_ARM |
| 63 | static void __iomem *rtc_base; | ||
| 64 | static struct timespec64 persistent_ts; | ||
| 65 | static u64 persistent_ms, last_persistent_ms; | ||
| 66 | static struct delay_timer tegra_delay_timer; | 63 | static struct delay_timer tegra_delay_timer; |
| 67 | #endif | 64 | #endif |
| 68 | 65 | ||
| @@ -199,40 +196,30 @@ static unsigned long tegra_delay_timer_read_counter_long(void) | |||
| 199 | return readl(timer_reg_base + TIMERUS_CNTR_1US); | 196 | return readl(timer_reg_base + TIMERUS_CNTR_1US); |
| 200 | } | 197 | } |
| 201 | 198 | ||
| 199 | static struct timer_of suspend_rtc_to = { | ||
| 200 | .flags = TIMER_OF_BASE | TIMER_OF_CLOCK, | ||
| 201 | }; | ||
| 202 | |||
| 202 | /* | 203 | /* |
| 203 | * tegra_rtc_read - Reads the Tegra RTC registers | 204 | * tegra_rtc_read - Reads the Tegra RTC registers |
| 204 | * Care must be taken that this funciton is not called while the | 205 | * Care must be taken that this funciton is not called while the |
| 205 | * tegra_rtc driver could be executing to avoid race conditions | 206 | * tegra_rtc driver could be executing to avoid race conditions |
| 206 | * on the RTC shadow register | 207 | * on the RTC shadow register |
| 207 | */ | 208 | */ |
| 208 | static u64 tegra_rtc_read_ms(void) | 209 | static u64 tegra_rtc_read_ms(struct clocksource *cs) |
| 209 | { | 210 | { |
| 210 | u32 ms = readl(rtc_base + RTC_MILLISECONDS); | 211 | u32 ms = readl(timer_of_base(&suspend_rtc_to) + RTC_MILLISECONDS); |
| 211 | u32 s = readl(rtc_base + RTC_SHADOW_SECONDS); | 212 | u32 s = readl(timer_of_base(&suspend_rtc_to) + RTC_SHADOW_SECONDS); |
| 212 | return (u64)s * MSEC_PER_SEC + ms; | 213 | return (u64)s * MSEC_PER_SEC + ms; |
| 213 | } | 214 | } |
| 214 | 215 | ||
| 215 | /* | 216 | static struct clocksource suspend_rtc_clocksource = { |
| 216 | * tegra_read_persistent_clock64 - Return time from a persistent clock. | 217 | .name = "tegra_suspend_timer", |
| 217 | * | 218 | .rating = 200, |
| 218 | * Reads the time from a source which isn't disabled during PM, the | 219 | .read = tegra_rtc_read_ms, |
| 219 | * 32k sync timer. Convert the cycles elapsed since last read into | 220 | .mask = CLOCKSOURCE_MASK(32), |
| 220 | * nsecs and adds to a monotonically increasing timespec64. | 221 | .flags = CLOCK_SOURCE_IS_CONTINUOUS | CLOCK_SOURCE_SUSPEND_NONSTOP, |
| 221 | * Care must be taken that this funciton is not called while the | 222 | }; |
| 222 | * tegra_rtc driver could be executing to avoid race conditions | ||
| 223 | * on the RTC shadow register | ||
| 224 | */ | ||
| 225 | static void tegra_read_persistent_clock64(struct timespec64 *ts) | ||
| 226 | { | ||
| 227 | u64 delta; | ||
| 228 | |||
| 229 | last_persistent_ms = persistent_ms; | ||
| 230 | persistent_ms = tegra_rtc_read_ms(); | ||
| 231 | delta = persistent_ms - last_persistent_ms; | ||
| 232 | |||
| 233 | timespec64_add_ns(&persistent_ts, delta * NSEC_PER_MSEC); | ||
| 234 | *ts = persistent_ts; | ||
| 235 | } | ||
| 236 | #endif | 223 | #endif |
| 237 | 224 | ||
| 238 | static int tegra_timer_common_init(struct device_node *np, struct timer_of *to) | 225 | static int tegra_timer_common_init(struct device_node *np, struct timer_of *to) |
| @@ -385,25 +372,15 @@ out: | |||
| 385 | 372 | ||
| 386 | static int __init tegra20_init_rtc(struct device_node *np) | 373 | static int __init tegra20_init_rtc(struct device_node *np) |
| 387 | { | 374 | { |
| 388 | struct clk *clk; | 375 | int ret; |
| 389 | 376 | ||
| 390 | rtc_base = of_iomap(np, 0); | 377 | ret = timer_of_init(np, &suspend_rtc_to); |
| 391 | if (!rtc_base) { | 378 | if (ret) |
| 392 | pr_err("Can't map RTC registers\n"); | 379 | return ret; |
| 393 | return -ENXIO; | ||
| 394 | } | ||
| 395 | 380 | ||
| 396 | /* | 381 | clocksource_register_hz(&suspend_rtc_clocksource, 1000); |
| 397 | * rtc registers are used by read_persistent_clock, keep the rtc clock | ||
| 398 | * enabled | ||
| 399 | */ | ||
| 400 | clk = of_clk_get(np, 0); | ||
| 401 | if (IS_ERR(clk)) | ||
| 402 | pr_warn("Unable to get rtc-tegra clock\n"); | ||
| 403 | else | ||
| 404 | clk_prepare_enable(clk); | ||
| 405 | 382 | ||
| 406 | return register_persistent_clock(tegra_read_persistent_clock64); | 383 | return 0; |
| 407 | } | 384 | } |
| 408 | TIMER_OF_DECLARE(tegra20_rtc, "nvidia,tegra20-rtc", tegra20_init_rtc); | 385 | TIMER_OF_DECLARE(tegra20_rtc, "nvidia,tegra20-rtc", tegra20_init_rtc); |
| 409 | #endif | 386 | #endif |
diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c index 3fbbb61012c4..ef93406ace1b 100644 --- a/drivers/firmware/ti_sci.c +++ b/drivers/firmware/ti_sci.c | |||
| @@ -65,18 +65,36 @@ struct ti_sci_xfers_info { | |||
| 65 | }; | 65 | }; |
| 66 | 66 | ||
| 67 | /** | 67 | /** |
| 68 | * struct ti_sci_rm_type_map - Structure representing TISCI Resource | ||
| 69 | * management representation of dev_ids. | ||
| 70 | * @dev_id: TISCI device ID | ||
| 71 | * @type: Corresponding id as identified by TISCI RM. | ||
| 72 | * | ||
| 73 | * Note: This is used only as a work around for using RM range apis | ||
| 74 | * for AM654 SoC. For future SoCs dev_id will be used as type | ||
| 75 | * for RM range APIs. In order to maintain ABI backward compatibility | ||
| 76 | * type is not being changed for AM654 SoC. | ||
| 77 | */ | ||
| 78 | struct ti_sci_rm_type_map { | ||
| 79 | u32 dev_id; | ||
| 80 | u16 type; | ||
| 81 | }; | ||
| 82 | |||
| 83 | /** | ||
| 68 | * struct ti_sci_desc - Description of SoC integration | 84 | * struct ti_sci_desc - Description of SoC integration |
| 69 | * @default_host_id: Host identifier representing the compute entity | 85 | * @default_host_id: Host identifier representing the compute entity |
| 70 | * @max_rx_timeout_ms: Timeout for communication with SoC (in Milliseconds) | 86 | * @max_rx_timeout_ms: Timeout for communication with SoC (in Milliseconds) |
| 71 | * @max_msgs: Maximum number of messages that can be pending | 87 | * @max_msgs: Maximum number of messages that can be pending |
| 72 | * simultaneously in the system | 88 | * simultaneously in the system |
| 73 | * @max_msg_size: Maximum size of data per message that can be handled. | 89 | * @max_msg_size: Maximum size of data per message that can be handled. |
| 90 | * @rm_type_map: RM resource type mapping structure. | ||
| 74 | */ | 91 | */ |
| 75 | struct ti_sci_desc { | 92 | struct ti_sci_desc { |
| 76 | u8 default_host_id; | 93 | u8 default_host_id; |
| 77 | int max_rx_timeout_ms; | 94 | int max_rx_timeout_ms; |
| 78 | int max_msgs; | 95 | int max_msgs; |
| 79 | int max_msg_size; | 96 | int max_msg_size; |
| 97 | struct ti_sci_rm_type_map *rm_type_map; | ||
| 80 | }; | 98 | }; |
| 81 | 99 | ||
| 82 | /** | 100 | /** |
| @@ -1600,6 +1618,392 @@ fail: | |||
| 1600 | return ret; | 1618 | return ret; |
| 1601 | } | 1619 | } |
| 1602 | 1620 | ||
| 1621 | static int ti_sci_get_resource_type(struct ti_sci_info *info, u16 dev_id, | ||
| 1622 | u16 *type) | ||
| 1623 | { | ||
| 1624 | struct ti_sci_rm_type_map *rm_type_map = info->desc->rm_type_map; | ||
| 1625 | bool found = false; | ||
| 1626 | int i; | ||
| 1627 | |||
| 1628 | /* If map is not provided then assume dev_id is used as type */ | ||
| 1629 | if (!rm_type_map) { | ||
| 1630 | *type = dev_id; | ||
| 1631 | return 0; | ||
| 1632 | } | ||
| 1633 | |||
| 1634 | for (i = 0; rm_type_map[i].dev_id; i++) { | ||
| 1635 | if (rm_type_map[i].dev_id == dev_id) { | ||
| 1636 | *type = rm_type_map[i].type; | ||
| 1637 | found = true; | ||
| 1638 | break; | ||
| 1639 | } | ||
| 1640 | } | ||
| 1641 | |||
| 1642 | if (!found) | ||
| 1643 | return -EINVAL; | ||
| 1644 | |||
| 1645 | return 0; | ||
| 1646 | } | ||
| 1647 | |||
| 1648 | /** | ||
| 1649 | * ti_sci_get_resource_range - Helper to get a range of resources assigned | ||
| 1650 | * to a host. Resource is uniquely identified by | ||
| 1651 | * type and subtype. | ||
| 1652 | * @handle: Pointer to TISCI handle. | ||
| 1653 | * @dev_id: TISCI device ID. | ||
| 1654 | * @subtype: Resource assignment subtype that is being requested | ||
| 1655 | * from the given device. | ||
| 1656 | * @s_host: Host processor ID to which the resources are allocated | ||
| 1657 | * @range_start: Start index of the resource range | ||
| 1658 | * @range_num: Number of resources in the range | ||
| 1659 | * | ||
| 1660 | * Return: 0 if all went fine, else return appropriate error. | ||
| 1661 | */ | ||
| 1662 | static int ti_sci_get_resource_range(const struct ti_sci_handle *handle, | ||
| 1663 | u32 dev_id, u8 subtype, u8 s_host, | ||
| 1664 | u16 *range_start, u16 *range_num) | ||
| 1665 | { | ||
| 1666 | struct ti_sci_msg_resp_get_resource_range *resp; | ||
| 1667 | struct ti_sci_msg_req_get_resource_range *req; | ||
| 1668 | struct ti_sci_xfer *xfer; | ||
| 1669 | struct ti_sci_info *info; | ||
| 1670 | struct device *dev; | ||
| 1671 | u16 type; | ||
| 1672 | int ret = 0; | ||
| 1673 | |||
| 1674 | if (IS_ERR(handle)) | ||
| 1675 | return PTR_ERR(handle); | ||
| 1676 | if (!handle) | ||
| 1677 | return -EINVAL; | ||
| 1678 | |||
| 1679 | info = handle_to_ti_sci_info(handle); | ||
| 1680 | dev = info->dev; | ||
| 1681 | |||
| 1682 | xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_GET_RESOURCE_RANGE, | ||
| 1683 | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, | ||
| 1684 | sizeof(*req), sizeof(*resp)); | ||
| 1685 | if (IS_ERR(xfer)) { | ||
| 1686 | ret = PTR_ERR(xfer); | ||
| 1687 | dev_err(dev, "Message alloc failed(%d)\n", ret); | ||
| 1688 | return ret; | ||
| 1689 | } | ||
| 1690 | |||
| 1691 | ret = ti_sci_get_resource_type(info, dev_id, &type); | ||
| 1692 | if (ret) { | ||
| 1693 | dev_err(dev, "rm type lookup failed for %u\n", dev_id); | ||
| 1694 | goto fail; | ||
| 1695 | } | ||
| 1696 | |||
| 1697 | req = (struct ti_sci_msg_req_get_resource_range *)xfer->xfer_buf; | ||
| 1698 | req->secondary_host = s_host; | ||
| 1699 | req->type = type & MSG_RM_RESOURCE_TYPE_MASK; | ||
| 1700 | req->subtype = subtype & MSG_RM_RESOURCE_SUBTYPE_MASK; | ||
| 1701 | |||
| 1702 | ret = ti_sci_do_xfer(info, xfer); | ||
| 1703 | if (ret) { | ||
| 1704 | dev_err(dev, "Mbox send fail %d\n", ret); | ||
| 1705 | goto fail; | ||
| 1706 | } | ||
| 1707 | |||
| 1708 | resp = (struct ti_sci_msg_resp_get_resource_range *)xfer->xfer_buf; | ||
| 1709 | |||
| 1710 | if (!ti_sci_is_response_ack(resp)) { | ||
| 1711 | ret = -ENODEV; | ||
| 1712 | } else if (!resp->range_start && !resp->range_num) { | ||
| 1713 | ret = -ENODEV; | ||
| 1714 | } else { | ||
| 1715 | *range_start = resp->range_start; | ||
| 1716 | *range_num = resp->range_num; | ||
| 1717 | }; | ||
| 1718 | |||
| 1719 | fail: | ||
| 1720 | ti_sci_put_one_xfer(&info->minfo, xfer); | ||
| 1721 | |||
| 1722 | return ret; | ||
| 1723 | } | ||
| 1724 | |||
| 1725 | /** | ||
| 1726 | * ti_sci_cmd_get_resource_range - Get a range of resources assigned to host | ||
| 1727 | * that is same as ti sci interface host. | ||
| 1728 | * @handle: Pointer to TISCI handle. | ||
| 1729 | * @dev_id: TISCI device ID. | ||
| 1730 | * @subtype: Resource assignment subtype that is being requested | ||
| 1731 | * from the given device. | ||
| 1732 | * @range_start: Start index of the resource range | ||
| 1733 | * @range_num: Number of resources in the range | ||
| 1734 | * | ||
| 1735 | * Return: 0 if all went fine, else return appropriate error. | ||
| 1736 | */ | ||
| 1737 | static int ti_sci_cmd_get_resource_range(const struct ti_sci_handle *handle, | ||
| 1738 | u32 dev_id, u8 subtype, | ||
| 1739 | u16 *range_start, u16 *range_num) | ||
| 1740 | { | ||
| 1741 | return ti_sci_get_resource_range(handle, dev_id, subtype, | ||
| 1742 | TI_SCI_IRQ_SECONDARY_HOST_INVALID, | ||
| 1743 | range_start, range_num); | ||
| 1744 | } | ||
| 1745 | |||
| 1746 | /** | ||
| 1747 | * ti_sci_cmd_get_resource_range_from_shost - Get a range of resources | ||
| 1748 | * assigned to a specified host. | ||
| 1749 | * @handle: Pointer to TISCI handle. | ||
| 1750 | * @dev_id: TISCI device ID. | ||
| 1751 | * @subtype: Resource assignment subtype that is being requested | ||
| 1752 | * from the given device. | ||
| 1753 | * @s_host: Host processor ID to which the resources are allocated | ||
| 1754 | * @range_start: Start index of the resource range | ||
| 1755 | * @range_num: Number of resources in the range | ||
| 1756 | * | ||
| 1757 | * Return: 0 if all went fine, else return appropriate error. | ||
| 1758 | */ | ||
| 1759 | static | ||
| 1760 | int ti_sci_cmd_get_resource_range_from_shost(const struct ti_sci_handle *handle, | ||
| 1761 | u32 dev_id, u8 subtype, u8 s_host, | ||
| 1762 | u16 *range_start, u16 *range_num) | ||
| 1763 | { | ||
| 1764 | return ti_sci_get_resource_range(handle, dev_id, subtype, s_host, | ||
| 1765 | range_start, range_num); | ||
| 1766 | } | ||
| 1767 | |||
| 1768 | /** | ||
| 1769 | * ti_sci_manage_irq() - Helper api to configure/release the irq route between | ||
| 1770 | * the requested source and destination | ||
| 1771 | * @handle: Pointer to TISCI handle. | ||
| 1772 | * @valid_params: Bit fields defining the validity of certain params | ||
| 1773 | * @src_id: Device ID of the IRQ source | ||
| 1774 | * @src_index: IRQ source index within the source device | ||
| 1775 | * @dst_id: Device ID of the IRQ destination | ||
| 1776 | * @dst_host_irq: IRQ number of the destination device | ||
| 1777 | * @ia_id: Device ID of the IA, if the IRQ flows through this IA | ||
| 1778 | * @vint: Virtual interrupt to be used within the IA | ||
| 1779 | * @global_event: Global event number to be used for the requesting event | ||
| 1780 | * @vint_status_bit: Virtual interrupt status bit to be used for the event | ||
| 1781 | * @s_host: Secondary host ID to which the irq/event is being | ||
| 1782 | * requested for. | ||
| 1783 | * @type: Request type irq set or release. | ||
| 1784 | * | ||
| 1785 | * Return: 0 if all went fine, else return appropriate error. | ||
| 1786 | */ | ||
| 1787 | static int ti_sci_manage_irq(const struct ti_sci_handle *handle, | ||
| 1788 | u32 valid_params, u16 src_id, u16 src_index, | ||
| 1789 | u16 dst_id, u16 dst_host_irq, u16 ia_id, u16 vint, | ||
| 1790 | u16 global_event, u8 vint_status_bit, u8 s_host, | ||
| 1791 | u16 type) | ||
| 1792 | { | ||
| 1793 | struct ti_sci_msg_req_manage_irq *req; | ||
| 1794 | struct ti_sci_msg_hdr *resp; | ||
| 1795 | struct ti_sci_xfer *xfer; | ||
| 1796 | struct ti_sci_info *info; | ||
| 1797 | struct device *dev; | ||
| 1798 | int ret = 0; | ||
| 1799 | |||
| 1800 | if (IS_ERR(handle)) | ||
| 1801 | return PTR_ERR(handle); | ||
| 1802 | if (!handle) | ||
| 1803 | return -EINVAL; | ||
| 1804 | |||
| 1805 | info = handle_to_ti_sci_info(handle); | ||
| 1806 | dev = info->dev; | ||
| 1807 | |||
| 1808 | xfer = ti_sci_get_one_xfer(info, type, TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, | ||
| 1809 | sizeof(*req), sizeof(*resp)); | ||
| 1810 | if (IS_ERR(xfer)) { | ||
| 1811 | ret = PTR_ERR(xfer); | ||
| 1812 | dev_err(dev, "Message alloc failed(%d)\n", ret); | ||
| 1813 | return ret; | ||
| 1814 | } | ||
| 1815 | req = (struct ti_sci_msg_req_manage_irq *)xfer->xfer_buf; | ||
| 1816 | req->valid_params = valid_params; | ||
| 1817 | req->src_id = src_id; | ||
| 1818 | req->src_index = src_index; | ||
| 1819 | req->dst_id = dst_id; | ||
| 1820 | req->dst_host_irq = dst_host_irq; | ||
| 1821 | req->ia_id = ia_id; | ||
| 1822 | req->vint = vint; | ||
| 1823 | req->global_event = global_event; | ||
| 1824 | req->vint_status_bit = vint_status_bit; | ||
| 1825 | req->secondary_host = s_host; | ||
| 1826 | |||
| 1827 | ret = ti_sci_do_xfer(info, xfer); | ||
| 1828 | if (ret) { | ||
| 1829 | dev_err(dev, "Mbox send fail %d\n", ret); | ||
| 1830 | goto fail; | ||
| 1831 | } | ||
| 1832 | |||
| 1833 | resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf; | ||
| 1834 | |||
| 1835 | ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV; | ||
| 1836 | |||
| 1837 | fail: | ||
| 1838 | ti_sci_put_one_xfer(&info->minfo, xfer); | ||
| 1839 | |||
| 1840 | return ret; | ||
| 1841 | } | ||
| 1842 | |||
| 1843 | /** | ||
| 1844 | * ti_sci_set_irq() - Helper api to configure the irq route between the | ||
| 1845 | * requested source and destination | ||
| 1846 | * @handle: Pointer to TISCI handle. | ||
| 1847 | * @valid_params: Bit fields defining the validity of certain params | ||
| 1848 | * @src_id: Device ID of the IRQ source | ||
| 1849 | * @src_index: IRQ source index within the source device | ||
| 1850 | * @dst_id: Device ID of the IRQ destination | ||
| 1851 | * @dst_host_irq: IRQ number of the destination device | ||
| 1852 | * @ia_id: Device ID of the IA, if the IRQ flows through this IA | ||
| 1853 | * @vint: Virtual interrupt to be used within the IA | ||
| 1854 | * @global_event: Global event number to be used for the requesting event | ||
| 1855 | * @vint_status_bit: Virtual interrupt status bit to be used for the event | ||
| 1856 | * @s_host: Secondary host ID to which the irq/event is being | ||
| 1857 | * requested for. | ||
| 1858 | * | ||
| 1859 | * Return: 0 if all went fine, else return appropriate error. | ||
| 1860 | */ | ||
| 1861 | static int ti_sci_set_irq(const struct ti_sci_handle *handle, u32 valid_params, | ||
| 1862 | u16 src_id, u16 src_index, u16 dst_id, | ||
| 1863 | u16 dst_host_irq, u16 ia_id, u16 vint, | ||
| 1864 | u16 global_event, u8 vint_status_bit, u8 s_host) | ||
| 1865 | { | ||
| 1866 | pr_debug("%s: IRQ set with valid_params = 0x%x from src = %d, index = %d, to dst = %d, irq = %d,via ia_id = %d, vint = %d, global event = %d,status_bit = %d\n", | ||
| 1867 | __func__, valid_params, src_id, src_index, | ||
| 1868 | dst_id, dst_host_irq, ia_id, vint, global_event, | ||
| 1869 | vint_status_bit); | ||
| 1870 | |||
| 1871 | return ti_sci_manage_irq(handle, valid_params, src_id, src_index, | ||
| 1872 | dst_id, dst_host_irq, ia_id, vint, | ||
| 1873 | global_event, vint_status_bit, s_host, | ||
| 1874 | TI_SCI_MSG_SET_IRQ); | ||
| 1875 | } | ||
| 1876 | |||
| 1877 | /** | ||
| 1878 | * ti_sci_free_irq() - Helper api to free the irq route between the | ||
| 1879 | * requested source and destination | ||
| 1880 | * @handle: Pointer to TISCI handle. | ||
| 1881 | * @valid_params: Bit fields defining the validity of certain params | ||
| 1882 | * @src_id: Device ID of the IRQ source | ||
| 1883 | * @src_index: IRQ source index within the source device | ||
| 1884 | * @dst_id: Device ID of the IRQ destination | ||
| 1885 | * @dst_host_irq: IRQ number of the destination device | ||
| 1886 | * @ia_id: Device ID of the IA, if the IRQ flows through this IA | ||
| 1887 | * @vint: Virtual interrupt to be used within the IA | ||
| 1888 | * @global_event: Global event number to be used for the requesting event | ||
| 1889 | * @vint_status_bit: Virtual interrupt status bit to be used for the event | ||
| 1890 | * @s_host: Secondary host ID to which the irq/event is being | ||
| 1891 | * requested for. | ||
| 1892 | * | ||
| 1893 | * Return: 0 if all went fine, else return appropriate error. | ||
| 1894 | */ | ||
| 1895 | static int ti_sci_free_irq(const struct ti_sci_handle *handle, u32 valid_params, | ||
| 1896 | u16 src_id, u16 src_index, u16 dst_id, | ||
| 1897 | u16 dst_host_irq, u16 ia_id, u16 vint, | ||
| 1898 | u16 global_event, u8 vint_status_bit, u8 s_host) | ||
| 1899 | { | ||
| 1900 | pr_debug("%s: IRQ release with valid_params = 0x%x from src = %d, index = %d, to dst = %d, irq = %d,via ia_id = %d, vint = %d, global event = %d,status_bit = %d\n", | ||
| 1901 | __func__, valid_params, src_id, src_index, | ||
| 1902 | dst_id, dst_host_irq, ia_id, vint, global_event, | ||
| 1903 | vint_status_bit); | ||
| 1904 | |||
| 1905 | return ti_sci_manage_irq(handle, valid_params, src_id, src_index, | ||
| 1906 | dst_id, dst_host_irq, ia_id, vint, | ||
| 1907 | global_event, vint_status_bit, s_host, | ||
| 1908 | TI_SCI_MSG_FREE_IRQ); | ||
| 1909 | } | ||
| 1910 | |||
| 1911 | /** | ||
| 1912 | * ti_sci_cmd_set_irq() - Configure a host irq route between the requested | ||
| 1913 | * source and destination. | ||
| 1914 | * @handle: Pointer to TISCI handle. | ||
| 1915 | * @src_id: Device ID of the IRQ source | ||
| 1916 | * @src_index: IRQ source index within the source device | ||
| 1917 | * @dst_id: Device ID of the IRQ destination | ||
| 1918 | * @dst_host_irq: IRQ number of the destination device | ||
| 1919 | * @vint_irq: Boolean specifying if this interrupt belongs to | ||
| 1920 | * Interrupt Aggregator. | ||
| 1921 | * | ||
| 1922 | * Return: 0 if all went fine, else return appropriate error. | ||
| 1923 | */ | ||
| 1924 | static int ti_sci_cmd_set_irq(const struct ti_sci_handle *handle, u16 src_id, | ||
| 1925 | u16 src_index, u16 dst_id, u16 dst_host_irq) | ||
| 1926 | { | ||
| 1927 | u32 valid_params = MSG_FLAG_DST_ID_VALID | MSG_FLAG_DST_HOST_IRQ_VALID; | ||
| 1928 | |||
| 1929 | return ti_sci_set_irq(handle, valid_params, src_id, src_index, dst_id, | ||
| 1930 | dst_host_irq, 0, 0, 0, 0, 0); | ||
| 1931 | } | ||
| 1932 | |||
| 1933 | /** | ||
| 1934 | * ti_sci_cmd_set_event_map() - Configure an event based irq route between the | ||
| 1935 | * requested source and Interrupt Aggregator. | ||
| 1936 | * @handle: Pointer to TISCI handle. | ||
| 1937 | * @src_id: Device ID of the IRQ source | ||
| 1938 | * @src_index: IRQ source index within the source device | ||
| 1939 | * @ia_id: Device ID of the IA, if the IRQ flows through this IA | ||
| 1940 | * @vint: Virtual interrupt to be used within the IA | ||
| 1941 | * @global_event: Global event number to be used for the requesting event | ||
| 1942 | * @vint_status_bit: Virtual interrupt status bit to be used for the event | ||
| 1943 | * | ||
| 1944 | * Return: 0 if all went fine, else return appropriate error. | ||
| 1945 | */ | ||
| 1946 | static int ti_sci_cmd_set_event_map(const struct ti_sci_handle *handle, | ||
| 1947 | u16 src_id, u16 src_index, u16 ia_id, | ||
| 1948 | u16 vint, u16 global_event, | ||
| 1949 | u8 vint_status_bit) | ||
| 1950 | { | ||
| 1951 | u32 valid_params = MSG_FLAG_IA_ID_VALID | MSG_FLAG_VINT_VALID | | ||
| 1952 | MSG_FLAG_GLB_EVNT_VALID | | ||
| 1953 | MSG_FLAG_VINT_STS_BIT_VALID; | ||
| 1954 | |||
| 1955 | return ti_sci_set_irq(handle, valid_params, src_id, src_index, 0, 0, | ||
| 1956 | ia_id, vint, global_event, vint_status_bit, 0); | ||
| 1957 | } | ||
| 1958 | |||
| 1959 | /** | ||
| 1960 | * ti_sci_cmd_free_irq() - Free a host irq route between the between the | ||
| 1961 | * requested source and destination. | ||
| 1962 | * @handle: Pointer to TISCI handle. | ||
| 1963 | * @src_id: Device ID of the IRQ source | ||
| 1964 | * @src_index: IRQ source index within the source device | ||
| 1965 | * @dst_id: Device ID of the IRQ destination | ||
| 1966 | * @dst_host_irq: IRQ number of the destination device | ||
| 1967 | * @vint_irq: Boolean specifying if this interrupt belongs to | ||
| 1968 | * Interrupt Aggregator. | ||
| 1969 | * | ||
| 1970 | * Return: 0 if all went fine, else return appropriate error. | ||
| 1971 | */ | ||
| 1972 | static int ti_sci_cmd_free_irq(const struct ti_sci_handle *handle, u16 src_id, | ||
| 1973 | u16 src_index, u16 dst_id, u16 dst_host_irq) | ||
| 1974 | { | ||
| 1975 | u32 valid_params = MSG_FLAG_DST_ID_VALID | MSG_FLAG_DST_HOST_IRQ_VALID; | ||
| 1976 | |||
| 1977 | return ti_sci_free_irq(handle, valid_params, src_id, src_index, dst_id, | ||
| 1978 | dst_host_irq, 0, 0, 0, 0, 0); | ||
| 1979 | } | ||
| 1980 | |||
| 1981 | /** | ||
| 1982 | * ti_sci_cmd_free_event_map() - Free an event map between the requested source | ||
| 1983 | * and Interrupt Aggregator. | ||
| 1984 | * @handle: Pointer to TISCI handle. | ||
| 1985 | * @src_id: Device ID of the IRQ source | ||
| 1986 | * @src_index: IRQ source index within the source device | ||
| 1987 | * @ia_id: Device ID of the IA, if the IRQ flows through this IA | ||
| 1988 | * @vint: Virtual interrupt to be used within the IA | ||
| 1989 | * @global_event: Global event number to be used for the requesting event | ||
| 1990 | * @vint_status_bit: Virtual interrupt status bit to be used for the event | ||
| 1991 | * | ||
| 1992 | * Return: 0 if all went fine, else return appropriate error. | ||
| 1993 | */ | ||
| 1994 | static int ti_sci_cmd_free_event_map(const struct ti_sci_handle *handle, | ||
| 1995 | u16 src_id, u16 src_index, u16 ia_id, | ||
| 1996 | u16 vint, u16 global_event, | ||
| 1997 | u8 vint_status_bit) | ||
| 1998 | { | ||
| 1999 | u32 valid_params = MSG_FLAG_IA_ID_VALID | | ||
| 2000 | MSG_FLAG_VINT_VALID | MSG_FLAG_GLB_EVNT_VALID | | ||
| 2001 | MSG_FLAG_VINT_STS_BIT_VALID; | ||
| 2002 | |||
| 2003 | return ti_sci_free_irq(handle, valid_params, src_id, src_index, 0, 0, | ||
| 2004 | ia_id, vint, global_event, vint_status_bit, 0); | ||
| 2005 | } | ||
| 2006 | |||
| 1603 | /* | 2007 | /* |
| 1604 | * ti_sci_setup_ops() - Setup the operations structures | 2008 | * ti_sci_setup_ops() - Setup the operations structures |
| 1605 | * @info: pointer to TISCI pointer | 2009 | * @info: pointer to TISCI pointer |
| @@ -1610,6 +2014,8 @@ static void ti_sci_setup_ops(struct ti_sci_info *info) | |||
| 1610 | struct ti_sci_core_ops *core_ops = &ops->core_ops; | 2014 | struct ti_sci_core_ops *core_ops = &ops->core_ops; |
| 1611 | struct ti_sci_dev_ops *dops = &ops->dev_ops; | 2015 | struct ti_sci_dev_ops *dops = &ops->dev_ops; |
| 1612 | struct ti_sci_clk_ops *cops = &ops->clk_ops; | 2016 | struct ti_sci_clk_ops *cops = &ops->clk_ops; |
| 2017 | struct ti_sci_rm_core_ops *rm_core_ops = &ops->rm_core_ops; | ||
| 2018 | struct ti_sci_rm_irq_ops *iops = &ops->rm_irq_ops; | ||
| 1613 | 2019 | ||
| 1614 | core_ops->reboot_device = ti_sci_cmd_core_reboot; | 2020 | core_ops->reboot_device = ti_sci_cmd_core_reboot; |
| 1615 | 2021 | ||
| @@ -1640,6 +2046,15 @@ static void ti_sci_setup_ops(struct ti_sci_info *info) | |||
| 1640 | cops->get_best_match_freq = ti_sci_cmd_clk_get_match_freq; | 2046 | cops->get_best_match_freq = ti_sci_cmd_clk_get_match_freq; |
| 1641 | cops->set_freq = ti_sci_cmd_clk_set_freq; | 2047 | cops->set_freq = ti_sci_cmd_clk_set_freq; |
| 1642 | cops->get_freq = ti_sci_cmd_clk_get_freq; | 2048 | cops->get_freq = ti_sci_cmd_clk_get_freq; |
| 2049 | |||
| 2050 | rm_core_ops->get_range = ti_sci_cmd_get_resource_range; | ||
| 2051 | rm_core_ops->get_range_from_shost = | ||
| 2052 | ti_sci_cmd_get_resource_range_from_shost; | ||
| 2053 | |||
| 2054 | iops->set_irq = ti_sci_cmd_set_irq; | ||
| 2055 | iops->set_event_map = ti_sci_cmd_set_event_map; | ||
| 2056 | iops->free_irq = ti_sci_cmd_free_irq; | ||
| 2057 | iops->free_event_map = ti_sci_cmd_free_event_map; | ||
| 1643 | } | 2058 | } |
| 1644 | 2059 | ||
| 1645 | /** | 2060 | /** |
| @@ -1764,6 +2179,219 @@ const struct ti_sci_handle *devm_ti_sci_get_handle(struct device *dev) | |||
| 1764 | } | 2179 | } |
| 1765 | EXPORT_SYMBOL_GPL(devm_ti_sci_get_handle); | 2180 | EXPORT_SYMBOL_GPL(devm_ti_sci_get_handle); |
| 1766 | 2181 | ||
| 2182 | /** | ||
| 2183 | * ti_sci_get_by_phandle() - Get the TI SCI handle using DT phandle | ||
| 2184 | * @np: device node | ||
| 2185 | * @property: property name containing phandle on TISCI node | ||
| 2186 | * | ||
| 2187 | * NOTE: The function does not track individual clients of the framework | ||
| 2188 | * and is expected to be maintained by caller of TI SCI protocol library. | ||
| 2189 | * ti_sci_put_handle must be balanced with successful ti_sci_get_by_phandle | ||
| 2190 | * Return: pointer to handle if successful, else: | ||
| 2191 | * -EPROBE_DEFER if the instance is not ready | ||
| 2192 | * -ENODEV if the required node handler is missing | ||
| 2193 | * -EINVAL if invalid conditions are encountered. | ||
| 2194 | */ | ||
| 2195 | const struct ti_sci_handle *ti_sci_get_by_phandle(struct device_node *np, | ||
| 2196 | const char *property) | ||
| 2197 | { | ||
| 2198 | struct ti_sci_handle *handle = NULL; | ||
| 2199 | struct device_node *ti_sci_np; | ||
| 2200 | struct ti_sci_info *info; | ||
| 2201 | struct list_head *p; | ||
| 2202 | |||
| 2203 | if (!np) { | ||
| 2204 | pr_err("I need a device pointer\n"); | ||
| 2205 | return ERR_PTR(-EINVAL); | ||
| 2206 | } | ||
| 2207 | |||
| 2208 | ti_sci_np = of_parse_phandle(np, property, 0); | ||
| 2209 | if (!ti_sci_np) | ||
| 2210 | return ERR_PTR(-ENODEV); | ||
| 2211 | |||
| 2212 | mutex_lock(&ti_sci_list_mutex); | ||
| 2213 | list_for_each(p, &ti_sci_list) { | ||
| 2214 | info = list_entry(p, struct ti_sci_info, node); | ||
| 2215 | if (ti_sci_np == info->dev->of_node) { | ||
| 2216 | handle = &info->handle; | ||
| 2217 | info->users++; | ||
| 2218 | break; | ||
| 2219 | } | ||
| 2220 | } | ||
| 2221 | mutex_unlock(&ti_sci_list_mutex); | ||
| 2222 | of_node_put(ti_sci_np); | ||
| 2223 | |||
| 2224 | if (!handle) | ||
| 2225 | return ERR_PTR(-EPROBE_DEFER); | ||
| 2226 | |||
| 2227 | return handle; | ||
| 2228 | } | ||
| 2229 | EXPORT_SYMBOL_GPL(ti_sci_get_by_phandle); | ||
| 2230 | |||
| 2231 | /** | ||
| 2232 | * devm_ti_sci_get_by_phandle() - Managed get handle using phandle | ||
| 2233 | * @dev: Device pointer requesting TISCI handle | ||
| 2234 | * @property: property name containing phandle on TISCI node | ||
| 2235 | * | ||
| 2236 | * NOTE: This releases the handle once the device resources are | ||
| 2237 | * no longer needed. MUST NOT BE released with ti_sci_put_handle. | ||
| 2238 | * The function does not track individual clients of the framework | ||
| 2239 | * and is expected to be maintained by caller of TI SCI protocol library. | ||
| 2240 | * | ||
| 2241 | * Return: 0 if all went fine, else corresponding error. | ||
| 2242 | */ | ||
| 2243 | const struct ti_sci_handle *devm_ti_sci_get_by_phandle(struct device *dev, | ||
| 2244 | const char *property) | ||
| 2245 | { | ||
| 2246 | const struct ti_sci_handle *handle; | ||
| 2247 | const struct ti_sci_handle **ptr; | ||
| 2248 | |||
| 2249 | ptr = devres_alloc(devm_ti_sci_release, sizeof(*ptr), GFP_KERNEL); | ||
| 2250 | if (!ptr) | ||
| 2251 | return ERR_PTR(-ENOMEM); | ||
| 2252 | handle = ti_sci_get_by_phandle(dev_of_node(dev), property); | ||
| 2253 | |||
| 2254 | if (!IS_ERR(handle)) { | ||
| 2255 | *ptr = handle; | ||
| 2256 | devres_add(dev, ptr); | ||
| 2257 | } else { | ||
| 2258 | devres_free(ptr); | ||
| 2259 | } | ||
| 2260 | |||
| 2261 | return handle; | ||
| 2262 | } | ||
| 2263 | EXPORT_SYMBOL_GPL(devm_ti_sci_get_by_phandle); | ||
| 2264 | |||
| 2265 | /** | ||
| 2266 | * ti_sci_get_free_resource() - Get a free resource from TISCI resource. | ||
| 2267 | * @res: Pointer to the TISCI resource | ||
| 2268 | * | ||
| 2269 | * Return: resource num if all went ok else TI_SCI_RESOURCE_NULL. | ||
| 2270 | */ | ||
| 2271 | u16 ti_sci_get_free_resource(struct ti_sci_resource *res) | ||
| 2272 | { | ||
| 2273 | unsigned long flags; | ||
| 2274 | u16 set, free_bit; | ||
| 2275 | |||
| 2276 | raw_spin_lock_irqsave(&res->lock, flags); | ||
| 2277 | for (set = 0; set < res->sets; set++) { | ||
| 2278 | free_bit = find_first_zero_bit(res->desc[set].res_map, | ||
| 2279 | res->desc[set].num); | ||
| 2280 | if (free_bit != res->desc[set].num) { | ||
| 2281 | set_bit(free_bit, res->desc[set].res_map); | ||
| 2282 | raw_spin_unlock_irqrestore(&res->lock, flags); | ||
| 2283 | return res->desc[set].start + free_bit; | ||
| 2284 | } | ||
| 2285 | } | ||
| 2286 | raw_spin_unlock_irqrestore(&res->lock, flags); | ||
| 2287 | |||
| 2288 | return TI_SCI_RESOURCE_NULL; | ||
| 2289 | } | ||
| 2290 | EXPORT_SYMBOL_GPL(ti_sci_get_free_resource); | ||
| 2291 | |||
| 2292 | /** | ||
| 2293 | * ti_sci_release_resource() - Release a resource from TISCI resource. | ||
| 2294 | * @res: Pointer to the TISCI resource | ||
| 2295 | * @id: Resource id to be released. | ||
| 2296 | */ | ||
| 2297 | void ti_sci_release_resource(struct ti_sci_resource *res, u16 id) | ||
| 2298 | { | ||
| 2299 | unsigned long flags; | ||
| 2300 | u16 set; | ||
| 2301 | |||
| 2302 | raw_spin_lock_irqsave(&res->lock, flags); | ||
| 2303 | for (set = 0; set < res->sets; set++) { | ||
| 2304 | if (res->desc[set].start <= id && | ||
| 2305 | (res->desc[set].num + res->desc[set].start) > id) | ||
| 2306 | clear_bit(id - res->desc[set].start, | ||
| 2307 | res->desc[set].res_map); | ||
| 2308 | } | ||
| 2309 | raw_spin_unlock_irqrestore(&res->lock, flags); | ||
| 2310 | } | ||
| 2311 | EXPORT_SYMBOL_GPL(ti_sci_release_resource); | ||
| 2312 | |||
| 2313 | /** | ||
| 2314 | * ti_sci_get_num_resources() - Get the number of resources in TISCI resource | ||
| 2315 | * @res: Pointer to the TISCI resource | ||
| 2316 | * | ||
| 2317 | * Return: Total number of available resources. | ||
| 2318 | */ | ||
| 2319 | u32 ti_sci_get_num_resources(struct ti_sci_resource *res) | ||
| 2320 | { | ||
| 2321 | u32 set, count = 0; | ||
| 2322 | |||
| 2323 | for (set = 0; set < res->sets; set++) | ||
| 2324 | count += res->desc[set].num; | ||
| 2325 | |||
| 2326 | return count; | ||
| 2327 | } | ||
| 2328 | EXPORT_SYMBOL_GPL(ti_sci_get_num_resources); | ||
| 2329 | |||
| 2330 | /** | ||
| 2331 | * devm_ti_sci_get_of_resource() - Get a TISCI resource assigned to a device | ||
| 2332 | * @handle: TISCI handle | ||
| 2333 | * @dev: Device pointer to which the resource is assigned | ||
| 2334 | * @dev_id: TISCI device id to which the resource is assigned | ||
| 2335 | * @of_prop: property name by which the resource are represented | ||
| 2336 | * | ||
| 2337 | * Return: Pointer to ti_sci_resource if all went well else appropriate | ||
| 2338 | * error pointer. | ||
| 2339 | */ | ||
| 2340 | struct ti_sci_resource * | ||
| 2341 | devm_ti_sci_get_of_resource(const struct ti_sci_handle *handle, | ||
| 2342 | struct device *dev, u32 dev_id, char *of_prop) | ||
| 2343 | { | ||
| 2344 | struct ti_sci_resource *res; | ||
| 2345 | u32 resource_subtype; | ||
| 2346 | int i, ret; | ||
| 2347 | |||
| 2348 | res = devm_kzalloc(dev, sizeof(*res), GFP_KERNEL); | ||
| 2349 | if (!res) | ||
| 2350 | return ERR_PTR(-ENOMEM); | ||
| 2351 | |||
| 2352 | res->sets = of_property_count_elems_of_size(dev_of_node(dev), of_prop, | ||
| 2353 | sizeof(u32)); | ||
| 2354 | if (res->sets < 0) { | ||
| 2355 | dev_err(dev, "%s resource type ids not available\n", of_prop); | ||
| 2356 | return ERR_PTR(res->sets); | ||
| 2357 | } | ||
| 2358 | |||
| 2359 | res->desc = devm_kcalloc(dev, res->sets, sizeof(*res->desc), | ||
| 2360 | GFP_KERNEL); | ||
| 2361 | if (!res->desc) | ||
| 2362 | return ERR_PTR(-ENOMEM); | ||
| 2363 | |||
| 2364 | for (i = 0; i < res->sets; i++) { | ||
| 2365 | ret = of_property_read_u32_index(dev_of_node(dev), of_prop, i, | ||
| 2366 | &resource_subtype); | ||
| 2367 | if (ret) | ||
| 2368 | return ERR_PTR(-EINVAL); | ||
| 2369 | |||
| 2370 | ret = handle->ops.rm_core_ops.get_range(handle, dev_id, | ||
| 2371 | resource_subtype, | ||
| 2372 | &res->desc[i].start, | ||
| 2373 | &res->desc[i].num); | ||
| 2374 | if (ret) { | ||
| 2375 | dev_err(dev, "dev = %d subtype %d not allocated for this host\n", | ||
| 2376 | dev_id, resource_subtype); | ||
| 2377 | return ERR_PTR(ret); | ||
| 2378 | } | ||
| 2379 | |||
| 2380 | dev_dbg(dev, "dev = %d, subtype = %d, start = %d, num = %d\n", | ||
| 2381 | dev_id, resource_subtype, res->desc[i].start, | ||
| 2382 | res->desc[i].num); | ||
| 2383 | |||
| 2384 | res->desc[i].res_map = | ||
| 2385 | devm_kzalloc(dev, BITS_TO_LONGS(res->desc[i].num) * | ||
| 2386 | sizeof(*res->desc[i].res_map), GFP_KERNEL); | ||
| 2387 | if (!res->desc[i].res_map) | ||
| 2388 | return ERR_PTR(-ENOMEM); | ||
| 2389 | } | ||
| 2390 | raw_spin_lock_init(&res->lock); | ||
| 2391 | |||
| 2392 | return res; | ||
| 2393 | } | ||
| 2394 | |||
| 1767 | static int tisci_reboot_handler(struct notifier_block *nb, unsigned long mode, | 2395 | static int tisci_reboot_handler(struct notifier_block *nb, unsigned long mode, |
| 1768 | void *cmd) | 2396 | void *cmd) |
| 1769 | { | 2397 | { |
| @@ -1784,10 +2412,33 @@ static const struct ti_sci_desc ti_sci_pmmc_k2g_desc = { | |||
| 1784 | /* Limited by MBOX_TX_QUEUE_LEN. K2G can handle upto 128 messages! */ | 2412 | /* Limited by MBOX_TX_QUEUE_LEN. K2G can handle upto 128 messages! */ |
| 1785 | .max_msgs = 20, | 2413 | .max_msgs = 20, |
| 1786 | .max_msg_size = 64, | 2414 | .max_msg_size = 64, |
| 2415 | .rm_type_map = NULL, | ||
| 2416 | }; | ||
| 2417 | |||
| 2418 | static struct ti_sci_rm_type_map ti_sci_am654_rm_type_map[] = { | ||
| 2419 | {.dev_id = 56, .type = 0x00b}, /* GIC_IRQ */ | ||
| 2420 | {.dev_id = 179, .type = 0x000}, /* MAIN_NAV_UDMASS_IA0 */ | ||
| 2421 | {.dev_id = 187, .type = 0x009}, /* MAIN_NAV_RA */ | ||
| 2422 | {.dev_id = 188, .type = 0x006}, /* MAIN_NAV_UDMAP */ | ||
| 2423 | {.dev_id = 194, .type = 0x007}, /* MCU_NAV_UDMAP */ | ||
| 2424 | {.dev_id = 195, .type = 0x00a}, /* MCU_NAV_RA */ | ||
| 2425 | {.dev_id = 0, .type = 0x000}, /* end of table */ | ||
| 2426 | }; | ||
| 2427 | |||
| 2428 | /* Description for AM654 */ | ||
| 2429 | static const struct ti_sci_desc ti_sci_pmmc_am654_desc = { | ||
| 2430 | .default_host_id = 12, | ||
| 2431 | /* Conservative duration */ | ||
| 2432 | .max_rx_timeout_ms = 10000, | ||
| 2433 | /* Limited by MBOX_TX_QUEUE_LEN. K2G can handle upto 128 messages! */ | ||
| 2434 | .max_msgs = 20, | ||
| 2435 | .max_msg_size = 60, | ||
| 2436 | .rm_type_map = ti_sci_am654_rm_type_map, | ||
| 1787 | }; | 2437 | }; |
| 1788 | 2438 | ||
| 1789 | static const struct of_device_id ti_sci_of_match[] = { | 2439 | static const struct of_device_id ti_sci_of_match[] = { |
| 1790 | {.compatible = "ti,k2g-sci", .data = &ti_sci_pmmc_k2g_desc}, | 2440 | {.compatible = "ti,k2g-sci", .data = &ti_sci_pmmc_k2g_desc}, |
| 2441 | {.compatible = "ti,am654-sci", .data = &ti_sci_pmmc_am654_desc}, | ||
| 1791 | { /* Sentinel */ }, | 2442 | { /* Sentinel */ }, |
| 1792 | }; | 2443 | }; |
| 1793 | MODULE_DEVICE_TABLE(of, ti_sci_of_match); | 2444 | MODULE_DEVICE_TABLE(of, ti_sci_of_match); |
diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h index 12bf316b68df..4983827151bf 100644 --- a/drivers/firmware/ti_sci.h +++ b/drivers/firmware/ti_sci.h | |||
| @@ -35,6 +35,13 @@ | |||
| 35 | #define TI_SCI_MSG_QUERY_CLOCK_FREQ 0x010d | 35 | #define TI_SCI_MSG_QUERY_CLOCK_FREQ 0x010d |
| 36 | #define TI_SCI_MSG_GET_CLOCK_FREQ 0x010e | 36 | #define TI_SCI_MSG_GET_CLOCK_FREQ 0x010e |
| 37 | 37 | ||
| 38 | /* Resource Management Requests */ | ||
| 39 | #define TI_SCI_MSG_GET_RESOURCE_RANGE 0x1500 | ||
| 40 | |||
| 41 | /* IRQ requests */ | ||
| 42 | #define TI_SCI_MSG_SET_IRQ 0x1000 | ||
| 43 | #define TI_SCI_MSG_FREE_IRQ 0x1001 | ||
| 44 | |||
| 38 | /** | 45 | /** |
| 39 | * struct ti_sci_msg_hdr - Generic Message Header for All messages and responses | 46 | * struct ti_sci_msg_hdr - Generic Message Header for All messages and responses |
| 40 | * @type: Type of messages: One of TI_SCI_MSG* values | 47 | * @type: Type of messages: One of TI_SCI_MSG* values |
| @@ -461,4 +468,99 @@ struct ti_sci_msg_resp_get_clock_freq { | |||
| 461 | u64 freq_hz; | 468 | u64 freq_hz; |
| 462 | } __packed; | 469 | } __packed; |
| 463 | 470 | ||
| 471 | #define TI_SCI_IRQ_SECONDARY_HOST_INVALID 0xff | ||
| 472 | |||
| 473 | /** | ||
| 474 | * struct ti_sci_msg_req_get_resource_range - Request to get a host's assigned | ||
| 475 | * range of resources. | ||
| 476 | * @hdr: Generic Header | ||
| 477 | * @type: Unique resource assignment type | ||
| 478 | * @subtype: Resource assignment subtype within the resource type. | ||
| 479 | * @secondary_host: Host processing entity to which the resources are | ||
| 480 | * allocated. This is required only when the destination | ||
| 481 | * host id id different from ti sci interface host id, | ||
| 482 | * else TI_SCI_IRQ_SECONDARY_HOST_INVALID can be passed. | ||
| 483 | * | ||
| 484 | * Request type is TI_SCI_MSG_GET_RESOURCE_RANGE. Responded with requested | ||
| 485 | * resource range which is of type TI_SCI_MSG_GET_RESOURCE_RANGE. | ||
| 486 | */ | ||
| 487 | struct ti_sci_msg_req_get_resource_range { | ||
| 488 | struct ti_sci_msg_hdr hdr; | ||
| 489 | #define MSG_RM_RESOURCE_TYPE_MASK GENMASK(9, 0) | ||
| 490 | #define MSG_RM_RESOURCE_SUBTYPE_MASK GENMASK(5, 0) | ||
| 491 | u16 type; | ||
| 492 | u8 subtype; | ||
| 493 | u8 secondary_host; | ||
| 494 | } __packed; | ||
| 495 | |||
| 496 | /** | ||
| 497 | * struct ti_sci_msg_resp_get_resource_range - Response to resource get range. | ||
| 498 | * @hdr: Generic Header | ||
| 499 | * @range_start: Start index of the resource range. | ||
| 500 | * @range_num: Number of resources in the range. | ||
| 501 | * | ||
| 502 | * Response to request TI_SCI_MSG_GET_RESOURCE_RANGE. | ||
| 503 | */ | ||
| 504 | struct ti_sci_msg_resp_get_resource_range { | ||
| 505 | struct ti_sci_msg_hdr hdr; | ||
| 506 | u16 range_start; | ||
| 507 | u16 range_num; | ||
| 508 | } __packed; | ||
| 509 | |||
| 510 | /** | ||
| 511 | * struct ti_sci_msg_req_manage_irq - Request to configure/release the route | ||
| 512 | * between the dev and the host. | ||
| 513 | * @hdr: Generic Header | ||
| 514 | * @valid_params: Bit fields defining the validity of interrupt source | ||
| 515 | * parameters. If a bit is not set, then corresponding | ||
| 516 | * field is not valid and will not be used for route set. | ||
| 517 | * Bit field definitions: | ||
| 518 | * 0 - Valid bit for @dst_id | ||
| 519 | * 1 - Valid bit for @dst_host_irq | ||
| 520 | * 2 - Valid bit for @ia_id | ||
| 521 | * 3 - Valid bit for @vint | ||
| 522 | * 4 - Valid bit for @global_event | ||
| 523 | * 5 - Valid bit for @vint_status_bit_index | ||
| 524 | * 31 - Valid bit for @secondary_host | ||
| 525 | * @src_id: IRQ source peripheral ID. | ||
| 526 | * @src_index: IRQ source index within the peripheral | ||
| 527 | * @dst_id: IRQ Destination ID. Based on the architecture it can be | ||
| 528 | * IRQ controller or host processor ID. | ||
| 529 | * @dst_host_irq: IRQ number of the destination host IRQ controller | ||
| 530 | * @ia_id: Device ID of the interrupt aggregator in which the | ||
| 531 | * vint resides. | ||
| 532 | * @vint: Virtual interrupt number if the interrupt route | ||
| 533 | * is through an interrupt aggregator. | ||
| 534 | * @global_event: Global event that is to be mapped to interrupt | ||
| 535 | * aggregator virtual interrupt status bit. | ||
| 536 | * @vint_status_bit: Virtual interrupt status bit if the interrupt route | ||
| 537 | * utilizes an interrupt aggregator status bit. | ||
| 538 | * @secondary_host: Host ID of the IRQ destination computing entity. This is | ||
| 539 | * required only when destination host id is different | ||
| 540 | * from ti sci interface host id. | ||
| 541 | * | ||
| 542 | * Request type is TI_SCI_MSG_SET/RELEASE_IRQ. | ||
| 543 | * Response is generic ACK / NACK message. | ||
| 544 | */ | ||
| 545 | struct ti_sci_msg_req_manage_irq { | ||
| 546 | struct ti_sci_msg_hdr hdr; | ||
| 547 | #define MSG_FLAG_DST_ID_VALID TI_SCI_MSG_FLAG(0) | ||
| 548 | #define MSG_FLAG_DST_HOST_IRQ_VALID TI_SCI_MSG_FLAG(1) | ||
| 549 | #define MSG_FLAG_IA_ID_VALID TI_SCI_MSG_FLAG(2) | ||
| 550 | #define MSG_FLAG_VINT_VALID TI_SCI_MSG_FLAG(3) | ||
| 551 | #define MSG_FLAG_GLB_EVNT_VALID TI_SCI_MSG_FLAG(4) | ||
| 552 | #define MSG_FLAG_VINT_STS_BIT_VALID TI_SCI_MSG_FLAG(5) | ||
| 553 | #define MSG_FLAG_SHOST_VALID TI_SCI_MSG_FLAG(31) | ||
| 554 | u32 valid_params; | ||
| 555 | u16 src_id; | ||
| 556 | u16 src_index; | ||
| 557 | u16 dst_id; | ||
| 558 | u16 dst_host_irq; | ||
| 559 | u16 ia_id; | ||
| 560 | u16 vint; | ||
| 561 | u16 global_event; | ||
| 562 | u8 vint_status_bit; | ||
| 563 | u8 secondary_host; | ||
| 564 | } __packed; | ||
| 565 | |||
| 464 | #endif /* __TI_SCI_H */ | 566 | #endif /* __TI_SCI_H */ |
diff --git a/drivers/gpio/gpio-thunderx.c b/drivers/gpio/gpio-thunderx.c index 1306722faa5a..715371b5102a 100644 --- a/drivers/gpio/gpio-thunderx.c +++ b/drivers/gpio/gpio-thunderx.c | |||
| @@ -363,22 +363,16 @@ static int thunderx_gpio_irq_request_resources(struct irq_data *data) | |||
| 363 | { | 363 | { |
| 364 | struct thunderx_line *txline = irq_data_get_irq_chip_data(data); | 364 | struct thunderx_line *txline = irq_data_get_irq_chip_data(data); |
| 365 | struct thunderx_gpio *txgpio = txline->txgpio; | 365 | struct thunderx_gpio *txgpio = txline->txgpio; |
| 366 | struct irq_data *parent_data = data->parent_data; | ||
| 367 | int r; | 366 | int r; |
| 368 | 367 | ||
| 369 | r = gpiochip_lock_as_irq(&txgpio->chip, txline->line); | 368 | r = gpiochip_lock_as_irq(&txgpio->chip, txline->line); |
| 370 | if (r) | 369 | if (r) |
| 371 | return r; | 370 | return r; |
| 372 | 371 | ||
| 373 | if (parent_data && parent_data->chip->irq_request_resources) { | 372 | r = irq_chip_request_resources_parent(data); |
| 374 | r = parent_data->chip->irq_request_resources(parent_data); | 373 | if (r) |
| 375 | if (r) | 374 | gpiochip_unlock_as_irq(&txgpio->chip, txline->line); |
| 376 | goto error; | ||
| 377 | } | ||
| 378 | 375 | ||
| 379 | return 0; | ||
| 380 | error: | ||
| 381 | gpiochip_unlock_as_irq(&txgpio->chip, txline->line); | ||
| 382 | return r; | 376 | return r; |
| 383 | } | 377 | } |
| 384 | 378 | ||
| @@ -386,10 +380,8 @@ static void thunderx_gpio_irq_release_resources(struct irq_data *data) | |||
| 386 | { | 380 | { |
| 387 | struct thunderx_line *txline = irq_data_get_irq_chip_data(data); | 381 | struct thunderx_line *txline = irq_data_get_irq_chip_data(data); |
| 388 | struct thunderx_gpio *txgpio = txline->txgpio; | 382 | struct thunderx_gpio *txgpio = txline->txgpio; |
| 389 | struct irq_data *parent_data = data->parent_data; | ||
| 390 | 383 | ||
| 391 | if (parent_data && parent_data->chip->irq_release_resources) | 384 | irq_chip_release_resources_parent(data); |
| 392 | parent_data->chip->irq_release_resources(parent_data); | ||
| 393 | 385 | ||
| 394 | gpiochip_unlock_as_irq(&txgpio->chip, txline->line); | 386 | gpiochip_unlock_as_irq(&txgpio->chip, txline->line); |
| 395 | } | 387 | } |
diff --git a/drivers/hid/intel-ish-hid/Makefile b/drivers/hid/intel-ish-hid/Makefile index 2de97e4b7740..f0a82b1c7cb9 100644 --- a/drivers/hid/intel-ish-hid/Makefile +++ b/drivers/hid/intel-ish-hid/Makefile | |||
| @@ -23,4 +23,4 @@ intel-ishtp-hid-objs += ishtp-hid-client.o | |||
| 23 | obj-$(CONFIG_INTEL_ISH_FIRMWARE_DOWNLOADER) += intel-ishtp-loader.o | 23 | obj-$(CONFIG_INTEL_ISH_FIRMWARE_DOWNLOADER) += intel-ishtp-loader.o |
| 24 | intel-ishtp-loader-objs += ishtp-fw-loader.o | 24 | intel-ishtp-loader-objs += ishtp-fw-loader.o |
| 25 | 25 | ||
| 26 | ccflags-y += -Idrivers/hid/intel-ish-hid/ishtp | 26 | ccflags-y += -I $(srctree)/$(src)/ishtp |
diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index 9732a81bb7dd..d389d4fb0623 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c | |||
| @@ -714,7 +714,7 @@ static int i2c_dev_irq_from_resources(const struct resource *resources, | |||
| 714 | } | 714 | } |
| 715 | 715 | ||
| 716 | /** | 716 | /** |
| 717 | * i2c_new_device - instantiate an i2c device | 717 | * i2c_new_client_device - instantiate an i2c device |
| 718 | * @adap: the adapter managing the device | 718 | * @adap: the adapter managing the device |
| 719 | * @info: describes one I2C device; bus_num is ignored | 719 | * @info: describes one I2C device; bus_num is ignored |
| 720 | * Context: can sleep | 720 | * Context: can sleep |
| @@ -727,17 +727,17 @@ static int i2c_dev_irq_from_resources(const struct resource *resources, | |||
| 727 | * before any i2c_adapter could exist. | 727 | * before any i2c_adapter could exist. |
| 728 | * | 728 | * |
| 729 | * This returns the new i2c client, which may be saved for later use with | 729 | * This returns the new i2c client, which may be saved for later use with |
| 730 | * i2c_unregister_device(); or NULL to indicate an error. | 730 | * i2c_unregister_device(); or an ERR_PTR to describe the error. |
| 731 | */ | 731 | */ |
| 732 | struct i2c_client * | 732 | static struct i2c_client * |
| 733 | i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) | 733 | i2c_new_client_device(struct i2c_adapter *adap, struct i2c_board_info const *info) |
| 734 | { | 734 | { |
| 735 | struct i2c_client *client; | 735 | struct i2c_client *client; |
| 736 | int status; | 736 | int status; |
| 737 | 737 | ||
| 738 | client = kzalloc(sizeof *client, GFP_KERNEL); | 738 | client = kzalloc(sizeof *client, GFP_KERNEL); |
| 739 | if (!client) | 739 | if (!client) |
| 740 | return NULL; | 740 | return ERR_PTR(-ENOMEM); |
| 741 | 741 | ||
| 742 | client->adapter = adap; | 742 | client->adapter = adap; |
| 743 | 743 | ||
| @@ -803,7 +803,31 @@ out_err: | |||
| 803 | client->name, client->addr, status); | 803 | client->name, client->addr, status); |
| 804 | out_err_silent: | 804 | out_err_silent: |
| 805 | kfree(client); | 805 | kfree(client); |
| 806 | return NULL; | 806 | return ERR_PTR(status); |
| 807 | } | ||
| 808 | EXPORT_SYMBOL_GPL(i2c_new_client_device); | ||
| 809 | |||
| 810 | /** | ||
| 811 | * i2c_new_device - instantiate an i2c device | ||
| 812 | * @adap: the adapter managing the device | ||
| 813 | * @info: describes one I2C device; bus_num is ignored | ||
| 814 | * Context: can sleep | ||
| 815 | * | ||
| 816 | * This deprecated function has the same functionality as | ||
| 817 | * @i2c_new_client_device, it just returns NULL instead of an ERR_PTR in case of | ||
| 818 | * an error for compatibility with current I2C API. It will be removed once all | ||
| 819 | * users are converted. | ||
| 820 | * | ||
| 821 | * This returns the new i2c client, which may be saved for later use with | ||
| 822 | * i2c_unregister_device(); or NULL to indicate an error. | ||
| 823 | */ | ||
| 824 | struct i2c_client * | ||
| 825 | i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) | ||
| 826 | { | ||
| 827 | struct i2c_client *ret; | ||
| 828 | |||
| 829 | ret = i2c_new_client_device(adap, info); | ||
| 830 | return IS_ERR(ret) ? NULL : ret; | ||
| 807 | } | 831 | } |
| 808 | EXPORT_SYMBOL_GPL(i2c_new_device); | 832 | EXPORT_SYMBOL_GPL(i2c_new_device); |
| 809 | 833 | ||
| @@ -854,7 +878,7 @@ static struct i2c_driver dummy_driver = { | |||
| 854 | }; | 878 | }; |
| 855 | 879 | ||
| 856 | /** | 880 | /** |
| 857 | * i2c_new_dummy - return a new i2c device bound to a dummy driver | 881 | * i2c_new_dummy_device - return a new i2c device bound to a dummy driver |
| 858 | * @adapter: the adapter managing the device | 882 | * @adapter: the adapter managing the device |
| 859 | * @address: seven bit address to be used | 883 | * @address: seven bit address to be used |
| 860 | * Context: can sleep | 884 | * Context: can sleep |
| @@ -869,18 +893,86 @@ static struct i2c_driver dummy_driver = { | |||
| 869 | * different driver. | 893 | * different driver. |
| 870 | * | 894 | * |
| 871 | * This returns the new i2c client, which should be saved for later use with | 895 | * This returns the new i2c client, which should be saved for later use with |
| 872 | * i2c_unregister_device(); or NULL to indicate an error. | 896 | * i2c_unregister_device(); or an ERR_PTR to describe the error. |
| 873 | */ | 897 | */ |
| 874 | struct i2c_client *i2c_new_dummy(struct i2c_adapter *adapter, u16 address) | 898 | static struct i2c_client * |
| 899 | i2c_new_dummy_device(struct i2c_adapter *adapter, u16 address) | ||
| 875 | { | 900 | { |
| 876 | struct i2c_board_info info = { | 901 | struct i2c_board_info info = { |
| 877 | I2C_BOARD_INFO("dummy", address), | 902 | I2C_BOARD_INFO("dummy", address), |
| 878 | }; | 903 | }; |
| 879 | 904 | ||
| 880 | return i2c_new_device(adapter, &info); | 905 | return i2c_new_client_device(adapter, &info); |
| 906 | } | ||
| 907 | EXPORT_SYMBOL_GPL(i2c_new_dummy_device); | ||
| 908 | |||
| 909 | /** | ||
| 910 | * i2c_new_dummy - return a new i2c device bound to a dummy driver | ||
| 911 | * @adapter: the adapter managing the device | ||
| 912 | * @address: seven bit address to be used | ||
| 913 | * Context: can sleep | ||
| 914 | * | ||
| 915 | * This deprecated function has the same functionality as @i2c_new_dummy_device, | ||
| 916 | * it just returns NULL instead of an ERR_PTR in case of an error for | ||
| 917 | * compatibility with current I2C API. It will be removed once all users are | ||
| 918 | * converted. | ||
| 919 | * | ||
| 920 | * This returns the new i2c client, which should be saved for later use with | ||
| 921 | * i2c_unregister_device(); or NULL to indicate an error. | ||
| 922 | */ | ||
| 923 | struct i2c_client *i2c_new_dummy(struct i2c_adapter *adapter, u16 address) | ||
| 924 | { | ||
| 925 | struct i2c_client *ret; | ||
| 926 | |||
| 927 | ret = i2c_new_dummy_device(adapter, address); | ||
| 928 | return IS_ERR(ret) ? NULL : ret; | ||
| 881 | } | 929 | } |
| 882 | EXPORT_SYMBOL_GPL(i2c_new_dummy); | 930 | EXPORT_SYMBOL_GPL(i2c_new_dummy); |
| 883 | 931 | ||
| 932 | struct i2c_dummy_devres { | ||
| 933 | struct i2c_client *client; | ||
| 934 | }; | ||
| 935 | |||
| 936 | static void devm_i2c_release_dummy(struct device *dev, void *res) | ||
| 937 | { | ||
| 938 | struct i2c_dummy_devres *this = res; | ||
| 939 | |||
| 940 | i2c_unregister_device(this->client); | ||
| 941 | } | ||
| 942 | |||
| 943 | /** | ||
| 944 | * devm_i2c_new_dummy_device - return a new i2c device bound to a dummy driver | ||
| 945 | * @dev: device the managed resource is bound to | ||
| 946 | * @adapter: the adapter managing the device | ||
| 947 | * @address: seven bit address to be used | ||
| 948 | * Context: can sleep | ||
| 949 | * | ||
| 950 | * This is the device-managed version of @i2c_new_dummy_device. It returns the | ||
| 951 | * new i2c client or an ERR_PTR in case of an error. | ||
| 952 | */ | ||
| 953 | struct i2c_client *devm_i2c_new_dummy_device(struct device *dev, | ||
| 954 | struct i2c_adapter *adapter, | ||
| 955 | u16 address) | ||
| 956 | { | ||
| 957 | struct i2c_dummy_devres *dr; | ||
| 958 | struct i2c_client *client; | ||
| 959 | |||
| 960 | dr = devres_alloc(devm_i2c_release_dummy, sizeof(*dr), GFP_KERNEL); | ||
| 961 | if (!dr) | ||
| 962 | return ERR_PTR(-ENOMEM); | ||
| 963 | |||
| 964 | client = i2c_new_dummy_device(adapter, address); | ||
| 965 | if (IS_ERR(client)) { | ||
| 966 | devres_free(dr); | ||
| 967 | } else { | ||
| 968 | dr->client = client; | ||
| 969 | devres_add(dev, dr); | ||
| 970 | } | ||
| 971 | |||
| 972 | return client; | ||
| 973 | } | ||
| 974 | EXPORT_SYMBOL_GPL(devm_i2c_new_dummy_device); | ||
| 975 | |||
| 884 | /** | 976 | /** |
| 885 | * i2c_new_secondary_device - Helper to get the instantiated secondary address | 977 | * i2c_new_secondary_device - Helper to get the instantiated secondary address |
| 886 | * and create the associated device | 978 | * and create the associated device |
| @@ -1000,9 +1092,9 @@ i2c_sysfs_new_device(struct device *dev, struct device_attribute *attr, | |||
| 1000 | info.flags |= I2C_CLIENT_SLAVE; | 1092 | info.flags |= I2C_CLIENT_SLAVE; |
| 1001 | } | 1093 | } |
| 1002 | 1094 | ||
| 1003 | client = i2c_new_device(adap, &info); | 1095 | client = i2c_new_client_device(adap, &info); |
| 1004 | if (!client) | 1096 | if (IS_ERR(client)) |
| 1005 | return -EINVAL; | 1097 | return PTR_ERR(client); |
| 1006 | 1098 | ||
| 1007 | /* Keep track of the added device */ | 1099 | /* Keep track of the added device */ |
| 1008 | mutex_lock(&adap->userspace_clients_lock); | 1100 | mutex_lock(&adap->userspace_clients_lock); |
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index 15b831113ded..e559e43c8ac2 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig | |||
| @@ -94,6 +94,7 @@ config IOMMU_DMA | |||
| 94 | bool | 94 | bool |
| 95 | select IOMMU_API | 95 | select IOMMU_API |
| 96 | select IOMMU_IOVA | 96 | select IOMMU_IOVA |
| 97 | select IRQ_MSI_IOMMU | ||
| 97 | select NEED_SG_DMA_LENGTH | 98 | select NEED_SG_DMA_LENGTH |
| 98 | 99 | ||
| 99 | config FSL_PAMU | 100 | config FSL_PAMU |
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c index 5e898047c390..129c4badf9ae 100644 --- a/drivers/iommu/dma-iommu.c +++ b/drivers/iommu/dma-iommu.c | |||
| @@ -907,17 +907,18 @@ out_free_page: | |||
| 907 | return NULL; | 907 | return NULL; |
| 908 | } | 908 | } |
| 909 | 909 | ||
| 910 | void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg) | 910 | int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr) |
| 911 | { | 911 | { |
| 912 | struct device *dev = msi_desc_to_dev(irq_get_msi_desc(irq)); | 912 | struct device *dev = msi_desc_to_dev(desc); |
| 913 | struct iommu_domain *domain = iommu_get_domain_for_dev(dev); | 913 | struct iommu_domain *domain = iommu_get_domain_for_dev(dev); |
| 914 | struct iommu_dma_cookie *cookie; | 914 | struct iommu_dma_cookie *cookie; |
| 915 | struct iommu_dma_msi_page *msi_page; | 915 | struct iommu_dma_msi_page *msi_page; |
| 916 | phys_addr_t msi_addr = (u64)msg->address_hi << 32 | msg->address_lo; | ||
| 917 | unsigned long flags; | 916 | unsigned long flags; |
| 918 | 917 | ||
| 919 | if (!domain || !domain->iova_cookie) | 918 | if (!domain || !domain->iova_cookie) { |
| 920 | return; | 919 | desc->iommu_cookie = NULL; |
| 920 | return 0; | ||
| 921 | } | ||
| 921 | 922 | ||
| 922 | cookie = domain->iova_cookie; | 923 | cookie = domain->iova_cookie; |
| 923 | 924 | ||
| @@ -930,19 +931,26 @@ void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg) | |||
| 930 | msi_page = iommu_dma_get_msi_page(dev, msi_addr, domain); | 931 | msi_page = iommu_dma_get_msi_page(dev, msi_addr, domain); |
| 931 | spin_unlock_irqrestore(&cookie->msi_lock, flags); | 932 | spin_unlock_irqrestore(&cookie->msi_lock, flags); |
| 932 | 933 | ||
| 933 | if (WARN_ON(!msi_page)) { | 934 | msi_desc_set_iommu_cookie(desc, msi_page); |
| 934 | /* | 935 | |
| 935 | * We're called from a void callback, so the best we can do is | 936 | if (!msi_page) |
| 936 | * 'fail' by filling the message with obviously bogus values. | 937 | return -ENOMEM; |
| 937 | * Since we got this far due to an IOMMU being present, it's | 938 | return 0; |
| 938 | * not like the existing address would have worked anyway... | 939 | } |
| 939 | */ | 940 | |
| 940 | msg->address_hi = ~0U; | 941 | void iommu_dma_compose_msi_msg(struct msi_desc *desc, |
| 941 | msg->address_lo = ~0U; | 942 | struct msi_msg *msg) |
| 942 | msg->data = ~0U; | 943 | { |
| 943 | } else { | 944 | struct device *dev = msi_desc_to_dev(desc); |
| 944 | msg->address_hi = upper_32_bits(msi_page->iova); | 945 | const struct iommu_domain *domain = iommu_get_domain_for_dev(dev); |
| 945 | msg->address_lo &= cookie_msi_granule(cookie) - 1; | 946 | const struct iommu_dma_msi_page *msi_page; |
| 946 | msg->address_lo += lower_32_bits(msi_page->iova); | 947 | |
| 947 | } | 948 | msi_page = msi_desc_get_iommu_cookie(desc); |
| 949 | |||
| 950 | if (!domain || !domain->iova_cookie || WARN_ON(!msi_page)) | ||
| 951 | return; | ||
| 952 | |||
| 953 | msg->address_hi = upper_32_bits(msi_page->iova); | ||
| 954 | msg->address_lo &= cookie_msi_granule(domain->iova_cookie) - 1; | ||
| 955 | msg->address_lo += lower_32_bits(msi_page->iova); | ||
| 948 | } | 956 | } |
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index cf7984991062..1c1f3f66dfd3 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig | |||
| @@ -6,7 +6,6 @@ config IRQCHIP | |||
| 6 | 6 | ||
| 7 | config ARM_GIC | 7 | config ARM_GIC |
| 8 | bool | 8 | bool |
| 9 | select IRQ_DOMAIN | ||
| 10 | select IRQ_DOMAIN_HIERARCHY | 9 | select IRQ_DOMAIN_HIERARCHY |
| 11 | select GENERIC_IRQ_MULTI_HANDLER | 10 | select GENERIC_IRQ_MULTI_HANDLER |
| 12 | select GENERIC_IRQ_EFFECTIVE_AFF_MASK | 11 | select GENERIC_IRQ_EFFECTIVE_AFF_MASK |
| @@ -33,7 +32,6 @@ config GIC_NON_BANKED | |||
| 33 | 32 | ||
| 34 | config ARM_GIC_V3 | 33 | config ARM_GIC_V3 |
| 35 | bool | 34 | bool |
| 36 | select IRQ_DOMAIN | ||
| 37 | select GENERIC_IRQ_MULTI_HANDLER | 35 | select GENERIC_IRQ_MULTI_HANDLER |
| 38 | select IRQ_DOMAIN_HIERARCHY | 36 | select IRQ_DOMAIN_HIERARCHY |
| 39 | select PARTITION_PERCPU | 37 | select PARTITION_PERCPU |
| @@ -59,7 +57,6 @@ config ARM_GIC_V3_ITS_FSL_MC | |||
| 59 | 57 | ||
| 60 | config ARM_NVIC | 58 | config ARM_NVIC |
| 61 | bool | 59 | bool |
| 62 | select IRQ_DOMAIN | ||
| 63 | select IRQ_DOMAIN_HIERARCHY | 60 | select IRQ_DOMAIN_HIERARCHY |
| 64 | select GENERIC_IRQ_CHIP | 61 | select GENERIC_IRQ_CHIP |
| 65 | 62 | ||
| @@ -358,7 +355,6 @@ config STM32_EXTI | |||
| 358 | config QCOM_IRQ_COMBINER | 355 | config QCOM_IRQ_COMBINER |
| 359 | bool "QCOM IRQ combiner support" | 356 | bool "QCOM IRQ combiner support" |
| 360 | depends on ARCH_QCOM && ACPI | 357 | depends on ARCH_QCOM && ACPI |
| 361 | select IRQ_DOMAIN | ||
| 362 | select IRQ_DOMAIN_HIERARCHY | 358 | select IRQ_DOMAIN_HIERARCHY |
| 363 | help | 359 | help |
| 364 | Say yes here to add support for the IRQ combiner devices embedded | 360 | Say yes here to add support for the IRQ combiner devices embedded |
| @@ -375,7 +371,6 @@ config IRQ_UNIPHIER_AIDET | |||
| 375 | config MESON_IRQ_GPIO | 371 | config MESON_IRQ_GPIO |
| 376 | bool "Meson GPIO Interrupt Multiplexer" | 372 | bool "Meson GPIO Interrupt Multiplexer" |
| 377 | depends on ARCH_MESON | 373 | depends on ARCH_MESON |
| 378 | select IRQ_DOMAIN | ||
| 379 | select IRQ_DOMAIN_HIERARCHY | 374 | select IRQ_DOMAIN_HIERARCHY |
| 380 | help | 375 | help |
| 381 | Support Meson SoC Family GPIO Interrupt Multiplexer | 376 | Support Meson SoC Family GPIO Interrupt Multiplexer |
| @@ -391,7 +386,6 @@ config GOLDFISH_PIC | |||
| 391 | config QCOM_PDC | 386 | config QCOM_PDC |
| 392 | bool "QCOM PDC" | 387 | bool "QCOM PDC" |
| 393 | depends on ARCH_QCOM | 388 | depends on ARCH_QCOM |
| 394 | select IRQ_DOMAIN | ||
| 395 | select IRQ_DOMAIN_HIERARCHY | 389 | select IRQ_DOMAIN_HIERARCHY |
| 396 | help | 390 | help |
| 397 | Power Domain Controller driver to manage and configure wakeup | 391 | Power Domain Controller driver to manage and configure wakeup |
| @@ -431,6 +425,27 @@ config LS1X_IRQ | |||
| 431 | help | 425 | help |
| 432 | Support for the Loongson-1 platform Interrupt Controller. | 426 | Support for the Loongson-1 platform Interrupt Controller. |
| 433 | 427 | ||
| 428 | config TI_SCI_INTR_IRQCHIP | ||
| 429 | bool | ||
| 430 | depends on TI_SCI_PROTOCOL | ||
| 431 | select IRQ_DOMAIN_HIERARCHY | ||
| 432 | help | ||
| 433 | This enables the irqchip driver support for K3 Interrupt router | ||
| 434 | over TI System Control Interface available on some new TI's SoCs. | ||
| 435 | If you wish to use interrupt router irq resources managed by the | ||
| 436 | TI System Controller, say Y here. Otherwise, say N. | ||
| 437 | |||
| 438 | config TI_SCI_INTA_IRQCHIP | ||
| 439 | bool | ||
| 440 | depends on TI_SCI_PROTOCOL | ||
| 441 | select IRQ_DOMAIN_HIERARCHY | ||
| 442 | select TI_SCI_INTA_MSI_DOMAIN | ||
| 443 | help | ||
| 444 | This enables the irqchip driver support for K3 Interrupt aggregator | ||
| 445 | over TI System Control Interface available on some new TI's SoCs. | ||
| 446 | If you wish to use interrupt aggregator irq resources managed by the | ||
| 447 | TI System Controller, say Y here. Otherwise, say N. | ||
| 448 | |||
| 434 | endmenu | 449 | endmenu |
| 435 | 450 | ||
| 436 | config SIFIVE_PLIC | 451 | config SIFIVE_PLIC |
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index f8c66e958a64..606a003a0000 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile | |||
| @@ -98,3 +98,5 @@ obj-$(CONFIG_SIFIVE_PLIC) += irq-sifive-plic.o | |||
| 98 | obj-$(CONFIG_IMX_IRQSTEER) += irq-imx-irqsteer.o | 98 | obj-$(CONFIG_IMX_IRQSTEER) += irq-imx-irqsteer.o |
| 99 | obj-$(CONFIG_MADERA_IRQ) += irq-madera.o | 99 | obj-$(CONFIG_MADERA_IRQ) += irq-madera.o |
| 100 | obj-$(CONFIG_LS1X_IRQ) += irq-ls1x.o | 100 | obj-$(CONFIG_LS1X_IRQ) += irq-ls1x.o |
| 101 | obj-$(CONFIG_TI_SCI_INTR_IRQCHIP) += irq-ti-sci-intr.o | ||
| 102 | obj-$(CONFIG_TI_SCI_INTA_IRQCHIP) += irq-ti-sci-inta.o | ||
diff --git a/drivers/irqchip/irq-bcm7038-l1.c b/drivers/irqchip/irq-bcm7038-l1.c index 0f6e30e9009d..0acebac1920b 100644 --- a/drivers/irqchip/irq-bcm7038-l1.c +++ b/drivers/irqchip/irq-bcm7038-l1.c | |||
| @@ -343,6 +343,9 @@ int __init bcm7038_l1_of_init(struct device_node *dn, | |||
| 343 | goto out_unmap; | 343 | goto out_unmap; |
| 344 | } | 344 | } |
| 345 | 345 | ||
| 346 | pr_info("registered BCM7038 L1 intc (%pOF, IRQs: %d)\n", | ||
| 347 | dn, IRQS_PER_WORD * intc->n_words); | ||
| 348 | |||
| 346 | return 0; | 349 | return 0; |
| 347 | 350 | ||
| 348 | out_unmap: | 351 | out_unmap: |
diff --git a/drivers/irqchip/irq-bcm7120-l2.c b/drivers/irqchip/irq-bcm7120-l2.c index 8968e5e93fcb..541bdca9f4af 100644 --- a/drivers/irqchip/irq-bcm7120-l2.c +++ b/drivers/irqchip/irq-bcm7120-l2.c | |||
| @@ -318,6 +318,9 @@ static int __init bcm7120_l2_intc_probe(struct device_node *dn, | |||
| 318 | } | 318 | } |
| 319 | } | 319 | } |
| 320 | 320 | ||
| 321 | pr_info("registered %s intc (%pOF, parent IRQ(s): %d)\n", | ||
| 322 | intc_name, dn, data->num_parent_irqs); | ||
| 323 | |||
| 321 | return 0; | 324 | return 0; |
| 322 | 325 | ||
| 323 | out_free_domain: | 326 | out_free_domain: |
diff --git a/drivers/irqchip/irq-brcmstb-l2.c b/drivers/irqchip/irq-brcmstb-l2.c index 5e4ca139e4ea..a0642b59befa 100644 --- a/drivers/irqchip/irq-brcmstb-l2.c +++ b/drivers/irqchip/irq-brcmstb-l2.c | |||
| @@ -264,6 +264,8 @@ static int __init brcmstb_l2_intc_of_init(struct device_node *np, | |||
| 264 | ct->chip.irq_set_wake = irq_gc_set_wake; | 264 | ct->chip.irq_set_wake = irq_gc_set_wake; |
| 265 | } | 265 | } |
| 266 | 266 | ||
| 267 | pr_info("registered L2 intc (%pOF, parent irq: %d)\n", np, parent_irq); | ||
| 268 | |||
| 267 | return 0; | 269 | return 0; |
| 268 | 270 | ||
| 269 | out_free_domain: | 271 | out_free_domain: |
diff --git a/drivers/irqchip/irq-gic-pm.c b/drivers/irqchip/irq-gic-pm.c index ecafd295c31c..c4aac0977d8a 100644 --- a/drivers/irqchip/irq-gic-pm.c +++ b/drivers/irqchip/irq-gic-pm.c | |||
| @@ -19,7 +19,6 @@ | |||
| 19 | #include <linux/of_irq.h> | 19 | #include <linux/of_irq.h> |
| 20 | #include <linux/irqchip/arm-gic.h> | 20 | #include <linux/irqchip/arm-gic.h> |
| 21 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
| 22 | #include <linux/pm_clock.h> | ||
| 23 | #include <linux/pm_runtime.h> | 22 | #include <linux/pm_runtime.h> |
| 24 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
| 25 | 24 | ||
| @@ -28,17 +27,27 @@ struct gic_clk_data { | |||
| 28 | const char *const *clocks; | 27 | const char *const *clocks; |
| 29 | }; | 28 | }; |
| 30 | 29 | ||
| 30 | struct gic_chip_pm { | ||
| 31 | struct gic_chip_data *chip_data; | ||
| 32 | const struct gic_clk_data *clk_data; | ||
| 33 | struct clk_bulk_data *clks; | ||
| 34 | }; | ||
| 35 | |||
| 31 | static int gic_runtime_resume(struct device *dev) | 36 | static int gic_runtime_resume(struct device *dev) |
| 32 | { | 37 | { |
| 33 | struct gic_chip_data *gic = dev_get_drvdata(dev); | 38 | struct gic_chip_pm *chip_pm = dev_get_drvdata(dev); |
| 39 | struct gic_chip_data *gic = chip_pm->chip_data; | ||
| 40 | const struct gic_clk_data *data = chip_pm->clk_data; | ||
| 34 | int ret; | 41 | int ret; |
| 35 | 42 | ||
| 36 | ret = pm_clk_resume(dev); | 43 | ret = clk_bulk_prepare_enable(data->num_clocks, chip_pm->clks); |
| 37 | if (ret) | 44 | if (ret) { |
| 45 | dev_err(dev, "clk_enable failed: %d\n", ret); | ||
| 38 | return ret; | 46 | return ret; |
| 47 | } | ||
| 39 | 48 | ||
| 40 | /* | 49 | /* |
| 41 | * On the very first resume, the pointer to the driver data | 50 | * On the very first resume, the pointer to chip_pm->chip_data |
| 42 | * will be NULL and this is intentional, because we do not | 51 | * will be NULL and this is intentional, because we do not |
| 43 | * want to restore the GIC on the very first resume. So if | 52 | * want to restore the GIC on the very first resume. So if |
| 44 | * the pointer is not valid just return. | 53 | * the pointer is not valid just return. |
| @@ -54,35 +63,14 @@ static int gic_runtime_resume(struct device *dev) | |||
| 54 | 63 | ||
| 55 | static int gic_runtime_suspend(struct device *dev) | 64 | static int gic_runtime_suspend(struct device *dev) |
| 56 | { | 65 | { |
| 57 | struct gic_chip_data *gic = dev_get_drvdata(dev); | 66 | struct gic_chip_pm *chip_pm = dev_get_drvdata(dev); |
| 67 | struct gic_chip_data *gic = chip_pm->chip_data; | ||
| 68 | const struct gic_clk_data *data = chip_pm->clk_data; | ||
| 58 | 69 | ||
| 59 | gic_dist_save(gic); | 70 | gic_dist_save(gic); |
| 60 | gic_cpu_save(gic); | 71 | gic_cpu_save(gic); |
| 61 | 72 | ||
| 62 | return pm_clk_suspend(dev); | 73 | clk_bulk_disable_unprepare(data->num_clocks, chip_pm->clks); |
| 63 | } | ||
| 64 | |||
| 65 | static int gic_get_clocks(struct device *dev, const struct gic_clk_data *data) | ||
| 66 | { | ||
| 67 | unsigned int i; | ||
| 68 | int ret; | ||
| 69 | |||
| 70 | if (!dev || !data) | ||
| 71 | return -EINVAL; | ||
| 72 | |||
| 73 | ret = pm_clk_create(dev); | ||
| 74 | if (ret) | ||
| 75 | return ret; | ||
| 76 | |||
| 77 | for (i = 0; i < data->num_clocks; i++) { | ||
| 78 | ret = of_pm_clk_add_clk(dev, data->clocks[i]); | ||
| 79 | if (ret) { | ||
| 80 | dev_err(dev, "failed to add clock %s\n", | ||
| 81 | data->clocks[i]); | ||
| 82 | pm_clk_destroy(dev); | ||
| 83 | return ret; | ||
| 84 | } | ||
| 85 | } | ||
| 86 | 74 | ||
| 87 | return 0; | 75 | return 0; |
| 88 | } | 76 | } |
| @@ -91,8 +79,8 @@ static int gic_probe(struct platform_device *pdev) | |||
| 91 | { | 79 | { |
| 92 | struct device *dev = &pdev->dev; | 80 | struct device *dev = &pdev->dev; |
| 93 | const struct gic_clk_data *data; | 81 | const struct gic_clk_data *data; |
| 94 | struct gic_chip_data *gic; | 82 | struct gic_chip_pm *chip_pm; |
| 95 | int ret, irq; | 83 | int ret, irq, i; |
| 96 | 84 | ||
| 97 | data = of_device_get_match_data(&pdev->dev); | 85 | data = of_device_get_match_data(&pdev->dev); |
| 98 | if (!data) { | 86 | if (!data) { |
| @@ -100,28 +88,41 @@ static int gic_probe(struct platform_device *pdev) | |||
| 100 | return -ENODEV; | 88 | return -ENODEV; |
| 101 | } | 89 | } |
| 102 | 90 | ||
| 91 | chip_pm = devm_kzalloc(dev, sizeof(*chip_pm), GFP_KERNEL); | ||
| 92 | if (!chip_pm) | ||
| 93 | return -ENOMEM; | ||
| 94 | |||
| 103 | irq = irq_of_parse_and_map(dev->of_node, 0); | 95 | irq = irq_of_parse_and_map(dev->of_node, 0); |
| 104 | if (!irq) { | 96 | if (!irq) { |
| 105 | dev_err(dev, "no parent interrupt found!\n"); | 97 | dev_err(dev, "no parent interrupt found!\n"); |
| 106 | return -EINVAL; | 98 | return -EINVAL; |
| 107 | } | 99 | } |
| 108 | 100 | ||
| 109 | ret = gic_get_clocks(dev, data); | 101 | chip_pm->clks = devm_kcalloc(dev, data->num_clocks, |
| 102 | sizeof(*chip_pm->clks), GFP_KERNEL); | ||
| 103 | if (!chip_pm->clks) | ||
| 104 | return -ENOMEM; | ||
| 105 | |||
| 106 | for (i = 0; i < data->num_clocks; i++) | ||
| 107 | chip_pm->clks[i].id = data->clocks[i]; | ||
| 108 | |||
| 109 | ret = devm_clk_bulk_get(dev, data->num_clocks, chip_pm->clks); | ||
| 110 | if (ret) | 110 | if (ret) |
| 111 | goto irq_dispose; | 111 | goto irq_dispose; |
| 112 | 112 | ||
| 113 | chip_pm->clk_data = data; | ||
| 114 | dev_set_drvdata(dev, chip_pm); | ||
| 115 | |||
| 113 | pm_runtime_enable(dev); | 116 | pm_runtime_enable(dev); |
| 114 | 117 | ||
| 115 | ret = pm_runtime_get_sync(dev); | 118 | ret = pm_runtime_get_sync(dev); |
| 116 | if (ret < 0) | 119 | if (ret < 0) |
| 117 | goto rpm_disable; | 120 | goto rpm_disable; |
| 118 | 121 | ||
| 119 | ret = gic_of_init_child(dev, &gic, irq); | 122 | ret = gic_of_init_child(dev, &chip_pm->chip_data, irq); |
| 120 | if (ret) | 123 | if (ret) |
| 121 | goto rpm_put; | 124 | goto rpm_put; |
| 122 | 125 | ||
| 123 | platform_set_drvdata(pdev, gic); | ||
| 124 | |||
| 125 | pm_runtime_put(dev); | 126 | pm_runtime_put(dev); |
| 126 | 127 | ||
| 127 | dev_info(dev, "GIC IRQ controller registered\n"); | 128 | dev_info(dev, "GIC IRQ controller registered\n"); |
| @@ -132,7 +133,6 @@ rpm_put: | |||
| 132 | pm_runtime_put_sync(dev); | 133 | pm_runtime_put_sync(dev); |
| 133 | rpm_disable: | 134 | rpm_disable: |
| 134 | pm_runtime_disable(dev); | 135 | pm_runtime_disable(dev); |
| 135 | pm_clk_destroy(dev); | ||
| 136 | irq_dispose: | 136 | irq_dispose: |
| 137 | irq_dispose_mapping(irq); | 137 | irq_dispose_mapping(irq); |
| 138 | 138 | ||
| @@ -142,6 +142,8 @@ irq_dispose: | |||
| 142 | static const struct dev_pm_ops gic_pm_ops = { | 142 | static const struct dev_pm_ops gic_pm_ops = { |
| 143 | SET_RUNTIME_PM_OPS(gic_runtime_suspend, | 143 | SET_RUNTIME_PM_OPS(gic_runtime_suspend, |
| 144 | gic_runtime_resume, NULL) | 144 | gic_runtime_resume, NULL) |
| 145 | SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, | ||
| 146 | pm_runtime_force_resume) | ||
| 145 | }; | 147 | }; |
| 146 | 148 | ||
| 147 | static const char * const gic400_clocks[] = { | 149 | static const char * const gic400_clocks[] = { |
diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c index de14e06fd9ec..3c77ab676e54 100644 --- a/drivers/irqchip/irq-gic-v2m.c +++ b/drivers/irqchip/irq-gic-v2m.c | |||
| @@ -110,7 +110,7 @@ static void gicv2m_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) | |||
| 110 | if (v2m->flags & GICV2M_NEEDS_SPI_OFFSET) | 110 | if (v2m->flags & GICV2M_NEEDS_SPI_OFFSET) |
| 111 | msg->data -= v2m->spi_offset; | 111 | msg->data -= v2m->spi_offset; |
| 112 | 112 | ||
| 113 | iommu_dma_map_msi_msg(data->irq, msg); | 113 | iommu_dma_compose_msi_msg(irq_data_get_msi_desc(data), msg); |
| 114 | } | 114 | } |
| 115 | 115 | ||
| 116 | static struct irq_chip gicv2m_irq_chip = { | 116 | static struct irq_chip gicv2m_irq_chip = { |
| @@ -167,6 +167,7 @@ static void gicv2m_unalloc_msi(struct v2m_data *v2m, unsigned int hwirq, | |||
| 167 | static int gicv2m_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, | 167 | static int gicv2m_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, |
| 168 | unsigned int nr_irqs, void *args) | 168 | unsigned int nr_irqs, void *args) |
| 169 | { | 169 | { |
| 170 | msi_alloc_info_t *info = args; | ||
| 170 | struct v2m_data *v2m = NULL, *tmp; | 171 | struct v2m_data *v2m = NULL, *tmp; |
| 171 | int hwirq, offset, i, err = 0; | 172 | int hwirq, offset, i, err = 0; |
| 172 | 173 | ||
| @@ -186,6 +187,11 @@ static int gicv2m_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, | |||
| 186 | 187 | ||
| 187 | hwirq = v2m->spi_start + offset; | 188 | hwirq = v2m->spi_start + offset; |
| 188 | 189 | ||
| 190 | err = iommu_dma_prepare_msi(info->desc, | ||
| 191 | v2m->res.start + V2M_MSI_SETSPI_NS); | ||
| 192 | if (err) | ||
| 193 | return err; | ||
| 194 | |||
| 189 | for (i = 0; i < nr_irqs; i++) { | 195 | for (i = 0; i < nr_irqs; i++) { |
| 190 | err = gicv2m_irq_gic_domain_alloc(domain, virq + i, hwirq + i); | 196 | err = gicv2m_irq_gic_domain_alloc(domain, virq + i, hwirq + i); |
| 191 | if (err) | 197 | if (err) |
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 128ac893d7e4..cfb9b4e5f914 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c | |||
| @@ -26,7 +26,6 @@ | |||
| 26 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
| 27 | #include <linux/irqdomain.h> | 27 | #include <linux/irqdomain.h> |
| 28 | #include <linux/list.h> | 28 | #include <linux/list.h> |
| 29 | #include <linux/list_sort.h> | ||
| 30 | #include <linux/log2.h> | 29 | #include <linux/log2.h> |
| 31 | #include <linux/memblock.h> | 30 | #include <linux/memblock.h> |
| 32 | #include <linux/mm.h> | 31 | #include <linux/mm.h> |
| @@ -1179,7 +1178,7 @@ static void its_irq_compose_msi_msg(struct irq_data *d, struct msi_msg *msg) | |||
| 1179 | msg->address_hi = upper_32_bits(addr); | 1178 | msg->address_hi = upper_32_bits(addr); |
| 1180 | msg->data = its_get_event_id(d); | 1179 | msg->data = its_get_event_id(d); |
| 1181 | 1180 | ||
| 1182 | iommu_dma_map_msi_msg(d->irq, msg); | 1181 | iommu_dma_compose_msi_msg(irq_data_get_msi_desc(d), msg); |
| 1183 | } | 1182 | } |
| 1184 | 1183 | ||
| 1185 | static int its_irq_set_irqchip_state(struct irq_data *d, | 1184 | static int its_irq_set_irqchip_state(struct irq_data *d, |
| @@ -1465,9 +1464,8 @@ static struct lpi_range *mk_lpi_range(u32 base, u32 span) | |||
| 1465 | { | 1464 | { |
| 1466 | struct lpi_range *range; | 1465 | struct lpi_range *range; |
| 1467 | 1466 | ||
| 1468 | range = kzalloc(sizeof(*range), GFP_KERNEL); | 1467 | range = kmalloc(sizeof(*range), GFP_KERNEL); |
| 1469 | if (range) { | 1468 | if (range) { |
| 1470 | INIT_LIST_HEAD(&range->entry); | ||
| 1471 | range->base_id = base; | 1469 | range->base_id = base; |
| 1472 | range->span = span; | 1470 | range->span = span; |
| 1473 | } | 1471 | } |
| @@ -1475,31 +1473,6 @@ static struct lpi_range *mk_lpi_range(u32 base, u32 span) | |||
| 1475 | return range; | 1473 | return range; |
| 1476 | } | 1474 | } |
| 1477 | 1475 | ||
| 1478 | static int lpi_range_cmp(void *priv, struct list_head *a, struct list_head *b) | ||
| 1479 | { | ||
| 1480 | struct lpi_range *ra, *rb; | ||
| 1481 | |||
| 1482 | ra = container_of(a, struct lpi_range, entry); | ||
| 1483 | rb = container_of(b, struct lpi_range, entry); | ||
| 1484 | |||
| 1485 | return ra->base_id - rb->base_id; | ||
| 1486 | } | ||
| 1487 | |||
| 1488 | static void merge_lpi_ranges(void) | ||
| 1489 | { | ||
| 1490 | struct lpi_range *range, *tmp; | ||
| 1491 | |||
| 1492 | list_for_each_entry_safe(range, tmp, &lpi_range_list, entry) { | ||
| 1493 | if (!list_is_last(&range->entry, &lpi_range_list) && | ||
| 1494 | (tmp->base_id == (range->base_id + range->span))) { | ||
| 1495 | tmp->base_id = range->base_id; | ||
| 1496 | tmp->span += range->span; | ||
| 1497 | list_del(&range->entry); | ||
| 1498 | kfree(range); | ||
| 1499 | } | ||
| 1500 | } | ||
| 1501 | } | ||
| 1502 | |||
| 1503 | static int alloc_lpi_range(u32 nr_lpis, u32 *base) | 1476 | static int alloc_lpi_range(u32 nr_lpis, u32 *base) |
| 1504 | { | 1477 | { |
| 1505 | struct lpi_range *range, *tmp; | 1478 | struct lpi_range *range, *tmp; |
| @@ -1529,25 +1502,49 @@ static int alloc_lpi_range(u32 nr_lpis, u32 *base) | |||
| 1529 | return err; | 1502 | return err; |
| 1530 | } | 1503 | } |
| 1531 | 1504 | ||
| 1505 | static void merge_lpi_ranges(struct lpi_range *a, struct lpi_range *b) | ||
| 1506 | { | ||
| 1507 | if (&a->entry == &lpi_range_list || &b->entry == &lpi_range_list) | ||
| 1508 | return; | ||
| 1509 | if (a->base_id + a->span != b->base_id) | ||
| 1510 | return; | ||
| 1511 | b->base_id = a->base_id; | ||
| 1512 | b->span += a->span; | ||
| 1513 | list_del(&a->entry); | ||
| 1514 | kfree(a); | ||
| 1515 | } | ||
| 1516 | |||
| 1532 | static int free_lpi_range(u32 base, u32 nr_lpis) | 1517 | static int free_lpi_range(u32 base, u32 nr_lpis) |
| 1533 | { | 1518 | { |
| 1534 | struct lpi_range *new; | 1519 | struct lpi_range *new, *old; |
| 1535 | int err = 0; | 1520 | |
| 1521 | new = mk_lpi_range(base, nr_lpis); | ||
| 1522 | if (!new) | ||
| 1523 | return -ENOMEM; | ||
| 1536 | 1524 | ||
| 1537 | mutex_lock(&lpi_range_lock); | 1525 | mutex_lock(&lpi_range_lock); |
| 1538 | 1526 | ||
| 1539 | new = mk_lpi_range(base, nr_lpis); | 1527 | list_for_each_entry_reverse(old, &lpi_range_list, entry) { |
| 1540 | if (!new) { | 1528 | if (old->base_id < base) |
| 1541 | err = -ENOMEM; | 1529 | break; |
| 1542 | goto out; | ||
| 1543 | } | 1530 | } |
| 1531 | /* | ||
| 1532 | * old is the last element with ->base_id smaller than base, | ||
| 1533 | * so new goes right after it. If there are no elements with | ||
| 1534 | * ->base_id smaller than base, &old->entry ends up pointing | ||
| 1535 | * at the head of the list, and inserting new it the start of | ||
| 1536 | * the list is the right thing to do in that case as well. | ||
| 1537 | */ | ||
| 1538 | list_add(&new->entry, &old->entry); | ||
| 1539 | /* | ||
| 1540 | * Now check if we can merge with the preceding and/or | ||
| 1541 | * following ranges. | ||
| 1542 | */ | ||
| 1543 | merge_lpi_ranges(old, new); | ||
| 1544 | merge_lpi_ranges(new, list_next_entry(new, entry)); | ||
| 1544 | 1545 | ||
| 1545 | list_add(&new->entry, &lpi_range_list); | ||
| 1546 | list_sort(NULL, &lpi_range_list, lpi_range_cmp); | ||
| 1547 | merge_lpi_ranges(); | ||
| 1548 | out: | ||
| 1549 | mutex_unlock(&lpi_range_lock); | 1546 | mutex_unlock(&lpi_range_lock); |
| 1550 | return err; | 1547 | return 0; |
| 1551 | } | 1548 | } |
| 1552 | 1549 | ||
| 1553 | static int __init its_lpi_init(u32 id_bits) | 1550 | static int __init its_lpi_init(u32 id_bits) |
| @@ -2487,7 +2484,7 @@ static int its_msi_prepare(struct irq_domain *domain, struct device *dev, | |||
| 2487 | int err = 0; | 2484 | int err = 0; |
| 2488 | 2485 | ||
| 2489 | /* | 2486 | /* |
| 2490 | * We ignore "dev" entierely, and rely on the dev_id that has | 2487 | * We ignore "dev" entirely, and rely on the dev_id that has |
| 2491 | * been passed via the scratchpad. This limits this domain's | 2488 | * been passed via the scratchpad. This limits this domain's |
| 2492 | * usefulness to upper layers that definitely know that they | 2489 | * usefulness to upper layers that definitely know that they |
| 2493 | * are built on top of the ITS. | 2490 | * are built on top of the ITS. |
| @@ -2566,6 +2563,7 @@ static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, | |||
| 2566 | { | 2563 | { |
| 2567 | msi_alloc_info_t *info = args; | 2564 | msi_alloc_info_t *info = args; |
| 2568 | struct its_device *its_dev = info->scratchpad[0].ptr; | 2565 | struct its_device *its_dev = info->scratchpad[0].ptr; |
| 2566 | struct its_node *its = its_dev->its; | ||
| 2569 | irq_hw_number_t hwirq; | 2567 | irq_hw_number_t hwirq; |
| 2570 | int err; | 2568 | int err; |
| 2571 | int i; | 2569 | int i; |
| @@ -2574,6 +2572,10 @@ static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, | |||
| 2574 | if (err) | 2572 | if (err) |
| 2575 | return err; | 2573 | return err; |
| 2576 | 2574 | ||
| 2575 | err = iommu_dma_prepare_msi(info->desc, its->get_msi_base(its_dev)); | ||
| 2576 | if (err) | ||
| 2577 | return err; | ||
| 2578 | |||
| 2577 | for (i = 0; i < nr_irqs; i++) { | 2579 | for (i = 0; i < nr_irqs; i++) { |
| 2578 | err = its_irq_gic_domain_alloc(domain, virq + i, hwirq + i); | 2580 | err = its_irq_gic_domain_alloc(domain, virq + i, hwirq + i); |
| 2579 | if (err) | 2581 | if (err) |
diff --git a/drivers/irqchip/irq-gic-v3-mbi.c b/drivers/irqchip/irq-gic-v3-mbi.c index fbfa7ff6deb1..563a9b366294 100644 --- a/drivers/irqchip/irq-gic-v3-mbi.c +++ b/drivers/irqchip/irq-gic-v3-mbi.c | |||
| @@ -84,6 +84,7 @@ static void mbi_free_msi(struct mbi_range *mbi, unsigned int hwirq, | |||
| 84 | static int mbi_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, | 84 | static int mbi_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, |
| 85 | unsigned int nr_irqs, void *args) | 85 | unsigned int nr_irqs, void *args) |
| 86 | { | 86 | { |
| 87 | msi_alloc_info_t *info = args; | ||
| 87 | struct mbi_range *mbi = NULL; | 88 | struct mbi_range *mbi = NULL; |
| 88 | int hwirq, offset, i, err = 0; | 89 | int hwirq, offset, i, err = 0; |
| 89 | 90 | ||
| @@ -104,6 +105,11 @@ static int mbi_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, | |||
| 104 | 105 | ||
| 105 | hwirq = mbi->spi_start + offset; | 106 | hwirq = mbi->spi_start + offset; |
| 106 | 107 | ||
| 108 | err = iommu_dma_prepare_msi(info->desc, | ||
| 109 | mbi_phys_base + GICD_SETSPI_NSR); | ||
| 110 | if (err) | ||
| 111 | return err; | ||
| 112 | |||
| 107 | for (i = 0; i < nr_irqs; i++) { | 113 | for (i = 0; i < nr_irqs; i++) { |
| 108 | err = mbi_irq_gic_domain_alloc(domain, virq + i, hwirq + i); | 114 | err = mbi_irq_gic_domain_alloc(domain, virq + i, hwirq + i); |
| 109 | if (err) | 115 | if (err) |
| @@ -142,7 +148,7 @@ static void mbi_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) | |||
| 142 | msg[0].address_lo = lower_32_bits(mbi_phys_base + GICD_SETSPI_NSR); | 148 | msg[0].address_lo = lower_32_bits(mbi_phys_base + GICD_SETSPI_NSR); |
| 143 | msg[0].data = data->parent_data->hwirq; | 149 | msg[0].data = data->parent_data->hwirq; |
| 144 | 150 | ||
| 145 | iommu_dma_map_msi_msg(data->irq, msg); | 151 | iommu_dma_compose_msi_msg(irq_data_get_msi_desc(data), msg); |
| 146 | } | 152 | } |
| 147 | 153 | ||
| 148 | #ifdef CONFIG_PCI_MSI | 154 | #ifdef CONFIG_PCI_MSI |
| @@ -202,7 +208,7 @@ static void mbi_compose_mbi_msg(struct irq_data *data, struct msi_msg *msg) | |||
| 202 | msg[1].address_lo = lower_32_bits(mbi_phys_base + GICD_CLRSPI_NSR); | 208 | msg[1].address_lo = lower_32_bits(mbi_phys_base + GICD_CLRSPI_NSR); |
| 203 | msg[1].data = data->parent_data->hwirq; | 209 | msg[1].data = data->parent_data->hwirq; |
| 204 | 210 | ||
| 205 | iommu_dma_map_msi_msg(data->irq, &msg[1]); | 211 | iommu_dma_compose_msi_msg(irq_data_get_msi_desc(data), &msg[1]); |
| 206 | } | 212 | } |
| 207 | 213 | ||
| 208 | /* Platform-MSI specific irqchip */ | 214 | /* Platform-MSI specific irqchip */ |
diff --git a/drivers/irqchip/irq-imx-irqsteer.c b/drivers/irqchip/irq-imx-irqsteer.c index 88df3d00052c..290531ec3d61 100644 --- a/drivers/irqchip/irq-imx-irqsteer.c +++ b/drivers/irqchip/irq-imx-irqsteer.c | |||
| @@ -144,7 +144,6 @@ static int imx_irqsteer_probe(struct platform_device *pdev) | |||
| 144 | { | 144 | { |
| 145 | struct device_node *np = pdev->dev.of_node; | 145 | struct device_node *np = pdev->dev.of_node; |
| 146 | struct irqsteer_data *data; | 146 | struct irqsteer_data *data; |
| 147 | struct resource *res; | ||
| 148 | u32 irqs_num; | 147 | u32 irqs_num; |
| 149 | int i, ret; | 148 | int i, ret; |
| 150 | 149 | ||
| @@ -152,8 +151,7 @@ static int imx_irqsteer_probe(struct platform_device *pdev) | |||
| 152 | if (!data) | 151 | if (!data) |
| 153 | return -ENOMEM; | 152 | return -ENOMEM; |
| 154 | 153 | ||
| 155 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 154 | data->regs = devm_platform_ioremap_resource(pdev, 0); |
| 156 | data->regs = devm_ioremap_resource(&pdev->dev, res); | ||
| 157 | if (IS_ERR(data->regs)) { | 155 | if (IS_ERR(data->regs)) { |
| 158 | dev_err(&pdev->dev, "failed to initialize reg\n"); | 156 | dev_err(&pdev->dev, "failed to initialize reg\n"); |
| 159 | return PTR_ERR(data->regs); | 157 | return PTR_ERR(data->regs); |
diff --git a/drivers/irqchip/irq-ls-scfg-msi.c b/drivers/irqchip/irq-ls-scfg-msi.c index c671b3212010..669d29105772 100644 --- a/drivers/irqchip/irq-ls-scfg-msi.c +++ b/drivers/irqchip/irq-ls-scfg-msi.c | |||
| @@ -100,7 +100,7 @@ static void ls_scfg_msi_compose_msg(struct irq_data *data, struct msi_msg *msg) | |||
| 100 | msg->data |= cpumask_first(mask); | 100 | msg->data |= cpumask_first(mask); |
| 101 | } | 101 | } |
| 102 | 102 | ||
| 103 | iommu_dma_map_msi_msg(data->irq, msg); | 103 | iommu_dma_compose_msi_msg(irq_data_get_msi_desc(data), msg); |
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | static int ls_scfg_msi_set_affinity(struct irq_data *irq_data, | 106 | static int ls_scfg_msi_set_affinity(struct irq_data *irq_data, |
| @@ -141,6 +141,7 @@ static int ls_scfg_msi_domain_irq_alloc(struct irq_domain *domain, | |||
| 141 | unsigned int nr_irqs, | 141 | unsigned int nr_irqs, |
| 142 | void *args) | 142 | void *args) |
| 143 | { | 143 | { |
| 144 | msi_alloc_info_t *info = args; | ||
| 144 | struct ls_scfg_msi *msi_data = domain->host_data; | 145 | struct ls_scfg_msi *msi_data = domain->host_data; |
| 145 | int pos, err = 0; | 146 | int pos, err = 0; |
| 146 | 147 | ||
| @@ -157,6 +158,10 @@ static int ls_scfg_msi_domain_irq_alloc(struct irq_domain *domain, | |||
| 157 | if (err) | 158 | if (err) |
| 158 | return err; | 159 | return err; |
| 159 | 160 | ||
| 161 | err = iommu_dma_prepare_msi(info->desc, msi_data->msiir_addr); | ||
| 162 | if (err) | ||
| 163 | return err; | ||
| 164 | |||
| 160 | irq_domain_set_info(domain, virq, pos, | 165 | irq_domain_set_info(domain, virq, pos, |
| 161 | &ls_scfg_msi_parent_chip, msi_data, | 166 | &ls_scfg_msi_parent_chip, msi_data, |
| 162 | handle_simple_irq, NULL, NULL); | 167 | handle_simple_irq, NULL, NULL); |
diff --git a/drivers/irqchip/irq-renesas-intc-irqpin.c b/drivers/irqchip/irq-renesas-intc-irqpin.c index 8c039525703f..04c05a18600c 100644 --- a/drivers/irqchip/irq-renesas-intc-irqpin.c +++ b/drivers/irqchip/irq-renesas-intc-irqpin.c | |||
| @@ -389,10 +389,8 @@ static int intc_irqpin_probe(struct platform_device *pdev) | |||
| 389 | int k; | 389 | int k; |
| 390 | 390 | ||
| 391 | p = devm_kzalloc(dev, sizeof(*p), GFP_KERNEL); | 391 | p = devm_kzalloc(dev, sizeof(*p), GFP_KERNEL); |
| 392 | if (!p) { | 392 | if (!p) |
| 393 | dev_err(dev, "failed to allocate driver data\n"); | ||
| 394 | return -ENOMEM; | 393 | return -ENOMEM; |
| 395 | } | ||
| 396 | 394 | ||
| 397 | /* deal with driver instance configuration */ | 395 | /* deal with driver instance configuration */ |
| 398 | of_property_read_u32(dev->of_node, "sense-bitfield-width", | 396 | of_property_read_u32(dev->of_node, "sense-bitfield-width", |
diff --git a/drivers/irqchip/irq-stm32-exti.c b/drivers/irqchip/irq-stm32-exti.c index 7bd1d4cb2e19..e00f2fa27f00 100644 --- a/drivers/irqchip/irq-stm32-exti.c +++ b/drivers/irqchip/irq-stm32-exti.c | |||
| @@ -14,8 +14,10 @@ | |||
| 14 | #include <linux/irqchip.h> | 14 | #include <linux/irqchip.h> |
| 15 | #include <linux/irqchip/chained_irq.h> | 15 | #include <linux/irqchip/chained_irq.h> |
| 16 | #include <linux/irqdomain.h> | 16 | #include <linux/irqdomain.h> |
| 17 | #include <linux/module.h> | ||
| 17 | #include <linux/of_address.h> | 18 | #include <linux/of_address.h> |
| 18 | #include <linux/of_irq.h> | 19 | #include <linux/of_irq.h> |
| 20 | #include <linux/of_platform.h> | ||
| 19 | #include <linux/syscore_ops.h> | 21 | #include <linux/syscore_ops.h> |
| 20 | 22 | ||
| 21 | #include <dt-bindings/interrupt-controller/arm-gic.h> | 23 | #include <dt-bindings/interrupt-controller/arm-gic.h> |
| @@ -37,12 +39,6 @@ struct stm32_exti_bank { | |||
| 37 | 39 | ||
| 38 | #define UNDEF_REG ~0 | 40 | #define UNDEF_REG ~0 |
| 39 | 41 | ||
| 40 | enum stm32_exti_hwspinlock { | ||
| 41 | HWSPINLOCK_UNKNOWN, | ||
| 42 | HWSPINLOCK_NONE, | ||
| 43 | HWSPINLOCK_READY, | ||
| 44 | }; | ||
| 45 | |||
| 46 | struct stm32_desc_irq { | 42 | struct stm32_desc_irq { |
| 47 | u32 exti; | 43 | u32 exti; |
| 48 | u32 irq_parent; | 44 | u32 irq_parent; |
| @@ -69,8 +65,6 @@ struct stm32_exti_host_data { | |||
| 69 | void __iomem *base; | 65 | void __iomem *base; |
| 70 | struct stm32_exti_chip_data *chips_data; | 66 | struct stm32_exti_chip_data *chips_data; |
| 71 | const struct stm32_exti_drv_data *drv_data; | 67 | const struct stm32_exti_drv_data *drv_data; |
| 72 | struct device_node *node; | ||
| 73 | enum stm32_exti_hwspinlock hwlock_state; | ||
| 74 | struct hwspinlock *hwlock; | 68 | struct hwspinlock *hwlock; |
| 75 | }; | 69 | }; |
| 76 | 70 | ||
| @@ -285,49 +279,27 @@ static int stm32_exti_set_type(struct irq_data *d, | |||
| 285 | 279 | ||
| 286 | static int stm32_exti_hwspin_lock(struct stm32_exti_chip_data *chip_data) | 280 | static int stm32_exti_hwspin_lock(struct stm32_exti_chip_data *chip_data) |
| 287 | { | 281 | { |
| 288 | struct stm32_exti_host_data *host_data = chip_data->host_data; | 282 | int ret, timeout = 0; |
| 289 | struct hwspinlock *hwlock; | ||
| 290 | int id, ret = 0, timeout = 0; | ||
| 291 | |||
| 292 | /* first time, check for hwspinlock availability */ | ||
| 293 | if (unlikely(host_data->hwlock_state == HWSPINLOCK_UNKNOWN)) { | ||
| 294 | id = of_hwspin_lock_get_id(host_data->node, 0); | ||
| 295 | if (id >= 0) { | ||
| 296 | hwlock = hwspin_lock_request_specific(id); | ||
| 297 | if (hwlock) { | ||
| 298 | /* found valid hwspinlock */ | ||
| 299 | host_data->hwlock_state = HWSPINLOCK_READY; | ||
| 300 | host_data->hwlock = hwlock; | ||
| 301 | pr_debug("%s hwspinlock = %d\n", __func__, id); | ||
| 302 | } else { | ||
| 303 | host_data->hwlock_state = HWSPINLOCK_NONE; | ||
| 304 | } | ||
| 305 | } else if (id != -EPROBE_DEFER) { | ||
| 306 | host_data->hwlock_state = HWSPINLOCK_NONE; | ||
| 307 | } else { | ||
| 308 | /* hwspinlock driver shall be ready at that stage */ | ||
| 309 | ret = -EPROBE_DEFER; | ||
| 310 | } | ||
| 311 | } | ||
| 312 | 283 | ||
| 313 | if (likely(host_data->hwlock_state == HWSPINLOCK_READY)) { | 284 | if (!chip_data->host_data->hwlock) |
| 314 | /* | 285 | return 0; |
| 315 | * Use the x_raw API since we are under spin_lock protection. | 286 | |
| 316 | * Do not use the x_timeout API because we are under irq_disable | 287 | /* |
| 317 | * mode (see __setup_irq()) | 288 | * Use the x_raw API since we are under spin_lock protection. |
| 318 | */ | 289 | * Do not use the x_timeout API because we are under irq_disable |
| 319 | do { | 290 | * mode (see __setup_irq()) |
| 320 | ret = hwspin_trylock_raw(host_data->hwlock); | 291 | */ |
| 321 | if (!ret) | 292 | do { |
| 322 | return 0; | 293 | ret = hwspin_trylock_raw(chip_data->host_data->hwlock); |
| 323 | 294 | if (!ret) | |
| 324 | udelay(HWSPNLCK_RETRY_DELAY); | 295 | return 0; |
| 325 | timeout += HWSPNLCK_RETRY_DELAY; | 296 | |
| 326 | } while (timeout < HWSPNLCK_TIMEOUT); | 297 | udelay(HWSPNLCK_RETRY_DELAY); |
| 327 | 298 | timeout += HWSPNLCK_RETRY_DELAY; | |
| 328 | if (ret == -EBUSY) | 299 | } while (timeout < HWSPNLCK_TIMEOUT); |
| 329 | ret = -ETIMEDOUT; | 300 | |
| 330 | } | 301 | if (ret == -EBUSY) |
| 302 | ret = -ETIMEDOUT; | ||
| 331 | 303 | ||
| 332 | if (ret) | 304 | if (ret) |
| 333 | pr_err("%s can't get hwspinlock (%d)\n", __func__, ret); | 305 | pr_err("%s can't get hwspinlock (%d)\n", __func__, ret); |
| @@ -337,7 +309,7 @@ static int stm32_exti_hwspin_lock(struct stm32_exti_chip_data *chip_data) | |||
| 337 | 309 | ||
| 338 | static void stm32_exti_hwspin_unlock(struct stm32_exti_chip_data *chip_data) | 310 | static void stm32_exti_hwspin_unlock(struct stm32_exti_chip_data *chip_data) |
| 339 | { | 311 | { |
| 340 | if (likely(chip_data->host_data->hwlock_state == HWSPINLOCK_READY)) | 312 | if (chip_data->host_data->hwlock) |
| 341 | hwspin_unlock_raw(chip_data->host_data->hwlock); | 313 | hwspin_unlock_raw(chip_data->host_data->hwlock); |
| 342 | } | 314 | } |
| 343 | 315 | ||
| @@ -586,8 +558,7 @@ static int stm32_exti_h_set_affinity(struct irq_data *d, | |||
| 586 | return -EINVAL; | 558 | return -EINVAL; |
| 587 | } | 559 | } |
| 588 | 560 | ||
| 589 | #ifdef CONFIG_PM | 561 | static int __maybe_unused stm32_exti_h_suspend(void) |
| 590 | static int stm32_exti_h_suspend(void) | ||
| 591 | { | 562 | { |
| 592 | struct stm32_exti_chip_data *chip_data; | 563 | struct stm32_exti_chip_data *chip_data; |
| 593 | int i; | 564 | int i; |
| @@ -602,7 +573,7 @@ static int stm32_exti_h_suspend(void) | |||
| 602 | return 0; | 573 | return 0; |
| 603 | } | 574 | } |
| 604 | 575 | ||
| 605 | static void stm32_exti_h_resume(void) | 576 | static void __maybe_unused stm32_exti_h_resume(void) |
| 606 | { | 577 | { |
| 607 | struct stm32_exti_chip_data *chip_data; | 578 | struct stm32_exti_chip_data *chip_data; |
| 608 | int i; | 579 | int i; |
| @@ -616,17 +587,22 @@ static void stm32_exti_h_resume(void) | |||
| 616 | } | 587 | } |
| 617 | 588 | ||
| 618 | static struct syscore_ops stm32_exti_h_syscore_ops = { | 589 | static struct syscore_ops stm32_exti_h_syscore_ops = { |
| 590 | #ifdef CONFIG_PM_SLEEP | ||
| 619 | .suspend = stm32_exti_h_suspend, | 591 | .suspend = stm32_exti_h_suspend, |
| 620 | .resume = stm32_exti_h_resume, | 592 | .resume = stm32_exti_h_resume, |
| 593 | #endif | ||
| 621 | }; | 594 | }; |
| 622 | 595 | ||
| 623 | static void stm32_exti_h_syscore_init(void) | 596 | static void stm32_exti_h_syscore_init(struct stm32_exti_host_data *host_data) |
| 624 | { | 597 | { |
| 598 | stm32_host_data = host_data; | ||
| 625 | register_syscore_ops(&stm32_exti_h_syscore_ops); | 599 | register_syscore_ops(&stm32_exti_h_syscore_ops); |
| 626 | } | 600 | } |
| 627 | #else | 601 | |
| 628 | static inline void stm32_exti_h_syscore_init(void) {} | 602 | static void stm32_exti_h_syscore_deinit(void) |
| 629 | #endif | 603 | { |
| 604 | unregister_syscore_ops(&stm32_exti_h_syscore_ops); | ||
| 605 | } | ||
| 630 | 606 | ||
| 631 | static struct irq_chip stm32_exti_h_chip = { | 607 | static struct irq_chip stm32_exti_h_chip = { |
| 632 | .name = "stm32-exti-h", | 608 | .name = "stm32-exti-h", |
| @@ -683,8 +659,6 @@ stm32_exti_host_data *stm32_exti_host_init(const struct stm32_exti_drv_data *dd, | |||
| 683 | return NULL; | 659 | return NULL; |
| 684 | 660 | ||
| 685 | host_data->drv_data = dd; | 661 | host_data->drv_data = dd; |
| 686 | host_data->node = node; | ||
| 687 | host_data->hwlock_state = HWSPINLOCK_UNKNOWN; | ||
| 688 | host_data->chips_data = kcalloc(dd->bank_nr, | 662 | host_data->chips_data = kcalloc(dd->bank_nr, |
| 689 | sizeof(struct stm32_exti_chip_data), | 663 | sizeof(struct stm32_exti_chip_data), |
| 690 | GFP_KERNEL); | 664 | GFP_KERNEL); |
| @@ -711,7 +685,8 @@ free_host_data: | |||
| 711 | 685 | ||
| 712 | static struct | 686 | static struct |
| 713 | stm32_exti_chip_data *stm32_exti_chip_init(struct stm32_exti_host_data *h_data, | 687 | stm32_exti_chip_data *stm32_exti_chip_init(struct stm32_exti_host_data *h_data, |
| 714 | u32 bank_idx) | 688 | u32 bank_idx, |
| 689 | struct device_node *node) | ||
| 715 | { | 690 | { |
| 716 | const struct stm32_exti_bank *stm32_bank; | 691 | const struct stm32_exti_bank *stm32_bank; |
| 717 | struct stm32_exti_chip_data *chip_data; | 692 | struct stm32_exti_chip_data *chip_data; |
| @@ -731,7 +706,7 @@ stm32_exti_chip_data *stm32_exti_chip_init(struct stm32_exti_host_data *h_data, | |||
| 731 | writel_relaxed(0, base + stm32_bank->imr_ofst); | 706 | writel_relaxed(0, base + stm32_bank->imr_ofst); |
| 732 | writel_relaxed(0, base + stm32_bank->emr_ofst); | 707 | writel_relaxed(0, base + stm32_bank->emr_ofst); |
| 733 | 708 | ||
| 734 | pr_info("%pOF: bank%d\n", h_data->node, bank_idx); | 709 | pr_info("%pOF: bank%d\n", node, bank_idx); |
| 735 | 710 | ||
| 736 | return chip_data; | 711 | return chip_data; |
| 737 | } | 712 | } |
| @@ -771,7 +746,7 @@ static int __init stm32_exti_init(const struct stm32_exti_drv_data *drv_data, | |||
| 771 | struct stm32_exti_chip_data *chip_data; | 746 | struct stm32_exti_chip_data *chip_data; |
| 772 | 747 | ||
| 773 | stm32_bank = drv_data->exti_banks[i]; | 748 | stm32_bank = drv_data->exti_banks[i]; |
| 774 | chip_data = stm32_exti_chip_init(host_data, i); | 749 | chip_data = stm32_exti_chip_init(host_data, i, node); |
| 775 | 750 | ||
| 776 | gc = irq_get_domain_generic_chip(domain, i * IRQS_PER_BANK); | 751 | gc = irq_get_domain_generic_chip(domain, i * IRQS_PER_BANK); |
| 777 | 752 | ||
| @@ -815,50 +790,130 @@ static const struct irq_domain_ops stm32_exti_h_domain_ops = { | |||
| 815 | .xlate = irq_domain_xlate_twocell, | 790 | .xlate = irq_domain_xlate_twocell, |
| 816 | }; | 791 | }; |
| 817 | 792 | ||
| 818 | static int | 793 | static void stm32_exti_remove_irq(void *data) |
| 819 | __init stm32_exti_hierarchy_init(const struct stm32_exti_drv_data *drv_data, | 794 | { |
| 820 | struct device_node *node, | 795 | struct irq_domain *domain = data; |
| 821 | struct device_node *parent) | 796 | |
| 797 | irq_domain_remove(domain); | ||
| 798 | } | ||
| 799 | |||
| 800 | static int stm32_exti_remove(struct platform_device *pdev) | ||
| 801 | { | ||
| 802 | stm32_exti_h_syscore_deinit(); | ||
| 803 | return 0; | ||
| 804 | } | ||
| 805 | |||
| 806 | static int stm32_exti_probe(struct platform_device *pdev) | ||
| 822 | { | 807 | { |
| 808 | int ret, i; | ||
| 809 | struct device *dev = &pdev->dev; | ||
| 810 | struct device_node *np = dev->of_node; | ||
| 823 | struct irq_domain *parent_domain, *domain; | 811 | struct irq_domain *parent_domain, *domain; |
| 824 | struct stm32_exti_host_data *host_data; | 812 | struct stm32_exti_host_data *host_data; |
| 825 | int ret, i; | 813 | const struct stm32_exti_drv_data *drv_data; |
| 814 | struct resource *res; | ||
| 826 | 815 | ||
| 827 | parent_domain = irq_find_host(parent); | 816 | host_data = devm_kzalloc(dev, sizeof(*host_data), GFP_KERNEL); |
| 828 | if (!parent_domain) { | 817 | if (!host_data) |
| 829 | pr_err("interrupt-parent not found\n"); | 818 | return -ENOMEM; |
| 830 | return -EINVAL; | 819 | |
| 820 | /* check for optional hwspinlock which may be not available yet */ | ||
| 821 | ret = of_hwspin_lock_get_id(np, 0); | ||
| 822 | if (ret == -EPROBE_DEFER) | ||
| 823 | /* hwspinlock framework not yet ready */ | ||
| 824 | return ret; | ||
| 825 | |||
| 826 | if (ret >= 0) { | ||
| 827 | host_data->hwlock = devm_hwspin_lock_request_specific(dev, ret); | ||
| 828 | if (!host_data->hwlock) { | ||
| 829 | dev_err(dev, "Failed to request hwspinlock\n"); | ||
| 830 | return -EINVAL; | ||
| 831 | } | ||
| 832 | } else if (ret != -ENOENT) { | ||
| 833 | /* note: ENOENT is a valid case (means 'no hwspinlock') */ | ||
| 834 | dev_err(dev, "Failed to get hwspinlock\n"); | ||
| 835 | return ret; | ||
| 831 | } | 836 | } |
| 832 | 837 | ||
| 833 | host_data = stm32_exti_host_init(drv_data, node); | 838 | /* initialize host_data */ |
| 834 | if (!host_data) | 839 | drv_data = of_device_get_match_data(dev); |
| 840 | if (!drv_data) { | ||
| 841 | dev_err(dev, "no of match data\n"); | ||
| 842 | return -ENODEV; | ||
| 843 | } | ||
| 844 | host_data->drv_data = drv_data; | ||
| 845 | |||
| 846 | host_data->chips_data = devm_kcalloc(dev, drv_data->bank_nr, | ||
| 847 | sizeof(*host_data->chips_data), | ||
| 848 | GFP_KERNEL); | ||
| 849 | if (!host_data->chips_data) | ||
| 835 | return -ENOMEM; | 850 | return -ENOMEM; |
| 836 | 851 | ||
| 852 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 853 | host_data->base = devm_ioremap_resource(dev, res); | ||
| 854 | if (IS_ERR(host_data->base)) { | ||
| 855 | dev_err(dev, "Unable to map registers\n"); | ||
| 856 | return PTR_ERR(host_data->base); | ||
| 857 | } | ||
| 858 | |||
| 837 | for (i = 0; i < drv_data->bank_nr; i++) | 859 | for (i = 0; i < drv_data->bank_nr; i++) |
| 838 | stm32_exti_chip_init(host_data, i); | 860 | stm32_exti_chip_init(host_data, i, np); |
| 861 | |||
| 862 | parent_domain = irq_find_host(of_irq_find_parent(np)); | ||
| 863 | if (!parent_domain) { | ||
| 864 | dev_err(dev, "GIC interrupt-parent not found\n"); | ||
| 865 | return -EINVAL; | ||
| 866 | } | ||
| 839 | 867 | ||
| 840 | domain = irq_domain_add_hierarchy(parent_domain, 0, | 868 | domain = irq_domain_add_hierarchy(parent_domain, 0, |
| 841 | drv_data->bank_nr * IRQS_PER_BANK, | 869 | drv_data->bank_nr * IRQS_PER_BANK, |
| 842 | node, &stm32_exti_h_domain_ops, | 870 | np, &stm32_exti_h_domain_ops, |
| 843 | host_data); | 871 | host_data); |
| 844 | 872 | ||
| 845 | if (!domain) { | 873 | if (!domain) { |
| 846 | pr_err("%pOFn: Could not register exti domain.\n", node); | 874 | dev_err(dev, "Could not register exti domain\n"); |
| 847 | ret = -ENOMEM; | 875 | return -ENOMEM; |
| 848 | goto out_unmap; | ||
| 849 | } | 876 | } |
| 850 | 877 | ||
| 851 | stm32_exti_h_syscore_init(); | 878 | ret = devm_add_action_or_reset(dev, stm32_exti_remove_irq, domain); |
| 879 | if (ret) | ||
| 880 | return ret; | ||
| 881 | |||
| 882 | stm32_exti_h_syscore_init(host_data); | ||
| 852 | 883 | ||
| 853 | return 0; | 884 | return 0; |
| 885 | } | ||
| 854 | 886 | ||
| 855 | out_unmap: | 887 | /* platform driver only for MP1 */ |
| 856 | iounmap(host_data->base); | 888 | static const struct of_device_id stm32_exti_ids[] = { |
| 857 | kfree(host_data->chips_data); | 889 | { .compatible = "st,stm32mp1-exti", .data = &stm32mp1_drv_data}, |
| 858 | kfree(host_data); | 890 | {}, |
| 859 | return ret; | 891 | }; |
| 892 | MODULE_DEVICE_TABLE(of, stm32_exti_ids); | ||
| 893 | |||
| 894 | static struct platform_driver stm32_exti_driver = { | ||
| 895 | .probe = stm32_exti_probe, | ||
| 896 | .remove = stm32_exti_remove, | ||
| 897 | .driver = { | ||
| 898 | .name = "stm32_exti", | ||
| 899 | .of_match_table = stm32_exti_ids, | ||
| 900 | }, | ||
| 901 | }; | ||
| 902 | |||
| 903 | static int __init stm32_exti_arch_init(void) | ||
| 904 | { | ||
| 905 | return platform_driver_register(&stm32_exti_driver); | ||
| 860 | } | 906 | } |
| 861 | 907 | ||
| 908 | static void __exit stm32_exti_arch_exit(void) | ||
| 909 | { | ||
| 910 | return platform_driver_unregister(&stm32_exti_driver); | ||
| 911 | } | ||
| 912 | |||
| 913 | arch_initcall(stm32_exti_arch_init); | ||
| 914 | module_exit(stm32_exti_arch_exit); | ||
| 915 | |||
| 916 | /* no platform driver for F4 and H7 */ | ||
| 862 | static int __init stm32f4_exti_of_init(struct device_node *np, | 917 | static int __init stm32f4_exti_of_init(struct device_node *np, |
| 863 | struct device_node *parent) | 918 | struct device_node *parent) |
| 864 | { | 919 | { |
| @@ -874,11 +929,3 @@ static int __init stm32h7_exti_of_init(struct device_node *np, | |||
| 874 | } | 929 | } |
| 875 | 930 | ||
| 876 | IRQCHIP_DECLARE(stm32h7_exti, "st,stm32h7-exti", stm32h7_exti_of_init); | 931 | IRQCHIP_DECLARE(stm32h7_exti, "st,stm32h7-exti", stm32h7_exti_of_init); |
| 877 | |||
| 878 | static int __init stm32mp1_exti_of_init(struct device_node *np, | ||
| 879 | struct device_node *parent) | ||
| 880 | { | ||
| 881 | return stm32_exti_hierarchy_init(&stm32mp1_drv_data, np, parent); | ||
| 882 | } | ||
| 883 | |||
| 884 | IRQCHIP_DECLARE(stm32mp1_exti, "st,stm32mp1-exti", stm32mp1_exti_of_init); | ||
diff --git a/drivers/irqchip/irq-ti-sci-inta.c b/drivers/irqchip/irq-ti-sci-inta.c new file mode 100644 index 000000000000..011b60a49e3f --- /dev/null +++ b/drivers/irqchip/irq-ti-sci-inta.c | |||
| @@ -0,0 +1,615 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * Texas Instruments' K3 Interrupt Aggregator irqchip driver | ||
| 4 | * | ||
| 5 | * Copyright (C) 2018-2019 Texas Instruments Incorporated - http://www.ti.com/ | ||
| 6 | * Lokesh Vutla <lokeshvutla@ti.com> | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <linux/err.h> | ||
| 10 | #include <linux/io.h> | ||
| 11 | #include <linux/irqchip.h> | ||
| 12 | #include <linux/irqdomain.h> | ||
| 13 | #include <linux/interrupt.h> | ||
| 14 | #include <linux/msi.h> | ||
| 15 | #include <linux/module.h> | ||
| 16 | #include <linux/moduleparam.h> | ||
| 17 | #include <linux/of_address.h> | ||
| 18 | #include <linux/of_irq.h> | ||
| 19 | #include <linux/of_platform.h> | ||
| 20 | #include <linux/irqchip/chained_irq.h> | ||
| 21 | #include <linux/soc/ti/ti_sci_inta_msi.h> | ||
| 22 | #include <linux/soc/ti/ti_sci_protocol.h> | ||
| 23 | #include <asm-generic/msi.h> | ||
| 24 | |||
| 25 | #define TI_SCI_DEV_ID_MASK 0xffff | ||
| 26 | #define TI_SCI_DEV_ID_SHIFT 16 | ||
| 27 | #define TI_SCI_IRQ_ID_MASK 0xffff | ||
| 28 | #define TI_SCI_IRQ_ID_SHIFT 0 | ||
| 29 | #define HWIRQ_TO_DEVID(hwirq) (((hwirq) >> (TI_SCI_DEV_ID_SHIFT)) & \ | ||
| 30 | (TI_SCI_DEV_ID_MASK)) | ||
| 31 | #define HWIRQ_TO_IRQID(hwirq) ((hwirq) & (TI_SCI_IRQ_ID_MASK)) | ||
| 32 | #define TO_HWIRQ(dev, index) ((((dev) & TI_SCI_DEV_ID_MASK) << \ | ||
| 33 | TI_SCI_DEV_ID_SHIFT) | \ | ||
| 34 | ((index) & TI_SCI_IRQ_ID_MASK)) | ||
| 35 | |||
| 36 | #define MAX_EVENTS_PER_VINT 64 | ||
| 37 | #define VINT_ENABLE_SET_OFFSET 0x0 | ||
| 38 | #define VINT_ENABLE_CLR_OFFSET 0x8 | ||
| 39 | #define VINT_STATUS_OFFSET 0x18 | ||
| 40 | |||
| 41 | /** | ||
| 42 | * struct ti_sci_inta_event_desc - Description of an event coming to | ||
| 43 | * Interrupt Aggregator. This serves | ||
| 44 | * as a mapping table for global event, | ||
| 45 | * hwirq and vint bit. | ||
| 46 | * @global_event: Global event number corresponding to this event | ||
| 47 | * @hwirq: Hwirq of the incoming interrupt | ||
| 48 | * @vint_bit: Corresponding vint bit to which this event is attached. | ||
| 49 | */ | ||
| 50 | struct ti_sci_inta_event_desc { | ||
| 51 | u16 global_event; | ||
| 52 | u32 hwirq; | ||
| 53 | u8 vint_bit; | ||
| 54 | }; | ||
| 55 | |||
| 56 | /** | ||
| 57 | * struct ti_sci_inta_vint_desc - Description of a virtual interrupt coming out | ||
| 58 | * of Interrupt Aggregator. | ||
| 59 | * @domain: Pointer to IRQ domain to which this vint belongs. | ||
| 60 | * @list: List entry for the vint list | ||
| 61 | * @event_map: Bitmap to manage the allocation of events to vint. | ||
| 62 | * @events: Array of event descriptors assigned to this vint. | ||
| 63 | * @parent_virq: Linux IRQ number that gets attached to parent | ||
| 64 | * @vint_id: TISCI vint ID | ||
| 65 | */ | ||
| 66 | struct ti_sci_inta_vint_desc { | ||
| 67 | struct irq_domain *domain; | ||
| 68 | struct list_head list; | ||
| 69 | DECLARE_BITMAP(event_map, MAX_EVENTS_PER_VINT); | ||
| 70 | struct ti_sci_inta_event_desc events[MAX_EVENTS_PER_VINT]; | ||
| 71 | unsigned int parent_virq; | ||
| 72 | u16 vint_id; | ||
| 73 | }; | ||
| 74 | |||
| 75 | /** | ||
| 76 | * struct ti_sci_inta_irq_domain - Structure representing a TISCI based | ||
| 77 | * Interrupt Aggregator IRQ domain. | ||
| 78 | * @sci: Pointer to TISCI handle | ||
| 79 | * @vint: TISCI resource pointer representing IA inerrupts. | ||
| 80 | * @global_event: TISCI resource pointer representing global events. | ||
| 81 | * @vint_list: List of the vints active in the system | ||
| 82 | * @vint_mutex: Mutex to protect vint_list | ||
| 83 | * @base: Base address of the memory mapped IO registers | ||
| 84 | * @pdev: Pointer to platform device. | ||
| 85 | */ | ||
| 86 | struct ti_sci_inta_irq_domain { | ||
| 87 | const struct ti_sci_handle *sci; | ||
| 88 | struct ti_sci_resource *vint; | ||
| 89 | struct ti_sci_resource *global_event; | ||
| 90 | struct list_head vint_list; | ||
| 91 | /* Mutex to protect vint list */ | ||
| 92 | struct mutex vint_mutex; | ||
| 93 | void __iomem *base; | ||
| 94 | struct platform_device *pdev; | ||
| 95 | }; | ||
| 96 | |||
| 97 | #define to_vint_desc(e, i) container_of(e, struct ti_sci_inta_vint_desc, \ | ||
| 98 | events[i]) | ||
| 99 | |||
| 100 | /** | ||
| 101 | * ti_sci_inta_irq_handler() - Chained IRQ handler for the vint irqs | ||
| 102 | * @desc: Pointer to irq_desc corresponding to the irq | ||
| 103 | */ | ||
| 104 | static void ti_sci_inta_irq_handler(struct irq_desc *desc) | ||
| 105 | { | ||
| 106 | struct ti_sci_inta_vint_desc *vint_desc; | ||
| 107 | struct ti_sci_inta_irq_domain *inta; | ||
| 108 | struct irq_domain *domain; | ||
| 109 | unsigned int virq, bit; | ||
| 110 | unsigned long val; | ||
| 111 | |||
| 112 | vint_desc = irq_desc_get_handler_data(desc); | ||
| 113 | domain = vint_desc->domain; | ||
| 114 | inta = domain->host_data; | ||
| 115 | |||
| 116 | chained_irq_enter(irq_desc_get_chip(desc), desc); | ||
| 117 | |||
| 118 | val = readq_relaxed(inta->base + vint_desc->vint_id * 0x1000 + | ||
| 119 | VINT_STATUS_OFFSET); | ||
| 120 | |||
| 121 | for_each_set_bit(bit, &val, MAX_EVENTS_PER_VINT) { | ||
| 122 | virq = irq_find_mapping(domain, vint_desc->events[bit].hwirq); | ||
| 123 | if (virq) | ||
| 124 | generic_handle_irq(virq); | ||
| 125 | } | ||
| 126 | |||
| 127 | chained_irq_exit(irq_desc_get_chip(desc), desc); | ||
| 128 | } | ||
| 129 | |||
| 130 | /** | ||
| 131 | * ti_sci_inta_alloc_parent_irq() - Allocate parent irq to Interrupt aggregator | ||
| 132 | * @domain: IRQ domain corresponding to Interrupt Aggregator | ||
| 133 | * | ||
| 134 | * Return 0 if all went well else corresponding error value. | ||
| 135 | */ | ||
| 136 | static struct ti_sci_inta_vint_desc *ti_sci_inta_alloc_parent_irq(struct irq_domain *domain) | ||
| 137 | { | ||
| 138 | struct ti_sci_inta_irq_domain *inta = domain->host_data; | ||
| 139 | struct ti_sci_inta_vint_desc *vint_desc; | ||
| 140 | struct irq_fwspec parent_fwspec; | ||
| 141 | unsigned int parent_virq; | ||
| 142 | u16 vint_id; | ||
| 143 | |||
| 144 | vint_id = ti_sci_get_free_resource(inta->vint); | ||
| 145 | if (vint_id == TI_SCI_RESOURCE_NULL) | ||
| 146 | return ERR_PTR(-EINVAL); | ||
| 147 | |||
| 148 | vint_desc = kzalloc(sizeof(*vint_desc), GFP_KERNEL); | ||
| 149 | if (!vint_desc) | ||
| 150 | return ERR_PTR(-ENOMEM); | ||
| 151 | |||
| 152 | vint_desc->domain = domain; | ||
| 153 | vint_desc->vint_id = vint_id; | ||
| 154 | INIT_LIST_HEAD(&vint_desc->list); | ||
| 155 | |||
| 156 | parent_fwspec.fwnode = of_node_to_fwnode(of_irq_find_parent(dev_of_node(&inta->pdev->dev))); | ||
| 157 | parent_fwspec.param_count = 2; | ||
| 158 | parent_fwspec.param[0] = inta->pdev->id; | ||
| 159 | parent_fwspec.param[1] = vint_desc->vint_id; | ||
| 160 | |||
| 161 | parent_virq = irq_create_fwspec_mapping(&parent_fwspec); | ||
| 162 | if (parent_virq <= 0) { | ||
| 163 | kfree(vint_desc); | ||
| 164 | return ERR_PTR(parent_virq); | ||
| 165 | } | ||
| 166 | vint_desc->parent_virq = parent_virq; | ||
| 167 | |||
| 168 | list_add_tail(&vint_desc->list, &inta->vint_list); | ||
| 169 | irq_set_chained_handler_and_data(vint_desc->parent_virq, | ||
| 170 | ti_sci_inta_irq_handler, vint_desc); | ||
| 171 | |||
| 172 | return vint_desc; | ||
| 173 | } | ||
| 174 | |||
| 175 | /** | ||
| 176 | * ti_sci_inta_alloc_event() - Attach an event to a IA vint. | ||
| 177 | * @vint_desc: Pointer to vint_desc to which the event gets attached | ||
| 178 | * @free_bit: Bit inside vint to which event gets attached | ||
| 179 | * @hwirq: hwirq of the input event | ||
| 180 | * | ||
| 181 | * Return event_desc pointer if all went ok else appropriate error value. | ||
| 182 | */ | ||
| 183 | static struct ti_sci_inta_event_desc *ti_sci_inta_alloc_event(struct ti_sci_inta_vint_desc *vint_desc, | ||
| 184 | u16 free_bit, | ||
| 185 | u32 hwirq) | ||
| 186 | { | ||
| 187 | struct ti_sci_inta_irq_domain *inta = vint_desc->domain->host_data; | ||
| 188 | struct ti_sci_inta_event_desc *event_desc; | ||
| 189 | u16 dev_id, dev_index; | ||
| 190 | int err; | ||
| 191 | |||
| 192 | dev_id = HWIRQ_TO_DEVID(hwirq); | ||
| 193 | dev_index = HWIRQ_TO_IRQID(hwirq); | ||
| 194 | |||
| 195 | event_desc = &vint_desc->events[free_bit]; | ||
| 196 | event_desc->hwirq = hwirq; | ||
| 197 | event_desc->vint_bit = free_bit; | ||
| 198 | event_desc->global_event = ti_sci_get_free_resource(inta->global_event); | ||
| 199 | if (event_desc->global_event == TI_SCI_RESOURCE_NULL) | ||
| 200 | return ERR_PTR(-EINVAL); | ||
| 201 | |||
| 202 | err = inta->sci->ops.rm_irq_ops.set_event_map(inta->sci, | ||
| 203 | dev_id, dev_index, | ||
| 204 | inta->pdev->id, | ||
| 205 | vint_desc->vint_id, | ||
| 206 | event_desc->global_event, | ||
| 207 | free_bit); | ||
| 208 | if (err) | ||
| 209 | goto free_global_event; | ||
| 210 | |||
| 211 | return event_desc; | ||
| 212 | free_global_event: | ||
| 213 | ti_sci_release_resource(inta->global_event, event_desc->global_event); | ||
| 214 | return ERR_PTR(err); | ||
| 215 | } | ||
| 216 | |||
| 217 | /** | ||
| 218 | * ti_sci_inta_alloc_irq() - Allocate an irq within INTA domain | ||
| 219 | * @domain: irq_domain pointer corresponding to INTA | ||
| 220 | * @hwirq: hwirq of the input event | ||
| 221 | * | ||
| 222 | * Note: Allocation happens in the following manner: | ||
| 223 | * - Find a free bit available in any of the vints available in the list. | ||
| 224 | * - If not found, allocate a vint from the vint pool | ||
| 225 | * - Attach the free bit to input hwirq. | ||
| 226 | * Return event_desc if all went ok else appropriate error value. | ||
| 227 | */ | ||
| 228 | static struct ti_sci_inta_event_desc *ti_sci_inta_alloc_irq(struct irq_domain *domain, | ||
| 229 | u32 hwirq) | ||
| 230 | { | ||
| 231 | struct ti_sci_inta_irq_domain *inta = domain->host_data; | ||
| 232 | struct ti_sci_inta_vint_desc *vint_desc = NULL; | ||
| 233 | struct ti_sci_inta_event_desc *event_desc; | ||
| 234 | u16 free_bit; | ||
| 235 | |||
| 236 | mutex_lock(&inta->vint_mutex); | ||
| 237 | list_for_each_entry(vint_desc, &inta->vint_list, list) { | ||
| 238 | free_bit = find_first_zero_bit(vint_desc->event_map, | ||
| 239 | MAX_EVENTS_PER_VINT); | ||
| 240 | if (free_bit != MAX_EVENTS_PER_VINT) { | ||
| 241 | set_bit(free_bit, vint_desc->event_map); | ||
| 242 | goto alloc_event; | ||
| 243 | } | ||
| 244 | } | ||
| 245 | |||
| 246 | /* No free bits available. Allocate a new vint */ | ||
| 247 | vint_desc = ti_sci_inta_alloc_parent_irq(domain); | ||
| 248 | if (IS_ERR(vint_desc)) { | ||
| 249 | mutex_unlock(&inta->vint_mutex); | ||
| 250 | return ERR_PTR(PTR_ERR(vint_desc)); | ||
| 251 | } | ||
| 252 | |||
| 253 | free_bit = find_first_zero_bit(vint_desc->event_map, | ||
| 254 | MAX_EVENTS_PER_VINT); | ||
| 255 | set_bit(free_bit, vint_desc->event_map); | ||
| 256 | |||
| 257 | alloc_event: | ||
| 258 | event_desc = ti_sci_inta_alloc_event(vint_desc, free_bit, hwirq); | ||
| 259 | if (IS_ERR(event_desc)) | ||
| 260 | clear_bit(free_bit, vint_desc->event_map); | ||
| 261 | |||
| 262 | mutex_unlock(&inta->vint_mutex); | ||
| 263 | return event_desc; | ||
| 264 | } | ||
| 265 | |||
| 266 | /** | ||
| 267 | * ti_sci_inta_free_parent_irq() - Free a parent irq to INTA | ||
| 268 | * @inta: Pointer to inta domain. | ||
| 269 | * @vint_desc: Pointer to vint_desc that needs to be freed. | ||
| 270 | */ | ||
| 271 | static void ti_sci_inta_free_parent_irq(struct ti_sci_inta_irq_domain *inta, | ||
| 272 | struct ti_sci_inta_vint_desc *vint_desc) | ||
| 273 | { | ||
| 274 | if (find_first_bit(vint_desc->event_map, MAX_EVENTS_PER_VINT) == MAX_EVENTS_PER_VINT) { | ||
| 275 | list_del(&vint_desc->list); | ||
| 276 | ti_sci_release_resource(inta->vint, vint_desc->vint_id); | ||
| 277 | irq_dispose_mapping(vint_desc->parent_virq); | ||
| 278 | kfree(vint_desc); | ||
| 279 | } | ||
| 280 | } | ||
| 281 | |||
| 282 | /** | ||
| 283 | * ti_sci_inta_free_irq() - Free an IRQ within INTA domain | ||
| 284 | * @event_desc: Pointer to event_desc that needs to be freed. | ||
| 285 | * @hwirq: Hwirq number within INTA domain that needs to be freed | ||
| 286 | */ | ||
| 287 | static void ti_sci_inta_free_irq(struct ti_sci_inta_event_desc *event_desc, | ||
| 288 | u32 hwirq) | ||
| 289 | { | ||
| 290 | struct ti_sci_inta_vint_desc *vint_desc; | ||
| 291 | struct ti_sci_inta_irq_domain *inta; | ||
| 292 | |||
| 293 | vint_desc = to_vint_desc(event_desc, event_desc->vint_bit); | ||
| 294 | inta = vint_desc->domain->host_data; | ||
| 295 | /* free event irq */ | ||
| 296 | mutex_lock(&inta->vint_mutex); | ||
| 297 | inta->sci->ops.rm_irq_ops.free_event_map(inta->sci, | ||
| 298 | HWIRQ_TO_DEVID(hwirq), | ||
| 299 | HWIRQ_TO_IRQID(hwirq), | ||
| 300 | inta->pdev->id, | ||
| 301 | vint_desc->vint_id, | ||
| 302 | event_desc->global_event, | ||
| 303 | event_desc->vint_bit); | ||
| 304 | |||
| 305 | clear_bit(event_desc->vint_bit, vint_desc->event_map); | ||
| 306 | ti_sci_release_resource(inta->global_event, event_desc->global_event); | ||
| 307 | event_desc->global_event = TI_SCI_RESOURCE_NULL; | ||
| 308 | event_desc->hwirq = 0; | ||
| 309 | |||
| 310 | ti_sci_inta_free_parent_irq(inta, vint_desc); | ||
| 311 | mutex_unlock(&inta->vint_mutex); | ||
| 312 | } | ||
| 313 | |||
| 314 | /** | ||
| 315 | * ti_sci_inta_request_resources() - Allocate resources for input irq | ||
| 316 | * @data: Pointer to corresponding irq_data | ||
| 317 | * | ||
| 318 | * Note: This is the core api where the actual allocation happens for input | ||
| 319 | * hwirq. This allocation involves creating a parent irq for vint. | ||
| 320 | * If this is done in irq_domain_ops.alloc() then a deadlock is reached | ||
| 321 | * for allocation. So this allocation is being done in request_resources() | ||
| 322 | * | ||
| 323 | * Return: 0 if all went well else corresponding error. | ||
| 324 | */ | ||
| 325 | static int ti_sci_inta_request_resources(struct irq_data *data) | ||
| 326 | { | ||
| 327 | struct ti_sci_inta_event_desc *event_desc; | ||
| 328 | |||
| 329 | event_desc = ti_sci_inta_alloc_irq(data->domain, data->hwirq); | ||
| 330 | if (IS_ERR(event_desc)) | ||
| 331 | return PTR_ERR(event_desc); | ||
| 332 | |||
| 333 | data->chip_data = event_desc; | ||
| 334 | |||
| 335 | return 0; | ||
| 336 | } | ||
| 337 | |||
| 338 | /** | ||
| 339 | * ti_sci_inta_release_resources - Release resources for input irq | ||
| 340 | * @data: Pointer to corresponding irq_data | ||
| 341 | * | ||
| 342 | * Note: Corresponding to request_resources(), all the unmapping and deletion | ||
| 343 | * of parent vint irqs happens in this api. | ||
| 344 | */ | ||
| 345 | static void ti_sci_inta_release_resources(struct irq_data *data) | ||
| 346 | { | ||
| 347 | struct ti_sci_inta_event_desc *event_desc; | ||
| 348 | |||
| 349 | event_desc = irq_data_get_irq_chip_data(data); | ||
| 350 | ti_sci_inta_free_irq(event_desc, data->hwirq); | ||
| 351 | } | ||
| 352 | |||
| 353 | /** | ||
| 354 | * ti_sci_inta_manage_event() - Control the event based on the offset | ||
| 355 | * @data: Pointer to corresponding irq_data | ||
| 356 | * @offset: register offset using which event is controlled. | ||
| 357 | */ | ||
| 358 | static void ti_sci_inta_manage_event(struct irq_data *data, u32 offset) | ||
| 359 | { | ||
| 360 | struct ti_sci_inta_event_desc *event_desc; | ||
| 361 | struct ti_sci_inta_vint_desc *vint_desc; | ||
| 362 | struct ti_sci_inta_irq_domain *inta; | ||
| 363 | |||
| 364 | event_desc = irq_data_get_irq_chip_data(data); | ||
| 365 | vint_desc = to_vint_desc(event_desc, event_desc->vint_bit); | ||
| 366 | inta = data->domain->host_data; | ||
| 367 | |||
| 368 | writeq_relaxed(BIT(event_desc->vint_bit), | ||
| 369 | inta->base + vint_desc->vint_id * 0x1000 + offset); | ||
| 370 | } | ||
| 371 | |||
| 372 | /** | ||
| 373 | * ti_sci_inta_mask_irq() - Mask an event | ||
| 374 | * @data: Pointer to corresponding irq_data | ||
| 375 | */ | ||
| 376 | static void ti_sci_inta_mask_irq(struct irq_data *data) | ||
| 377 | { | ||
| 378 | ti_sci_inta_manage_event(data, VINT_ENABLE_CLR_OFFSET); | ||
| 379 | } | ||
| 380 | |||
| 381 | /** | ||
| 382 | * ti_sci_inta_unmask_irq() - Unmask an event | ||
| 383 | * @data: Pointer to corresponding irq_data | ||
| 384 | */ | ||
| 385 | static void ti_sci_inta_unmask_irq(struct irq_data *data) | ||
| 386 | { | ||
| 387 | ti_sci_inta_manage_event(data, VINT_ENABLE_SET_OFFSET); | ||
| 388 | } | ||
| 389 | |||
| 390 | /** | ||
| 391 | * ti_sci_inta_ack_irq() - Ack an event | ||
| 392 | * @data: Pointer to corresponding irq_data | ||
| 393 | */ | ||
| 394 | static void ti_sci_inta_ack_irq(struct irq_data *data) | ||
| 395 | { | ||
| 396 | /* | ||
| 397 | * Do not clear the event if hardware is capable of sending | ||
| 398 | * a down event. | ||
| 399 | */ | ||
| 400 | if (irqd_get_trigger_type(data) != IRQF_TRIGGER_HIGH) | ||
| 401 | ti_sci_inta_manage_event(data, VINT_STATUS_OFFSET); | ||
| 402 | } | ||
| 403 | |||
| 404 | static int ti_sci_inta_set_affinity(struct irq_data *d, | ||
| 405 | const struct cpumask *mask_val, bool force) | ||
| 406 | { | ||
| 407 | return -EINVAL; | ||
| 408 | } | ||
| 409 | |||
| 410 | /** | ||
| 411 | * ti_sci_inta_set_type() - Update the trigger type of the irq. | ||
| 412 | * @data: Pointer to corresponding irq_data | ||
| 413 | * @type: Trigger type as specified by user | ||
| 414 | * | ||
| 415 | * Note: This updates the handle_irq callback for level msi. | ||
| 416 | * | ||
| 417 | * Return 0 if all went well else appropriate error. | ||
| 418 | */ | ||
| 419 | static int ti_sci_inta_set_type(struct irq_data *data, unsigned int type) | ||
| 420 | { | ||
| 421 | /* | ||
| 422 | * .alloc default sets handle_edge_irq. But if the user specifies | ||
| 423 | * that IRQ is level MSI, then update the handle to handle_level_irq | ||
| 424 | */ | ||
| 425 | switch (type & IRQ_TYPE_SENSE_MASK) { | ||
| 426 | case IRQF_TRIGGER_HIGH: | ||
| 427 | irq_set_handler_locked(data, handle_level_irq); | ||
| 428 | return 0; | ||
| 429 | case IRQF_TRIGGER_RISING: | ||
| 430 | return 0; | ||
| 431 | default: | ||
| 432 | return -EINVAL; | ||
| 433 | } | ||
| 434 | |||
| 435 | return -EINVAL; | ||
| 436 | } | ||
| 437 | |||
| 438 | static struct irq_chip ti_sci_inta_irq_chip = { | ||
| 439 | .name = "INTA", | ||
| 440 | .irq_ack = ti_sci_inta_ack_irq, | ||
| 441 | .irq_mask = ti_sci_inta_mask_irq, | ||
| 442 | .irq_set_type = ti_sci_inta_set_type, | ||
| 443 | .irq_unmask = ti_sci_inta_unmask_irq, | ||
| 444 | .irq_set_affinity = ti_sci_inta_set_affinity, | ||
| 445 | .irq_request_resources = ti_sci_inta_request_resources, | ||
| 446 | .irq_release_resources = ti_sci_inta_release_resources, | ||
| 447 | }; | ||
| 448 | |||
| 449 | /** | ||
| 450 | * ti_sci_inta_irq_domain_free() - Free an IRQ from the IRQ domain | ||
| 451 | * @domain: Domain to which the irqs belong | ||
| 452 | * @virq: base linux virtual IRQ to be freed. | ||
| 453 | * @nr_irqs: Number of continuous irqs to be freed | ||
| 454 | */ | ||
| 455 | static void ti_sci_inta_irq_domain_free(struct irq_domain *domain, | ||
| 456 | unsigned int virq, unsigned int nr_irqs) | ||
| 457 | { | ||
| 458 | struct irq_data *data = irq_domain_get_irq_data(domain, virq); | ||
| 459 | |||
| 460 | irq_domain_reset_irq_data(data); | ||
| 461 | } | ||
| 462 | |||
| 463 | /** | ||
| 464 | * ti_sci_inta_irq_domain_alloc() - Allocate Interrupt aggregator IRQs | ||
| 465 | * @domain: Point to the interrupt aggregator IRQ domain | ||
| 466 | * @virq: Corresponding Linux virtual IRQ number | ||
| 467 | * @nr_irqs: Continuous irqs to be allocated | ||
| 468 | * @data: Pointer to firmware specifier | ||
| 469 | * | ||
| 470 | * No actual allocation happens here. | ||
| 471 | * | ||
| 472 | * Return 0 if all went well else appropriate error value. | ||
| 473 | */ | ||
| 474 | static int ti_sci_inta_irq_domain_alloc(struct irq_domain *domain, | ||
| 475 | unsigned int virq, unsigned int nr_irqs, | ||
| 476 | void *data) | ||
| 477 | { | ||
| 478 | msi_alloc_info_t *arg = data; | ||
| 479 | |||
| 480 | irq_domain_set_info(domain, virq, arg->hwirq, &ti_sci_inta_irq_chip, | ||
| 481 | NULL, handle_edge_irq, NULL, NULL); | ||
| 482 | |||
| 483 | return 0; | ||
| 484 | } | ||
| 485 | |||
| 486 | static const struct irq_domain_ops ti_sci_inta_irq_domain_ops = { | ||
| 487 | .free = ti_sci_inta_irq_domain_free, | ||
| 488 | .alloc = ti_sci_inta_irq_domain_alloc, | ||
| 489 | }; | ||
| 490 | |||
| 491 | static struct irq_chip ti_sci_inta_msi_irq_chip = { | ||
| 492 | .name = "MSI-INTA", | ||
| 493 | .flags = IRQCHIP_SUPPORTS_LEVEL_MSI, | ||
| 494 | }; | ||
| 495 | |||
| 496 | static void ti_sci_inta_msi_set_desc(msi_alloc_info_t *arg, | ||
| 497 | struct msi_desc *desc) | ||
| 498 | { | ||
| 499 | struct platform_device *pdev = to_platform_device(desc->dev); | ||
| 500 | |||
| 501 | arg->desc = desc; | ||
| 502 | arg->hwirq = TO_HWIRQ(pdev->id, desc->inta.dev_index); | ||
| 503 | } | ||
| 504 | |||
| 505 | static struct msi_domain_ops ti_sci_inta_msi_ops = { | ||
| 506 | .set_desc = ti_sci_inta_msi_set_desc, | ||
| 507 | }; | ||
| 508 | |||
| 509 | static struct msi_domain_info ti_sci_inta_msi_domain_info = { | ||
| 510 | .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | | ||
| 511 | MSI_FLAG_LEVEL_CAPABLE), | ||
| 512 | .ops = &ti_sci_inta_msi_ops, | ||
| 513 | .chip = &ti_sci_inta_msi_irq_chip, | ||
| 514 | }; | ||
| 515 | |||
| 516 | static int ti_sci_inta_irq_domain_probe(struct platform_device *pdev) | ||
| 517 | { | ||
| 518 | struct irq_domain *parent_domain, *domain, *msi_domain; | ||
| 519 | struct device_node *parent_node, *node; | ||
| 520 | struct ti_sci_inta_irq_domain *inta; | ||
| 521 | struct device *dev = &pdev->dev; | ||
| 522 | struct resource *res; | ||
| 523 | int ret; | ||
| 524 | |||
| 525 | node = dev_of_node(dev); | ||
| 526 | parent_node = of_irq_find_parent(node); | ||
| 527 | if (!parent_node) { | ||
| 528 | dev_err(dev, "Failed to get IRQ parent node\n"); | ||
| 529 | return -ENODEV; | ||
| 530 | } | ||
| 531 | |||
| 532 | parent_domain = irq_find_host(parent_node); | ||
| 533 | if (!parent_domain) | ||
| 534 | return -EPROBE_DEFER; | ||
| 535 | |||
| 536 | inta = devm_kzalloc(dev, sizeof(*inta), GFP_KERNEL); | ||
| 537 | if (!inta) | ||
| 538 | return -ENOMEM; | ||
| 539 | |||
| 540 | inta->pdev = pdev; | ||
| 541 | inta->sci = devm_ti_sci_get_by_phandle(dev, "ti,sci"); | ||
| 542 | if (IS_ERR(inta->sci)) { | ||
| 543 | ret = PTR_ERR(inta->sci); | ||
| 544 | if (ret != -EPROBE_DEFER) | ||
| 545 | dev_err(dev, "ti,sci read fail %d\n", ret); | ||
| 546 | inta->sci = NULL; | ||
| 547 | return ret; | ||
| 548 | } | ||
| 549 | |||
| 550 | ret = of_property_read_u32(dev->of_node, "ti,sci-dev-id", &pdev->id); | ||
| 551 | if (ret) { | ||
| 552 | dev_err(dev, "missing 'ti,sci-dev-id' property\n"); | ||
| 553 | return -EINVAL; | ||
| 554 | } | ||
| 555 | |||
| 556 | inta->vint = devm_ti_sci_get_of_resource(inta->sci, dev, pdev->id, | ||
| 557 | "ti,sci-rm-range-vint"); | ||
| 558 | if (IS_ERR(inta->vint)) { | ||
| 559 | dev_err(dev, "VINT resource allocation failed\n"); | ||
| 560 | return PTR_ERR(inta->vint); | ||
| 561 | } | ||
| 562 | |||
| 563 | inta->global_event = devm_ti_sci_get_of_resource(inta->sci, dev, pdev->id, | ||
| 564 | "ti,sci-rm-range-global-event"); | ||
| 565 | if (IS_ERR(inta->global_event)) { | ||
| 566 | dev_err(dev, "Global event resource allocation failed\n"); | ||
| 567 | return PTR_ERR(inta->global_event); | ||
| 568 | } | ||
| 569 | |||
| 570 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 571 | inta->base = devm_ioremap_resource(dev, res); | ||
| 572 | if (IS_ERR(inta->base)) | ||
| 573 | return -ENODEV; | ||
| 574 | |||
| 575 | domain = irq_domain_add_linear(dev_of_node(dev), | ||
| 576 | ti_sci_get_num_resources(inta->vint), | ||
| 577 | &ti_sci_inta_irq_domain_ops, inta); | ||
| 578 | if (!domain) { | ||
| 579 | dev_err(dev, "Failed to allocate IRQ domain\n"); | ||
| 580 | return -ENOMEM; | ||
| 581 | } | ||
| 582 | |||
| 583 | msi_domain = ti_sci_inta_msi_create_irq_domain(of_node_to_fwnode(node), | ||
| 584 | &ti_sci_inta_msi_domain_info, | ||
| 585 | domain); | ||
| 586 | if (!msi_domain) { | ||
| 587 | irq_domain_remove(domain); | ||
| 588 | dev_err(dev, "Failed to allocate msi domain\n"); | ||
| 589 | return -ENOMEM; | ||
| 590 | } | ||
| 591 | |||
| 592 | INIT_LIST_HEAD(&inta->vint_list); | ||
| 593 | mutex_init(&inta->vint_mutex); | ||
| 594 | |||
| 595 | return 0; | ||
| 596 | } | ||
| 597 | |||
| 598 | static const struct of_device_id ti_sci_inta_irq_domain_of_match[] = { | ||
| 599 | { .compatible = "ti,sci-inta", }, | ||
| 600 | { /* sentinel */ }, | ||
| 601 | }; | ||
| 602 | MODULE_DEVICE_TABLE(of, ti_sci_inta_irq_domain_of_match); | ||
| 603 | |||
| 604 | static struct platform_driver ti_sci_inta_irq_domain_driver = { | ||
| 605 | .probe = ti_sci_inta_irq_domain_probe, | ||
| 606 | .driver = { | ||
| 607 | .name = "ti-sci-inta", | ||
| 608 | .of_match_table = ti_sci_inta_irq_domain_of_match, | ||
| 609 | }, | ||
| 610 | }; | ||
| 611 | module_platform_driver(ti_sci_inta_irq_domain_driver); | ||
| 612 | |||
| 613 | MODULE_AUTHOR("Lokesh Vutla <lokeshvutla@ticom>"); | ||
| 614 | MODULE_DESCRIPTION("K3 Interrupt Aggregator driver over TI SCI protocol"); | ||
| 615 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/irqchip/irq-ti-sci-intr.c b/drivers/irqchip/irq-ti-sci-intr.c new file mode 100644 index 000000000000..59d51a20bbd8 --- /dev/null +++ b/drivers/irqchip/irq-ti-sci-intr.c | |||
| @@ -0,0 +1,275 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * Texas Instruments' K3 Interrupt Router irqchip driver | ||
| 4 | * | ||
| 5 | * Copyright (C) 2018-2019 Texas Instruments Incorporated - http://www.ti.com/ | ||
| 6 | * Lokesh Vutla <lokeshvutla@ti.com> | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <linux/err.h> | ||
| 10 | #include <linux/module.h> | ||
| 11 | #include <linux/moduleparam.h> | ||
| 12 | #include <linux/io.h> | ||
| 13 | #include <linux/irqchip.h> | ||
| 14 | #include <linux/irqdomain.h> | ||
| 15 | #include <linux/of_platform.h> | ||
| 16 | #include <linux/of_address.h> | ||
| 17 | #include <linux/of_irq.h> | ||
| 18 | #include <linux/soc/ti/ti_sci_protocol.h> | ||
| 19 | |||
| 20 | #define TI_SCI_DEV_ID_MASK 0xffff | ||
| 21 | #define TI_SCI_DEV_ID_SHIFT 16 | ||
| 22 | #define TI_SCI_IRQ_ID_MASK 0xffff | ||
| 23 | #define TI_SCI_IRQ_ID_SHIFT 0 | ||
| 24 | #define HWIRQ_TO_DEVID(hwirq) (((hwirq) >> (TI_SCI_DEV_ID_SHIFT)) & \ | ||
| 25 | (TI_SCI_DEV_ID_MASK)) | ||
| 26 | #define HWIRQ_TO_IRQID(hwirq) ((hwirq) & (TI_SCI_IRQ_ID_MASK)) | ||
| 27 | #define TO_HWIRQ(dev, index) ((((dev) & TI_SCI_DEV_ID_MASK) << \ | ||
| 28 | TI_SCI_DEV_ID_SHIFT) | \ | ||
| 29 | ((index) & TI_SCI_IRQ_ID_MASK)) | ||
| 30 | |||
| 31 | /** | ||
| 32 | * struct ti_sci_intr_irq_domain - Structure representing a TISCI based | ||
| 33 | * Interrupt Router IRQ domain. | ||
| 34 | * @sci: Pointer to TISCI handle | ||
| 35 | * @dst_irq: TISCI resource pointer representing GIC irq controller. | ||
| 36 | * @dst_id: TISCI device ID of the GIC irq controller. | ||
| 37 | * @type: Specifies the trigger type supported by this Interrupt Router | ||
| 38 | */ | ||
| 39 | struct ti_sci_intr_irq_domain { | ||
| 40 | const struct ti_sci_handle *sci; | ||
| 41 | struct ti_sci_resource *dst_irq; | ||
| 42 | u32 dst_id; | ||
| 43 | u32 type; | ||
| 44 | }; | ||
| 45 | |||
| 46 | static struct irq_chip ti_sci_intr_irq_chip = { | ||
| 47 | .name = "INTR", | ||
| 48 | .irq_eoi = irq_chip_eoi_parent, | ||
| 49 | .irq_mask = irq_chip_mask_parent, | ||
| 50 | .irq_unmask = irq_chip_unmask_parent, | ||
| 51 | .irq_set_type = irq_chip_set_type_parent, | ||
| 52 | .irq_retrigger = irq_chip_retrigger_hierarchy, | ||
| 53 | .irq_set_affinity = irq_chip_set_affinity_parent, | ||
| 54 | }; | ||
| 55 | |||
| 56 | /** | ||
| 57 | * ti_sci_intr_irq_domain_translate() - Retrieve hwirq and type from | ||
| 58 | * IRQ firmware specific handler. | ||
| 59 | * @domain: Pointer to IRQ domain | ||
| 60 | * @fwspec: Pointer to IRQ specific firmware structure | ||
| 61 | * @hwirq: IRQ number identified by hardware | ||
| 62 | * @type: IRQ type | ||
| 63 | * | ||
| 64 | * Return 0 if all went ok else appropriate error. | ||
| 65 | */ | ||
| 66 | static int ti_sci_intr_irq_domain_translate(struct irq_domain *domain, | ||
| 67 | struct irq_fwspec *fwspec, | ||
| 68 | unsigned long *hwirq, | ||
| 69 | unsigned int *type) | ||
| 70 | { | ||
| 71 | struct ti_sci_intr_irq_domain *intr = domain->host_data; | ||
| 72 | |||
| 73 | if (fwspec->param_count != 2) | ||
| 74 | return -EINVAL; | ||
| 75 | |||
| 76 | *hwirq = TO_HWIRQ(fwspec->param[0], fwspec->param[1]); | ||
| 77 | *type = intr->type; | ||
| 78 | |||
| 79 | return 0; | ||
| 80 | } | ||
| 81 | |||
| 82 | /** | ||
| 83 | * ti_sci_intr_irq_domain_free() - Free the specified IRQs from the domain. | ||
| 84 | * @domain: Domain to which the irqs belong | ||
| 85 | * @virq: Linux virtual IRQ to be freed. | ||
| 86 | * @nr_irqs: Number of continuous irqs to be freed | ||
| 87 | */ | ||
| 88 | static void ti_sci_intr_irq_domain_free(struct irq_domain *domain, | ||
| 89 | unsigned int virq, unsigned int nr_irqs) | ||
| 90 | { | ||
| 91 | struct ti_sci_intr_irq_domain *intr = domain->host_data; | ||
| 92 | struct irq_data *data, *parent_data; | ||
| 93 | u16 dev_id, irq_index; | ||
| 94 | |||
| 95 | parent_data = irq_domain_get_irq_data(domain->parent, virq); | ||
| 96 | data = irq_domain_get_irq_data(domain, virq); | ||
| 97 | irq_index = HWIRQ_TO_IRQID(data->hwirq); | ||
| 98 | dev_id = HWIRQ_TO_DEVID(data->hwirq); | ||
| 99 | |||
| 100 | intr->sci->ops.rm_irq_ops.free_irq(intr->sci, dev_id, irq_index, | ||
| 101 | intr->dst_id, parent_data->hwirq); | ||
| 102 | ti_sci_release_resource(intr->dst_irq, parent_data->hwirq); | ||
| 103 | irq_domain_free_irqs_parent(domain, virq, 1); | ||
| 104 | irq_domain_reset_irq_data(data); | ||
| 105 | } | ||
| 106 | |||
| 107 | /** | ||
| 108 | * ti_sci_intr_alloc_gic_irq() - Allocate GIC specific IRQ | ||
| 109 | * @domain: Pointer to the interrupt router IRQ domain | ||
| 110 | * @virq: Corresponding Linux virtual IRQ number | ||
| 111 | * @hwirq: Corresponding hwirq for the IRQ within this IRQ domain | ||
| 112 | * | ||
| 113 | * Returns 0 if all went well else appropriate error pointer. | ||
| 114 | */ | ||
| 115 | static int ti_sci_intr_alloc_gic_irq(struct irq_domain *domain, | ||
| 116 | unsigned int virq, u32 hwirq) | ||
| 117 | { | ||
| 118 | struct ti_sci_intr_irq_domain *intr = domain->host_data; | ||
| 119 | struct irq_fwspec fwspec; | ||
| 120 | u16 dev_id, irq_index; | ||
| 121 | u16 dst_irq; | ||
| 122 | int err; | ||
| 123 | |||
| 124 | dev_id = HWIRQ_TO_DEVID(hwirq); | ||
| 125 | irq_index = HWIRQ_TO_IRQID(hwirq); | ||
| 126 | |||
| 127 | dst_irq = ti_sci_get_free_resource(intr->dst_irq); | ||
| 128 | if (dst_irq == TI_SCI_RESOURCE_NULL) | ||
| 129 | return -EINVAL; | ||
| 130 | |||
| 131 | fwspec.fwnode = domain->parent->fwnode; | ||
| 132 | fwspec.param_count = 3; | ||
| 133 | fwspec.param[0] = 0; /* SPI */ | ||
| 134 | fwspec.param[1] = dst_irq - 32; /* SPI offset */ | ||
| 135 | fwspec.param[2] = intr->type; | ||
| 136 | |||
| 137 | err = irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec); | ||
| 138 | if (err) | ||
| 139 | goto err_irqs; | ||
| 140 | |||
| 141 | err = intr->sci->ops.rm_irq_ops.set_irq(intr->sci, dev_id, irq_index, | ||
| 142 | intr->dst_id, dst_irq); | ||
| 143 | if (err) | ||
| 144 | goto err_msg; | ||
| 145 | |||
| 146 | return 0; | ||
| 147 | |||
| 148 | err_msg: | ||
| 149 | irq_domain_free_irqs_parent(domain, virq, 1); | ||
| 150 | err_irqs: | ||
| 151 | ti_sci_release_resource(intr->dst_irq, dst_irq); | ||
| 152 | return err; | ||
| 153 | } | ||
| 154 | |||
| 155 | /** | ||
| 156 | * ti_sci_intr_irq_domain_alloc() - Allocate Interrupt router IRQs | ||
| 157 | * @domain: Point to the interrupt router IRQ domain | ||
| 158 | * @virq: Corresponding Linux virtual IRQ number | ||
| 159 | * @nr_irqs: Continuous irqs to be allocated | ||
| 160 | * @data: Pointer to firmware specifier | ||
| 161 | * | ||
| 162 | * Return 0 if all went well else appropriate error value. | ||
| 163 | */ | ||
| 164 | static int ti_sci_intr_irq_domain_alloc(struct irq_domain *domain, | ||
| 165 | unsigned int virq, unsigned int nr_irqs, | ||
| 166 | void *data) | ||
| 167 | { | ||
| 168 | struct irq_fwspec *fwspec = data; | ||
| 169 | unsigned long hwirq; | ||
| 170 | unsigned int flags; | ||
| 171 | int err; | ||
| 172 | |||
| 173 | err = ti_sci_intr_irq_domain_translate(domain, fwspec, &hwirq, &flags); | ||
| 174 | if (err) | ||
| 175 | return err; | ||
| 176 | |||
| 177 | err = ti_sci_intr_alloc_gic_irq(domain, virq, hwirq); | ||
| 178 | if (err) | ||
| 179 | return err; | ||
| 180 | |||
| 181 | irq_domain_set_hwirq_and_chip(domain, virq, hwirq, | ||
| 182 | &ti_sci_intr_irq_chip, NULL); | ||
| 183 | |||
| 184 | return 0; | ||
| 185 | } | ||
| 186 | |||
| 187 | static const struct irq_domain_ops ti_sci_intr_irq_domain_ops = { | ||
| 188 | .free = ti_sci_intr_irq_domain_free, | ||
| 189 | .alloc = ti_sci_intr_irq_domain_alloc, | ||
| 190 | .translate = ti_sci_intr_irq_domain_translate, | ||
| 191 | }; | ||
| 192 | |||
| 193 | static int ti_sci_intr_irq_domain_probe(struct platform_device *pdev) | ||
| 194 | { | ||
| 195 | struct irq_domain *parent_domain, *domain; | ||
| 196 | struct ti_sci_intr_irq_domain *intr; | ||
| 197 | struct device_node *parent_node; | ||
| 198 | struct device *dev = &pdev->dev; | ||
| 199 | int ret; | ||
| 200 | |||
| 201 | parent_node = of_irq_find_parent(dev_of_node(dev)); | ||
| 202 | if (!parent_node) { | ||
| 203 | dev_err(dev, "Failed to get IRQ parent node\n"); | ||
| 204 | return -ENODEV; | ||
| 205 | } | ||
| 206 | |||
| 207 | parent_domain = irq_find_host(parent_node); | ||
| 208 | if (!parent_domain) { | ||
| 209 | dev_err(dev, "Failed to find IRQ parent domain\n"); | ||
| 210 | return -ENODEV; | ||
| 211 | } | ||
| 212 | |||
| 213 | intr = devm_kzalloc(dev, sizeof(*intr), GFP_KERNEL); | ||
| 214 | if (!intr) | ||
| 215 | return -ENOMEM; | ||
| 216 | |||
| 217 | ret = of_property_read_u32(dev_of_node(dev), "ti,intr-trigger-type", | ||
| 218 | &intr->type); | ||
| 219 | if (ret) { | ||
| 220 | dev_err(dev, "missing ti,intr-trigger-type property\n"); | ||
| 221 | return -EINVAL; | ||
| 222 | } | ||
| 223 | |||
| 224 | intr->sci = devm_ti_sci_get_by_phandle(dev, "ti,sci"); | ||
| 225 | if (IS_ERR(intr->sci)) { | ||
| 226 | ret = PTR_ERR(intr->sci); | ||
| 227 | if (ret != -EPROBE_DEFER) | ||
| 228 | dev_err(dev, "ti,sci read fail %d\n", ret); | ||
| 229 | intr->sci = NULL; | ||
| 230 | return ret; | ||
| 231 | } | ||
| 232 | |||
| 233 | ret = of_property_read_u32(dev_of_node(dev), "ti,sci-dst-id", | ||
| 234 | &intr->dst_id); | ||
| 235 | if (ret) { | ||
| 236 | dev_err(dev, "missing 'ti,sci-dst-id' property\n"); | ||
| 237 | return -EINVAL; | ||
| 238 | } | ||
| 239 | |||
| 240 | intr->dst_irq = devm_ti_sci_get_of_resource(intr->sci, dev, | ||
| 241 | intr->dst_id, | ||
| 242 | "ti,sci-rm-range-girq"); | ||
| 243 | if (IS_ERR(intr->dst_irq)) { | ||
| 244 | dev_err(dev, "Destination irq resource allocation failed\n"); | ||
| 245 | return PTR_ERR(intr->dst_irq); | ||
| 246 | } | ||
| 247 | |||
| 248 | domain = irq_domain_add_hierarchy(parent_domain, 0, 0, dev_of_node(dev), | ||
| 249 | &ti_sci_intr_irq_domain_ops, intr); | ||
| 250 | if (!domain) { | ||
| 251 | dev_err(dev, "Failed to allocate IRQ domain\n"); | ||
| 252 | return -ENOMEM; | ||
| 253 | } | ||
| 254 | |||
| 255 | return 0; | ||
| 256 | } | ||
| 257 | |||
| 258 | static const struct of_device_id ti_sci_intr_irq_domain_of_match[] = { | ||
| 259 | { .compatible = "ti,sci-intr", }, | ||
| 260 | { /* sentinel */ }, | ||
| 261 | }; | ||
| 262 | MODULE_DEVICE_TABLE(of, ti_sci_intr_irq_domain_of_match); | ||
| 263 | |||
| 264 | static struct platform_driver ti_sci_intr_irq_domain_driver = { | ||
| 265 | .probe = ti_sci_intr_irq_domain_probe, | ||
| 266 | .driver = { | ||
| 267 | .name = "ti-sci-intr", | ||
| 268 | .of_match_table = ti_sci_intr_irq_domain_of_match, | ||
| 269 | }, | ||
| 270 | }; | ||
| 271 | module_platform_driver(ti_sci_intr_irq_domain_driver); | ||
| 272 | |||
| 273 | MODULE_AUTHOR("Lokesh Vutla <lokeshvutla@ticom>"); | ||
| 274 | MODULE_DESCRIPTION("K3 Interrupt Router driver over TI SCI protocol"); | ||
| 275 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/media/common/b2c2/Makefile b/drivers/media/common/b2c2/Makefile index aa2dc2434ee5..0e32b77f349b 100644 --- a/drivers/media/common/b2c2/Makefile +++ b/drivers/media/common/b2c2/Makefile | |||
| @@ -4,5 +4,5 @@ b2c2-flexcop-objs += flexcop-sram.o flexcop-eeprom.o flexcop-misc.o | |||
| 4 | b2c2-flexcop-objs += flexcop-hw-filter.o | 4 | b2c2-flexcop-objs += flexcop-hw-filter.o |
| 5 | obj-$(CONFIG_DVB_B2C2_FLEXCOP) += b2c2-flexcop.o | 5 | obj-$(CONFIG_DVB_B2C2_FLEXCOP) += b2c2-flexcop.o |
| 6 | 6 | ||
| 7 | ccflags-y += -Idrivers/media/dvb-frontends/ | 7 | ccflags-y += -I $(srctree)/drivers/media/dvb-frontends/ |
| 8 | ccflags-y += -Idrivers/media/tuners/ | 8 | ccflags-y += -I $(srctree)/drivers/media/tuners/ |
diff --git a/drivers/media/dvb-frontends/cxd2880/Makefile b/drivers/media/dvb-frontends/cxd2880/Makefile index c6baa4caba19..646598b556d5 100644 --- a/drivers/media/dvb-frontends/cxd2880/Makefile +++ b/drivers/media/dvb-frontends/cxd2880/Makefile | |||
| @@ -14,5 +14,3 @@ cxd2880-objs := cxd2880_common.o \ | |||
| 14 | cxd2880_top.o | 14 | cxd2880_top.o |
| 15 | 15 | ||
| 16 | obj-$(CONFIG_DVB_CXD2880) += cxd2880.o | 16 | obj-$(CONFIG_DVB_CXD2880) += cxd2880.o |
| 17 | |||
| 18 | ccflags-y += -Idrivers/media/dvb-frontends | ||
diff --git a/drivers/media/i2c/smiapp/Makefile b/drivers/media/i2c/smiapp/Makefile index f45a003cbe7e..9f03aefd4fd7 100644 --- a/drivers/media/i2c/smiapp/Makefile +++ b/drivers/media/i2c/smiapp/Makefile | |||
| @@ -2,4 +2,4 @@ smiapp-objs += smiapp-core.o smiapp-regs.o \ | |||
| 2 | smiapp-quirk.o smiapp-limits.o | 2 | smiapp-quirk.o smiapp-limits.o |
| 3 | obj-$(CONFIG_VIDEO_SMIAPP) += smiapp.o | 3 | obj-$(CONFIG_VIDEO_SMIAPP) += smiapp.o |
| 4 | 4 | ||
| 5 | ccflags-y += -Idrivers/media/i2c | 5 | ccflags-y += -I $(srctree)/drivers/media/i2c |
diff --git a/drivers/media/mmc/siano/Makefile b/drivers/media/mmc/siano/Makefile index 5fc345645a80..848548feeb19 100644 --- a/drivers/media/mmc/siano/Makefile +++ b/drivers/media/mmc/siano/Makefile | |||
| @@ -1,4 +1,3 @@ | |||
| 1 | obj-$(CONFIG_SMS_SDIO_DRV) += smssdio.o | 1 | obj-$(CONFIG_SMS_SDIO_DRV) += smssdio.o |
| 2 | 2 | ||
| 3 | ccflags-y += -Idrivers/media/common/siano | 3 | ccflags-y += -I $(srctree)/drivers/media/common/siano |
| 4 | |||
diff --git a/drivers/media/pci/b2c2/Makefile b/drivers/media/pci/b2c2/Makefile index b43b9167db5a..14ed6e441738 100644 --- a/drivers/media/pci/b2c2/Makefile +++ b/drivers/media/pci/b2c2/Makefile | |||
| @@ -6,4 +6,4 @@ endif | |||
| 6 | b2c2-flexcop-pci-objs += flexcop-pci.o | 6 | b2c2-flexcop-pci-objs += flexcop-pci.o |
| 7 | obj-$(CONFIG_DVB_B2C2_FLEXCOP_PCI) += b2c2-flexcop-pci.o | 7 | obj-$(CONFIG_DVB_B2C2_FLEXCOP_PCI) += b2c2-flexcop-pci.o |
| 8 | 8 | ||
| 9 | ccflags-y += -Idrivers/media/common/b2c2/ | 9 | ccflags-y += -I $(srctree)/drivers/media/common/b2c2/ |
diff --git a/drivers/media/pci/bt8xx/Makefile b/drivers/media/pci/bt8xx/Makefile index 7f1c3beb1bbc..69bc0d9c478e 100644 --- a/drivers/media/pci/bt8xx/Makefile +++ b/drivers/media/pci/bt8xx/Makefile | |||
| @@ -6,6 +6,5 @@ bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \ | |||
| 6 | obj-$(CONFIG_VIDEO_BT848) += bttv.o | 6 | obj-$(CONFIG_VIDEO_BT848) += bttv.o |
| 7 | obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o | 7 | obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o |
| 8 | 8 | ||
| 9 | ccflags-y += -Idrivers/media/dvb-frontends | 9 | ccflags-y += -I $(srctree)/drivers/media/dvb-frontends |
| 10 | ccflags-y += -Idrivers/media/common | 10 | ccflags-y += -I $(srctree)/drivers/media/tuners |
| 11 | ccflags-y += -Idrivers/media/tuners | ||
diff --git a/drivers/media/pci/cx18/Makefile b/drivers/media/pci/cx18/Makefile index 9c82c2df05e1..df00ef8b4521 100644 --- a/drivers/media/pci/cx18/Makefile +++ b/drivers/media/pci/cx18/Makefile | |||
| @@ -9,5 +9,5 @@ cx18-alsa-objs := cx18-alsa-main.o cx18-alsa-pcm.o | |||
| 9 | obj-$(CONFIG_VIDEO_CX18) += cx18.o | 9 | obj-$(CONFIG_VIDEO_CX18) += cx18.o |
| 10 | obj-$(CONFIG_VIDEO_CX18_ALSA) += cx18-alsa.o | 10 | obj-$(CONFIG_VIDEO_CX18_ALSA) += cx18-alsa.o |
| 11 | 11 | ||
| 12 | ccflags-y += -Idrivers/media/dvb-frontends | 12 | ccflags-y += -I $(srctree)/drivers/media/dvb-frontends |
| 13 | ccflags-y += -Idrivers/media/tuners | 13 | ccflags-y += -I $(srctree)/drivers/media/tuners |
diff --git a/drivers/media/pci/cx23885/Makefile b/drivers/media/pci/cx23885/Makefile index 130f0aa29ac6..a785169ec368 100644 --- a/drivers/media/pci/cx23885/Makefile +++ b/drivers/media/pci/cx23885/Makefile | |||
| @@ -8,7 +8,7 @@ cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o \ | |||
| 8 | obj-$(CONFIG_VIDEO_CX23885) += cx23885.o | 8 | obj-$(CONFIG_VIDEO_CX23885) += cx23885.o |
| 9 | obj-$(CONFIG_MEDIA_ALTERA_CI) += altera-ci.o | 9 | obj-$(CONFIG_MEDIA_ALTERA_CI) += altera-ci.o |
| 10 | 10 | ||
| 11 | ccflags-y += -Idrivers/media/tuners | 11 | ccflags-y += -I $(srctree)/drivers/media/tuners |
| 12 | ccflags-y += -Idrivers/media/dvb-frontends | 12 | ccflags-y += -I $(srctree)/drivers/media/dvb-frontends |
| 13 | 13 | ||
| 14 | ccflags-y += $(extra-cflags-y) $(extra-cflags-m) | 14 | ccflags-y += $(extra-cflags-y) $(extra-cflags-m) |
diff --git a/drivers/media/pci/cx88/Makefile b/drivers/media/pci/cx88/Makefile index d0f45d652d6e..c2a015869760 100644 --- a/drivers/media/pci/cx88/Makefile +++ b/drivers/media/pci/cx88/Makefile | |||
| @@ -10,5 +10,5 @@ obj-$(CONFIG_VIDEO_CX88_ALSA) += cx88-alsa.o | |||
| 10 | obj-$(CONFIG_VIDEO_CX88_BLACKBIRD) += cx88-blackbird.o | 10 | obj-$(CONFIG_VIDEO_CX88_BLACKBIRD) += cx88-blackbird.o |
| 11 | obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o | 11 | obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o |
| 12 | obj-$(CONFIG_VIDEO_CX88_VP3054) += cx88-vp3054-i2c.o | 12 | obj-$(CONFIG_VIDEO_CX88_VP3054) += cx88-vp3054-i2c.o |
| 13 | ccflags-y += -Idrivers/media/tuners | 13 | ccflags-y += -I $(srctree)/drivers/media/tuners |
| 14 | ccflags-y += -Idrivers/media/dvb-frontends | 14 | ccflags-y += -I $(srctree)/drivers/media/dvb-frontends |
diff --git a/drivers/media/pci/ddbridge/Makefile b/drivers/media/pci/ddbridge/Makefile index 5b6d5bbc38af..2b77c8d0eb2e 100644 --- a/drivers/media/pci/ddbridge/Makefile +++ b/drivers/media/pci/ddbridge/Makefile | |||
| @@ -9,5 +9,5 @@ ddbridge-objs := ddbridge-main.o ddbridge-core.o ddbridge-ci.o \ | |||
| 9 | 9 | ||
| 10 | obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o | 10 | obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o |
| 11 | 11 | ||
| 12 | ccflags-y += -Idrivers/media/dvb-frontends/ | 12 | ccflags-y += -I $(srctree)/drivers/media/dvb-frontends/ |
| 13 | ccflags-y += -Idrivers/media/tuners/ | 13 | ccflags-y += -I $(srctree)/drivers/media/tuners/ |
diff --git a/drivers/media/pci/dm1105/Makefile b/drivers/media/pci/dm1105/Makefile index d22c2547ee86..87e8e8052cdd 100644 --- a/drivers/media/pci/dm1105/Makefile +++ b/drivers/media/pci/dm1105/Makefile | |||
| @@ -1,3 +1,3 @@ | |||
| 1 | obj-$(CONFIG_DVB_DM1105) += dm1105.o | 1 | obj-$(CONFIG_DVB_DM1105) += dm1105.o |
| 2 | 2 | ||
| 3 | ccflags-y += -Idrivers/media/dvb-frontends | 3 | ccflags-y += -I $(srctree)/drivers/media/dvb-frontends |
diff --git a/drivers/media/pci/mantis/Makefile b/drivers/media/pci/mantis/Makefile index b5ef39692cb0..49e82247b618 100644 --- a/drivers/media/pci/mantis/Makefile +++ b/drivers/media/pci/mantis/Makefile | |||
| @@ -26,4 +26,4 @@ obj-$(CONFIG_MANTIS_CORE) += mantis_core.o | |||
| 26 | obj-$(CONFIG_DVB_MANTIS) += mantis.o | 26 | obj-$(CONFIG_DVB_MANTIS) += mantis.o |
| 27 | obj-$(CONFIG_DVB_HOPPER) += hopper.o | 27 | obj-$(CONFIG_DVB_HOPPER) += hopper.o |
| 28 | 28 | ||
| 29 | ccflags-y += -Idrivers/media/dvb-frontends/ | 29 | ccflags-y += -I $(srctree)/drivers/media/dvb-frontends/ |
diff --git a/drivers/media/pci/netup_unidvb/Makefile b/drivers/media/pci/netup_unidvb/Makefile index 944c3e164157..215bdafcc279 100644 --- a/drivers/media/pci/netup_unidvb/Makefile +++ b/drivers/media/pci/netup_unidvb/Makefile | |||
| @@ -6,4 +6,4 @@ netup-unidvb-objs += netup_unidvb_spi.o | |||
| 6 | 6 | ||
| 7 | obj-$(CONFIG_DVB_NETUP_UNIDVB) += netup-unidvb.o | 7 | obj-$(CONFIG_DVB_NETUP_UNIDVB) += netup-unidvb.o |
| 8 | 8 | ||
| 9 | ccflags-y += -Idrivers/media/dvb-frontends | 9 | ccflags-y += -I $(srctree)/drivers/media/dvb-frontends |
diff --git a/drivers/media/pci/ngene/Makefile b/drivers/media/pci/ngene/Makefile index ec450ad19281..5d16090e0677 100644 --- a/drivers/media/pci/ngene/Makefile +++ b/drivers/media/pci/ngene/Makefile | |||
| @@ -7,5 +7,5 @@ ngene-objs := ngene-core.o ngene-i2c.o ngene-cards.o ngene-dvb.o | |||
| 7 | 7 | ||
| 8 | obj-$(CONFIG_DVB_NGENE) += ngene.o | 8 | obj-$(CONFIG_DVB_NGENE) += ngene.o |
| 9 | 9 | ||
| 10 | ccflags-y += -Idrivers/media/dvb-frontends/ | 10 | ccflags-y += -I $(srctree)/drivers/media/dvb-frontends/ |
| 11 | ccflags-y += -Idrivers/media/tuners/ | 11 | ccflags-y += -I $(srctree)/drivers/media/tuners/ |
diff --git a/drivers/media/pci/pluto2/Makefile b/drivers/media/pci/pluto2/Makefile index 3c2aea1ac752..4d21a2c1544d 100644 --- a/drivers/media/pci/pluto2/Makefile +++ b/drivers/media/pci/pluto2/Makefile | |||
| @@ -1,3 +1,3 @@ | |||
| 1 | obj-$(CONFIG_DVB_PLUTO2) += pluto2.o | 1 | obj-$(CONFIG_DVB_PLUTO2) += pluto2.o |
| 2 | 2 | ||
| 3 | ccflags-y += -Idrivers/media/dvb-frontends/ | 3 | ccflags-y += -I $(srctree)/drivers/media/dvb-frontends/ |
diff --git a/drivers/media/pci/pt1/Makefile b/drivers/media/pci/pt1/Makefile index bc491e08dd63..f80a1cd4c0f5 100644 --- a/drivers/media/pci/pt1/Makefile +++ b/drivers/media/pci/pt1/Makefile | |||
| @@ -2,5 +2,5 @@ earth-pt1-objs := pt1.o | |||
| 2 | 2 | ||
| 3 | obj-$(CONFIG_DVB_PT1) += earth-pt1.o | 3 | obj-$(CONFIG_DVB_PT1) += earth-pt1.o |
| 4 | 4 | ||
| 5 | ccflags-y += -Idrivers/media/dvb-frontends | 5 | ccflags-y += -I $(srctree)/drivers/media/dvb-frontends |
| 6 | ccflags-y += -Idrivers/media/tuners | 6 | ccflags-y += -I $(srctree)/drivers/media/tuners |
diff --git a/drivers/media/pci/pt3/Makefile b/drivers/media/pci/pt3/Makefile index 8698d5dfaf52..da6b265f4b39 100644 --- a/drivers/media/pci/pt3/Makefile +++ b/drivers/media/pci/pt3/Makefile | |||
| @@ -4,5 +4,5 @@ earth-pt3-objs += pt3.o pt3_i2c.o pt3_dma.o | |||
| 4 | 4 | ||
| 5 | obj-$(CONFIG_DVB_PT3) += earth-pt3.o | 5 | obj-$(CONFIG_DVB_PT3) += earth-pt3.o |
| 6 | 6 | ||
| 7 | ccflags-y += -Idrivers/media/dvb-frontends | 7 | ccflags-y += -I $(srctree)/drivers/media/dvb-frontends |
| 8 | ccflags-y += -Idrivers/media/tuners | 8 | ccflags-y += -I $(srctree)/drivers/media/tuners |
diff --git a/drivers/media/pci/smipcie/Makefile b/drivers/media/pci/smipcie/Makefile index 214ebfe12cf7..2426b7566553 100644 --- a/drivers/media/pci/smipcie/Makefile +++ b/drivers/media/pci/smipcie/Makefile | |||
| @@ -4,6 +4,5 @@ smipcie-objs := smipcie-main.o smipcie-ir.o | |||
| 4 | 4 | ||
| 5 | obj-$(CONFIG_DVB_SMIPCIE) += smipcie.o | 5 | obj-$(CONFIG_DVB_SMIPCIE) += smipcie.o |
| 6 | 6 | ||
| 7 | ccflags-y += -Idrivers/media/tuners | 7 | ccflags-y += -I $(srctree)/drivers/media/tuners |
| 8 | ccflags-y += -Idrivers/media/dvb-frontends | 8 | ccflags-y += -I $(srctree)/drivers/media/dvb-frontends |
| 9 | |||
diff --git a/drivers/media/pci/ttpci/Makefile b/drivers/media/pci/ttpci/Makefile index 58ca12732aad..9b44c479fcdd 100644 --- a/drivers/media/pci/ttpci/Makefile +++ b/drivers/media/pci/ttpci/Makefile | |||
| @@ -18,5 +18,5 @@ obj-$(CONFIG_DVB_BUDGET_CI) += budget-ci.o | |||
| 18 | obj-$(CONFIG_DVB_BUDGET_PATCH) += budget-patch.o | 18 | obj-$(CONFIG_DVB_BUDGET_PATCH) += budget-patch.o |
| 19 | obj-$(CONFIG_DVB_AV7110) += dvb-ttpci.o | 19 | obj-$(CONFIG_DVB_AV7110) += dvb-ttpci.o |
| 20 | 20 | ||
| 21 | ccflags-y += -Idrivers/media/dvb-frontends/ | 21 | ccflags-y += -I $(srctree)/drivers/media/dvb-frontends/ |
| 22 | ccflags-y += -Idrivers/media/tuners | 22 | ccflags-y += -I $(srctree)/drivers/media/tuners |
diff --git a/drivers/media/platform/sti/c8sectpfe/Makefile b/drivers/media/platform/sti/c8sectpfe/Makefile index 34d69472b6f0..aedfc725cc19 100644 --- a/drivers/media/platform/sti/c8sectpfe/Makefile +++ b/drivers/media/platform/sti/c8sectpfe/Makefile | |||
| @@ -4,6 +4,5 @@ c8sectpfe-y += c8sectpfe-core.o c8sectpfe-common.o c8sectpfe-dvb.o \ | |||
| 4 | 4 | ||
| 5 | obj-$(CONFIG_DVB_C8SECTPFE) += c8sectpfe.o | 5 | obj-$(CONFIG_DVB_C8SECTPFE) += c8sectpfe.o |
| 6 | 6 | ||
| 7 | ccflags-y += -Idrivers/media/common | 7 | ccflags-y += -I $(srctree)/drivers/media/dvb-frontends/ |
| 8 | ccflags-y += -Idrivers/media/dvb-frontends/ | 8 | ccflags-y += -I $(srctree)/drivers/media/tuners/ |
| 9 | ccflags-y += -Idrivers/media/tuners/ | ||
diff --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile index 37e6e8255b57..53c7ae135460 100644 --- a/drivers/media/radio/Makefile +++ b/drivers/media/radio/Makefile | |||
| @@ -36,5 +36,3 @@ obj-$(CONFIG_RADIO_TEA575X) += tea575x.o | |||
| 36 | obj-$(CONFIG_USB_RAREMONO) += radio-raremono.o | 36 | obj-$(CONFIG_USB_RAREMONO) += radio-raremono.o |
| 37 | 37 | ||
| 38 | shark2-objs := radio-shark2.o radio-tea5777.o | 38 | shark2-objs := radio-shark2.o radio-tea5777.o |
| 39 | |||
| 40 | ccflags-y += -Isound | ||
diff --git a/drivers/media/spi/Makefile b/drivers/media/spi/Makefile index 9e536777a330..446e6c567e94 100644 --- a/drivers/media/spi/Makefile +++ b/drivers/media/spi/Makefile | |||
| @@ -1,6 +1,4 @@ | |||
| 1 | obj-$(CONFIG_VIDEO_GS1662) += gs1662.o | 1 | obj-$(CONFIG_VIDEO_GS1662) += gs1662.o |
| 2 | obj-$(CONFIG_CXD2880_SPI_DRV) += cxd2880-spi.o | 2 | obj-$(CONFIG_CXD2880_SPI_DRV) += cxd2880-spi.o |
| 3 | 3 | ||
| 4 | ccflags-y += -Idrivers/media/dvb-core | 4 | ccflags-y += -I $(srctree)/drivers/media/dvb-frontends/cxd2880 |
| 5 | ccflags-y += -Idrivers/media/dvb-frontends | ||
| 6 | ccflags-y += -Idrivers/media/dvb-frontends/cxd2880 | ||
diff --git a/drivers/media/usb/as102/Makefile b/drivers/media/usb/as102/Makefile index b0b319622edb..de671aed5dfc 100644 --- a/drivers/media/usb/as102/Makefile +++ b/drivers/media/usb/as102/Makefile | |||
| @@ -4,4 +4,4 @@ dvb-as102-objs := as102_drv.o as102_fw.o as10x_cmd.o as10x_cmd_stream.o \ | |||
| 4 | 4 | ||
| 5 | obj-$(CONFIG_DVB_AS102) += dvb-as102.o | 5 | obj-$(CONFIG_DVB_AS102) += dvb-as102.o |
| 6 | 6 | ||
| 7 | ccflags-y += -Idrivers/media/dvb-frontends | 7 | ccflags-y += -I $(srctree)/drivers/media/dvb-frontends |
diff --git a/drivers/media/usb/au0828/Makefile b/drivers/media/usb/au0828/Makefile index 5691881c56c0..4347812d101a 100644 --- a/drivers/media/usb/au0828/Makefile +++ b/drivers/media/usb/au0828/Makefile | |||
| @@ -11,7 +11,7 @@ endif | |||
| 11 | 11 | ||
| 12 | obj-$(CONFIG_VIDEO_AU0828) += au0828.o | 12 | obj-$(CONFIG_VIDEO_AU0828) += au0828.o |
| 13 | 13 | ||
| 14 | ccflags-y += -Idrivers/media/tuners | 14 | ccflags-y += -I $(srctree)/drivers/media/tuners |
| 15 | ccflags-y += -Idrivers/media/dvb-frontends | 15 | ccflags-y += -I $(srctree)/drivers/media/dvb-frontends |
| 16 | 16 | ||
| 17 | ccflags-y += $(extra-cflags-y) $(extra-cflags-m) | 17 | ccflags-y += $(extra-cflags-y) $(extra-cflags-m) |
diff --git a/drivers/media/usb/b2c2/Makefile b/drivers/media/usb/b2c2/Makefile index f3cef05f37b6..e7f949d18fbf 100644 --- a/drivers/media/usb/b2c2/Makefile +++ b/drivers/media/usb/b2c2/Makefile | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | b2c2-flexcop-usb-objs := flexcop-usb.o | 1 | b2c2-flexcop-usb-objs := flexcop-usb.o |
| 2 | obj-$(CONFIG_DVB_B2C2_FLEXCOP_USB) += b2c2-flexcop-usb.o | 2 | obj-$(CONFIG_DVB_B2C2_FLEXCOP_USB) += b2c2-flexcop-usb.o |
| 3 | 3 | ||
| 4 | ccflags-y += -Idrivers/media/common/b2c2/ | 4 | ccflags-y += -I $(srctree)/drivers/media/common/b2c2/ |
diff --git a/drivers/media/usb/cx231xx/Makefile b/drivers/media/usb/cx231xx/Makefile index c023d97407de..8acbbcba7d0c 100644 --- a/drivers/media/usb/cx231xx/Makefile +++ b/drivers/media/usb/cx231xx/Makefile | |||
| @@ -9,6 +9,5 @@ obj-$(CONFIG_VIDEO_CX231XX) += cx231xx.o | |||
| 9 | obj-$(CONFIG_VIDEO_CX231XX_ALSA) += cx231xx-alsa.o | 9 | obj-$(CONFIG_VIDEO_CX231XX_ALSA) += cx231xx-alsa.o |
| 10 | obj-$(CONFIG_VIDEO_CX231XX_DVB) += cx231xx-dvb.o | 10 | obj-$(CONFIG_VIDEO_CX231XX_DVB) += cx231xx-dvb.o |
| 11 | 11 | ||
| 12 | ccflags-y += -Idrivers/media/tuners | 12 | ccflags-y += -I $(srctree)/drivers/media/tuners |
| 13 | ccflags-y += -Idrivers/media/dvb-frontends | 13 | ccflags-y += -I $(srctree)/drivers/media/dvb-frontends |
| 14 | ccflags-y += -Idrivers/media/usb/dvb-usb | ||
diff --git a/drivers/media/usb/em28xx/Makefile b/drivers/media/usb/em28xx/Makefile index 8a224007d755..8c2fc3104561 100644 --- a/drivers/media/usb/em28xx/Makefile +++ b/drivers/media/usb/em28xx/Makefile | |||
| @@ -11,5 +11,5 @@ obj-$(CONFIG_VIDEO_EM28XX_ALSA) += em28xx-alsa.o | |||
| 11 | obj-$(CONFIG_VIDEO_EM28XX_DVB) += em28xx-dvb.o | 11 | obj-$(CONFIG_VIDEO_EM28XX_DVB) += em28xx-dvb.o |
| 12 | obj-$(CONFIG_VIDEO_EM28XX_RC) += em28xx-rc.o | 12 | obj-$(CONFIG_VIDEO_EM28XX_RC) += em28xx-rc.o |
| 13 | 13 | ||
| 14 | ccflags-y += -Idrivers/media/tuners | 14 | ccflags-y += -I $(srctree)/drivers/media/tuners |
| 15 | ccflags-y += -Idrivers/media/dvb-frontends | 15 | ccflags-y += -I $(srctree)/drivers/media/dvb-frontends |
diff --git a/drivers/media/usb/go7007/Makefile b/drivers/media/usb/go7007/Makefile index 3d95bbc4192c..712a3507f195 100644 --- a/drivers/media/usb/go7007/Makefile +++ b/drivers/media/usb/go7007/Makefile | |||
| @@ -9,4 +9,4 @@ go7007-y := go7007-v4l2.o go7007-driver.o go7007-i2c.o go7007-fw.o \ | |||
| 9 | 9 | ||
| 10 | s2250-y := s2250-board.o | 10 | s2250-y := s2250-board.o |
| 11 | 11 | ||
| 12 | ccflags-$(CONFIG_VIDEO_GO7007_LOADER:m=y) += -Idrivers/media/common | 12 | ccflags-$(CONFIG_VIDEO_GO7007_LOADER:m=y) += -I $(srctree)/drivers/media/common |
diff --git a/drivers/media/usb/pvrusb2/Makefile b/drivers/media/usb/pvrusb2/Makefile index 9facf6873404..2e71afc4f6de 100644 --- a/drivers/media/usb/pvrusb2/Makefile +++ b/drivers/media/usb/pvrusb2/Makefile | |||
| @@ -17,5 +17,5 @@ pvrusb2-objs := pvrusb2-i2c-core.o \ | |||
| 17 | 17 | ||
| 18 | obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2.o | 18 | obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2.o |
| 19 | 19 | ||
| 20 | ccflags-y += -Idrivers/media/tuners | 20 | ccflags-y += -I $(srctree)/drivers/media/tuners |
| 21 | ccflags-y += -Idrivers/media/dvb-frontends | 21 | ccflags-y += -I $(srctree)/drivers/media/dvb-frontends |
diff --git a/drivers/media/usb/siano/Makefile b/drivers/media/usb/siano/Makefile index 7d48864e2782..ba56e9818489 100644 --- a/drivers/media/usb/siano/Makefile +++ b/drivers/media/usb/siano/Makefile | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | obj-$(CONFIG_SMS_USB_DRV) += smsusb.o | 1 | obj-$(CONFIG_SMS_USB_DRV) += smsusb.o |
| 2 | 2 | ||
| 3 | ccflags-y += -Idrivers/media/common/siano | 3 | ccflags-y += -I $(srctree)/drivers/media/common/siano |
| 4 | ccflags-y += $(extra-cflags-y) $(extra-cflags-m) | 4 | ccflags-y += $(extra-cflags-y) $(extra-cflags-m) |
| 5 | 5 | ||
diff --git a/drivers/media/usb/tm6000/Makefile b/drivers/media/usb/tm6000/Makefile index 744c039e621a..75247a02a485 100644 --- a/drivers/media/usb/tm6000/Makefile +++ b/drivers/media/usb/tm6000/Makefile | |||
| @@ -10,5 +10,5 @@ obj-$(CONFIG_VIDEO_TM6000) += tm6000.o | |||
| 10 | obj-$(CONFIG_VIDEO_TM6000_ALSA) += tm6000-alsa.o | 10 | obj-$(CONFIG_VIDEO_TM6000_ALSA) += tm6000-alsa.o |
| 11 | obj-$(CONFIG_VIDEO_TM6000_DVB) += tm6000-dvb.o | 11 | obj-$(CONFIG_VIDEO_TM6000_DVB) += tm6000-dvb.o |
| 12 | 12 | ||
| 13 | ccflags-y += -Idrivers/media/tuners | 13 | ccflags-y += -I $(srctree)/drivers/media/tuners |
| 14 | ccflags-y += -Idrivers/media/dvb-frontends | 14 | ccflags-y += -I $(srctree)/drivers/media/dvb-frontends |
diff --git a/drivers/media/usb/ttusb-budget/Makefile b/drivers/media/usb/ttusb-budget/Makefile index fe4372dddd0e..37847d773921 100644 --- a/drivers/media/usb/ttusb-budget/Makefile +++ b/drivers/media/usb/ttusb-budget/Makefile | |||
| @@ -1,3 +1,3 @@ | |||
| 1 | obj-$(CONFIG_DVB_TTUSB_BUDGET) += dvb-ttusb-budget.o | 1 | obj-$(CONFIG_DVB_TTUSB_BUDGET) += dvb-ttusb-budget.o |
| 2 | 2 | ||
| 3 | ccflags-y += -Idrivers/media/dvb-frontends | 3 | ccflags-y += -I $(srctree)/drivers/media/dvb-frontends |
diff --git a/drivers/media/usb/usbvision/Makefile b/drivers/media/usb/usbvision/Makefile index 494d030b4979..e8e5eda08b6f 100644 --- a/drivers/media/usb/usbvision/Makefile +++ b/drivers/media/usb/usbvision/Makefile | |||
| @@ -1,5 +1,3 @@ | |||
| 1 | usbvision-objs := usbvision-core.o usbvision-video.o usbvision-i2c.o usbvision-cards.o | 1 | usbvision-objs := usbvision-core.o usbvision-video.o usbvision-i2c.o usbvision-cards.o |
| 2 | 2 | ||
| 3 | obj-$(CONFIG_VIDEO_USBVISION) += usbvision.o | 3 | obj-$(CONFIG_VIDEO_USBVISION) += usbvision.o |
| 4 | |||
| 5 | ccflags-y += -Idrivers/media/tuners | ||
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index b80cb6af0cb4..6a0365b2332c 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig | |||
| @@ -59,30 +59,6 @@ config ATMEL_TCLIB | |||
| 59 | blocks found on many Atmel processors. This facilitates using | 59 | blocks found on many Atmel processors. This facilitates using |
| 60 | these blocks by different drivers despite processor differences. | 60 | these blocks by different drivers despite processor differences. |
| 61 | 61 | ||
| 62 | config ATMEL_TCB_CLKSRC | ||
| 63 | bool "TC Block Clocksource" | ||
| 64 | depends on ATMEL_TCLIB | ||
| 65 | default y | ||
| 66 | help | ||
| 67 | Select this to get a high precision clocksource based on a | ||
| 68 | TC block with a 5+ MHz base clock rate. Two timer channels | ||
| 69 | are combined to make a single 32-bit timer. | ||
| 70 | |||
| 71 | When GENERIC_CLOCKEVENTS is defined, the third timer channel | ||
| 72 | may be used as a clock event device supporting oneshot mode | ||
| 73 | (delays of up to two seconds) based on the 32 KiHz clock. | ||
| 74 | |||
| 75 | config ATMEL_TCB_CLKSRC_BLOCK | ||
| 76 | int | ||
| 77 | depends on ATMEL_TCB_CLKSRC | ||
| 78 | default 0 | ||
| 79 | range 0 1 | ||
| 80 | help | ||
| 81 | Some chips provide more than one TC block, so you have the | ||
| 82 | choice of which one to use for the clock framework. The other | ||
| 83 | TC can be used for other purposes, such as PWM generation and | ||
| 84 | interval timing. | ||
| 85 | |||
| 86 | config DUMMY_IRQ | 62 | config DUMMY_IRQ |
| 87 | tristate "Dummy IRQ handler" | 63 | tristate "Dummy IRQ handler" |
| 88 | default n | 64 | default n |
diff --git a/drivers/misc/atmel_tclib.c b/drivers/misc/atmel_tclib.c index ac24a4bd63f7..2c6850ef0e9c 100644 --- a/drivers/misc/atmel_tclib.c +++ b/drivers/misc/atmel_tclib.c | |||
| @@ -1,4 +1,3 @@ | |||
| 1 | #include <linux/atmel_tc.h> | ||
| 2 | #include <linux/clk.h> | 1 | #include <linux/clk.h> |
| 3 | #include <linux/err.h> | 2 | #include <linux/err.h> |
| 4 | #include <linux/init.h> | 3 | #include <linux/init.h> |
| @@ -10,6 +9,7 @@ | |||
| 10 | #include <linux/slab.h> | 9 | #include <linux/slab.h> |
| 11 | #include <linux/export.h> | 10 | #include <linux/export.h> |
| 12 | #include <linux/of.h> | 11 | #include <linux/of.h> |
| 12 | #include <soc/at91/atmel_tcb.h> | ||
| 13 | 13 | ||
| 14 | /* | 14 | /* |
| 15 | * This is a thin library to solve the problem of how to portably allocate | 15 | * This is a thin library to solve the problem of how to portably allocate |
| @@ -111,6 +111,9 @@ static int __init tc_probe(struct platform_device *pdev) | |||
| 111 | struct resource *r; | 111 | struct resource *r; |
| 112 | unsigned int i; | 112 | unsigned int i; |
| 113 | 113 | ||
| 114 | if (of_get_child_count(pdev->dev.of_node)) | ||
| 115 | return -EBUSY; | ||
| 116 | |||
| 114 | irq = platform_get_irq(pdev, 0); | 117 | irq = platform_get_irq(pdev, 0); |
| 115 | if (irq < 0) | 118 | if (irq < 0) |
| 116 | return -EINVAL; | 119 | return -EINVAL; |
diff --git a/drivers/net/ethernet/chelsio/libcxgb/Makefile b/drivers/net/ethernet/chelsio/libcxgb/Makefile index 2534e30a1560..441913b5221e 100644 --- a/drivers/net/ethernet/chelsio/libcxgb/Makefile +++ b/drivers/net/ethernet/chelsio/libcxgb/Makefile | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | ccflags-y := -Idrivers/net/ethernet/chelsio/cxgb4 | 1 | ccflags-y := -I $(srctree)/$(src)/../cxgb4 |
| 2 | 2 | ||
| 3 | obj-$(CONFIG_CHELSIO_LIB) += libcxgb.o | 3 | obj-$(CONFIG_CHELSIO_LIB) += libcxgb.o |
| 4 | 4 | ||
diff --git a/drivers/pwm/pwm-atmel-tcb.c b/drivers/pwm/pwm-atmel-tcb.c index 0d0f8376bc35..7da1fdb4d269 100644 --- a/drivers/pwm/pwm-atmel-tcb.c +++ b/drivers/pwm/pwm-atmel-tcb.c | |||
| @@ -17,10 +17,10 @@ | |||
| 17 | #include <linux/ioport.h> | 17 | #include <linux/ioport.h> |
| 18 | #include <linux/io.h> | 18 | #include <linux/io.h> |
| 19 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
| 20 | #include <linux/atmel_tc.h> | ||
| 21 | #include <linux/pwm.h> | 20 | #include <linux/pwm.h> |
| 22 | #include <linux/of_device.h> | 21 | #include <linux/of_device.h> |
| 23 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
| 23 | #include <soc/at91/atmel_tcb.h> | ||
| 24 | 24 | ||
| 25 | #define NPWM 6 | 25 | #define NPWM 6 |
| 26 | 26 | ||
diff --git a/drivers/soc/fsl/qe/gpio.c b/drivers/soc/fsl/qe/gpio.c index 819bed0f5667..51b3a47b5a55 100644 --- a/drivers/soc/fsl/qe/gpio.c +++ b/drivers/soc/fsl/qe/gpio.c | |||
| @@ -179,8 +179,10 @@ struct qe_pin *qe_pin_request(struct device_node *np, int index) | |||
| 179 | if (err < 0) | 179 | if (err < 0) |
| 180 | goto err0; | 180 | goto err0; |
| 181 | gc = gpio_to_chip(err); | 181 | gc = gpio_to_chip(err); |
| 182 | if (WARN_ON(!gc)) | 182 | if (WARN_ON(!gc)) { |
| 183 | err = -ENODEV; | ||
| 183 | goto err0; | 184 | goto err0; |
| 185 | } | ||
| 184 | 186 | ||
| 185 | if (!of_device_is_compatible(gc->of_node, "fsl,mpc8323-qe-pario-bank")) { | 187 | if (!of_device_is_compatible(gc->of_node, "fsl,mpc8323-qe-pario-bank")) { |
| 186 | pr_debug("%s: tried to get a non-qe pin\n", __func__); | 188 | pr_debug("%s: tried to get a non-qe pin\n", __func__); |
diff --git a/drivers/soc/ixp4xx/ixp4xx-qmgr.c b/drivers/soc/ixp4xx/ixp4xx-qmgr.c index 13a8a13c9b01..bb90670ec160 100644 --- a/drivers/soc/ixp4xx/ixp4xx-qmgr.c +++ b/drivers/soc/ixp4xx/ixp4xx-qmgr.c | |||
| @@ -385,8 +385,8 @@ static int ixp4xx_qmgr_probe(struct platform_device *pdev) | |||
| 385 | if (!res) | 385 | if (!res) |
| 386 | return -ENODEV; | 386 | return -ENODEV; |
| 387 | qmgr_regs = devm_ioremap_resource(dev, res); | 387 | qmgr_regs = devm_ioremap_resource(dev, res); |
| 388 | if (!qmgr_regs) | 388 | if (IS_ERR(qmgr_regs)) |
| 389 | return -ENOMEM; | 389 | return PTR_ERR(qmgr_regs); |
| 390 | 390 | ||
| 391 | irq1 = platform_get_irq(pdev, 0); | 391 | irq1 = platform_get_irq(pdev, 0); |
| 392 | if (irq1 <= 0) | 392 | if (irq1 <= 0) |
diff --git a/drivers/soc/ti/Kconfig b/drivers/soc/ti/Kconfig index 57960e92ebe0..dbd6c60b81db 100644 --- a/drivers/soc/ti/Kconfig +++ b/drivers/soc/ti/Kconfig | |||
| @@ -74,4 +74,10 @@ config TI_SCI_PM_DOMAINS | |||
| 74 | called ti_sci_pm_domains. Note this is needed early in boot before | 74 | called ti_sci_pm_domains. Note this is needed early in boot before |
| 75 | rootfs may be available. | 75 | rootfs may be available. |
| 76 | 76 | ||
| 77 | config TI_SCI_INTA_MSI_DOMAIN | ||
| 78 | bool | ||
| 79 | select GENERIC_MSI_IRQ_DOMAIN | ||
| 80 | help | ||
| 81 | Driver to enable Interrupt Aggregator specific MSI Domain. | ||
| 82 | |||
| 77 | endif # SOC_TI | 83 | endif # SOC_TI |
diff --git a/drivers/soc/ti/Makefile b/drivers/soc/ti/Makefile index a22edc0b258a..b3868d392d4f 100644 --- a/drivers/soc/ti/Makefile +++ b/drivers/soc/ti/Makefile | |||
| @@ -8,3 +8,4 @@ obj-$(CONFIG_KEYSTONE_NAVIGATOR_DMA) += knav_dma.o | |||
| 8 | obj-$(CONFIG_AMX3_PM) += pm33xx.o | 8 | obj-$(CONFIG_AMX3_PM) += pm33xx.o |
| 9 | obj-$(CONFIG_WKUP_M3_IPC) += wkup_m3_ipc.o | 9 | obj-$(CONFIG_WKUP_M3_IPC) += wkup_m3_ipc.o |
| 10 | obj-$(CONFIG_TI_SCI_PM_DOMAINS) += ti_sci_pm_domains.o | 10 | obj-$(CONFIG_TI_SCI_PM_DOMAINS) += ti_sci_pm_domains.o |
| 11 | obj-$(CONFIG_TI_SCI_INTA_MSI_DOMAIN) += ti_sci_inta_msi.o | ||
diff --git a/drivers/soc/ti/ti_sci_inta_msi.c b/drivers/soc/ti/ti_sci_inta_msi.c new file mode 100644 index 000000000000..0eb9462f609e --- /dev/null +++ b/drivers/soc/ti/ti_sci_inta_msi.c | |||
| @@ -0,0 +1,146 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * Texas Instruments' K3 Interrupt Aggregator MSI bus | ||
| 4 | * | ||
| 5 | * Copyright (C) 2018-2019 Texas Instruments Incorporated - http://www.ti.com/ | ||
| 6 | * Lokesh Vutla <lokeshvutla@ti.com> | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <linux/irq.h> | ||
| 10 | #include <linux/irqdomain.h> | ||
| 11 | #include <linux/msi.h> | ||
| 12 | #include <linux/of_address.h> | ||
| 13 | #include <linux/of_device.h> | ||
| 14 | #include <linux/of_irq.h> | ||
| 15 | #include <linux/soc/ti/ti_sci_inta_msi.h> | ||
| 16 | #include <linux/soc/ti/ti_sci_protocol.h> | ||
| 17 | |||
| 18 | static void ti_sci_inta_msi_write_msg(struct irq_data *data, | ||
| 19 | struct msi_msg *msg) | ||
| 20 | { | ||
| 21 | /* Nothing to do */ | ||
| 22 | } | ||
| 23 | |||
| 24 | static void ti_sci_inta_msi_compose_msi_msg(struct irq_data *data, | ||
| 25 | struct msi_msg *msg) | ||
| 26 | { | ||
| 27 | /* Nothing to do */ | ||
| 28 | } | ||
| 29 | |||
| 30 | static void ti_sci_inta_msi_update_chip_ops(struct msi_domain_info *info) | ||
| 31 | { | ||
| 32 | struct irq_chip *chip = info->chip; | ||
| 33 | |||
| 34 | if (WARN_ON(!chip)) | ||
| 35 | return; | ||
| 36 | |||
| 37 | chip->irq_request_resources = irq_chip_request_resources_parent; | ||
| 38 | chip->irq_release_resources = irq_chip_release_resources_parent; | ||
| 39 | chip->irq_compose_msi_msg = ti_sci_inta_msi_compose_msi_msg; | ||
| 40 | chip->irq_write_msi_msg = ti_sci_inta_msi_write_msg; | ||
| 41 | chip->irq_set_type = irq_chip_set_type_parent; | ||
| 42 | chip->irq_unmask = irq_chip_unmask_parent; | ||
| 43 | chip->irq_mask = irq_chip_mask_parent; | ||
| 44 | chip->irq_ack = irq_chip_ack_parent; | ||
| 45 | } | ||
| 46 | |||
| 47 | struct irq_domain *ti_sci_inta_msi_create_irq_domain(struct fwnode_handle *fwnode, | ||
| 48 | struct msi_domain_info *info, | ||
| 49 | struct irq_domain *parent) | ||
| 50 | { | ||
| 51 | struct irq_domain *domain; | ||
| 52 | |||
| 53 | ti_sci_inta_msi_update_chip_ops(info); | ||
| 54 | |||
| 55 | domain = msi_create_irq_domain(fwnode, info, parent); | ||
| 56 | if (domain) | ||
| 57 | irq_domain_update_bus_token(domain, DOMAIN_BUS_TI_SCI_INTA_MSI); | ||
| 58 | |||
| 59 | return domain; | ||
| 60 | } | ||
| 61 | EXPORT_SYMBOL_GPL(ti_sci_inta_msi_create_irq_domain); | ||
| 62 | |||
| 63 | static void ti_sci_inta_msi_free_descs(struct device *dev) | ||
| 64 | { | ||
| 65 | struct msi_desc *desc, *tmp; | ||
| 66 | |||
| 67 | list_for_each_entry_safe(desc, tmp, dev_to_msi_list(dev), list) { | ||
| 68 | list_del(&desc->list); | ||
| 69 | free_msi_entry(desc); | ||
| 70 | } | ||
| 71 | } | ||
| 72 | |||
| 73 | static int ti_sci_inta_msi_alloc_descs(struct device *dev, | ||
| 74 | struct ti_sci_resource *res) | ||
| 75 | { | ||
| 76 | struct msi_desc *msi_desc; | ||
| 77 | int set, i, count = 0; | ||
| 78 | |||
| 79 | for (set = 0; set < res->sets; set++) { | ||
| 80 | for (i = 0; i < res->desc[set].num; i++) { | ||
| 81 | msi_desc = alloc_msi_entry(dev, 1, NULL); | ||
| 82 | if (!msi_desc) { | ||
| 83 | ti_sci_inta_msi_free_descs(dev); | ||
| 84 | return -ENOMEM; | ||
| 85 | } | ||
| 86 | |||
| 87 | msi_desc->inta.dev_index = res->desc[set].start + i; | ||
| 88 | INIT_LIST_HEAD(&msi_desc->list); | ||
| 89 | list_add_tail(&msi_desc->list, dev_to_msi_list(dev)); | ||
| 90 | count++; | ||
| 91 | } | ||
| 92 | } | ||
| 93 | |||
| 94 | return count; | ||
| 95 | } | ||
| 96 | |||
| 97 | int ti_sci_inta_msi_domain_alloc_irqs(struct device *dev, | ||
| 98 | struct ti_sci_resource *res) | ||
| 99 | { | ||
| 100 | struct platform_device *pdev = to_platform_device(dev); | ||
| 101 | struct irq_domain *msi_domain; | ||
| 102 | int ret, nvec; | ||
| 103 | |||
| 104 | msi_domain = dev_get_msi_domain(dev); | ||
| 105 | if (!msi_domain) | ||
| 106 | return -EINVAL; | ||
| 107 | |||
| 108 | if (pdev->id < 0) | ||
| 109 | return -ENODEV; | ||
| 110 | |||
| 111 | nvec = ti_sci_inta_msi_alloc_descs(dev, res); | ||
| 112 | if (nvec <= 0) | ||
| 113 | return nvec; | ||
| 114 | |||
| 115 | ret = msi_domain_alloc_irqs(msi_domain, dev, nvec); | ||
| 116 | if (ret) { | ||
| 117 | dev_err(dev, "Failed to allocate IRQs %d\n", ret); | ||
| 118 | goto cleanup; | ||
| 119 | } | ||
| 120 | |||
| 121 | return 0; | ||
| 122 | |||
| 123 | cleanup: | ||
| 124 | ti_sci_inta_msi_free_descs(&pdev->dev); | ||
| 125 | return ret; | ||
| 126 | } | ||
| 127 | EXPORT_SYMBOL_GPL(ti_sci_inta_msi_domain_alloc_irqs); | ||
| 128 | |||
| 129 | void ti_sci_inta_msi_domain_free_irqs(struct device *dev) | ||
| 130 | { | ||
| 131 | msi_domain_free_irqs(dev->msi_domain, dev); | ||
| 132 | ti_sci_inta_msi_free_descs(dev); | ||
| 133 | } | ||
| 134 | EXPORT_SYMBOL_GPL(ti_sci_inta_msi_domain_free_irqs); | ||
| 135 | |||
| 136 | unsigned int ti_sci_inta_msi_get_virq(struct device *dev, u32 dev_index) | ||
| 137 | { | ||
| 138 | struct msi_desc *desc; | ||
| 139 | |||
| 140 | for_each_msi_entry(desc, dev) | ||
| 141 | if (desc->inta.dev_index == dev_index) | ||
| 142 | return desc->irq; | ||
| 143 | |||
| 144 | return -ENODEV; | ||
| 145 | } | ||
| 146 | EXPORT_SYMBOL_GPL(ti_sci_inta_msi_get_virq); | ||
diff --git a/drivers/target/iscsi/cxgbit/Makefile b/drivers/target/iscsi/cxgbit/Makefile index d16aaae7ba2a..0dcaf2006f78 100644 --- a/drivers/target/iscsi/cxgbit/Makefile +++ b/drivers/target/iscsi/cxgbit/Makefile | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | 1 | # SPDX-License-Identifier: GPL-2.0 |
| 2 | ccflags-y := -Idrivers/net/ethernet/chelsio/cxgb4 | 2 | ccflags-y := -I $(srctree)/drivers/net/ethernet/chelsio/cxgb4 |
| 3 | ccflags-y += -Idrivers/net/ethernet/chelsio/libcxgb | 3 | ccflags-y += -I $(srctree)/drivers/net/ethernet/chelsio/libcxgb |
| 4 | ccflags-y += -Idrivers/target/iscsi | 4 | ccflags-y += -I $(srctree)/drivers/target/iscsi |
| 5 | 5 | ||
| 6 | obj-$(CONFIG_ISCSI_TARGET_CXGB4) += cxgbit.o | 6 | obj-$(CONFIG_ISCSI_TARGET_CXGB4) += cxgbit.o |
| 7 | 7 | ||
diff --git a/drivers/tty/hvc/hvc_riscv_sbi.c b/drivers/tty/hvc/hvc_riscv_sbi.c index 75155bde2b88..31f53fa77e4a 100644 --- a/drivers/tty/hvc/hvc_riscv_sbi.c +++ b/drivers/tty/hvc/hvc_riscv_sbi.c | |||
| @@ -53,7 +53,6 @@ device_initcall(hvc_sbi_init); | |||
| 53 | static int __init hvc_sbi_console_init(void) | 53 | static int __init hvc_sbi_console_init(void) |
| 54 | { | 54 | { |
| 55 | hvc_instantiate(0, 0, &hvc_sbi_ops); | 55 | hvc_instantiate(0, 0, &hvc_sbi_ops); |
| 56 | add_preferred_console("hvc", 0, NULL); | ||
| 57 | 56 | ||
| 58 | return 0; | 57 | return 0; |
| 59 | } | 58 | } |
diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index c5126a4cd954..a67ddcbb4e24 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | # Rewritten to use lists instead of if-statements. | 6 | # Rewritten to use lists instead of if-statements. |
| 7 | # | 7 | # |
| 8 | 8 | ||
| 9 | ccflags-y := -Idrivers/scsi | 9 | ccflags-y := -I $(srctree)/drivers/scsi |
| 10 | 10 | ||
| 11 | obj-$(CONFIG_USB_UAS) += uas.o | 11 | obj-$(CONFIG_USB_UAS) += uas.o |
| 12 | obj-$(CONFIG_USB_STORAGE) += usb-storage.o | 12 | obj-$(CONFIG_USB_STORAGE) += usb-storage.o |
diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c index 9e529cc2b4ff..9f39f0c360e0 100644 --- a/drivers/video/fbdev/efifb.c +++ b/drivers/video/fbdev/efifb.c | |||
| @@ -477,8 +477,12 @@ static int efifb_probe(struct platform_device *dev) | |||
| 477 | * If the UEFI memory map covers the efifb region, we may only | 477 | * If the UEFI memory map covers the efifb region, we may only |
| 478 | * remap it using the attributes the memory map prescribes. | 478 | * remap it using the attributes the memory map prescribes. |
| 479 | */ | 479 | */ |
| 480 | mem_flags |= EFI_MEMORY_WT | EFI_MEMORY_WB; | 480 | md.attribute &= EFI_MEMORY_UC | EFI_MEMORY_WC | |
| 481 | mem_flags &= md.attribute; | 481 | EFI_MEMORY_WT | EFI_MEMORY_WB; |
| 482 | if (md.attribute) { | ||
| 483 | mem_flags |= EFI_MEMORY_WT | EFI_MEMORY_WB; | ||
| 484 | mem_flags &= md.attribute; | ||
| 485 | } | ||
| 482 | } | 486 | } |
| 483 | if (mem_flags & EFI_MEMORY_WC) | 487 | if (mem_flags & EFI_MEMORY_WC) |
| 484 | info->screen_base = ioremap_wc(efifb_fix.smem_start, | 488 | info->screen_base = ioremap_wc(efifb_fix.smem_start, |
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index 6a69f11aacf7..45e74da40f3a 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c | |||
| @@ -380,6 +380,8 @@ skip_rdma: | |||
| 380 | atomic_read(&server->in_send), | 380 | atomic_read(&server->in_send), |
| 381 | atomic_read(&server->num_waiters)); | 381 | atomic_read(&server->num_waiters)); |
| 382 | #endif | 382 | #endif |
| 383 | /* dump session id helpful for use with network trace */ | ||
| 384 | seq_printf(m, " SessionId: 0x%llx", ses->Suid); | ||
| 383 | if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) | 385 | if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) |
| 384 | seq_puts(m, " encrypted"); | 386 | seq_puts(m, " encrypted"); |
| 385 | if (ses->sign) | 387 | if (ses->sign) |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index b1a5fcfa3ce1..f5fcd6360056 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
| @@ -878,6 +878,9 @@ out: | |||
| 878 | 878 | ||
| 879 | static loff_t cifs_llseek(struct file *file, loff_t offset, int whence) | 879 | static loff_t cifs_llseek(struct file *file, loff_t offset, int whence) |
| 880 | { | 880 | { |
| 881 | struct cifsFileInfo *cfile = file->private_data; | ||
| 882 | struct cifs_tcon *tcon; | ||
| 883 | |||
| 881 | /* | 884 | /* |
| 882 | * whence == SEEK_END || SEEK_DATA || SEEK_HOLE => we must revalidate | 885 | * whence == SEEK_END || SEEK_DATA || SEEK_HOLE => we must revalidate |
| 883 | * the cached file length | 886 | * the cached file length |
| @@ -909,6 +912,12 @@ static loff_t cifs_llseek(struct file *file, loff_t offset, int whence) | |||
| 909 | if (rc < 0) | 912 | if (rc < 0) |
| 910 | return (loff_t)rc; | 913 | return (loff_t)rc; |
| 911 | } | 914 | } |
| 915 | if (cfile && cfile->tlink) { | ||
| 916 | tcon = tlink_tcon(cfile->tlink); | ||
| 917 | if (tcon->ses->server->ops->llseek) | ||
| 918 | return tcon->ses->server->ops->llseek(file, tcon, | ||
| 919 | offset, whence); | ||
| 920 | } | ||
| 912 | return generic_file_llseek(file, offset, whence); | 921 | return generic_file_llseek(file, offset, whence); |
| 913 | } | 922 | } |
| 914 | 923 | ||
| @@ -1070,11 +1079,6 @@ ssize_t cifs_file_copychunk_range(unsigned int xid, | |||
| 1070 | 1079 | ||
| 1071 | cifs_dbg(FYI, "copychunk range\n"); | 1080 | cifs_dbg(FYI, "copychunk range\n"); |
| 1072 | 1081 | ||
| 1073 | if (src_inode == target_inode) { | ||
| 1074 | rc = -EINVAL; | ||
| 1075 | goto out; | ||
| 1076 | } | ||
| 1077 | |||
| 1078 | if (!src_file->private_data || !dst_file->private_data) { | 1082 | if (!src_file->private_data || !dst_file->private_data) { |
| 1079 | rc = -EBADF; | 1083 | rc = -EBADF; |
| 1080 | cifs_dbg(VFS, "missing cifsFileInfo on copy range src file\n"); | 1084 | cifs_dbg(VFS, "missing cifsFileInfo on copy range src file\n"); |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 33c251b408aa..334ff5f9c3f3 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
| @@ -497,6 +497,8 @@ struct smb_version_operations { | |||
| 497 | /* version specific fiemap implementation */ | 497 | /* version specific fiemap implementation */ |
| 498 | int (*fiemap)(struct cifs_tcon *tcon, struct cifsFileInfo *, | 498 | int (*fiemap)(struct cifs_tcon *tcon, struct cifsFileInfo *, |
| 499 | struct fiemap_extent_info *, u64, u64); | 499 | struct fiemap_extent_info *, u64, u64); |
| 500 | /* version specific llseek implementation */ | ||
| 501 | loff_t (*llseek)(struct file *, struct cifs_tcon *, loff_t, int); | ||
| 500 | }; | 502 | }; |
| 501 | 503 | ||
| 502 | struct smb_version_values { | 504 | struct smb_version_values { |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 084756cfdaee..8c4121da624e 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
| @@ -528,6 +528,21 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
| 528 | /* do not want to be sending data on a socket we are freeing */ | 528 | /* do not want to be sending data on a socket we are freeing */ |
| 529 | cifs_dbg(FYI, "%s: tearing down socket\n", __func__); | 529 | cifs_dbg(FYI, "%s: tearing down socket\n", __func__); |
| 530 | mutex_lock(&server->srv_mutex); | 530 | mutex_lock(&server->srv_mutex); |
| 531 | if (server->ssocket) { | ||
| 532 | cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n", | ||
| 533 | server->ssocket->state, server->ssocket->flags); | ||
| 534 | kernel_sock_shutdown(server->ssocket, SHUT_WR); | ||
| 535 | cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n", | ||
| 536 | server->ssocket->state, server->ssocket->flags); | ||
| 537 | sock_release(server->ssocket); | ||
| 538 | server->ssocket = NULL; | ||
| 539 | } | ||
| 540 | server->sequence_number = 0; | ||
| 541 | server->session_estab = false; | ||
| 542 | kfree(server->session_key.response); | ||
| 543 | server->session_key.response = NULL; | ||
| 544 | server->session_key.len = 0; | ||
| 545 | server->lstrp = jiffies; | ||
| 531 | 546 | ||
| 532 | /* mark submitted MIDs for retry and issue callback */ | 547 | /* mark submitted MIDs for retry and issue callback */ |
| 533 | INIT_LIST_HEAD(&retry_list); | 548 | INIT_LIST_HEAD(&retry_list); |
| @@ -540,6 +555,7 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
| 540 | list_move(&mid_entry->qhead, &retry_list); | 555 | list_move(&mid_entry->qhead, &retry_list); |
| 541 | } | 556 | } |
| 542 | spin_unlock(&GlobalMid_Lock); | 557 | spin_unlock(&GlobalMid_Lock); |
| 558 | mutex_unlock(&server->srv_mutex); | ||
| 543 | 559 | ||
| 544 | cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__); | 560 | cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__); |
| 545 | list_for_each_safe(tmp, tmp2, &retry_list) { | 561 | list_for_each_safe(tmp, tmp2, &retry_list) { |
| @@ -548,24 +564,11 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
| 548 | mid_entry->callback(mid_entry); | 564 | mid_entry->callback(mid_entry); |
| 549 | } | 565 | } |
| 550 | 566 | ||
| 551 | if (server->ssocket) { | 567 | if (cifs_rdma_enabled(server)) { |
| 552 | cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n", | 568 | mutex_lock(&server->srv_mutex); |
| 553 | server->ssocket->state, server->ssocket->flags); | ||
| 554 | kernel_sock_shutdown(server->ssocket, SHUT_WR); | ||
| 555 | cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n", | ||
| 556 | server->ssocket->state, server->ssocket->flags); | ||
| 557 | sock_release(server->ssocket); | ||
| 558 | server->ssocket = NULL; | ||
| 559 | } else if (cifs_rdma_enabled(server)) | ||
| 560 | smbd_destroy(server); | 569 | smbd_destroy(server); |
| 561 | server->sequence_number = 0; | 570 | mutex_unlock(&server->srv_mutex); |
| 562 | server->session_estab = false; | 571 | } |
| 563 | kfree(server->session_key.response); | ||
| 564 | server->session_key.response = NULL; | ||
| 565 | server->session_key.len = 0; | ||
| 566 | server->lstrp = jiffies; | ||
| 567 | |||
| 568 | mutex_unlock(&server->srv_mutex); | ||
| 569 | 572 | ||
| 570 | do { | 573 | do { |
| 571 | try_to_freeze(); | 574 | try_to_freeze(); |
| @@ -2443,6 +2446,10 @@ match_port(struct TCP_Server_Info *server, struct sockaddr *addr) | |||
| 2443 | { | 2446 | { |
| 2444 | __be16 port, *sport; | 2447 | __be16 port, *sport; |
| 2445 | 2448 | ||
| 2449 | /* SMBDirect manages its own ports, don't match it here */ | ||
| 2450 | if (server->rdma) | ||
| 2451 | return true; | ||
| 2452 | |||
| 2446 | switch (addr->sa_family) { | 2453 | switch (addr->sa_family) { |
| 2447 | case AF_INET: | 2454 | case AF_INET: |
| 2448 | sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port; | 2455 | sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port; |
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index a930c8965e5c..e921e6511728 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 1 | /* | 2 | /* |
| 2 | * SMB2 version specific operations | 3 | * SMB2 version specific operations |
| 3 | * | 4 | * |
| @@ -282,7 +283,7 @@ smb2_find_mid(struct TCP_Server_Info *server, char *buf) | |||
| 282 | __u64 wire_mid = le64_to_cpu(shdr->MessageId); | 283 | __u64 wire_mid = le64_to_cpu(shdr->MessageId); |
| 283 | 284 | ||
| 284 | if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) { | 285 | if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) { |
| 285 | cifs_dbg(VFS, "encrypted frame parsing not supported yet"); | 286 | cifs_dbg(VFS, "Encrypted frame parsing not supported yet\n"); |
| 286 | return NULL; | 287 | return NULL; |
| 287 | } | 288 | } |
| 288 | 289 | ||
| @@ -324,6 +325,7 @@ static int | |||
| 324 | smb2_negotiate(const unsigned int xid, struct cifs_ses *ses) | 325 | smb2_negotiate(const unsigned int xid, struct cifs_ses *ses) |
| 325 | { | 326 | { |
| 326 | int rc; | 327 | int rc; |
| 328 | |||
| 327 | ses->server->CurrentMid = 0; | 329 | ses->server->CurrentMid = 0; |
| 328 | rc = SMB2_negotiate(xid, ses); | 330 | rc = SMB2_negotiate(xid, ses); |
| 329 | /* BB we probably don't need to retry with modern servers */ | 331 | /* BB we probably don't need to retry with modern servers */ |
| @@ -789,8 +791,6 @@ smb3_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon) | |||
| 789 | SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); | 791 | SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); |
| 790 | else | 792 | else |
| 791 | close_shroot(&tcon->crfid); | 793 | close_shroot(&tcon->crfid); |
| 792 | |||
| 793 | return; | ||
| 794 | } | 794 | } |
| 795 | 795 | ||
| 796 | static void | 796 | static void |
| @@ -818,7 +818,6 @@ smb2_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon) | |||
| 818 | SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid, | 818 | SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid, |
| 819 | FS_DEVICE_INFORMATION); | 819 | FS_DEVICE_INFORMATION); |
| 820 | SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); | 820 | SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); |
| 821 | return; | ||
| 822 | } | 821 | } |
| 823 | 822 | ||
| 824 | static int | 823 | static int |
| @@ -906,9 +905,8 @@ move_smb2_ea_to_cifs(char *dst, size_t dst_size, | |||
| 906 | value = &src->ea_data[src->ea_name_length + 1]; | 905 | value = &src->ea_data[src->ea_name_length + 1]; |
| 907 | value_len = (size_t)le16_to_cpu(src->ea_value_length); | 906 | value_len = (size_t)le16_to_cpu(src->ea_value_length); |
| 908 | 907 | ||
| 909 | if (name_len == 0) { | 908 | if (name_len == 0) |
| 910 | break; | 909 | break; |
| 911 | } | ||
| 912 | 910 | ||
| 913 | if (src_size < 8 + name_len + 1 + value_len) { | 911 | if (src_size < 8 + name_len + 1 + value_len) { |
| 914 | cifs_dbg(FYI, "EA entry goes beyond length of list\n"); | 912 | cifs_dbg(FYI, "EA entry goes beyond length of list\n"); |
| @@ -1161,6 +1159,7 @@ static void | |||
| 1161 | smb2_clear_stats(struct cifs_tcon *tcon) | 1159 | smb2_clear_stats(struct cifs_tcon *tcon) |
| 1162 | { | 1160 | { |
| 1163 | int i; | 1161 | int i; |
| 1162 | |||
| 1164 | for (i = 0; i < NUMBER_OF_SMB2_COMMANDS; i++) { | 1163 | for (i = 0; i < NUMBER_OF_SMB2_COMMANDS; i++) { |
| 1165 | atomic_set(&tcon->stats.smb2_stats.smb2_com_sent[i], 0); | 1164 | atomic_set(&tcon->stats.smb2_stats.smb2_com_sent[i], 0); |
| 1166 | atomic_set(&tcon->stats.smb2_stats.smb2_com_failed[i], 0); | 1165 | atomic_set(&tcon->stats.smb2_stats.smb2_com_failed[i], 0); |
| @@ -1529,7 +1528,7 @@ smb2_copychunk_range(const unsigned int xid, | |||
| 1529 | if (pcchunk == NULL) | 1528 | if (pcchunk == NULL) |
| 1530 | return -ENOMEM; | 1529 | return -ENOMEM; |
| 1531 | 1530 | ||
| 1532 | cifs_dbg(FYI, "in smb2_copychunk_range - about to call request res key\n"); | 1531 | cifs_dbg(FYI, "%s: about to call request res key\n", __func__); |
| 1533 | /* Request a key from the server to identify the source of the copy */ | 1532 | /* Request a key from the server to identify the source of the copy */ |
| 1534 | rc = SMB2_request_res_key(xid, tlink_tcon(srcfile->tlink), | 1533 | rc = SMB2_request_res_key(xid, tlink_tcon(srcfile->tlink), |
| 1535 | srcfile->fid.persistent_fid, | 1534 | srcfile->fid.persistent_fid, |
| @@ -1649,6 +1648,7 @@ static unsigned int | |||
| 1649 | smb2_read_data_offset(char *buf) | 1648 | smb2_read_data_offset(char *buf) |
| 1650 | { | 1649 | { |
| 1651 | struct smb2_read_rsp *rsp = (struct smb2_read_rsp *)buf; | 1650 | struct smb2_read_rsp *rsp = (struct smb2_read_rsp *)buf; |
| 1651 | |||
| 1652 | return rsp->DataOffset; | 1652 | return rsp->DataOffset; |
| 1653 | } | 1653 | } |
| 1654 | 1654 | ||
| @@ -1777,7 +1777,7 @@ smb2_duplicate_extents(const unsigned int xid, | |||
| 1777 | dup_ext_buf.SourceFileOffset = cpu_to_le64(src_off); | 1777 | dup_ext_buf.SourceFileOffset = cpu_to_le64(src_off); |
| 1778 | dup_ext_buf.TargetFileOffset = cpu_to_le64(dest_off); | 1778 | dup_ext_buf.TargetFileOffset = cpu_to_le64(dest_off); |
| 1779 | dup_ext_buf.ByteCount = cpu_to_le64(len); | 1779 | dup_ext_buf.ByteCount = cpu_to_le64(len); |
| 1780 | cifs_dbg(FYI, "duplicate extents: src off %lld dst off %lld len %lld", | 1780 | cifs_dbg(FYI, "Duplicate extents: src off %lld dst off %lld len %lld\n", |
| 1781 | src_off, dest_off, len); | 1781 | src_off, dest_off, len); |
| 1782 | 1782 | ||
| 1783 | rc = smb2_set_file_size(xid, tcon, trgtfile, dest_off + len, false); | 1783 | rc = smb2_set_file_size(xid, tcon, trgtfile, dest_off + len, false); |
| @@ -1794,7 +1794,7 @@ smb2_duplicate_extents(const unsigned int xid, | |||
| 1794 | &ret_data_len); | 1794 | &ret_data_len); |
| 1795 | 1795 | ||
| 1796 | if (ret_data_len > 0) | 1796 | if (ret_data_len > 0) |
| 1797 | cifs_dbg(FYI, "non-zero response length in duplicate extents"); | 1797 | cifs_dbg(FYI, "Non-zero response length in duplicate extents\n"); |
| 1798 | 1798 | ||
| 1799 | duplicate_extents_out: | 1799 | duplicate_extents_out: |
| 1800 | return rc; | 1800 | return rc; |
| @@ -1983,9 +1983,9 @@ smb2_close_dir(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 1983 | } | 1983 | } |
| 1984 | 1984 | ||
| 1985 | /* | 1985 | /* |
| 1986 | * If we negotiate SMB2 protocol and get STATUS_PENDING - update | 1986 | * If we negotiate SMB2 protocol and get STATUS_PENDING - update |
| 1987 | * the number of credits and return true. Otherwise - return false. | 1987 | * the number of credits and return true. Otherwise - return false. |
| 1988 | */ | 1988 | */ |
| 1989 | static bool | 1989 | static bool |
| 1990 | smb2_is_status_pending(char *buf, struct TCP_Server_Info *server) | 1990 | smb2_is_status_pending(char *buf, struct TCP_Server_Info *server) |
| 1991 | { | 1991 | { |
| @@ -2306,7 +2306,7 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses, | |||
| 2306 | struct get_dfs_referral_rsp *dfs_rsp = NULL; | 2306 | struct get_dfs_referral_rsp *dfs_rsp = NULL; |
| 2307 | u32 dfs_req_size = 0, dfs_rsp_size = 0; | 2307 | u32 dfs_req_size = 0, dfs_rsp_size = 0; |
| 2308 | 2308 | ||
| 2309 | cifs_dbg(FYI, "smb2_get_dfs_refer path <%s>\n", search_name); | 2309 | cifs_dbg(FYI, "%s: path: %s\n", __func__, search_name); |
| 2310 | 2310 | ||
| 2311 | /* | 2311 | /* |
| 2312 | * Try to use the IPC tcon, otherwise just use any | 2312 | * Try to use the IPC tcon, otherwise just use any |
| @@ -2360,7 +2360,7 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses, | |||
| 2360 | 2360 | ||
| 2361 | if (rc) { | 2361 | if (rc) { |
| 2362 | if ((rc != -ENOENT) && (rc != -EOPNOTSUPP)) | 2362 | if ((rc != -ENOENT) && (rc != -EOPNOTSUPP)) |
| 2363 | cifs_dbg(VFS, "ioctl error in smb2_get_dfs_refer rc=%d\n", rc); | 2363 | cifs_dbg(VFS, "ioctl error in %s rc=%d\n", __func__, rc); |
| 2364 | goto out; | 2364 | goto out; |
| 2365 | } | 2365 | } |
| 2366 | 2366 | ||
| @@ -2369,7 +2369,7 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses, | |||
| 2369 | nls_codepage, remap, search_name, | 2369 | nls_codepage, remap, search_name, |
| 2370 | true /* is_unicode */); | 2370 | true /* is_unicode */); |
| 2371 | if (rc) { | 2371 | if (rc) { |
| 2372 | cifs_dbg(VFS, "parse error in smb2_get_dfs_refer rc=%d\n", rc); | 2372 | cifs_dbg(VFS, "parse error in %s rc=%d\n", __func__, rc); |
| 2373 | goto out; | 2373 | goto out; |
| 2374 | } | 2374 | } |
| 2375 | 2375 | ||
| @@ -2745,7 +2745,7 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon, | |||
| 2745 | inode = d_inode(cfile->dentry); | 2745 | inode = d_inode(cfile->dentry); |
| 2746 | cifsi = CIFS_I(inode); | 2746 | cifsi = CIFS_I(inode); |
| 2747 | 2747 | ||
| 2748 | trace_smb3_zero_enter(xid, cfile->fid.persistent_fid, tcon->tid, | 2748 | trace_smb3_zero_enter(xid, cfile->fid.persistent_fid, tcon->tid, |
| 2749 | ses->Suid, offset, len); | 2749 | ses->Suid, offset, len); |
| 2750 | 2750 | ||
| 2751 | 2751 | ||
| @@ -2759,7 +2759,7 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon, | |||
| 2759 | return rc; | 2759 | return rc; |
| 2760 | } | 2760 | } |
| 2761 | 2761 | ||
| 2762 | cifs_dbg(FYI, "offset %lld len %lld", offset, len); | 2762 | cifs_dbg(FYI, "Offset %lld len %lld\n", offset, len); |
| 2763 | 2763 | ||
| 2764 | fsctl_buf.FileOffset = cpu_to_le64(offset); | 2764 | fsctl_buf.FileOffset = cpu_to_le64(offset); |
| 2765 | fsctl_buf.BeyondFinalZero = cpu_to_le64(offset + len); | 2765 | fsctl_buf.BeyondFinalZero = cpu_to_le64(offset + len); |
| @@ -2816,7 +2816,7 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon, | |||
| 2816 | return rc; | 2816 | return rc; |
| 2817 | } | 2817 | } |
| 2818 | 2818 | ||
| 2819 | cifs_dbg(FYI, "offset %lld len %lld", offset, len); | 2819 | cifs_dbg(FYI, "Offset %lld len %lld\n", offset, len); |
| 2820 | 2820 | ||
| 2821 | fsctl_buf.FileOffset = cpu_to_le64(offset); | 2821 | fsctl_buf.FileOffset = cpu_to_le64(offset); |
| 2822 | fsctl_buf.BeyondFinalZero = cpu_to_le64(offset + len); | 2822 | fsctl_buf.BeyondFinalZero = cpu_to_le64(offset + len); |
| @@ -2922,6 +2922,90 @@ static long smb3_simple_falloc(struct file *file, struct cifs_tcon *tcon, | |||
| 2922 | return rc; | 2922 | return rc; |
| 2923 | } | 2923 | } |
| 2924 | 2924 | ||
| 2925 | static loff_t smb3_llseek(struct file *file, struct cifs_tcon *tcon, loff_t offset, int whence) | ||
| 2926 | { | ||
| 2927 | struct cifsFileInfo *wrcfile, *cfile = file->private_data; | ||
| 2928 | struct cifsInodeInfo *cifsi; | ||
| 2929 | struct inode *inode; | ||
| 2930 | int rc = 0; | ||
| 2931 | struct file_allocated_range_buffer in_data, *out_data = NULL; | ||
| 2932 | u32 out_data_len; | ||
| 2933 | unsigned int xid; | ||
| 2934 | |||
| 2935 | if (whence != SEEK_HOLE && whence != SEEK_DATA) | ||
| 2936 | return generic_file_llseek(file, offset, whence); | ||
| 2937 | |||
| 2938 | inode = d_inode(cfile->dentry); | ||
| 2939 | cifsi = CIFS_I(inode); | ||
| 2940 | |||
| 2941 | if (offset < 0 || offset >= i_size_read(inode)) | ||
| 2942 | return -ENXIO; | ||
| 2943 | |||
| 2944 | xid = get_xid(); | ||
| 2945 | /* | ||
| 2946 | * We need to be sure that all dirty pages are written as they | ||
| 2947 | * might fill holes on the server. | ||
| 2948 | * Note that we also MUST flush any written pages since at least | ||
| 2949 | * some servers (Windows2016) will not reflect recent writes in | ||
| 2950 | * QUERY_ALLOCATED_RANGES until SMB2_flush is called. | ||
| 2951 | */ | ||
| 2952 | wrcfile = find_writable_file(cifsi, false); | ||
| 2953 | if (wrcfile) { | ||
| 2954 | filemap_write_and_wait(inode->i_mapping); | ||
| 2955 | smb2_flush_file(xid, tcon, &wrcfile->fid); | ||
| 2956 | cifsFileInfo_put(wrcfile); | ||
| 2957 | } | ||
| 2958 | |||
| 2959 | if (!(cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE)) { | ||
| 2960 | if (whence == SEEK_HOLE) | ||
| 2961 | offset = i_size_read(inode); | ||
| 2962 | goto lseek_exit; | ||
| 2963 | } | ||
| 2964 | |||
| 2965 | in_data.file_offset = cpu_to_le64(offset); | ||
| 2966 | in_data.length = cpu_to_le64(i_size_read(inode)); | ||
| 2967 | |||
| 2968 | rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid, | ||
| 2969 | cfile->fid.volatile_fid, | ||
| 2970 | FSCTL_QUERY_ALLOCATED_RANGES, true, | ||
| 2971 | (char *)&in_data, sizeof(in_data), | ||
| 2972 | sizeof(struct file_allocated_range_buffer), | ||
| 2973 | (char **)&out_data, &out_data_len); | ||
| 2974 | if (rc == -E2BIG) | ||
| 2975 | rc = 0; | ||
| 2976 | if (rc) | ||
| 2977 | goto lseek_exit; | ||
| 2978 | |||
| 2979 | if (whence == SEEK_HOLE && out_data_len == 0) | ||
| 2980 | goto lseek_exit; | ||
| 2981 | |||
| 2982 | if (whence == SEEK_DATA && out_data_len == 0) { | ||
| 2983 | rc = -ENXIO; | ||
| 2984 | goto lseek_exit; | ||
| 2985 | } | ||
| 2986 | |||
| 2987 | if (out_data_len < sizeof(struct file_allocated_range_buffer)) { | ||
| 2988 | rc = -EINVAL; | ||
| 2989 | goto lseek_exit; | ||
| 2990 | } | ||
| 2991 | if (whence == SEEK_DATA) { | ||
| 2992 | offset = le64_to_cpu(out_data->file_offset); | ||
| 2993 | goto lseek_exit; | ||
| 2994 | } | ||
| 2995 | if (offset < le64_to_cpu(out_data->file_offset)) | ||
| 2996 | goto lseek_exit; | ||
| 2997 | |||
| 2998 | offset = le64_to_cpu(out_data->file_offset) + le64_to_cpu(out_data->length); | ||
| 2999 | |||
| 3000 | lseek_exit: | ||
| 3001 | free_xid(xid); | ||
| 3002 | kfree(out_data); | ||
| 3003 | if (!rc) | ||
| 3004 | return vfs_setpos(file, offset, inode->i_sb->s_maxbytes); | ||
| 3005 | else | ||
| 3006 | return rc; | ||
| 3007 | } | ||
| 3008 | |||
| 2925 | static int smb3_fiemap(struct cifs_tcon *tcon, | 3009 | static int smb3_fiemap(struct cifs_tcon *tcon, |
| 2926 | struct cifsFileInfo *cfile, | 3010 | struct cifsFileInfo *cfile, |
| 2927 | struct fiemap_extent_info *fei, u64 start, u64 len) | 3011 | struct fiemap_extent_info *fei, u64 start, u64 len) |
| @@ -3384,7 +3468,7 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst, | |||
| 3384 | 3468 | ||
| 3385 | req = aead_request_alloc(tfm, GFP_KERNEL); | 3469 | req = aead_request_alloc(tfm, GFP_KERNEL); |
| 3386 | if (!req) { | 3470 | if (!req) { |
| 3387 | cifs_dbg(VFS, "%s: Failed to alloc aead request", __func__); | 3471 | cifs_dbg(VFS, "%s: Failed to alloc aead request\n", __func__); |
| 3388 | return -ENOMEM; | 3472 | return -ENOMEM; |
| 3389 | } | 3473 | } |
| 3390 | 3474 | ||
| @@ -3395,7 +3479,7 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst, | |||
| 3395 | 3479 | ||
| 3396 | sg = init_sg(num_rqst, rqst, sign); | 3480 | sg = init_sg(num_rqst, rqst, sign); |
| 3397 | if (!sg) { | 3481 | if (!sg) { |
| 3398 | cifs_dbg(VFS, "%s: Failed to init sg", __func__); | 3482 | cifs_dbg(VFS, "%s: Failed to init sg\n", __func__); |
| 3399 | rc = -ENOMEM; | 3483 | rc = -ENOMEM; |
| 3400 | goto free_req; | 3484 | goto free_req; |
| 3401 | } | 3485 | } |
| @@ -3403,7 +3487,7 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst, | |||
| 3403 | iv_len = crypto_aead_ivsize(tfm); | 3487 | iv_len = crypto_aead_ivsize(tfm); |
| 3404 | iv = kzalloc(iv_len, GFP_KERNEL); | 3488 | iv = kzalloc(iv_len, GFP_KERNEL); |
| 3405 | if (!iv) { | 3489 | if (!iv) { |
| 3406 | cifs_dbg(VFS, "%s: Failed to alloc IV", __func__); | 3490 | cifs_dbg(VFS, "%s: Failed to alloc iv\n", __func__); |
| 3407 | rc = -ENOMEM; | 3491 | rc = -ENOMEM; |
| 3408 | goto free_sg; | 3492 | goto free_sg; |
| 3409 | } | 3493 | } |
| @@ -3511,7 +3595,7 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, int num_rqst, | |||
| 3511 | fill_transform_hdr(tr_hdr, orig_len, old_rq); | 3595 | fill_transform_hdr(tr_hdr, orig_len, old_rq); |
| 3512 | 3596 | ||
| 3513 | rc = crypt_message(server, num_rqst, new_rq, 1); | 3597 | rc = crypt_message(server, num_rqst, new_rq, 1); |
| 3514 | cifs_dbg(FYI, "encrypt message returned %d", rc); | 3598 | cifs_dbg(FYI, "Encrypt message returned %d\n", rc); |
| 3515 | if (rc) | 3599 | if (rc) |
| 3516 | goto err_free; | 3600 | goto err_free; |
| 3517 | 3601 | ||
| @@ -3552,7 +3636,7 @@ decrypt_raw_data(struct TCP_Server_Info *server, char *buf, | |||
| 3552 | rqst.rq_tailsz = (page_data_size % PAGE_SIZE) ? : PAGE_SIZE; | 3636 | rqst.rq_tailsz = (page_data_size % PAGE_SIZE) ? : PAGE_SIZE; |
| 3553 | 3637 | ||
| 3554 | rc = crypt_message(server, 1, &rqst, 0); | 3638 | rc = crypt_message(server, 1, &rqst, 0); |
| 3555 | cifs_dbg(FYI, "decrypt message returned %d\n", rc); | 3639 | cifs_dbg(FYI, "Decrypt message returned %d\n", rc); |
| 3556 | 3640 | ||
| 3557 | if (rc) | 3641 | if (rc) |
| 3558 | return rc; | 3642 | return rc; |
| @@ -4166,6 +4250,7 @@ struct smb_version_operations smb20_operations = { | |||
| 4166 | .ioctl_query_info = smb2_ioctl_query_info, | 4250 | .ioctl_query_info = smb2_ioctl_query_info, |
| 4167 | .make_node = smb2_make_node, | 4251 | .make_node = smb2_make_node, |
| 4168 | .fiemap = smb3_fiemap, | 4252 | .fiemap = smb3_fiemap, |
| 4253 | .llseek = smb3_llseek, | ||
| 4169 | }; | 4254 | }; |
| 4170 | 4255 | ||
| 4171 | struct smb_version_operations smb21_operations = { | 4256 | struct smb_version_operations smb21_operations = { |
| @@ -4266,6 +4351,7 @@ struct smb_version_operations smb21_operations = { | |||
| 4266 | .ioctl_query_info = smb2_ioctl_query_info, | 4351 | .ioctl_query_info = smb2_ioctl_query_info, |
| 4267 | .make_node = smb2_make_node, | 4352 | .make_node = smb2_make_node, |
| 4268 | .fiemap = smb3_fiemap, | 4353 | .fiemap = smb3_fiemap, |
| 4354 | .llseek = smb3_llseek, | ||
| 4269 | }; | 4355 | }; |
| 4270 | 4356 | ||
| 4271 | struct smb_version_operations smb30_operations = { | 4357 | struct smb_version_operations smb30_operations = { |
| @@ -4375,6 +4461,7 @@ struct smb_version_operations smb30_operations = { | |||
| 4375 | .ioctl_query_info = smb2_ioctl_query_info, | 4461 | .ioctl_query_info = smb2_ioctl_query_info, |
| 4376 | .make_node = smb2_make_node, | 4462 | .make_node = smb2_make_node, |
| 4377 | .fiemap = smb3_fiemap, | 4463 | .fiemap = smb3_fiemap, |
| 4464 | .llseek = smb3_llseek, | ||
| 4378 | }; | 4465 | }; |
| 4379 | 4466 | ||
| 4380 | struct smb_version_operations smb311_operations = { | 4467 | struct smb_version_operations smb311_operations = { |
| @@ -4485,6 +4572,7 @@ struct smb_version_operations smb311_operations = { | |||
| 4485 | .ioctl_query_info = smb2_ioctl_query_info, | 4572 | .ioctl_query_info = smb2_ioctl_query_info, |
| 4486 | .make_node = smb2_make_node, | 4573 | .make_node = smb2_make_node, |
| 4487 | .fiemap = smb3_fiemap, | 4574 | .fiemap = smb3_fiemap, |
| 4575 | .llseek = smb3_llseek, | ||
| 4488 | }; | 4576 | }; |
| 4489 | 4577 | ||
| 4490 | struct smb_version_values smb20_values = { | 4578 | struct smb_version_values smb20_values = { |
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 29f011d8d8e2..710ceb875161 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c | |||
| @@ -2538,11 +2538,25 @@ SMB2_ioctl_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, | |||
| 2538 | struct kvec *iov = rqst->rq_iov; | 2538 | struct kvec *iov = rqst->rq_iov; |
| 2539 | unsigned int total_len; | 2539 | unsigned int total_len; |
| 2540 | int rc; | 2540 | int rc; |
| 2541 | char *in_data_buf; | ||
| 2541 | 2542 | ||
| 2542 | rc = smb2_plain_req_init(SMB2_IOCTL, tcon, (void **) &req, &total_len); | 2543 | rc = smb2_plain_req_init(SMB2_IOCTL, tcon, (void **) &req, &total_len); |
| 2543 | if (rc) | 2544 | if (rc) |
| 2544 | return rc; | 2545 | return rc; |
| 2545 | 2546 | ||
| 2547 | if (indatalen) { | ||
| 2548 | /* | ||
| 2549 | * indatalen is usually small at a couple of bytes max, so | ||
| 2550 | * just allocate through generic pool | ||
| 2551 | */ | ||
| 2552 | in_data_buf = kmalloc(indatalen, GFP_NOFS); | ||
| 2553 | if (!in_data_buf) { | ||
| 2554 | cifs_small_buf_release(req); | ||
| 2555 | return -ENOMEM; | ||
| 2556 | } | ||
| 2557 | memcpy(in_data_buf, in_data, indatalen); | ||
| 2558 | } | ||
| 2559 | |||
| 2546 | req->CtlCode = cpu_to_le32(opcode); | 2560 | req->CtlCode = cpu_to_le32(opcode); |
| 2547 | req->PersistentFileId = persistent_fid; | 2561 | req->PersistentFileId = persistent_fid; |
| 2548 | req->VolatileFileId = volatile_fid; | 2562 | req->VolatileFileId = volatile_fid; |
| @@ -2563,7 +2577,7 @@ SMB2_ioctl_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, | |||
| 2563 | cpu_to_le32(offsetof(struct smb2_ioctl_req, Buffer)); | 2577 | cpu_to_le32(offsetof(struct smb2_ioctl_req, Buffer)); |
| 2564 | rqst->rq_nvec = 2; | 2578 | rqst->rq_nvec = 2; |
| 2565 | iov[0].iov_len = total_len - 1; | 2579 | iov[0].iov_len = total_len - 1; |
| 2566 | iov[1].iov_base = in_data; | 2580 | iov[1].iov_base = in_data_buf; |
| 2567 | iov[1].iov_len = indatalen; | 2581 | iov[1].iov_len = indatalen; |
| 2568 | } else { | 2582 | } else { |
| 2569 | rqst->rq_nvec = 1; | 2583 | rqst->rq_nvec = 1; |
| @@ -2605,8 +2619,11 @@ SMB2_ioctl_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, | |||
| 2605 | void | 2619 | void |
| 2606 | SMB2_ioctl_free(struct smb_rqst *rqst) | 2620 | SMB2_ioctl_free(struct smb_rqst *rqst) |
| 2607 | { | 2621 | { |
| 2608 | if (rqst && rqst->rq_iov) | 2622 | if (rqst && rqst->rq_iov) { |
| 2609 | cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */ | 2623 | cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */ |
| 2624 | if (rqst->rq_iov[1].iov_len) | ||
| 2625 | kfree(rqst->rq_iov[1].iov_base); | ||
| 2626 | } | ||
| 2610 | } | 2627 | } |
| 2611 | 2628 | ||
| 2612 | 2629 | ||
diff --git a/fs/cifs/smbdirect.c b/fs/cifs/smbdirect.c index 251ef1223206..caac37b1de8c 100644 --- a/fs/cifs/smbdirect.c +++ b/fs/cifs/smbdirect.c | |||
| @@ -903,7 +903,7 @@ static int smbd_create_header(struct smbd_connection *info, | |||
| 903 | request->sge[0].addr = ib_dma_map_single(info->id->device, | 903 | request->sge[0].addr = ib_dma_map_single(info->id->device, |
| 904 | (void *)packet, | 904 | (void *)packet, |
| 905 | header_length, | 905 | header_length, |
| 906 | DMA_BIDIRECTIONAL); | 906 | DMA_TO_DEVICE); |
| 907 | if (ib_dma_mapping_error(info->id->device, request->sge[0].addr)) { | 907 | if (ib_dma_mapping_error(info->id->device, request->sge[0].addr)) { |
| 908 | mempool_free(request, info->request_mempool); | 908 | mempool_free(request, info->request_mempool); |
| 909 | rc = -EIO; | 909 | rc = -EIO; |
| @@ -1005,7 +1005,7 @@ static int smbd_post_send_sgl(struct smbd_connection *info, | |||
| 1005 | for_each_sg(sgl, sg, num_sgs, i) { | 1005 | for_each_sg(sgl, sg, num_sgs, i) { |
| 1006 | request->sge[i+1].addr = | 1006 | request->sge[i+1].addr = |
| 1007 | ib_dma_map_page(info->id->device, sg_page(sg), | 1007 | ib_dma_map_page(info->id->device, sg_page(sg), |
| 1008 | sg->offset, sg->length, DMA_BIDIRECTIONAL); | 1008 | sg->offset, sg->length, DMA_TO_DEVICE); |
| 1009 | if (ib_dma_mapping_error( | 1009 | if (ib_dma_mapping_error( |
| 1010 | info->id->device, request->sge[i+1].addr)) { | 1010 | info->id->device, request->sge[i+1].addr)) { |
| 1011 | rc = -EIO; | 1011 | rc = -EIO; |
| @@ -2110,8 +2110,10 @@ int smbd_send(struct TCP_Server_Info *server, | |||
| 2110 | goto done; | 2110 | goto done; |
| 2111 | } | 2111 | } |
| 2112 | 2112 | ||
| 2113 | rqst_idx = 0; | 2113 | log_write(INFO, "num_rqst=%d total length=%u\n", |
| 2114 | num_rqst, remaining_data_length); | ||
| 2114 | 2115 | ||
| 2116 | rqst_idx = 0; | ||
| 2115 | next_rqst: | 2117 | next_rqst: |
| 2116 | rqst = &rqst_array[rqst_idx]; | 2118 | rqst = &rqst_array[rqst_idx]; |
| 2117 | iov = rqst->rq_iov; | 2119 | iov = rqst->rq_iov; |
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index 9a16ff4b9f5e..60661b3f983a 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c | |||
| @@ -33,7 +33,7 @@ | |||
| 33 | #include <linux/uaccess.h> | 33 | #include <linux/uaccess.h> |
| 34 | #include <asm/processor.h> | 34 | #include <asm/processor.h> |
| 35 | #include <linux/mempool.h> | 35 | #include <linux/mempool.h> |
| 36 | #include <linux/signal.h> | 36 | #include <linux/sched/signal.h> |
| 37 | #include "cifspdu.h" | 37 | #include "cifspdu.h" |
| 38 | #include "cifsglob.h" | 38 | #include "cifsglob.h" |
| 39 | #include "cifsproto.h" | 39 | #include "cifsproto.h" |
diff --git a/fs/ext4/block_validity.c b/fs/ext4/block_validity.c index 968f163b5feb..8e83741b02e0 100644 --- a/fs/ext4/block_validity.c +++ b/fs/ext4/block_validity.c | |||
| @@ -142,7 +142,8 @@ static int ext4_protect_reserved_inode(struct super_block *sb, u32 ino) | |||
| 142 | struct inode *inode; | 142 | struct inode *inode; |
| 143 | struct ext4_sb_info *sbi = EXT4_SB(sb); | 143 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
| 144 | struct ext4_map_blocks map; | 144 | struct ext4_map_blocks map; |
| 145 | u32 i = 0, err = 0, num, n; | 145 | u32 i = 0, num; |
| 146 | int err = 0, n; | ||
| 146 | 147 | ||
| 147 | if ((ino < EXT4_ROOT_INO) || | 148 | if ((ino < EXT4_ROOT_INO) || |
| 148 | (ino > le32_to_cpu(sbi->s_es->s_inodes_count))) | 149 | (ino > le32_to_cpu(sbi->s_es->s_inodes_count))) |
| @@ -276,6 +277,11 @@ int ext4_check_blockref(const char *function, unsigned int line, | |||
| 276 | __le32 *bref = p; | 277 | __le32 *bref = p; |
| 277 | unsigned int blk; | 278 | unsigned int blk; |
| 278 | 279 | ||
| 280 | if (ext4_has_feature_journal(inode->i_sb) && | ||
| 281 | (inode->i_ino == | ||
| 282 | le32_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_journal_inum))) | ||
| 283 | return 0; | ||
| 284 | |||
| 279 | while (bref < p+max) { | 285 | while (bref < p+max) { |
| 280 | blk = le32_to_cpu(*bref++); | 286 | blk = le32_to_cpu(*bref++); |
| 281 | if (blk && | 287 | if (blk && |
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 0f89f5190cd7..f2c62e2a0c98 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
| @@ -1035,6 +1035,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, | |||
| 1035 | __le32 border; | 1035 | __le32 border; |
| 1036 | ext4_fsblk_t *ablocks = NULL; /* array of allocated blocks */ | 1036 | ext4_fsblk_t *ablocks = NULL; /* array of allocated blocks */ |
| 1037 | int err = 0; | 1037 | int err = 0; |
| 1038 | size_t ext_size = 0; | ||
| 1038 | 1039 | ||
| 1039 | /* make decision: where to split? */ | 1040 | /* make decision: where to split? */ |
| 1040 | /* FIXME: now decision is simplest: at current extent */ | 1041 | /* FIXME: now decision is simplest: at current extent */ |
| @@ -1126,6 +1127,10 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, | |||
| 1126 | le16_add_cpu(&neh->eh_entries, m); | 1127 | le16_add_cpu(&neh->eh_entries, m); |
| 1127 | } | 1128 | } |
| 1128 | 1129 | ||
| 1130 | /* zero out unused area in the extent block */ | ||
| 1131 | ext_size = sizeof(struct ext4_extent_header) + | ||
| 1132 | sizeof(struct ext4_extent) * le16_to_cpu(neh->eh_entries); | ||
| 1133 | memset(bh->b_data + ext_size, 0, inode->i_sb->s_blocksize - ext_size); | ||
| 1129 | ext4_extent_block_csum_set(inode, neh); | 1134 | ext4_extent_block_csum_set(inode, neh); |
| 1130 | set_buffer_uptodate(bh); | 1135 | set_buffer_uptodate(bh); |
| 1131 | unlock_buffer(bh); | 1136 | unlock_buffer(bh); |
| @@ -1205,6 +1210,11 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, | |||
| 1205 | sizeof(struct ext4_extent_idx) * m); | 1210 | sizeof(struct ext4_extent_idx) * m); |
| 1206 | le16_add_cpu(&neh->eh_entries, m); | 1211 | le16_add_cpu(&neh->eh_entries, m); |
| 1207 | } | 1212 | } |
| 1213 | /* zero out unused area in the extent block */ | ||
| 1214 | ext_size = sizeof(struct ext4_extent_header) + | ||
| 1215 | (sizeof(struct ext4_extent) * le16_to_cpu(neh->eh_entries)); | ||
| 1216 | memset(bh->b_data + ext_size, 0, | ||
| 1217 | inode->i_sb->s_blocksize - ext_size); | ||
| 1208 | ext4_extent_block_csum_set(inode, neh); | 1218 | ext4_extent_block_csum_set(inode, neh); |
| 1209 | set_buffer_uptodate(bh); | 1219 | set_buffer_uptodate(bh); |
| 1210 | unlock_buffer(bh); | 1220 | unlock_buffer(bh); |
| @@ -1270,6 +1280,7 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode, | |||
| 1270 | ext4_fsblk_t newblock, goal = 0; | 1280 | ext4_fsblk_t newblock, goal = 0; |
| 1271 | struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es; | 1281 | struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es; |
| 1272 | int err = 0; | 1282 | int err = 0; |
| 1283 | size_t ext_size = 0; | ||
| 1273 | 1284 | ||
| 1274 | /* Try to prepend new index to old one */ | 1285 | /* Try to prepend new index to old one */ |
| 1275 | if (ext_depth(inode)) | 1286 | if (ext_depth(inode)) |
| @@ -1295,9 +1306,11 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode, | |||
| 1295 | goto out; | 1306 | goto out; |
| 1296 | } | 1307 | } |
| 1297 | 1308 | ||
| 1309 | ext_size = sizeof(EXT4_I(inode)->i_data); | ||
| 1298 | /* move top-level index/leaf into new block */ | 1310 | /* move top-level index/leaf into new block */ |
| 1299 | memmove(bh->b_data, EXT4_I(inode)->i_data, | 1311 | memmove(bh->b_data, EXT4_I(inode)->i_data, ext_size); |
| 1300 | sizeof(EXT4_I(inode)->i_data)); | 1312 | /* zero out unused area in the extent block */ |
| 1313 | memset(bh->b_data + ext_size, 0, inode->i_sb->s_blocksize - ext_size); | ||
| 1301 | 1314 | ||
| 1302 | /* set size of new block */ | 1315 | /* set size of new block */ |
| 1303 | neh = ext_block_hdr(bh); | 1316 | neh = ext_block_hdr(bh); |
diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 98ec11f69cd4..2c5baa5e8291 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c | |||
| @@ -264,6 +264,13 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from) | |||
| 264 | } | 264 | } |
| 265 | 265 | ||
| 266 | ret = __generic_file_write_iter(iocb, from); | 266 | ret = __generic_file_write_iter(iocb, from); |
| 267 | /* | ||
| 268 | * Unaligned direct AIO must be the only IO in flight. Otherwise | ||
| 269 | * overlapping aligned IO after unaligned might result in data | ||
| 270 | * corruption. | ||
| 271 | */ | ||
| 272 | if (ret == -EIOCBQUEUED && unaligned_aio) | ||
| 273 | ext4_unwritten_wait(inode); | ||
| 267 | inode_unlock(inode); | 274 | inode_unlock(inode); |
| 268 | 275 | ||
| 269 | if (ret > 0) | 276 | if (ret > 0) |
diff --git a/fs/ext4/fsmap.c b/fs/ext4/fsmap.c index 4b99e2db95b8..dbccf46f1770 100644 --- a/fs/ext4/fsmap.c +++ b/fs/ext4/fsmap.c | |||
| @@ -626,7 +626,7 @@ int ext4_getfsmap(struct super_block *sb, struct ext4_fsmap_head *head, | |||
| 626 | { | 626 | { |
| 627 | struct ext4_fsmap dkeys[2]; /* per-dev keys */ | 627 | struct ext4_fsmap dkeys[2]; /* per-dev keys */ |
| 628 | struct ext4_getfsmap_dev handlers[EXT4_GETFSMAP_DEVS]; | 628 | struct ext4_getfsmap_dev handlers[EXT4_GETFSMAP_DEVS]; |
| 629 | struct ext4_getfsmap_info info = {0}; | 629 | struct ext4_getfsmap_info info = { NULL }; |
| 630 | int i; | 630 | int i; |
| 631 | int error = 0; | 631 | int error = 0; |
| 632 | 632 | ||
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index 7e85ecf0b849..e486e49b31ed 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c | |||
| @@ -608,7 +608,7 @@ static int ext4_getfsmap_format(struct ext4_fsmap *xfm, void *priv) | |||
| 608 | static int ext4_ioc_getfsmap(struct super_block *sb, | 608 | static int ext4_ioc_getfsmap(struct super_block *sb, |
| 609 | struct fsmap_head __user *arg) | 609 | struct fsmap_head __user *arg) |
| 610 | { | 610 | { |
| 611 | struct getfsmap_info info = {0}; | 611 | struct getfsmap_info info = { NULL }; |
| 612 | struct ext4_fsmap_head xhead = {0}; | 612 | struct ext4_fsmap_head xhead = {0}; |
| 613 | struct fsmap_head head; | 613 | struct fsmap_head head; |
| 614 | bool aborted = false; | 614 | bool aborted = false; |
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 6d50f53b7a15..cd01c4a67ffb 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c | |||
| @@ -872,12 +872,15 @@ static void dx_release(struct dx_frame *frames) | |||
| 872 | { | 872 | { |
| 873 | struct dx_root_info *info; | 873 | struct dx_root_info *info; |
| 874 | int i; | 874 | int i; |
| 875 | unsigned int indirect_levels; | ||
| 875 | 876 | ||
| 876 | if (frames[0].bh == NULL) | 877 | if (frames[0].bh == NULL) |
| 877 | return; | 878 | return; |
| 878 | 879 | ||
| 879 | info = &((struct dx_root *)frames[0].bh->b_data)->info; | 880 | info = &((struct dx_root *)frames[0].bh->b_data)->info; |
| 880 | for (i = 0; i <= info->indirect_levels; i++) { | 881 | /* save local copy, "info" may be freed after brelse() */ |
| 882 | indirect_levels = info->indirect_levels; | ||
| 883 | for (i = 0; i <= indirect_levels; i++) { | ||
| 881 | if (frames[i].bh == NULL) | 884 | if (frames[i].bh == NULL) |
| 882 | break; | 885 | break; |
| 883 | brelse(frames[i].bh); | 886 | brelse(frames[i].bh); |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index f71b5254a990..4079605d437a 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
| @@ -699,7 +699,7 @@ void __ext4_abort(struct super_block *sb, const char *function, | |||
| 699 | jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO); | 699 | jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO); |
| 700 | save_error_info(sb, function, line); | 700 | save_error_info(sb, function, line); |
| 701 | } | 701 | } |
| 702 | if (test_opt(sb, ERRORS_PANIC)) { | 702 | if (test_opt(sb, ERRORS_PANIC) && !system_going_down()) { |
| 703 | if (EXT4_SB(sb)->s_journal && | 703 | if (EXT4_SB(sb)->s_journal && |
| 704 | !(EXT4_SB(sb)->s_journal->j_flags & JBD2_REC_ERR)) | 704 | !(EXT4_SB(sb)->s_journal->j_flags & JBD2_REC_ERR)) |
| 705 | return; | 705 | return; |
| @@ -4661,7 +4661,7 @@ failed_mount: | |||
| 4661 | 4661 | ||
| 4662 | #ifdef CONFIG_QUOTA | 4662 | #ifdef CONFIG_QUOTA |
| 4663 | for (i = 0; i < EXT4_MAXQUOTAS; i++) | 4663 | for (i = 0; i < EXT4_MAXQUOTAS; i++) |
| 4664 | kfree(sbi->s_qf_names[i]); | 4664 | kfree(get_qf_name(sb, sbi, i)); |
| 4665 | #endif | 4665 | #endif |
| 4666 | ext4_blkdev_remove(sbi); | 4666 | ext4_blkdev_remove(sbi); |
| 4667 | brelse(bh); | 4667 | brelse(bh); |
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 37e16d969925..43df0c943229 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c | |||
| @@ -2375,22 +2375,19 @@ static struct kmem_cache *jbd2_journal_head_cache; | |||
| 2375 | static atomic_t nr_journal_heads = ATOMIC_INIT(0); | 2375 | static atomic_t nr_journal_heads = ATOMIC_INIT(0); |
| 2376 | #endif | 2376 | #endif |
| 2377 | 2377 | ||
| 2378 | static int jbd2_journal_init_journal_head_cache(void) | 2378 | static int __init jbd2_journal_init_journal_head_cache(void) |
| 2379 | { | 2379 | { |
| 2380 | int retval; | 2380 | J_ASSERT(!jbd2_journal_head_cache); |
| 2381 | |||
| 2382 | J_ASSERT(jbd2_journal_head_cache == NULL); | ||
| 2383 | jbd2_journal_head_cache = kmem_cache_create("jbd2_journal_head", | 2381 | jbd2_journal_head_cache = kmem_cache_create("jbd2_journal_head", |
| 2384 | sizeof(struct journal_head), | 2382 | sizeof(struct journal_head), |
| 2385 | 0, /* offset */ | 2383 | 0, /* offset */ |
| 2386 | SLAB_TEMPORARY | SLAB_TYPESAFE_BY_RCU, | 2384 | SLAB_TEMPORARY | SLAB_TYPESAFE_BY_RCU, |
| 2387 | NULL); /* ctor */ | 2385 | NULL); /* ctor */ |
| 2388 | retval = 0; | ||
| 2389 | if (!jbd2_journal_head_cache) { | 2386 | if (!jbd2_journal_head_cache) { |
| 2390 | retval = -ENOMEM; | ||
| 2391 | printk(KERN_EMERG "JBD2: no memory for journal_head cache\n"); | 2387 | printk(KERN_EMERG "JBD2: no memory for journal_head cache\n"); |
| 2388 | return -ENOMEM; | ||
| 2392 | } | 2389 | } |
| 2393 | return retval; | 2390 | return 0; |
| 2394 | } | 2391 | } |
| 2395 | 2392 | ||
| 2396 | static void jbd2_journal_destroy_journal_head_cache(void) | 2393 | static void jbd2_journal_destroy_journal_head_cache(void) |
| @@ -2636,28 +2633,38 @@ static void __exit jbd2_remove_jbd_stats_proc_entry(void) | |||
| 2636 | 2633 | ||
| 2637 | struct kmem_cache *jbd2_handle_cache, *jbd2_inode_cache; | 2634 | struct kmem_cache *jbd2_handle_cache, *jbd2_inode_cache; |
| 2638 | 2635 | ||
| 2636 | static int __init jbd2_journal_init_inode_cache(void) | ||
| 2637 | { | ||
| 2638 | J_ASSERT(!jbd2_inode_cache); | ||
| 2639 | jbd2_inode_cache = KMEM_CACHE(jbd2_inode, 0); | ||
| 2640 | if (!jbd2_inode_cache) { | ||
| 2641 | pr_emerg("JBD2: failed to create inode cache\n"); | ||
| 2642 | return -ENOMEM; | ||
| 2643 | } | ||
| 2644 | return 0; | ||
| 2645 | } | ||
| 2646 | |||
| 2639 | static int __init jbd2_journal_init_handle_cache(void) | 2647 | static int __init jbd2_journal_init_handle_cache(void) |
| 2640 | { | 2648 | { |
| 2649 | J_ASSERT(!jbd2_handle_cache); | ||
| 2641 | jbd2_handle_cache = KMEM_CACHE(jbd2_journal_handle, SLAB_TEMPORARY); | 2650 | jbd2_handle_cache = KMEM_CACHE(jbd2_journal_handle, SLAB_TEMPORARY); |
| 2642 | if (jbd2_handle_cache == NULL) { | 2651 | if (!jbd2_handle_cache) { |
| 2643 | printk(KERN_EMERG "JBD2: failed to create handle cache\n"); | 2652 | printk(KERN_EMERG "JBD2: failed to create handle cache\n"); |
| 2644 | return -ENOMEM; | 2653 | return -ENOMEM; |
| 2645 | } | 2654 | } |
| 2646 | jbd2_inode_cache = KMEM_CACHE(jbd2_inode, 0); | ||
| 2647 | if (jbd2_inode_cache == NULL) { | ||
| 2648 | printk(KERN_EMERG "JBD2: failed to create inode cache\n"); | ||
| 2649 | kmem_cache_destroy(jbd2_handle_cache); | ||
| 2650 | return -ENOMEM; | ||
| 2651 | } | ||
| 2652 | return 0; | 2655 | return 0; |
| 2653 | } | 2656 | } |
| 2654 | 2657 | ||
| 2658 | static void jbd2_journal_destroy_inode_cache(void) | ||
| 2659 | { | ||
| 2660 | kmem_cache_destroy(jbd2_inode_cache); | ||
| 2661 | jbd2_inode_cache = NULL; | ||
| 2662 | } | ||
| 2663 | |||
| 2655 | static void jbd2_journal_destroy_handle_cache(void) | 2664 | static void jbd2_journal_destroy_handle_cache(void) |
| 2656 | { | 2665 | { |
| 2657 | kmem_cache_destroy(jbd2_handle_cache); | 2666 | kmem_cache_destroy(jbd2_handle_cache); |
| 2658 | jbd2_handle_cache = NULL; | 2667 | jbd2_handle_cache = NULL; |
| 2659 | kmem_cache_destroy(jbd2_inode_cache); | ||
| 2660 | jbd2_inode_cache = NULL; | ||
| 2661 | } | 2668 | } |
| 2662 | 2669 | ||
| 2663 | /* | 2670 | /* |
| @@ -2668,21 +2675,27 @@ static int __init journal_init_caches(void) | |||
| 2668 | { | 2675 | { |
| 2669 | int ret; | 2676 | int ret; |
| 2670 | 2677 | ||
| 2671 | ret = jbd2_journal_init_revoke_caches(); | 2678 | ret = jbd2_journal_init_revoke_record_cache(); |
| 2679 | if (ret == 0) | ||
| 2680 | ret = jbd2_journal_init_revoke_table_cache(); | ||
| 2672 | if (ret == 0) | 2681 | if (ret == 0) |
| 2673 | ret = jbd2_journal_init_journal_head_cache(); | 2682 | ret = jbd2_journal_init_journal_head_cache(); |
| 2674 | if (ret == 0) | 2683 | if (ret == 0) |
| 2675 | ret = jbd2_journal_init_handle_cache(); | 2684 | ret = jbd2_journal_init_handle_cache(); |
| 2676 | if (ret == 0) | 2685 | if (ret == 0) |
| 2686 | ret = jbd2_journal_init_inode_cache(); | ||
| 2687 | if (ret == 0) | ||
| 2677 | ret = jbd2_journal_init_transaction_cache(); | 2688 | ret = jbd2_journal_init_transaction_cache(); |
| 2678 | return ret; | 2689 | return ret; |
| 2679 | } | 2690 | } |
| 2680 | 2691 | ||
| 2681 | static void jbd2_journal_destroy_caches(void) | 2692 | static void jbd2_journal_destroy_caches(void) |
| 2682 | { | 2693 | { |
| 2683 | jbd2_journal_destroy_revoke_caches(); | 2694 | jbd2_journal_destroy_revoke_record_cache(); |
| 2695 | jbd2_journal_destroy_revoke_table_cache(); | ||
| 2684 | jbd2_journal_destroy_journal_head_cache(); | 2696 | jbd2_journal_destroy_journal_head_cache(); |
| 2685 | jbd2_journal_destroy_handle_cache(); | 2697 | jbd2_journal_destroy_handle_cache(); |
| 2698 | jbd2_journal_destroy_inode_cache(); | ||
| 2686 | jbd2_journal_destroy_transaction_cache(); | 2699 | jbd2_journal_destroy_transaction_cache(); |
| 2687 | jbd2_journal_destroy_slabs(); | 2700 | jbd2_journal_destroy_slabs(); |
| 2688 | } | 2701 | } |
diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c index a1143e57a718..69b9bc329964 100644 --- a/fs/jbd2/revoke.c +++ b/fs/jbd2/revoke.c | |||
| @@ -178,33 +178,41 @@ static struct jbd2_revoke_record_s *find_revoke_record(journal_t *journal, | |||
| 178 | return NULL; | 178 | return NULL; |
| 179 | } | 179 | } |
| 180 | 180 | ||
| 181 | void jbd2_journal_destroy_revoke_caches(void) | 181 | void jbd2_journal_destroy_revoke_record_cache(void) |
| 182 | { | 182 | { |
| 183 | kmem_cache_destroy(jbd2_revoke_record_cache); | 183 | kmem_cache_destroy(jbd2_revoke_record_cache); |
| 184 | jbd2_revoke_record_cache = NULL; | 184 | jbd2_revoke_record_cache = NULL; |
| 185 | } | ||
| 186 | |||
| 187 | void jbd2_journal_destroy_revoke_table_cache(void) | ||
| 188 | { | ||
| 185 | kmem_cache_destroy(jbd2_revoke_table_cache); | 189 | kmem_cache_destroy(jbd2_revoke_table_cache); |
| 186 | jbd2_revoke_table_cache = NULL; | 190 | jbd2_revoke_table_cache = NULL; |
| 187 | } | 191 | } |
| 188 | 192 | ||
| 189 | int __init jbd2_journal_init_revoke_caches(void) | 193 | int __init jbd2_journal_init_revoke_record_cache(void) |
| 190 | { | 194 | { |
| 191 | J_ASSERT(!jbd2_revoke_record_cache); | 195 | J_ASSERT(!jbd2_revoke_record_cache); |
| 192 | J_ASSERT(!jbd2_revoke_table_cache); | ||
| 193 | |||
| 194 | jbd2_revoke_record_cache = KMEM_CACHE(jbd2_revoke_record_s, | 196 | jbd2_revoke_record_cache = KMEM_CACHE(jbd2_revoke_record_s, |
| 195 | SLAB_HWCACHE_ALIGN|SLAB_TEMPORARY); | 197 | SLAB_HWCACHE_ALIGN|SLAB_TEMPORARY); |
| 196 | if (!jbd2_revoke_record_cache) | ||
| 197 | goto record_cache_failure; | ||
| 198 | 198 | ||
| 199 | if (!jbd2_revoke_record_cache) { | ||
| 200 | pr_emerg("JBD2: failed to create revoke_record cache\n"); | ||
| 201 | return -ENOMEM; | ||
| 202 | } | ||
| 203 | return 0; | ||
| 204 | } | ||
| 205 | |||
| 206 | int __init jbd2_journal_init_revoke_table_cache(void) | ||
| 207 | { | ||
| 208 | J_ASSERT(!jbd2_revoke_table_cache); | ||
| 199 | jbd2_revoke_table_cache = KMEM_CACHE(jbd2_revoke_table_s, | 209 | jbd2_revoke_table_cache = KMEM_CACHE(jbd2_revoke_table_s, |
| 200 | SLAB_TEMPORARY); | 210 | SLAB_TEMPORARY); |
| 201 | if (!jbd2_revoke_table_cache) | 211 | if (!jbd2_revoke_table_cache) { |
| 202 | goto table_cache_failure; | 212 | pr_emerg("JBD2: failed to create revoke_table cache\n"); |
| 203 | return 0; | ||
| 204 | table_cache_failure: | ||
| 205 | jbd2_journal_destroy_revoke_caches(); | ||
| 206 | record_cache_failure: | ||
| 207 | return -ENOMEM; | 213 | return -ENOMEM; |
| 214 | } | ||
| 215 | return 0; | ||
| 208 | } | 216 | } |
| 209 | 217 | ||
| 210 | static struct jbd2_revoke_table_s *jbd2_journal_init_revoke_table(int hash_size) | 218 | static struct jbd2_revoke_table_s *jbd2_journal_init_revoke_table(int hash_size) |
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index f940d31c2adc..8ca4fddc705f 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c | |||
| @@ -42,9 +42,11 @@ int __init jbd2_journal_init_transaction_cache(void) | |||
| 42 | 0, | 42 | 0, |
| 43 | SLAB_HWCACHE_ALIGN|SLAB_TEMPORARY, | 43 | SLAB_HWCACHE_ALIGN|SLAB_TEMPORARY, |
| 44 | NULL); | 44 | NULL); |
| 45 | if (transaction_cache) | 45 | if (!transaction_cache) { |
| 46 | return 0; | 46 | pr_emerg("JBD2: failed to create transaction cache\n"); |
| 47 | return -ENOMEM; | 47 | return -ENOMEM; |
| 48 | } | ||
| 49 | return 0; | ||
| 48 | } | 50 | } |
| 49 | 51 | ||
| 50 | void jbd2_journal_destroy_transaction_cache(void) | 52 | void jbd2_journal_destroy_transaction_cache(void) |
diff --git a/fs/ocfs2/dlm/Makefile b/fs/ocfs2/dlm/Makefile index ef2854422a6e..3d4041f0431e 100644 --- a/fs/ocfs2/dlm/Makefile +++ b/fs/ocfs2/dlm/Makefile | |||
| @@ -1,7 +1,6 @@ | |||
| 1 | ccflags-y := -I$(src)/.. | 1 | ccflags-y := -I $(srctree)/$(src)/.. |
| 2 | 2 | ||
| 3 | obj-$(CONFIG_OCFS2_FS_O2CB) += ocfs2_dlm.o | 3 | obj-$(CONFIG_OCFS2_FS_O2CB) += ocfs2_dlm.o |
| 4 | 4 | ||
| 5 | ocfs2_dlm-objs := dlmdomain.o dlmdebug.o dlmthread.o dlmrecovery.o \ | 5 | ocfs2_dlm-objs := dlmdomain.o dlmdebug.o dlmthread.o dlmrecovery.o \ |
| 6 | dlmmaster.o dlmast.o dlmconvert.o dlmlock.o dlmunlock.o | 6 | dlmmaster.o dlmast.o dlmconvert.o dlmlock.o dlmunlock.o |
| 7 | |||
diff --git a/fs/ocfs2/dlmfs/Makefile b/fs/ocfs2/dlmfs/Makefile index 33431a0296a3..0a0b93d940fe 100644 --- a/fs/ocfs2/dlmfs/Makefile +++ b/fs/ocfs2/dlmfs/Makefile | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | ccflags-y := -I$(src)/.. | 1 | ccflags-y := -I $(srctree)/$(src)/.. |
| 2 | 2 | ||
| 3 | obj-$(CONFIG_OCFS2_FS) += ocfs2_dlmfs.o | 3 | obj-$(CONFIG_OCFS2_FS) += ocfs2_dlmfs.o |
| 4 | 4 | ||
diff --git a/fs/unicode/README.utf8data b/fs/unicode/README.utf8data index 9307cf0727de..c73786807d3b 100644 --- a/fs/unicode/README.utf8data +++ b/fs/unicode/README.utf8data | |||
| @@ -5,29 +5,15 @@ The full set of files can be found here: | |||
| 5 | 5 | ||
| 6 | http://www.unicode.org/Public/12.1.0/ucd/ | 6 | http://www.unicode.org/Public/12.1.0/ucd/ |
| 7 | 7 | ||
| 8 | Note! | ||
| 9 | |||
| 10 | The URL's listed below are not stable. That's because Unicode 12.1.0 | ||
| 11 | has not been officially released yet; it is scheduled to be released | ||
| 12 | on May 8, 2019. We taking Unicode 12.1.0 a few weeks early because it | ||
| 13 | contains a new Japanese character which is required in order to | ||
| 14 | specify Japenese dates after May 1, 2019, when Crown Prince Naruhito | ||
| 15 | ascends to the Chrysanthemum Throne. (Isn't internationalization fun? | ||
| 16 | The abdication of Emperor Akihito of Japan is requiring dozens of | ||
| 17 | software packages to be updated with only a month's notice. :-) | ||
| 18 | |||
| 19 | We will update the URL's (and any needed changes to the checksums) | ||
| 20 | after the final Unicode 12.1.0 is released. | ||
| 21 | |||
| 22 | Individual source links: | 8 | Individual source links: |
| 23 | 9 | ||
| 24 | https://www.unicode.org/Public/12.1.0/ucd/CaseFolding-12.1.0d2.txt | 10 | https://www.unicode.org/Public/12.1.0/ucd/CaseFolding.txt |
| 25 | https://www.unicode.org/Public/12.1.0/ucd/DerivedAge-12.1.0d3.txt | 11 | https://www.unicode.org/Public/12.1.0/ucd/DerivedAge.txt |
| 26 | https://www.unicode.org/Public/12.1.0/ucd/extracted/DerivedCombiningClass-12.1.0d2.txt | 12 | https://www.unicode.org/Public/12.1.0/ucd/extracted/DerivedCombiningClass.txt |
| 27 | https://www.unicode.org/Public/12.1.0/ucd/DerivedCoreProperties-12.1.0d2.txt | 13 | https://www.unicode.org/Public/12.1.0/ucd/DerivedCoreProperties.txt |
| 28 | https://www.unicode.org/Public/12.1.0/ucd/NormalizationCorrections-12.1.0d1.txt | 14 | https://www.unicode.org/Public/12.1.0/ucd/NormalizationCorrections.txt |
| 29 | https://www.unicode.org/Public/12.1.0/ucd/NormalizationTest-12.1.0d3.txt | 15 | https://www.unicode.org/Public/12.1.0/ucd/NormalizationTest.txt |
| 30 | https://www.unicode.org/Public/12.1.0/ucd/UnicodeData-12.1.0d2.txt | 16 | https://www.unicode.org/Public/12.1.0/ucd/UnicodeData.txt |
| 31 | 17 | ||
| 32 | md5sums (verify by running "md5sum -c README.utf8data"): | 18 | md5sums (verify by running "md5sum -c README.utf8data"): |
| 33 | 19 | ||
diff --git a/fs/unicode/utf8-norm.c b/fs/unicode/utf8-norm.c index 20d440c3f2db..801ed6d2ea37 100644 --- a/fs/unicode/utf8-norm.c +++ b/fs/unicode/utf8-norm.c | |||
| @@ -714,6 +714,8 @@ int utf8byte(struct utf8cursor *u8c) | |||
| 714 | } | 714 | } |
| 715 | 715 | ||
| 716 | leaf = utf8lookup(u8c->data, u8c->hangul, u8c->s); | 716 | leaf = utf8lookup(u8c->data, u8c->hangul, u8c->s); |
| 717 | if (!leaf) | ||
| 718 | return -1; | ||
| 717 | ccc = LEAF_CCC(leaf); | 719 | ccc = LEAF_CCC(leaf); |
| 718 | } | 720 | } |
| 719 | 721 | ||
diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index 1dfc6df2e2bd..91831975363b 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile | |||
| @@ -4,8 +4,8 @@ | |||
| 4 | # All Rights Reserved. | 4 | # All Rights Reserved. |
| 5 | # | 5 | # |
| 6 | 6 | ||
| 7 | ccflags-y += -I$(src) # needed for trace events | 7 | ccflags-y += -I $(srctree)/$(src) # needed for trace events |
| 8 | ccflags-y += -I$(src)/libxfs | 8 | ccflags-y += -I $(srctree)/$(src)/libxfs |
| 9 | 9 | ||
| 10 | ccflags-$(CONFIG_XFS_DEBUG) += -g | 10 | ccflags-$(CONFIG_XFS_DEBUG) += -g |
| 11 | 11 | ||
diff --git a/include/asm-generic/mm_hooks.h b/include/asm-generic/mm_hooks.h index 8ac4e68a12f0..6736ed2f632b 100644 --- a/include/asm-generic/mm_hooks.h +++ b/include/asm-generic/mm_hooks.h | |||
| @@ -18,7 +18,6 @@ static inline void arch_exit_mmap(struct mm_struct *mm) | |||
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | static inline void arch_unmap(struct mm_struct *mm, | 20 | static inline void arch_unmap(struct mm_struct *mm, |
| 21 | struct vm_area_struct *vma, | ||
| 22 | unsigned long start, unsigned long end) | 21 | unsigned long start, unsigned long end) |
| 23 | { | 22 | { |
| 24 | } | 23 | } |
diff --git a/include/linux/clk/at91_pmc.h b/include/linux/clk/at91_pmc.h index 0c53f26ae3d3..44e8fc30b889 100644 --- a/include/linux/clk/at91_pmc.h +++ b/include/linux/clk/at91_pmc.h | |||
| @@ -161,6 +161,7 @@ | |||
| 161 | 161 | ||
| 162 | #define AT91_PMC_FSMR 0x70 /* Fast Startup Mode Register */ | 162 | #define AT91_PMC_FSMR 0x70 /* Fast Startup Mode Register */ |
| 163 | #define AT91_PMC_FSTT(n) BIT(n) | 163 | #define AT91_PMC_FSTT(n) BIT(n) |
| 164 | #define AT91_PMC_RTTAL BIT(16) | ||
| 164 | #define AT91_PMC_RTCAL BIT(17) /* RTC Alarm Enable */ | 165 | #define AT91_PMC_RTCAL BIT(17) /* RTC Alarm Enable */ |
| 165 | #define AT91_PMC_USBAL BIT(18) /* USB Resume Enable */ | 166 | #define AT91_PMC_USBAL BIT(18) /* USB Resume Enable */ |
| 166 | #define AT91_PMC_SDMMC_CD BIT(19) /* SDMMC Card Detect Enable */ | 167 | #define AT91_PMC_SDMMC_CD BIT(19) /* SDMMC Card Detect Enable */ |
diff --git a/include/linux/dma-iommu.h b/include/linux/dma-iommu.h index e760dc5d1fa8..476e0c54de2d 100644 --- a/include/linux/dma-iommu.h +++ b/include/linux/dma-iommu.h | |||
| @@ -71,12 +71,25 @@ void iommu_dma_unmap_resource(struct device *dev, dma_addr_t handle, | |||
| 71 | size_t size, enum dma_data_direction dir, unsigned long attrs); | 71 | size_t size, enum dma_data_direction dir, unsigned long attrs); |
| 72 | 72 | ||
| 73 | /* The DMA API isn't _quite_ the whole story, though... */ | 73 | /* The DMA API isn't _quite_ the whole story, though... */ |
| 74 | void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg); | 74 | /* |
| 75 | * iommu_dma_prepare_msi() - Map the MSI page in the IOMMU device | ||
| 76 | * | ||
| 77 | * The MSI page will be stored in @desc. | ||
| 78 | * | ||
| 79 | * Return: 0 on success otherwise an error describing the failure. | ||
| 80 | */ | ||
| 81 | int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr); | ||
| 82 | |||
| 83 | /* Update the MSI message if required. */ | ||
| 84 | void iommu_dma_compose_msi_msg(struct msi_desc *desc, | ||
| 85 | struct msi_msg *msg); | ||
| 86 | |||
| 75 | void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list); | 87 | void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list); |
| 76 | 88 | ||
| 77 | #else | 89 | #else |
| 78 | 90 | ||
| 79 | struct iommu_domain; | 91 | struct iommu_domain; |
| 92 | struct msi_desc; | ||
| 80 | struct msi_msg; | 93 | struct msi_msg; |
| 81 | struct device; | 94 | struct device; |
| 82 | 95 | ||
| @@ -99,7 +112,14 @@ static inline void iommu_put_dma_cookie(struct iommu_domain *domain) | |||
| 99 | { | 112 | { |
| 100 | } | 113 | } |
| 101 | 114 | ||
| 102 | static inline void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg) | 115 | static inline int iommu_dma_prepare_msi(struct msi_desc *desc, |
| 116 | phys_addr_t msi_addr) | ||
| 117 | { | ||
| 118 | return 0; | ||
| 119 | } | ||
| 120 | |||
| 121 | static inline void iommu_dma_compose_msi_msg(struct msi_desc *desc, | ||
| 122 | struct msi_msg *msg) | ||
| 103 | { | 123 | { |
| 104 | } | 124 | } |
| 105 | 125 | ||
diff --git a/include/linux/i2c.h b/include/linux/i2c.h index be27062f8ed1..6c4db54714f6 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h | |||
| @@ -470,6 +470,9 @@ extern struct i2c_client * | |||
| 470 | i2c_new_dummy(struct i2c_adapter *adap, u16 address); | 470 | i2c_new_dummy(struct i2c_adapter *adap, u16 address); |
| 471 | 471 | ||
| 472 | extern struct i2c_client * | 472 | extern struct i2c_client * |
| 473 | devm_i2c_new_dummy_device(struct device *dev, struct i2c_adapter *adap, u16 address); | ||
| 474 | |||
| 475 | extern struct i2c_client * | ||
| 473 | i2c_new_secondary_device(struct i2c_client *client, | 476 | i2c_new_secondary_device(struct i2c_client *client, |
| 474 | const char *name, | 477 | const char *name, |
| 475 | u16 default_addr); | 478 | u16 default_addr); |
diff --git a/include/linux/irq.h b/include/linux/irq.h index 7ae8de5ad0f2..fb301cf29148 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h | |||
| @@ -625,6 +625,8 @@ extern int irq_chip_set_wake_parent(struct irq_data *data, unsigned int on); | |||
| 625 | extern int irq_chip_set_vcpu_affinity_parent(struct irq_data *data, | 625 | extern int irq_chip_set_vcpu_affinity_parent(struct irq_data *data, |
| 626 | void *vcpu_info); | 626 | void *vcpu_info); |
| 627 | extern int irq_chip_set_type_parent(struct irq_data *data, unsigned int type); | 627 | extern int irq_chip_set_type_parent(struct irq_data *data, unsigned int type); |
| 628 | extern int irq_chip_request_resources_parent(struct irq_data *data); | ||
| 629 | extern void irq_chip_release_resources_parent(struct irq_data *data); | ||
| 628 | #endif | 630 | #endif |
| 629 | 631 | ||
| 630 | /* Handling of unhandled and spurious interrupts: */ | 632 | /* Handling of unhandled and spurious interrupts: */ |
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h index c848a7cc502e..c7e3e39224c6 100644 --- a/include/linux/irqchip/arm-gic-v3.h +++ b/include/linux/irqchip/arm-gic-v3.h | |||
| @@ -165,7 +165,7 @@ | |||
| 165 | #define GICR_PROPBASER_nCnB GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, nCnB) | 165 | #define GICR_PROPBASER_nCnB GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, nCnB) |
| 166 | #define GICR_PROPBASER_nC GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, nC) | 166 | #define GICR_PROPBASER_nC GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, nC) |
| 167 | #define GICR_PROPBASER_RaWt GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, RaWt) | 167 | #define GICR_PROPBASER_RaWt GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, RaWt) |
| 168 | #define GICR_PROPBASER_RaWb GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, RaWt) | 168 | #define GICR_PROPBASER_RaWb GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, RaWb) |
| 169 | #define GICR_PROPBASER_WaWt GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, WaWt) | 169 | #define GICR_PROPBASER_WaWt GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, WaWt) |
| 170 | #define GICR_PROPBASER_WaWb GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, WaWb) | 170 | #define GICR_PROPBASER_WaWb GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, WaWb) |
| 171 | #define GICR_PROPBASER_RaWaWt GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, RaWaWt) | 171 | #define GICR_PROPBASER_RaWaWt GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, RaWaWt) |
| @@ -192,7 +192,7 @@ | |||
| 192 | #define GICR_PENDBASER_nCnB GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, nCnB) | 192 | #define GICR_PENDBASER_nCnB GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, nCnB) |
| 193 | #define GICR_PENDBASER_nC GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, nC) | 193 | #define GICR_PENDBASER_nC GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, nC) |
| 194 | #define GICR_PENDBASER_RaWt GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, RaWt) | 194 | #define GICR_PENDBASER_RaWt GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, RaWt) |
| 195 | #define GICR_PENDBASER_RaWb GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, RaWt) | 195 | #define GICR_PENDBASER_RaWb GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, RaWb) |
| 196 | #define GICR_PENDBASER_WaWt GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, WaWt) | 196 | #define GICR_PENDBASER_WaWt GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, WaWt) |
| 197 | #define GICR_PENDBASER_WaWb GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, WaWb) | 197 | #define GICR_PENDBASER_WaWb GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, WaWb) |
| 198 | #define GICR_PENDBASER_RaWaWt GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, RaWaWt) | 198 | #define GICR_PENDBASER_RaWaWt GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, RaWaWt) |
| @@ -251,7 +251,7 @@ | |||
| 251 | #define GICR_VPROPBASER_nCnB GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, nCnB) | 251 | #define GICR_VPROPBASER_nCnB GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, nCnB) |
| 252 | #define GICR_VPROPBASER_nC GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, nC) | 252 | #define GICR_VPROPBASER_nC GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, nC) |
| 253 | #define GICR_VPROPBASER_RaWt GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, RaWt) | 253 | #define GICR_VPROPBASER_RaWt GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, RaWt) |
| 254 | #define GICR_VPROPBASER_RaWb GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, RaWt) | 254 | #define GICR_VPROPBASER_RaWb GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, RaWb) |
| 255 | #define GICR_VPROPBASER_WaWt GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, WaWt) | 255 | #define GICR_VPROPBASER_WaWt GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, WaWt) |
| 256 | #define GICR_VPROPBASER_WaWb GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, WaWb) | 256 | #define GICR_VPROPBASER_WaWb GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, WaWb) |
| 257 | #define GICR_VPROPBASER_RaWaWt GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, RaWaWt) | 257 | #define GICR_VPROPBASER_RaWaWt GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, RaWaWt) |
| @@ -277,7 +277,7 @@ | |||
| 277 | #define GICR_VPENDBASER_nCnB GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, nCnB) | 277 | #define GICR_VPENDBASER_nCnB GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, nCnB) |
| 278 | #define GICR_VPENDBASER_nC GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, nC) | 278 | #define GICR_VPENDBASER_nC GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, nC) |
| 279 | #define GICR_VPENDBASER_RaWt GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, RaWt) | 279 | #define GICR_VPENDBASER_RaWt GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, RaWt) |
| 280 | #define GICR_VPENDBASER_RaWb GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, RaWt) | 280 | #define GICR_VPENDBASER_RaWb GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, RaWb) |
| 281 | #define GICR_VPENDBASER_WaWt GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, WaWt) | 281 | #define GICR_VPENDBASER_WaWt GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, WaWt) |
| 282 | #define GICR_VPENDBASER_WaWb GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, WaWb) | 282 | #define GICR_VPENDBASER_WaWb GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, WaWb) |
| 283 | #define GICR_VPENDBASER_RaWaWt GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, RaWaWt) | 283 | #define GICR_VPENDBASER_RaWaWt GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, RaWaWt) |
| @@ -351,7 +351,7 @@ | |||
| 351 | #define GITS_CBASER_nCnB GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, nCnB) | 351 | #define GITS_CBASER_nCnB GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, nCnB) |
| 352 | #define GITS_CBASER_nC GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, nC) | 352 | #define GITS_CBASER_nC GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, nC) |
| 353 | #define GITS_CBASER_RaWt GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, RaWt) | 353 | #define GITS_CBASER_RaWt GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, RaWt) |
| 354 | #define GITS_CBASER_RaWb GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, RaWt) | 354 | #define GITS_CBASER_RaWb GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, RaWb) |
| 355 | #define GITS_CBASER_WaWt GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, WaWt) | 355 | #define GITS_CBASER_WaWt GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, WaWt) |
| 356 | #define GITS_CBASER_WaWb GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, WaWb) | 356 | #define GITS_CBASER_WaWb GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, WaWb) |
| 357 | #define GITS_CBASER_RaWaWt GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, RaWaWt) | 357 | #define GITS_CBASER_RaWaWt GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, RaWaWt) |
| @@ -377,7 +377,7 @@ | |||
| 377 | #define GITS_BASER_nCnB GIC_BASER_CACHEABILITY(GITS_BASER, INNER, nCnB) | 377 | #define GITS_BASER_nCnB GIC_BASER_CACHEABILITY(GITS_BASER, INNER, nCnB) |
| 378 | #define GITS_BASER_nC GIC_BASER_CACHEABILITY(GITS_BASER, INNER, nC) | 378 | #define GITS_BASER_nC GIC_BASER_CACHEABILITY(GITS_BASER, INNER, nC) |
| 379 | #define GITS_BASER_RaWt GIC_BASER_CACHEABILITY(GITS_BASER, INNER, RaWt) | 379 | #define GITS_BASER_RaWt GIC_BASER_CACHEABILITY(GITS_BASER, INNER, RaWt) |
| 380 | #define GITS_BASER_RaWb GIC_BASER_CACHEABILITY(GITS_BASER, INNER, RaWt) | 380 | #define GITS_BASER_RaWb GIC_BASER_CACHEABILITY(GITS_BASER, INNER, RaWb) |
| 381 | #define GITS_BASER_WaWt GIC_BASER_CACHEABILITY(GITS_BASER, INNER, WaWt) | 381 | #define GITS_BASER_WaWt GIC_BASER_CACHEABILITY(GITS_BASER, INNER, WaWt) |
| 382 | #define GITS_BASER_WaWb GIC_BASER_CACHEABILITY(GITS_BASER, INNER, WaWb) | 382 | #define GITS_BASER_WaWb GIC_BASER_CACHEABILITY(GITS_BASER, INNER, WaWb) |
| 383 | #define GITS_BASER_RaWaWt GIC_BASER_CACHEABILITY(GITS_BASER, INNER, RaWaWt) | 383 | #define GITS_BASER_RaWaWt GIC_BASER_CACHEABILITY(GITS_BASER, INNER, RaWaWt) |
diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h index 61706b430907..07ec8b390161 100644 --- a/include/linux/irqdomain.h +++ b/include/linux/irqdomain.h | |||
| @@ -82,6 +82,7 @@ enum irq_domain_bus_token { | |||
| 82 | DOMAIN_BUS_NEXUS, | 82 | DOMAIN_BUS_NEXUS, |
| 83 | DOMAIN_BUS_IPI, | 83 | DOMAIN_BUS_IPI, |
| 84 | DOMAIN_BUS_FSL_MC_MSI, | 84 | DOMAIN_BUS_FSL_MC_MSI, |
| 85 | DOMAIN_BUS_TI_SCI_INTA_MSI, | ||
| 85 | }; | 86 | }; |
| 86 | 87 | ||
| 87 | /** | 88 | /** |
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h index c2ffff5f9ae2..6c9870e16b19 100644 --- a/include/linux/jbd2.h +++ b/include/linux/jbd2.h | |||
| @@ -1318,7 +1318,7 @@ extern void __wait_on_journal (journal_t *); | |||
| 1318 | 1318 | ||
| 1319 | /* Transaction cache support */ | 1319 | /* Transaction cache support */ |
| 1320 | extern void jbd2_journal_destroy_transaction_cache(void); | 1320 | extern void jbd2_journal_destroy_transaction_cache(void); |
| 1321 | extern int jbd2_journal_init_transaction_cache(void); | 1321 | extern int __init jbd2_journal_init_transaction_cache(void); |
| 1322 | extern void jbd2_journal_free_transaction(transaction_t *); | 1322 | extern void jbd2_journal_free_transaction(transaction_t *); |
| 1323 | 1323 | ||
| 1324 | /* | 1324 | /* |
| @@ -1446,8 +1446,10 @@ static inline void jbd2_free_inode(struct jbd2_inode *jinode) | |||
| 1446 | /* Primary revoke support */ | 1446 | /* Primary revoke support */ |
| 1447 | #define JOURNAL_REVOKE_DEFAULT_HASH 256 | 1447 | #define JOURNAL_REVOKE_DEFAULT_HASH 256 |
| 1448 | extern int jbd2_journal_init_revoke(journal_t *, int); | 1448 | extern int jbd2_journal_init_revoke(journal_t *, int); |
| 1449 | extern void jbd2_journal_destroy_revoke_caches(void); | 1449 | extern void jbd2_journal_destroy_revoke_record_cache(void); |
| 1450 | extern int jbd2_journal_init_revoke_caches(void); | 1450 | extern void jbd2_journal_destroy_revoke_table_cache(void); |
| 1451 | extern int __init jbd2_journal_init_revoke_record_cache(void); | ||
| 1452 | extern int __init jbd2_journal_init_revoke_table_cache(void); | ||
| 1451 | 1453 | ||
| 1452 | extern void jbd2_journal_destroy_revoke(journal_t *); | 1454 | extern void jbd2_journal_destroy_revoke(journal_t *); |
| 1453 | extern int jbd2_journal_revoke (handle_t *, unsigned long long, struct buffer_head *); | 1455 | extern int jbd2_journal_revoke (handle_t *, unsigned long long, struct buffer_head *); |
diff --git a/include/linux/msi.h b/include/linux/msi.h index 052f04fcf953..d48e919d55ae 100644 --- a/include/linux/msi.h +++ b/include/linux/msi.h | |||
| @@ -48,6 +48,14 @@ struct fsl_mc_msi_desc { | |||
| 48 | }; | 48 | }; |
| 49 | 49 | ||
| 50 | /** | 50 | /** |
| 51 | * ti_sci_inta_msi_desc - TISCI based INTA specific msi descriptor data | ||
| 52 | * @dev_index: TISCI device index | ||
| 53 | */ | ||
| 54 | struct ti_sci_inta_msi_desc { | ||
| 55 | u16 dev_index; | ||
| 56 | }; | ||
| 57 | |||
| 58 | /** | ||
| 51 | * struct msi_desc - Descriptor structure for MSI based interrupts | 59 | * struct msi_desc - Descriptor structure for MSI based interrupts |
| 52 | * @list: List head for management | 60 | * @list: List head for management |
| 53 | * @irq: The base interrupt number | 61 | * @irq: The base interrupt number |
| @@ -68,6 +76,7 @@ struct fsl_mc_msi_desc { | |||
| 68 | * @mask_base: [PCI MSI-X] Mask register base address | 76 | * @mask_base: [PCI MSI-X] Mask register base address |
| 69 | * @platform: [platform] Platform device specific msi descriptor data | 77 | * @platform: [platform] Platform device specific msi descriptor data |
| 70 | * @fsl_mc: [fsl-mc] FSL MC device specific msi descriptor data | 78 | * @fsl_mc: [fsl-mc] FSL MC device specific msi descriptor data |
| 79 | * @inta: [INTA] TISCI based INTA specific msi descriptor data | ||
| 71 | */ | 80 | */ |
| 72 | struct msi_desc { | 81 | struct msi_desc { |
| 73 | /* Shared device/bus type independent data */ | 82 | /* Shared device/bus type independent data */ |
| @@ -77,6 +86,9 @@ struct msi_desc { | |||
| 77 | struct device *dev; | 86 | struct device *dev; |
| 78 | struct msi_msg msg; | 87 | struct msi_msg msg; |
| 79 | struct irq_affinity_desc *affinity; | 88 | struct irq_affinity_desc *affinity; |
| 89 | #ifdef CONFIG_IRQ_MSI_IOMMU | ||
| 90 | const void *iommu_cookie; | ||
| 91 | #endif | ||
| 80 | 92 | ||
| 81 | union { | 93 | union { |
| 82 | /* PCI MSI/X specific data */ | 94 | /* PCI MSI/X specific data */ |
| @@ -106,6 +118,7 @@ struct msi_desc { | |||
| 106 | */ | 118 | */ |
| 107 | struct platform_msi_desc platform; | 119 | struct platform_msi_desc platform; |
| 108 | struct fsl_mc_msi_desc fsl_mc; | 120 | struct fsl_mc_msi_desc fsl_mc; |
| 121 | struct ti_sci_inta_msi_desc inta; | ||
| 109 | }; | 122 | }; |
| 110 | }; | 123 | }; |
| 111 | 124 | ||
| @@ -119,6 +132,29 @@ struct msi_desc { | |||
| 119 | #define for_each_msi_entry_safe(desc, tmp, dev) \ | 132 | #define for_each_msi_entry_safe(desc, tmp, dev) \ |
| 120 | list_for_each_entry_safe((desc), (tmp), dev_to_msi_list((dev)), list) | 133 | list_for_each_entry_safe((desc), (tmp), dev_to_msi_list((dev)), list) |
| 121 | 134 | ||
| 135 | #ifdef CONFIG_IRQ_MSI_IOMMU | ||
| 136 | static inline const void *msi_desc_get_iommu_cookie(struct msi_desc *desc) | ||
| 137 | { | ||
| 138 | return desc->iommu_cookie; | ||
| 139 | } | ||
| 140 | |||
| 141 | static inline void msi_desc_set_iommu_cookie(struct msi_desc *desc, | ||
| 142 | const void *iommu_cookie) | ||
| 143 | { | ||
| 144 | desc->iommu_cookie = iommu_cookie; | ||
| 145 | } | ||
| 146 | #else | ||
| 147 | static inline const void *msi_desc_get_iommu_cookie(struct msi_desc *desc) | ||
| 148 | { | ||
| 149 | return NULL; | ||
| 150 | } | ||
| 151 | |||
| 152 | static inline void msi_desc_set_iommu_cookie(struct msi_desc *desc, | ||
| 153 | const void *iommu_cookie) | ||
| 154 | { | ||
| 155 | } | ||
| 156 | #endif | ||
| 157 | |||
| 122 | #ifdef CONFIG_PCI_MSI | 158 | #ifdef CONFIG_PCI_MSI |
| 123 | #define first_pci_msi_entry(pdev) first_msi_entry(&(pdev)->dev) | 159 | #define first_pci_msi_entry(pdev) first_msi_entry(&(pdev)->dev) |
| 124 | #define for_each_pci_msi_entry(desc, pdev) \ | 160 | #define for_each_pci_msi_entry(desc, pdev) \ |
diff --git a/include/linux/platform_data/xtalk-bridge.h b/include/linux/platform_data/xtalk-bridge.h new file mode 100644 index 000000000000..51e5001f2c05 --- /dev/null +++ b/include/linux/platform_data/xtalk-bridge.h | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | /* | ||
| 3 | * SGI PCI Xtalk Bridge | ||
| 4 | */ | ||
| 5 | |||
| 6 | #ifndef PLATFORM_DATA_XTALK_BRIDGE_H | ||
| 7 | #define PLATFORM_DATA_XTALK_BRIDGE_H | ||
| 8 | |||
| 9 | #include <asm/sn/types.h> | ||
| 10 | |||
| 11 | struct xtalk_bridge_platform_data { | ||
| 12 | struct resource mem; | ||
| 13 | struct resource io; | ||
| 14 | unsigned long bridge_addr; | ||
| 15 | unsigned long intr_addr; | ||
| 16 | unsigned long mem_offset; | ||
| 17 | unsigned long io_offset; | ||
| 18 | nasid_t nasid; | ||
| 19 | int masterwid; | ||
| 20 | }; | ||
| 21 | |||
| 22 | #endif /* PLATFORM_DATA_XTALK_BRIDGE_H */ | ||
diff --git a/include/linux/soc/ti/ti_sci_inta_msi.h b/include/linux/soc/ti/ti_sci_inta_msi.h new file mode 100644 index 000000000000..11fb5048f5f6 --- /dev/null +++ b/include/linux/soc/ti/ti_sci_inta_msi.h | |||
| @@ -0,0 +1,23 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | /* | ||
| 3 | * Texas Instruments' K3 TI SCI INTA MSI helper | ||
| 4 | * | ||
| 5 | * Copyright (C) 2018-2019 Texas Instruments Incorporated - http://www.ti.com/ | ||
| 6 | * Lokesh Vutla <lokeshvutla@ti.com> | ||
| 7 | */ | ||
| 8 | |||
| 9 | #ifndef __INCLUDE_LINUX_TI_SCI_INTA_MSI_H | ||
| 10 | #define __INCLUDE_LINUX_TI_SCI_INTA_MSI_H | ||
| 11 | |||
| 12 | #include <linux/msi.h> | ||
| 13 | #include <linux/soc/ti/ti_sci_protocol.h> | ||
| 14 | |||
| 15 | struct irq_domain | ||
| 16 | *ti_sci_inta_msi_create_irq_domain(struct fwnode_handle *fwnode, | ||
| 17 | struct msi_domain_info *info, | ||
| 18 | struct irq_domain *parent); | ||
| 19 | int ti_sci_inta_msi_domain_alloc_irqs(struct device *dev, | ||
| 20 | struct ti_sci_resource *res); | ||
| 21 | unsigned int ti_sci_inta_msi_get_virq(struct device *dev, u32 index); | ||
| 22 | void ti_sci_inta_msi_domain_free_irqs(struct device *dev); | ||
| 23 | #endif /* __INCLUDE_LINUX_IRQCHIP_TI_SCI_INTA_H */ | ||
diff --git a/include/linux/soc/ti/ti_sci_protocol.h b/include/linux/soc/ti/ti_sci_protocol.h index 18435e5c6364..568722a041bf 100644 --- a/include/linux/soc/ti/ti_sci_protocol.h +++ b/include/linux/soc/ti/ti_sci_protocol.h | |||
| @@ -193,14 +193,67 @@ struct ti_sci_clk_ops { | |||
| 193 | }; | 193 | }; |
| 194 | 194 | ||
| 195 | /** | 195 | /** |
| 196 | * struct ti_sci_rm_core_ops - Resource management core operations | ||
| 197 | * @get_range: Get a range of resources belonging to ti sci host. | ||
| 198 | * @get_rage_from_shost: Get a range of resources belonging to | ||
| 199 | * specified host id. | ||
| 200 | * - s_host: Host processing entity to which the | ||
| 201 | * resources are allocated | ||
| 202 | * | ||
| 203 | * NOTE: for these functions, all the parameters are consolidated and defined | ||
| 204 | * as below: | ||
| 205 | * - handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle | ||
| 206 | * - dev_id: TISCI device ID. | ||
| 207 | * - subtype: Resource assignment subtype that is being requested | ||
| 208 | * from the given device. | ||
| 209 | * - range_start: Start index of the resource range | ||
| 210 | * - range_end: Number of resources in the range | ||
| 211 | */ | ||
| 212 | struct ti_sci_rm_core_ops { | ||
| 213 | int (*get_range)(const struct ti_sci_handle *handle, u32 dev_id, | ||
| 214 | u8 subtype, u16 *range_start, u16 *range_num); | ||
| 215 | int (*get_range_from_shost)(const struct ti_sci_handle *handle, | ||
| 216 | u32 dev_id, u8 subtype, u8 s_host, | ||
| 217 | u16 *range_start, u16 *range_num); | ||
| 218 | }; | ||
| 219 | |||
| 220 | /** | ||
| 221 | * struct ti_sci_rm_irq_ops: IRQ management operations | ||
| 222 | * @set_irq: Set an IRQ route between the requested source | ||
| 223 | * and destination | ||
| 224 | * @set_event_map: Set an Event based peripheral irq to Interrupt | ||
| 225 | * Aggregator. | ||
| 226 | * @free_irq: Free an an IRQ route between the requested source | ||
| 227 | * destination. | ||
| 228 | * @free_event_map: Free an event based peripheral irq to Interrupt | ||
| 229 | * Aggregator. | ||
| 230 | */ | ||
| 231 | struct ti_sci_rm_irq_ops { | ||
| 232 | int (*set_irq)(const struct ti_sci_handle *handle, u16 src_id, | ||
| 233 | u16 src_index, u16 dst_id, u16 dst_host_irq); | ||
| 234 | int (*set_event_map)(const struct ti_sci_handle *handle, u16 src_id, | ||
| 235 | u16 src_index, u16 ia_id, u16 vint, | ||
| 236 | u16 global_event, u8 vint_status_bit); | ||
| 237 | int (*free_irq)(const struct ti_sci_handle *handle, u16 src_id, | ||
| 238 | u16 src_index, u16 dst_id, u16 dst_host_irq); | ||
| 239 | int (*free_event_map)(const struct ti_sci_handle *handle, u16 src_id, | ||
| 240 | u16 src_index, u16 ia_id, u16 vint, | ||
| 241 | u16 global_event, u8 vint_status_bit); | ||
| 242 | }; | ||
| 243 | |||
| 244 | /** | ||
| 196 | * struct ti_sci_ops - Function support for TI SCI | 245 | * struct ti_sci_ops - Function support for TI SCI |
| 197 | * @dev_ops: Device specific operations | 246 | * @dev_ops: Device specific operations |
| 198 | * @clk_ops: Clock specific operations | 247 | * @clk_ops: Clock specific operations |
| 248 | * @rm_core_ops: Resource management core operations. | ||
| 249 | * @rm_irq_ops: IRQ management specific operations | ||
| 199 | */ | 250 | */ |
| 200 | struct ti_sci_ops { | 251 | struct ti_sci_ops { |
| 201 | struct ti_sci_core_ops core_ops; | 252 | struct ti_sci_core_ops core_ops; |
| 202 | struct ti_sci_dev_ops dev_ops; | 253 | struct ti_sci_dev_ops dev_ops; |
| 203 | struct ti_sci_clk_ops clk_ops; | 254 | struct ti_sci_clk_ops clk_ops; |
| 255 | struct ti_sci_rm_core_ops rm_core_ops; | ||
| 256 | struct ti_sci_rm_irq_ops rm_irq_ops; | ||
| 204 | }; | 257 | }; |
| 205 | 258 | ||
| 206 | /** | 259 | /** |
| @@ -213,10 +266,47 @@ struct ti_sci_handle { | |||
| 213 | struct ti_sci_ops ops; | 266 | struct ti_sci_ops ops; |
| 214 | }; | 267 | }; |
| 215 | 268 | ||
| 269 | #define TI_SCI_RESOURCE_NULL 0xffff | ||
| 270 | |||
| 271 | /** | ||
| 272 | * struct ti_sci_resource_desc - Description of TI SCI resource instance range. | ||
| 273 | * @start: Start index of the resource. | ||
| 274 | * @num: Number of resources. | ||
| 275 | * @res_map: Bitmap to manage the allocation of these resources. | ||
| 276 | */ | ||
| 277 | struct ti_sci_resource_desc { | ||
| 278 | u16 start; | ||
| 279 | u16 num; | ||
| 280 | unsigned long *res_map; | ||
| 281 | }; | ||
| 282 | |||
| 283 | /** | ||
| 284 | * struct ti_sci_resource - Structure representing a resource assigned | ||
| 285 | * to a device. | ||
| 286 | * @sets: Number of sets available from this resource type | ||
| 287 | * @lock: Lock to guard the res map in each set. | ||
| 288 | * @desc: Array of resource descriptors. | ||
| 289 | */ | ||
| 290 | struct ti_sci_resource { | ||
| 291 | u16 sets; | ||
| 292 | raw_spinlock_t lock; | ||
| 293 | struct ti_sci_resource_desc *desc; | ||
| 294 | }; | ||
| 295 | |||
| 216 | #if IS_ENABLED(CONFIG_TI_SCI_PROTOCOL) | 296 | #if IS_ENABLED(CONFIG_TI_SCI_PROTOCOL) |
| 217 | const struct ti_sci_handle *ti_sci_get_handle(struct device *dev); | 297 | const struct ti_sci_handle *ti_sci_get_handle(struct device *dev); |
| 218 | int ti_sci_put_handle(const struct ti_sci_handle *handle); | 298 | int ti_sci_put_handle(const struct ti_sci_handle *handle); |
| 219 | const struct ti_sci_handle *devm_ti_sci_get_handle(struct device *dev); | 299 | const struct ti_sci_handle *devm_ti_sci_get_handle(struct device *dev); |
| 300 | const struct ti_sci_handle *ti_sci_get_by_phandle(struct device_node *np, | ||
| 301 | const char *property); | ||
| 302 | const struct ti_sci_handle *devm_ti_sci_get_by_phandle(struct device *dev, | ||
| 303 | const char *property); | ||
| 304 | u16 ti_sci_get_free_resource(struct ti_sci_resource *res); | ||
| 305 | void ti_sci_release_resource(struct ti_sci_resource *res, u16 id); | ||
| 306 | u32 ti_sci_get_num_resources(struct ti_sci_resource *res); | ||
| 307 | struct ti_sci_resource * | ||
| 308 | devm_ti_sci_get_of_resource(const struct ti_sci_handle *handle, | ||
| 309 | struct device *dev, u32 dev_id, char *of_prop); | ||
| 220 | 310 | ||
| 221 | #else /* CONFIG_TI_SCI_PROTOCOL */ | 311 | #else /* CONFIG_TI_SCI_PROTOCOL */ |
| 222 | 312 | ||
| @@ -236,6 +326,40 @@ const struct ti_sci_handle *devm_ti_sci_get_handle(struct device *dev) | |||
| 236 | return ERR_PTR(-EINVAL); | 326 | return ERR_PTR(-EINVAL); |
| 237 | } | 327 | } |
| 238 | 328 | ||
| 329 | static inline | ||
| 330 | const struct ti_sci_handle *ti_sci_get_by_phandle(struct device_node *np, | ||
| 331 | const char *property) | ||
| 332 | { | ||
| 333 | return ERR_PTR(-EINVAL); | ||
| 334 | } | ||
| 335 | |||
| 336 | static inline | ||
| 337 | const struct ti_sci_handle *devm_ti_sci_get_by_phandle(struct device *dev, | ||
| 338 | const char *property) | ||
| 339 | { | ||
| 340 | return ERR_PTR(-EINVAL); | ||
| 341 | } | ||
| 342 | |||
| 343 | static inline u16 ti_sci_get_free_resource(struct ti_sci_resource *res) | ||
| 344 | { | ||
| 345 | return TI_SCI_RESOURCE_NULL; | ||
| 346 | } | ||
| 347 | |||
| 348 | static inline void ti_sci_release_resource(struct ti_sci_resource *res, u16 id) | ||
| 349 | { | ||
| 350 | } | ||
| 351 | |||
| 352 | static inline u32 ti_sci_get_num_resources(struct ti_sci_resource *res) | ||
| 353 | { | ||
| 354 | return 0; | ||
| 355 | } | ||
| 356 | |||
| 357 | static inline struct ti_sci_resource * | ||
| 358 | devm_ti_sci_get_of_resource(const struct ti_sci_handle *handle, | ||
| 359 | struct device *dev, u32 dev_id, char *of_prop) | ||
| 360 | { | ||
| 361 | return ERR_PTR(-EINVAL); | ||
| 362 | } | ||
| 239 | #endif /* CONFIG_TI_SCI_PROTOCOL */ | 363 | #endif /* CONFIG_TI_SCI_PROTOCOL */ |
| 240 | 364 | ||
| 241 | #endif /* __TISCI_PROTOCOL_H */ | 365 | #endif /* __TISCI_PROTOCOL_H */ |
diff --git a/include/linux/atmel_tc.h b/include/soc/at91/atmel_tcb.h index 468fdfa643f0..c3c7200ce151 100644 --- a/include/linux/atmel_tc.h +++ b/include/soc/at91/atmel_tcb.h | |||
| @@ -7,8 +7,8 @@ | |||
| 7 | * (at your option) any later version. | 7 | * (at your option) any later version. |
| 8 | */ | 8 | */ |
| 9 | 9 | ||
| 10 | #ifndef ATMEL_TC_H | 10 | #ifndef __SOC_ATMEL_TCB_H |
| 11 | #define ATMEL_TC_H | 11 | #define __SOC_ATMEL_TCB_H |
| 12 | 12 | ||
| 13 | #include <linux/compiler.h> | 13 | #include <linux/compiler.h> |
| 14 | #include <linux/list.h> | 14 | #include <linux/list.h> |
diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index 896c3f45503b..e8346784cf3f 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h | |||
| @@ -81,6 +81,7 @@ struct hdac_device { | |||
| 81 | atomic_t in_pm; /* suspend/resume being performed */ | 81 | atomic_t in_pm; /* suspend/resume being performed */ |
| 82 | 82 | ||
| 83 | /* sysfs */ | 83 | /* sysfs */ |
| 84 | struct mutex widget_lock; | ||
| 84 | struct hdac_widget_tree *widgets; | 85 | struct hdac_widget_tree *widgets; |
| 85 | 86 | ||
| 86 | /* regmap */ | 87 | /* regmap */ |
diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig index 5f3e2baefca9..8fee06625c37 100644 --- a/kernel/irq/Kconfig +++ b/kernel/irq/Kconfig | |||
| @@ -91,6 +91,9 @@ config GENERIC_MSI_IRQ_DOMAIN | |||
| 91 | select IRQ_DOMAIN_HIERARCHY | 91 | select IRQ_DOMAIN_HIERARCHY |
| 92 | select GENERIC_MSI_IRQ | 92 | select GENERIC_MSI_IRQ |
| 93 | 93 | ||
| 94 | config IRQ_MSI_IOMMU | ||
| 95 | bool | ||
| 96 | |||
| 94 | config HANDLE_DOMAIN_IRQ | 97 | config HANDLE_DOMAIN_IRQ |
| 95 | bool | 98 | bool |
| 96 | 99 | ||
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index 51128bea3846..29d6c7d070b4 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c | |||
| @@ -1459,6 +1459,33 @@ int irq_chip_set_wake_parent(struct irq_data *data, unsigned int on) | |||
| 1459 | return -ENOSYS; | 1459 | return -ENOSYS; |
| 1460 | } | 1460 | } |
| 1461 | EXPORT_SYMBOL_GPL(irq_chip_set_wake_parent); | 1461 | EXPORT_SYMBOL_GPL(irq_chip_set_wake_parent); |
| 1462 | |||
| 1463 | /** | ||
| 1464 | * irq_chip_request_resources_parent - Request resources on the parent interrupt | ||
| 1465 | * @data: Pointer to interrupt specific data | ||
| 1466 | */ | ||
| 1467 | int irq_chip_request_resources_parent(struct irq_data *data) | ||
| 1468 | { | ||
| 1469 | data = data->parent_data; | ||
| 1470 | |||
| 1471 | if (data->chip->irq_request_resources) | ||
| 1472 | return data->chip->irq_request_resources(data); | ||
| 1473 | |||
| 1474 | return -ENOSYS; | ||
| 1475 | } | ||
| 1476 | EXPORT_SYMBOL_GPL(irq_chip_request_resources_parent); | ||
| 1477 | |||
| 1478 | /** | ||
| 1479 | * irq_chip_release_resources_parent - Release resources on the parent interrupt | ||
| 1480 | * @data: Pointer to interrupt specific data | ||
| 1481 | */ | ||
| 1482 | void irq_chip_release_resources_parent(struct irq_data *data) | ||
| 1483 | { | ||
| 1484 | data = data->parent_data; | ||
| 1485 | if (data->chip->irq_release_resources) | ||
| 1486 | data->chip->irq_release_resources(data); | ||
| 1487 | } | ||
| 1488 | EXPORT_SYMBOL_GPL(irq_chip_release_resources_parent); | ||
| 1462 | #endif | 1489 | #endif |
| 1463 | 1490 | ||
| 1464 | /** | 1491 | /** |
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 9ed29e4a7dbf..a453e229f99c 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c | |||
| @@ -1297,7 +1297,7 @@ int irq_domain_alloc_irqs_hierarchy(struct irq_domain *domain, | |||
| 1297 | /** | 1297 | /** |
| 1298 | * __irq_domain_alloc_irqs - Allocate IRQs from domain | 1298 | * __irq_domain_alloc_irqs - Allocate IRQs from domain |
| 1299 | * @domain: domain to allocate from | 1299 | * @domain: domain to allocate from |
| 1300 | * @irq_base: allocate specified IRQ nubmer if irq_base >= 0 | 1300 | * @irq_base: allocate specified IRQ number if irq_base >= 0 |
| 1301 | * @nr_irqs: number of IRQs to allocate | 1301 | * @nr_irqs: number of IRQs to allocate |
| 1302 | * @node: NUMA node id for memory allocation | 1302 | * @node: NUMA node id for memory allocation |
| 1303 | * @arg: domain specific argument | 1303 | * @arg: domain specific argument |
| @@ -2735,9 +2735,17 @@ int __do_munmap(struct mm_struct *mm, unsigned long start, size_t len, | |||
| 2735 | return -EINVAL; | 2735 | return -EINVAL; |
| 2736 | 2736 | ||
| 2737 | len = PAGE_ALIGN(len); | 2737 | len = PAGE_ALIGN(len); |
| 2738 | end = start + len; | ||
| 2738 | if (len == 0) | 2739 | if (len == 0) |
| 2739 | return -EINVAL; | 2740 | return -EINVAL; |
| 2740 | 2741 | ||
| 2742 | /* | ||
| 2743 | * arch_unmap() might do unmaps itself. It must be called | ||
| 2744 | * and finish any rbtree manipulation before this code | ||
| 2745 | * runs and also starts to manipulate the rbtree. | ||
| 2746 | */ | ||
| 2747 | arch_unmap(mm, start, end); | ||
| 2748 | |||
| 2741 | /* Find the first overlapping VMA */ | 2749 | /* Find the first overlapping VMA */ |
| 2742 | vma = find_vma(mm, start); | 2750 | vma = find_vma(mm, start); |
| 2743 | if (!vma) | 2751 | if (!vma) |
| @@ -2746,7 +2754,6 @@ int __do_munmap(struct mm_struct *mm, unsigned long start, size_t len, | |||
| 2746 | /* we have start < vma->vm_end */ | 2754 | /* we have start < vma->vm_end */ |
| 2747 | 2755 | ||
| 2748 | /* if it doesn't overlap, we have nothing.. */ | 2756 | /* if it doesn't overlap, we have nothing.. */ |
| 2749 | end = start + len; | ||
| 2750 | if (vma->vm_start >= end) | 2757 | if (vma->vm_start >= end) |
| 2751 | return 0; | 2758 | return 0; |
| 2752 | 2759 | ||
| @@ -2816,12 +2823,6 @@ int __do_munmap(struct mm_struct *mm, unsigned long start, size_t len, | |||
| 2816 | /* Detach vmas from rbtree */ | 2823 | /* Detach vmas from rbtree */ |
| 2817 | detach_vmas_to_be_unmapped(mm, vma, prev, end); | 2824 | detach_vmas_to_be_unmapped(mm, vma, prev, end); |
| 2818 | 2825 | ||
| 2819 | /* | ||
| 2820 | * mpx unmap needs to be called with mmap_sem held for write. | ||
| 2821 | * It is safe to call it before unmap_region(). | ||
| 2822 | */ | ||
| 2823 | arch_unmap(mm, vma, start, end); | ||
| 2824 | |||
| 2825 | if (downgrade) | 2826 | if (downgrade) |
| 2826 | downgrade_write(&mm->mmap_sem); | 2827 | downgrade_write(&mm->mmap_sem); |
| 2827 | 2828 | ||
diff --git a/net/bpfilter/Makefile b/net/bpfilter/Makefile index 854395fb98cd..aa945ab5b655 100644 --- a/net/bpfilter/Makefile +++ b/net/bpfilter/Makefile | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | hostprogs-y := bpfilter_umh | 6 | hostprogs-y := bpfilter_umh |
| 7 | bpfilter_umh-objs := main.o | 7 | bpfilter_umh-objs := main.o |
| 8 | KBUILD_HOSTCFLAGS += -Itools/include/ -Itools/include/uapi | 8 | KBUILD_HOSTCFLAGS += -I $(srctree)/tools/include/ -I $(srctree)/tools/include/uapi |
| 9 | HOSTCC := $(CC) | 9 | HOSTCC := $(CC) |
| 10 | 10 | ||
| 11 | ifeq ($(CONFIG_BPFILTER_UMH), y) | 11 | ifeq ($(CONFIG_BPFILTER_UMH), y) |
diff --git a/samples/Makefile b/samples/Makefile index 8e096e0d45d1..debf8925f06f 100644 --- a/samples/Makefile +++ b/samples/Makefile | |||
| @@ -1,6 +1,22 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | ||
| 1 | # Makefile for Linux samples code | 2 | # Makefile for Linux samples code |
| 2 | 3 | ||
| 3 | obj-y += kobject/ kprobes/ trace_events/ livepatch/ \ | 4 | obj-$(CONFIG_SAMPLE_ANDROID_BINDERFS) += binderfs/ |
| 4 | hw_breakpoint/ kfifo/ kdb/ hidraw/ rpmsg/ seccomp/ \ | 5 | obj-$(CONFIG_SAMPLE_CONFIGFS) += configfs/ |
| 5 | configfs/ connector/ v4l/ trace_printk/ \ | 6 | obj-$(CONFIG_SAMPLE_CONNECTOR) += connector/ |
| 6 | vfio-mdev/ vfs/ qmi/ binderfs/ pidfd/ | 7 | subdir-y += hidraw |
| 8 | obj-$(CONFIG_SAMPLE_HW_BREAKPOINT) += hw_breakpoint/ | ||
| 9 | obj-$(CONFIG_SAMPLE_KDB) += kdb/ | ||
| 10 | obj-$(CONFIG_SAMPLE_KFIFO) += kfifo/ | ||
| 11 | obj-$(CONFIG_SAMPLE_KOBJECT) += kobject/ | ||
| 12 | obj-$(CONFIG_SAMPLE_KPROBES) += kprobes/ | ||
| 13 | obj-$(CONFIG_SAMPLE_LIVEPATCH) += livepatch/ | ||
| 14 | subdir-y += pidfd | ||
| 15 | obj-$(CONFIG_SAMPLE_QMI_CLIENT) += qmi/ | ||
| 16 | obj-$(CONFIG_SAMPLE_RPMSG_CLIENT) += rpmsg/ | ||
| 17 | subdir-$(CONFIG_SAMPLE_SECCOMP) += seccomp | ||
| 18 | obj-$(CONFIG_SAMPLE_TRACE_EVENTS) += trace_events/ | ||
| 19 | obj-$(CONFIG_SAMPLE_TRACE_PRINTK) += trace_printk/ | ||
| 20 | obj-$(CONFIG_VIDEO_PCI_SKELETON) += v4l/ | ||
| 21 | obj-y += vfio-mdev/ | ||
| 22 | subdir-$(CONFIG_SAMPLE_VFS) += vfs | ||
diff --git a/samples/seccomp/Makefile b/samples/seccomp/Makefile index 00e0b5e90bd0..009775b52538 100644 --- a/samples/seccomp/Makefile +++ b/samples/seccomp/Makefile | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | 1 | # SPDX-License-Identifier: GPL-2.0 |
| 2 | ifndef CROSS_COMPILE | 2 | ifndef CROSS_COMPILE |
| 3 | hostprogs-$(CONFIG_SAMPLE_SECCOMP) := bpf-fancy dropper bpf-direct user-trap | 3 | hostprogs-y := bpf-fancy dropper bpf-direct user-trap |
| 4 | 4 | ||
| 5 | HOSTCFLAGS_bpf-fancy.o += -I$(objtree)/usr/include | 5 | HOSTCFLAGS_bpf-fancy.o += -I$(objtree)/usr/include |
| 6 | HOSTCFLAGS_bpf-fancy.o += -idirafter $(objtree)/include | 6 | HOSTCFLAGS_bpf-fancy.o += -idirafter $(objtree)/include |
diff --git a/samples/vfs/Makefile b/samples/vfs/Makefile index 4ac9690fb3c4..a3e4ffd4c773 100644 --- a/samples/vfs/Makefile +++ b/samples/vfs/Makefile | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | # List of programs to build | 1 | # List of programs to build |
| 2 | hostprogs-$(CONFIG_SAMPLE_VFS) := \ | 2 | hostprogs-y := \ |
| 3 | test-fsmount \ | 3 | test-fsmount \ |
| 4 | test-statx | 4 | test-statx |
| 5 | 5 | ||
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include index 7484b9d8272f..a675ce11a573 100644 --- a/scripts/Kbuild.include +++ b/scripts/Kbuild.include | |||
| @@ -192,14 +192,6 @@ clean := -f $(srctree)/scripts/Makefile.clean obj | |||
| 192 | # $(Q)$(MAKE) $(hdr-inst)=dir | 192 | # $(Q)$(MAKE) $(hdr-inst)=dir |
| 193 | hdr-inst := -f $(srctree)/scripts/Makefile.headersinst obj | 193 | hdr-inst := -f $(srctree)/scripts/Makefile.headersinst obj |
| 194 | 194 | ||
| 195 | # Prefix -I with $(srctree) if it is not an absolute path. | ||
| 196 | # skip if -I has no parameter | ||
| 197 | addtree = $(if $(patsubst -I%,%,$(1)), \ | ||
| 198 | $(if $(filter-out -I/% -I./% -I../%,$(1)),$(patsubst -I%,-I$(srctree)/%,$(1)),$(1)),$(1)) | ||
| 199 | |||
| 200 | # Find all -I options and call addtree | ||
| 201 | flags = $(foreach o,$($(1)),$(if $(filter -I%,$(o)),$(call addtree,$(o)),$(o))) | ||
| 202 | |||
| 203 | # echo command. | 195 | # echo command. |
| 204 | # Short version is used, if $(quiet) equals `quiet_', otherwise full one. | 196 | # Short version is used, if $(quiet) equals `quiet_', otherwise full one. |
| 205 | echo-cmd = $(if $($(quiet)cmd_$(1)),\ | 197 | echo-cmd = $(if $($(quiet)cmd_$(1)),\ |
diff --git a/scripts/Kconfig.include b/scripts/Kconfig.include index 87ff1dcc6bd5..0b267fb27f07 100644 --- a/scripts/Kconfig.include +++ b/scripts/Kconfig.include | |||
| @@ -18,6 +18,10 @@ if-success = $(shell,{ $(1); } >/dev/null 2>&1 && echo "$(2)" || echo "$(3)") | |||
| 18 | # Return y if <command> exits with 0, n otherwise | 18 | # Return y if <command> exits with 0, n otherwise |
| 19 | success = $(if-success,$(1),y,n) | 19 | success = $(if-success,$(1),y,n) |
| 20 | 20 | ||
| 21 | # $(failure,<command>) | ||
| 22 | # Return n if <command> exits with 0, y otherwise | ||
| 23 | failure = $(if-success,$(1),n,y) | ||
| 24 | |||
| 21 | # $(cc-option,<flag>) | 25 | # $(cc-option,<flag>) |
| 22 | # Return y if the compiler supports <flag>, n otherwise | 26 | # Return y if the compiler supports <flag>, n otherwise |
| 23 | cc-option = $(success,$(CC) -Werror $(1) -E -x c /dev/null -o /dev/null) | 27 | cc-option = $(success,$(CC) -Werror $(1) -E -x c /dev/null -o /dev/null) |
| @@ -26,5 +30,9 @@ cc-option = $(success,$(CC) -Werror $(1) -E -x c /dev/null -o /dev/null) | |||
| 26 | # Return y if the linker supports <flag>, n otherwise | 30 | # Return y if the linker supports <flag>, n otherwise |
| 27 | ld-option = $(success,$(LD) -v $(1)) | 31 | ld-option = $(success,$(LD) -v $(1)) |
| 28 | 32 | ||
| 33 | # check if $(CC) and $(LD) exist | ||
| 34 | $(error-if,$(failure,command -v $(CC)),compiler '$(CC)' not found) | ||
| 35 | $(error-if,$(failure,command -v $(LD)),linker '$(LD)' not found) | ||
| 36 | |||
| 29 | # gcc version including patch level | 37 | # gcc version including patch level |
| 30 | gcc-version := $(shell,$(srctree)/scripts/gcc-version.sh $(CC)) | 38 | gcc-version := $(shell,$(srctree)/scripts/gcc-version.sh $(CC)) |
diff --git a/scripts/Makefile.extrawarn b/scripts/Makefile.extrawarn index 768306add591..3ab8d1a303cd 100644 --- a/scripts/Makefile.extrawarn +++ b/scripts/Makefile.extrawarn | |||
| @@ -23,15 +23,16 @@ warning- := $(empty) | |||
| 23 | warning-1 := -Wextra -Wunused -Wno-unused-parameter | 23 | warning-1 := -Wextra -Wunused -Wno-unused-parameter |
| 24 | warning-1 += -Wmissing-declarations | 24 | warning-1 += -Wmissing-declarations |
| 25 | warning-1 += -Wmissing-format-attribute | 25 | warning-1 += -Wmissing-format-attribute |
| 26 | warning-1 += $(call cc-option, -Wmissing-prototypes) | 26 | warning-1 += -Wmissing-prototypes |
| 27 | warning-1 += -Wold-style-definition | 27 | warning-1 += -Wold-style-definition |
| 28 | warning-1 += $(call cc-option, -Wmissing-include-dirs) | 28 | warning-1 += -Wmissing-include-dirs |
| 29 | warning-1 += $(call cc-option, -Wunused-but-set-variable) | 29 | warning-1 += $(call cc-option, -Wunused-but-set-variable) |
| 30 | warning-1 += $(call cc-option, -Wunused-const-variable) | 30 | warning-1 += $(call cc-option, -Wunused-const-variable) |
| 31 | warning-1 += $(call cc-option, -Wpacked-not-aligned) | 31 | warning-1 += $(call cc-option, -Wpacked-not-aligned) |
| 32 | warning-1 += $(call cc-option, -Wstringop-truncation) | 32 | warning-1 += $(call cc-option, -Wstringop-truncation) |
| 33 | warning-1 += $(call cc-disable-warning, missing-field-initializers) | 33 | # The following turn off the warnings enabled by -Wextra |
| 34 | warning-1 += $(call cc-disable-warning, sign-compare) | 34 | warning-1 += -Wno-missing-field-initializers |
| 35 | warning-1 += -Wno-sign-compare | ||
| 35 | 36 | ||
| 36 | warning-2 := -Waggregate-return | 37 | warning-2 := -Waggregate-return |
| 37 | warning-2 += -Wcast-align | 38 | warning-2 += -Wcast-align |
| @@ -39,8 +40,8 @@ warning-2 += -Wdisabled-optimization | |||
| 39 | warning-2 += -Wnested-externs | 40 | warning-2 += -Wnested-externs |
| 40 | warning-2 += -Wshadow | 41 | warning-2 += -Wshadow |
| 41 | warning-2 += $(call cc-option, -Wlogical-op) | 42 | warning-2 += $(call cc-option, -Wlogical-op) |
| 42 | warning-2 += $(call cc-option, -Wmissing-field-initializers) | 43 | warning-2 += -Wmissing-field-initializers |
| 43 | warning-2 += $(call cc-option, -Wsign-compare) | 44 | warning-2 += -Wsign-compare |
| 44 | warning-2 += $(call cc-option, -Wmaybe-uninitialized) | 45 | warning-2 += $(call cc-option, -Wmaybe-uninitialized) |
| 45 | warning-2 += $(call cc-option, -Wunused-macros) | 46 | warning-2 += $(call cc-option, -Wunused-macros) |
| 46 | 47 | ||
| @@ -66,11 +67,11 @@ KBUILD_CFLAGS += $(warning) | |||
| 66 | else | 67 | else |
| 67 | 68 | ||
| 68 | ifdef CONFIG_CC_IS_CLANG | 69 | ifdef CONFIG_CC_IS_CLANG |
| 69 | KBUILD_CFLAGS += $(call cc-disable-warning, initializer-overrides) | 70 | KBUILD_CFLAGS += -Wno-initializer-overrides |
| 70 | KBUILD_CFLAGS += $(call cc-disable-warning, unused-value) | 71 | KBUILD_CFLAGS += -Wno-unused-value |
| 71 | KBUILD_CFLAGS += $(call cc-disable-warning, format) | 72 | KBUILD_CFLAGS += -Wno-format |
| 72 | KBUILD_CFLAGS += $(call cc-disable-warning, sign-compare) | 73 | KBUILD_CFLAGS += -Wno-sign-compare |
| 73 | KBUILD_CFLAGS += $(call cc-disable-warning, format-zero-length) | 74 | KBUILD_CFLAGS += -Wno-format-zero-length |
| 74 | KBUILD_CFLAGS += $(call cc-disable-warning, uninitialized) | 75 | KBUILD_CFLAGS += -Wno-uninitialized |
| 75 | endif | 76 | endif |
| 76 | endif | 77 | endif |
diff --git a/scripts/Makefile.host b/scripts/Makefile.host index 73b804197fca..b6a54bdf0965 100644 --- a/scripts/Makefile.host +++ b/scripts/Makefile.host | |||
| @@ -67,18 +67,16 @@ _hostc_flags = $(KBUILD_HOSTCFLAGS) $(HOST_EXTRACFLAGS) \ | |||
| 67 | _hostcxx_flags = $(KBUILD_HOSTCXXFLAGS) $(HOST_EXTRACXXFLAGS) \ | 67 | _hostcxx_flags = $(KBUILD_HOSTCXXFLAGS) $(HOST_EXTRACXXFLAGS) \ |
| 68 | $(HOSTCXXFLAGS_$(basetarget).o) | 68 | $(HOSTCXXFLAGS_$(basetarget).o) |
| 69 | 69 | ||
| 70 | __hostc_flags = $(_hostc_flags) | 70 | # $(objtree)/$(obj) for including generated headers from checkin source files |
| 71 | __hostcxx_flags = $(_hostcxx_flags) | ||
| 72 | |||
| 73 | ifeq ($(KBUILD_EXTMOD),) | 71 | ifeq ($(KBUILD_EXTMOD),) |
| 74 | ifneq ($(srctree),.) | 72 | ifneq ($(srctree),.) |
| 75 | __hostc_flags = -I$(obj) $(call flags,_hostc_flags) | 73 | _hostc_flags += -I $(objtree)/$(obj) |
| 76 | __hostcxx_flags = -I$(obj) $(call flags,_hostcxx_flags) | 74 | _hostcxx_flags += -I $(objtree)/$(obj) |
| 77 | endif | 75 | endif |
| 78 | endif | 76 | endif |
| 79 | 77 | ||
| 80 | hostc_flags = -Wp,-MD,$(depfile) $(__hostc_flags) | 78 | hostc_flags = -Wp,-MD,$(depfile) $(_hostc_flags) |
| 81 | hostcxx_flags = -Wp,-MD,$(depfile) $(__hostcxx_flags) | 79 | hostcxx_flags = -Wp,-MD,$(depfile) $(_hostcxx_flags) |
| 82 | 80 | ||
| 83 | ##### | 81 | ##### |
| 84 | # Compile programs on the host | 82 | # Compile programs on the host |
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 41e98fa66b91..1b412d4394ae 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib | |||
| @@ -137,36 +137,26 @@ _c_flags += $(if $(patsubst n%,, \ | |||
| 137 | $(CFLAGS_KCOV)) | 137 | $(CFLAGS_KCOV)) |
| 138 | endif | 138 | endif |
| 139 | 139 | ||
| 140 | __c_flags = $(_c_flags) | 140 | # $(srctree)/$(src) for including checkin headers from generated source files |
| 141 | __a_flags = $(_a_flags) | 141 | # $(objtree)/$(obj) for including generated headers from checkin source files |
| 142 | __cpp_flags = $(_cpp_flags) | ||
| 143 | |||
| 144 | # If building the kernel in a separate objtree expand all occurrences | ||
| 145 | # of -Idir to -I$(srctree)/dir except for absolute paths (starting with '/'). | ||
| 146 | ifeq ($(KBUILD_EXTMOD),) | 142 | ifeq ($(KBUILD_EXTMOD),) |
| 147 | ifneq ($(srctree),.) | 143 | ifneq ($(srctree),.) |
| 148 | 144 | _c_flags += -I $(srctree)/$(src) -I $(objtree)/$(obj) | |
| 149 | # -I$(obj) locates generated .h files | 145 | _a_flags += -I $(srctree)/$(src) -I $(objtree)/$(obj) |
| 150 | # $(call addtree,-I$(obj)) locates .h files in srctree, from generated .c files | 146 | _cpp_flags += -I $(srctree)/$(src) -I $(objtree)/$(obj) |
| 151 | # and locates generated .h files | ||
| 152 | # FIXME: Replace both with specific CFLAGS* statements in the makefiles | ||
| 153 | __c_flags = $(if $(obj),$(call addtree,-I$(src)) -I$(obj)) \ | ||
| 154 | $(call flags,_c_flags) | ||
| 155 | __a_flags = $(call flags,_a_flags) | ||
| 156 | __cpp_flags = $(call flags,_cpp_flags) | ||
| 157 | endif | 147 | endif |
| 158 | endif | 148 | endif |
| 159 | 149 | ||
| 160 | c_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \ | 150 | c_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \ |
| 161 | -include $(srctree)/include/linux/compiler_types.h \ | 151 | -include $(srctree)/include/linux/compiler_types.h \ |
| 162 | $(__c_flags) $(modkern_cflags) \ | 152 | $(_c_flags) $(modkern_cflags) \ |
| 163 | $(basename_flags) $(modname_flags) | 153 | $(basename_flags) $(modname_flags) |
| 164 | 154 | ||
| 165 | a_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \ | 155 | a_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \ |
| 166 | $(__a_flags) $(modkern_aflags) | 156 | $(_a_flags) $(modkern_aflags) |
| 167 | 157 | ||
| 168 | cpp_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \ | 158 | cpp_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \ |
| 169 | $(__cpp_flags) | 159 | $(_cpp_flags) |
| 170 | 160 | ||
| 171 | ld_flags = $(KBUILD_LDFLAGS) $(ldflags-y) $(LDFLAGS_$(@F)) | 161 | ld_flags = $(KBUILD_LDFLAGS) $(ldflags-y) $(LDFLAGS_$(@F)) |
| 172 | 162 | ||
diff --git a/scripts/dtc/Makefile b/scripts/dtc/Makefile index 5f227d8d39d8..82160808765c 100644 --- a/scripts/dtc/Makefile +++ b/scripts/dtc/Makefile | |||
| @@ -9,7 +9,7 @@ dtc-objs := dtc.o flattree.o fstree.o data.o livetree.o treesource.o \ | |||
| 9 | dtc-objs += dtc-lexer.lex.o dtc-parser.tab.o | 9 | dtc-objs += dtc-lexer.lex.o dtc-parser.tab.o |
| 10 | 10 | ||
| 11 | # Source files need to get at the userspace version of libfdt_env.h to compile | 11 | # Source files need to get at the userspace version of libfdt_env.h to compile |
| 12 | HOST_EXTRACFLAGS := -I$(src)/libfdt | 12 | HOST_EXTRACFLAGS := -I $(srctree)/$(src)/libfdt |
| 13 | 13 | ||
| 14 | ifeq ($(wildcard /usr/include/yaml.h),) | 14 | ifeq ($(wildcard /usr/include/yaml.h),) |
| 15 | ifneq ($(CHECK_DTBS),) | 15 | ifneq ($(CHECK_DTBS),) |
| @@ -23,8 +23,8 @@ HOSTLDLIBS_dtc := -lyaml | |||
| 23 | endif | 23 | endif |
| 24 | 24 | ||
| 25 | # Generated files need one more search path to include headers in source tree | 25 | # Generated files need one more search path to include headers in source tree |
| 26 | HOSTCFLAGS_dtc-lexer.lex.o := -I$(src) | 26 | HOSTCFLAGS_dtc-lexer.lex.o := -I $(srctree)/$(src) |
| 27 | HOSTCFLAGS_dtc-parser.tab.o := -I$(src) | 27 | HOSTCFLAGS_dtc-parser.tab.o := -I $(srctree)/$(src) |
| 28 | 28 | ||
| 29 | # dependencies on generated files need to be listed explicitly | 29 | # dependencies on generated files need to be listed explicitly |
| 30 | $(obj)/dtc-lexer.lex.o: $(obj)/dtc-parser.tab.h | 30 | $(obj)/dtc-lexer.lex.o: $(obj)/dtc-parser.tab.h |
diff --git a/scripts/genksyms/Makefile b/scripts/genksyms/Makefile index 03b7ce97de14..66c314bc5933 100644 --- a/scripts/genksyms/Makefile +++ b/scripts/genksyms/Makefile | |||
| @@ -31,8 +31,8 @@ $(obj)/parse.tab.h: $(src)/parse.y FORCE | |||
| 31 | endif | 31 | endif |
| 32 | 32 | ||
| 33 | # -I needed for generated C source (shipped source) | 33 | # -I needed for generated C source (shipped source) |
| 34 | HOSTCFLAGS_parse.tab.o := -I$(src) | 34 | HOSTCFLAGS_parse.tab.o := -I $(srctree)/$(src) |
| 35 | HOSTCFLAGS_lex.lex.o := -I$(src) | 35 | HOSTCFLAGS_lex.lex.o := -I $(srctree)/$(src) |
| 36 | 36 | ||
| 37 | # dependencies on generated files need to be listed explicitly | 37 | # dependencies on generated files need to be listed explicitly |
| 38 | $(obj)/lex.lex.o: $(obj)/parse.tab.h | 38 | $(obj)/lex.lex.o: $(obj)/parse.tab.h |
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile index 7c5dc31c1d95..3f327e21f60e 100644 --- a/scripts/kconfig/Makefile +++ b/scripts/kconfig/Makefile | |||
| @@ -76,15 +76,13 @@ savedefconfig: $(obj)/conf | |||
| 76 | defconfig: $(obj)/conf | 76 | defconfig: $(obj)/conf |
| 77 | ifeq ($(KBUILD_DEFCONFIG),) | 77 | ifeq ($(KBUILD_DEFCONFIG),) |
| 78 | $< $(silent) --defconfig $(Kconfig) | 78 | $< $(silent) --defconfig $(Kconfig) |
| 79 | else | 79 | else ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG)),) |
| 80 | ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG)),) | ||
| 81 | @$(kecho) "*** Default configuration is based on '$(KBUILD_DEFCONFIG)'" | 80 | @$(kecho) "*** Default configuration is based on '$(KBUILD_DEFCONFIG)'" |
| 82 | $(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG) $(Kconfig) | 81 | $(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG) $(Kconfig) |
| 83 | else | 82 | else |
| 84 | @$(kecho) "*** Default configuration is based on target '$(KBUILD_DEFCONFIG)'" | 83 | @$(kecho) "*** Default configuration is based on target '$(KBUILD_DEFCONFIG)'" |
| 85 | $(Q)$(MAKE) -f $(srctree)/Makefile $(KBUILD_DEFCONFIG) | 84 | $(Q)$(MAKE) -f $(srctree)/Makefile $(KBUILD_DEFCONFIG) |
| 86 | endif | 85 | endif |
| 87 | endif | ||
| 88 | 86 | ||
| 89 | %_defconfig: $(obj)/conf | 87 | %_defconfig: $(obj)/conf |
| 90 | $(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig) | 88 | $(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig) |
| @@ -147,8 +145,8 @@ common-objs := confdata.o expr.o lexer.lex.o parser.tab.o preprocess.o \ | |||
| 147 | symbol.o | 145 | symbol.o |
| 148 | 146 | ||
| 149 | $(obj)/lexer.lex.o: $(obj)/parser.tab.h | 147 | $(obj)/lexer.lex.o: $(obj)/parser.tab.h |
| 150 | HOSTCFLAGS_lexer.lex.o := -I$(src) | 148 | HOSTCFLAGS_lexer.lex.o := -I $(srctree)/$(src) |
| 151 | HOSTCFLAGS_parser.tab.o := -I$(src) | 149 | HOSTCFLAGS_parser.tab.o := -I $(srctree)/$(src) |
| 152 | 150 | ||
| 153 | # conf: Used for defconfig, oldconfig and related targets | 151 | # conf: Used for defconfig, oldconfig and related targets |
| 154 | hostprogs-y += conf | 152 | hostprogs-y += conf |
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index 492ac3410147..6006154d36bd 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c | |||
| @@ -867,6 +867,7 @@ int conf_write(const char *name) | |||
| 867 | const char *str; | 867 | const char *str; |
| 868 | char tmpname[PATH_MAX + 1], oldname[PATH_MAX + 1]; | 868 | char tmpname[PATH_MAX + 1], oldname[PATH_MAX + 1]; |
| 869 | char *env; | 869 | char *env; |
| 870 | bool need_newline = false; | ||
| 870 | 871 | ||
| 871 | if (!name) | 872 | if (!name) |
| 872 | name = conf_get_configname(); | 873 | name = conf_get_configname(); |
| @@ -912,12 +913,16 @@ int conf_write(const char *name) | |||
| 912 | "#\n" | 913 | "#\n" |
| 913 | "# %s\n" | 914 | "# %s\n" |
| 914 | "#\n", str); | 915 | "#\n", str); |
| 916 | need_newline = false; | ||
| 915 | } else if (!(sym->flags & SYMBOL_CHOICE)) { | 917 | } else if (!(sym->flags & SYMBOL_CHOICE)) { |
| 916 | sym_calc_value(sym); | 918 | sym_calc_value(sym); |
| 917 | if (!(sym->flags & SYMBOL_WRITE)) | 919 | if (!(sym->flags & SYMBOL_WRITE)) |
| 918 | goto next; | 920 | goto next; |
| 921 | if (need_newline) { | ||
| 922 | fprintf(out, "\n"); | ||
| 923 | need_newline = false; | ||
| 924 | } | ||
| 919 | sym->flags &= ~SYMBOL_WRITE; | 925 | sym->flags &= ~SYMBOL_WRITE; |
| 920 | |||
| 921 | conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); | 926 | conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); |
| 922 | } | 927 | } |
| 923 | 928 | ||
| @@ -929,6 +934,12 @@ next: | |||
| 929 | if (menu->next) | 934 | if (menu->next) |
| 930 | menu = menu->next; | 935 | menu = menu->next; |
| 931 | else while ((menu = menu->parent)) { | 936 | else while ((menu = menu->parent)) { |
| 937 | if (!menu->sym && menu_is_visible(menu) && | ||
| 938 | menu != &rootmenu) { | ||
| 939 | str = menu_get_prompt(menu); | ||
| 940 | fprintf(out, "# end of %s\n", str); | ||
| 941 | need_newline = true; | ||
| 942 | } | ||
| 932 | if (menu->next) { | 943 | if (menu->next) { |
| 933 | menu = menu->next; | 944 | menu = menu->next; |
| 934 | break; | 945 | break; |
diff --git a/scripts/modules-check.sh b/scripts/modules-check.sh new file mode 100755 index 000000000000..2f659530e1ec --- /dev/null +++ b/scripts/modules-check.sh | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | #!/bin/sh | ||
| 2 | # SPDX-License-Identifier: GPL-2.0 | ||
| 3 | |||
| 4 | set -e | ||
| 5 | |||
| 6 | # Check uniqueness of module names | ||
| 7 | check_same_name_modules() | ||
| 8 | { | ||
| 9 | for m in $(sed 's:.*/::' modules.order modules.builtin | sort | uniq -d) | ||
| 10 | do | ||
| 11 | echo "warning: same basename if the following are built as modules:" >&2 | ||
| 12 | sed "/\/$m/!d;s:^kernel/: :" modules.order modules.builtin >&2 | ||
| 13 | done | ||
| 14 | } | ||
| 15 | |||
| 16 | check_same_name_modules | ||
diff --git a/sound/hda/hdac_device.c b/sound/hda/hdac_device.c index 95b073ee4b32..4769f4c03e14 100644 --- a/sound/hda/hdac_device.c +++ b/sound/hda/hdac_device.c | |||
| @@ -55,6 +55,7 @@ int snd_hdac_device_init(struct hdac_device *codec, struct hdac_bus *bus, | |||
| 55 | codec->bus = bus; | 55 | codec->bus = bus; |
| 56 | codec->addr = addr; | 56 | codec->addr = addr; |
| 57 | codec->type = HDA_DEV_CORE; | 57 | codec->type = HDA_DEV_CORE; |
| 58 | mutex_init(&codec->widget_lock); | ||
| 58 | pm_runtime_set_active(&codec->dev); | 59 | pm_runtime_set_active(&codec->dev); |
| 59 | pm_runtime_get_noresume(&codec->dev); | 60 | pm_runtime_get_noresume(&codec->dev); |
| 60 | atomic_set(&codec->in_pm, 0); | 61 | atomic_set(&codec->in_pm, 0); |
| @@ -141,7 +142,9 @@ int snd_hdac_device_register(struct hdac_device *codec) | |||
| 141 | err = device_add(&codec->dev); | 142 | err = device_add(&codec->dev); |
| 142 | if (err < 0) | 143 | if (err < 0) |
| 143 | return err; | 144 | return err; |
| 145 | mutex_lock(&codec->widget_lock); | ||
| 144 | err = hda_widget_sysfs_init(codec); | 146 | err = hda_widget_sysfs_init(codec); |
| 147 | mutex_unlock(&codec->widget_lock); | ||
| 145 | if (err < 0) { | 148 | if (err < 0) { |
| 146 | device_del(&codec->dev); | 149 | device_del(&codec->dev); |
| 147 | return err; | 150 | return err; |
| @@ -158,7 +161,9 @@ EXPORT_SYMBOL_GPL(snd_hdac_device_register); | |||
| 158 | void snd_hdac_device_unregister(struct hdac_device *codec) | 161 | void snd_hdac_device_unregister(struct hdac_device *codec) |
| 159 | { | 162 | { |
| 160 | if (device_is_registered(&codec->dev)) { | 163 | if (device_is_registered(&codec->dev)) { |
| 164 | mutex_lock(&codec->widget_lock); | ||
| 161 | hda_widget_sysfs_exit(codec); | 165 | hda_widget_sysfs_exit(codec); |
| 166 | mutex_unlock(&codec->widget_lock); | ||
| 162 | device_del(&codec->dev); | 167 | device_del(&codec->dev); |
| 163 | snd_hdac_bus_remove_device(codec->bus, codec); | 168 | snd_hdac_bus_remove_device(codec->bus, codec); |
| 164 | } | 169 | } |
| @@ -404,7 +409,9 @@ int snd_hdac_refresh_widgets(struct hdac_device *codec, bool sysfs) | |||
| 404 | } | 409 | } |
| 405 | 410 | ||
| 406 | if (sysfs) { | 411 | if (sysfs) { |
| 412 | mutex_lock(&codec->widget_lock); | ||
| 407 | err = hda_widget_sysfs_reinit(codec, start_nid, nums); | 413 | err = hda_widget_sysfs_reinit(codec, start_nid, nums); |
| 414 | mutex_unlock(&codec->widget_lock); | ||
| 408 | if (err < 0) | 415 | if (err < 0) |
| 409 | return err; | 416 | return err; |
| 410 | } | 417 | } |
diff --git a/sound/hda/hdac_sysfs.c b/sound/hda/hdac_sysfs.c index fb2aa344981e..909d5ef1179c 100644 --- a/sound/hda/hdac_sysfs.c +++ b/sound/hda/hdac_sysfs.c | |||
| @@ -395,6 +395,7 @@ static int widget_tree_create(struct hdac_device *codec) | |||
| 395 | return 0; | 395 | return 0; |
| 396 | } | 396 | } |
| 397 | 397 | ||
| 398 | /* call with codec->widget_lock held */ | ||
| 398 | int hda_widget_sysfs_init(struct hdac_device *codec) | 399 | int hda_widget_sysfs_init(struct hdac_device *codec) |
| 399 | { | 400 | { |
| 400 | int err; | 401 | int err; |
| @@ -411,11 +412,13 @@ int hda_widget_sysfs_init(struct hdac_device *codec) | |||
| 411 | return 0; | 412 | return 0; |
| 412 | } | 413 | } |
| 413 | 414 | ||
| 415 | /* call with codec->widget_lock held */ | ||
| 414 | void hda_widget_sysfs_exit(struct hdac_device *codec) | 416 | void hda_widget_sysfs_exit(struct hdac_device *codec) |
| 415 | { | 417 | { |
| 416 | widget_tree_free(codec); | 418 | widget_tree_free(codec); |
| 417 | } | 419 | } |
| 418 | 420 | ||
| 421 | /* call with codec->widget_lock held */ | ||
| 419 | int hda_widget_sysfs_reinit(struct hdac_device *codec, | 422 | int hda_widget_sysfs_reinit(struct hdac_device *codec, |
| 420 | hda_nid_t start_nid, int num_nodes) | 423 | hda_nid_t start_nid, int num_nodes) |
| 421 | { | 424 | { |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index c53ca589c930..f83f21d64dd4 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
| @@ -478,12 +478,45 @@ static void alc_auto_setup_eapd(struct hda_codec *codec, bool on) | |||
| 478 | set_eapd(codec, *p, on); | 478 | set_eapd(codec, *p, on); |
| 479 | } | 479 | } |
| 480 | 480 | ||
| 481 | static int find_ext_mic_pin(struct hda_codec *codec); | ||
| 482 | |||
| 483 | static void alc_headset_mic_no_shutup(struct hda_codec *codec) | ||
| 484 | { | ||
| 485 | const struct hda_pincfg *pin; | ||
| 486 | int mic_pin = find_ext_mic_pin(codec); | ||
| 487 | int i; | ||
| 488 | |||
| 489 | /* don't shut up pins when unloading the driver; otherwise it breaks | ||
| 490 | * the default pin setup at the next load of the driver | ||
| 491 | */ | ||
| 492 | if (codec->bus->shutdown) | ||
| 493 | return; | ||
| 494 | |||
| 495 | snd_array_for_each(&codec->init_pins, i, pin) { | ||
| 496 | /* use read here for syncing after issuing each verb */ | ||
| 497 | if (pin->nid != mic_pin) | ||
| 498 | snd_hda_codec_read(codec, pin->nid, 0, | ||
| 499 | AC_VERB_SET_PIN_WIDGET_CONTROL, 0); | ||
| 500 | } | ||
| 501 | |||
| 502 | codec->pins_shutup = 1; | ||
| 503 | } | ||
| 504 | |||
| 481 | static void alc_shutup_pins(struct hda_codec *codec) | 505 | static void alc_shutup_pins(struct hda_codec *codec) |
| 482 | { | 506 | { |
| 483 | struct alc_spec *spec = codec->spec; | 507 | struct alc_spec *spec = codec->spec; |
| 484 | 508 | ||
| 485 | if (!spec->no_shutup_pins) | 509 | switch (codec->core.vendor_id) { |
| 486 | snd_hda_shutup_pins(codec); | 510 | case 0x10ec0286: |
| 511 | case 0x10ec0288: | ||
| 512 | case 0x10ec0298: | ||
| 513 | alc_headset_mic_no_shutup(codec); | ||
| 514 | break; | ||
| 515 | default: | ||
| 516 | if (!spec->no_shutup_pins) | ||
| 517 | snd_hda_shutup_pins(codec); | ||
| 518 | break; | ||
| 519 | } | ||
| 487 | } | 520 | } |
| 488 | 521 | ||
| 489 | /* generic shutup callback; | 522 | /* generic shutup callback; |
| @@ -502,7 +535,6 @@ static void alc_eapd_shutup(struct hda_codec *codec) | |||
| 502 | /* generic EAPD initialization */ | 535 | /* generic EAPD initialization */ |
| 503 | static void alc_auto_init_amp(struct hda_codec *codec, int type) | 536 | static void alc_auto_init_amp(struct hda_codec *codec, int type) |
| 504 | { | 537 | { |
| 505 | alc_fill_eapd_coef(codec); | ||
| 506 | alc_auto_setup_eapd(codec, true); | 538 | alc_auto_setup_eapd(codec, true); |
| 507 | alc_write_gpio(codec); | 539 | alc_write_gpio(codec); |
| 508 | switch (type) { | 540 | switch (type) { |
| @@ -797,10 +829,22 @@ static int alc_build_controls(struct hda_codec *codec) | |||
| 797 | * Common callbacks | 829 | * Common callbacks |
| 798 | */ | 830 | */ |
| 799 | 831 | ||
| 832 | static void alc_pre_init(struct hda_codec *codec) | ||
| 833 | { | ||
| 834 | alc_fill_eapd_coef(codec); | ||
| 835 | } | ||
| 836 | |||
| 837 | #define is_s4_resume(codec) \ | ||
| 838 | ((codec)->core.dev.power.power_state.event == PM_EVENT_RESTORE) | ||
| 839 | |||
| 800 | static int alc_init(struct hda_codec *codec) | 840 | static int alc_init(struct hda_codec *codec) |
| 801 | { | 841 | { |
| 802 | struct alc_spec *spec = codec->spec; | 842 | struct alc_spec *spec = codec->spec; |
| 803 | 843 | ||
| 844 | /* hibernation resume needs the full chip initialization */ | ||
| 845 | if (is_s4_resume(codec)) | ||
| 846 | alc_pre_init(codec); | ||
| 847 | |||
| 804 | if (spec->init_hook) | 848 | if (spec->init_hook) |
| 805 | spec->init_hook(codec); | 849 | spec->init_hook(codec); |
| 806 | 850 | ||
| @@ -1538,6 +1582,8 @@ static int patch_alc880(struct hda_codec *codec) | |||
| 1538 | 1582 | ||
| 1539 | codec->patch_ops.unsol_event = alc880_unsol_event; | 1583 | codec->patch_ops.unsol_event = alc880_unsol_event; |
| 1540 | 1584 | ||
| 1585 | alc_pre_init(codec); | ||
| 1586 | |||
| 1541 | snd_hda_pick_fixup(codec, alc880_fixup_models, alc880_fixup_tbl, | 1587 | snd_hda_pick_fixup(codec, alc880_fixup_models, alc880_fixup_tbl, |
| 1542 | alc880_fixups); | 1588 | alc880_fixups); |
| 1543 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 1589 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
| @@ -1789,6 +1835,8 @@ static int patch_alc260(struct hda_codec *codec) | |||
| 1789 | 1835 | ||
| 1790 | spec->shutup = alc_eapd_shutup; | 1836 | spec->shutup = alc_eapd_shutup; |
| 1791 | 1837 | ||
| 1838 | alc_pre_init(codec); | ||
| 1839 | |||
| 1792 | snd_hda_pick_fixup(codec, alc260_fixup_models, alc260_fixup_tbl, | 1840 | snd_hda_pick_fixup(codec, alc260_fixup_models, alc260_fixup_tbl, |
| 1793 | alc260_fixups); | 1841 | alc260_fixups); |
| 1794 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 1842 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
| @@ -2492,6 +2540,8 @@ static int patch_alc882(struct hda_codec *codec) | |||
| 2492 | break; | 2540 | break; |
| 2493 | } | 2541 | } |
| 2494 | 2542 | ||
| 2543 | alc_pre_init(codec); | ||
| 2544 | |||
| 2495 | snd_hda_pick_fixup(codec, alc882_fixup_models, alc882_fixup_tbl, | 2545 | snd_hda_pick_fixup(codec, alc882_fixup_models, alc882_fixup_tbl, |
| 2496 | alc882_fixups); | 2546 | alc882_fixups); |
| 2497 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 2547 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
| @@ -2666,6 +2716,8 @@ static int patch_alc262(struct hda_codec *codec) | |||
| 2666 | #endif | 2716 | #endif |
| 2667 | alc_fix_pll_init(codec, 0x20, 0x0a, 10); | 2717 | alc_fix_pll_init(codec, 0x20, 0x0a, 10); |
| 2668 | 2718 | ||
| 2719 | alc_pre_init(codec); | ||
| 2720 | |||
| 2669 | snd_hda_pick_fixup(codec, alc262_fixup_models, alc262_fixup_tbl, | 2721 | snd_hda_pick_fixup(codec, alc262_fixup_models, alc262_fixup_tbl, |
| 2670 | alc262_fixups); | 2722 | alc262_fixups); |
| 2671 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 2723 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
| @@ -2810,6 +2862,8 @@ static int patch_alc268(struct hda_codec *codec) | |||
| 2810 | 2862 | ||
| 2811 | spec->shutup = alc_eapd_shutup; | 2863 | spec->shutup = alc_eapd_shutup; |
| 2812 | 2864 | ||
| 2865 | alc_pre_init(codec); | ||
| 2866 | |||
| 2813 | snd_hda_pick_fixup(codec, alc268_fixup_models, alc268_fixup_tbl, alc268_fixups); | 2867 | snd_hda_pick_fixup(codec, alc268_fixup_models, alc268_fixup_tbl, alc268_fixups); |
| 2814 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 2868 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
| 2815 | 2869 | ||
| @@ -2924,27 +2978,6 @@ static int alc269_parse_auto_config(struct hda_codec *codec) | |||
| 2924 | return alc_parse_auto_config(codec, alc269_ignore, ssids); | 2978 | return alc_parse_auto_config(codec, alc269_ignore, ssids); |
| 2925 | } | 2979 | } |
| 2926 | 2980 | ||
| 2927 | static int find_ext_mic_pin(struct hda_codec *codec); | ||
| 2928 | |||
| 2929 | static void alc286_shutup(struct hda_codec *codec) | ||
| 2930 | { | ||
| 2931 | const struct hda_pincfg *pin; | ||
| 2932 | int i; | ||
| 2933 | int mic_pin = find_ext_mic_pin(codec); | ||
| 2934 | /* don't shut up pins when unloading the driver; otherwise it breaks | ||
| 2935 | * the default pin setup at the next load of the driver | ||
| 2936 | */ | ||
| 2937 | if (codec->bus->shutdown) | ||
| 2938 | return; | ||
| 2939 | snd_array_for_each(&codec->init_pins, i, pin) { | ||
| 2940 | /* use read here for syncing after issuing each verb */ | ||
| 2941 | if (pin->nid != mic_pin) | ||
| 2942 | snd_hda_codec_read(codec, pin->nid, 0, | ||
| 2943 | AC_VERB_SET_PIN_WIDGET_CONTROL, 0); | ||
| 2944 | } | ||
| 2945 | codec->pins_shutup = 1; | ||
| 2946 | } | ||
| 2947 | |||
| 2948 | static void alc269vb_toggle_power_output(struct hda_codec *codec, int power_up) | 2981 | static void alc269vb_toggle_power_output(struct hda_codec *codec, int power_up) |
| 2949 | { | 2982 | { |
| 2950 | alc_update_coef_idx(codec, 0x04, 1 << 11, power_up ? (1 << 11) : 0); | 2983 | alc_update_coef_idx(codec, 0x04, 1 << 11, power_up ? (1 << 11) : 0); |
| @@ -6964,7 +6997,9 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
| 6964 | SND_PCI_QUIRK(0x1462, 0xb171, "Cubi N 8GL (MS-B171)", ALC283_FIXUP_HEADSET_MIC), | 6997 | SND_PCI_QUIRK(0x1462, 0xb171, "Cubi N 8GL (MS-B171)", ALC283_FIXUP_HEADSET_MIC), |
| 6965 | SND_PCI_QUIRK(0x1558, 0x1325, "System76 Darter Pro (darp5)", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | 6998 | SND_PCI_QUIRK(0x1558, 0x1325, "System76 Darter Pro (darp5)", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), |
| 6966 | SND_PCI_QUIRK(0x1558, 0x8550, "System76 Gazelle (gaze14)", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | 6999 | SND_PCI_QUIRK(0x1558, 0x8550, "System76 Gazelle (gaze14)", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), |
| 6967 | SND_PCI_QUIRK(0x1558, 0x8560, "System76 Gazelle (gaze14)", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | 7000 | SND_PCI_QUIRK(0x1558, 0x8551, "System76 Gazelle (gaze14)", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), |
| 7001 | SND_PCI_QUIRK(0x1558, 0x8560, "System76 Gazelle (gaze14)", ALC269_FIXUP_HEADSET_MIC), | ||
| 7002 | SND_PCI_QUIRK(0x1558, 0x8561, "System76 Gazelle (gaze14)", ALC269_FIXUP_HEADSET_MIC), | ||
| 6968 | SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC233_FIXUP_LENOVO_MULTI_CODECS), | 7003 | SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC233_FIXUP_LENOVO_MULTI_CODECS), |
| 6969 | SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE), | 7004 | SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE), |
| 6970 | SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE), | 7005 | SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE), |
| @@ -7007,7 +7042,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
| 7007 | SND_PCI_QUIRK(0x17aa, 0x313c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION), | 7042 | SND_PCI_QUIRK(0x17aa, 0x313c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION), |
| 7008 | SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI), | 7043 | SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI), |
| 7009 | SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC), | 7044 | SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC), |
| 7010 | SND_PCI_QUIRK(0x17aa, 0x3978, "IdeaPad Y410P", ALC269_FIXUP_NO_SHUTUP), | 7045 | SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo B50-70", ALC269_FIXUP_DMIC_THINKPAD_ACPI), |
| 7011 | SND_PCI_QUIRK(0x17aa, 0x5013, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), | 7046 | SND_PCI_QUIRK(0x17aa, 0x5013, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), |
| 7012 | SND_PCI_QUIRK(0x17aa, 0x501a, "Thinkpad", ALC283_FIXUP_INT_MIC), | 7047 | SND_PCI_QUIRK(0x17aa, 0x501a, "Thinkpad", ALC283_FIXUP_INT_MIC), |
| 7013 | SND_PCI_QUIRK(0x17aa, 0x501e, "Thinkpad L440", ALC292_FIXUP_TPT440_DOCK), | 7048 | SND_PCI_QUIRK(0x17aa, 0x501e, "Thinkpad L440", ALC292_FIXUP_TPT440_DOCK), |
| @@ -7736,7 +7771,6 @@ static int patch_alc269(struct hda_codec *codec) | |||
| 7736 | case 0x10ec0286: | 7771 | case 0x10ec0286: |
| 7737 | case 0x10ec0288: | 7772 | case 0x10ec0288: |
| 7738 | spec->codec_variant = ALC269_TYPE_ALC286; | 7773 | spec->codec_variant = ALC269_TYPE_ALC286; |
| 7739 | spec->shutup = alc286_shutup; | ||
| 7740 | break; | 7774 | break; |
| 7741 | case 0x10ec0298: | 7775 | case 0x10ec0298: |
| 7742 | spec->codec_variant = ALC269_TYPE_ALC298; | 7776 | spec->codec_variant = ALC269_TYPE_ALC298; |
| @@ -7805,6 +7839,8 @@ static int patch_alc269(struct hda_codec *codec) | |||
| 7805 | spec->init_hook = alc5505_dsp_init; | 7839 | spec->init_hook = alc5505_dsp_init; |
| 7806 | } | 7840 | } |
| 7807 | 7841 | ||
| 7842 | alc_pre_init(codec); | ||
| 7843 | |||
| 7808 | snd_hda_pick_fixup(codec, alc269_fixup_models, | 7844 | snd_hda_pick_fixup(codec, alc269_fixup_models, |
| 7809 | alc269_fixup_tbl, alc269_fixups); | 7845 | alc269_fixup_tbl, alc269_fixups); |
| 7810 | snd_hda_pick_pin_fixup(codec, alc269_pin_fixup_tbl, alc269_fixups); | 7846 | snd_hda_pick_pin_fixup(codec, alc269_pin_fixup_tbl, alc269_fixups); |
| @@ -7947,6 +7983,8 @@ static int patch_alc861(struct hda_codec *codec) | |||
| 7947 | spec->power_hook = alc_power_eapd; | 7983 | spec->power_hook = alc_power_eapd; |
| 7948 | #endif | 7984 | #endif |
| 7949 | 7985 | ||
| 7986 | alc_pre_init(codec); | ||
| 7987 | |||
| 7950 | snd_hda_pick_fixup(codec, NULL, alc861_fixup_tbl, alc861_fixups); | 7988 | snd_hda_pick_fixup(codec, NULL, alc861_fixup_tbl, alc861_fixups); |
| 7951 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 7989 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
| 7952 | 7990 | ||
| @@ -8044,6 +8082,8 @@ static int patch_alc861vd(struct hda_codec *codec) | |||
| 8044 | 8082 | ||
| 8045 | spec->shutup = alc_eapd_shutup; | 8083 | spec->shutup = alc_eapd_shutup; |
| 8046 | 8084 | ||
| 8085 | alc_pre_init(codec); | ||
| 8086 | |||
| 8047 | snd_hda_pick_fixup(codec, NULL, alc861vd_fixup_tbl, alc861vd_fixups); | 8087 | snd_hda_pick_fixup(codec, NULL, alc861vd_fixup_tbl, alc861vd_fixups); |
| 8048 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 8088 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
| 8049 | 8089 | ||
| @@ -8779,6 +8819,8 @@ static int patch_alc662(struct hda_codec *codec) | |||
| 8779 | break; | 8819 | break; |
| 8780 | } | 8820 | } |
| 8781 | 8821 | ||
| 8822 | alc_pre_init(codec); | ||
| 8823 | |||
| 8782 | snd_hda_pick_fixup(codec, alc662_fixup_models, | 8824 | snd_hda_pick_fixup(codec, alc662_fixup_models, |
| 8783 | alc662_fixup_tbl, alc662_fixups); | 8825 | alc662_fixup_tbl, alc662_fixups); |
| 8784 | snd_hda_pick_pin_fixup(codec, alc662_pin_fixup_tbl, alc662_fixups); | 8826 | snd_hda_pick_pin_fixup(codec, alc662_pin_fixup_tbl, alc662_fixups); |
diff --git a/tools/arch/x86/include/uapi/asm/kvm.h b/tools/arch/x86/include/uapi/asm/kvm.h index dabfcf7c3941..7a0e64ccd6ff 100644 --- a/tools/arch/x86/include/uapi/asm/kvm.h +++ b/tools/arch/x86/include/uapi/asm/kvm.h | |||
| @@ -381,6 +381,7 @@ struct kvm_sync_regs { | |||
| 381 | #define KVM_X86_QUIRK_LINT0_REENABLED (1 << 0) | 381 | #define KVM_X86_QUIRK_LINT0_REENABLED (1 << 0) |
| 382 | #define KVM_X86_QUIRK_CD_NW_CLEARED (1 << 1) | 382 | #define KVM_X86_QUIRK_CD_NW_CLEARED (1 << 1) |
| 383 | #define KVM_X86_QUIRK_LAPIC_MMIO_HOLE (1 << 2) | 383 | #define KVM_X86_QUIRK_LAPIC_MMIO_HOLE (1 << 2) |
| 384 | #define KVM_X86_QUIRK_OUT_7E_INC_RIP (1 << 3) | ||
| 384 | 385 | ||
| 385 | #define KVM_STATE_NESTED_GUEST_MODE 0x00000001 | 386 | #define KVM_STATE_NESTED_GUEST_MODE 0x00000001 |
| 386 | #define KVM_STATE_NESTED_RUN_PENDING 0x00000002 | 387 | #define KVM_STATE_NESTED_RUN_PENDING 0x00000002 |
diff --git a/tools/arch/x86/include/uapi/asm/perf_regs.h b/tools/arch/x86/include/uapi/asm/perf_regs.h index f3329cabce5c..ac67bbea10ca 100644 --- a/tools/arch/x86/include/uapi/asm/perf_regs.h +++ b/tools/arch/x86/include/uapi/asm/perf_regs.h | |||
| @@ -27,8 +27,29 @@ enum perf_event_x86_regs { | |||
| 27 | PERF_REG_X86_R13, | 27 | PERF_REG_X86_R13, |
| 28 | PERF_REG_X86_R14, | 28 | PERF_REG_X86_R14, |
| 29 | PERF_REG_X86_R15, | 29 | PERF_REG_X86_R15, |
| 30 | 30 | /* These are the limits for the GPRs. */ | |
| 31 | PERF_REG_X86_32_MAX = PERF_REG_X86_GS + 1, | 31 | PERF_REG_X86_32_MAX = PERF_REG_X86_GS + 1, |
| 32 | PERF_REG_X86_64_MAX = PERF_REG_X86_R15 + 1, | 32 | PERF_REG_X86_64_MAX = PERF_REG_X86_R15 + 1, |
| 33 | |||
| 34 | /* These all need two bits set because they are 128bit */ | ||
| 35 | PERF_REG_X86_XMM0 = 32, | ||
| 36 | PERF_REG_X86_XMM1 = 34, | ||
| 37 | PERF_REG_X86_XMM2 = 36, | ||
| 38 | PERF_REG_X86_XMM3 = 38, | ||
| 39 | PERF_REG_X86_XMM4 = 40, | ||
| 40 | PERF_REG_X86_XMM5 = 42, | ||
| 41 | PERF_REG_X86_XMM6 = 44, | ||
| 42 | PERF_REG_X86_XMM7 = 46, | ||
| 43 | PERF_REG_X86_XMM8 = 48, | ||
| 44 | PERF_REG_X86_XMM9 = 50, | ||
| 45 | PERF_REG_X86_XMM10 = 52, | ||
| 46 | PERF_REG_X86_XMM11 = 54, | ||
| 47 | PERF_REG_X86_XMM12 = 56, | ||
| 48 | PERF_REG_X86_XMM13 = 58, | ||
| 49 | PERF_REG_X86_XMM14 = 60, | ||
| 50 | PERF_REG_X86_XMM15 = 62, | ||
| 51 | |||
| 52 | /* These include both GPRs and XMMX registers */ | ||
| 53 | PERF_REG_X86_XMM_MAX = PERF_REG_X86_XMM15 + 2, | ||
| 33 | }; | 54 | }; |
| 34 | #endif /* _ASM_X86_PERF_REGS_H */ | 55 | #endif /* _ASM_X86_PERF_REGS_H */ |
diff --git a/tools/arch/x86/lib/memcpy_64.S b/tools/arch/x86/lib/memcpy_64.S index 3b24dc05251c..9d05572370ed 100644 --- a/tools/arch/x86/lib/memcpy_64.S +++ b/tools/arch/x86/lib/memcpy_64.S | |||
| @@ -257,6 +257,7 @@ ENTRY(__memcpy_mcsafe) | |||
| 257 | /* Copy successful. Return zero */ | 257 | /* Copy successful. Return zero */ |
| 258 | .L_done_memcpy_trap: | 258 | .L_done_memcpy_trap: |
| 259 | xorl %eax, %eax | 259 | xorl %eax, %eax |
| 260 | .L_done: | ||
| 260 | ret | 261 | ret |
| 261 | ENDPROC(__memcpy_mcsafe) | 262 | ENDPROC(__memcpy_mcsafe) |
| 262 | EXPORT_SYMBOL_GPL(__memcpy_mcsafe) | 263 | EXPORT_SYMBOL_GPL(__memcpy_mcsafe) |
| @@ -273,7 +274,7 @@ EXPORT_SYMBOL_GPL(__memcpy_mcsafe) | |||
| 273 | addl %edx, %ecx | 274 | addl %edx, %ecx |
| 274 | .E_trailing_bytes: | 275 | .E_trailing_bytes: |
| 275 | mov %ecx, %eax | 276 | mov %ecx, %eax |
| 276 | ret | 277 | jmp .L_done |
| 277 | 278 | ||
| 278 | /* | 279 | /* |
| 279 | * For write fault handling, given the destination is unaligned, | 280 | * For write fault handling, given the destination is unaligned, |
diff --git a/tools/lib/traceevent/Documentation/Makefile b/tools/lib/traceevent/Documentation/Makefile new file mode 100644 index 000000000000..aa72ab96c3c1 --- /dev/null +++ b/tools/lib/traceevent/Documentation/Makefile | |||
| @@ -0,0 +1,207 @@ | |||
| 1 | include ../../../scripts/Makefile.include | ||
| 2 | include ../../../scripts/utilities.mak | ||
| 3 | |||
| 4 | # This Makefile and manpage XSL files were taken from tools/perf/Documentation | ||
| 5 | # and modified for libtraceevent. | ||
| 6 | |||
| 7 | MAN3_TXT= \ | ||
| 8 | $(wildcard libtraceevent-*.txt) \ | ||
| 9 | libtraceevent.txt | ||
| 10 | |||
| 11 | MAN_TXT = $(MAN3_TXT) | ||
| 12 | _MAN_XML=$(patsubst %.txt,%.xml,$(MAN_TXT)) | ||
| 13 | _MAN_HTML=$(patsubst %.txt,%.html,$(MAN_TXT)) | ||
| 14 | _DOC_MAN3=$(patsubst %.txt,%.3,$(MAN3_TXT)) | ||
| 15 | |||
| 16 | MAN_XML=$(addprefix $(OUTPUT),$(_MAN_XML)) | ||
| 17 | MAN_HTML=$(addprefix $(OUTPUT),$(_MAN_HTML)) | ||
| 18 | DOC_MAN3=$(addprefix $(OUTPUT),$(_DOC_MAN3)) | ||
| 19 | |||
| 20 | # Make the path relative to DESTDIR, not prefix | ||
| 21 | ifndef DESTDIR | ||
| 22 | prefix?=$(HOME) | ||
| 23 | endif | ||
| 24 | bindir?=$(prefix)/bin | ||
| 25 | htmldir?=$(prefix)/share/doc/libtraceevent-doc | ||
| 26 | pdfdir?=$(prefix)/share/doc/libtraceevent-doc | ||
| 27 | mandir?=$(prefix)/share/man | ||
| 28 | man3dir=$(mandir)/man3 | ||
| 29 | |||
| 30 | ASCIIDOC=asciidoc | ||
| 31 | ASCIIDOC_EXTRA = --unsafe -f asciidoc.conf | ||
| 32 | ASCIIDOC_HTML = xhtml11 | ||
| 33 | MANPAGE_XSL = manpage-normal.xsl | ||
| 34 | XMLTO_EXTRA = | ||
| 35 | INSTALL?=install | ||
| 36 | RM ?= rm -f | ||
| 37 | |||
| 38 | ifdef USE_ASCIIDOCTOR | ||
| 39 | ASCIIDOC = asciidoctor | ||
| 40 | ASCIIDOC_EXTRA = -a compat-mode | ||
| 41 | ASCIIDOC_EXTRA += -I. -rasciidoctor-extensions | ||
| 42 | ASCIIDOC_EXTRA += -a mansource="libtraceevent" -a manmanual="libtraceevent Manual" | ||
| 43 | ASCIIDOC_HTML = xhtml5 | ||
| 44 | endif | ||
| 45 | |||
| 46 | XMLTO=xmlto | ||
| 47 | |||
| 48 | _tmp_tool_path := $(call get-executable,$(ASCIIDOC)) | ||
| 49 | ifeq ($(_tmp_tool_path),) | ||
| 50 | missing_tools = $(ASCIIDOC) | ||
| 51 | endif | ||
| 52 | |||
| 53 | ifndef USE_ASCIIDOCTOR | ||
| 54 | _tmp_tool_path := $(call get-executable,$(XMLTO)) | ||
| 55 | ifeq ($(_tmp_tool_path),) | ||
| 56 | missing_tools += $(XMLTO) | ||
| 57 | endif | ||
| 58 | endif | ||
| 59 | |||
| 60 | # | ||
| 61 | # For asciidoc ... | ||
| 62 | # -7.1.2, no extra settings are needed. | ||
| 63 | # 8.0-, set ASCIIDOC8. | ||
| 64 | # | ||
| 65 | |||
| 66 | # | ||
| 67 | # For docbook-xsl ... | ||
| 68 | # -1.68.1, set ASCIIDOC_NO_ROFF? (based on changelog from 1.73.0) | ||
| 69 | # 1.69.0, no extra settings are needed? | ||
| 70 | # 1.69.1-1.71.0, set DOCBOOK_SUPPRESS_SP? | ||
| 71 | # 1.71.1, no extra settings are needed? | ||
| 72 | # 1.72.0, set DOCBOOK_XSL_172. | ||
| 73 | # 1.73.0-, set ASCIIDOC_NO_ROFF | ||
| 74 | # | ||
| 75 | |||
| 76 | # | ||
| 77 | # If you had been using DOCBOOK_XSL_172 in an attempt to get rid | ||
| 78 | # of 'the ".ft C" problem' in your generated manpages, and you | ||
| 79 | # instead ended up with weird characters around callouts, try | ||
| 80 | # using ASCIIDOC_NO_ROFF instead (it works fine with ASCIIDOC8). | ||
| 81 | # | ||
| 82 | |||
| 83 | ifdef ASCIIDOC8 | ||
| 84 | ASCIIDOC_EXTRA += -a asciidoc7compatible | ||
| 85 | endif | ||
| 86 | ifdef DOCBOOK_XSL_172 | ||
| 87 | ASCIIDOC_EXTRA += -a libtraceevent-asciidoc-no-roff | ||
| 88 | MANPAGE_XSL = manpage-1.72.xsl | ||
| 89 | else | ||
| 90 | ifdef ASCIIDOC_NO_ROFF | ||
| 91 | # docbook-xsl after 1.72 needs the regular XSL, but will not | ||
| 92 | # pass-thru raw roff codes from asciidoc.conf, so turn them off. | ||
| 93 | ASCIIDOC_EXTRA += -a libtraceevent-asciidoc-no-roff | ||
| 94 | endif | ||
| 95 | endif | ||
| 96 | ifdef MAN_BOLD_LITERAL | ||
| 97 | XMLTO_EXTRA += -m manpage-bold-literal.xsl | ||
| 98 | endif | ||
| 99 | ifdef DOCBOOK_SUPPRESS_SP | ||
| 100 | XMLTO_EXTRA += -m manpage-suppress-sp.xsl | ||
| 101 | endif | ||
| 102 | |||
| 103 | SHELL_PATH ?= $(SHELL) | ||
| 104 | # Shell quote; | ||
| 105 | SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) | ||
| 106 | |||
| 107 | DESTDIR ?= | ||
| 108 | DESTDIR_SQ = '$(subst ','\'',$(DESTDIR))' | ||
| 109 | |||
| 110 | export DESTDIR DESTDIR_SQ | ||
| 111 | |||
| 112 | # | ||
| 113 | # Please note that there is a minor bug in asciidoc. | ||
| 114 | # The version after 6.0.3 _will_ include the patch found here: | ||
| 115 | # http://marc.theaimsgroup.com/?l=libtraceevent&m=111558757202243&w=2 | ||
| 116 | # | ||
| 117 | # Until that version is released you may have to apply the patch | ||
| 118 | # yourself - yes, all 6 characters of it! | ||
| 119 | # | ||
| 120 | QUIET_SUBDIR0 = +$(MAKE) -C # space to separate -C and subdir | ||
| 121 | QUIET_SUBDIR1 = | ||
| 122 | |||
| 123 | ifneq ($(findstring $(MAKEFLAGS),w),w) | ||
| 124 | PRINT_DIR = --no-print-directory | ||
| 125 | else # "make -w" | ||
| 126 | NO_SUBDIR = : | ||
| 127 | endif | ||
| 128 | |||
| 129 | ifneq ($(findstring $(MAKEFLAGS),s),s) | ||
| 130 | ifneq ($(V),1) | ||
| 131 | QUIET_ASCIIDOC = @echo ' ASCIIDOC '$@; | ||
| 132 | QUIET_XMLTO = @echo ' XMLTO '$@; | ||
| 133 | QUIET_SUBDIR0 = +@subdir= | ||
| 134 | QUIET_SUBDIR1 = ;$(NO_SUBDIR) \ | ||
| 135 | echo ' SUBDIR ' $$subdir; \ | ||
| 136 | $(MAKE) $(PRINT_DIR) -C $$subdir | ||
| 137 | export V | ||
| 138 | endif | ||
| 139 | endif | ||
| 140 | |||
| 141 | all: html man | ||
| 142 | |||
| 143 | man: man3 | ||
| 144 | man3: $(DOC_MAN3) | ||
| 145 | |||
| 146 | html: $(MAN_HTML) | ||
| 147 | |||
| 148 | $(MAN_HTML) $(DOC_MAN3): asciidoc.conf | ||
| 149 | |||
| 150 | install: install-man | ||
| 151 | |||
| 152 | check-man-tools: | ||
| 153 | ifdef missing_tools | ||
| 154 | $(error "You need to install $(missing_tools) for man pages") | ||
| 155 | endif | ||
| 156 | |||
| 157 | do-install-man: man | ||
| 158 | $(call QUIET_INSTALL, Documentation-man) \ | ||
| 159 | $(INSTALL) -d -m 755 $(DESTDIR)$(man3dir); \ | ||
| 160 | $(INSTALL) -m 644 $(DOC_MAN3) $(DESTDIR)$(man3dir); | ||
| 161 | |||
| 162 | install-man: check-man-tools man do-install-man | ||
| 163 | |||
| 164 | uninstall: uninstall-man | ||
| 165 | |||
| 166 | uninstall-man: | ||
| 167 | $(call QUIET_UNINST, Documentation-man) \ | ||
| 168 | $(Q)$(RM) $(addprefix $(DESTDIR)$(man3dir)/,$(DOC_MAN3)) | ||
| 169 | |||
| 170 | |||
| 171 | ifdef missing_tools | ||
| 172 | DO_INSTALL_MAN = $(warning Please install $(missing_tools) to have the man pages installed) | ||
| 173 | else | ||
| 174 | DO_INSTALL_MAN = do-install-man | ||
| 175 | endif | ||
| 176 | |||
| 177 | CLEAN_FILES = \ | ||
| 178 | $(MAN_XML) $(addsuffix +,$(MAN_XML)) \ | ||
| 179 | $(MAN_HTML) $(addsuffix +,$(MAN_HTML)) \ | ||
| 180 | $(DOC_MAN3) *.3 | ||
| 181 | |||
| 182 | clean: | ||
| 183 | $(call QUIET_CLEAN, Documentation) $(RM) $(CLEAN_FILES) | ||
| 184 | |||
| 185 | ifdef USE_ASCIIDOCTOR | ||
| 186 | $(OUTPUT)%.3 : $(OUTPUT)%.txt | ||
| 187 | $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ | ||
| 188 | $(ASCIIDOC) -b manpage -d manpage \ | ||
| 189 | $(ASCIIDOC_EXTRA) -alibtraceevent_version=$(EVENT_PARSE_VERSION) -o $@+ $< && \ | ||
| 190 | mv $@+ $@ | ||
| 191 | endif | ||
| 192 | |||
| 193 | $(OUTPUT)%.3 : $(OUTPUT)%.xml | ||
| 194 | $(QUIET_XMLTO)$(RM) $@ && \ | ||
| 195 | $(XMLTO) -o $(OUTPUT). -m $(MANPAGE_XSL) $(XMLTO_EXTRA) man $< | ||
| 196 | |||
| 197 | $(OUTPUT)%.xml : %.txt | ||
| 198 | $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ | ||
| 199 | $(ASCIIDOC) -b docbook -d manpage \ | ||
| 200 | $(ASCIIDOC_EXTRA) -alibtraceevent_version=$(EVENT_PARSE_VERSION) -o $@+ $< && \ | ||
| 201 | mv $@+ $@ | ||
| 202 | |||
| 203 | $(MAN_HTML): $(OUTPUT)%.html : %.txt | ||
| 204 | $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ | ||
| 205 | $(ASCIIDOC) -b $(ASCIIDOC_HTML) -d manpage \ | ||
| 206 | $(ASCIIDOC_EXTRA) -aperf_version=$(EVENT_PARSE_VERSION) -o $@+ $< && \ | ||
| 207 | mv $@+ $@ | ||
diff --git a/tools/lib/traceevent/Documentation/asciidoc.conf b/tools/lib/traceevent/Documentation/asciidoc.conf new file mode 100644 index 000000000000..07595717f06e --- /dev/null +++ b/tools/lib/traceevent/Documentation/asciidoc.conf | |||
| @@ -0,0 +1,120 @@ | |||
| 1 | ## linktep: macro | ||
| 2 | # | ||
| 3 | # Usage: linktep:command[manpage-section] | ||
| 4 | # | ||
| 5 | # Note, {0} is the manpage section, while {target} is the command. | ||
| 6 | # | ||
| 7 | # Show TEP link as: <command>(<section>); if section is defined, else just show | ||
| 8 | # the command. | ||
| 9 | |||
| 10 | [macros] | ||
| 11 | (?su)[\\]?(?P<name>linktep):(?P<target>\S*?)\[(?P<attrlist>.*?)\]= | ||
| 12 | |||
| 13 | [attributes] | ||
| 14 | asterisk=* | ||
| 15 | plus=+ | ||
| 16 | caret=^ | ||
| 17 | startsb=[ | ||
| 18 | endsb=] | ||
| 19 | tilde=~ | ||
| 20 | |||
| 21 | ifdef::backend-docbook[] | ||
| 22 | [linktep-inlinemacro] | ||
| 23 | {0%{target}} | ||
| 24 | {0#<citerefentry>} | ||
| 25 | {0#<refentrytitle>{target}</refentrytitle><manvolnum>{0}</manvolnum>} | ||
| 26 | {0#</citerefentry>} | ||
| 27 | endif::backend-docbook[] | ||
| 28 | |||
| 29 | ifdef::backend-docbook[] | ||
| 30 | ifndef::tep-asciidoc-no-roff[] | ||
| 31 | # "unbreak" docbook-xsl v1.68 for manpages. v1.69 works with or without this. | ||
| 32 | # v1.72 breaks with this because it replaces dots not in roff requests. | ||
| 33 | [listingblock] | ||
| 34 | <example><title>{title}</title> | ||
| 35 | <literallayout> | ||
| 36 | ifdef::doctype-manpage[] | ||
| 37 | .ft C | ||
| 38 | endif::doctype-manpage[] | ||
| 39 | | | ||
| 40 | ifdef::doctype-manpage[] | ||
| 41 | .ft | ||
| 42 | endif::doctype-manpage[] | ||
| 43 | </literallayout> | ||
| 44 | {title#}</example> | ||
| 45 | endif::tep-asciidoc-no-roff[] | ||
| 46 | |||
| 47 | ifdef::tep-asciidoc-no-roff[] | ||
| 48 | ifdef::doctype-manpage[] | ||
| 49 | # The following two small workarounds insert a simple paragraph after screen | ||
| 50 | [listingblock] | ||
| 51 | <example><title>{title}</title> | ||
| 52 | <literallayout> | ||
| 53 | | | ||
| 54 | </literallayout><simpara></simpara> | ||
| 55 | {title#}</example> | ||
| 56 | |||
| 57 | [verseblock] | ||
| 58 | <formalpara{id? id="{id}"}><title>{title}</title><para> | ||
| 59 | {title%}<literallayout{id? id="{id}"}> | ||
| 60 | {title#}<literallayout> | ||
| 61 | | | ||
| 62 | </literallayout> | ||
| 63 | {title#}</para></formalpara> | ||
| 64 | {title%}<simpara></simpara> | ||
| 65 | endif::doctype-manpage[] | ||
| 66 | endif::tep-asciidoc-no-roff[] | ||
| 67 | endif::backend-docbook[] | ||
| 68 | |||
| 69 | ifdef::doctype-manpage[] | ||
| 70 | ifdef::backend-docbook[] | ||
| 71 | [header] | ||
| 72 | template::[header-declarations] | ||
| 73 | <refentry> | ||
| 74 | <refmeta> | ||
| 75 | <refentrytitle>{mantitle}</refentrytitle> | ||
| 76 | <manvolnum>{manvolnum}</manvolnum> | ||
| 77 | <refmiscinfo class="source">libtraceevent</refmiscinfo> | ||
| 78 | <refmiscinfo class="version">{libtraceevent_version}</refmiscinfo> | ||
| 79 | <refmiscinfo class="manual">libtraceevent Manual</refmiscinfo> | ||
| 80 | </refmeta> | ||
| 81 | <refnamediv> | ||
| 82 | <refname>{manname1}</refname> | ||
| 83 | <refname>{manname2}</refname> | ||
| 84 | <refname>{manname3}</refname> | ||
| 85 | <refname>{manname4}</refname> | ||
| 86 | <refname>{manname5}</refname> | ||
| 87 | <refname>{manname6}</refname> | ||
| 88 | <refname>{manname7}</refname> | ||
| 89 | <refname>{manname8}</refname> | ||
| 90 | <refname>{manname9}</refname> | ||
| 91 | <refname>{manname10}</refname> | ||
| 92 | <refname>{manname11}</refname> | ||
| 93 | <refname>{manname12}</refname> | ||
| 94 | <refname>{manname13}</refname> | ||
| 95 | <refname>{manname14}</refname> | ||
| 96 | <refname>{manname15}</refname> | ||
| 97 | <refname>{manname16}</refname> | ||
| 98 | <refname>{manname17}</refname> | ||
| 99 | <refname>{manname18}</refname> | ||
| 100 | <refname>{manname19}</refname> | ||
| 101 | <refname>{manname20}</refname> | ||
| 102 | <refname>{manname21}</refname> | ||
| 103 | <refname>{manname22}</refname> | ||
| 104 | <refname>{manname23}</refname> | ||
| 105 | <refname>{manname24}</refname> | ||
| 106 | <refname>{manname25}</refname> | ||
| 107 | <refname>{manname26}</refname> | ||
| 108 | <refname>{manname27}</refname> | ||
| 109 | <refname>{manname28}</refname> | ||
| 110 | <refname>{manname29}</refname> | ||
| 111 | <refname>{manname30}</refname> | ||
| 112 | <refpurpose>{manpurpose}</refpurpose> | ||
| 113 | </refnamediv> | ||
| 114 | endif::backend-docbook[] | ||
| 115 | endif::doctype-manpage[] | ||
| 116 | |||
| 117 | ifdef::backend-xhtml11[] | ||
| 118 | [linktep-inlinemacro] | ||
| 119 | <a href="{target}.html">{target}{0?({0})}</a> | ||
| 120 | endif::backend-xhtml11[] | ||
diff --git a/tools/lib/traceevent/Documentation/libtraceevent-commands.txt b/tools/lib/traceevent/Documentation/libtraceevent-commands.txt new file mode 100644 index 000000000000..bec552001f8e --- /dev/null +++ b/tools/lib/traceevent/Documentation/libtraceevent-commands.txt | |||
| @@ -0,0 +1,153 @@ | |||
| 1 | libtraceevent(3) | ||
| 2 | ================ | ||
| 3 | |||
| 4 | NAME | ||
| 5 | ---- | ||
| 6 | tep_register_comm, tep_override_comm, tep_pid_is_registered, | ||
| 7 | tep_data_comm_from_pid, tep_data_pid_from_comm, tep_cmdline_pid - | ||
| 8 | Manage pid to process name mappings. | ||
| 9 | |||
| 10 | SYNOPSIS | ||
| 11 | -------- | ||
| 12 | [verse] | ||
| 13 | -- | ||
| 14 | *#include <event-parse.h>* | ||
| 15 | |||
| 16 | int *tep_register_comm*(struct tep_handle pass:[*]_tep_, const char pass:[*]_comm_, int _pid_); | ||
| 17 | int *tep_override_comm*(struct tep_handle pass:[*]_tep_, const char pass:[*]_comm_, int _pid_); | ||
| 18 | bool *tep_is_pid_registered*(struct tep_handle pass:[*]_tep_, int _pid_); | ||
| 19 | const char pass:[*]*tep_data_comm_from_pid*(struct tep_handle pass:[*]_pevent_, int _pid_); | ||
| 20 | struct cmdline pass:[*]*tep_data_pid_from_comm*(struct tep_handle pass:[*]_pevent_, const char pass:[*]_comm_, struct cmdline pass:[*]_next_); | ||
| 21 | int *tep_cmdline_pid*(struct tep_handle pass:[*]_pevent_, struct cmdline pass:[*]_cmdline_); | ||
| 22 | -- | ||
| 23 | |||
| 24 | DESCRIPTION | ||
| 25 | ----------- | ||
| 26 | These functions can be used to handle the mapping between pid and process name. | ||
| 27 | The library builds a cache of these mappings, which is used to display the name | ||
| 28 | of the process, instead of its pid. This information can be retrieved from | ||
| 29 | tracefs/saved_cmdlines file. | ||
| 30 | |||
| 31 | The _tep_register_comm()_ function registers a _pid_ / process name mapping. | ||
| 32 | If a command with the same _pid_ is already registered, an error is returned. | ||
| 33 | The _pid_ argument is the process ID, the _comm_ argument is the process name, | ||
| 34 | _tep_ is the event context. The _comm_ is duplicated internally. | ||
| 35 | |||
| 36 | The _tep_override_comm()_ function registers a _pid_ / process name mapping. | ||
| 37 | If a process with the same pid is already registered, the process name string is | ||
| 38 | udapted with the new one. The _pid_ argument is the process ID, the _comm_ | ||
| 39 | argument is the process name, _tep_ is the event context. The _comm_ is | ||
| 40 | duplicated internally. | ||
| 41 | |||
| 42 | The _tep_is_pid_registered()_ function checks if a pid has a process name | ||
| 43 | mapping registered. The _pid_ argument is the process ID, _tep_ is the event | ||
| 44 | context. | ||
| 45 | |||
| 46 | The _tep_data_comm_from_pid()_ function returns the process name for a given | ||
| 47 | pid. The _pid_ argument is the process ID, _tep_ is the event context. | ||
| 48 | The returned string should not be freed, but will be freed when the _tep_ | ||
| 49 | handler is closed. | ||
| 50 | |||
| 51 | The _tep_data_pid_from_comm()_ function returns a pid for a given process name. | ||
| 52 | The _comm_ argument is the process name, _tep_ is the event context. | ||
| 53 | The argument _next_ is the cmdline structure to search for the next pid. | ||
| 54 | As there may be more than one pid for a given process, the result of this call | ||
| 55 | can be passed back into a recurring call in the _next_ parameter, to search for | ||
| 56 | the next pid. If _next_ is NULL, it will return the first pid associated with | ||
| 57 | the _comm_. The function performs a linear search, so it may be slow. | ||
| 58 | |||
| 59 | The _tep_cmdline_pid()_ function returns the pid associated with a given | ||
| 60 | _cmdline_. The _tep_ argument is the event context. | ||
| 61 | |||
| 62 | RETURN VALUE | ||
| 63 | ------------ | ||
| 64 | _tep_register_comm()_ function returns 0 on success. In case of an error -1 is | ||
| 65 | returned and errno is set to indicate the cause of the problem: ENOMEM, if there | ||
| 66 | is not enough memory to duplicate the _comm_ or EEXIST if a mapping for this | ||
| 67 | _pid_ is already registered. | ||
| 68 | |||
| 69 | _tep_override_comm()_ function returns 0 on success. In case of an error -1 is | ||
| 70 | returned and errno is set to indicate the cause of the problem: ENOMEM, if there | ||
| 71 | is not enough memory to duplicate the _comm_. | ||
| 72 | |||
| 73 | _tep_is_pid_registered()_ function returns true if the _pid_ has a process name | ||
| 74 | mapped to it, false otherwise. | ||
| 75 | |||
| 76 | _tep_data_comm_from_pid()_ function returns the process name as string, or the | ||
| 77 | string "<...>" if there is no mapping for the given pid. | ||
| 78 | |||
| 79 | _tep_data_pid_from_comm()_ function returns a pointer to a struct cmdline, that | ||
| 80 | holds a pid for a given process, or NULL if none is found. This result can be | ||
| 81 | passed back into a recurring call as the _next_ parameter of the function. | ||
| 82 | |||
| 83 | _tep_cmdline_pid()_ functions returns the pid for the give cmdline. If _cmdline_ | ||
| 84 | is NULL, then -1 is returned. | ||
| 85 | |||
| 86 | EXAMPLE | ||
| 87 | ------- | ||
| 88 | The following example registers pid for command "ls", in context of event _tep_ | ||
| 89 | and performs various searches for pid / process name mappings: | ||
| 90 | [source,c] | ||
| 91 | -- | ||
| 92 | #include <event-parse.h> | ||
| 93 | ... | ||
| 94 | int ret; | ||
| 95 | int ls_pid = 1021; | ||
| 96 | struct tep_handle *tep = tep_alloc(); | ||
| 97 | ... | ||
| 98 | ret = tep_register_comm(tep, "ls", ls_pid); | ||
| 99 | if (ret != 0 && errno == EEXIST) | ||
| 100 | ret = tep_override_comm(tep, "ls", ls_pid); | ||
| 101 | if (ret != 0) { | ||
| 102 | /* Failed to register pid / command mapping */ | ||
| 103 | } | ||
| 104 | ... | ||
| 105 | if (tep_is_pid_registered(tep, ls_pid) == 0) { | ||
| 106 | /* Command mapping for ls_pid is not registered */ | ||
| 107 | } | ||
| 108 | ... | ||
| 109 | const char *comm = tep_data_comm_from_pid(tep, ls_pid); | ||
| 110 | if (comm) { | ||
| 111 | /* Found process name for ls_pid */ | ||
| 112 | } | ||
| 113 | ... | ||
| 114 | int pid; | ||
| 115 | struct cmdline *cmd = tep_data_pid_from_comm(tep, "ls", NULL); | ||
| 116 | while (cmd) { | ||
| 117 | pid = tep_cmdline_pid(tep, cmd); | ||
| 118 | /* Found pid for process "ls" */ | ||
| 119 | cmd = tep_data_pid_from_comm(tep, "ls", cmd); | ||
| 120 | } | ||
| 121 | -- | ||
| 122 | FILES | ||
| 123 | ----- | ||
| 124 | [verse] | ||
| 125 | -- | ||
| 126 | *event-parse.h* | ||
| 127 | Header file to include in order to have access to the library APIs. | ||
| 128 | *-ltraceevent* | ||
| 129 | Linker switch to add when building a program that uses the library. | ||
| 130 | -- | ||
| 131 | |||
| 132 | SEE ALSO | ||
| 133 | -------- | ||
| 134 | _libtraceevent(3)_, _trace-cmd(1)_ | ||
| 135 | |||
| 136 | AUTHOR | ||
| 137 | ------ | ||
| 138 | [verse] | ||
| 139 | -- | ||
| 140 | *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. | ||
| 141 | *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. | ||
| 142 | -- | ||
| 143 | REPORTING BUGS | ||
| 144 | -------------- | ||
| 145 | Report bugs to <linux-trace-devel@vger.kernel.org> | ||
| 146 | |||
| 147 | LICENSE | ||
| 148 | ------- | ||
| 149 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 | ||
| 150 | |||
| 151 | RESOURCES | ||
| 152 | --------- | ||
| 153 | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git | ||
diff --git a/tools/lib/traceevent/Documentation/libtraceevent-cpus.txt b/tools/lib/traceevent/Documentation/libtraceevent-cpus.txt new file mode 100644 index 000000000000..5ad70e43b752 --- /dev/null +++ b/tools/lib/traceevent/Documentation/libtraceevent-cpus.txt | |||
| @@ -0,0 +1,77 @@ | |||
| 1 | libtraceevent(3) | ||
| 2 | ================ | ||
| 3 | |||
| 4 | NAME | ||
| 5 | ---- | ||
| 6 | tep_get_cpus, tep_set_cpus - Get / set the number of CPUs, which have a tracing | ||
| 7 | buffer representing it. Note, the buffer may be empty. | ||
| 8 | |||
| 9 | SYNOPSIS | ||
| 10 | -------- | ||
| 11 | [verse] | ||
| 12 | -- | ||
| 13 | *#include <event-parse.h>* | ||
| 14 | |||
| 15 | int *tep_get_cpus*(struct tep_handle pass:[*]_tep_); | ||
| 16 | void *tep_set_cpus*(struct tep_handle pass:[*]_tep_, int _cpus_); | ||
| 17 | -- | ||
| 18 | |||
| 19 | DESCRIPTION | ||
| 20 | ----------- | ||
| 21 | The _tep_get_cpus()_ function gets the number of CPUs, which have a tracing | ||
| 22 | buffer representing it. The _tep_ argument is trace event parser context. | ||
| 23 | |||
| 24 | The _tep_set_cpus()_ function sets the number of CPUs, which have a tracing | ||
| 25 | buffer representing it. The _tep_ argument is trace event parser context. | ||
| 26 | The _cpu_ argument is the number of CPUs with tracing data. | ||
| 27 | |||
| 28 | RETURN VALUE | ||
| 29 | ------------ | ||
| 30 | The _tep_get_cpus()_ functions returns the number of CPUs, which have tracing | ||
| 31 | data recorded. | ||
| 32 | |||
| 33 | EXAMPLE | ||
| 34 | ------- | ||
| 35 | [source,c] | ||
| 36 | -- | ||
| 37 | #include <event-parse.h> | ||
| 38 | ... | ||
| 39 | struct tep_handle *tep = tep_alloc(); | ||
| 40 | ... | ||
| 41 | tep_set_cpus(tep, 5); | ||
| 42 | ... | ||
| 43 | printf("We have tracing data for %d CPUs", tep_get_cpus(tep)); | ||
| 44 | -- | ||
| 45 | |||
| 46 | FILES | ||
| 47 | ----- | ||
| 48 | [verse] | ||
| 49 | -- | ||
| 50 | *event-parse.h* | ||
| 51 | Header file to include in order to have access to the library APIs. | ||
| 52 | *-ltraceevent* | ||
| 53 | Linker switch to add when building a program that uses the library. | ||
| 54 | -- | ||
| 55 | |||
| 56 | SEE ALSO | ||
| 57 | -------- | ||
| 58 | _libtraceevent(3)_, _trace-cmd(1)_ | ||
| 59 | |||
| 60 | AUTHOR | ||
| 61 | ------ | ||
| 62 | [verse] | ||
| 63 | -- | ||
| 64 | *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. | ||
| 65 | *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. | ||
| 66 | -- | ||
| 67 | REPORTING BUGS | ||
| 68 | -------------- | ||
| 69 | Report bugs to <linux-trace-devel@vger.kernel.org> | ||
| 70 | |||
| 71 | LICENSE | ||
| 72 | ------- | ||
| 73 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 | ||
| 74 | |||
| 75 | RESOURCES | ||
| 76 | --------- | ||
| 77 | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git | ||
diff --git a/tools/lib/traceevent/Documentation/libtraceevent-endian_read.txt b/tools/lib/traceevent/Documentation/libtraceevent-endian_read.txt new file mode 100644 index 000000000000..e64851b6e189 --- /dev/null +++ b/tools/lib/traceevent/Documentation/libtraceevent-endian_read.txt | |||
| @@ -0,0 +1,78 @@ | |||
| 1 | libtraceevent(3) | ||
| 2 | ================ | ||
| 3 | |||
| 4 | NAME | ||
| 5 | ---- | ||
| 6 | tep_read_number - Reads a number from raw data. | ||
| 7 | |||
| 8 | SYNOPSIS | ||
| 9 | -------- | ||
| 10 | [verse] | ||
| 11 | -- | ||
| 12 | *#include <event-parse.h>* | ||
| 13 | |||
| 14 | unsigned long long *tep_read_number*(struct tep_handle pass:[*]_tep_, const void pass:[*]_ptr_, int _size_); | ||
| 15 | -- | ||
| 16 | |||
| 17 | DESCRIPTION | ||
| 18 | ----------- | ||
| 19 | The _tep_read_number()_ function reads an integer from raw data, taking into | ||
| 20 | account the endianness of the raw data and the current host. The _tep_ argument | ||
| 21 | is the trace event parser context. The _ptr_ is a pointer to the raw data, where | ||
| 22 | the integer is, and the _size_ is the size of the integer. | ||
| 23 | |||
| 24 | RETURN VALUE | ||
| 25 | ------------ | ||
| 26 | The _tep_read_number()_ function returns the integer in the byte order of | ||
| 27 | the current host. In case of an error, 0 is returned. | ||
| 28 | |||
| 29 | EXAMPLE | ||
| 30 | ------- | ||
| 31 | [source,c] | ||
| 32 | -- | ||
| 33 | #include <event-parse.h> | ||
| 34 | ... | ||
| 35 | struct tep_handle *tep = tep_alloc(); | ||
| 36 | ... | ||
| 37 | void process_record(struct tep_record *record) | ||
| 38 | { | ||
| 39 | int offset = 24; | ||
| 40 | int data = tep_read_number(tep, record->data + offset, 4); | ||
| 41 | |||
| 42 | /* Read the 4 bytes at the offset 24 of data as an integer */ | ||
| 43 | } | ||
| 44 | ... | ||
| 45 | -- | ||
| 46 | |||
| 47 | FILES | ||
| 48 | ----- | ||
| 49 | [verse] | ||
| 50 | -- | ||
| 51 | *event-parse.h* | ||
| 52 | Header file to include in order to have access to the library APIs. | ||
| 53 | *-ltraceevent* | ||
| 54 | Linker switch to add when building a program that uses the library. | ||
| 55 | -- | ||
| 56 | |||
| 57 | SEE ALSO | ||
| 58 | -------- | ||
| 59 | _libtraceevent(3)_, _trace-cmd(1)_ | ||
| 60 | |||
| 61 | AUTHOR | ||
| 62 | ------ | ||
| 63 | [verse] | ||
| 64 | -- | ||
| 65 | *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. | ||
| 66 | *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. | ||
| 67 | -- | ||
| 68 | REPORTING BUGS | ||
| 69 | -------------- | ||
| 70 | Report bugs to <linux-trace-devel@vger.kernel.org> | ||
| 71 | |||
| 72 | LICENSE | ||
| 73 | ------- | ||
| 74 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 | ||
| 75 | |||
| 76 | RESOURCES | ||
| 77 | --------- | ||
| 78 | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git | ||
diff --git a/tools/lib/traceevent/Documentation/libtraceevent-event_find.txt b/tools/lib/traceevent/Documentation/libtraceevent-event_find.txt new file mode 100644 index 000000000000..7bc062c9f76f --- /dev/null +++ b/tools/lib/traceevent/Documentation/libtraceevent-event_find.txt | |||
| @@ -0,0 +1,103 @@ | |||
| 1 | libtraceevent(3) | ||
| 2 | ================ | ||
| 3 | |||
| 4 | NAME | ||
| 5 | ---- | ||
| 6 | tep_find_event,tep_find_event_by_name,tep_find_event_by_record - | ||
| 7 | Find events by given key. | ||
| 8 | |||
| 9 | SYNOPSIS | ||
| 10 | -------- | ||
| 11 | [verse] | ||
| 12 | -- | ||
| 13 | *#include <event-parse.h>* | ||
| 14 | |||
| 15 | struct tep_event pass:[*]*tep_find_event*(struct tep_handle pass:[*]_tep_, int _id_); | ||
| 16 | struct tep_event pass:[*]*tep_find_event_by_name*(struct tep_handle pass:[*]_tep_, const char pass:[*]_sys_, const char pass:[*]_name_); | ||
| 17 | struct tep_event pass:[*]*tep_find_event_by_record*(struct tep_handle pass:[*]_tep_, struct tep_record pass:[*]_record_); | ||
| 18 | -- | ||
| 19 | |||
| 20 | DESCRIPTION | ||
| 21 | ----------- | ||
| 22 | This set of functions can be used to search for an event, based on a given | ||
| 23 | criteria. All functions require a pointer to a _tep_, trace event parser | ||
| 24 | context. | ||
| 25 | |||
| 26 | The _tep_find_event()_ function searches for an event by given event _id_. The | ||
| 27 | event ID is assigned dynamically and can be viewed in event's format file, | ||
| 28 | "ID" field. | ||
| 29 | |||
| 30 | The tep_find_event_by_name()_ function searches for an event by given | ||
| 31 | event _name_, under the system _sys_. If the _sys_ is NULL (not specified), | ||
| 32 | the first event with _name_ is returned. | ||
| 33 | |||
| 34 | The tep_find_event_by_record()_ function searches for an event from a given | ||
| 35 | _record_. | ||
| 36 | |||
| 37 | RETURN VALUE | ||
| 38 | ------------ | ||
| 39 | All these functions return a pointer to the found event, or NULL if there is no | ||
| 40 | such event. | ||
| 41 | |||
| 42 | EXAMPLE | ||
| 43 | ------- | ||
| 44 | [source,c] | ||
| 45 | -- | ||
| 46 | #include <event-parse.h> | ||
| 47 | ... | ||
| 48 | struct tep_handle *tep = tep_alloc(); | ||
| 49 | ... | ||
| 50 | struct tep_event *event; | ||
| 51 | |||
| 52 | event = tep_find_event(tep, 1857); | ||
| 53 | if (event == NULL) { | ||
| 54 | /* There is no event with ID 1857 */ | ||
| 55 | } | ||
| 56 | |||
| 57 | event = tep_find_event_by_name(tep, "kvm", "kvm_exit"); | ||
| 58 | if (event == NULL) { | ||
| 59 | /* There is no kvm_exit event, from kvm system */ | ||
| 60 | } | ||
| 61 | |||
| 62 | void event_from_record(struct tep_record *record) | ||
| 63 | { | ||
| 64 | struct tep_event *event = tep_find_event_by_record(tep, record); | ||
| 65 | if (event == NULL) { | ||
| 66 | /* There is no event from given record */ | ||
| 67 | } | ||
| 68 | } | ||
| 69 | ... | ||
| 70 | -- | ||
| 71 | |||
| 72 | FILES | ||
| 73 | ----- | ||
| 74 | [verse] | ||
| 75 | -- | ||
| 76 | *event-parse.h* | ||
| 77 | Header file to include in order to have access to the library APIs. | ||
| 78 | *-ltraceevent* | ||
| 79 | Linker switch to add when building a program that uses the library. | ||
| 80 | -- | ||
| 81 | |||
| 82 | SEE ALSO | ||
| 83 | -------- | ||
| 84 | _libtraceevent(3)_, _trace-cmd(1)_ | ||
| 85 | |||
| 86 | AUTHOR | ||
| 87 | ------ | ||
| 88 | [verse] | ||
| 89 | -- | ||
| 90 | *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. | ||
| 91 | *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. | ||
| 92 | -- | ||
| 93 | REPORTING BUGS | ||
| 94 | -------------- | ||
| 95 | Report bugs to <linux-trace-devel@vger.kernel.org> | ||
| 96 | |||
| 97 | LICENSE | ||
| 98 | ------- | ||
| 99 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 | ||
| 100 | |||
| 101 | RESOURCES | ||
| 102 | --------- | ||
| 103 | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git | ||
diff --git a/tools/lib/traceevent/Documentation/libtraceevent-event_get.txt b/tools/lib/traceevent/Documentation/libtraceevent-event_get.txt new file mode 100644 index 000000000000..6525092fc417 --- /dev/null +++ b/tools/lib/traceevent/Documentation/libtraceevent-event_get.txt | |||
| @@ -0,0 +1,99 @@ | |||
| 1 | libtraceevent(3) | ||
| 2 | ================ | ||
| 3 | |||
| 4 | NAME | ||
| 5 | ---- | ||
| 6 | tep_get_event, tep_get_first_event, tep_get_events_count - Access events. | ||
| 7 | |||
| 8 | SYNOPSIS | ||
| 9 | -------- | ||
| 10 | [verse] | ||
| 11 | -- | ||
| 12 | *#include <event-parse.h>* | ||
| 13 | |||
| 14 | struct tep_event pass:[*]*tep_get_event*(struct tep_handle pass:[*]_tep_, int _index_); | ||
| 15 | struct tep_event pass:[*]*tep_get_first_event*(struct tep_handle pass:[*]_tep_); | ||
| 16 | int *tep_get_events_count*(struct tep_handle pass:[*]_tep_); | ||
| 17 | -- | ||
| 18 | |||
| 19 | DESCRIPTION | ||
| 20 | ----------- | ||
| 21 | The _tep_get_event()_ function returns a pointer to event at the given _index_. | ||
| 22 | The _tep_ argument is trace event parser context, the _index_ is the index of | ||
| 23 | the requested event. | ||
| 24 | |||
| 25 | The _tep_get_first_event()_ function returns a pointer to the first event. | ||
| 26 | As events are stored in an array, this function returns the pointer to the | ||
| 27 | beginning of the array. The _tep_ argument is trace event parser context. | ||
| 28 | |||
| 29 | The _tep_get_events_count()_ function returns the number of the events | ||
| 30 | in the array. The _tep_ argument is trace event parser context. | ||
| 31 | |||
| 32 | RETURN VALUE | ||
| 33 | ------------ | ||
| 34 | The _tep_get_event()_ returns a pointer to the event located at _index_. | ||
| 35 | NULL is returned in case of error, in case there are no events or _index_ is | ||
| 36 | out of range. | ||
| 37 | |||
| 38 | The _tep_get_first_event()_ returns a pointer to the first event. NULL is | ||
| 39 | returned in case of error, or in case there are no events. | ||
| 40 | |||
| 41 | The _tep_get_events_count()_ returns the number of the events. 0 is | ||
| 42 | returned in case of error, or in case there are no events. | ||
| 43 | |||
| 44 | EXAMPLE | ||
| 45 | ------- | ||
| 46 | [source,c] | ||
| 47 | -- | ||
| 48 | #include <event-parse.h> | ||
| 49 | ... | ||
| 50 | struct tep_handle *tep = tep_alloc(); | ||
| 51 | ... | ||
| 52 | int i,count = tep_get_events_count(tep); | ||
| 53 | struct tep_event *event, *events = tep_get_first_event(tep); | ||
| 54 | |||
| 55 | if (events == NULL) { | ||
| 56 | /* There are no events */ | ||
| 57 | } else { | ||
| 58 | for (i = 0; i < count; i++) { | ||
| 59 | event = (events+i); | ||
| 60 | /* process events[i] */ | ||
| 61 | } | ||
| 62 | |||
| 63 | /* Get the last event */ | ||
| 64 | event = tep_get_event(tep, count-1); | ||
| 65 | } | ||
| 66 | -- | ||
| 67 | |||
| 68 | FILES | ||
| 69 | ----- | ||
| 70 | [verse] | ||
| 71 | -- | ||
| 72 | *event-parse.h* | ||
| 73 | Header file to include in order to have access to the library APIs. | ||
| 74 | *-ltraceevent* | ||
| 75 | Linker switch to add when building a program that uses the library. | ||
| 76 | -- | ||
| 77 | |||
| 78 | SEE ALSO | ||
| 79 | -------- | ||
| 80 | _libtraceevent(3)_, _trace-cmd(1)_ | ||
| 81 | |||
| 82 | AUTHOR | ||
| 83 | ------ | ||
| 84 | [verse] | ||
| 85 | -- | ||
| 86 | *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. | ||
| 87 | *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. | ||
| 88 | -- | ||
| 89 | REPORTING BUGS | ||
| 90 | -------------- | ||
| 91 | Report bugs to <linux-trace-devel@vger.kernel.org> | ||
| 92 | |||
| 93 | LICENSE | ||
| 94 | ------- | ||
| 95 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 | ||
| 96 | |||
| 97 | RESOURCES | ||
| 98 | --------- | ||
| 99 | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git | ||
diff --git a/tools/lib/traceevent/Documentation/libtraceevent-event_list.txt b/tools/lib/traceevent/Documentation/libtraceevent-event_list.txt new file mode 100644 index 000000000000..fba350e5a4cb --- /dev/null +++ b/tools/lib/traceevent/Documentation/libtraceevent-event_list.txt | |||
| @@ -0,0 +1,122 @@ | |||
| 1 | libtraceevent(3) | ||
| 2 | ================ | ||
| 3 | |||
| 4 | NAME | ||
| 5 | ---- | ||
| 6 | tep_list_events, tep_list_events_copy - | ||
| 7 | Get list of events, sorted by given criteria. | ||
| 8 | |||
| 9 | SYNOPSIS | ||
| 10 | -------- | ||
| 11 | [verse] | ||
| 12 | -- | ||
| 13 | *#include <event-parse.h>* | ||
| 14 | |||
| 15 | enum *tep_event_sort_type* { | ||
| 16 | _TEP_EVENT_SORT_ID_, | ||
| 17 | _TEP_EVENT_SORT_NAME_, | ||
| 18 | _TEP_EVENT_SORT_SYSTEM_, | ||
| 19 | }; | ||
| 20 | |||
| 21 | struct tep_event pass:[*]pass:[*]*tep_list_events*(struct tep_handle pass:[*]_tep_, enum tep_event_sort_type _sort_type_); | ||
| 22 | struct tep_event pass:[*]pass:[*]*tep_list_events_copy*(struct tep_handle pass:[*]_tep_, enum tep_event_sort_type _sort_type_); | ||
| 23 | -- | ||
| 24 | |||
| 25 | DESCRIPTION | ||
| 26 | ----------- | ||
| 27 | The _tep_list_events()_ function returns an array of pointers to the events, | ||
| 28 | sorted by the _sort_type_ criteria. The last element of the array is NULL. | ||
| 29 | The returned memory must not be freed, it is managed by the library. | ||
| 30 | The function is not thread safe. The _tep_ argument is trace event parser | ||
| 31 | context. The _sort_type_ argument is the required sort criteria: | ||
| 32 | [verse] | ||
| 33 | -- | ||
| 34 | _TEP_EVENT_SORT_ID_ - sort by the event ID. | ||
| 35 | _TEP_EVENT_SORT_NAME_ - sort by the event (name, system, id) triplet. | ||
| 36 | _TEP_EVENT_SORT_SYSTEM_ - sort by the event (system, name, id) triplet. | ||
| 37 | -- | ||
| 38 | |||
| 39 | The _tep_list_events_copy()_ is a thread safe version of _tep_list_events()_. | ||
| 40 | It has the same behavior, but the returned array is allocated internally and | ||
| 41 | must be freed by the caller. Note that the content of the array must not be | ||
| 42 | freed (see the EXAMPLE below). | ||
| 43 | |||
| 44 | RETURN VALUE | ||
| 45 | ------------ | ||
| 46 | The _tep_list_events()_ function returns an array of pointers to events. | ||
| 47 | In case of an error, NULL is returned. The returned array must not be freed, | ||
| 48 | it is managed by the library. | ||
| 49 | |||
| 50 | The _tep_list_events_copy()_ function returns an array of pointers to events. | ||
| 51 | In case of an error, NULL is returned. The returned array must be freed by | ||
| 52 | the caller. | ||
| 53 | |||
| 54 | EXAMPLE | ||
| 55 | ------- | ||
| 56 | [source,c] | ||
| 57 | -- | ||
| 58 | #include <event-parse.h> | ||
| 59 | ... | ||
| 60 | struct tep_handle *tep = tep_alloc(); | ||
| 61 | ... | ||
| 62 | int i; | ||
| 63 | struct tep_event_format **events; | ||
| 64 | |||
| 65 | i=0; | ||
| 66 | events = tep_list_events(tep, TEP_EVENT_SORT_ID); | ||
| 67 | if (events == NULL) { | ||
| 68 | /* Failed to get the events, sorted by ID */ | ||
| 69 | } else { | ||
| 70 | while(events[i]) { | ||
| 71 | /* walk through the list of the events, sorted by ID */ | ||
| 72 | i++; | ||
| 73 | } | ||
| 74 | } | ||
| 75 | |||
| 76 | i=0; | ||
| 77 | events = tep_list_events_copy(tep, TEP_EVENT_SORT_NAME); | ||
| 78 | if (events == NULL) { | ||
| 79 | /* Failed to get the events, sorted by name */ | ||
| 80 | } else { | ||
| 81 | while(events[i]) { | ||
| 82 | /* walk through the list of the events, sorted by name */ | ||
| 83 | i++; | ||
| 84 | } | ||
| 85 | free(events); | ||
| 86 | } | ||
| 87 | |||
| 88 | ... | ||
| 89 | -- | ||
| 90 | |||
| 91 | FILES | ||
| 92 | ----- | ||
| 93 | [verse] | ||
| 94 | -- | ||
| 95 | *event-parse.h* | ||
| 96 | Header file to include in order to have access to the library APIs. | ||
| 97 | *-ltraceevent* | ||
| 98 | Linker switch to add when building a program that uses the library. | ||
| 99 | -- | ||
| 100 | |||
| 101 | SEE ALSO | ||
| 102 | -------- | ||
| 103 | _libtraceevent(3)_, _trace-cmd(1)_ | ||
| 104 | |||
| 105 | AUTHOR | ||
| 106 | ------ | ||
| 107 | [verse] | ||
| 108 | -- | ||
| 109 | *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. | ||
| 110 | *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. | ||
| 111 | -- | ||
| 112 | REPORTING BUGS | ||
| 113 | -------------- | ||
| 114 | Report bugs to <linux-trace-devel@vger.kernel.org> | ||
| 115 | |||
| 116 | LICENSE | ||
| 117 | ------- | ||
| 118 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 | ||
| 119 | |||
| 120 | RESOURCES | ||
| 121 | --------- | ||
| 122 | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git | ||
diff --git a/tools/lib/traceevent/Documentation/libtraceevent-field_find.txt b/tools/lib/traceevent/Documentation/libtraceevent-field_find.txt new file mode 100644 index 000000000000..0896af5b9eff --- /dev/null +++ b/tools/lib/traceevent/Documentation/libtraceevent-field_find.txt | |||
| @@ -0,0 +1,118 @@ | |||
| 1 | libtraceevent(3) | ||
| 2 | ================ | ||
| 3 | |||
| 4 | NAME | ||
| 5 | ---- | ||
| 6 | tep_find_common_field, tep_find_field, tep_find_any_field - | ||
| 7 | Search for a field in an event. | ||
| 8 | |||
| 9 | SYNOPSIS | ||
| 10 | -------- | ||
| 11 | [verse] | ||
| 12 | -- | ||
| 13 | *#include <event-parse.h>* | ||
| 14 | |||
| 15 | struct tep_format_field pass:[*]*tep_find_common_field*(struct tep_event pass:[*]_event_, const char pass:[*]_name_); | ||
| 16 | struct tep_format_field pass:[*]*tep_find_field*(struct tep_event_ormat pass:[*]_event_, const char pass:[*]_name_); | ||
| 17 | struct tep_format_field pass:[*]*tep_find_any_field*(struct tep_event pass:[*]_event_, const char pass:[*]_name_); | ||
| 18 | -- | ||
| 19 | |||
| 20 | DESCRIPTION | ||
| 21 | ----------- | ||
| 22 | These functions search for a field with given name in an event. The field | ||
| 23 | returned can be used to find the field content from within a data record. | ||
| 24 | |||
| 25 | The _tep_find_common_field()_ function searches for a common field with _name_ | ||
| 26 | in the _event_. | ||
| 27 | |||
| 28 | The _tep_find_field()_ function searches for an event specific field with | ||
| 29 | _name_ in the _event_. | ||
| 30 | |||
| 31 | The _tep_find_any_field()_ function searches for any field with _name_ in the | ||
| 32 | _event_. | ||
| 33 | |||
| 34 | RETURN VALUE | ||
| 35 | ------------ | ||
| 36 | The _tep_find_common_field(), _tep_find_field()_ and _tep_find_any_field()_ | ||
| 37 | functions return a pointer to the found field, or NULL in case there is no field | ||
| 38 | with the requested name. | ||
| 39 | |||
| 40 | EXAMPLE | ||
| 41 | ------- | ||
| 42 | [source,c] | ||
| 43 | -- | ||
| 44 | #include <event-parse.h> | ||
| 45 | ... | ||
| 46 | void get_htimer_info(struct tep_handle *tep, struct tep_record *record) | ||
| 47 | { | ||
| 48 | struct tep_format_field *field; | ||
| 49 | struct tep_event *event; | ||
| 50 | long long softexpires; | ||
| 51 | int mode; | ||
| 52 | int pid; | ||
| 53 | |||
| 54 | event = tep_find_event_by_name(tep, "timer", "hrtimer_start"); | ||
| 55 | |||
| 56 | field = tep_find_common_field(event, "common_pid"); | ||
| 57 | if (field == NULL) { | ||
| 58 | /* Cannot find "common_pid" field in the event */ | ||
| 59 | } else { | ||
| 60 | /* Get pid from the data record */ | ||
| 61 | pid = tep_read_number(tep, record->data + field->offset, | ||
| 62 | field->size); | ||
| 63 | } | ||
| 64 | |||
| 65 | field = tep_find_field(event, "softexpires"); | ||
| 66 | if (field == NULL) { | ||
| 67 | /* Cannot find "softexpires" event specific field in the event */ | ||
| 68 | } else { | ||
| 69 | /* Get softexpires parameter from the data record */ | ||
| 70 | softexpires = tep_read_number(tep, record->data + field->offset, | ||
| 71 | field->size); | ||
| 72 | } | ||
| 73 | |||
| 74 | field = tep_find_any_field(event, "mode"); | ||
| 75 | if (field == NULL) { | ||
| 76 | /* Cannot find "mode" field in the event */ | ||
| 77 | } else | ||
| 78 | { | ||
| 79 | /* Get mode parameter from the data record */ | ||
| 80 | mode = tep_read_number(tep, record->data + field->offset, | ||
| 81 | field->size); | ||
| 82 | } | ||
| 83 | } | ||
| 84 | ... | ||
| 85 | -- | ||
| 86 | |||
| 87 | FILES | ||
| 88 | ----- | ||
| 89 | [verse] | ||
| 90 | -- | ||
| 91 | *event-parse.h* | ||
| 92 | Header file to include in order to have access to the library APIs. | ||
| 93 | *-ltraceevent* | ||
| 94 | Linker switch to add when building a program that uses the library. | ||
| 95 | -- | ||
| 96 | |||
| 97 | SEE ALSO | ||
| 98 | -------- | ||
| 99 | _libtraceevent(3)_, _trace-cmd(1)_ | ||
| 100 | |||
| 101 | AUTHOR | ||
| 102 | ------ | ||
| 103 | [verse] | ||
| 104 | -- | ||
| 105 | *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. | ||
| 106 | *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. | ||
| 107 | -- | ||
| 108 | REPORTING BUGS | ||
| 109 | -------------- | ||
| 110 | Report bugs to <linux-trace-devel@vger.kernel.org> | ||
| 111 | |||
| 112 | LICENSE | ||
| 113 | ------- | ||
| 114 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 | ||
| 115 | |||
| 116 | RESOURCES | ||
| 117 | --------- | ||
| 118 | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git | ||
diff --git a/tools/lib/traceevent/Documentation/libtraceevent-field_get_val.txt b/tools/lib/traceevent/Documentation/libtraceevent-field_get_val.txt new file mode 100644 index 000000000000..6324f0d48aeb --- /dev/null +++ b/tools/lib/traceevent/Documentation/libtraceevent-field_get_val.txt | |||
| @@ -0,0 +1,122 @@ | |||
| 1 | libtraceevent(3) | ||
| 2 | ================ | ||
| 3 | |||
| 4 | NAME | ||
| 5 | ---- | ||
| 6 | tep_get_any_field_val, tep_get_common_field_val, tep_get_field_val, | ||
| 7 | tep_get_field_raw - Get value of a field. | ||
| 8 | |||
| 9 | SYNOPSIS | ||
| 10 | -------- | ||
| 11 | [verse] | ||
| 12 | -- | ||
| 13 | *#include <event-parse.h>* | ||
| 14 | *#include <trace-seq.h>* | ||
| 15 | |||
| 16 | int *tep_get_any_field_val*(struct trace_seq pass:[*]_s_, struct tep_event pass:[*]_event_, const char pass:[*]_name_, struct tep_record pass:[*]_record_, unsigned long long pass:[*]_val_, int _err_); | ||
| 17 | int *tep_get_common_field_val*(struct trace_seq pass:[*]_s_, struct tep_event pass:[*]_event_, const char pass:[*]_name_, struct tep_record pass:[*]_record_, unsigned long long pass:[*]_val_, int _err_); | ||
| 18 | int *tep_get_field_val*(struct trace_seq pass:[*]_s_, struct tep_event pass:[*]_event_, const char pass:[*]_name_, struct tep_record pass:[*]_record_, unsigned long long pass:[*]_val_, int _err_); | ||
| 19 | void pass:[*]*tep_get_field_raw*(struct trace_seq pass:[*]_s_, struct tep_event pass:[*]_event_, const char pass:[*]_name_, struct tep_record pass:[*]_record_, int pass:[*]_len_, int _err_); | ||
| 20 | -- | ||
| 21 | |||
| 22 | DESCRIPTION | ||
| 23 | ----------- | ||
| 24 | These functions can be used to find a field and retrieve its value. | ||
| 25 | |||
| 26 | The _tep_get_any_field_val()_ function searches in the _record_ for a field | ||
| 27 | with _name_, part of the _event_. If the field is found, its value is stored in | ||
| 28 | _val_. If there is an error and _err_ is not zero, then an error string is | ||
| 29 | written into _s_. | ||
| 30 | |||
| 31 | The _tep_get_common_field_val()_ function does the same as | ||
| 32 | _tep_get_any_field_val()_, but searches only in the common fields. This works | ||
| 33 | for any event as all events include the common fields. | ||
| 34 | |||
| 35 | The _tep_get_field_val()_ function does the same as _tep_get_any_field_val()_, | ||
| 36 | but searches only in the event specific fields. | ||
| 37 | |||
| 38 | The _tep_get_field_raw()_ function searches in the _record_ for a field with | ||
| 39 | _name_, part of the _event_. If the field is found, a pointer to where the field | ||
| 40 | exists in the record's raw data is returned. The size of the data is stored in | ||
| 41 | _len_. If there is an error and _err_ is not zero, then an error string is | ||
| 42 | written into _s_. | ||
| 43 | |||
| 44 | RETURN VALUE | ||
| 45 | ------------ | ||
| 46 | The _tep_get_any_field_val()_, _tep_get_common_field_val()_ and | ||
| 47 | _tep_get_field_val()_ functions return 0 on success, or -1 in case of an error. | ||
| 48 | |||
| 49 | The _tep_get_field_raw()_ function returns a pointer to field's raw data, and | ||
| 50 | places the length of this data in _len_. In case of an error NULL is returned. | ||
| 51 | |||
| 52 | EXAMPLE | ||
| 53 | ------- | ||
| 54 | [source,c] | ||
| 55 | -- | ||
| 56 | #include <event-parse.h> | ||
| 57 | #include <trace-seq.h> | ||
| 58 | ... | ||
| 59 | struct tep_handle *tep = tep_alloc(); | ||
| 60 | ... | ||
| 61 | struct tep_event *event = tep_find_event_by_name(tep, "kvm", "kvm_exit"); | ||
| 62 | ... | ||
| 63 | void process_record(struct tep_record *record) | ||
| 64 | { | ||
| 65 | int len; | ||
| 66 | char *comm; | ||
| 67 | struct tep_event_format *event; | ||
| 68 | unsigned long long val; | ||
| 69 | |||
| 70 | event = tep_find_event_by_record(pevent, record); | ||
| 71 | if (event != NULL) { | ||
| 72 | if (tep_get_common_field_val(NULL, event, "common_type", | ||
| 73 | record, &val, 0) == 0) { | ||
| 74 | /* Got the value of common type field */ | ||
| 75 | } | ||
| 76 | if (tep_get_field_val(NULL, event, "pid", record, &val, 0) == 0) { | ||
| 77 | /* Got the value of pid specific field */ | ||
| 78 | } | ||
| 79 | comm = tep_get_field_raw(NULL, event, "comm", record, &len, 0); | ||
| 80 | if (comm != NULL) { | ||
| 81 | /* Got a pointer to the comm event specific field */ | ||
| 82 | } | ||
| 83 | } | ||
| 84 | } | ||
| 85 | -- | ||
| 86 | |||
| 87 | FILES | ||
| 88 | ----- | ||
| 89 | [verse] | ||
| 90 | -- | ||
| 91 | *event-parse.h* | ||
| 92 | Header file to include in order to have access to the library APIs. | ||
| 93 | *trace-seq.h* | ||
| 94 | Header file to include in order to have access to trace sequences | ||
| 95 | related APIs. Trace sequences are used to allow a function to call | ||
| 96 | several other functions to create a string of data to use. | ||
| 97 | *-ltraceevent* | ||
| 98 | Linker switch to add when building a program that uses the library. | ||
| 99 | -- | ||
| 100 | |||
| 101 | SEE ALSO | ||
| 102 | -------- | ||
| 103 | _libtraceevent(3)_, _trace-cmd(1)_ | ||
| 104 | |||
| 105 | AUTHOR | ||
| 106 | ------ | ||
| 107 | [verse] | ||
| 108 | -- | ||
| 109 | *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. | ||
| 110 | *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. | ||
| 111 | -- | ||
| 112 | REPORTING BUGS | ||
| 113 | -------------- | ||
| 114 | Report bugs to <linux-trace-devel@vger.kernel.org> | ||
| 115 | |||
| 116 | LICENSE | ||
| 117 | ------- | ||
| 118 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 | ||
| 119 | |||
| 120 | RESOURCES | ||
| 121 | --------- | ||
| 122 | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git | ||
diff --git a/tools/lib/traceevent/Documentation/libtraceevent-field_print.txt b/tools/lib/traceevent/Documentation/libtraceevent-field_print.txt new file mode 100644 index 000000000000..9a9df98ac44d --- /dev/null +++ b/tools/lib/traceevent/Documentation/libtraceevent-field_print.txt | |||
| @@ -0,0 +1,126 @@ | |||
| 1 | libtraceevent(3) | ||
| 2 | ================ | ||
| 3 | |||
| 4 | NAME | ||
| 5 | ---- | ||
| 6 | tep_print_field, tep_print_fields, tep_print_num_field, tep_print_func_field - | ||
| 7 | Print the field content. | ||
| 8 | |||
| 9 | SYNOPSIS | ||
| 10 | -------- | ||
| 11 | [verse] | ||
| 12 | -- | ||
| 13 | *#include <event-parse.h>* | ||
| 14 | *#include <trace-seq.h>* | ||
| 15 | |||
| 16 | void *tep_print_field*(struct trace_seq pass:[*]_s_, void pass:[*]_data_, struct tep_format_field pass:[*]_field_); | ||
| 17 | void *tep_print_fields*(struct trace_seq pass:[*]_s_, void pass:[*]_data_, int _size_, struct tep_event pass:[*]_event_); | ||
| 18 | int *tep_print_num_field*(struct trace_seq pass:[*]_s_, const char pass:[*]_fmt_, struct tep_event pass:[*]_event_, const char pass:[*]_name_, struct tep_record pass:[*]_record_, int _err_); | ||
| 19 | int *tep_print_func_field*(struct trace_seq pass:[*]_s_, const char pass:[*]_fmt_, struct tep_event pass:[*]_event_, const char pass:[*]_name_, struct tep_record pass:[*]_record_, int _err_); | ||
| 20 | -- | ||
| 21 | |||
| 22 | DESCRIPTION | ||
| 23 | ----------- | ||
| 24 | These functions print recorded field's data, according to the field's type. | ||
| 25 | |||
| 26 | The _tep_print_field()_ function extracts from the recorded raw _data_ value of | ||
| 27 | the _field_ and prints it into _s_, according to the field type. | ||
| 28 | |||
| 29 | The _tep_print_fields()_ prints each field name followed by the record's field | ||
| 30 | value according to the field's type: | ||
| 31 | [verse] | ||
| 32 | -- | ||
| 33 | "field1_name=field1_value field2_name=field2_value ..." | ||
| 34 | -- | ||
| 35 | It iterates all fields of the _event_, and calls _tep_print_field()_ for each of | ||
| 36 | them. | ||
| 37 | |||
| 38 | The _tep_print_num_field()_ function prints a numeric field with given format | ||
| 39 | string. A search is performed in the _event_ for a field with _name_. If such | ||
| 40 | field is found, its value is extracted from the _record_ and is printed in the | ||
| 41 | _s_, according to the given format string _fmt_. If the argument _err_ is | ||
| 42 | non-zero, and an error occures - it is printed in the _s_. | ||
| 43 | |||
| 44 | The _tep_print_func_field()_ function prints a function field with given format | ||
| 45 | string. A search is performed in the _event_ for a field with _name_. If such | ||
| 46 | field is found, its value is extracted from the _record_. The value is assumed | ||
| 47 | to be a function address, and a search is perform to find the name of this | ||
| 48 | function. The function name (if found) and its address are printed in the _s_, | ||
| 49 | according to the given format string _fmt_. If the argument _err_ is non-zero, | ||
| 50 | and an error occures - it is printed in _s_. | ||
| 51 | |||
| 52 | RETURN VALUE | ||
| 53 | ------------ | ||
| 54 | The _tep_print_num_field()_ and _tep_print_func_field()_ functions return 1 | ||
| 55 | on success, -1 in case of an error or 0 if the print buffer _s_ is full. | ||
| 56 | |||
| 57 | EXAMPLE | ||
| 58 | ------- | ||
| 59 | [source,c] | ||
| 60 | -- | ||
| 61 | #include <event-parse.h> | ||
| 62 | #include <trace-seq.h> | ||
| 63 | ... | ||
| 64 | struct tep_handle *tep = tep_alloc(); | ||
| 65 | ... | ||
| 66 | struct trace_seq seq; | ||
| 67 | trace_seq_init(&seq); | ||
| 68 | struct tep_event *event = tep_find_event_by_name(tep, "timer", "hrtimer_start"); | ||
| 69 | ... | ||
| 70 | void process_record(struct tep_record *record) | ||
| 71 | { | ||
| 72 | struct tep_format_field *field_pid = tep_find_common_field(event, "common_pid"); | ||
| 73 | |||
| 74 | trace_seq_reset(&seq); | ||
| 75 | |||
| 76 | /* Print the value of "common_pid" */ | ||
| 77 | tep_print_field(&seq, record->data, field_pid); | ||
| 78 | |||
| 79 | /* Print all fields of the "hrtimer_start" event */ | ||
| 80 | tep_print_fields(&seq, record->data, record->size, event); | ||
| 81 | |||
| 82 | /* Print the value of "expires" field with custom format string */ | ||
| 83 | tep_print_num_field(&seq, " timer expires in %llu ", event, "expires", record, 0); | ||
| 84 | |||
| 85 | /* Print the address and the name of "function" field with custom format string */ | ||
| 86 | tep_print_func_field(&seq, " timer function is %s ", event, "function", record, 0); | ||
| 87 | } | ||
| 88 | ... | ||
| 89 | -- | ||
| 90 | |||
| 91 | FILES | ||
| 92 | ----- | ||
| 93 | [verse] | ||
| 94 | -- | ||
| 95 | *event-parse.h* | ||
| 96 | Header file to include in order to have access to the library APIs. | ||
| 97 | *trace-seq.h* | ||
| 98 | Header file to include in order to have access to trace sequences related APIs. | ||
| 99 | Trace sequences are used to allow a function to call several other functions | ||
| 100 | to create a string of data to use. | ||
| 101 | *-ltraceevent* | ||
| 102 | Linker switch to add when building a program that uses the library. | ||
| 103 | -- | ||
| 104 | |||
| 105 | SEE ALSO | ||
| 106 | -------- | ||
| 107 | _libtraceevent(3)_, _trace-cmd(1)_ | ||
| 108 | |||
| 109 | AUTHOR | ||
| 110 | ------ | ||
| 111 | [verse] | ||
| 112 | -- | ||
| 113 | *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. | ||
| 114 | *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. | ||
| 115 | -- | ||
| 116 | REPORTING BUGS | ||
| 117 | -------------- | ||
| 118 | Report bugs to <linux-trace-devel@vger.kernel.org> | ||
| 119 | |||
| 120 | LICENSE | ||
| 121 | ------- | ||
| 122 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 | ||
| 123 | |||
| 124 | RESOURCES | ||
| 125 | --------- | ||
| 126 | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git | ||
diff --git a/tools/lib/traceevent/Documentation/libtraceevent-field_read.txt b/tools/lib/traceevent/Documentation/libtraceevent-field_read.txt new file mode 100644 index 000000000000..64e9e25d3fd9 --- /dev/null +++ b/tools/lib/traceevent/Documentation/libtraceevent-field_read.txt | |||
| @@ -0,0 +1,81 @@ | |||
| 1 | libtraceevent(3) | ||
| 2 | ================ | ||
| 3 | |||
| 4 | NAME | ||
| 5 | ---- | ||
| 6 | tep_read_number_field - Reads a number from raw data. | ||
| 7 | |||
| 8 | SYNOPSIS | ||
| 9 | -------- | ||
| 10 | [verse] | ||
| 11 | -- | ||
| 12 | *#include <event-parse.h>* | ||
| 13 | |||
| 14 | int *tep_read_number_field*(struct tep_format_field pass:[*]_field_, const void pass:[*]_data_, unsigned long long pass:[*]_value_); | ||
| 15 | -- | ||
| 16 | |||
| 17 | DESCRIPTION | ||
| 18 | ----------- | ||
| 19 | The _tep_read_number_field()_ function reads the value of the _field_ from the | ||
| 20 | raw _data_ and stores it in the _value_. The function sets the _value_ according | ||
| 21 | to the endianness of the raw data and the current machine and stores it in | ||
| 22 | _value_. | ||
| 23 | |||
| 24 | RETURN VALUE | ||
| 25 | ------------ | ||
| 26 | The _tep_read_number_field()_ function retunrs 0 in case of success, or -1 in | ||
| 27 | case of an error. | ||
| 28 | |||
| 29 | EXAMPLE | ||
| 30 | ------- | ||
| 31 | [source,c] | ||
| 32 | -- | ||
| 33 | #include <event-parse.h> | ||
| 34 | ... | ||
| 35 | struct tep_handle *tep = tep_alloc(); | ||
| 36 | ... | ||
| 37 | struct tep_event *event = tep_find_event_by_name(tep, "timer", "hrtimer_start"); | ||
| 38 | ... | ||
| 39 | void process_record(struct tep_record *record) | ||
| 40 | { | ||
| 41 | unsigned long long pid; | ||
| 42 | struct tep_format_field *field_pid = tep_find_common_field(event, "common_pid"); | ||
| 43 | |||
| 44 | if (tep_read_number_field(field_pid, record->data, &pid) != 0) { | ||
| 45 | /* Failed to get "common_pid" value */ | ||
| 46 | } | ||
| 47 | } | ||
| 48 | ... | ||
| 49 | -- | ||
| 50 | FILES | ||
| 51 | ----- | ||
| 52 | [verse] | ||
| 53 | -- | ||
| 54 | *event-parse.h* | ||
| 55 | Header file to include in order to have access to the library APIs. | ||
| 56 | *-ltraceevent* | ||
| 57 | Linker switch to add when building a program that uses the library. | ||
| 58 | -- | ||
| 59 | |||
| 60 | SEE ALSO | ||
| 61 | -------- | ||
| 62 | _libtraceevent(3)_, _trace-cmd(1)_ | ||
| 63 | |||
| 64 | AUTHOR | ||
| 65 | ------ | ||
| 66 | [verse] | ||
| 67 | -- | ||
| 68 | *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. | ||
| 69 | *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. | ||
| 70 | -- | ||
| 71 | REPORTING BUGS | ||
| 72 | -------------- | ||
| 73 | Report bugs to <linux-trace-devel@vger.kernel.org> | ||
| 74 | |||
| 75 | LICENSE | ||
| 76 | ------- | ||
| 77 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 | ||
| 78 | |||
| 79 | RESOURCES | ||
| 80 | --------- | ||
| 81 | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git | ||
diff --git a/tools/lib/traceevent/Documentation/libtraceevent-fields.txt b/tools/lib/traceevent/Documentation/libtraceevent-fields.txt new file mode 100644 index 000000000000..1ccb531d5114 --- /dev/null +++ b/tools/lib/traceevent/Documentation/libtraceevent-fields.txt | |||
| @@ -0,0 +1,105 @@ | |||
| 1 | libtraceevent(3) | ||
| 2 | ================ | ||
| 3 | |||
| 4 | NAME | ||
| 5 | ---- | ||
| 6 | tep_event_common_fields, tep_event_fields - Get a list of fields for an event. | ||
| 7 | |||
| 8 | SYNOPSIS | ||
| 9 | -------- | ||
| 10 | [verse] | ||
| 11 | -- | ||
| 12 | *#include <event-parse.h>* | ||
| 13 | |||
| 14 | struct tep_format_field pass:[*]pass:[*]*tep_event_common_fields*(struct tep_event pass:[*]_event_); | ||
| 15 | struct tep_format_field pass:[*]pass:[*]*tep_event_fields*(struct tep_event pass:[*]_event_); | ||
| 16 | -- | ||
| 17 | |||
| 18 | DESCRIPTION | ||
| 19 | ----------- | ||
| 20 | The _tep_event_common_fields()_ function returns an array of pointers to common | ||
| 21 | fields for the _event_. The array is allocated in the function and must be freed | ||
| 22 | by free(). The last element of the array is NULL. | ||
| 23 | |||
| 24 | The _tep_event_fields()_ function returns an array of pointers to event specific | ||
| 25 | fields for the _event_. The array is allocated in the function and must be freed | ||
| 26 | by free(). The last element of the array is NULL. | ||
| 27 | |||
| 28 | RETURN VALUE | ||
| 29 | ------------ | ||
| 30 | Both _tep_event_common_fields()_ and _tep_event_fields()_ functions return | ||
| 31 | an array of pointers to tep_format_field structures in case of success, or | ||
| 32 | NULL in case of an error. | ||
| 33 | |||
| 34 | EXAMPLE | ||
| 35 | ------- | ||
| 36 | [source,c] | ||
| 37 | -- | ||
| 38 | #include <event-parse.h> | ||
| 39 | ... | ||
| 40 | struct tep_handle *tep = tep_alloc(); | ||
| 41 | ... | ||
| 42 | int i; | ||
| 43 | struct tep_format_field **fields; | ||
| 44 | struct tep_event *event = tep_find_event_by_name(tep, "kvm", "kvm_exit"); | ||
| 45 | if (event != NULL) { | ||
| 46 | fields = tep_event_common_fields(event); | ||
| 47 | if (fields != NULL) { | ||
| 48 | i = 0; | ||
| 49 | while (fields[i]) { | ||
| 50 | /* | ||
| 51 | walk through the list of the common fields | ||
| 52 | of the kvm_exit event | ||
| 53 | */ | ||
| 54 | i++; | ||
| 55 | } | ||
| 56 | free(fields); | ||
| 57 | } | ||
| 58 | fields = tep_event_fields(event); | ||
| 59 | if (fields != NULL) { | ||
| 60 | i = 0; | ||
| 61 | while (fields[i]) { | ||
| 62 | /* | ||
| 63 | walk through the list of the event specific | ||
| 64 | fields of the kvm_exit event | ||
| 65 | */ | ||
| 66 | i++; | ||
| 67 | } | ||
| 68 | free(fields); | ||
| 69 | } | ||
| 70 | } | ||
| 71 | ... | ||
| 72 | -- | ||
| 73 | |||
| 74 | FILES | ||
| 75 | ----- | ||
| 76 | [verse] | ||
| 77 | -- | ||
| 78 | *event-parse.h* | ||
| 79 | Header file to include in order to have access to the library APIs. | ||
| 80 | *-ltraceevent* | ||
| 81 | Linker switch to add when building a program that uses the library. | ||
| 82 | -- | ||
| 83 | |||
| 84 | SEE ALSO | ||
| 85 | -------- | ||
| 86 | _libtraceevent(3)_, _trace-cmd(1)_ | ||
| 87 | |||
| 88 | AUTHOR | ||
| 89 | ------ | ||
| 90 | [verse] | ||
| 91 | -- | ||
| 92 | *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. | ||
| 93 | *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. | ||
| 94 | -- | ||
| 95 | REPORTING BUGS | ||
| 96 | -------------- | ||
| 97 | Report bugs to <linux-trace-devel@vger.kernel.org> | ||
| 98 | |||
| 99 | LICENSE | ||
| 100 | ------- | ||
| 101 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 | ||
| 102 | |||
| 103 | RESOURCES | ||
| 104 | --------- | ||
| 105 | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git | ||
diff --git a/tools/lib/traceevent/Documentation/libtraceevent-file_endian.txt b/tools/lib/traceevent/Documentation/libtraceevent-file_endian.txt new file mode 100644 index 000000000000..f401ad311047 --- /dev/null +++ b/tools/lib/traceevent/Documentation/libtraceevent-file_endian.txt | |||
| @@ -0,0 +1,91 @@ | |||
| 1 | libtraceevent(3) | ||
| 2 | ================ | ||
| 3 | |||
| 4 | NAME | ||
| 5 | ---- | ||
| 6 | tep_is_file_bigendian, tep_set_file_bigendian - Get / set the endianness of the | ||
| 7 | raw data being accessed by the tep handler. | ||
| 8 | |||
| 9 | SYNOPSIS | ||
| 10 | -------- | ||
| 11 | [verse] | ||
| 12 | -- | ||
| 13 | *#include <event-parse.h>* | ||
| 14 | |||
| 15 | enum *tep_endian* { | ||
| 16 | TEP_LITTLE_ENDIAN = 0, | ||
| 17 | TEP_BIG_ENDIAN | ||
| 18 | }; | ||
| 19 | |||
| 20 | bool *tep_is_file_bigendian*(struct tep_handle pass:[*]_tep_); | ||
| 21 | void *tep_set_file_bigendian*(struct tep_handle pass:[*]_tep_, enum tep_endian _endian_); | ||
| 22 | |||
| 23 | -- | ||
| 24 | DESCRIPTION | ||
| 25 | ----------- | ||
| 26 | The _tep_is_file_bigendian()_ function gets the endianness of the raw data, | ||
| 27 | being accessed by the tep handler. The _tep_ argument is trace event parser | ||
| 28 | context. | ||
| 29 | |||
| 30 | The _tep_set_file_bigendian()_ function sets the endianness of raw data being | ||
| 31 | accessed by the tep handler. The _tep_ argument is trace event parser context. | ||
| 32 | [verse] | ||
| 33 | -- | ||
| 34 | The _endian_ argument is the endianness: | ||
| 35 | _TEP_LITTLE_ENDIAN_ - the raw data is in little endian format, | ||
| 36 | _TEP_BIG_ENDIAN_ - the raw data is in big endian format. | ||
| 37 | -- | ||
| 38 | RETURN VALUE | ||
| 39 | ------------ | ||
| 40 | The _tep_is_file_bigendian()_ function returns true if the data is in bigendian | ||
| 41 | format, false otherwise. | ||
| 42 | |||
| 43 | EXAMPLE | ||
| 44 | ------- | ||
| 45 | [source,c] | ||
| 46 | -- | ||
| 47 | #include <event-parse.h> | ||
| 48 | ... | ||
| 49 | struct tep_handle *tep = tep_alloc(); | ||
| 50 | ... | ||
| 51 | tep_set_file_bigendian(tep, TEP_LITTLE_ENDIAN); | ||
| 52 | ... | ||
| 53 | if (tep_is_file_bigendian(tep)) { | ||
| 54 | /* The raw data is in big endian */ | ||
| 55 | } else { | ||
| 56 | /* The raw data is in little endian */ | ||
| 57 | } | ||
| 58 | -- | ||
| 59 | |||
| 60 | FILES | ||
| 61 | ----- | ||
| 62 | [verse] | ||
| 63 | -- | ||
| 64 | *event-parse.h* | ||
| 65 | Header file to include in order to have access to the library APIs. | ||
| 66 | *-ltraceevent* | ||
| 67 | Linker switch to add when building a program that uses the library. | ||
| 68 | -- | ||
| 69 | |||
| 70 | SEE ALSO | ||
| 71 | -------- | ||
| 72 | _libtraceevent(3)_, _trace-cmd(1)_ | ||
| 73 | |||
| 74 | AUTHOR | ||
| 75 | ------ | ||
| 76 | [verse] | ||
| 77 | -- | ||
| 78 | *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. | ||
| 79 | *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. | ||
| 80 | -- | ||
| 81 | REPORTING BUGS | ||
| 82 | -------------- | ||
| 83 | Report bugs to <linux-trace-devel@vger.kernel.org> | ||
| 84 | |||
| 85 | LICENSE | ||
| 86 | ------- | ||
| 87 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 | ||
| 88 | |||
| 89 | RESOURCES | ||
| 90 | --------- | ||
| 91 | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git | ||
diff --git a/tools/lib/traceevent/Documentation/libtraceevent-filter.txt b/tools/lib/traceevent/Documentation/libtraceevent-filter.txt new file mode 100644 index 000000000000..4a9962d8cb59 --- /dev/null +++ b/tools/lib/traceevent/Documentation/libtraceevent-filter.txt | |||
| @@ -0,0 +1,209 @@ | |||
| 1 | libtraceevent(3) | ||
| 2 | ================ | ||
| 3 | |||
| 4 | NAME | ||
| 5 | ---- | ||
| 6 | tep_filter_alloc, tep_filter_free, tep_filter_reset, tep_filter_make_string, | ||
| 7 | tep_filter_copy, tep_filter_compare, tep_filter_match, tep_event_filtered, | ||
| 8 | tep_filter_remove_event, tep_filter_strerror, tep_filter_add_filter_str - | ||
| 9 | Event filter related APIs. | ||
| 10 | |||
| 11 | SYNOPSIS | ||
| 12 | -------- | ||
| 13 | [verse] | ||
| 14 | -- | ||
| 15 | *#include <event-parse.h>* | ||
| 16 | |||
| 17 | struct tep_event_filter pass:[*]*tep_filter_alloc*(struct tep_handle pass:[*]_tep_); | ||
| 18 | void *tep_filter_free*(struct tep_event_filter pass:[*]_filter_); | ||
| 19 | void *tep_filter_reset*(struct tep_event_filter pass:[*]_filter_); | ||
| 20 | enum tep_errno *tep_filter_add_filter_str*(struct tep_event_filter pass:[*]_filter_, const char pass:[*]_filter_str_); | ||
| 21 | int *tep_event_filtered*(struct tep_event_filter pass:[*]_filter_, int _event_id_); | ||
| 22 | int *tep_filter_remove_event*(struct tep_event_filter pass:[*]_filter_, int _event_id_); | ||
| 23 | enum tep_errno *tep_filter_match*(struct tep_event_filter pass:[*]_filter_, struct tep_record pass:[*]_record_); | ||
| 24 | int *tep_filter_copy*(struct tep_event_filter pass:[*]_dest_, struct tep_event_filter pass:[*]_source_); | ||
| 25 | int *tep_filter_compare*(struct tep_event_filter pass:[*]_filter1_, struct tep_event_filter pass:[*]_filter2_); | ||
| 26 | char pass:[*]*tep_filter_make_string*(struct tep_event_filter pass:[*]_filter_, int _event_id_); | ||
| 27 | int *tep_filter_strerror*(struct tep_event_filter pass:[*]_filter_, enum tep_errno _err_, char pass:[*]buf, size_t _buflen_); | ||
| 28 | -- | ||
| 29 | |||
| 30 | DESCRIPTION | ||
| 31 | ----------- | ||
| 32 | Filters can be attached to traced events. They can be used to filter out various | ||
| 33 | events when outputting them. Each event can be filtered based on its parameters, | ||
| 34 | described in the event's format file. This set of functions can be used to | ||
| 35 | create, delete, modify and attach event filters. | ||
| 36 | |||
| 37 | The _tep_filter_alloc()_ function creates a new event filter. The _tep_ argument | ||
| 38 | is the trace event parser context. | ||
| 39 | |||
| 40 | The _tep_filter_free()_ function frees an event filter and all resources that it | ||
| 41 | had used. | ||
| 42 | |||
| 43 | The _tep_filter_reset()_ function removes all rules from an event filter and | ||
| 44 | resets it. | ||
| 45 | |||
| 46 | The _tep_filter_add_filter_str()_ function adds a new rule to the _filter_. The | ||
| 47 | _filter_str_ argument is the filter string, that contains the rule. | ||
| 48 | |||
| 49 | The _tep_event_filtered()_ function checks if the event with _event_id_ has | ||
| 50 | _filter_. | ||
| 51 | |||
| 52 | The _tep_filter_remove_event()_ function removes a _filter_ for an event with | ||
| 53 | _event_id_. | ||
| 54 | |||
| 55 | The _tep_filter_match()_ function tests if a _record_ matches given _filter_. | ||
| 56 | |||
| 57 | The _tep_filter_copy()_ function copies a _source_ filter into a _dest_ filter. | ||
| 58 | |||
| 59 | The _tep_filter_compare()_ function compares two filers - _filter1_ and _filter2_. | ||
| 60 | |||
| 61 | The _tep_filter_make_string()_ function constructs a string, displaying | ||
| 62 | the _filter_ contents for given _event_id_. | ||
| 63 | |||
| 64 | The _tep_filter_strerror()_ function copies the _filter_ error buffer into the | ||
| 65 | given _buf_ with the size _buflen_. If the error buffer is empty, in the _buf_ | ||
| 66 | is copied a string, describing the error _err_. | ||
| 67 | |||
| 68 | RETURN VALUE | ||
| 69 | ------------ | ||
| 70 | The _tep_filter_alloc()_ function returns a pointer to the newly created event | ||
| 71 | filter, or NULL in case of an error. | ||
| 72 | |||
| 73 | The _tep_filter_add_filter_str()_ function returns 0 if the rule was | ||
| 74 | successfully added or a negative error code. Use _tep_filter_strerror()_ to see | ||
| 75 | actual error message in case of an error. | ||
| 76 | |||
| 77 | The _tep_event_filtered()_ function returns 1 if the filter is found for given | ||
| 78 | event, or 0 otherwise. | ||
| 79 | |||
| 80 | The _tep_filter_remove_event()_ function returns 1 if the vent was removed, or | ||
| 81 | 0 if the event was not found. | ||
| 82 | |||
| 83 | The _tep_filter_match()_ function returns _tep_errno_, according to the result: | ||
| 84 | [verse] | ||
| 85 | -- | ||
| 86 | _pass:[TEP_ERRNO__FILTER_MATCH]_ - filter found for event, the record matches. | ||
| 87 | _pass:[TEP_ERRNO__FILTER_MISS]_ - filter found for event, the record does not match. | ||
| 88 | _pass:[TEP_ERRNO__FILTER_NOT_FOUND]_ - no filter found for record's event. | ||
| 89 | _pass:[TEP_ERRNO__NO_FILTER]_ - no rules in the filter. | ||
| 90 | -- | ||
| 91 | or any other _tep_errno_, if an error occurred during the test. | ||
| 92 | |||
| 93 | The _tep_filter_copy()_ function returns 0 on success or -1 if not all rules | ||
| 94 | were copied. | ||
| 95 | |||
| 96 | The _tep_filter_compare()_ function returns 1 if the two filters hold the same | ||
| 97 | content, or 0 if they do not. | ||
| 98 | |||
| 99 | The _tep_filter_make_string()_ function returns a string, which must be freed | ||
| 100 | with free(), or NULL in case of an error. | ||
| 101 | |||
| 102 | The _tep_filter_strerror()_ function returns 0 if message was filled | ||
| 103 | successfully, or -1 in case of an error. | ||
| 104 | |||
| 105 | EXAMPLE | ||
| 106 | ------- | ||
| 107 | [source,c] | ||
| 108 | -- | ||
| 109 | #include <event-parse.h> | ||
| 110 | ... | ||
| 111 | struct tep_handle *tep = tep_alloc(); | ||
| 112 | ... | ||
| 113 | char errstr[200]; | ||
| 114 | int ret; | ||
| 115 | |||
| 116 | struct tep_event_filter *filter = tep_filter_alloc(tep); | ||
| 117 | struct tep_event_filter *filter1 = tep_filter_alloc(tep); | ||
| 118 | ret = tep_filter_add_filter_str(filter, "sched/sched_wakeup:target_cpu==1"); | ||
| 119 | if(ret < 0) { | ||
| 120 | tep_filter_strerror(filter, ret, errstr, sizeof(errstr)); | ||
| 121 | /* Failed to add a new rule to the filter, the error string is in errstr */ | ||
| 122 | } | ||
| 123 | if (tep_filter_copy(filter1, filter) != 0) { | ||
| 124 | /* Failed to copy filter in filter1 */ | ||
| 125 | } | ||
| 126 | ... | ||
| 127 | if (tep_filter_compare(filter, filter1) != 1) { | ||
| 128 | /* Both filters are different */ | ||
| 129 | } | ||
| 130 | ... | ||
| 131 | void process_record(struct tep_handle *tep, struct tep_record *record) | ||
| 132 | { | ||
| 133 | struct tep_event *event; | ||
| 134 | char *fstring; | ||
| 135 | |||
| 136 | event = tep_find_event_by_record(tep, record); | ||
| 137 | |||
| 138 | if (tep_event_filtered(filter, event->id) == 1) { | ||
| 139 | /* The event has filter */ | ||
| 140 | fstring = tep_filter_make_string(filter, event->id); | ||
| 141 | if (fstring != NULL) { | ||
| 142 | /* The filter for the event is in fstring */ | ||
| 143 | free(fstring); | ||
| 144 | } | ||
| 145 | } | ||
| 146 | |||
| 147 | switch (tep_filter_match(filter, record)) { | ||
| 148 | case TEP_ERRNO__FILTER_MATCH: | ||
| 149 | /* The filter matches the record */ | ||
| 150 | break; | ||
| 151 | case TEP_ERRNO__FILTER_MISS: | ||
| 152 | /* The filter does not match the record */ | ||
| 153 | break; | ||
| 154 | case TEP_ERRNO__FILTER_NOT_FOUND: | ||
| 155 | /* No filter found for record's event */ | ||
| 156 | break; | ||
| 157 | case TEP_ERRNO__NO_FILTER: | ||
| 158 | /* There are no rules in the filter */ | ||
| 159 | break | ||
| 160 | default: | ||
| 161 | /* An error occurred during the test */ | ||
| 162 | break; | ||
| 163 | } | ||
| 164 | |||
| 165 | if (tep_filter_remove_event(filter, event->id) == 1) { | ||
| 166 | /* The event was removed from the filter */ | ||
| 167 | } | ||
| 168 | } | ||
| 169 | |||
| 170 | ... | ||
| 171 | tep_filter_reset(filter); | ||
| 172 | ... | ||
| 173 | tep_filter_free(filter); | ||
| 174 | tep_filter_free(filter1); | ||
| 175 | ... | ||
| 176 | -- | ||
| 177 | |||
| 178 | FILES | ||
| 179 | ----- | ||
| 180 | [verse] | ||
| 181 | -- | ||
| 182 | *event-parse.h* | ||
| 183 | Header file to include in order to have access to the library APIs. | ||
| 184 | *-ltraceevent* | ||
| 185 | Linker switch to add when building a program that uses the library. | ||
| 186 | -- | ||
| 187 | |||
| 188 | SEE ALSO | ||
| 189 | -------- | ||
| 190 | _libtraceevent(3)_, _trace-cmd(1)_ | ||
| 191 | |||
| 192 | AUTHOR | ||
| 193 | ------ | ||
| 194 | [verse] | ||
| 195 | -- | ||
| 196 | *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. | ||
| 197 | *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. | ||
| 198 | -- | ||
| 199 | REPORTING BUGS | ||
| 200 | -------------- | ||
| 201 | Report bugs to <linux-trace-devel@vger.kernel.org> | ||
| 202 | |||
| 203 | LICENSE | ||
| 204 | ------- | ||
| 205 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 | ||
| 206 | |||
| 207 | RESOURCES | ||
| 208 | --------- | ||
| 209 | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git | ||
diff --git a/tools/lib/traceevent/Documentation/libtraceevent-func_apis.txt b/tools/lib/traceevent/Documentation/libtraceevent-func_apis.txt new file mode 100644 index 000000000000..38bfea30a5f6 --- /dev/null +++ b/tools/lib/traceevent/Documentation/libtraceevent-func_apis.txt | |||
| @@ -0,0 +1,183 @@ | |||
| 1 | libtraceevent(3) | ||
| 2 | ================ | ||
| 3 | |||
| 4 | NAME | ||
| 5 | ---- | ||
| 6 | tep_find_function, tep_find_function_address, tep_set_function_resolver, | ||
| 7 | tep_reset_function_resolver, tep_register_function, tep_register_print_string - | ||
| 8 | function related tep APIs | ||
| 9 | |||
| 10 | SYNOPSIS | ||
| 11 | -------- | ||
| 12 | [verse] | ||
| 13 | -- | ||
| 14 | *#include <event-parse.h>* | ||
| 15 | |||
| 16 | typedef char pass:[*](*tep_func_resolver_t*)(void pass:[*]_priv_, unsigned long long pass:[*]_addrp_, char pass:[**]_modp_); | ||
| 17 | int *tep_set_function_resolver*(struct tep_handle pass:[*]_tep_, tep_func_resolver_t pass:[*]_func_, void pass:[*]_priv_); | ||
| 18 | void *tep_reset_function_resolver*(struct tep_handle pass:[*]_tep_); | ||
| 19 | const char pass:[*]*tep_find_function*(struct tep_handle pass:[*]_tep_, unsigned long long _addr_); | ||
| 20 | unsigned long long *tep_find_function_address*(struct tep_handle pass:[*]_tep_, unsigned long long _addr_); | ||
| 21 | int *tep_register_function*(struct tep_handle pass:[*]_tep_, char pass:[*]_name_, unsigned long long _addr_, char pass:[*]_mod_); | ||
| 22 | int *tep_register_print_string*(struct tep_handle pass:[*]_tep_, const char pass:[*]_fmt_, unsigned long long _addr_); | ||
| 23 | -- | ||
| 24 | |||
| 25 | DESCRIPTION | ||
| 26 | ----------- | ||
| 27 | Some tools may have already a way to resolve the kernel functions. These APIs | ||
| 28 | allow them to keep using it instead of duplicating all the entries inside. | ||
| 29 | |||
| 30 | The _tep_func_resolver_t_ type is the prototype of the alternative kernel | ||
| 31 | functions resolver. This function receives a pointer to its custom context | ||
| 32 | (set with the _tep_set_function_resolver()_ call ) and the address of a kernel | ||
| 33 | function, which has to be resolved. In case of success, it should return | ||
| 34 | the name of the function and its module (if any) in _modp_. | ||
| 35 | |||
| 36 | The _tep_set_function_resolver()_ function registers _func_ as an alternative | ||
| 37 | kernel functions resolver. The _tep_ argument is trace event parser context. | ||
| 38 | The _priv_ argument is a custom context of the _func_ function. The function | ||
| 39 | resolver is used by the APIs _tep_find_function()_, | ||
| 40 | _tep_find_function_address()_, and _tep_print_func_field()_ to resolve | ||
| 41 | a function address to a function name. | ||
| 42 | |||
| 43 | The _tep_reset_function_resolver()_ function resets the kernel functions | ||
| 44 | resolver to the default function. The _tep_ argument is trace event parser | ||
| 45 | context. | ||
| 46 | |||
| 47 | |||
| 48 | These APIs can be used to find function name and start address, by given | ||
| 49 | address. The given address does not have to be exact, it will select | ||
| 50 | the function that would contain it. | ||
| 51 | |||
| 52 | The _tep_find_function()_ function returns the function name, which contains the | ||
| 53 | given address _addr_. The _tep_ argument is the trace event parser context. | ||
| 54 | |||
| 55 | The _tep_find_function_address()_ function returns the function start address, | ||
| 56 | by given address _addr_. The _addr_ does not have to be exact, it will select | ||
| 57 | the function that would contain it. The _tep_ argument is the trace event | ||
| 58 | parser context. | ||
| 59 | |||
| 60 | The _tep_register_function()_ function registers a function name mapped to an | ||
| 61 | address and (optional) module. This mapping is used in case the function tracer | ||
| 62 | or events have "%pF" or "%pS" parameter in its format string. It is common to | ||
| 63 | pass in the kallsyms function names with their corresponding addresses with this | ||
| 64 | function. The _tep_ argument is the trace event parser context. The _name_ is | ||
| 65 | the name of the function, the string is copied internally. The _addr_ is | ||
| 66 | the start address of the function. The _mod_ is the kernel module | ||
| 67 | the function may be in (NULL for none). | ||
| 68 | |||
| 69 | The _tep_register_print_string()_ function registers a string by the address | ||
| 70 | it was stored in the kernel. Some strings internal to the kernel with static | ||
| 71 | address are passed to certain events. The "%s" in the event's format field | ||
| 72 | which has an address needs to know what string would be at that address. The | ||
| 73 | tep_register_print_string() supplies the parsing with the mapping between kernel | ||
| 74 | addresses and those strings. The _tep_ argument is the trace event parser | ||
| 75 | context. The _fmt_ is the string to register, it is copied internally. | ||
| 76 | The _addr_ is the address the string was located at. | ||
| 77 | |||
| 78 | |||
| 79 | RETURN VALUE | ||
| 80 | ------------ | ||
| 81 | The _tep_set_function_resolver()_ function returns 0 in case of success, or -1 | ||
| 82 | in case of an error. | ||
| 83 | |||
| 84 | The _tep_find_function()_ function returns the function name, or NULL in case | ||
| 85 | it cannot be found. | ||
| 86 | |||
| 87 | The _tep_find_function_address()_ function returns the function start address, | ||
| 88 | or 0 in case it cannot be found. | ||
| 89 | |||
| 90 | The _tep_register_function()_ function returns 0 in case of success. In case of | ||
| 91 | an error -1 is returned, and errno is set to the appropriate error number. | ||
| 92 | |||
| 93 | The _tep_register_print_string()_ function returns 0 in case of success. In case | ||
| 94 | of an error -1 is returned, and errno is set to the appropriate error number. | ||
| 95 | |||
| 96 | EXAMPLE | ||
| 97 | ------- | ||
| 98 | [source,c] | ||
| 99 | -- | ||
| 100 | #include <event-parse.h> | ||
| 101 | ... | ||
| 102 | struct tep_handle *tep = tep_alloc(); | ||
| 103 | ... | ||
| 104 | char *my_resolve_kernel_addr(void *context, | ||
| 105 | unsigned long long *addrp, char **modp) | ||
| 106 | { | ||
| 107 | struct db *function_database = context; | ||
| 108 | struct symbol *sym = sql_lookup(function_database, *addrp); | ||
| 109 | |||
| 110 | if (!sym) | ||
| 111 | return NULL; | ||
| 112 | |||
| 113 | *modp = sym->module_name; | ||
| 114 | return sym->name; | ||
| 115 | } | ||
| 116 | |||
| 117 | void show_function( unsigned long long addr) | ||
| 118 | { | ||
| 119 | unsigned long long fstart; | ||
| 120 | const char *fname; | ||
| 121 | |||
| 122 | if (tep_set_function_resolver(tep, my_resolve_kernel_addr, | ||
| 123 | function_database) != 0) { | ||
| 124 | /* failed to register my_resolve_kernel_addr */ | ||
| 125 | } | ||
| 126 | |||
| 127 | /* These APIs use my_resolve_kernel_addr() to resolve the addr */ | ||
| 128 | fname = tep_find_function(tep, addr); | ||
| 129 | fstart = tep_find_function_address(tep, addr); | ||
| 130 | |||
| 131 | /* | ||
| 132 | addr is in function named fname, starting at fstart address, | ||
| 133 | at offset (addr - fstart) | ||
| 134 | */ | ||
| 135 | |||
| 136 | tep_reset_function_resolver(tep); | ||
| 137 | |||
| 138 | } | ||
| 139 | ... | ||
| 140 | if (tep_register_function(tep, "kvm_exit", | ||
| 141 | (unsigned long long) 0x12345678, "kvm") != 0) { | ||
| 142 | /* Failed to register kvm_exit address mapping */ | ||
| 143 | } | ||
| 144 | ... | ||
| 145 | if (tep_register_print_string(tep, "print string", | ||
| 146 | (unsigned long long) 0x87654321, NULL) != 0) { | ||
| 147 | /* Failed to register "print string" address mapping */ | ||
| 148 | } | ||
| 149 | ... | ||
| 150 | -- | ||
| 151 | |||
| 152 | FILES | ||
| 153 | ----- | ||
| 154 | [verse] | ||
| 155 | -- | ||
| 156 | *event-parse.h* | ||
| 157 | Header file to include in order to have access to the library APIs. | ||
| 158 | *-ltraceevent* | ||
| 159 | Linker switch to add when building a program that uses the library. | ||
| 160 | -- | ||
| 161 | |||
| 162 | SEE ALSO | ||
| 163 | -------- | ||
| 164 | _libtraceevent(3)_, _trace-cmd(1)_ | ||
| 165 | |||
| 166 | AUTHOR | ||
| 167 | ------ | ||
| 168 | [verse] | ||
| 169 | -- | ||
| 170 | *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. | ||
| 171 | *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. | ||
| 172 | -- | ||
| 173 | REPORTING BUGS | ||
| 174 | -------------- | ||
| 175 | Report bugs to <linux-trace-devel@vger.kernel.org> | ||
| 176 | |||
| 177 | LICENSE | ||
| 178 | ------- | ||
| 179 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 | ||
| 180 | |||
| 181 | RESOURCES | ||
| 182 | --------- | ||
| 183 | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git | ||
diff --git a/tools/lib/traceevent/Documentation/libtraceevent-func_find.txt b/tools/lib/traceevent/Documentation/libtraceevent-func_find.txt new file mode 100644 index 000000000000..04840e244445 --- /dev/null +++ b/tools/lib/traceevent/Documentation/libtraceevent-func_find.txt | |||
| @@ -0,0 +1,88 @@ | |||
| 1 | libtraceevent(3) | ||
| 2 | ================ | ||
| 3 | |||
| 4 | NAME | ||
| 5 | ---- | ||
| 6 | tep_find_function,tep_find_function_address - Find function name / start address. | ||
| 7 | |||
| 8 | SYNOPSIS | ||
| 9 | -------- | ||
| 10 | [verse] | ||
| 11 | -- | ||
| 12 | *#include <event-parse.h>* | ||
| 13 | |||
| 14 | const char pass:[*]*tep_find_function*(struct tep_handle pass:[*]_tep_, unsigned long long _addr_); | ||
| 15 | unsigned long long *tep_find_function_address*(struct tep_handle pass:[*]_tep_, unsigned long long _addr_); | ||
| 16 | -- | ||
| 17 | |||
| 18 | DESCRIPTION | ||
| 19 | ----------- | ||
| 20 | These functions can be used to find function name and start address, by given | ||
| 21 | address. The given address does not have to be exact, it will select the function | ||
| 22 | that would contain it. | ||
| 23 | |||
| 24 | The _tep_find_function()_ function returns the function name, which contains the | ||
| 25 | given address _addr_. The _tep_ argument is the trace event parser context. | ||
| 26 | |||
| 27 | The _tep_find_function_address()_ function returns the function start address, | ||
| 28 | by given address _addr_. The _addr_ does not have to be exact, it will select the | ||
| 29 | function that would contain it. The _tep_ argument is the trace event parser context. | ||
| 30 | |||
| 31 | RETURN VALUE | ||
| 32 | ------------ | ||
| 33 | The _tep_find_function()_ function returns the function name, or NULL in case | ||
| 34 | it cannot be found. | ||
| 35 | |||
| 36 | The _tep_find_function_address()_ function returns the function start address, | ||
| 37 | or 0 in case it cannot be found. | ||
| 38 | |||
| 39 | EXAMPLE | ||
| 40 | ------- | ||
| 41 | [source,c] | ||
| 42 | -- | ||
| 43 | #include <event-parse.h> | ||
| 44 | ... | ||
| 45 | struct tep_handle *tep = tep_alloc(); | ||
| 46 | ... | ||
| 47 | void show_function( unsigned long long addr) | ||
| 48 | { | ||
| 49 | const char *fname = tep_find_function(tep, addr); | ||
| 50 | unsigned long long fstart = tep_find_function_address(tep, addr); | ||
| 51 | |||
| 52 | /* addr is in function named fname, starting at fstart address, at offset (addr - fstart) */ | ||
| 53 | } | ||
| 54 | ... | ||
| 55 | -- | ||
| 56 | |||
| 57 | FILES | ||
| 58 | ----- | ||
| 59 | [verse] | ||
| 60 | -- | ||
| 61 | *event-parse.h* | ||
| 62 | Header file to include in order to have access to the library APIs. | ||
| 63 | *-ltraceevent* | ||
| 64 | Linker switch to add when building a program that uses the library. | ||
| 65 | -- | ||
| 66 | |||
| 67 | SEE ALSO | ||
| 68 | -------- | ||
| 69 | _libtraceevent(3)_, _trace-cmd(1)_ | ||
| 70 | |||
| 71 | AUTHOR | ||
| 72 | ------ | ||
| 73 | [verse] | ||
| 74 | -- | ||
| 75 | *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. | ||
| 76 | *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. | ||
| 77 | -- | ||
| 78 | REPORTING BUGS | ||
| 79 | -------------- | ||
| 80 | Report bugs to <linux-trace-devel@vger.kernel.org> | ||
| 81 | |||
| 82 | LICENSE | ||
| 83 | ------- | ||
| 84 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 | ||
| 85 | |||
| 86 | RESOURCES | ||
| 87 | --------- | ||
| 88 | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git | ||
diff --git a/tools/lib/traceevent/Documentation/libtraceevent-handle.txt b/tools/lib/traceevent/Documentation/libtraceevent-handle.txt new file mode 100644 index 000000000000..8d568316847d --- /dev/null +++ b/tools/lib/traceevent/Documentation/libtraceevent-handle.txt | |||
| @@ -0,0 +1,101 @@ | |||
| 1 | libtraceevent(3) | ||
| 2 | ================ | ||
| 3 | |||
| 4 | NAME | ||
| 5 | ---- | ||
| 6 | tep_alloc, tep_free,tep_ref, tep_unref,tep_ref_get - Create, destroy, manage | ||
| 7 | references of trace event parser context. | ||
| 8 | |||
| 9 | SYNOPSIS | ||
| 10 | -------- | ||
| 11 | [verse] | ||
| 12 | -- | ||
| 13 | *#include <event-parse.h>* | ||
| 14 | |||
| 15 | struct tep_handle pass:[*]*tep_alloc*(void); | ||
| 16 | void *tep_free*(struct tep_handle pass:[*]_tep_); | ||
| 17 | void *tep_ref*(struct tep_handle pass:[*]_tep_); | ||
| 18 | void *tep_unref*(struct tep_handle pass:[*]_tep_); | ||
| 19 | int *tep_ref_get*(struct tep_handle pass:[*]_tep_); | ||
| 20 | -- | ||
| 21 | |||
| 22 | DESCRIPTION | ||
| 23 | ----------- | ||
| 24 | These are the main functions to create and destroy tep_handle - the main | ||
| 25 | structure, representing the trace event parser context. This context is used as | ||
| 26 | the input parameter of most library APIs. | ||
| 27 | |||
| 28 | The _tep_alloc()_ function allocates and initializes the tep context. | ||
| 29 | |||
| 30 | The _tep_free()_ function will decrement the reference of the _tep_ handler. | ||
| 31 | When there is no more references, then it will free the handler, as well | ||
| 32 | as clean up all its resources that it had used. The argument _tep_ is | ||
| 33 | the pointer to the trace event parser context. | ||
| 34 | |||
| 35 | The _tep_ref()_ function adds a reference to the _tep_ handler. | ||
| 36 | |||
| 37 | The _tep_unref()_ function removes a reference from the _tep_ handler. When | ||
| 38 | the last reference is removed, the _tep_ is destroyed, and all resources that | ||
| 39 | it had used are cleaned up. | ||
| 40 | |||
| 41 | The _tep_ref_get()_ functions gets the current references of the _tep_ handler. | ||
| 42 | |||
| 43 | RETURN VALUE | ||
| 44 | ------------ | ||
| 45 | _tep_alloc()_ returns a pointer to a newly created tep_handle structure. | ||
| 46 | NULL is returned in case there is not enough free memory to allocate it. | ||
| 47 | |||
| 48 | _tep_ref_get()_ returns the current references of _tep_. | ||
| 49 | If _tep_ is NULL, 0 is returned. | ||
| 50 | |||
| 51 | EXAMPLE | ||
| 52 | ------- | ||
| 53 | [source,c] | ||
| 54 | -- | ||
| 55 | #include <event-parse.h> | ||
| 56 | |||
| 57 | ... | ||
| 58 | struct tep_handle *tep = tep_alloc(); | ||
| 59 | ... | ||
| 60 | int ref = tep_ref_get(tep); | ||
| 61 | tep_ref(tep); | ||
| 62 | if ( (ref+1) != tep_ref_get(tep)) { | ||
| 63 | /* Something wrong happened, the counter is not incremented by 1 */ | ||
| 64 | } | ||
| 65 | tep_unref(tep); | ||
| 66 | ... | ||
| 67 | tep_free(tep); | ||
| 68 | ... | ||
| 69 | -- | ||
| 70 | FILES | ||
| 71 | ----- | ||
| 72 | [verse] | ||
| 73 | -- | ||
| 74 | *event-parse.h* | ||
| 75 | Header file to include in order to have access to the library APIs. | ||
| 76 | *-ltraceevent* | ||
| 77 | Linker switch to add when building a program that uses the library. | ||
| 78 | -- | ||
| 79 | |||
| 80 | SEE ALSO | ||
| 81 | -------- | ||
| 82 | _libtraceevent(3)_, _trace-cmd(1)_ | ||
| 83 | |||
| 84 | AUTHOR | ||
| 85 | ------ | ||
| 86 | [verse] | ||
| 87 | -- | ||
| 88 | *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. | ||
| 89 | *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. | ||
| 90 | -- | ||
| 91 | REPORTING BUGS | ||
| 92 | -------------- | ||
| 93 | Report bugs to <linux-trace-devel@vger.kernel.org> | ||
| 94 | |||
| 95 | LICENSE | ||
| 96 | ------- | ||
| 97 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 | ||
| 98 | |||
| 99 | RESOURCES | ||
| 100 | --------- | ||
| 101 | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git | ||
diff --git a/tools/lib/traceevent/Documentation/libtraceevent-header_page.txt b/tools/lib/traceevent/Documentation/libtraceevent-header_page.txt new file mode 100644 index 000000000000..615d117dc39f --- /dev/null +++ b/tools/lib/traceevent/Documentation/libtraceevent-header_page.txt | |||
| @@ -0,0 +1,102 @@ | |||
| 1 | libtraceevent(3) | ||
| 2 | ================ | ||
| 3 | |||
| 4 | NAME | ||
| 5 | ---- | ||
| 6 | tep_get_header_page_size, tep_get_header_timestamp_size, tep_is_old_format - | ||
| 7 | Get the data stored in the header page, in kernel context. | ||
| 8 | |||
| 9 | SYNOPSIS | ||
| 10 | -------- | ||
| 11 | [verse] | ||
| 12 | -- | ||
| 13 | *#include <event-parse.h>* | ||
| 14 | |||
| 15 | int *tep_get_header_page_size*(struct tep_handle pass:[*]_tep_); | ||
| 16 | int *tep_get_header_timestamp_size*(struct tep_handle pass:[*]_tep_); | ||
| 17 | bool *tep_is_old_format*(struct tep_handle pass:[*]_tep_); | ||
| 18 | -- | ||
| 19 | DESCRIPTION | ||
| 20 | ----------- | ||
| 21 | These functions retrieve information from kernel context, stored in tracefs | ||
| 22 | events/header_page. Old kernels do not have header page info, so default values | ||
| 23 | from user space context are used. | ||
| 24 | |||
| 25 | The _tep_get_header_page_size()_ function returns the size of a long integer, | ||
| 26 | in kernel context. The _tep_ argument is trace event parser context. | ||
| 27 | This information is retrieved from tracefs events/header_page, "commit" field. | ||
| 28 | |||
| 29 | The _tep_get_header_timestamp_size()_ function returns the size of timestamps, | ||
| 30 | in kernel context. The _tep_ argument is trace event parser context. This | ||
| 31 | information is retrieved from tracefs events/header_page, "timestamp" field. | ||
| 32 | |||
| 33 | The _tep_is_old_format()_ function returns true if the kernel predates | ||
| 34 | the addition of events/header_page, otherwise it returns false. | ||
| 35 | |||
| 36 | RETURN VALUE | ||
| 37 | ------------ | ||
| 38 | The _tep_get_header_page_size()_ function returns the size of a long integer, | ||
| 39 | in bytes. | ||
| 40 | |||
| 41 | The _tep_get_header_timestamp_size()_ function returns the size of timestamps, | ||
| 42 | in bytes. | ||
| 43 | |||
| 44 | The _tep_is_old_format()_ function returns true, if an old kernel is used to | ||
| 45 | generate the tracing data, which has no event/header_page. If the kernel is new, | ||
| 46 | or _tep_ is NULL, false is returned. | ||
| 47 | |||
| 48 | EXAMPLE | ||
| 49 | ------- | ||
| 50 | [source,c] | ||
| 51 | -- | ||
| 52 | #include <event-parse.h> | ||
| 53 | ... | ||
| 54 | struct tep_handle *tep = tep_alloc(); | ||
| 55 | ... | ||
| 56 | int longsize; | ||
| 57 | int timesize; | ||
| 58 | bool old; | ||
| 59 | |||
| 60 | longsize = tep_get_header_page_size(tep); | ||
| 61 | timesize = tep_get_header_timestamp_size(tep); | ||
| 62 | old = tep_is_old_format(tep); | ||
| 63 | |||
| 64 | printf ("%s kernel is used to generate the tracing data.\n", | ||
| 65 | old?"Old":"New"); | ||
| 66 | printf("The size of a long integer is %d bytes.\n", longsize); | ||
| 67 | printf("The timestamps size is %d bytes.\n", timesize); | ||
| 68 | ... | ||
| 69 | -- | ||
| 70 | |||
| 71 | FILES | ||
| 72 | ----- | ||
| 73 | [verse] | ||
| 74 | -- | ||
| 75 | *event-parse.h* | ||
| 76 | Header file to include in order to have access to the library APIs. | ||
| 77 | *-ltraceevent* | ||
| 78 | Linker switch to add when building a program that uses the library. | ||
| 79 | -- | ||
| 80 | |||
| 81 | SEE ALSO | ||
| 82 | -------- | ||
| 83 | _libtraceevent(3)_, _trace-cmd(1)_ | ||
| 84 | |||
| 85 | AUTHOR | ||
| 86 | ------ | ||
| 87 | [verse] | ||
| 88 | -- | ||
| 89 | *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. | ||
| 90 | *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. | ||
| 91 | -- | ||
| 92 | REPORTING BUGS | ||
| 93 | -------------- | ||
| 94 | Report bugs to <linux-trace-devel@vger.kernel.org> | ||
| 95 | |||
| 96 | LICENSE | ||
| 97 | ------- | ||
| 98 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 | ||
| 99 | |||
| 100 | RESOURCES | ||
| 101 | --------- | ||
| 102 | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git | ||
diff --git a/tools/lib/traceevent/Documentation/libtraceevent-host_endian.txt b/tools/lib/traceevent/Documentation/libtraceevent-host_endian.txt new file mode 100644 index 000000000000..d5d375eb8d1e --- /dev/null +++ b/tools/lib/traceevent/Documentation/libtraceevent-host_endian.txt | |||
| @@ -0,0 +1,104 @@ | |||
| 1 | libtraceevent(3) | ||
| 2 | ================ | ||
| 3 | |||
| 4 | NAME | ||
| 5 | ---- | ||
| 6 | tep_is_bigendian, tep_is_local_bigendian, tep_set_local_bigendian - Get / set | ||
| 7 | the endianness of the local machine. | ||
| 8 | |||
| 9 | SYNOPSIS | ||
| 10 | -------- | ||
| 11 | [verse] | ||
| 12 | -- | ||
| 13 | *#include <event-parse.h>* | ||
| 14 | |||
| 15 | enum *tep_endian* { | ||
| 16 | TEP_LITTLE_ENDIAN = 0, | ||
| 17 | TEP_BIG_ENDIAN | ||
| 18 | }; | ||
| 19 | |||
| 20 | int *tep_is_bigendian*(void); | ||
| 21 | bool *tep_is_local_bigendian*(struct tep_handle pass:[*]_tep_); | ||
| 22 | void *tep_set_local_bigendian*(struct tep_handle pass:[*]_tep_, enum tep_endian _endian_); | ||
| 23 | -- | ||
| 24 | |||
| 25 | DESCRIPTION | ||
| 26 | ----------- | ||
| 27 | |||
| 28 | The _tep_is_bigendian()_ gets the endianness of the machine, executing | ||
| 29 | the function. | ||
| 30 | |||
| 31 | The _tep_is_local_bigendian()_ function gets the endianness of the local | ||
| 32 | machine, saved in the _tep_ handler. The _tep_ argument is the trace event | ||
| 33 | parser context. This API is a bit faster than _tep_is_bigendian()_, as it | ||
| 34 | returns cached endianness of the local machine instead of checking it each time. | ||
| 35 | |||
| 36 | The _tep_set_local_bigendian()_ function sets the endianness of the local | ||
| 37 | machine in the _tep_ handler. The _tep_ argument is trace event parser context. | ||
| 38 | The _endian_ argument is the endianness: | ||
| 39 | [verse] | ||
| 40 | -- | ||
| 41 | _TEP_LITTLE_ENDIAN_ - the machine is little endian, | ||
| 42 | _TEP_BIG_ENDIAN_ - the machine is big endian. | ||
| 43 | -- | ||
| 44 | |||
| 45 | RETURN VALUE | ||
| 46 | ------------ | ||
| 47 | The _tep_is_bigendian()_ function returns non zero if the endianness of the | ||
| 48 | machine, executing the code, is big endian and zero otherwise. | ||
| 49 | |||
| 50 | The _tep_is_local_bigendian()_ function returns true, if the endianness of the | ||
| 51 | local machine, saved in the _tep_ handler, is big endian, or false otherwise. | ||
| 52 | |||
| 53 | EXAMPLE | ||
| 54 | ------- | ||
| 55 | [source,c] | ||
| 56 | -- | ||
| 57 | #include <event-parse.h> | ||
| 58 | ... | ||
| 59 | struct tep_handle *tep = tep_alloc(); | ||
| 60 | ... | ||
| 61 | if (tep_is_bigendian()) | ||
| 62 | tep_set_local_bigendian(tep, TEP_BIG_ENDIAN); | ||
| 63 | else | ||
| 64 | tep_set_local_bigendian(tep, TEP_LITTLE_ENDIAN); | ||
| 65 | ... | ||
| 66 | if (tep_is_local_bigendian(tep)) | ||
| 67 | printf("This machine you are running on is bigendian\n"); | ||
| 68 | else | ||
| 69 | printf("This machine you are running on is little endian\n"); | ||
| 70 | |||
| 71 | -- | ||
| 72 | |||
| 73 | FILES | ||
| 74 | ----- | ||
| 75 | [verse] | ||
| 76 | -- | ||
| 77 | *event-parse.h* | ||
| 78 | Header file to include in order to have access to the library APIs. | ||
| 79 | *-ltraceevent* | ||
| 80 | Linker switch to add when building a program that uses the library. | ||
| 81 | -- | ||
| 82 | |||
| 83 | SEE ALSO | ||
| 84 | -------- | ||
| 85 | _libtraceevent(3)_, _trace-cmd(1)_ | ||
| 86 | |||
| 87 | AUTHOR | ||
| 88 | ------ | ||
| 89 | [verse] | ||
| 90 | -- | ||
| 91 | *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. | ||
| 92 | *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. | ||
| 93 | -- | ||
| 94 | REPORTING BUGS | ||
| 95 | -------------- | ||
| 96 | Report bugs to <linux-trace-devel@vger.kernel.org> | ||
| 97 | |||
| 98 | LICENSE | ||
| 99 | ------- | ||
| 100 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 | ||
| 101 | |||
| 102 | RESOURCES | ||
| 103 | --------- | ||
| 104 | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git | ||
diff --git a/tools/lib/traceevent/Documentation/libtraceevent-long_size.txt b/tools/lib/traceevent/Documentation/libtraceevent-long_size.txt new file mode 100644 index 000000000000..01d78ea2519a --- /dev/null +++ b/tools/lib/traceevent/Documentation/libtraceevent-long_size.txt | |||
| @@ -0,0 +1,78 @@ | |||
| 1 | libtraceevent(3) | ||
| 2 | ================ | ||
| 3 | |||
| 4 | NAME | ||
| 5 | ---- | ||
| 6 | tep_get_long_size, tep_set_long_size - Get / set the size of a long integer on | ||
| 7 | the machine, where the trace is generated, in bytes | ||
| 8 | |||
| 9 | SYNOPSIS | ||
| 10 | -------- | ||
| 11 | [verse] | ||
| 12 | -- | ||
| 13 | *#include <event-parse.h>* | ||
| 14 | |||
| 15 | int *tep_get_long_size*(strucqt tep_handle pass:[*]_tep_); | ||
| 16 | void *tep_set_long_size*(struct tep_handle pass:[*]_tep_, int _long_size_); | ||
| 17 | -- | ||
| 18 | |||
| 19 | DESCRIPTION | ||
| 20 | ----------- | ||
| 21 | The _tep_get_long_size()_ function returns the size of a long integer on the machine, | ||
| 22 | where the trace is generated. The _tep_ argument is trace event parser context. | ||
| 23 | |||
| 24 | The _tep_set_long_size()_ function sets the size of a long integer on the machine, | ||
| 25 | where the trace is generated. The _tep_ argument is trace event parser context. | ||
| 26 | The _long_size_ is the size of a long integer, in bytes. | ||
| 27 | |||
| 28 | RETURN VALUE | ||
| 29 | ------------ | ||
| 30 | The _tep_get_long_size()_ function returns the size of a long integer on the machine, | ||
| 31 | where the trace is generated, in bytes. | ||
| 32 | |||
| 33 | EXAMPLE | ||
| 34 | ------- | ||
| 35 | [source,c] | ||
| 36 | -- | ||
| 37 | #include <event-parse.h> | ||
| 38 | ... | ||
| 39 | struct tep_handle *tep = tep_alloc(); | ||
| 40 | ... | ||
| 41 | tep_set_long_size(tep, 4); | ||
| 42 | ... | ||
| 43 | int long_size = tep_get_long_size(tep); | ||
| 44 | ... | ||
| 45 | -- | ||
| 46 | |||
| 47 | FILES | ||
| 48 | ----- | ||
| 49 | [verse] | ||
| 50 | -- | ||
| 51 | *event-parse.h* | ||
| 52 | Header file to include in order to have access to the library APIs. | ||
| 53 | *-ltraceevent* | ||
| 54 | Linker switch to add when building a program that uses the library. | ||
| 55 | -- | ||
| 56 | |||
| 57 | SEE ALSO | ||
| 58 | -------- | ||
| 59 | _libtraceevent(3)_, _trace-cmd(1)_ | ||
| 60 | |||
| 61 | AUTHOR | ||
| 62 | ------ | ||
| 63 | [verse] | ||
| 64 | -- | ||
| 65 | *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. | ||
| 66 | *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. | ||
| 67 | -- | ||
| 68 | REPORTING BUGS | ||
| 69 | -------------- | ||
| 70 | Report bugs to <linux-trace-devel@vger.kernel.org> | ||
| 71 | |||
| 72 | LICENSE | ||
| 73 | ------- | ||
| 74 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 | ||
| 75 | |||
| 76 | RESOURCES | ||
| 77 | --------- | ||
| 78 | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git | ||
diff --git a/tools/lib/traceevent/Documentation/libtraceevent-page_size.txt b/tools/lib/traceevent/Documentation/libtraceevent-page_size.txt new file mode 100644 index 000000000000..452c0cfa1822 --- /dev/null +++ b/tools/lib/traceevent/Documentation/libtraceevent-page_size.txt | |||
| @@ -0,0 +1,82 @@ | |||
| 1 | libtraceevent(3) | ||
| 2 | ================ | ||
| 3 | |||
| 4 | NAME | ||
| 5 | ---- | ||
| 6 | tep_get_page_size, tep_set_page_size - Get / set the size of a memory page on | ||
| 7 | the machine, where the trace is generated | ||
| 8 | |||
| 9 | SYNOPSIS | ||
| 10 | -------- | ||
| 11 | [verse] | ||
| 12 | -- | ||
| 13 | *#include <event-parse.h>* | ||
| 14 | |||
| 15 | int *tep_get_page_size*(struct tep_handle pass:[*]_tep_); | ||
| 16 | void *tep_set_page_size*(struct tep_handle pass:[*]_tep_, int _page_size_); | ||
| 17 | -- | ||
| 18 | |||
| 19 | DESCRIPTION | ||
| 20 | ----------- | ||
| 21 | The _tep_get_page_size()_ function returns the size of a memory page on | ||
| 22 | the machine, where the trace is generated. The _tep_ argument is trace | ||
| 23 | event parser context. | ||
| 24 | |||
| 25 | The _tep_set_page_size()_ function stores in the _tep_ context the size of a | ||
| 26 | memory page on the machine, where the trace is generated. | ||
| 27 | The _tep_ argument is trace event parser context. | ||
| 28 | The _page_size_ argument is the size of a memory page, in bytes. | ||
| 29 | |||
| 30 | RETURN VALUE | ||
| 31 | ------------ | ||
| 32 | The _tep_get_page_size()_ function returns size of the memory page, in bytes. | ||
| 33 | |||
| 34 | EXAMPLE | ||
| 35 | ------- | ||
| 36 | [source,c] | ||
| 37 | -- | ||
| 38 | #include <unistd.h> | ||
| 39 | #include <event-parse.h> | ||
| 40 | ... | ||
| 41 | struct tep_handle *tep = tep_alloc(); | ||
| 42 | ... | ||
| 43 | int page_size = getpagesize(); | ||
| 44 | |||
| 45 | tep_set_page_size(tep, page_size); | ||
| 46 | |||
| 47 | printf("The page size for this machine is %d\n", tep_get_page_size(tep)); | ||
| 48 | |||
| 49 | -- | ||
| 50 | |||
| 51 | FILES | ||
| 52 | ----- | ||
| 53 | [verse] | ||
| 54 | -- | ||
| 55 | *event-parse.h* | ||
| 56 | Header file to include in order to have access to the library APIs. | ||
| 57 | *-ltraceevent* | ||
| 58 | Linker switch to add when building a program that uses the library. | ||
| 59 | -- | ||
| 60 | |||
| 61 | SEE ALSO | ||
| 62 | -------- | ||
| 63 | _libtraceevent(3)_, _trace-cmd(1)_ | ||
| 64 | |||
| 65 | AUTHOR | ||
| 66 | ------ | ||
| 67 | [verse] | ||
| 68 | -- | ||
| 69 | *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. | ||
| 70 | *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. | ||
| 71 | -- | ||
| 72 | REPORTING BUGS | ||
| 73 | -------------- | ||
| 74 | Report bugs to <linux-trace-devel@vger.kernel.org> | ||
| 75 | |||
| 76 | LICENSE | ||
| 77 | ------- | ||
| 78 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 | ||
| 79 | |||
| 80 | RESOURCES | ||
| 81 | --------- | ||
| 82 | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git | ||
diff --git a/tools/lib/traceevent/Documentation/libtraceevent-parse_event.txt b/tools/lib/traceevent/Documentation/libtraceevent-parse_event.txt new file mode 100644 index 000000000000..f248114ca1ff --- /dev/null +++ b/tools/lib/traceevent/Documentation/libtraceevent-parse_event.txt | |||
| @@ -0,0 +1,90 @@ | |||
| 1 | libtraceevent(3) | ||
| 2 | ================ | ||
| 3 | |||
| 4 | NAME | ||
| 5 | ---- | ||
| 6 | tep_parse_event, tep_parse_format - Parse the event format information | ||
| 7 | |||
| 8 | SYNOPSIS | ||
| 9 | -------- | ||
| 10 | [verse] | ||
| 11 | -- | ||
| 12 | *#include <event-parse.h>* | ||
| 13 | |||
| 14 | enum tep_errno *tep_parse_event*(struct tep_handle pass:[*]_tep_, const char pass:[*]_buf_, unsigned long _size_, const char pass:[*]_sys_); | ||
| 15 | enum tep_errno *tep_parse_format*(struct tep_handle pass:[*]_tep_, struct tep_event pass:[*]pass:[*]_eventp_, const char pass:[*]_buf_, unsigned long _size_, const char pass:[*]_sys_); | ||
| 16 | -- | ||
| 17 | |||
| 18 | DESCRIPTION | ||
| 19 | ----------- | ||
| 20 | The _tep_parse_event()_ function parses the event format and creates an event | ||
| 21 | structure to quickly parse raw data for a given event. The _tep_ argument is | ||
| 22 | the trace event parser context. The created event structure is stored in the | ||
| 23 | _tep_ context. The _buf_ argument is a buffer with _size_, where the event | ||
| 24 | format data is. The event format data can be taken from | ||
| 25 | tracefs/events/.../.../format files. The _sys_ argument is the system of | ||
| 26 | the event. | ||
| 27 | |||
| 28 | The _tep_parse_format()_ function does the same as _tep_parse_event()_. The only | ||
| 29 | difference is in the extra _eventp_ argument, where the newly created event | ||
| 30 | structure is returned. | ||
| 31 | |||
| 32 | RETURN VALUE | ||
| 33 | ------------ | ||
| 34 | Both _tep_parse_event()_ and _tep_parse_format()_ functions return 0 on success, | ||
| 35 | or TEP_ERRNO__... in case of an error. | ||
| 36 | |||
| 37 | EXAMPLE | ||
| 38 | ------- | ||
| 39 | [source,c] | ||
| 40 | -- | ||
| 41 | #include <event-parse.h> | ||
| 42 | ... | ||
| 43 | struct tep_handle *tep = tep_alloc(); | ||
| 44 | ... | ||
| 45 | char *buf; | ||
| 46 | int size; | ||
| 47 | struct tep_event *event = NULL; | ||
| 48 | buf = read_file("/sys/kernel/tracing/events/ftrace/print/format", &size); | ||
| 49 | if (tep_parse_event(tep, buf, size, "ftrace") != 0) { | ||
| 50 | /* Failed to parse the ftrace print format */ | ||
| 51 | } | ||
| 52 | |||
| 53 | if (tep_parse_format(tep, &event, buf, size, "ftrace") != 0) { | ||
| 54 | /* Failed to parse the ftrace print format */ | ||
| 55 | } | ||
| 56 | ... | ||
| 57 | -- | ||
| 58 | |||
| 59 | FILES | ||
| 60 | ----- | ||
| 61 | [verse] | ||
| 62 | -- | ||
| 63 | *event-parse.h* | ||
| 64 | Header file to include in order to have access to the library APIs. | ||
| 65 | *-ltraceevent* | ||
| 66 | Linker switch to add when building a program that uses the library. | ||
| 67 | -- | ||
| 68 | |||
| 69 | SEE ALSO | ||
| 70 | -------- | ||
| 71 | _libtraceevent(3)_, _trace-cmd(1)_ | ||
| 72 | |||
| 73 | AUTHOR | ||
| 74 | ------ | ||
| 75 | [verse] | ||
| 76 | -- | ||
| 77 | *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. | ||
| 78 | *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. | ||
| 79 | -- | ||
| 80 | REPORTING BUGS | ||
| 81 | -------------- | ||
| 82 | Report bugs to <linux-trace-devel@vger.kernel.org> | ||
| 83 | |||
| 84 | LICENSE | ||
| 85 | ------- | ||
| 86 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 | ||
| 87 | |||
| 88 | RESOURCES | ||
| 89 | --------- | ||
| 90 | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git | ||
diff --git a/tools/lib/traceevent/Documentation/libtraceevent-parse_head.txt b/tools/lib/traceevent/Documentation/libtraceevent-parse_head.txt new file mode 100644 index 000000000000..c90f16c7d8e6 --- /dev/null +++ b/tools/lib/traceevent/Documentation/libtraceevent-parse_head.txt | |||
| @@ -0,0 +1,82 @@ | |||
| 1 | libtraceevent(3) | ||
| 2 | ================ | ||
| 3 | |||
| 4 | NAME | ||
| 5 | ---- | ||
| 6 | tep_parse_header_page - Parses the data stored in the header page. | ||
| 7 | |||
| 8 | SYNOPSIS | ||
| 9 | -------- | ||
| 10 | [verse] | ||
| 11 | -- | ||
| 12 | *#include <event-parse.h>* | ||
| 13 | |||
| 14 | int *tep_parse_header_page*(struct tep_handle pass:[*]_tep_, char pass:[*]_buf_, unsigned long _size_, int _long_size_); | ||
| 15 | -- | ||
| 16 | |||
| 17 | DESCRIPTION | ||
| 18 | ----------- | ||
| 19 | The _tep_parse_header_page()_ function parses the header page data from _buf_, | ||
| 20 | and initializes the _tep_, trace event parser context, with it. The buffer | ||
| 21 | _buf_ is with _size_, and is supposed to be copied from | ||
| 22 | tracefs/events/header_page. | ||
| 23 | |||
| 24 | Some old kernels do not have header page info, in this case the | ||
| 25 | _tep_parse_header_page()_ function can be called with _size_ equal to 0. The | ||
| 26 | _tep_ context is initialized with default values. The _long_size_ can be used in | ||
| 27 | this use case, to set the size of a long integer to be used. | ||
| 28 | |||
| 29 | RETURN VALUE | ||
| 30 | ------------ | ||
| 31 | The _tep_parse_header_page()_ function returns 0 in case of success, or -1 | ||
| 32 | in case of an error. | ||
| 33 | |||
| 34 | EXAMPLE | ||
| 35 | ------- | ||
| 36 | [source,c] | ||
| 37 | -- | ||
| 38 | #include <event-parse.h> | ||
| 39 | ... | ||
| 40 | struct tep_handle *tep = tep_alloc(); | ||
| 41 | ... | ||
| 42 | char *buf; | ||
| 43 | int size; | ||
| 44 | buf = read_file("/sys/kernel/tracing/events/header_page", &size); | ||
| 45 | if (tep_parse_header_page(tep, buf, size, sizeof(unsigned long)) != 0) { | ||
| 46 | /* Failed to parse the header page */ | ||
| 47 | } | ||
| 48 | ... | ||
| 49 | -- | ||
| 50 | |||
| 51 | FILES | ||
| 52 | ----- | ||
| 53 | [verse] | ||
| 54 | -- | ||
| 55 | *event-parse.h* | ||
| 56 | Header file to include in order to have access to the library APIs. | ||
| 57 | *-ltraceevent* | ||
| 58 | Linker switch to add when building a program that uses the library. | ||
| 59 | -- | ||
| 60 | |||
| 61 | SEE ALSO | ||
| 62 | -------- | ||
| 63 | _libtraceevent(3)_, _trace-cmd(1)_ | ||
| 64 | |||
| 65 | AUTHOR | ||
| 66 | ------ | ||
| 67 | [verse] | ||
| 68 | -- | ||
| 69 | *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. | ||
| 70 | *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. | ||
| 71 | -- | ||
| 72 | REPORTING BUGS | ||
| 73 | -------------- | ||
| 74 | Report bugs to <linux-trace-devel@vger.kernel.org> | ||
| 75 | |||
| 76 | LICENSE | ||
| 77 | ------- | ||
| 78 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 | ||
| 79 | |||
| 80 | RESOURCES | ||
| 81 | --------- | ||
| 82 | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git | ||
diff --git a/tools/lib/traceevent/Documentation/libtraceevent-record_parse.txt b/tools/lib/traceevent/Documentation/libtraceevent-record_parse.txt new file mode 100644 index 000000000000..e9a69116c78b --- /dev/null +++ b/tools/lib/traceevent/Documentation/libtraceevent-record_parse.txt | |||
| @@ -0,0 +1,137 @@ | |||
| 1 | libtraceevent(3) | ||
| 2 | ================ | ||
| 3 | |||
| 4 | NAME | ||
| 5 | ---- | ||
| 6 | tep_data_type, tep_data_pid,tep_data_preempt_count, tep_data_flags - | ||
| 7 | Extract common fields from a record. | ||
| 8 | |||
| 9 | SYNOPSIS | ||
| 10 | -------- | ||
| 11 | [verse] | ||
| 12 | -- | ||
| 13 | *#include <event-parse.h>* | ||
| 14 | |||
| 15 | enum *trace_flag_type* { | ||
| 16 | _TRACE_FLAG_IRQS_OFF_, | ||
| 17 | _TRACE_FLAG_IRQS_NOSUPPORT_, | ||
| 18 | _TRACE_FLAG_NEED_RESCHED_, | ||
| 19 | _TRACE_FLAG_HARDIRQ_, | ||
| 20 | _TRACE_FLAG_SOFTIRQ_, | ||
| 21 | }; | ||
| 22 | |||
| 23 | int *tep_data_type*(struct tep_handle pass:[*]_tep_, struct tep_record pass:[*]_rec_); | ||
| 24 | int *tep_data_pid*(struct tep_handle pass:[*]_tep_, struct tep_record pass:[*]_rec_); | ||
| 25 | int *tep_data_preempt_count*(struct tep_handle pass:[*]_tep_, struct tep_record pass:[*]_rec_); | ||
| 26 | int *tep_data_flags*(struct tep_handle pass:[*]_tep_, struct tep_record pass:[*]_rec_); | ||
| 27 | -- | ||
| 28 | |||
| 29 | DESCRIPTION | ||
| 30 | ----------- | ||
| 31 | This set of functions can be used to extract common fields from a record. | ||
| 32 | |||
| 33 | The _tep_data_type()_ function gets the event id from the record _rec_. | ||
| 34 | It reads the "common_type" field. The _tep_ argument is the trace event parser | ||
| 35 | context. | ||
| 36 | |||
| 37 | The _tep_data_pid()_ function gets the process id from the record _rec_. | ||
| 38 | It reads the "common_pid" field. The _tep_ argument is the trace event parser | ||
| 39 | context. | ||
| 40 | |||
| 41 | The _tep_data_preempt_count()_ function gets the preemption count from the | ||
| 42 | record _rec_. It reads the "common_preempt_count" field. The _tep_ argument is | ||
| 43 | the trace event parser context. | ||
| 44 | |||
| 45 | The _tep_data_flags()_ function gets the latency flags from the record _rec_. | ||
| 46 | It reads the "common_flags" field. The _tep_ argument is the trace event parser | ||
| 47 | context. Supported latency flags are: | ||
| 48 | [verse] | ||
| 49 | -- | ||
| 50 | _TRACE_FLAG_IRQS_OFF_, Interrupts are disabled. | ||
| 51 | _TRACE_FLAG_IRQS_NOSUPPORT_, Reading IRQ flag is not supported by the architecture. | ||
| 52 | _TRACE_FLAG_NEED_RESCHED_, Task needs rescheduling. | ||
| 53 | _TRACE_FLAG_HARDIRQ_, Hard IRQ is running. | ||
| 54 | _TRACE_FLAG_SOFTIRQ_, Soft IRQ is running. | ||
| 55 | -- | ||
| 56 | |||
| 57 | RETURN VALUE | ||
| 58 | ------------ | ||
| 59 | The _tep_data_type()_ function returns an integer, representing the event id. | ||
| 60 | |||
| 61 | The _tep_data_pid()_ function returns an integer, representing the process id | ||
| 62 | |||
| 63 | The _tep_data_preempt_count()_ function returns an integer, representing the | ||
| 64 | preemption count. | ||
| 65 | |||
| 66 | The _tep_data_flags()_ function returns an integer, representing the latency | ||
| 67 | flags. Look at the _trace_flag_type_ enum for supported flags. | ||
| 68 | |||
| 69 | All these functions in case of an error return a negative integer. | ||
| 70 | |||
| 71 | EXAMPLE | ||
| 72 | ------- | ||
| 73 | [source,c] | ||
| 74 | -- | ||
| 75 | #include <event-parse.h> | ||
| 76 | ... | ||
| 77 | struct tep_handle *tep = tep_alloc(); | ||
| 78 | ... | ||
| 79 | void process_record(struct tep_record *record) | ||
| 80 | { | ||
| 81 | int data; | ||
| 82 | |||
| 83 | data = tep_data_type(tep, record); | ||
| 84 | if (data >= 0) { | ||
| 85 | /* Got the ID of the event */ | ||
| 86 | } | ||
| 87 | |||
| 88 | data = tep_data_pid(tep, record); | ||
| 89 | if (data >= 0) { | ||
| 90 | /* Got the process ID */ | ||
| 91 | } | ||
| 92 | |||
| 93 | data = tep_data_preempt_count(tep, record); | ||
| 94 | if (data >= 0) { | ||
| 95 | /* Got the preemption count */ | ||
| 96 | } | ||
| 97 | |||
| 98 | data = tep_data_flags(tep, record); | ||
| 99 | if (data >= 0) { | ||
| 100 | /* Got the latency flags */ | ||
| 101 | } | ||
| 102 | } | ||
| 103 | ... | ||
| 104 | -- | ||
| 105 | |||
| 106 | FILES | ||
| 107 | ----- | ||
| 108 | [verse] | ||
| 109 | -- | ||
| 110 | *event-parse.h* | ||
| 111 | Header file to include in order to have access to the library APIs. | ||
| 112 | *-ltraceevent* | ||
| 113 | Linker switch to add when building a program that uses the library. | ||
| 114 | -- | ||
| 115 | |||
| 116 | SEE ALSO | ||
| 117 | -------- | ||
| 118 | _libtraceevent(3)_, _trace-cmd(1)_ | ||
| 119 | |||
| 120 | AUTHOR | ||
| 121 | ------ | ||
| 122 | [verse] | ||
| 123 | -- | ||
| 124 | *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. | ||
| 125 | *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. | ||
| 126 | -- | ||
| 127 | REPORTING BUGS | ||
| 128 | -------------- | ||
| 129 | Report bugs to <linux-trace-devel@vger.kernel.org> | ||
| 130 | |||
| 131 | LICENSE | ||
| 132 | ------- | ||
| 133 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 | ||
| 134 | |||
| 135 | RESOURCES | ||
| 136 | --------- | ||
| 137 | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git | ||
diff --git a/tools/lib/traceevent/Documentation/libtraceevent-reg_event_handler.txt b/tools/lib/traceevent/Documentation/libtraceevent-reg_event_handler.txt new file mode 100644 index 000000000000..53d37d72a1c1 --- /dev/null +++ b/tools/lib/traceevent/Documentation/libtraceevent-reg_event_handler.txt | |||
| @@ -0,0 +1,156 @@ | |||
| 1 | libtraceevent(3) | ||
| 2 | ================ | ||
| 3 | |||
| 4 | NAME | ||
| 5 | ---- | ||
| 6 | tep_register_event_handler, tep_unregister_event_handler - Register / | ||
| 7 | unregisters a callback function to parse an event information. | ||
| 8 | |||
| 9 | SYNOPSIS | ||
| 10 | -------- | ||
| 11 | [verse] | ||
| 12 | -- | ||
| 13 | *#include <event-parse.h>* | ||
| 14 | |||
| 15 | enum *tep_reg_handler* { | ||
| 16 | _TEP_REGISTER_SUCCESS_, | ||
| 17 | _TEP_REGISTER_SUCCESS_OVERWRITE_, | ||
| 18 | }; | ||
| 19 | |||
| 20 | int *tep_register_event_handler*(struct tep_handle pass:[*]_tep_, int _id_, const char pass:[*]_sys_name_, const char pass:[*]_event_name_, tep_event_handler_func _func_, void pass:[*]_context_); | ||
| 21 | int *tep_unregister_event_handler*(struct tep_handle pass:[*]tep, int id, const char pass:[*]sys_name, const char pass:[*]event_name, tep_event_handler_func func, void pass:[*]_context_); | ||
| 22 | |||
| 23 | typedef int (*pass:[*]tep_event_handler_func*)(struct trace_seq pass:[*]s, struct tep_record pass:[*]record, struct tep_event pass:[*]event, void pass:[*]context); | ||
| 24 | -- | ||
| 25 | |||
| 26 | DESCRIPTION | ||
| 27 | ----------- | ||
| 28 | The _tep_register_event_handler()_ function registers a handler function, | ||
| 29 | which is going to be called to parse the information for a given event. | ||
| 30 | The _tep_ argument is the trace event parser context. The _id_ argument is | ||
| 31 | the id of the event. The _sys_name_ argument is the name of the system, | ||
| 32 | the event belongs to. The _event_name_ argument is the name of the event. | ||
| 33 | If _id_ is >= 0, it is used to find the event, otherwise _sys_name_ and | ||
| 34 | _event_name_ are used. The _func_ is a pointer to the function, which is going | ||
| 35 | to be called to parse the event information. The _context_ argument is a pointer | ||
| 36 | to the context data, which will be passed to the _func_. If a handler function | ||
| 37 | for the same event is already registered, it will be overridden with the new | ||
| 38 | one. This mechanism allows a developer to override the parsing of a given event. | ||
| 39 | If for some reason the default print format is not sufficient, the developer | ||
| 40 | can register a function for an event to be used to parse the data instead. | ||
| 41 | |||
| 42 | The _tep_unregister_event_handler()_ function unregisters the handler function, | ||
| 43 | previously registered with _tep_register_event_handler()_. The _tep_ argument | ||
| 44 | is the trace event parser context. The _id_, _sys_name_, _event_name_, _func_, | ||
| 45 | and _context_ are the same arguments, as when the callback function _func_ was | ||
| 46 | registered. | ||
| 47 | |||
| 48 | The _tep_event_handler_func_ is the type of the custom event handler | ||
| 49 | function. The _s_ argument is the trace sequence, it can be used to create a | ||
| 50 | custom string, describing the event. A _record_ to get the event from is passed | ||
| 51 | as input parameter and also the _event_ - the handle to the record's event. The | ||
| 52 | _context_ is custom context, set when the custom event handler is registered. | ||
| 53 | |||
| 54 | RETURN VALUE | ||
| 55 | ------------ | ||
| 56 | The _tep_register_event_handler()_ function returns _TEP_REGISTER_SUCCESS_ | ||
| 57 | if the new handler is registered successfully or | ||
| 58 | _TEP_REGISTER_SUCCESS_OVERWRITE_ if an existing handler is overwritten. | ||
| 59 | If there is not enough memory to complete the registration, | ||
| 60 | TEP_ERRNO__MEM_ALLOC_FAILED is returned. | ||
| 61 | |||
| 62 | The _tep_unregister_event_handler()_ function returns 0 if _func_ was removed | ||
| 63 | successful or, -1 if the event was not found. | ||
| 64 | |||
| 65 | The _tep_event_handler_func_ should return -1 in case of an error, | ||
| 66 | or 0 otherwise. | ||
| 67 | |||
| 68 | EXAMPLE | ||
| 69 | ------- | ||
| 70 | [source,c] | ||
| 71 | -- | ||
| 72 | #include <event-parse.h> | ||
| 73 | #include <trace-seq.h> | ||
| 74 | ... | ||
| 75 | struct tep_handle *tep = tep_alloc(); | ||
| 76 | ... | ||
| 77 | int timer_expire_handler(struct trace_seq *s, struct tep_record *record, | ||
| 78 | struct tep_event *event, void *context) | ||
| 79 | { | ||
| 80 | trace_seq_printf(s, "hrtimer="); | ||
| 81 | |||
| 82 | if (tep_print_num_field(s, "0x%llx", event, "timer", record, 0) == -1) | ||
| 83 | tep_print_num_field(s, "0x%llx", event, "hrtimer", record, 1); | ||
| 84 | |||
| 85 | trace_seq_printf(s, " now="); | ||
| 86 | |||
| 87 | tep_print_num_field(s, "%llu", event, "now", record, 1); | ||
| 88 | |||
| 89 | tep_print_func_field(s, " function=%s", event, "function", record, 0); | ||
| 90 | |||
| 91 | return 0; | ||
| 92 | } | ||
| 93 | ... | ||
| 94 | int ret; | ||
| 95 | |||
| 96 | ret = tep_register_event_handler(tep, -1, "timer", "hrtimer_expire_entry", | ||
| 97 | timer_expire_handler, NULL); | ||
| 98 | if (ret < 0) { | ||
| 99 | char buf[32]; | ||
| 100 | |||
| 101 | tep_strerror(tep, ret, buf, 32) | ||
| 102 | printf("Failed to register handler for hrtimer_expire_entry: %s\n", buf); | ||
| 103 | } else { | ||
| 104 | switch (ret) { | ||
| 105 | case TEP_REGISTER_SUCCESS: | ||
| 106 | printf ("Registered handler for hrtimer_expire_entry\n"); | ||
| 107 | break; | ||
| 108 | case TEP_REGISTER_SUCCESS_OVERWRITE: | ||
| 109 | printf ("Overwrote handler for hrtimer_expire_entry\n"); | ||
| 110 | break; | ||
| 111 | } | ||
| 112 | } | ||
| 113 | ... | ||
| 114 | ret = tep_unregister_event_handler(tep, -1, "timer", "hrtimer_expire_entry", | ||
| 115 | timer_expire_handler, NULL); | ||
| 116 | if ( ret ) | ||
| 117 | printf ("Failed to unregister handler for hrtimer_expire_entry\n"); | ||
| 118 | |||
| 119 | -- | ||
| 120 | |||
| 121 | FILES | ||
| 122 | ----- | ||
| 123 | [verse] | ||
| 124 | -- | ||
| 125 | *event-parse.h* | ||
| 126 | Header file to include in order to have access to the library APIs. | ||
| 127 | *trace-seq.h* | ||
| 128 | Header file to include in order to have access to trace sequences | ||
| 129 | related APIs. Trace sequences are used to allow a function to call | ||
| 130 | several other functions to create a string of data to use. | ||
| 131 | *-ltraceevent* | ||
| 132 | Linker switch to add when building a program that uses the library. | ||
| 133 | -- | ||
| 134 | |||
| 135 | SEE ALSO | ||
| 136 | -------- | ||
| 137 | _libtraceevent(3)_, _trace-cmd(1)_ | ||
| 138 | |||
| 139 | AUTHOR | ||
| 140 | ------ | ||
| 141 | [verse] | ||
| 142 | -- | ||
| 143 | *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. | ||
| 144 | *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. | ||
| 145 | -- | ||
| 146 | REPORTING BUGS | ||
| 147 | -------------- | ||
| 148 | Report bugs to <linux-trace-devel@vger.kernel.org> | ||
| 149 | |||
| 150 | LICENSE | ||
| 151 | ------- | ||
| 152 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 | ||
| 153 | |||
| 154 | RESOURCES | ||
| 155 | --------- | ||
| 156 | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git | ||
diff --git a/tools/lib/traceevent/Documentation/libtraceevent-reg_print_func.txt b/tools/lib/traceevent/Documentation/libtraceevent-reg_print_func.txt new file mode 100644 index 000000000000..708dce91ebd8 --- /dev/null +++ b/tools/lib/traceevent/Documentation/libtraceevent-reg_print_func.txt | |||
| @@ -0,0 +1,155 @@ | |||
| 1 | libtraceevent(3) | ||
| 2 | ================ | ||
| 3 | |||
| 4 | NAME | ||
| 5 | ---- | ||
| 6 | tep_register_print_function,tep_unregister_print_function - | ||
| 7 | Registers / Unregisters a helper function. | ||
| 8 | |||
| 9 | SYNOPSIS | ||
| 10 | -------- | ||
| 11 | [verse] | ||
| 12 | -- | ||
| 13 | *#include <event-parse.h>* | ||
| 14 | |||
| 15 | enum *tep_func_arg_type* { | ||
| 16 | TEP_FUNC_ARG_VOID, | ||
| 17 | TEP_FUNC_ARG_INT, | ||
| 18 | TEP_FUNC_ARG_LONG, | ||
| 19 | TEP_FUNC_ARG_STRING, | ||
| 20 | TEP_FUNC_ARG_PTR, | ||
| 21 | TEP_FUNC_ARG_MAX_TYPES | ||
| 22 | }; | ||
| 23 | |||
| 24 | typedef unsigned long long (*pass:[*]tep_func_handler*)(struct trace_seq pass:[*]s, unsigned long long pass:[*]args); | ||
| 25 | |||
| 26 | int *tep_register_print_function*(struct tep_handle pass:[*]_tep_, tep_func_handler _func_, enum tep_func_arg_type _ret_type_, char pass:[*]_name_, _..._); | ||
| 27 | int *tep_unregister_print_function*(struct tep_handle pass:[*]_tep_, tep_func_handler _func_, char pass:[*]_name_); | ||
| 28 | -- | ||
| 29 | |||
| 30 | DESCRIPTION | ||
| 31 | ----------- | ||
| 32 | Some events may have helper functions in the print format arguments. | ||
| 33 | This allows a plugin to dynamically create a way to process one of | ||
| 34 | these functions. | ||
| 35 | |||
| 36 | The _tep_register_print_function()_ registers such helper function. The _tep_ | ||
| 37 | argument is the trace event parser context. The _func_ argument is a pointer | ||
| 38 | to the helper function. The _ret_type_ argument is the return type of the | ||
| 39 | helper function, value from the _tep_func_arg_type_ enum. The _name_ is the name | ||
| 40 | of the helper function, as seen in the print format arguments. The _..._ is a | ||
| 41 | variable list of _tep_func_arg_type_ enums, the _func_ function arguments. | ||
| 42 | This list must end with _TEP_FUNC_ARG_VOID_. See 'EXAMPLE' section. | ||
| 43 | |||
| 44 | The _tep_unregister_print_function()_ unregisters a helper function, previously | ||
| 45 | registered with _tep_register_print_function()_. The _tep_ argument is the | ||
| 46 | trace event parser context. The _func_ and _name_ arguments are the same, used | ||
| 47 | when the helper function was registered. | ||
| 48 | |||
| 49 | The _tep_func_handler_ is the type of the helper function. The _s_ argument is | ||
| 50 | the trace sequence, it can be used to create a custom string. | ||
| 51 | The _args_ is a list of arguments, defined when the helper function was | ||
| 52 | registered. | ||
| 53 | |||
| 54 | RETURN VALUE | ||
| 55 | ------------ | ||
| 56 | The _tep_register_print_function()_ function returns 0 in case of success. | ||
| 57 | In case of an error, TEP_ERRNO_... code is returned. | ||
| 58 | |||
| 59 | The _tep_unregister_print_function()_ returns 0 in case of success, or -1 in | ||
| 60 | case of an error. | ||
| 61 | |||
| 62 | EXAMPLE | ||
| 63 | ------- | ||
| 64 | Some events have internal functions calls, that appear in the print format | ||
| 65 | output. For example "tracefs/events/i915/g4x_wm/format" has: | ||
| 66 | [source,c] | ||
| 67 | -- | ||
| 68 | print fmt: "pipe %c, frame=%u, scanline=%u, wm %d/%d/%d, sr %s/%d/%d/%d, hpll %s/%d/%d/%d, fbc %s", | ||
| 69 | ((REC->pipe) + 'A'), REC->frame, REC->scanline, REC->primary, | ||
| 70 | REC->sprite, REC->cursor, yesno(REC->cxsr), REC->sr_plane, | ||
| 71 | REC->sr_cursor, REC->sr_fbc, yesno(REC->hpll), REC->hpll_plane, | ||
| 72 | REC->hpll_cursor, REC->hpll_fbc, yesno(REC->fbc) | ||
| 73 | -- | ||
| 74 | Notice the call to function _yesno()_ in the print arguments. In the kernel | ||
| 75 | context, this function has the following implementation: | ||
| 76 | [source,c] | ||
| 77 | -- | ||
| 78 | static const char *yesno(int x) | ||
| 79 | { | ||
| 80 | static const char *yes = "yes"; | ||
| 81 | static const char *no = "no"; | ||
| 82 | |||
| 83 | return x ? yes : no; | ||
| 84 | } | ||
| 85 | -- | ||
| 86 | The user space event parser has no idea how to handle this _yesno()_ function. | ||
| 87 | The _tep_register_print_function()_ API can be used to register a user space | ||
| 88 | helper function, mapped to the kernel's _yesno()_: | ||
| 89 | [source,c] | ||
| 90 | -- | ||
| 91 | #include <event-parse.h> | ||
| 92 | #include <trace-seq.h> | ||
| 93 | ... | ||
| 94 | struct tep_handle *tep = tep_alloc(); | ||
| 95 | ... | ||
| 96 | static const char *yes_no_helper(int x) | ||
| 97 | { | ||
| 98 | return x ? "yes" : "no"; | ||
| 99 | } | ||
| 100 | ... | ||
| 101 | if ( tep_register_print_function(tep, | ||
| 102 | yes_no_helper, | ||
| 103 | TEP_FUNC_ARG_STRING, | ||
| 104 | "yesno", | ||
| 105 | TEP_FUNC_ARG_INT, | ||
| 106 | TEP_FUNC_ARG_VOID) != 0) { | ||
| 107 | /* Failed to register yes_no_helper function */ | ||
| 108 | } | ||
| 109 | |||
| 110 | /* | ||
| 111 | Now, when the event parser encounters this yesno() function, it will know | ||
| 112 | how to handle it. | ||
| 113 | */ | ||
| 114 | ... | ||
| 115 | if (tep_unregister_print_function(tep, yes_no_helper, "yesno") != 0) { | ||
| 116 | /* Failed to unregister yes_no_helper function */ | ||
| 117 | } | ||
| 118 | -- | ||
| 119 | |||
| 120 | FILES | ||
| 121 | ----- | ||
| 122 | [verse] | ||
| 123 | -- | ||
| 124 | *event-parse.h* | ||
| 125 | Header file to include in order to have access to the library APIs. | ||
| 126 | *trace-seq.h* | ||
| 127 | Header file to include in order to have access to trace sequences | ||
| 128 | related APIs. Trace sequences are used to allow a function to call | ||
| 129 | several other functions to create a string of data to use. | ||
| 130 | *-ltraceevent* | ||
| 131 | Linker switch to add when building a program that uses the library. | ||
| 132 | -- | ||
| 133 | |||
| 134 | SEE ALSO | ||
| 135 | -------- | ||
| 136 | _libtraceevent(3)_, _trace-cmd(1)_ | ||
| 137 | |||
| 138 | AUTHOR | ||
| 139 | ------ | ||
| 140 | [verse] | ||
| 141 | -- | ||
| 142 | *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. | ||
| 143 | *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. | ||
| 144 | -- | ||
| 145 | REPORTING BUGS | ||
| 146 | -------------- | ||
| 147 | Report bugs to <linux-trace-devel@vger.kernel.org> | ||
| 148 | |||
| 149 | LICENSE | ||
| 150 | ------- | ||
| 151 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 | ||
| 152 | |||
| 153 | RESOURCES | ||
| 154 | --------- | ||
| 155 | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git | ||
diff --git a/tools/lib/traceevent/Documentation/libtraceevent-set_flag.txt b/tools/lib/traceevent/Documentation/libtraceevent-set_flag.txt new file mode 100644 index 000000000000..b0599780b9a6 --- /dev/null +++ b/tools/lib/traceevent/Documentation/libtraceevent-set_flag.txt | |||
| @@ -0,0 +1,104 @@ | |||
| 1 | libtraceevent(3) | ||
| 2 | ================ | ||
| 3 | |||
| 4 | NAME | ||
| 5 | ---- | ||
| 6 | tep_set_flag, tep_clear_flag, tep_test_flag - | ||
| 7 | Manage flags of trace event parser context. | ||
| 8 | |||
| 9 | SYNOPSIS | ||
| 10 | -------- | ||
| 11 | [verse] | ||
| 12 | -- | ||
| 13 | *#include <event-parse.h>* | ||
| 14 | |||
| 15 | enum *tep_flag* { | ||
| 16 | _TEP_NSEC_OUTPUT_, | ||
| 17 | _TEP_DISABLE_SYS_PLUGINS_, | ||
| 18 | _TEP_DISABLE_PLUGINS_ | ||
| 19 | }; | ||
| 20 | void *tep_set_flag*(struct tep_handle pass:[*]_tep_, enum tep_flag _flag_); | ||
| 21 | void *tep_clear_flag*(struct tep_handle pass:[*]_tep_, enum tep_flag _flag_); | ||
| 22 | bool *tep_test_flag*(struct tep_handle pass:[*]_tep_, enum tep_flag _flag_); | ||
| 23 | -- | ||
| 24 | |||
| 25 | DESCRIPTION | ||
| 26 | ----------- | ||
| 27 | Trace event parser context flags are defined in *enum tep_flag*: | ||
| 28 | [verse] | ||
| 29 | -- | ||
| 30 | _TEP_NSEC_OUTPUT_ - print event's timestamp in nano seconds, instead of micro seconds. | ||
| 31 | _TEP_DISABLE_SYS_PLUGINS_ - disable plugins, located in system's plugin | ||
| 32 | directory. This directory is defined at library compile | ||
| 33 | time, and usually depends on library installation | ||
| 34 | prefix: (install_preffix)/lib/traceevent/plugins | ||
| 35 | _TEP_DISABLE_PLUGINS_ - disable all library plugins: | ||
| 36 | - in system's plugin directory | ||
| 37 | - in directory, defined by the environment variable _TRACEEVENT_PLUGIN_DIR_ | ||
| 38 | - in user's home directory, _~/.traceevent/plugins_ | ||
| 39 | -- | ||
| 40 | Note: plugin related flags must me set before calling _tep_load_plugins()_ API. | ||
| 41 | |||
| 42 | The _tep_set_flag()_ function sets _flag_ to _tep_ context. | ||
| 43 | |||
| 44 | The _tep_clear_flag()_ function clears _flag_ from _tep_ context. | ||
| 45 | |||
| 46 | The _tep_test_flag()_ function tests if _flag_ is set to _tep_ context. | ||
| 47 | |||
| 48 | RETURN VALUE | ||
| 49 | ------------ | ||
| 50 | _tep_test_flag()_ function returns true if _flag_ is set, false otherwise. | ||
| 51 | |||
| 52 | EXAMPLE | ||
| 53 | ------- | ||
| 54 | [source,c] | ||
| 55 | -- | ||
| 56 | #include <event-parse.h> | ||
| 57 | ... | ||
| 58 | struct tep_handle *tep = tep_alloc(); | ||
| 59 | ... | ||
| 60 | /* Print timestamps in nanoseconds */ | ||
| 61 | tep_set_flag(tep, TEP_NSEC_OUTPUT); | ||
| 62 | ... | ||
| 63 | if (tep_test_flag(tep, TEP_NSEC_OUTPUT)) { | ||
| 64 | /* print timestamps in nanoseconds */ | ||
| 65 | } else { | ||
| 66 | /* print timestamps in microseconds */ | ||
| 67 | } | ||
| 68 | ... | ||
| 69 | /* Print timestamps in microseconds */ | ||
| 70 | tep_clear_flag(tep, TEP_NSEC_OUTPUT); | ||
| 71 | ... | ||
| 72 | -- | ||
| 73 | FILES | ||
| 74 | ----- | ||
| 75 | [verse] | ||
| 76 | -- | ||
| 77 | *event-parse.h* | ||
| 78 | Header file to include in order to have access to the library APIs. | ||
| 79 | *-ltraceevent* | ||
| 80 | Linker switch to add when building a program that uses the library. | ||
| 81 | -- | ||
| 82 | |||
| 83 | SEE ALSO | ||
| 84 | -------- | ||
| 85 | _libtraceevent(3)_, _trace-cmd(1)_ | ||
| 86 | |||
| 87 | AUTHOR | ||
| 88 | ------ | ||
| 89 | [verse] | ||
| 90 | -- | ||
| 91 | *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. | ||
| 92 | *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. | ||
| 93 | -- | ||
| 94 | REPORTING BUGS | ||
| 95 | -------------- | ||
| 96 | Report bugs to <linux-trace-devel@vger.kernel.org> | ||
| 97 | |||
| 98 | LICENSE | ||
| 99 | ------- | ||
| 100 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 | ||
| 101 | |||
| 102 | RESOURCES | ||
| 103 | --------- | ||
| 104 | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git | ||
diff --git a/tools/lib/traceevent/Documentation/libtraceevent-strerror.txt b/tools/lib/traceevent/Documentation/libtraceevent-strerror.txt new file mode 100644 index 000000000000..ee4062a00c9f --- /dev/null +++ b/tools/lib/traceevent/Documentation/libtraceevent-strerror.txt | |||
| @@ -0,0 +1,85 @@ | |||
| 1 | libtraceevent(3) | ||
| 2 | ================ | ||
| 3 | |||
| 4 | NAME | ||
| 5 | ---- | ||
| 6 | tep_strerror - Returns a string describing regular errno and tep error number. | ||
| 7 | |||
| 8 | SYNOPSIS | ||
| 9 | -------- | ||
| 10 | [verse] | ||
| 11 | -- | ||
| 12 | *#include <event-parse.h>* | ||
| 13 | |||
| 14 | int *tep_strerror*(struct tep_handle pass:[*]_tep_, enum tep_errno _errnum_, char pass:[*]_buf_, size_t _buflen_); | ||
| 15 | |||
| 16 | -- | ||
| 17 | DESCRIPTION | ||
| 18 | ----------- | ||
| 19 | The _tep_strerror()_ function converts tep error number into a human | ||
| 20 | readable string. | ||
| 21 | The _tep_ argument is trace event parser context. The _errnum_ is a regular | ||
| 22 | errno, defined in errno.h, or a tep error number. The string, describing this | ||
| 23 | error number is copied in the _buf_ argument. The _buflen_ argument is | ||
| 24 | the size of the _buf_. | ||
| 25 | |||
| 26 | It as a thread safe wrapper around strerror_r(). The library function has two | ||
| 27 | different behaviors - POSIX and GNU specific. The _tep_strerror()_ API always | ||
| 28 | behaves as the POSIX version - the error string is copied in the user supplied | ||
| 29 | buffer. | ||
| 30 | |||
| 31 | RETURN VALUE | ||
| 32 | ------------ | ||
| 33 | The _tep_strerror()_ function returns 0, if a valid _errnum_ is passed and the | ||
| 34 | string is copied into _buf_. If _errnum_ is not a valid error number, | ||
| 35 | -1 is returned and _buf_ is not modified. | ||
| 36 | |||
| 37 | EXAMPLE | ||
| 38 | ------- | ||
| 39 | [source,c] | ||
| 40 | -- | ||
| 41 | #include <event-parse.h> | ||
| 42 | ... | ||
| 43 | struct tep_handle *tep = tep_alloc(); | ||
| 44 | ... | ||
| 45 | char buf[32]; | ||
| 46 | char *pool = calloc(1, 128); | ||
| 47 | if (tep == NULL) { | ||
| 48 | tep_strerror(tep, TEP_ERRNO__MEM_ALLOC_FAILED, buf, 32); | ||
| 49 | printf ("The pool is not initialized, %s", buf); | ||
| 50 | } | ||
| 51 | ... | ||
| 52 | -- | ||
| 53 | |||
| 54 | FILES | ||
| 55 | ----- | ||
| 56 | [verse] | ||
| 57 | -- | ||
| 58 | *event-parse.h* | ||
| 59 | Header file to include in order to have access to the library APIs. | ||
| 60 | *-ltraceevent* | ||
| 61 | Linker switch to add when building a program that uses the library. | ||
| 62 | -- | ||
| 63 | |||
| 64 | SEE ALSO | ||
| 65 | -------- | ||
| 66 | _libtraceevent(3)_, _trace-cmd(1)_ | ||
| 67 | |||
| 68 | AUTHOR | ||
| 69 | ------ | ||
| 70 | [verse] | ||
| 71 | -- | ||
| 72 | *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. | ||
| 73 | *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. | ||
| 74 | -- | ||
| 75 | REPORTING BUGS | ||
| 76 | -------------- | ||
| 77 | Report bugs to <linux-trace-devel@vger.kernel.org> | ||
| 78 | |||
| 79 | LICENSE | ||
| 80 | ------- | ||
| 81 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 | ||
| 82 | |||
| 83 | RESOURCES | ||
| 84 | --------- | ||
| 85 | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git | ||
diff --git a/tools/lib/traceevent/Documentation/libtraceevent-tseq.txt b/tools/lib/traceevent/Documentation/libtraceevent-tseq.txt new file mode 100644 index 000000000000..8ac6aa174e12 --- /dev/null +++ b/tools/lib/traceevent/Documentation/libtraceevent-tseq.txt | |||
| @@ -0,0 +1,158 @@ | |||
| 1 | libtraceevent(3) | ||
| 2 | ================ | ||
| 3 | |||
| 4 | NAME | ||
| 5 | ---- | ||
| 6 | trace_seq_init, trace_seq_destroy, trace_seq_reset, trace_seq_terminate, | ||
| 7 | trace_seq_putc, trace_seq_puts, trace_seq_printf, trace_seq_vprintf, | ||
| 8 | trace_seq_do_fprintf, trace_seq_do_printf - | ||
| 9 | Initialize / destroy a trace sequence. | ||
| 10 | |||
| 11 | SYNOPSIS | ||
| 12 | -------- | ||
| 13 | [verse] | ||
| 14 | -- | ||
| 15 | *#include <event-parse.h>* | ||
| 16 | *#include <trace-seq.h>* | ||
| 17 | |||
| 18 | void *trace_seq_init*(struct trace_seq pass:[*]_s_); | ||
| 19 | void *trace_seq_destroy*(struct trace_seq pass:[*]_s_); | ||
| 20 | void *trace_seq_reset*(struct trace_seq pass:[*]_s_); | ||
| 21 | void *trace_seq_terminate*(struct trace_seq pass:[*]_s_); | ||
| 22 | int *trace_seq_putc*(struct trace_seq pass:[*]_s_, unsigned char _c_); | ||
| 23 | int *trace_seq_puts*(struct trace_seq pass:[*]_s_, const char pass:[*]_str_); | ||
| 24 | int *trace_seq_printf*(struct trace_seq pass:[*]_s_, const char pass:[*]_fmt_, _..._); | ||
| 25 | int *trace_seq_vprintf*(struct trace_seq pass:[*]_s_, const char pass:[*]_fmt_, va_list _args_); | ||
| 26 | int *trace_seq_do_printf*(struct trace_seq pass:[*]_s_); | ||
| 27 | int *trace_seq_do_fprintf*(struct trace_seq pass:[*]_s_, FILE pass:[*]_fp_); | ||
| 28 | -- | ||
| 29 | |||
| 30 | DESCRIPTION | ||
| 31 | ----------- | ||
| 32 | Trace sequences are used to allow a function to call several other functions | ||
| 33 | to create a string of data to use. | ||
| 34 | |||
| 35 | The _trace_seq_init()_ function initializes the trace sequence _s_. | ||
| 36 | |||
| 37 | The _trace_seq_destroy()_ function destroys the trace sequence _s_ and frees | ||
| 38 | all its resources that it had used. | ||
| 39 | |||
| 40 | The _trace_seq_reset()_ function re-initializes the trace sequence _s_. All | ||
| 41 | characters already written in _s_ will be deleted. | ||
| 42 | |||
| 43 | The _trace_seq_terminate()_ function terminates the trace sequence _s_. It puts | ||
| 44 | the null character pass:['\0'] at the end of the buffer. | ||
| 45 | |||
| 46 | The _trace_seq_putc()_ function puts a single character _c_ in the trace | ||
| 47 | sequence _s_. | ||
| 48 | |||
| 49 | The _trace_seq_puts()_ function puts a NULL terminated string _str_ in the | ||
| 50 | trace sequence _s_. | ||
| 51 | |||
| 52 | The _trace_seq_printf()_ function puts a formated string _fmt _with | ||
| 53 | variable arguments _..._ in the trace sequence _s_. | ||
| 54 | |||
| 55 | The _trace_seq_vprintf()_ function puts a formated string _fmt _with | ||
| 56 | list of arguments _args_ in the trace sequence _s_. | ||
| 57 | |||
| 58 | The _trace_seq_do_printf()_ function prints the buffer of trace sequence _s_ to | ||
| 59 | the standard output stdout. | ||
| 60 | |||
| 61 | The _trace_seq_do_fprintf()_ function prints the buffer of trace sequence _s_ | ||
| 62 | to the given file _fp_. | ||
| 63 | |||
| 64 | RETURN VALUE | ||
| 65 | ------------ | ||
| 66 | Both _trace_seq_putc()_ and _trace_seq_puts()_ functions return the number of | ||
| 67 | characters put in the trace sequence, or 0 in case of an error | ||
| 68 | |||
| 69 | Both _trace_seq_printf()_ and _trace_seq_vprintf()_ functions return 0 if the | ||
| 70 | trace oversizes the buffer's free space, the number of characters printed, or | ||
| 71 | a negative value in case of an error. | ||
| 72 | |||
| 73 | Both _trace_seq_do_printf()_ and _trace_seq_do_fprintf()_ functions return the | ||
| 74 | number of printed characters, or -1 in case of an error. | ||
| 75 | |||
| 76 | EXAMPLE | ||
| 77 | ------- | ||
| 78 | [source,c] | ||
| 79 | -- | ||
| 80 | #include <event-parse.h> | ||
| 81 | #include <trace-seq.h> | ||
| 82 | ... | ||
| 83 | struct trace_seq seq; | ||
| 84 | trace_seq_init(&seq); | ||
| 85 | ... | ||
| 86 | void foo_seq_print(struct trace_seq *tseq, char *format, ...) | ||
| 87 | { | ||
| 88 | va_list ap; | ||
| 89 | va_start(ap, format); | ||
| 90 | if (trace_seq_vprintf(tseq, format, ap) <= 0) { | ||
| 91 | /* Failed to print in the trace sequence */ | ||
| 92 | } | ||
| 93 | va_end(ap); | ||
| 94 | } | ||
| 95 | |||
| 96 | trace_seq_reset(&seq); | ||
| 97 | |||
| 98 | char *str = " MAN page example"; | ||
| 99 | if (trace_seq_puts(&seq, str) != strlen(str)) { | ||
| 100 | /* Failed to put str in the trace sequence */ | ||
| 101 | } | ||
| 102 | if (trace_seq_putc(&seq, ':') != 1) { | ||
| 103 | /* Failed to put ':' in the trace sequence */ | ||
| 104 | } | ||
| 105 | if (trace_seq_printf(&seq, " trace sequence: %d", 1) <= 0) { | ||
| 106 | /* Failed to print in the trace sequence */ | ||
| 107 | } | ||
| 108 | foo_seq_print( &seq, " %d\n", 2); | ||
| 109 | |||
| 110 | trace_seq_terminate(&seq); | ||
| 111 | ... | ||
| 112 | |||
| 113 | if (trace_seq_do_printf(&seq) < 0 ) { | ||
| 114 | /* Failed to print the sequence buffer to the standard output */ | ||
| 115 | } | ||
| 116 | FILE *fp = fopen("trace.txt", "w"); | ||
| 117 | if (trace_seq_do_fprintf(&seq, fp) < 0 ) [ | ||
| 118 | /* Failed to print the sequence buffer to the trace.txt file */ | ||
| 119 | } | ||
| 120 | |||
| 121 | trace_seq_destroy(&seq); | ||
| 122 | ... | ||
| 123 | -- | ||
| 124 | |||
| 125 | FILES | ||
| 126 | ----- | ||
| 127 | [verse] | ||
| 128 | -- | ||
| 129 | *event-parse.h* | ||
| 130 | Header file to include in order to have access to the library APIs. | ||
| 131 | *trace-seq.h* | ||
| 132 | Header file to include in order to have access to trace sequences related APIs. | ||
| 133 | *-ltraceevent* | ||
| 134 | Linker switch to add when building a program that uses the library. | ||
| 135 | -- | ||
| 136 | |||
| 137 | SEE ALSO | ||
| 138 | -------- | ||
| 139 | _libtraceevent(3)_, _trace-cmd(1)_ | ||
| 140 | |||
| 141 | AUTHOR | ||
| 142 | ------ | ||
| 143 | [verse] | ||
| 144 | -- | ||
| 145 | *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. | ||
| 146 | *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. | ||
| 147 | -- | ||
| 148 | REPORTING BUGS | ||
| 149 | -------------- | ||
| 150 | Report bugs to <linux-trace-devel@vger.kernel.org> | ||
| 151 | |||
| 152 | LICENSE | ||
| 153 | ------- | ||
| 154 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 | ||
| 155 | |||
| 156 | RESOURCES | ||
| 157 | --------- | ||
| 158 | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git | ||
diff --git a/tools/lib/traceevent/Documentation/libtraceevent.txt b/tools/lib/traceevent/Documentation/libtraceevent.txt new file mode 100644 index 000000000000..fbd977b47de1 --- /dev/null +++ b/tools/lib/traceevent/Documentation/libtraceevent.txt | |||
| @@ -0,0 +1,203 @@ | |||
| 1 | libtraceevent(3) | ||
| 2 | ================ | ||
| 3 | |||
| 4 | NAME | ||
| 5 | ---- | ||
| 6 | libtraceevent - Linux kernel trace event library | ||
| 7 | |||
| 8 | SYNOPSIS | ||
| 9 | -------- | ||
| 10 | [verse] | ||
| 11 | -- | ||
| 12 | *#include <event-parse.h>* | ||
| 13 | |||
| 14 | Management of tep handler data structure and access of its members: | ||
| 15 | struct tep_handle pass:[*]*tep_alloc*(void); | ||
| 16 | void *tep_free*(struct tep_handle pass:[*]_tep_); | ||
| 17 | void *tep_ref*(struct tep_handle pass:[*]_tep_); | ||
| 18 | void *tep_unref*(struct tep_handle pass:[*]_tep_); | ||
| 19 | int *tep_ref_get*(struct tep_handle pass:[*]_tep_); | ||
| 20 | void *tep_set_flag*(struct tep_handle pass:[*]_tep_, enum tep_flag _flag_); | ||
| 21 | void *tep_clear_flag*(struct tep_handle pass:[*]_tep_, enum tep_flag _flag_); | ||
| 22 | bool *tep_test_flag*(struct tep_handle pass:[*]_tep_, enum tep_flag _flags_); | ||
| 23 | int *tep_get_cpus*(struct tep_handle pass:[*]_tep_); | ||
| 24 | void *tep_set_cpus*(struct tep_handle pass:[*]_tep_, int _cpus_); | ||
| 25 | int *tep_get_long_size*(strucqt tep_handle pass:[*]_tep_); | ||
| 26 | void *tep_set_long_size*(struct tep_handle pass:[*]_tep_, int _long_size_); | ||
| 27 | int *tep_get_page_size*(struct tep_handle pass:[*]_tep_); | ||
| 28 | void *tep_set_page_size*(struct tep_handle pass:[*]_tep_, int _page_size_); | ||
| 29 | bool *tep_is_latency_format*(struct tep_handle pass:[*]_tep_); | ||
| 30 | void *tep_set_latency_format*(struct tep_handle pass:[*]_tep_, int _lat_); | ||
| 31 | int *tep_get_header_page_size*(struct tep_handle pass:[*]_tep_); | ||
| 32 | int *tep_get_header_timestamp_size*(struct tep_handle pass:[*]_tep_); | ||
| 33 | bool *tep_is_old_format*(struct tep_handle pass:[*]_tep_); | ||
| 34 | int *tep_strerror*(struct tep_handle pass:[*]_tep_, enum tep_errno _errnum_, char pass:[*]_buf_, size_t _buflen_); | ||
| 35 | |||
| 36 | Register / unregister APIs: | ||
| 37 | int *tep_register_trace_clock*(struct tep_handle pass:[*]_tep_, const char pass:[*]_trace_clock_); | ||
| 38 | int *tep_register_function*(struct tep_handle pass:[*]_tep_, char pass:[*]_name_, unsigned long long _addr_, char pass:[*]_mod_); | ||
| 39 | int *tep_register_event_handler*(struct tep_handle pass:[*]_tep_, int _id_, const char pass:[*]_sys_name_, const char pass:[*]_event_name_, tep_event_handler_func _func_, void pass:[*]_context_); | ||
| 40 | int *tep_unregister_event_handler*(struct tep_handle pass:[*]tep, int id, const char pass:[*]sys_name, const char pass:[*]event_name, tep_event_handler_func func, void pass:[*]_context_); | ||
| 41 | int *tep_register_print_string*(struct tep_handle pass:[*]_tep_, const char pass:[*]_fmt_, unsigned long long _addr_); | ||
| 42 | int *tep_register_print_function*(struct tep_handle pass:[*]_tep_, tep_func_handler _func_, enum tep_func_arg_type _ret_type_, char pass:[*]_name_, _..._); | ||
| 43 | int *tep_unregister_print_function*(struct tep_handle pass:[*]_tep_, tep_func_handler _func_, char pass:[*]_name_); | ||
| 44 | |||
| 45 | Plugins management: | ||
| 46 | struct tep_plugin_list pass:[*]*tep_load_plugins*(struct tep_handle pass:[*]_tep_); | ||
| 47 | void *tep_unload_plugins*(struct tep_plugin_list pass:[*]_plugin_list_, struct tep_handle pass:[*]_tep_); | ||
| 48 | char pass:[*]pass:[*]*tep_plugin_list_options*(void); | ||
| 49 | void *tep_plugin_free_options_list*(char pass:[*]pass:[*]_list_); | ||
| 50 | int *tep_plugin_add_options*(const char pass:[*]_name_, struct tep_plugin_option pass:[*]_options_); | ||
| 51 | void *tep_plugin_remove_options*(struct tep_plugin_option pass:[*]_options_); | ||
| 52 | void *tep_print_plugins*(struct trace_seq pass:[*]_s_, const char pass:[*]_prefix_, const char pass:[*]_suffix_, const struct tep_plugin_list pass:[*]_list_); | ||
| 53 | |||
| 54 | Event related APIs: | ||
| 55 | struct tep_event pass:[*]*tep_get_event*(struct tep_handle pass:[*]_tep_, int _index_); | ||
| 56 | struct tep_event pass:[*]*tep_get_first_event*(struct tep_handle pass:[*]_tep_); | ||
| 57 | int *tep_get_events_count*(struct tep_handle pass:[*]_tep_); | ||
| 58 | struct tep_event pass:[*]pass:[*]*tep_list_events*(struct tep_handle pass:[*]_tep_, enum tep_event_sort_type _sort_type_); | ||
| 59 | struct tep_event pass:[*]pass:[*]*tep_list_events_copy*(struct tep_handle pass:[*]_tep_, enum tep_event_sort_type _sort_type_); | ||
| 60 | |||
| 61 | Event printing: | ||
| 62 | void *tep_print_event*(struct tep_handle pass:[*]_tep_, struct trace_seq pass:[*]_s_, struct tep_record pass:[*]_record_, bool _use_trace_clock_); | ||
| 63 | void *tep_print_event_data*(struct tep_handle pass:[*]_tep_, struct trace_seq pass:[*]_s_, struct tep_event pass:[*]_event_, struct tep_record pass:[*]_record_); | ||
| 64 | void *tep_event_info*(struct trace_seq pass:[*]_s_, struct tep_event pass:[*]_event_, struct tep_record pass:[*]_record_); | ||
| 65 | void *tep_print_event_task*(struct tep_handle pass:[*]_tep_, struct trace_seq pass:[*]_s_, struct tep_event pass:[*]_event_, struct tep_record pass:[*]_record_); | ||
| 66 | void *tep_print_event_time*(struct tep_handle pass:[*]_tep_, struct trace_seq pass:[*]_s_, struct tep_event pass:[*]_event_, struct tep_record pass:[*]record, bool _use_trace_clock_); | ||
| 67 | void *tep_set_print_raw*(struct tep_handle pass:[*]_tep_, int _print_raw_); | ||
| 68 | |||
| 69 | Event finding: | ||
| 70 | struct tep_event pass:[*]*tep_find_event*(struct tep_handle pass:[*]_tep_, int _id_); | ||
| 71 | struct tep_event pass:[*]*tep_find_event_by_name*(struct tep_handle pass:[*]_tep_, const char pass:[*]_sys_, const char pass:[*]_name_); | ||
| 72 | struct tep_event pass:[*]*tep_find_event_by_record*(struct tep_handle pass:[*]_tep_, struct tep_record pass:[*]_record_); | ||
| 73 | |||
| 74 | Parsing of event files: | ||
| 75 | int *tep_parse_header_page*(struct tep_handle pass:[*]_tep_, char pass:[*]_buf_, unsigned long _size_, int _long_size_); | ||
| 76 | enum tep_errno *tep_parse_event*(struct tep_handle pass:[*]_tep_, const char pass:[*]_buf_, unsigned long _size_, const char pass:[*]_sys_); | ||
| 77 | enum tep_errno *tep_parse_format*(struct tep_handle pass:[*]_tep_, struct tep_event pass:[*]pass:[*]_eventp_, const char pass:[*]_buf_, unsigned long _size_, const char pass:[*]_sys_); | ||
| 78 | |||
| 79 | APIs related to fields from event's format files: | ||
| 80 | struct tep_format_field pass:[*]pass:[*]*tep_event_common_fields*(struct tep_event pass:[*]_event_); | ||
| 81 | struct tep_format_field pass:[*]pass:[*]*tep_event_fields*(struct tep_event pass:[*]_event_); | ||
| 82 | void pass:[*]*tep_get_field_raw*(struct trace_seq pass:[*]_s_, struct tep_event pass:[*]_event_, const char pass:[*]_name_, struct tep_record pass:[*]_record_, int pass:[*]_len_, int _err_); | ||
| 83 | int *tep_get_field_val*(struct trace_seq pass:[*]_s_, struct tep_event pass:[*]_event_, const char pass:[*]_name_, struct tep_record pass:[*]_record_, unsigned long long pass:[*]_val_, int _err_); | ||
| 84 | int *tep_get_common_field_val*(struct trace_seq pass:[*]_s_, struct tep_event pass:[*]_event_, const char pass:[*]_name_, struct tep_record pass:[*]_record_, unsigned long long pass:[*]_val_, int _err_); | ||
| 85 | int *tep_get_any_field_val*(struct trace_seq pass:[*]_s_, struct tep_event pass:[*]_event_, const char pass:[*]_name_, struct tep_record pass:[*]_record_, unsigned long long pass:[*]_val_, int _err_); | ||
| 86 | int *tep_read_number_field*(struct tep_format_field pass:[*]_field_, const void pass:[*]_data_, unsigned long long pass:[*]_value_); | ||
| 87 | |||
| 88 | Event fields printing: | ||
| 89 | void *tep_print_field*(struct trace_seq pass:[*]_s_, void pass:[*]_data_, struct tep_format_field pass:[*]_field_); | ||
| 90 | void *tep_print_fields*(struct trace_seq pass:[*]_s_, void pass:[*]_data_, int _size_, struct tep_event pass:[*]_event_); | ||
| 91 | int *tep_print_num_field*(struct trace_seq pass:[*]_s_, const char pass:[*]_fmt_, struct tep_event pass:[*]_event_, const char pass:[*]_name_, struct tep_record pass:[*]_record_, int _err_); | ||
| 92 | int *tep_print_func_field*(struct trace_seq pass:[*]_s_, const char pass:[*]_fmt_, struct tep_event pass:[*]_event_, const char pass:[*]_name_, struct tep_record pass:[*]_record_, int _err_); | ||
| 93 | |||
| 94 | Event fields finding: | ||
| 95 | struct tep_format_field pass:[*]*tep_find_common_field*(struct tep_event pass:[*]_event_, const char pass:[*]_name_); | ||
| 96 | struct tep_format_field pass:[*]*tep_find_field*(struct tep_event_ormat pass:[*]_event_, const char pass:[*]_name_); | ||
| 97 | struct tep_format_field pass:[*]*tep_find_any_field*(struct tep_event pass:[*]_event_, const char pass:[*]_name_); | ||
| 98 | |||
| 99 | Functions resolver: | ||
| 100 | int *tep_set_function_resolver*(struct tep_handle pass:[*]_tep_, tep_func_resolver_t pass:[*]_func_, void pass:[*]_priv_); | ||
| 101 | void *tep_reset_function_resolver*(struct tep_handle pass:[*]_tep_); | ||
| 102 | const char pass:[*]*tep_find_function*(struct tep_handle pass:[*]_tep_, unsigned long long _addr_); | ||
| 103 | unsigned long long *tep_find_function_address*(struct tep_handle pass:[*]_tep_, unsigned long long _addr_); | ||
| 104 | |||
| 105 | Filter management: | ||
| 106 | struct tep_event_filter pass:[*]*tep_filter_alloc*(struct tep_handle pass:[*]_tep_); | ||
| 107 | enum tep_errno *tep_filter_add_filter_str*(struct tep_event_filter pass:[*]_filter_, const char pass:[*]_filter_str_); | ||
| 108 | enum tep_errno *tep_filter_match*(struct tep_event_filter pass:[*]_filter_, struct tep_record pass:[*]_record_); | ||
| 109 | int *tep_filter_strerror*(struct tep_event_filter pass:[*]_filter_, enum tep_errno _err_, char pass:[*]buf, size_t _buflen_); | ||
| 110 | int *tep_event_filtered*(struct tep_event_filter pass:[*]_filter_, int _event_id_); | ||
| 111 | void *tep_filter_reset*(struct tep_event_filter pass:[*]_filter_); | ||
| 112 | void *tep_filter_free*(struct tep_event_filter pass:[*]_filter_); | ||
| 113 | char pass:[*]*tep_filter_make_string*(struct tep_event_filter pass:[*]_filter_, int _event_id_); | ||
| 114 | int *tep_filter_remove_event*(struct tep_event_filter pass:[*]_filter_, int _event_id_); | ||
| 115 | int *tep_filter_copy*(struct tep_event_filter pass:[*]_dest_, struct tep_event_filter pass:[*]_source_); | ||
| 116 | int *tep_filter_compare*(struct tep_event_filter pass:[*]_filter1_, struct tep_event_filter pass:[*]_filter2_); | ||
| 117 | |||
| 118 | Parsing various data from the records: | ||
| 119 | void *tep_data_latency_format*(struct tep_handle pass:[*]_tep_, struct trace_seq pass:[*]_s_, struct tep_record pass:[*]_record_); | ||
| 120 | int *tep_data_type*(struct tep_handle pass:[*]_tep_, struct tep_record pass:[*]_rec_); | ||
| 121 | int *tep_data_pid*(struct tep_handle pass:[*]_tep_, struct tep_record pass:[*]_rec_); | ||
| 122 | int *tep_data_preempt_count*(struct tep_handle pass:[*]_tep_, struct tep_record pass:[*]_rec_); | ||
| 123 | int *tep_data_flags*(struct tep_handle pass:[*]_tep_, struct tep_record pass:[*]_rec_); | ||
| 124 | |||
| 125 | Command and task related APIs: | ||
| 126 | const char pass:[*]*tep_data_comm_from_pid*(struct tep_handle pass:[*]_tep_, int _pid_); | ||
| 127 | struct cmdline pass:[*]*tep_data_pid_from_comm*(struct tep_handle pass:[*]_tep_, const char pass:[*]_comm_, struct cmdline pass:[*]_next_); | ||
| 128 | int *tep_register_comm*(struct tep_handle pass:[*]_tep_, const char pass:[*]_comm_, int _pid_); | ||
| 129 | int *tep_override_comm*(struct tep_handle pass:[*]_tep_, const char pass:[*]_comm_, int _pid_); | ||
| 130 | bool *tep_is_pid_registered*(struct tep_handle pass:[*]_tep_, int _pid_); | ||
| 131 | int *tep_cmdline_pid*(struct tep_handle pass:[*]_tep_, struct cmdline pass:[*]_cmdline_); | ||
| 132 | |||
| 133 | Endian related APIs: | ||
| 134 | int *tep_is_bigendian*(void); | ||
| 135 | unsigned long long *tep_read_number*(struct tep_handle pass:[*]_tep_, const void pass:[*]_ptr_, int _size_); | ||
| 136 | bool *tep_is_file_bigendian*(struct tep_handle pass:[*]_tep_); | ||
| 137 | void *tep_set_file_bigendian*(struct tep_handle pass:[*]_tep_, enum tep_endian _endian_); | ||
| 138 | bool *tep_is_local_bigendian*(struct tep_handle pass:[*]_tep_); | ||
| 139 | void *tep_set_local_bigendian*(struct tep_handle pass:[*]_tep_, enum tep_endian _endian_); | ||
| 140 | |||
| 141 | Trace sequences: | ||
| 142 | *#include <trace-seq.h>* | ||
| 143 | void *trace_seq_init*(struct trace_seq pass:[*]_s_); | ||
| 144 | void *trace_seq_reset*(struct trace_seq pass:[*]_s_); | ||
| 145 | void *trace_seq_destroy*(struct trace_seq pass:[*]_s_); | ||
| 146 | int *trace_seq_printf*(struct trace_seq pass:[*]_s_, const char pass:[*]_fmt_, ...); | ||
| 147 | int *trace_seq_vprintf*(struct trace_seq pass:[*]_s_, const char pass:[*]_fmt_, va_list _args_); | ||
| 148 | int *trace_seq_puts*(struct trace_seq pass:[*]_s_, const char pass:[*]_str_); | ||
| 149 | int *trace_seq_putc*(struct trace_seq pass:[*]_s_, unsigned char _c_); | ||
| 150 | void *trace_seq_terminate*(struct trace_seq pass:[*]_s_); | ||
| 151 | int *trace_seq_do_fprintf*(struct trace_seq pass:[*]_s_, FILE pass:[*]_fp_); | ||
| 152 | int *trace_seq_do_printf*(struct trace_seq pass:[*]_s_); | ||
| 153 | -- | ||
| 154 | |||
| 155 | DESCRIPTION | ||
| 156 | ----------- | ||
| 157 | The libtraceevent(3) library provides APIs to access kernel tracepoint events, | ||
| 158 | located in the tracefs file system under the events directory. | ||
| 159 | |||
| 160 | ENVIRONMENT | ||
| 161 | ----------- | ||
| 162 | [verse] | ||
| 163 | -- | ||
| 164 | TRACEEVENT_PLUGIN_DIR | ||
| 165 | Additional plugin directory. All shared object files, located in this directory will be loaded as traceevent plugins. | ||
| 166 | -- | ||
| 167 | |||
| 168 | FILES | ||
| 169 | ----- | ||
| 170 | [verse] | ||
| 171 | -- | ||
| 172 | *event-parse.h* | ||
| 173 | Header file to include in order to have access to the library APIs. | ||
| 174 | *trace-seq.h* | ||
| 175 | Header file to include in order to have access to trace sequences related APIs. | ||
| 176 | Trace sequences are used to allow a function to call several other functions | ||
| 177 | to create a string of data to use. | ||
| 178 | *-ltraceevent* | ||
| 179 | Linker switch to add when building a program that uses the library. | ||
| 180 | -- | ||
| 181 | |||
| 182 | SEE ALSO | ||
| 183 | -------- | ||
| 184 | _trace-cmd(1)_ | ||
| 185 | |||
| 186 | AUTHOR | ||
| 187 | ------ | ||
| 188 | [verse] | ||
| 189 | -- | ||
| 190 | *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. | ||
| 191 | *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. | ||
| 192 | -- | ||
| 193 | REPORTING BUGS | ||
| 194 | -------------- | ||
| 195 | Report bugs to <linux-trace-devel@vger.kernel.org> | ||
| 196 | |||
| 197 | LICENSE | ||
| 198 | ------- | ||
| 199 | libtraceevent is Free Software licensed under the GNU LGPL 2.1 | ||
| 200 | |||
| 201 | RESOURCES | ||
| 202 | --------- | ||
| 203 | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git | ||
diff --git a/tools/lib/traceevent/Documentation/manpage-1.72.xsl b/tools/lib/traceevent/Documentation/manpage-1.72.xsl new file mode 100644 index 000000000000..b4d315cb8c47 --- /dev/null +++ b/tools/lib/traceevent/Documentation/manpage-1.72.xsl | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | <!-- manpage-1.72.xsl: | ||
| 2 | special settings for manpages rendered from asciidoc+docbook | ||
| 3 | handles peculiarities in docbook-xsl 1.72.0 --> | ||
| 4 | <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" | ||
| 5 | version="1.0"> | ||
| 6 | |||
| 7 | <xsl:import href="manpage-base.xsl"/> | ||
| 8 | |||
| 9 | <!-- these are the special values for the roff control characters | ||
| 10 | needed for docbook-xsl 1.72.0 --> | ||
| 11 | <xsl:param name="git.docbook.backslash">▓</xsl:param> | ||
| 12 | <xsl:param name="git.docbook.dot" >⌂</xsl:param> | ||
| 13 | |||
| 14 | </xsl:stylesheet> | ||
diff --git a/tools/lib/traceevent/Documentation/manpage-base.xsl b/tools/lib/traceevent/Documentation/manpage-base.xsl new file mode 100644 index 000000000000..a264fa616093 --- /dev/null +++ b/tools/lib/traceevent/Documentation/manpage-base.xsl | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | <!-- manpage-base.xsl: | ||
| 2 | special formatting for manpages rendered from asciidoc+docbook --> | ||
| 3 | <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" | ||
| 4 | version="1.0"> | ||
| 5 | |||
| 6 | <!-- these params silence some output from xmlto --> | ||
| 7 | <xsl:param name="man.output.quietly" select="1"/> | ||
| 8 | <xsl:param name="refentry.meta.get.quietly" select="1"/> | ||
| 9 | |||
| 10 | <!-- convert asciidoc callouts to man page format; | ||
| 11 | git.docbook.backslash and git.docbook.dot params | ||
| 12 | must be supplied by another XSL file or other means --> | ||
| 13 | <xsl:template match="co"> | ||
| 14 | <xsl:value-of select="concat( | ||
| 15 | $git.docbook.backslash,'fB(', | ||
| 16 | substring-after(@id,'-'),')', | ||
| 17 | $git.docbook.backslash,'fR')"/> | ||
| 18 | </xsl:template> | ||
| 19 | <xsl:template match="calloutlist"> | ||
| 20 | <xsl:value-of select="$git.docbook.dot"/> | ||
| 21 | <xsl:text>sp </xsl:text> | ||
| 22 | <xsl:apply-templates/> | ||
| 23 | <xsl:text> </xsl:text> | ||
| 24 | </xsl:template> | ||
| 25 | <xsl:template match="callout"> | ||
| 26 | <xsl:value-of select="concat( | ||
| 27 | $git.docbook.backslash,'fB', | ||
| 28 | substring-after(@arearefs,'-'), | ||
| 29 | '. ',$git.docbook.backslash,'fR')"/> | ||
| 30 | <xsl:apply-templates/> | ||
| 31 | <xsl:value-of select="$git.docbook.dot"/> | ||
| 32 | <xsl:text>br </xsl:text> | ||
| 33 | </xsl:template> | ||
| 34 | |||
| 35 | </xsl:stylesheet> | ||
diff --git a/tools/lib/traceevent/Documentation/manpage-bold-literal.xsl b/tools/lib/traceevent/Documentation/manpage-bold-literal.xsl new file mode 100644 index 000000000000..608eb5df6281 --- /dev/null +++ b/tools/lib/traceevent/Documentation/manpage-bold-literal.xsl | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | <!-- manpage-bold-literal.xsl: | ||
| 2 | special formatting for manpages rendered from asciidoc+docbook --> | ||
| 3 | <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" | ||
| 4 | version="1.0"> | ||
| 5 | |||
| 6 | <!-- render literal text as bold (instead of plain or monospace); | ||
| 7 | this makes literal text easier to distinguish in manpages | ||
| 8 | viewed on a tty --> | ||
| 9 | <xsl:template match="literal"> | ||
| 10 | <xsl:value-of select="$git.docbook.backslash"/> | ||
| 11 | <xsl:text>fB</xsl:text> | ||
| 12 | <xsl:apply-templates/> | ||
| 13 | <xsl:value-of select="$git.docbook.backslash"/> | ||
| 14 | <xsl:text>fR</xsl:text> | ||
| 15 | </xsl:template> | ||
| 16 | |||
| 17 | </xsl:stylesheet> | ||
diff --git a/tools/lib/traceevent/Documentation/manpage-normal.xsl b/tools/lib/traceevent/Documentation/manpage-normal.xsl new file mode 100644 index 000000000000..a48f5b11f3dc --- /dev/null +++ b/tools/lib/traceevent/Documentation/manpage-normal.xsl | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | <!-- manpage-normal.xsl: | ||
| 2 | special settings for manpages rendered from asciidoc+docbook | ||
| 3 | handles anything we want to keep away from docbook-xsl 1.72.0 --> | ||
| 4 | <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" | ||
| 5 | version="1.0"> | ||
| 6 | |||
| 7 | <xsl:import href="manpage-base.xsl"/> | ||
| 8 | |||
| 9 | <!-- these are the normal values for the roff control characters --> | ||
| 10 | <xsl:param name="git.docbook.backslash">\</xsl:param> | ||
| 11 | <xsl:param name="git.docbook.dot" >.</xsl:param> | ||
| 12 | |||
| 13 | </xsl:stylesheet> | ||
diff --git a/tools/lib/traceevent/Documentation/manpage-suppress-sp.xsl b/tools/lib/traceevent/Documentation/manpage-suppress-sp.xsl new file mode 100644 index 000000000000..a63c7632a87d --- /dev/null +++ b/tools/lib/traceevent/Documentation/manpage-suppress-sp.xsl | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | <!-- manpage-suppress-sp.xsl: | ||
| 2 | special settings for manpages rendered from asciidoc+docbook | ||
| 3 | handles erroneous, inline .sp in manpage output of some | ||
| 4 | versions of docbook-xsl --> | ||
| 5 | <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" | ||
| 6 | version="1.0"> | ||
| 7 | |||
| 8 | <!-- attempt to work around spurious .sp at the tail of the line | ||
| 9 | that some versions of docbook stylesheets seem to add --> | ||
| 10 | <xsl:template match="simpara"> | ||
| 11 | <xsl:variable name="content"> | ||
| 12 | <xsl:apply-templates/> | ||
| 13 | </xsl:variable> | ||
| 14 | <xsl:value-of select="normalize-space($content)"/> | ||
| 15 | <xsl:if test="not(ancestor::authorblurb) and | ||
| 16 | not(ancestor::personblurb)"> | ||
| 17 | <xsl:text> </xsl:text> | ||
| 18 | </xsl:if> | ||
| 19 | </xsl:template> | ||
| 20 | |||
| 21 | </xsl:stylesheet> | ||
diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index 941761d9923d..3292c290654f 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile | |||
| @@ -50,9 +50,13 @@ man_dir = $(prefix)/share/man | |||
| 50 | man_dir_SQ = '$(subst ','\'',$(man_dir))' | 50 | man_dir_SQ = '$(subst ','\'',$(man_dir))' |
| 51 | pkgconfig_dir ?= $(word 1,$(shell $(PKG_CONFIG) \ | 51 | pkgconfig_dir ?= $(word 1,$(shell $(PKG_CONFIG) \ |
| 52 | --variable pc_path pkg-config | tr ":" " ")) | 52 | --variable pc_path pkg-config | tr ":" " ")) |
| 53 | includedir_relative = traceevent | ||
| 54 | includedir = $(prefix)/include/$(includedir_relative) | ||
| 55 | includedir_SQ = '$(subst ','\'',$(includedir))' | ||
| 53 | 56 | ||
| 54 | export man_dir man_dir_SQ INSTALL | 57 | export man_dir man_dir_SQ INSTALL |
| 55 | export DESTDIR DESTDIR_SQ | 58 | export DESTDIR DESTDIR_SQ |
| 59 | export EVENT_PARSE_VERSION | ||
| 56 | 60 | ||
| 57 | set_plugin_dir := 1 | 61 | set_plugin_dir := 1 |
| 58 | 62 | ||
| @@ -279,6 +283,8 @@ define do_install_pkgconfig_file | |||
| 279 | cp -f ${PKG_CONFIG_FILE}.template ${PKG_CONFIG_FILE}; \ | 283 | cp -f ${PKG_CONFIG_FILE}.template ${PKG_CONFIG_FILE}; \ |
| 280 | sed -i "s|INSTALL_PREFIX|${1}|g" ${PKG_CONFIG_FILE}; \ | 284 | sed -i "s|INSTALL_PREFIX|${1}|g" ${PKG_CONFIG_FILE}; \ |
| 281 | sed -i "s|LIB_VERSION|${EVENT_PARSE_VERSION}|g" ${PKG_CONFIG_FILE}; \ | 285 | sed -i "s|LIB_VERSION|${EVENT_PARSE_VERSION}|g" ${PKG_CONFIG_FILE}; \ |
| 286 | sed -i "s|LIB_DIR|${libdir}|g" ${PKG_CONFIG_FILE}; \ | ||
| 287 | sed -i "s|HEADER_DIR|$(includedir)|g" ${PKG_CONFIG_FILE}; \ | ||
| 282 | $(call do_install,$(PKG_CONFIG_FILE),$(pkgconfig_dir),644); \ | 288 | $(call do_install,$(PKG_CONFIG_FILE),$(pkgconfig_dir),644); \ |
| 283 | else \ | 289 | else \ |
| 284 | (echo Failed to locate pkg-config directory) 1>&2; \ | 290 | (echo Failed to locate pkg-config directory) 1>&2; \ |
| @@ -300,10 +306,10 @@ install_pkgconfig: | |||
| 300 | 306 | ||
| 301 | install_headers: | 307 | install_headers: |
| 302 | $(call QUIET_INSTALL, headers) \ | 308 | $(call QUIET_INSTALL, headers) \ |
| 303 | $(call do_install,event-parse.h,$(prefix)/include/traceevent,644); \ | 309 | $(call do_install,event-parse.h,$(DESTDIR)$(includedir_SQ),644); \ |
| 304 | $(call do_install,event-utils.h,$(prefix)/include/traceevent,644); \ | 310 | $(call do_install,event-utils.h,$(DESTDIR)$(includedir_SQ),644); \ |
| 305 | $(call do_install,trace-seq.h,$(prefix)/include/traceevent,644); \ | 311 | $(call do_install,trace-seq.h,$(DESTDIR)$(includedir_SQ),644); \ |
| 306 | $(call do_install,kbuffer.h,$(prefix)/include/traceevent,644) | 312 | $(call do_install,kbuffer.h,$(DESTDIR)$(includedir_SQ),644) |
| 307 | 313 | ||
| 308 | install: install_lib | 314 | install: install_lib |
| 309 | 315 | ||
| @@ -313,6 +319,38 @@ clean: | |||
| 313 | $(RM) TRACEEVENT-CFLAGS tags TAGS; \ | 319 | $(RM) TRACEEVENT-CFLAGS tags TAGS; \ |
| 314 | $(RM) $(PKG_CONFIG_FILE) | 320 | $(RM) $(PKG_CONFIG_FILE) |
| 315 | 321 | ||
| 322 | PHONY += doc | ||
| 323 | doc: | ||
| 324 | $(call descend,Documentation) | ||
| 325 | |||
| 326 | PHONY += doc-clean | ||
| 327 | doc-clean: | ||
| 328 | $(call descend,Documentation,clean) | ||
| 329 | |||
| 330 | PHONY += doc-install | ||
| 331 | doc-install: | ||
| 332 | $(call descend,Documentation,install) | ||
| 333 | |||
| 334 | PHONY += doc-uninstall | ||
| 335 | doc-uninstall: | ||
| 336 | $(call descend,Documentation,uninstall) | ||
| 337 | |||
| 338 | PHONY += help | ||
| 339 | help: | ||
| 340 | @echo 'Possible targets:' | ||
| 341 | @echo'' | ||
| 342 | @echo ' all - default, compile the library and the'\ | ||
| 343 | 'plugins' | ||
| 344 | @echo ' plugins - compile the plugins' | ||
| 345 | @echo ' install - install the library, the plugins,'\ | ||
| 346 | 'the header and pkgconfig files' | ||
| 347 | @echo ' clean - clean the library and the plugins object files' | ||
| 348 | @echo ' doc - compile the documentation files - man'\ | ||
| 349 | 'and html pages, in the Documentation directory' | ||
| 350 | @echo ' doc-clean - clean the documentation files' | ||
| 351 | @echo ' doc-install - install the man pages' | ||
| 352 | @echo ' doc-uninstall - uninstall the man pages' | ||
| 353 | @echo'' | ||
| 316 | PHONY += force plugins | 354 | PHONY += force plugins |
| 317 | force: | 355 | force: |
| 318 | 356 | ||
diff --git a/tools/lib/traceevent/libtraceevent.pc.template b/tools/lib/traceevent/libtraceevent.pc.template index 42e4d6cb6b9e..86384fcd57f1 100644 --- a/tools/lib/traceevent/libtraceevent.pc.template +++ b/tools/lib/traceevent/libtraceevent.pc.template | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | prefix=INSTALL_PREFIX | 1 | prefix=INSTALL_PREFIX |
| 2 | libdir=${prefix}/lib64 | 2 | libdir=LIB_DIR |
| 3 | includedir=${prefix}/include/traceevent | 3 | includedir=HEADER_DIR |
| 4 | 4 | ||
| 5 | Name: libtraceevent | 5 | Name: libtraceevent |
| 6 | URL: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git | 6 | URL: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git |
diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile index 53f8be0f4a1f..88158239622b 100644 --- a/tools/objtool/Makefile +++ b/tools/objtool/Makefile | |||
| @@ -7,11 +7,12 @@ ARCH := x86 | |||
| 7 | endif | 7 | endif |
| 8 | 8 | ||
| 9 | # always use the host compiler | 9 | # always use the host compiler |
| 10 | HOSTAR ?= ar | ||
| 10 | HOSTCC ?= gcc | 11 | HOSTCC ?= gcc |
| 11 | HOSTLD ?= ld | 12 | HOSTLD ?= ld |
| 13 | AR = $(HOSTAR) | ||
| 12 | CC = $(HOSTCC) | 14 | CC = $(HOSTCC) |
| 13 | LD = $(HOSTLD) | 15 | LD = $(HOSTLD) |
| 14 | AR = ar | ||
| 15 | 16 | ||
| 16 | ifeq ($(srctree),) | 17 | ifeq ($(srctree),) |
| 17 | srctree := $(patsubst %/,%,$(dir $(CURDIR))) | 18 | srctree := $(patsubst %/,%,$(dir $(CURDIR))) |
diff --git a/tools/pci/Makefile b/tools/pci/Makefile index 9b7534457060..6876ee4bd78c 100644 --- a/tools/pci/Makefile +++ b/tools/pci/Makefile | |||
| @@ -47,7 +47,7 @@ clean: | |||
| 47 | 47 | ||
| 48 | install: $(ALL_PROGRAMS) | 48 | install: $(ALL_PROGRAMS) |
| 49 | install -d -m 755 $(DESTDIR)$(bindir); \ | 49 | install -d -m 755 $(DESTDIR)$(bindir); \ |
| 50 | for program in $(ALL_PROGRAMS); do \ | 50 | for program in $(ALL_PROGRAMS) pcitest.sh; do \ |
| 51 | install $$program $(DESTDIR)$(bindir); \ | 51 | install $$program $(DESTDIR)$(bindir); \ |
| 52 | done; \ | 52 | done; \ |
| 53 | for script in $(ALL_SCRIPTS); do \ | 53 | for script in $(ALL_SCRIPTS); do \ |
diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt index 138fb6e94b3c..18ed1b0fceb3 100644 --- a/tools/perf/Documentation/perf-list.txt +++ b/tools/perf/Documentation/perf-list.txt | |||
| @@ -199,6 +199,18 @@ also be supplied. For example: | |||
| 199 | 199 | ||
| 200 | perf stat -C 0 -e 'hv_gpci/dtbp_ptitc,phys_processor_idx=0x2/' ... | 200 | perf stat -C 0 -e 'hv_gpci/dtbp_ptitc,phys_processor_idx=0x2/' ... |
| 201 | 201 | ||
| 202 | EVENT QUALIFIERS: | ||
| 203 | |||
| 204 | It is also possible to add extra qualifiers to an event: | ||
| 205 | |||
| 206 | percore: | ||
| 207 | |||
| 208 | Sums up the event counts for all hardware threads in a core, e.g.: | ||
| 209 | |||
| 210 | |||
| 211 | perf stat -e cpu/event=0,umask=0x3,percore=1/ | ||
| 212 | |||
| 213 | |||
| 202 | EVENT GROUPS | 214 | EVENT GROUPS |
| 203 | ------------ | 215 | ------------ |
| 204 | 216 | ||
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt index 58986f4cc190..de269430720a 100644 --- a/tools/perf/Documentation/perf-record.txt +++ b/tools/perf/Documentation/perf-record.txt | |||
| @@ -406,7 +406,8 @@ symbolic names, e.g. on x86, ax, si. To list the available registers use | |||
| 406 | --intr-regs=ax,bx. The list of register is architecture dependent. | 406 | --intr-regs=ax,bx. The list of register is architecture dependent. |
| 407 | 407 | ||
| 408 | --user-regs:: | 408 | --user-regs:: |
| 409 | Capture user registers at sample time. Same arguments as -I. | 409 | Similar to -I, but capture user registers at sample time. To list the available |
| 410 | user registers use --user-regs=\?. | ||
| 410 | 411 | ||
| 411 | --running-time:: | 412 | --running-time:: |
| 412 | Record running and enabled time for read events (:S) | 413 | Record running and enabled time for read events (:S) |
| @@ -478,6 +479,11 @@ Also at some cases executing less output write syscalls with bigger data size | |||
| 478 | can take less time than executing more output write syscalls with smaller data | 479 | can take less time than executing more output write syscalls with smaller data |
| 479 | size thus lowering runtime profiling overhead. | 480 | size thus lowering runtime profiling overhead. |
| 480 | 481 | ||
| 482 | -z:: | ||
| 483 | --compression-level[=n]:: | ||
| 484 | Produce compressed trace using specified level n (default: 1 - fastest compression, | ||
| 485 | 22 - smallest trace) | ||
| 486 | |||
| 481 | --all-kernel:: | 487 | --all-kernel:: |
| 482 | Configure all used events to run in kernel space. | 488 | Configure all used events to run in kernel space. |
| 483 | 489 | ||
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt index 39c05f89104e..1e312c2672e4 100644 --- a/tools/perf/Documentation/perf-stat.txt +++ b/tools/perf/Documentation/perf-stat.txt | |||
| @@ -43,6 +43,10 @@ report:: | |||
| 43 | param1 and param2 are defined as formats for the PMU in | 43 | param1 and param2 are defined as formats for the PMU in |
| 44 | /sys/bus/event_source/devices/<pmu>/format/* | 44 | /sys/bus/event_source/devices/<pmu>/format/* |
| 45 | 45 | ||
| 46 | 'percore' is a event qualifier that sums up the event counts for both | ||
| 47 | hardware threads in a core. For example: | ||
| 48 | perf stat -A -a -e cpu/event,percore=1/,otherevent ... | ||
| 49 | |||
| 46 | - a symbolically formed event like 'pmu/config=M,config1=N,config2=K/' | 50 | - a symbolically formed event like 'pmu/config=M,config1=N,config2=K/' |
| 47 | where M, N, K are numbers (in decimal, hex, octal format). | 51 | where M, N, K are numbers (in decimal, hex, octal format). |
| 48 | Acceptable values for each of 'config', 'config1' and 'config2' | 52 | Acceptable values for each of 'config', 'config1' and 'config2' |
diff --git a/tools/perf/Documentation/perf.data-file-format.txt b/tools/perf/Documentation/perf.data-file-format.txt index 593ef49b273c..6967e9b02be5 100644 --- a/tools/perf/Documentation/perf.data-file-format.txt +++ b/tools/perf/Documentation/perf.data-file-format.txt | |||
| @@ -272,6 +272,19 @@ struct { | |||
| 272 | 272 | ||
| 273 | Two uint64_t for the time of first sample and the time of last sample. | 273 | Two uint64_t for the time of first sample and the time of last sample. |
| 274 | 274 | ||
| 275 | HEADER_COMPRESSED = 27, | ||
| 276 | |||
| 277 | struct { | ||
| 278 | u32 version; | ||
| 279 | u32 type; | ||
| 280 | u32 level; | ||
| 281 | u32 ratio; | ||
| 282 | u32 mmap_len; | ||
| 283 | }; | ||
| 284 | |||
| 285 | Indicates that trace contains records of PERF_RECORD_COMPRESSED type | ||
| 286 | that have perf_events records in compressed form. | ||
| 287 | |||
| 275 | other bits are reserved and should ignored for now | 288 | other bits are reserved and should ignored for now |
| 276 | HEADER_FEAT_BITS = 256, | 289 | HEADER_FEAT_BITS = 256, |
| 277 | 290 | ||
| @@ -437,6 +450,17 @@ struct auxtrace_error_event { | |||
| 437 | Describes a header feature. These are records used in pipe-mode that | 450 | Describes a header feature. These are records used in pipe-mode that |
| 438 | contain information that otherwise would be in perf.data file's header. | 451 | contain information that otherwise would be in perf.data file's header. |
| 439 | 452 | ||
| 453 | PERF_RECORD_COMPRESSED = 81, | ||
| 454 | |||
| 455 | struct compressed_event { | ||
| 456 | struct perf_event_header header; | ||
| 457 | char data[]; | ||
| 458 | }; | ||
| 459 | |||
| 460 | The header is followed by compressed data frame that can be decompressed | ||
| 461 | into array of perf trace records. The size of the entire compressed event | ||
| 462 | record including the header is limited by the max value of header.size. | ||
| 463 | |||
| 440 | Event types | 464 | Event types |
| 441 | 465 | ||
| 442 | Define the event attributes with their IDs. | 466 | Define the event attributes with their IDs. |
diff --git a/tools/perf/Documentation/perf.txt b/tools/perf/Documentation/perf.txt index 864e37597252..401f0ed67439 100644 --- a/tools/perf/Documentation/perf.txt +++ b/tools/perf/Documentation/perf.txt | |||
| @@ -22,6 +22,8 @@ OPTIONS | |||
| 22 | verbose - general debug messages | 22 | verbose - general debug messages |
| 23 | ordered-events - ordered events object debug messages | 23 | ordered-events - ordered events object debug messages |
| 24 | data-convert - data convert command debug messages | 24 | data-convert - data convert command debug messages |
| 25 | stderr - write debug output (option -v) to stderr | ||
| 26 | in browser mode | ||
| 25 | 27 | ||
| 26 | --buildid-dir:: | 28 | --buildid-dir:: |
| 27 | Setup buildid cache directory. It has higher priority than | 29 | Setup buildid cache directory. It has higher priority than |
diff --git a/tools/perf/arch/x86/include/perf_regs.h b/tools/perf/arch/x86/include/perf_regs.h index 7f6d538f8a89..b7cd91a9014f 100644 --- a/tools/perf/arch/x86/include/perf_regs.h +++ b/tools/perf/arch/x86/include/perf_regs.h | |||
| @@ -8,9 +8,10 @@ | |||
| 8 | 8 | ||
| 9 | void perf_regs_load(u64 *regs); | 9 | void perf_regs_load(u64 *regs); |
| 10 | 10 | ||
| 11 | #define PERF_REGS_MAX PERF_REG_X86_XMM_MAX | ||
| 12 | #define PERF_XMM_REGS_MASK (~((1ULL << PERF_REG_X86_XMM0) - 1)) | ||
| 11 | #ifndef HAVE_ARCH_X86_64_SUPPORT | 13 | #ifndef HAVE_ARCH_X86_64_SUPPORT |
| 12 | #define PERF_REGS_MASK ((1ULL << PERF_REG_X86_32_MAX) - 1) | 14 | #define PERF_REGS_MASK ((1ULL << PERF_REG_X86_32_MAX) - 1) |
| 13 | #define PERF_REGS_MAX PERF_REG_X86_32_MAX | ||
| 14 | #define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_32 | 15 | #define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_32 |
| 15 | #else | 16 | #else |
| 16 | #define REG_NOSUPPORT ((1ULL << PERF_REG_X86_DS) | \ | 17 | #define REG_NOSUPPORT ((1ULL << PERF_REG_X86_DS) | \ |
| @@ -18,7 +19,6 @@ void perf_regs_load(u64 *regs); | |||
| 18 | (1ULL << PERF_REG_X86_FS) | \ | 19 | (1ULL << PERF_REG_X86_FS) | \ |
| 19 | (1ULL << PERF_REG_X86_GS)) | 20 | (1ULL << PERF_REG_X86_GS)) |
| 20 | #define PERF_REGS_MASK (((1ULL << PERF_REG_X86_64_MAX) - 1) & ~REG_NOSUPPORT) | 21 | #define PERF_REGS_MASK (((1ULL << PERF_REG_X86_64_MAX) - 1) & ~REG_NOSUPPORT) |
| 21 | #define PERF_REGS_MAX PERF_REG_X86_64_MAX | ||
| 22 | #define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_64 | 22 | #define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_64 |
| 23 | #endif | 23 | #endif |
| 24 | #define PERF_REG_IP PERF_REG_X86_IP | 24 | #define PERF_REG_IP PERF_REG_X86_IP |
| @@ -77,6 +77,28 @@ static inline const char *perf_reg_name(int id) | |||
| 77 | case PERF_REG_X86_R15: | 77 | case PERF_REG_X86_R15: |
| 78 | return "R15"; | 78 | return "R15"; |
| 79 | #endif /* HAVE_ARCH_X86_64_SUPPORT */ | 79 | #endif /* HAVE_ARCH_X86_64_SUPPORT */ |
| 80 | |||
| 81 | #define XMM(x) \ | ||
| 82 | case PERF_REG_X86_XMM ## x: \ | ||
| 83 | case PERF_REG_X86_XMM ## x + 1: \ | ||
| 84 | return "XMM" #x; | ||
| 85 | XMM(0) | ||
| 86 | XMM(1) | ||
| 87 | XMM(2) | ||
| 88 | XMM(3) | ||
| 89 | XMM(4) | ||
| 90 | XMM(5) | ||
| 91 | XMM(6) | ||
| 92 | XMM(7) | ||
| 93 | XMM(8) | ||
| 94 | XMM(9) | ||
| 95 | XMM(10) | ||
| 96 | XMM(11) | ||
| 97 | XMM(12) | ||
| 98 | XMM(13) | ||
| 99 | XMM(14) | ||
| 100 | XMM(15) | ||
| 101 | #undef XMM | ||
| 80 | default: | 102 | default: |
| 81 | return NULL; | 103 | return NULL; |
| 82 | } | 104 | } |
diff --git a/tools/perf/arch/x86/util/perf_regs.c b/tools/perf/arch/x86/util/perf_regs.c index fead6b3b4206..7886ca5263e3 100644 --- a/tools/perf/arch/x86/util/perf_regs.c +++ b/tools/perf/arch/x86/util/perf_regs.c | |||
| @@ -31,6 +31,22 @@ const struct sample_reg sample_reg_masks[] = { | |||
| 31 | SMPL_REG(R14, PERF_REG_X86_R14), | 31 | SMPL_REG(R14, PERF_REG_X86_R14), |
| 32 | SMPL_REG(R15, PERF_REG_X86_R15), | 32 | SMPL_REG(R15, PERF_REG_X86_R15), |
| 33 | #endif | 33 | #endif |
| 34 | SMPL_REG2(XMM0, PERF_REG_X86_XMM0), | ||
| 35 | SMPL_REG2(XMM1, PERF_REG_X86_XMM1), | ||
| 36 | SMPL_REG2(XMM2, PERF_REG_X86_XMM2), | ||
| 37 | SMPL_REG2(XMM3, PERF_REG_X86_XMM3), | ||
| 38 | SMPL_REG2(XMM4, PERF_REG_X86_XMM4), | ||
| 39 | SMPL_REG2(XMM5, PERF_REG_X86_XMM5), | ||
| 40 | SMPL_REG2(XMM6, PERF_REG_X86_XMM6), | ||
| 41 | SMPL_REG2(XMM7, PERF_REG_X86_XMM7), | ||
| 42 | SMPL_REG2(XMM8, PERF_REG_X86_XMM8), | ||
| 43 | SMPL_REG2(XMM9, PERF_REG_X86_XMM9), | ||
| 44 | SMPL_REG2(XMM10, PERF_REG_X86_XMM10), | ||
| 45 | SMPL_REG2(XMM11, PERF_REG_X86_XMM11), | ||
| 46 | SMPL_REG2(XMM12, PERF_REG_X86_XMM12), | ||
| 47 | SMPL_REG2(XMM13, PERF_REG_X86_XMM13), | ||
| 48 | SMPL_REG2(XMM14, PERF_REG_X86_XMM14), | ||
| 49 | SMPL_REG2(XMM15, PERF_REG_X86_XMM15), | ||
| 34 | SMPL_REG_END | 50 | SMPL_REG_END |
| 35 | }; | 51 | }; |
| 36 | 52 | ||
| @@ -254,3 +270,31 @@ int arch_sdt_arg_parse_op(char *old_op, char **new_op) | |||
| 254 | 270 | ||
| 255 | return SDT_ARG_VALID; | 271 | return SDT_ARG_VALID; |
| 256 | } | 272 | } |
| 273 | |||
| 274 | uint64_t arch__intr_reg_mask(void) | ||
| 275 | { | ||
| 276 | struct perf_event_attr attr = { | ||
| 277 | .type = PERF_TYPE_HARDWARE, | ||
| 278 | .config = PERF_COUNT_HW_CPU_CYCLES, | ||
| 279 | .sample_type = PERF_SAMPLE_REGS_INTR, | ||
| 280 | .sample_regs_intr = PERF_XMM_REGS_MASK, | ||
| 281 | .precise_ip = 1, | ||
| 282 | .disabled = 1, | ||
| 283 | .exclude_kernel = 1, | ||
| 284 | }; | ||
| 285 | int fd; | ||
| 286 | /* | ||
| 287 | * In an unnamed union, init it here to build on older gcc versions | ||
| 288 | */ | ||
| 289 | attr.sample_period = 1; | ||
| 290 | |||
| 291 | event_attr_init(&attr); | ||
| 292 | |||
| 293 | fd = sys_perf_event_open(&attr, 0, -1, -1, 0); | ||
| 294 | if (fd != -1) { | ||
| 295 | close(fd); | ||
| 296 | return (PERF_XMM_REGS_MASK | PERF_REGS_MASK); | ||
| 297 | } | ||
| 298 | |||
| 299 | return PERF_REGS_MASK; | ||
| 300 | } | ||
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 67f9d9ffacfb..77deb3a40596 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
| @@ -159,8 +159,6 @@ static int hist_iter__branch_callback(struct hist_entry_iter *iter, | |||
| 159 | struct perf_evsel *evsel = iter->evsel; | 159 | struct perf_evsel *evsel = iter->evsel; |
| 160 | int err; | 160 | int err; |
| 161 | 161 | ||
| 162 | hist__account_cycles(sample->branch_stack, al, sample, false); | ||
| 163 | |||
| 164 | bi = he->branch_info; | 162 | bi = he->branch_info; |
| 165 | err = addr_map_symbol__inc_samples(&bi->from, sample, evsel); | 163 | err = addr_map_symbol__inc_samples(&bi->from, sample, evsel); |
| 166 | 164 | ||
| @@ -199,6 +197,8 @@ static int process_branch_callback(struct perf_evsel *evsel, | |||
| 199 | if (a.map != NULL) | 197 | if (a.map != NULL) |
| 200 | a.map->dso->hit = 1; | 198 | a.map->dso->hit = 1; |
| 201 | 199 | ||
| 200 | hist__account_cycles(sample->branch_stack, al, sample, false); | ||
| 201 | |||
| 202 | ret = hist_entry_iter__add(&iter, &a, PERF_MAX_STACK_DEPTH, ann); | 202 | ret = hist_entry_iter__add(&iter, &a, PERF_MAX_STACK_DEPTH, ann); |
| 203 | return ret; | 203 | return ret; |
| 204 | } | 204 | } |
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index 24086b7f1b14..8e0e06d3edfc 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c | |||
| @@ -837,6 +837,9 @@ int cmd_inject(int argc, const char **argv) | |||
| 837 | if (inject.session == NULL) | 837 | if (inject.session == NULL) |
| 838 | return -1; | 838 | return -1; |
| 839 | 839 | ||
| 840 | if (zstd_init(&(inject.session->zstd_data), 0) < 0) | ||
| 841 | pr_warning("Decompression initialization failed.\n"); | ||
| 842 | |||
| 840 | if (inject.build_ids) { | 843 | if (inject.build_ids) { |
| 841 | /* | 844 | /* |
| 842 | * to make sure the mmap records are ordered correctly | 845 | * to make sure the mmap records are ordered correctly |
| @@ -867,6 +870,7 @@ int cmd_inject(int argc, const char **argv) | |||
| 867 | ret = __cmd_inject(&inject); | 870 | ret = __cmd_inject(&inject); |
| 868 | 871 | ||
| 869 | out_delete: | 872 | out_delete: |
| 873 | zstd_fini(&(inject.session->zstd_data)); | ||
| 870 | perf_session__delete(inject.session); | 874 | perf_session__delete(inject.session); |
| 871 | return ret; | 875 | return ret; |
| 872 | } | 876 | } |
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index c5e10552776a..e2c3a585a61e 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
| @@ -133,6 +133,11 @@ static int record__write(struct record *rec, struct perf_mmap *map __maybe_unuse | |||
| 133 | return 0; | 133 | return 0; |
| 134 | } | 134 | } |
| 135 | 135 | ||
| 136 | static int record__aio_enabled(struct record *rec); | ||
| 137 | static int record__comp_enabled(struct record *rec); | ||
| 138 | static size_t zstd_compress(struct perf_session *session, void *dst, size_t dst_size, | ||
| 139 | void *src, size_t src_size); | ||
| 140 | |||
| 136 | #ifdef HAVE_AIO_SUPPORT | 141 | #ifdef HAVE_AIO_SUPPORT |
| 137 | static int record__aio_write(struct aiocb *cblock, int trace_fd, | 142 | static int record__aio_write(struct aiocb *cblock, int trace_fd, |
| 138 | void *buf, size_t size, off_t off) | 143 | void *buf, size_t size, off_t off) |
| @@ -183,9 +188,9 @@ static int record__aio_complete(struct perf_mmap *md, struct aiocb *cblock) | |||
| 183 | if (rem_size == 0) { | 188 | if (rem_size == 0) { |
| 184 | cblock->aio_fildes = -1; | 189 | cblock->aio_fildes = -1; |
| 185 | /* | 190 | /* |
| 186 | * md->refcount is incremented in perf_mmap__push() for | 191 | * md->refcount is incremented in record__aio_pushfn() for |
| 187 | * every enqueued aio write request so decrement it because | 192 | * every aio write request started in record__aio_push() so |
| 188 | * the request is now complete. | 193 | * decrement it because the request is now complete. |
| 189 | */ | 194 | */ |
| 190 | perf_mmap__put(md); | 195 | perf_mmap__put(md); |
| 191 | rc = 1; | 196 | rc = 1; |
| @@ -240,18 +245,89 @@ static int record__aio_sync(struct perf_mmap *md, bool sync_all) | |||
| 240 | } while (1); | 245 | } while (1); |
| 241 | } | 246 | } |
| 242 | 247 | ||
| 243 | static int record__aio_pushfn(void *to, struct aiocb *cblock, void *bf, size_t size, off_t off) | 248 | struct record_aio { |
| 249 | struct record *rec; | ||
| 250 | void *data; | ||
| 251 | size_t size; | ||
| 252 | }; | ||
| 253 | |||
| 254 | static int record__aio_pushfn(struct perf_mmap *map, void *to, void *buf, size_t size) | ||
| 244 | { | 255 | { |
| 245 | struct record *rec = to; | 256 | struct record_aio *aio = to; |
| 246 | int ret, trace_fd = rec->session->data->file.fd; | ||
| 247 | 257 | ||
| 248 | rec->samples++; | 258 | /* |
| 259 | * map->base data pointed by buf is copied into free map->aio.data[] buffer | ||
| 260 | * to release space in the kernel buffer as fast as possible, calling | ||
| 261 | * perf_mmap__consume() from perf_mmap__push() function. | ||
| 262 | * | ||
| 263 | * That lets the kernel to proceed with storing more profiling data into | ||
| 264 | * the kernel buffer earlier than other per-cpu kernel buffers are handled. | ||
| 265 | * | ||
| 266 | * Coping can be done in two steps in case the chunk of profiling data | ||
| 267 | * crosses the upper bound of the kernel buffer. In this case we first move | ||
| 268 | * part of data from map->start till the upper bound and then the reminder | ||
| 269 | * from the beginning of the kernel buffer till the end of the data chunk. | ||
| 270 | */ | ||
| 271 | |||
| 272 | if (record__comp_enabled(aio->rec)) { | ||
| 273 | size = zstd_compress(aio->rec->session, aio->data + aio->size, | ||
| 274 | perf_mmap__mmap_len(map) - aio->size, | ||
| 275 | buf, size); | ||
| 276 | } else { | ||
| 277 | memcpy(aio->data + aio->size, buf, size); | ||
| 278 | } | ||
| 279 | |||
| 280 | if (!aio->size) { | ||
| 281 | /* | ||
| 282 | * Increment map->refcount to guard map->aio.data[] buffer | ||
| 283 | * from premature deallocation because map object can be | ||
| 284 | * released earlier than aio write request started on | ||
| 285 | * map->aio.data[] buffer is complete. | ||
| 286 | * | ||
| 287 | * perf_mmap__put() is done at record__aio_complete() | ||
| 288 | * after started aio request completion or at record__aio_push() | ||
| 289 | * if the request failed to start. | ||
| 290 | */ | ||
| 291 | perf_mmap__get(map); | ||
| 292 | } | ||
| 293 | |||
| 294 | aio->size += size; | ||
| 295 | |||
| 296 | return size; | ||
| 297 | } | ||
| 249 | 298 | ||
| 250 | ret = record__aio_write(cblock, trace_fd, bf, size, off); | 299 | static int record__aio_push(struct record *rec, struct perf_mmap *map, off_t *off) |
| 300 | { | ||
| 301 | int ret, idx; | ||
| 302 | int trace_fd = rec->session->data->file.fd; | ||
| 303 | struct record_aio aio = { .rec = rec, .size = 0 }; | ||
| 304 | |||
| 305 | /* | ||
| 306 | * Call record__aio_sync() to wait till map->aio.data[] buffer | ||
| 307 | * becomes available after previous aio write operation. | ||
| 308 | */ | ||
| 309 | |||
| 310 | idx = record__aio_sync(map, false); | ||
| 311 | aio.data = map->aio.data[idx]; | ||
| 312 | ret = perf_mmap__push(map, &aio, record__aio_pushfn); | ||
| 313 | if (ret != 0) /* ret > 0 - no data, ret < 0 - error */ | ||
| 314 | return ret; | ||
| 315 | |||
| 316 | rec->samples++; | ||
| 317 | ret = record__aio_write(&(map->aio.cblocks[idx]), trace_fd, aio.data, aio.size, *off); | ||
| 251 | if (!ret) { | 318 | if (!ret) { |
| 252 | rec->bytes_written += size; | 319 | *off += aio.size; |
| 320 | rec->bytes_written += aio.size; | ||
| 253 | if (switch_output_size(rec)) | 321 | if (switch_output_size(rec)) |
| 254 | trigger_hit(&switch_output_trigger); | 322 | trigger_hit(&switch_output_trigger); |
| 323 | } else { | ||
| 324 | /* | ||
| 325 | * Decrement map->refcount incremented in record__aio_pushfn() | ||
| 326 | * back if record__aio_write() operation failed to start, otherwise | ||
| 327 | * map->refcount is decremented in record__aio_complete() after | ||
| 328 | * aio write operation finishes successfully. | ||
| 329 | */ | ||
| 330 | perf_mmap__put(map); | ||
| 255 | } | 331 | } |
| 256 | 332 | ||
| 257 | return ret; | 333 | return ret; |
| @@ -273,7 +349,7 @@ static void record__aio_mmap_read_sync(struct record *rec) | |||
| 273 | struct perf_evlist *evlist = rec->evlist; | 349 | struct perf_evlist *evlist = rec->evlist; |
| 274 | struct perf_mmap *maps = evlist->mmap; | 350 | struct perf_mmap *maps = evlist->mmap; |
| 275 | 351 | ||
| 276 | if (!rec->opts.nr_cblocks) | 352 | if (!record__aio_enabled(rec)) |
| 277 | return; | 353 | return; |
| 278 | 354 | ||
| 279 | for (i = 0; i < evlist->nr_mmaps; i++) { | 355 | for (i = 0; i < evlist->nr_mmaps; i++) { |
| @@ -307,13 +383,8 @@ static int record__aio_parse(const struct option *opt, | |||
| 307 | #else /* HAVE_AIO_SUPPORT */ | 383 | #else /* HAVE_AIO_SUPPORT */ |
| 308 | static int nr_cblocks_max = 0; | 384 | static int nr_cblocks_max = 0; |
| 309 | 385 | ||
| 310 | static int record__aio_sync(struct perf_mmap *md __maybe_unused, bool sync_all __maybe_unused) | 386 | static int record__aio_push(struct record *rec __maybe_unused, struct perf_mmap *map __maybe_unused, |
| 311 | { | 387 | off_t *off __maybe_unused) |
| 312 | return -1; | ||
| 313 | } | ||
| 314 | |||
| 315 | static int record__aio_pushfn(void *to __maybe_unused, struct aiocb *cblock __maybe_unused, | ||
| 316 | void *bf __maybe_unused, size_t size __maybe_unused, off_t off __maybe_unused) | ||
| 317 | { | 388 | { |
| 318 | return -1; | 389 | return -1; |
| 319 | } | 390 | } |
| @@ -372,6 +443,32 @@ static int record__mmap_flush_parse(const struct option *opt, | |||
| 372 | return 0; | 443 | return 0; |
| 373 | } | 444 | } |
| 374 | 445 | ||
| 446 | #ifdef HAVE_ZSTD_SUPPORT | ||
| 447 | static unsigned int comp_level_default = 1; | ||
| 448 | |||
| 449 | static int record__parse_comp_level(const struct option *opt, const char *str, int unset) | ||
| 450 | { | ||
| 451 | struct record_opts *opts = opt->value; | ||
| 452 | |||
| 453 | if (unset) { | ||
| 454 | opts->comp_level = 0; | ||
| 455 | } else { | ||
| 456 | if (str) | ||
| 457 | opts->comp_level = strtol(str, NULL, 0); | ||
| 458 | if (!opts->comp_level) | ||
| 459 | opts->comp_level = comp_level_default; | ||
| 460 | } | ||
| 461 | |||
| 462 | return 0; | ||
| 463 | } | ||
| 464 | #endif | ||
| 465 | static unsigned int comp_level_max = 22; | ||
| 466 | |||
| 467 | static int record__comp_enabled(struct record *rec) | ||
| 468 | { | ||
| 469 | return rec->opts.comp_level > 0; | ||
| 470 | } | ||
| 471 | |||
| 375 | static int process_synthesized_event(struct perf_tool *tool, | 472 | static int process_synthesized_event(struct perf_tool *tool, |
| 376 | union perf_event *event, | 473 | union perf_event *event, |
| 377 | struct perf_sample *sample __maybe_unused, | 474 | struct perf_sample *sample __maybe_unused, |
| @@ -385,6 +482,11 @@ static int record__pushfn(struct perf_mmap *map, void *to, void *bf, size_t size | |||
| 385 | { | 482 | { |
| 386 | struct record *rec = to; | 483 | struct record *rec = to; |
| 387 | 484 | ||
| 485 | if (record__comp_enabled(rec)) { | ||
| 486 | size = zstd_compress(rec->session, map->data, perf_mmap__mmap_len(map), bf, size); | ||
| 487 | bf = map->data; | ||
| 488 | } | ||
| 489 | |||
| 388 | rec->samples++; | 490 | rec->samples++; |
| 389 | return record__write(rec, map, bf, size); | 491 | return record__write(rec, map, bf, size); |
| 390 | } | 492 | } |
| @@ -582,7 +684,7 @@ static int record__mmap_evlist(struct record *rec, | |||
| 582 | opts->auxtrace_mmap_pages, | 684 | opts->auxtrace_mmap_pages, |
| 583 | opts->auxtrace_snapshot_mode, | 685 | opts->auxtrace_snapshot_mode, |
| 584 | opts->nr_cblocks, opts->affinity, | 686 | opts->nr_cblocks, opts->affinity, |
| 585 | opts->mmap_flush) < 0) { | 687 | opts->mmap_flush, opts->comp_level) < 0) { |
| 586 | if (errno == EPERM) { | 688 | if (errno == EPERM) { |
| 587 | pr_err("Permission error mapping pages.\n" | 689 | pr_err("Permission error mapping pages.\n" |
| 588 | "Consider increasing " | 690 | "Consider increasing " |
| @@ -771,6 +873,37 @@ static void record__adjust_affinity(struct record *rec, struct perf_mmap *map) | |||
| 771 | } | 873 | } |
| 772 | } | 874 | } |
| 773 | 875 | ||
| 876 | static size_t process_comp_header(void *record, size_t increment) | ||
| 877 | { | ||
| 878 | struct compressed_event *event = record; | ||
| 879 | size_t size = sizeof(*event); | ||
| 880 | |||
| 881 | if (increment) { | ||
| 882 | event->header.size += increment; | ||
| 883 | return increment; | ||
| 884 | } | ||
| 885 | |||
| 886 | event->header.type = PERF_RECORD_COMPRESSED; | ||
| 887 | event->header.size = size; | ||
| 888 | |||
| 889 | return size; | ||
| 890 | } | ||
| 891 | |||
| 892 | static size_t zstd_compress(struct perf_session *session, void *dst, size_t dst_size, | ||
| 893 | void *src, size_t src_size) | ||
| 894 | { | ||
| 895 | size_t compressed; | ||
| 896 | size_t max_record_size = PERF_SAMPLE_MAX_SIZE - sizeof(struct compressed_event) - 1; | ||
| 897 | |||
| 898 | compressed = zstd_compress_stream_to_records(&session->zstd_data, dst, dst_size, src, src_size, | ||
| 899 | max_record_size, process_comp_header); | ||
| 900 | |||
| 901 | session->bytes_transferred += src_size; | ||
| 902 | session->bytes_compressed += compressed; | ||
| 903 | |||
| 904 | return compressed; | ||
| 905 | } | ||
| 906 | |||
| 774 | static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evlist, | 907 | static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evlist, |
| 775 | bool overwrite, bool synch) | 908 | bool overwrite, bool synch) |
| 776 | { | 909 | { |
| @@ -779,7 +912,7 @@ static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evli | |||
| 779 | int rc = 0; | 912 | int rc = 0; |
| 780 | struct perf_mmap *maps; | 913 | struct perf_mmap *maps; |
| 781 | int trace_fd = rec->data.file.fd; | 914 | int trace_fd = rec->data.file.fd; |
| 782 | off_t off; | 915 | off_t off = 0; |
| 783 | 916 | ||
| 784 | if (!evlist) | 917 | if (!evlist) |
| 785 | return 0; | 918 | return 0; |
| @@ -805,20 +938,14 @@ static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evli | |||
| 805 | map->flush = 1; | 938 | map->flush = 1; |
| 806 | } | 939 | } |
| 807 | if (!record__aio_enabled(rec)) { | 940 | if (!record__aio_enabled(rec)) { |
| 808 | if (perf_mmap__push(map, rec, record__pushfn) != 0) { | 941 | if (perf_mmap__push(map, rec, record__pushfn) < 0) { |
| 809 | if (synch) | 942 | if (synch) |
| 810 | map->flush = flush; | 943 | map->flush = flush; |
| 811 | rc = -1; | 944 | rc = -1; |
| 812 | goto out; | 945 | goto out; |
| 813 | } | 946 | } |
| 814 | } else { | 947 | } else { |
| 815 | int idx; | 948 | if (record__aio_push(rec, map, &off) < 0) { |
| 816 | /* | ||
| 817 | * Call record__aio_sync() to wait till map->data buffer | ||
| 818 | * becomes available after previous aio write request. | ||
| 819 | */ | ||
| 820 | idx = record__aio_sync(map, false); | ||
| 821 | if (perf_mmap__aio_push(map, rec, idx, record__aio_pushfn, &off) != 0) { | ||
| 822 | record__aio_set_pos(trace_fd, off); | 949 | record__aio_set_pos(trace_fd, off); |
| 823 | if (synch) | 950 | if (synch) |
| 824 | map->flush = flush; | 951 | map->flush = flush; |
| @@ -888,6 +1015,8 @@ static void record__init_features(struct record *rec) | |||
| 888 | perf_header__clear_feat(&session->header, HEADER_CLOCKID); | 1015 | perf_header__clear_feat(&session->header, HEADER_CLOCKID); |
| 889 | 1016 | ||
| 890 | perf_header__clear_feat(&session->header, HEADER_DIR_FORMAT); | 1017 | perf_header__clear_feat(&session->header, HEADER_DIR_FORMAT); |
| 1018 | if (!record__comp_enabled(rec)) | ||
| 1019 | perf_header__clear_feat(&session->header, HEADER_COMPRESSED); | ||
| 891 | 1020 | ||
| 892 | perf_header__clear_feat(&session->header, HEADER_STAT); | 1021 | perf_header__clear_feat(&session->header, HEADER_STAT); |
| 893 | } | 1022 | } |
| @@ -1186,6 +1315,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) | |||
| 1186 | bool disabled = false, draining = false; | 1315 | bool disabled = false, draining = false; |
| 1187 | struct perf_evlist *sb_evlist = NULL; | 1316 | struct perf_evlist *sb_evlist = NULL; |
| 1188 | int fd; | 1317 | int fd; |
| 1318 | float ratio = 0; | ||
| 1189 | 1319 | ||
| 1190 | atexit(record__sig_exit); | 1320 | atexit(record__sig_exit); |
| 1191 | signal(SIGCHLD, sig_handler); | 1321 | signal(SIGCHLD, sig_handler); |
| @@ -1215,6 +1345,14 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) | |||
| 1215 | fd = perf_data__fd(data); | 1345 | fd = perf_data__fd(data); |
| 1216 | rec->session = session; | 1346 | rec->session = session; |
| 1217 | 1347 | ||
| 1348 | if (zstd_init(&session->zstd_data, rec->opts.comp_level) < 0) { | ||
| 1349 | pr_err("Compression initialization failed.\n"); | ||
| 1350 | return -1; | ||
| 1351 | } | ||
| 1352 | |||
| 1353 | session->header.env.comp_type = PERF_COMP_ZSTD; | ||
| 1354 | session->header.env.comp_level = rec->opts.comp_level; | ||
| 1355 | |||
| 1218 | record__init_features(rec); | 1356 | record__init_features(rec); |
| 1219 | 1357 | ||
| 1220 | if (rec->opts.use_clockid && rec->opts.clockid_res_ns) | 1358 | if (rec->opts.use_clockid && rec->opts.clockid_res_ns) |
| @@ -1244,6 +1382,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) | |||
| 1244 | err = -1; | 1382 | err = -1; |
| 1245 | goto out_child; | 1383 | goto out_child; |
| 1246 | } | 1384 | } |
| 1385 | session->header.env.comp_mmap_len = session->evlist->mmap_len; | ||
| 1247 | 1386 | ||
| 1248 | err = bpf__apply_obj_config(); | 1387 | err = bpf__apply_obj_config(); |
| 1249 | if (err) { | 1388 | if (err) { |
| @@ -1491,6 +1630,11 @@ out_child: | |||
| 1491 | record__mmap_read_all(rec, true); | 1630 | record__mmap_read_all(rec, true); |
| 1492 | record__aio_mmap_read_sync(rec); | 1631 | record__aio_mmap_read_sync(rec); |
| 1493 | 1632 | ||
| 1633 | if (rec->session->bytes_transferred && rec->session->bytes_compressed) { | ||
| 1634 | ratio = (float)rec->session->bytes_transferred/(float)rec->session->bytes_compressed; | ||
| 1635 | session->header.env.comp_ratio = ratio + 0.5; | ||
| 1636 | } | ||
| 1637 | |||
| 1494 | if (forks) { | 1638 | if (forks) { |
| 1495 | int exit_status; | 1639 | int exit_status; |
| 1496 | 1640 | ||
| @@ -1537,12 +1681,19 @@ out_child: | |||
| 1537 | else | 1681 | else |
| 1538 | samples[0] = '\0'; | 1682 | samples[0] = '\0'; |
| 1539 | 1683 | ||
| 1540 | fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s%s ]\n", | 1684 | fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s%s", |
| 1541 | perf_data__size(data) / 1024.0 / 1024.0, | 1685 | perf_data__size(data) / 1024.0 / 1024.0, |
| 1542 | data->path, postfix, samples); | 1686 | data->path, postfix, samples); |
| 1687 | if (ratio) { | ||
| 1688 | fprintf(stderr, ", compressed (original %.3f MB, ratio is %.3f)", | ||
| 1689 | rec->session->bytes_transferred / 1024.0 / 1024.0, | ||
| 1690 | ratio); | ||
| 1691 | } | ||
| 1692 | fprintf(stderr, " ]\n"); | ||
| 1543 | } | 1693 | } |
| 1544 | 1694 | ||
| 1545 | out_delete_session: | 1695 | out_delete_session: |
| 1696 | zstd_fini(&session->zstd_data); | ||
| 1546 | perf_session__delete(session); | 1697 | perf_session__delete(session); |
| 1547 | 1698 | ||
| 1548 | if (!opts->no_bpf_event) | 1699 | if (!opts->no_bpf_event) |
| @@ -2017,10 +2168,10 @@ static struct option __record_options[] = { | |||
| 2017 | "use per-thread mmaps"), | 2168 | "use per-thread mmaps"), |
| 2018 | OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register", | 2169 | OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register", |
| 2019 | "sample selected machine registers on interrupt," | 2170 | "sample selected machine registers on interrupt," |
| 2020 | " use -I ? to list register names", parse_regs), | 2171 | " use '-I?' to list register names", parse_intr_regs), |
| 2021 | OPT_CALLBACK_OPTARG(0, "user-regs", &record.opts.sample_user_regs, NULL, "any register", | 2172 | OPT_CALLBACK_OPTARG(0, "user-regs", &record.opts.sample_user_regs, NULL, "any register", |
| 2022 | "sample selected machine registers on interrupt," | 2173 | "sample selected machine registers on interrupt," |
| 2023 | " use -I ? to list register names", parse_regs), | 2174 | " use '--user-regs=?' to list register names", parse_user_regs), |
| 2024 | OPT_BOOLEAN(0, "running-time", &record.opts.running_time, | 2175 | OPT_BOOLEAN(0, "running-time", &record.opts.running_time, |
| 2025 | "Record running/enabled time of read (:S) events"), | 2176 | "Record running/enabled time of read (:S) events"), |
| 2026 | OPT_CALLBACK('k', "clockid", &record.opts, | 2177 | OPT_CALLBACK('k', "clockid", &record.opts, |
| @@ -2068,6 +2219,11 @@ static struct option __record_options[] = { | |||
| 2068 | OPT_CALLBACK(0, "affinity", &record.opts, "node|cpu", | 2219 | OPT_CALLBACK(0, "affinity", &record.opts, "node|cpu", |
| 2069 | "Set affinity mask of trace reading thread to NUMA node cpu mask or cpu of processed mmap buffer", | 2220 | "Set affinity mask of trace reading thread to NUMA node cpu mask or cpu of processed mmap buffer", |
| 2070 | record__parse_affinity), | 2221 | record__parse_affinity), |
| 2222 | #ifdef HAVE_ZSTD_SUPPORT | ||
| 2223 | OPT_CALLBACK_OPTARG('z', "compression-level", &record.opts, &comp_level_default, | ||
| 2224 | "n", "Compressed records using specified level (default: 1 - fastest compression, 22 - greatest compression)", | ||
| 2225 | record__parse_comp_level), | ||
| 2226 | #endif | ||
| 2071 | OPT_END() | 2227 | OPT_END() |
| 2072 | }; | 2228 | }; |
| 2073 | 2229 | ||
| @@ -2127,6 +2283,12 @@ int cmd_record(int argc, const char **argv) | |||
| 2127 | "cgroup monitoring only available in system-wide mode"); | 2283 | "cgroup monitoring only available in system-wide mode"); |
| 2128 | 2284 | ||
| 2129 | } | 2285 | } |
| 2286 | |||
| 2287 | if (rec->opts.comp_level != 0) { | ||
| 2288 | pr_debug("Compression enabled, disabling build id collection at the end of the session.\n"); | ||
| 2289 | rec->no_buildid = true; | ||
| 2290 | } | ||
| 2291 | |||
| 2130 | if (rec->opts.record_switch_events && | 2292 | if (rec->opts.record_switch_events && |
| 2131 | !perf_can_record_switch_events()) { | 2293 | !perf_can_record_switch_events()) { |
| 2132 | ui__error("kernel does not support recording context switch events\n"); | 2294 | ui__error("kernel does not support recording context switch events\n"); |
| @@ -2272,12 +2434,15 @@ int cmd_record(int argc, const char **argv) | |||
| 2272 | 2434 | ||
| 2273 | if (rec->opts.nr_cblocks > nr_cblocks_max) | 2435 | if (rec->opts.nr_cblocks > nr_cblocks_max) |
| 2274 | rec->opts.nr_cblocks = nr_cblocks_max; | 2436 | rec->opts.nr_cblocks = nr_cblocks_max; |
| 2275 | if (verbose > 0) | 2437 | pr_debug("nr_cblocks: %d\n", rec->opts.nr_cblocks); |
| 2276 | pr_info("nr_cblocks: %d\n", rec->opts.nr_cblocks); | ||
| 2277 | 2438 | ||
| 2278 | pr_debug("affinity: %s\n", affinity_tags[rec->opts.affinity]); | 2439 | pr_debug("affinity: %s\n", affinity_tags[rec->opts.affinity]); |
| 2279 | pr_debug("mmap flush: %d\n", rec->opts.mmap_flush); | 2440 | pr_debug("mmap flush: %d\n", rec->opts.mmap_flush); |
| 2280 | 2441 | ||
| 2442 | if (rec->opts.comp_level > comp_level_max) | ||
| 2443 | rec->opts.comp_level = comp_level_max; | ||
| 2444 | pr_debug("comp level: %d\n", rec->opts.comp_level); | ||
| 2445 | |||
| 2281 | err = __cmd_record(&record, argc, argv); | 2446 | err = __cmd_record(&record, argc, argv); |
| 2282 | out: | 2447 | out: |
| 2283 | perf_evlist__delete(rec->evlist); | 2448 | perf_evlist__delete(rec->evlist); |
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 4054eb1f98ac..1ca533f06a4c 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
| @@ -136,9 +136,6 @@ static int hist_iter__report_callback(struct hist_entry_iter *iter, | |||
| 136 | if (!ui__has_annotation() && !rep->symbol_ipc) | 136 | if (!ui__has_annotation() && !rep->symbol_ipc) |
| 137 | return 0; | 137 | return 0; |
| 138 | 138 | ||
| 139 | hist__account_cycles(sample->branch_stack, al, sample, | ||
| 140 | rep->nonany_branch_mode); | ||
| 141 | |||
| 142 | if (sort__mode == SORT_MODE__BRANCH) { | 139 | if (sort__mode == SORT_MODE__BRANCH) { |
| 143 | bi = he->branch_info; | 140 | bi = he->branch_info; |
| 144 | err = addr_map_symbol__inc_samples(&bi->from, sample, evsel); | 141 | err = addr_map_symbol__inc_samples(&bi->from, sample, evsel); |
| @@ -181,9 +178,6 @@ static int hist_iter__branch_callback(struct hist_entry_iter *iter, | |||
| 181 | if (!ui__has_annotation() && !rep->symbol_ipc) | 178 | if (!ui__has_annotation() && !rep->symbol_ipc) |
| 182 | return 0; | 179 | return 0; |
| 183 | 180 | ||
| 184 | hist__account_cycles(sample->branch_stack, al, sample, | ||
| 185 | rep->nonany_branch_mode); | ||
| 186 | |||
| 187 | bi = he->branch_info; | 181 | bi = he->branch_info; |
| 188 | err = addr_map_symbol__inc_samples(&bi->from, sample, evsel); | 182 | err = addr_map_symbol__inc_samples(&bi->from, sample, evsel); |
| 189 | if (err) | 183 | if (err) |
| @@ -282,6 +276,11 @@ static int process_sample_event(struct perf_tool *tool, | |||
| 282 | if (al.map != NULL) | 276 | if (al.map != NULL) |
| 283 | al.map->dso->hit = 1; | 277 | al.map->dso->hit = 1; |
| 284 | 278 | ||
| 279 | if (ui__has_annotation() || rep->symbol_ipc) { | ||
| 280 | hist__account_cycles(sample->branch_stack, &al, sample, | ||
| 281 | rep->nonany_branch_mode); | ||
| 282 | } | ||
| 283 | |||
| 285 | ret = hist_entry_iter__add(&iter, &al, rep->max_stack, rep); | 284 | ret = hist_entry_iter__add(&iter, &al, rep->max_stack, rep); |
| 286 | if (ret < 0) | 285 | if (ret < 0) |
| 287 | pr_debug("problem adding hist entry, skipping event\n"); | 286 | pr_debug("problem adding hist entry, skipping event\n"); |
| @@ -1259,6 +1258,9 @@ repeat: | |||
| 1259 | if (session == NULL) | 1258 | if (session == NULL) |
| 1260 | return -1; | 1259 | return -1; |
| 1261 | 1260 | ||
| 1261 | if (zstd_init(&(session->zstd_data), 0) < 0) | ||
| 1262 | pr_warning("Decompression initialization failed. Reported data may be incomplete.\n"); | ||
| 1263 | |||
| 1262 | if (report.queue_size) { | 1264 | if (report.queue_size) { |
| 1263 | ordered_events__set_alloc_size(&session->ordered_events, | 1265 | ordered_events__set_alloc_size(&session->ordered_events, |
| 1264 | report.queue_size); | 1266 | report.queue_size); |
| @@ -1449,7 +1451,7 @@ repeat: | |||
| 1449 | error: | 1451 | error: |
| 1450 | if (report.ptime_range) | 1452 | if (report.ptime_range) |
| 1451 | zfree(&report.ptime_range); | 1453 | zfree(&report.ptime_range); |
| 1452 | 1454 | zstd_fini(&(session->zstd_data)); | |
| 1453 | perf_session__delete(session); | 1455 | perf_session__delete(session); |
| 1454 | return ret; | 1456 | return ret; |
| 1455 | } | 1457 | } |
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index a3c060878faa..24b8e690fb69 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c | |||
| @@ -847,6 +847,18 @@ static int perf_stat__get_core_cached(struct perf_stat_config *config, | |||
| 847 | return perf_stat__get_aggr(config, perf_stat__get_core, map, idx); | 847 | return perf_stat__get_aggr(config, perf_stat__get_core, map, idx); |
| 848 | } | 848 | } |
| 849 | 849 | ||
| 850 | static bool term_percore_set(void) | ||
| 851 | { | ||
| 852 | struct perf_evsel *counter; | ||
| 853 | |||
| 854 | evlist__for_each_entry(evsel_list, counter) { | ||
| 855 | if (counter->percore) | ||
| 856 | return true; | ||
| 857 | } | ||
| 858 | |||
| 859 | return false; | ||
| 860 | } | ||
| 861 | |||
| 850 | static int perf_stat_init_aggr_mode(void) | 862 | static int perf_stat_init_aggr_mode(void) |
| 851 | { | 863 | { |
| 852 | int nr; | 864 | int nr; |
| @@ -867,6 +879,15 @@ static int perf_stat_init_aggr_mode(void) | |||
| 867 | stat_config.aggr_get_id = perf_stat__get_core_cached; | 879 | stat_config.aggr_get_id = perf_stat__get_core_cached; |
| 868 | break; | 880 | break; |
| 869 | case AGGR_NONE: | 881 | case AGGR_NONE: |
| 882 | if (term_percore_set()) { | ||
| 883 | if (cpu_map__build_core_map(evsel_list->cpus, | ||
| 884 | &stat_config.aggr_map)) { | ||
| 885 | perror("cannot build core map"); | ||
| 886 | return -1; | ||
| 887 | } | ||
| 888 | stat_config.aggr_get_id = perf_stat__get_core_cached; | ||
| 889 | } | ||
| 890 | break; | ||
| 870 | case AGGR_GLOBAL: | 891 | case AGGR_GLOBAL: |
| 871 | case AGGR_THREAD: | 892 | case AGGR_THREAD: |
| 872 | case AGGR_UNSET: | 893 | case AGGR_UNSET: |
diff --git a/tools/perf/perf.h b/tools/perf/perf.h index 369eae61068d..d59dee61b64d 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h | |||
| @@ -86,6 +86,7 @@ struct record_opts { | |||
| 86 | int nr_cblocks; | 86 | int nr_cblocks; |
| 87 | int affinity; | 87 | int affinity; |
| 88 | int mmap_flush; | 88 | int mmap_flush; |
| 89 | unsigned int comp_level; | ||
| 89 | }; | 90 | }; |
| 90 | 91 | ||
| 91 | enum perf_affinity { | 92 | enum perf_affinity { |
diff --git a/tools/perf/pmu-events/arch/arm64/arm/cortex-a57-a72/core-imp-def.json b/tools/perf/pmu-events/arch/arm64/arm/cortex-a57-a72/core-imp-def.json new file mode 100644 index 000000000000..0ac9b7927450 --- /dev/null +++ b/tools/perf/pmu-events/arch/arm64/arm/cortex-a57-a72/core-imp-def.json | |||
| @@ -0,0 +1,179 @@ | |||
| 1 | [ | ||
| 2 | { | ||
| 3 | "ArchStdEvent": "L1D_CACHE_RD", | ||
| 4 | }, | ||
| 5 | { | ||
| 6 | "ArchStdEvent": "L1D_CACHE_WR", | ||
| 7 | }, | ||
| 8 | { | ||
| 9 | "ArchStdEvent": "L1D_CACHE_REFILL_RD", | ||
| 10 | }, | ||
| 11 | { | ||
| 12 | "ArchStdEvent": "L1D_CACHE_REFILL_WR", | ||
| 13 | }, | ||
| 14 | { | ||
| 15 | "ArchStdEvent": "L1D_CACHE_WB_VICTIM", | ||
| 16 | }, | ||
| 17 | { | ||
| 18 | "ArchStdEvent": "L1D_CACHE_WB_CLEAN", | ||
| 19 | }, | ||
| 20 | { | ||
| 21 | "ArchStdEvent": "L1D_CACHE_INVAL", | ||
| 22 | }, | ||
| 23 | { | ||
| 24 | "ArchStdEvent": "L1D_TLB_REFILL_RD", | ||
| 25 | }, | ||
| 26 | { | ||
| 27 | "ArchStdEvent": "L1D_TLB_REFILL_WR", | ||
| 28 | }, | ||
| 29 | { | ||
| 30 | "ArchStdEvent": "L2D_CACHE_RD", | ||
| 31 | }, | ||
| 32 | { | ||
| 33 | "ArchStdEvent": "L2D_CACHE_WR", | ||
| 34 | }, | ||
| 35 | { | ||
| 36 | "ArchStdEvent": "L2D_CACHE_REFILL_RD", | ||
| 37 | }, | ||
| 38 | { | ||
| 39 | "ArchStdEvent": "L2D_CACHE_REFILL_WR", | ||
| 40 | }, | ||
| 41 | { | ||
| 42 | "ArchStdEvent": "L2D_CACHE_WB_VICTIM", | ||
| 43 | }, | ||
| 44 | { | ||
| 45 | "ArchStdEvent": "L2D_CACHE_WB_CLEAN", | ||
| 46 | }, | ||
| 47 | { | ||
| 48 | "ArchStdEvent": "L2D_CACHE_INVAL", | ||
| 49 | }, | ||
| 50 | { | ||
| 51 | "ArchStdEvent": "BUS_ACCESS_RD", | ||
| 52 | }, | ||
| 53 | { | ||
| 54 | "ArchStdEvent": "BUS_ACCESS_WR", | ||
| 55 | }, | ||
| 56 | { | ||
| 57 | "ArchStdEvent": "BUS_ACCESS_SHARED", | ||
| 58 | }, | ||
| 59 | { | ||
| 60 | "ArchStdEvent": "BUS_ACCESS_NOT_SHARED", | ||
| 61 | }, | ||
| 62 | { | ||
| 63 | "ArchStdEvent": "BUS_ACCESS_NORMAL", | ||
| 64 | }, | ||
| 65 | { | ||
| 66 | "ArchStdEvent": "BUS_ACCESS_PERIPH", | ||
| 67 | }, | ||
| 68 | { | ||
| 69 | "ArchStdEvent": "MEM_ACCESS_RD", | ||
| 70 | }, | ||
| 71 | { | ||
| 72 | "ArchStdEvent": "MEM_ACCESS_WR", | ||
| 73 | }, | ||
| 74 | { | ||
| 75 | "ArchStdEvent": "UNALIGNED_LD_SPEC", | ||
| 76 | }, | ||
| 77 | { | ||
| 78 | "ArchStdEvent": "UNALIGNED_ST_SPEC", | ||
| 79 | }, | ||
| 80 | { | ||
| 81 | "ArchStdEvent": "UNALIGNED_LDST_SPEC", | ||
| 82 | }, | ||
| 83 | { | ||
| 84 | "ArchStdEvent": "LDREX_SPEC", | ||
| 85 | }, | ||
| 86 | { | ||
| 87 | "ArchStdEvent": "STREX_PASS_SPEC", | ||
| 88 | }, | ||
| 89 | { | ||
| 90 | "ArchStdEvent": "STREX_FAIL_SPEC", | ||
| 91 | }, | ||
| 92 | { | ||
| 93 | "ArchStdEvent": "LD_SPEC", | ||
| 94 | }, | ||
| 95 | { | ||
| 96 | "ArchStdEvent": "ST_SPEC", | ||
| 97 | }, | ||
| 98 | { | ||
| 99 | "ArchStdEvent": "LDST_SPEC", | ||
| 100 | }, | ||
| 101 | { | ||
| 102 | "ArchStdEvent": "DP_SPEC", | ||
| 103 | }, | ||
| 104 | { | ||
| 105 | "ArchStdEvent": "ASE_SPEC", | ||
| 106 | }, | ||
| 107 | { | ||
| 108 | "ArchStdEvent": "VFP_SPEC", | ||
| 109 | }, | ||
| 110 | { | ||
| 111 | "ArchStdEvent": "PC_WRITE_SPEC", | ||
| 112 | }, | ||
| 113 | { | ||
| 114 | "ArchStdEvent": "CRYPTO_SPEC", | ||
| 115 | }, | ||
| 116 | { | ||
| 117 | "ArchStdEvent": "BR_IMMED_SPEC", | ||
| 118 | }, | ||
| 119 | { | ||
| 120 | "ArchStdEvent": "BR_RETURN_SPEC", | ||
| 121 | }, | ||
| 122 | { | ||
| 123 | "ArchStdEvent": "BR_INDIRECT_SPEC", | ||
| 124 | }, | ||
| 125 | { | ||
| 126 | "ArchStdEvent": "ISB_SPEC", | ||
| 127 | }, | ||
| 128 | { | ||
| 129 | "ArchStdEvent": "DSB_SPEC", | ||
| 130 | }, | ||
| 131 | { | ||
| 132 | "ArchStdEvent": "DMB_SPEC", | ||
| 133 | }, | ||
| 134 | { | ||
| 135 | "ArchStdEvent": "EXC_UNDEF", | ||
| 136 | }, | ||
| 137 | { | ||
| 138 | "ArchStdEvent": "EXC_SVC", | ||
| 139 | }, | ||
| 140 | { | ||
| 141 | "ArchStdEvent": "EXC_PABORT", | ||
| 142 | }, | ||
| 143 | { | ||
| 144 | "ArchStdEvent": "EXC_DABORT", | ||
| 145 | }, | ||
| 146 | { | ||
| 147 | "ArchStdEvent": "EXC_IRQ", | ||
| 148 | }, | ||
| 149 | { | ||
| 150 | "ArchStdEvent": "EXC_FIQ", | ||
| 151 | }, | ||
| 152 | { | ||
| 153 | "ArchStdEvent": "EXC_SMC", | ||
| 154 | }, | ||
| 155 | { | ||
| 156 | "ArchStdEvent": "EXC_HVC", | ||
| 157 | }, | ||
| 158 | { | ||
| 159 | "ArchStdEvent": "EXC_TRAP_PABORT", | ||
| 160 | }, | ||
| 161 | { | ||
| 162 | "ArchStdEvent": "EXC_TRAP_DABORT", | ||
| 163 | }, | ||
| 164 | { | ||
| 165 | "ArchStdEvent": "EXC_TRAP_OTHER", | ||
| 166 | }, | ||
| 167 | { | ||
| 168 | "ArchStdEvent": "EXC_TRAP_IRQ", | ||
| 169 | }, | ||
| 170 | { | ||
| 171 | "ArchStdEvent": "EXC_TRAP_FIQ", | ||
| 172 | }, | ||
| 173 | { | ||
| 174 | "ArchStdEvent": "RC_LD_SPEC", | ||
| 175 | }, | ||
| 176 | { | ||
| 177 | "ArchStdEvent": "RC_ST_SPEC", | ||
| 178 | }, | ||
| 179 | ] | ||
diff --git a/tools/perf/pmu-events/arch/arm64/mapfile.csv b/tools/perf/pmu-events/arch/arm64/mapfile.csv index 59cd8604b0bd..927fcddcb4aa 100644 --- a/tools/perf/pmu-events/arch/arm64/mapfile.csv +++ b/tools/perf/pmu-events/arch/arm64/mapfile.csv | |||
| @@ -12,7 +12,10 @@ | |||
| 12 | # | 12 | # |
| 13 | # | 13 | # |
| 14 | #Family-model,Version,Filename,EventType | 14 | #Family-model,Version,Filename,EventType |
| 15 | 0x00000000410fd03[[:xdigit:]],v1,arm/cortex-a53,core | 15 | 0x00000000410fd030,v1,arm/cortex-a53,core |
| 16 | 0x00000000420f1000,v1,arm/cortex-a53,core | ||
| 17 | 0x00000000410fd070,v1,arm/cortex-a57-a72,core | ||
| 18 | 0x00000000410fd080,v1,arm/cortex-a57-a72,core | ||
| 16 | 0x00000000420f5160,v1,cavium/thunderx2,core | 19 | 0x00000000420f5160,v1,cavium/thunderx2,core |
| 17 | 0x00000000430f0af0,v1,cavium/thunderx2,core | 20 | 0x00000000430f0af0,v1,cavium/thunderx2,core |
| 18 | 0x00000000480fd010,v1,hisilicon/hip08,core | 21 | 0x00000000480fd010,v1,hisilicon/hip08,core |
diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c index 68c92bb599ee..58f77fd0f59f 100644 --- a/tools/perf/pmu-events/jevents.c +++ b/tools/perf/pmu-events/jevents.c | |||
| @@ -235,6 +235,7 @@ static struct map { | |||
| 235 | { "iMPH-U", "uncore_arb" }, | 235 | { "iMPH-U", "uncore_arb" }, |
| 236 | { "CPU-M-CF", "cpum_cf" }, | 236 | { "CPU-M-CF", "cpum_cf" }, |
| 237 | { "CPU-M-SF", "cpum_sf" }, | 237 | { "CPU-M-SF", "cpum_sf" }, |
| 238 | { "UPI LL", "uncore_upi" }, | ||
| 238 | {} | 239 | {} |
| 239 | }; | 240 | }; |
| 240 | 241 | ||
| @@ -414,7 +415,6 @@ static int save_arch_std_events(void *data, char *name, char *event, | |||
| 414 | char *metric_name, char *metric_group) | 415 | char *metric_name, char *metric_group) |
| 415 | { | 416 | { |
| 416 | struct event_struct *es; | 417 | struct event_struct *es; |
| 417 | struct stat *sb = data; | ||
| 418 | 418 | ||
| 419 | es = malloc(sizeof(*es)); | 419 | es = malloc(sizeof(*es)); |
| 420 | if (!es) | 420 | if (!es) |
diff --git a/tools/perf/scripts/python/exported-sql-viewer.py b/tools/perf/scripts/python/exported-sql-viewer.py index 74ef92f1d19a..affed7d149be 100755 --- a/tools/perf/scripts/python/exported-sql-viewer.py +++ b/tools/perf/scripts/python/exported-sql-viewer.py | |||
| @@ -456,6 +456,10 @@ class CallGraphLevelItemBase(object): | |||
| 456 | self.query_done = False; | 456 | self.query_done = False; |
| 457 | self.child_count = 0 | 457 | self.child_count = 0 |
| 458 | self.child_items = [] | 458 | self.child_items = [] |
| 459 | if parent_item: | ||
| 460 | self.level = parent_item.level + 1 | ||
| 461 | else: | ||
| 462 | self.level = 0 | ||
| 459 | 463 | ||
| 460 | def getChildItem(self, row): | 464 | def getChildItem(self, row): |
| 461 | return self.child_items[row] | 465 | return self.child_items[row] |
| @@ -877,9 +881,14 @@ class TreeWindowBase(QMdiSubWindow): | |||
| 877 | super(TreeWindowBase, self).__init__(parent) | 881 | super(TreeWindowBase, self).__init__(parent) |
| 878 | 882 | ||
| 879 | self.model = None | 883 | self.model = None |
| 880 | self.view = None | ||
| 881 | self.find_bar = None | 884 | self.find_bar = None |
| 882 | 885 | ||
| 886 | self.view = QTreeView() | ||
| 887 | self.view.setSelectionMode(QAbstractItemView.ContiguousSelection) | ||
| 888 | self.view.CopyCellsToClipboard = CopyTreeCellsToClipboard | ||
| 889 | |||
| 890 | self.context_menu = TreeContextMenu(self.view) | ||
| 891 | |||
| 883 | def DisplayFound(self, ids): | 892 | def DisplayFound(self, ids): |
| 884 | if not len(ids): | 893 | if not len(ids): |
| 885 | return False | 894 | return False |
| @@ -921,7 +930,6 @@ class CallGraphWindow(TreeWindowBase): | |||
| 921 | 930 | ||
| 922 | self.model = LookupCreateModel("Context-Sensitive Call Graph", lambda x=glb: CallGraphModel(x)) | 931 | self.model = LookupCreateModel("Context-Sensitive Call Graph", lambda x=glb: CallGraphModel(x)) |
| 923 | 932 | ||
| 924 | self.view = QTreeView() | ||
| 925 | self.view.setModel(self.model) | 933 | self.view.setModel(self.model) |
| 926 | 934 | ||
| 927 | for c, w in ((0, 250), (1, 100), (2, 60), (3, 70), (4, 70), (5, 100)): | 935 | for c, w in ((0, 250), (1, 100), (2, 60), (3, 70), (4, 70), (5, 100)): |
| @@ -944,7 +952,6 @@ class CallTreeWindow(TreeWindowBase): | |||
| 944 | 952 | ||
| 945 | self.model = LookupCreateModel("Call Tree", lambda x=glb: CallTreeModel(x)) | 953 | self.model = LookupCreateModel("Call Tree", lambda x=glb: CallTreeModel(x)) |
| 946 | 954 | ||
| 947 | self.view = QTreeView() | ||
| 948 | self.view.setModel(self.model) | 955 | self.view.setModel(self.model) |
| 949 | 956 | ||
| 950 | for c, w in ((0, 230), (1, 100), (2, 100), (3, 70), (4, 70), (5, 100)): | 957 | for c, w in ((0, 230), (1, 100), (2, 100), (3, 70), (4, 70), (5, 100)): |
| @@ -1649,10 +1656,14 @@ class BranchWindow(QMdiSubWindow): | |||
| 1649 | 1656 | ||
| 1650 | self.view = QTreeView() | 1657 | self.view = QTreeView() |
| 1651 | self.view.setUniformRowHeights(True) | 1658 | self.view.setUniformRowHeights(True) |
| 1659 | self.view.setSelectionMode(QAbstractItemView.ContiguousSelection) | ||
| 1660 | self.view.CopyCellsToClipboard = CopyTreeCellsToClipboard | ||
| 1652 | self.view.setModel(self.model) | 1661 | self.view.setModel(self.model) |
| 1653 | 1662 | ||
| 1654 | self.ResizeColumnsToContents() | 1663 | self.ResizeColumnsToContents() |
| 1655 | 1664 | ||
| 1665 | self.context_menu = TreeContextMenu(self.view) | ||
| 1666 | |||
| 1656 | self.find_bar = FindBar(self, self, True) | 1667 | self.find_bar = FindBar(self, self, True) |
| 1657 | 1668 | ||
| 1658 | self.finder = ChildDataItemFinder(self.model.root) | 1669 | self.finder = ChildDataItemFinder(self.model.root) |
| @@ -2261,6 +2272,240 @@ class ResizeColumnsToContentsBase(QObject): | |||
| 2261 | self.data_model.rowsInserted.disconnect(self.UpdateColumnWidths) | 2272 | self.data_model.rowsInserted.disconnect(self.UpdateColumnWidths) |
| 2262 | self.ResizeColumnsToContents() | 2273 | self.ResizeColumnsToContents() |
| 2263 | 2274 | ||
| 2275 | # Convert value to CSV | ||
| 2276 | |||
| 2277 | def ToCSValue(val): | ||
| 2278 | if '"' in val: | ||
| 2279 | val = val.replace('"', '""') | ||
| 2280 | if "," in val or '"' in val: | ||
| 2281 | val = '"' + val + '"' | ||
| 2282 | return val | ||
| 2283 | |||
| 2284 | # Key to sort table model indexes by row / column, assuming fewer than 1000 columns | ||
| 2285 | |||
| 2286 | glb_max_cols = 1000 | ||
| 2287 | |||
| 2288 | def RowColumnKey(a): | ||
| 2289 | return a.row() * glb_max_cols + a.column() | ||
| 2290 | |||
| 2291 | # Copy selected table cells to clipboard | ||
| 2292 | |||
| 2293 | def CopyTableCellsToClipboard(view, as_csv=False, with_hdr=False): | ||
| 2294 | indexes = sorted(view.selectedIndexes(), key=RowColumnKey) | ||
| 2295 | idx_cnt = len(indexes) | ||
| 2296 | if not idx_cnt: | ||
| 2297 | return | ||
| 2298 | if idx_cnt == 1: | ||
| 2299 | with_hdr=False | ||
| 2300 | min_row = indexes[0].row() | ||
| 2301 | max_row = indexes[0].row() | ||
| 2302 | min_col = indexes[0].column() | ||
| 2303 | max_col = indexes[0].column() | ||
| 2304 | for i in indexes: | ||
| 2305 | min_row = min(min_row, i.row()) | ||
| 2306 | max_row = max(max_row, i.row()) | ||
| 2307 | min_col = min(min_col, i.column()) | ||
| 2308 | max_col = max(max_col, i.column()) | ||
| 2309 | if max_col > glb_max_cols: | ||
| 2310 | raise RuntimeError("glb_max_cols is too low") | ||
| 2311 | max_width = [0] * (1 + max_col - min_col) | ||
| 2312 | for i in indexes: | ||
| 2313 | c = i.column() - min_col | ||
| 2314 | max_width[c] = max(max_width[c], len(str(i.data()))) | ||
| 2315 | text = "" | ||
| 2316 | pad = "" | ||
| 2317 | sep = "" | ||
| 2318 | if with_hdr: | ||
| 2319 | model = indexes[0].model() | ||
| 2320 | for col in range(min_col, max_col + 1): | ||
| 2321 | val = model.headerData(col, Qt.Horizontal) | ||
| 2322 | if as_csv: | ||
| 2323 | text += sep + ToCSValue(val) | ||
| 2324 | sep = "," | ||
| 2325 | else: | ||
| 2326 | c = col - min_col | ||
| 2327 | max_width[c] = max(max_width[c], len(val)) | ||
| 2328 | width = max_width[c] | ||
| 2329 | align = model.headerData(col, Qt.Horizontal, Qt.TextAlignmentRole) | ||
| 2330 | if align & Qt.AlignRight: | ||
| 2331 | val = val.rjust(width) | ||
| 2332 | text += pad + sep + val | ||
| 2333 | pad = " " * (width - len(val)) | ||
| 2334 | sep = " " | ||
| 2335 | text += "\n" | ||
| 2336 | pad = "" | ||
| 2337 | sep = "" | ||
| 2338 | last_row = min_row | ||
| 2339 | for i in indexes: | ||
| 2340 | if i.row() > last_row: | ||
| 2341 | last_row = i.row() | ||
| 2342 | text += "\n" | ||
| 2343 | pad = "" | ||
| 2344 | sep = "" | ||
| 2345 | if as_csv: | ||
| 2346 | text += sep + ToCSValue(str(i.data())) | ||
| 2347 | sep = "," | ||
| 2348 | else: | ||
| 2349 | width = max_width[i.column() - min_col] | ||
| 2350 | if i.data(Qt.TextAlignmentRole) & Qt.AlignRight: | ||
| 2351 | val = str(i.data()).rjust(width) | ||
| 2352 | else: | ||
| 2353 | val = str(i.data()) | ||
| 2354 | text += pad + sep + val | ||
| 2355 | pad = " " * (width - len(val)) | ||
| 2356 | sep = " " | ||
| 2357 | QApplication.clipboard().setText(text) | ||
| 2358 | |||
| 2359 | def CopyTreeCellsToClipboard(view, as_csv=False, with_hdr=False): | ||
| 2360 | indexes = view.selectedIndexes() | ||
| 2361 | if not len(indexes): | ||
| 2362 | return | ||
| 2363 | |||
| 2364 | selection = view.selectionModel() | ||
| 2365 | |||
| 2366 | first = None | ||
| 2367 | for i in indexes: | ||
| 2368 | above = view.indexAbove(i) | ||
| 2369 | if not selection.isSelected(above): | ||
| 2370 | first = i | ||
| 2371 | break | ||
| 2372 | |||
| 2373 | if first is None: | ||
| 2374 | raise RuntimeError("CopyTreeCellsToClipboard internal error") | ||
| 2375 | |||
| 2376 | model = first.model() | ||
| 2377 | row_cnt = 0 | ||
| 2378 | col_cnt = model.columnCount(first) | ||
| 2379 | max_width = [0] * col_cnt | ||
| 2380 | |||
| 2381 | indent_sz = 2 | ||
| 2382 | indent_str = " " * indent_sz | ||
| 2383 | |||
| 2384 | expanded_mark_sz = 2 | ||
| 2385 | if sys.version_info[0] == 3: | ||
| 2386 | expanded_mark = "\u25BC " | ||
| 2387 | not_expanded_mark = "\u25B6 " | ||
| 2388 | else: | ||
| 2389 | expanded_mark = unicode(chr(0xE2) + chr(0x96) + chr(0xBC) + " ", "utf-8") | ||
| 2390 | not_expanded_mark = unicode(chr(0xE2) + chr(0x96) + chr(0xB6) + " ", "utf-8") | ||
| 2391 | leaf_mark = " " | ||
| 2392 | |||
| 2393 | if not as_csv: | ||
| 2394 | pos = first | ||
| 2395 | while True: | ||
| 2396 | row_cnt += 1 | ||
| 2397 | row = pos.row() | ||
| 2398 | for c in range(col_cnt): | ||
| 2399 | i = pos.sibling(row, c) | ||
| 2400 | if c: | ||
| 2401 | n = len(str(i.data())) | ||
| 2402 | else: | ||
| 2403 | n = len(str(i.data()).strip()) | ||
| 2404 | n += (i.internalPointer().level - 1) * indent_sz | ||
| 2405 | n += expanded_mark_sz | ||
| 2406 | max_width[c] = max(max_width[c], n) | ||
| 2407 | pos = view.indexBelow(pos) | ||
| 2408 | if not selection.isSelected(pos): | ||
| 2409 | break | ||
| 2410 | |||
| 2411 | text = "" | ||
| 2412 | pad = "" | ||
| 2413 | sep = "" | ||
| 2414 | if with_hdr: | ||
| 2415 | for c in range(col_cnt): | ||
| 2416 | val = model.headerData(c, Qt.Horizontal, Qt.DisplayRole).strip() | ||
| 2417 | if as_csv: | ||
| 2418 | text += sep + ToCSValue(val) | ||
| 2419 | sep = "," | ||
| 2420 | else: | ||
| 2421 | max_width[c] = max(max_width[c], len(val)) | ||
| 2422 | width = max_width[c] | ||
| 2423 | align = model.headerData(c, Qt.Horizontal, Qt.TextAlignmentRole) | ||
| 2424 | if align & Qt.AlignRight: | ||
| 2425 | val = val.rjust(width) | ||
| 2426 | text += pad + sep + val | ||
| 2427 | pad = " " * (width - len(val)) | ||
| 2428 | sep = " " | ||
| 2429 | text += "\n" | ||
| 2430 | pad = "" | ||
| 2431 | sep = "" | ||
| 2432 | |||
| 2433 | pos = first | ||
| 2434 | while True: | ||
| 2435 | row = pos.row() | ||
| 2436 | for c in range(col_cnt): | ||
| 2437 | i = pos.sibling(row, c) | ||
| 2438 | val = str(i.data()) | ||
| 2439 | if not c: | ||
| 2440 | if model.hasChildren(i): | ||
| 2441 | if view.isExpanded(i): | ||
| 2442 | mark = expanded_mark | ||
| 2443 | else: | ||
| 2444 | mark = not_expanded_mark | ||
| 2445 | else: | ||
| 2446 | mark = leaf_mark | ||
| 2447 | val = indent_str * (i.internalPointer().level - 1) + mark + val.strip() | ||
| 2448 | if as_csv: | ||
| 2449 | text += sep + ToCSValue(val) | ||
| 2450 | sep = "," | ||
| 2451 | else: | ||
| 2452 | width = max_width[c] | ||
| 2453 | if c and i.data(Qt.TextAlignmentRole) & Qt.AlignRight: | ||
| 2454 | val = val.rjust(width) | ||
| 2455 | text += pad + sep + val | ||
| 2456 | pad = " " * (width - len(val)) | ||
| 2457 | sep = " " | ||
| 2458 | pos = view.indexBelow(pos) | ||
| 2459 | if not selection.isSelected(pos): | ||
| 2460 | break | ||
| 2461 | text = text.rstrip() + "\n" | ||
| 2462 | pad = "" | ||
| 2463 | sep = "" | ||
| 2464 | |||
| 2465 | QApplication.clipboard().setText(text) | ||
| 2466 | |||
| 2467 | def CopyCellsToClipboard(view, as_csv=False, with_hdr=False): | ||
| 2468 | view.CopyCellsToClipboard(view, as_csv, with_hdr) | ||
| 2469 | |||
| 2470 | def CopyCellsToClipboardHdr(view): | ||
| 2471 | CopyCellsToClipboard(view, False, True) | ||
| 2472 | |||
| 2473 | def CopyCellsToClipboardCSV(view): | ||
| 2474 | CopyCellsToClipboard(view, True, True) | ||
| 2475 | |||
| 2476 | # Context menu | ||
| 2477 | |||
| 2478 | class ContextMenu(object): | ||
| 2479 | |||
| 2480 | def __init__(self, view): | ||
| 2481 | self.view = view | ||
| 2482 | self.view.setContextMenuPolicy(Qt.CustomContextMenu) | ||
| 2483 | self.view.customContextMenuRequested.connect(self.ShowContextMenu) | ||
| 2484 | |||
| 2485 | def ShowContextMenu(self, pos): | ||
| 2486 | menu = QMenu(self.view) | ||
| 2487 | self.AddActions(menu) | ||
| 2488 | menu.exec_(self.view.mapToGlobal(pos)) | ||
| 2489 | |||
| 2490 | def AddCopy(self, menu): | ||
| 2491 | menu.addAction(CreateAction("&Copy selection", "Copy to clipboard", lambda: CopyCellsToClipboardHdr(self.view), self.view)) | ||
| 2492 | menu.addAction(CreateAction("Copy selection as CS&V", "Copy to clipboard as CSV", lambda: CopyCellsToClipboardCSV(self.view), self.view)) | ||
| 2493 | |||
| 2494 | def AddActions(self, menu): | ||
| 2495 | self.AddCopy(menu) | ||
| 2496 | |||
| 2497 | class TreeContextMenu(ContextMenu): | ||
| 2498 | |||
| 2499 | def __init__(self, view): | ||
| 2500 | super(TreeContextMenu, self).__init__(view) | ||
| 2501 | |||
| 2502 | def AddActions(self, menu): | ||
| 2503 | i = self.view.currentIndex() | ||
| 2504 | text = str(i.data()).strip() | ||
| 2505 | if len(text): | ||
| 2506 | menu.addAction(CreateAction('Copy "' + text + '"', "Copy to clipboard", lambda: QApplication.clipboard().setText(text), self.view)) | ||
| 2507 | self.AddCopy(menu) | ||
| 2508 | |||
| 2264 | # Table window | 2509 | # Table window |
| 2265 | 2510 | ||
| 2266 | class TableWindow(QMdiSubWindow, ResizeColumnsToContentsBase): | 2511 | class TableWindow(QMdiSubWindow, ResizeColumnsToContentsBase): |
| @@ -2279,9 +2524,13 @@ class TableWindow(QMdiSubWindow, ResizeColumnsToContentsBase): | |||
| 2279 | self.view.verticalHeader().setVisible(False) | 2524 | self.view.verticalHeader().setVisible(False) |
| 2280 | self.view.sortByColumn(-1, Qt.AscendingOrder) | 2525 | self.view.sortByColumn(-1, Qt.AscendingOrder) |
| 2281 | self.view.setSortingEnabled(True) | 2526 | self.view.setSortingEnabled(True) |
| 2527 | self.view.setSelectionMode(QAbstractItemView.ContiguousSelection) | ||
| 2528 | self.view.CopyCellsToClipboard = CopyTableCellsToClipboard | ||
| 2282 | 2529 | ||
| 2283 | self.ResizeColumnsToContents() | 2530 | self.ResizeColumnsToContents() |
| 2284 | 2531 | ||
| 2532 | self.context_menu = ContextMenu(self.view) | ||
| 2533 | |||
| 2285 | self.find_bar = FindBar(self, self, True) | 2534 | self.find_bar = FindBar(self, self, True) |
| 2286 | 2535 | ||
| 2287 | self.finder = ChildDataItemFinder(self.data_model) | 2536 | self.finder = ChildDataItemFinder(self.data_model) |
| @@ -2395,6 +2644,10 @@ class TopCallsWindow(QMdiSubWindow, ResizeColumnsToContentsBase): | |||
| 2395 | self.view.setModel(self.model) | 2644 | self.view.setModel(self.model) |
| 2396 | self.view.setEditTriggers(QAbstractItemView.NoEditTriggers) | 2645 | self.view.setEditTriggers(QAbstractItemView.NoEditTriggers) |
| 2397 | self.view.verticalHeader().setVisible(False) | 2646 | self.view.verticalHeader().setVisible(False) |
| 2647 | self.view.setSelectionMode(QAbstractItemView.ContiguousSelection) | ||
| 2648 | self.view.CopyCellsToClipboard = CopyTableCellsToClipboard | ||
| 2649 | |||
| 2650 | self.context_menu = ContextMenu(self.view) | ||
| 2398 | 2651 | ||
| 2399 | self.ResizeColumnsToContents() | 2652 | self.ResizeColumnsToContents() |
| 2400 | 2653 | ||
| @@ -2660,6 +2913,60 @@ class HelpOnlyWindow(QMainWindow): | |||
| 2660 | 2913 | ||
| 2661 | self.setCentralWidget(self.text) | 2914 | self.setCentralWidget(self.text) |
| 2662 | 2915 | ||
| 2916 | # PostqreSQL server version | ||
| 2917 | |||
| 2918 | def PostqreSQLServerVersion(db): | ||
| 2919 | query = QSqlQuery(db) | ||
| 2920 | QueryExec(query, "SELECT VERSION()") | ||
| 2921 | if query.next(): | ||
| 2922 | v_str = query.value(0) | ||
| 2923 | v_list = v_str.strip().split(" ") | ||
| 2924 | if v_list[0] == "PostgreSQL" and v_list[2] == "on": | ||
| 2925 | return v_list[1] | ||
| 2926 | return v_str | ||
| 2927 | return "Unknown" | ||
| 2928 | |||
| 2929 | # SQLite version | ||
| 2930 | |||
| 2931 | def SQLiteVersion(db): | ||
| 2932 | query = QSqlQuery(db) | ||
| 2933 | QueryExec(query, "SELECT sqlite_version()") | ||
| 2934 | if query.next(): | ||
| 2935 | return query.value(0) | ||
| 2936 | return "Unknown" | ||
| 2937 | |||
| 2938 | # About dialog | ||
| 2939 | |||
| 2940 | class AboutDialog(QDialog): | ||
| 2941 | |||
| 2942 | def __init__(self, glb, parent=None): | ||
| 2943 | super(AboutDialog, self).__init__(parent) | ||
| 2944 | |||
| 2945 | self.setWindowTitle("About Exported SQL Viewer") | ||
| 2946 | self.setMinimumWidth(300) | ||
| 2947 | |||
| 2948 | pyside_version = "1" if pyside_version_1 else "2" | ||
| 2949 | |||
| 2950 | text = "<pre>" | ||
| 2951 | text += "Python version: " + sys.version.split(" ")[0] + "\n" | ||
| 2952 | text += "PySide version: " + pyside_version + "\n" | ||
| 2953 | text += "Qt version: " + qVersion() + "\n" | ||
| 2954 | if glb.dbref.is_sqlite3: | ||
| 2955 | text += "SQLite version: " + SQLiteVersion(glb.db) + "\n" | ||
| 2956 | else: | ||
| 2957 | text += "PostqreSQL version: " + PostqreSQLServerVersion(glb.db) + "\n" | ||
| 2958 | text += "</pre>" | ||
| 2959 | |||
| 2960 | self.text = QTextBrowser() | ||
| 2961 | self.text.setHtml(text) | ||
| 2962 | self.text.setReadOnly(True) | ||
| 2963 | self.text.setOpenExternalLinks(True) | ||
| 2964 | |||
| 2965 | self.vbox = QVBoxLayout() | ||
| 2966 | self.vbox.addWidget(self.text) | ||
| 2967 | |||
| 2968 | self.setLayout(self.vbox); | ||
| 2969 | |||
| 2663 | # Font resize | 2970 | # Font resize |
| 2664 | 2971 | ||
| 2665 | def ResizeFont(widget, diff): | 2972 | def ResizeFont(widget, diff): |
| @@ -2732,6 +3039,8 @@ class MainWindow(QMainWindow): | |||
| 2732 | file_menu.addAction(CreateExitAction(glb.app, self)) | 3039 | file_menu.addAction(CreateExitAction(glb.app, self)) |
| 2733 | 3040 | ||
| 2734 | edit_menu = menu.addMenu("&Edit") | 3041 | edit_menu = menu.addMenu("&Edit") |
| 3042 | edit_menu.addAction(CreateAction("&Copy", "Copy to clipboard", self.CopyToClipboard, self, QKeySequence.Copy)) | ||
| 3043 | edit_menu.addAction(CreateAction("Copy as CS&V", "Copy to clipboard as CSV", self.CopyToClipboardCSV, self)) | ||
| 2735 | edit_menu.addAction(CreateAction("&Find...", "Find items", self.Find, self, QKeySequence.Find)) | 3044 | edit_menu.addAction(CreateAction("&Find...", "Find items", self.Find, self, QKeySequence.Find)) |
| 2736 | edit_menu.addAction(CreateAction("Fetch &more records...", "Fetch more records", self.FetchMoreRecords, self, [QKeySequence(Qt.Key_F8)])) | 3045 | edit_menu.addAction(CreateAction("Fetch &more records...", "Fetch more records", self.FetchMoreRecords, self, [QKeySequence(Qt.Key_F8)])) |
| 2737 | edit_menu.addAction(CreateAction("&Shrink Font", "Make text smaller", self.ShrinkFont, self, [QKeySequence("Ctrl+-")])) | 3046 | edit_menu.addAction(CreateAction("&Shrink Font", "Make text smaller", self.ShrinkFont, self, [QKeySequence("Ctrl+-")])) |
| @@ -2755,6 +3064,21 @@ class MainWindow(QMainWindow): | |||
| 2755 | 3064 | ||
| 2756 | help_menu = menu.addMenu("&Help") | 3065 | help_menu = menu.addMenu("&Help") |
| 2757 | help_menu.addAction(CreateAction("&Exported SQL Viewer Help", "Helpful information", self.Help, self, QKeySequence.HelpContents)) | 3066 | help_menu.addAction(CreateAction("&Exported SQL Viewer Help", "Helpful information", self.Help, self, QKeySequence.HelpContents)) |
| 3067 | help_menu.addAction(CreateAction("&About Exported SQL Viewer", "About this application", self.About, self)) | ||
| 3068 | |||
| 3069 | def Try(self, fn): | ||
| 3070 | win = self.mdi_area.activeSubWindow() | ||
| 3071 | if win: | ||
| 3072 | try: | ||
| 3073 | fn(win.view) | ||
| 3074 | except: | ||
| 3075 | pass | ||
| 3076 | |||
| 3077 | def CopyToClipboard(self): | ||
| 3078 | self.Try(CopyCellsToClipboardHdr) | ||
| 3079 | |||
| 3080 | def CopyToClipboardCSV(self): | ||
| 3081 | self.Try(CopyCellsToClipboardCSV) | ||
| 2758 | 3082 | ||
| 2759 | def Find(self): | 3083 | def Find(self): |
| 2760 | win = self.mdi_area.activeSubWindow() | 3084 | win = self.mdi_area.activeSubWindow() |
| @@ -2773,12 +3097,10 @@ class MainWindow(QMainWindow): | |||
| 2773 | pass | 3097 | pass |
| 2774 | 3098 | ||
| 2775 | def ShrinkFont(self): | 3099 | def ShrinkFont(self): |
| 2776 | win = self.mdi_area.activeSubWindow() | 3100 | self.Try(ShrinkFont) |
| 2777 | ShrinkFont(win.view) | ||
| 2778 | 3101 | ||
| 2779 | def EnlargeFont(self): | 3102 | def EnlargeFont(self): |
| 2780 | win = self.mdi_area.activeSubWindow() | 3103 | self.Try(EnlargeFont) |
| 2781 | EnlargeFont(win.view) | ||
| 2782 | 3104 | ||
| 2783 | def EventMenu(self, events, reports_menu): | 3105 | def EventMenu(self, events, reports_menu): |
| 2784 | branches_events = 0 | 3106 | branches_events = 0 |
| @@ -2828,6 +3150,10 @@ class MainWindow(QMainWindow): | |||
| 2828 | def Help(self): | 3150 | def Help(self): |
| 2829 | HelpWindow(self.glb, self) | 3151 | HelpWindow(self.glb, self) |
| 2830 | 3152 | ||
| 3153 | def About(self): | ||
| 3154 | dialog = AboutDialog(self.glb, self) | ||
| 3155 | dialog.exec_() | ||
| 3156 | |||
| 2831 | # XED Disassembler | 3157 | # XED Disassembler |
| 2832 | 3158 | ||
| 2833 | class xed_state_t(Structure): | 3159 | class xed_state_t(Structure): |
diff --git a/tools/perf/tests/dso-data.c b/tools/perf/tests/dso-data.c index 7f6c52021e41..946ab4b63acd 100644 --- a/tools/perf/tests/dso-data.c +++ b/tools/perf/tests/dso-data.c | |||
| @@ -304,7 +304,7 @@ int test__dso_data_cache(struct test *test __maybe_unused, int subtest __maybe_u | |||
| 304 | /* Make sure we did not leak any file descriptor. */ | 304 | /* Make sure we did not leak any file descriptor. */ |
| 305 | nr_end = open_files_cnt(); | 305 | nr_end = open_files_cnt(); |
| 306 | pr_debug("nr start %ld, nr stop %ld\n", nr, nr_end); | 306 | pr_debug("nr start %ld, nr stop %ld\n", nr, nr_end); |
| 307 | TEST_ASSERT_VAL("failed leadking files", nr == nr_end); | 307 | TEST_ASSERT_VAL("failed leaking files", nr == nr_end); |
| 308 | return 0; | 308 | return 0; |
| 309 | } | 309 | } |
| 310 | 310 | ||
| @@ -380,6 +380,6 @@ int test__dso_data_reopen(struct test *test __maybe_unused, int subtest __maybe_ | |||
| 380 | /* Make sure we did not leak any file descriptor. */ | 380 | /* Make sure we did not leak any file descriptor. */ |
| 381 | nr_end = open_files_cnt(); | 381 | nr_end = open_files_cnt(); |
| 382 | pr_debug("nr start %ld, nr stop %ld\n", nr, nr_end); | 382 | pr_debug("nr start %ld, nr stop %ld\n", nr, nr_end); |
| 383 | TEST_ASSERT_VAL("failed leadking files", nr == nr_end); | 383 | TEST_ASSERT_VAL("failed leaking files", nr == nr_end); |
| 384 | return 0; | 384 | return 0; |
| 385 | } | 385 | } |
diff --git a/tools/perf/tests/make b/tools/perf/tests/make index e46723568516..5363a12a8b9b 100644 --- a/tools/perf/tests/make +++ b/tools/perf/tests/make | |||
| @@ -107,7 +107,7 @@ make_minimal := NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1 | |||
| 107 | make_minimal += NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1 | 107 | make_minimal += NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1 |
| 108 | make_minimal += NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1 | 108 | make_minimal += NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1 |
| 109 | make_minimal += NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1 NO_LIBBPF=1 | 109 | make_minimal += NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1 NO_LIBBPF=1 |
| 110 | make_minimal += NO_LIBCRYPTO=1 NO_SDT=1 NO_JVMTI=1 | 110 | make_minimal += NO_LIBCRYPTO=1 NO_SDT=1 NO_JVMTI=1 NO_LIBZSTD=1 |
| 111 | 111 | ||
| 112 | # $(run) contains all available tests | 112 | # $(run) contains all available tests |
| 113 | run := make_pure | 113 | run := make_pure |
diff --git a/tools/perf/tests/shell/record+zstd_comp_decomp.sh b/tools/perf/tests/shell/record+zstd_comp_decomp.sh new file mode 100755 index 000000000000..5dcba800109f --- /dev/null +++ b/tools/perf/tests/shell/record+zstd_comp_decomp.sh | |||
| @@ -0,0 +1,34 @@ | |||
| 1 | #!/bin/sh | ||
| 2 | # Zstd perf.data compression/decompression | ||
| 3 | |||
| 4 | trace_file=$(mktemp /tmp/perf.data.XXX) | ||
| 5 | perf_tool=perf | ||
| 6 | |||
| 7 | skip_if_no_z_record() { | ||
| 8 | $perf_tool record -h 2>&1 | grep -q '\-z, \-\-compression\-level' | ||
| 9 | } | ||
| 10 | |||
| 11 | collect_z_record() { | ||
| 12 | echo "Collecting compressed record file:" | ||
| 13 | $perf_tool record -o $trace_file -g -z -F 5000 -- \ | ||
| 14 | dd count=500 if=/dev/random of=/dev/null | ||
| 15 | } | ||
| 16 | |||
| 17 | check_compressed_stats() { | ||
| 18 | echo "Checking compressed events stats:" | ||
| 19 | $perf_tool report -i $trace_file --header --stats | \ | ||
| 20 | grep -E "(# compressed : Zstd,)|(COMPRESSED events:)" | ||
| 21 | } | ||
| 22 | |||
| 23 | check_compressed_output() { | ||
| 24 | $perf_tool inject -i $trace_file -o $trace_file.decomp && | ||
| 25 | $perf_tool report -i $trace_file --stdio | head -n -3 > $trace_file.comp.output && | ||
| 26 | $perf_tool report -i $trace_file.decomp --stdio | head -n -3 > $trace_file.decomp.output && | ||
| 27 | diff $trace_file.comp.output $trace_file.decomp.output | ||
| 28 | } | ||
| 29 | |||
| 30 | skip_if_no_z_record || exit 2 | ||
| 31 | collect_z_record && check_compressed_stats && check_compressed_output | ||
| 32 | err=$? | ||
| 33 | rm -f $trace_file* | ||
| 34 | exit $err | ||
diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 8dd3102301ea..6d5bbc8b589b 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build | |||
| @@ -145,6 +145,8 @@ perf-y += scripting-engines/ | |||
| 145 | 145 | ||
| 146 | perf-$(CONFIG_ZLIB) += zlib.o | 146 | perf-$(CONFIG_ZLIB) += zlib.o |
| 147 | perf-$(CONFIG_LZMA) += lzma.o | 147 | perf-$(CONFIG_LZMA) += lzma.o |
| 148 | perf-$(CONFIG_ZSTD) += zstd.o | ||
| 149 | |||
| 148 | perf-y += demangle-java.o | 150 | perf-y += demangle-java.o |
| 149 | perf-y += demangle-rust.o | 151 | perf-y += demangle-rust.o |
| 150 | 152 | ||
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 09762985c713..0b8573fd9b05 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c | |||
| @@ -1021,7 +1021,7 @@ static void annotation__count_and_fill(struct annotation *notes, u64 start, u64 | |||
| 1021 | float ipc = n_insn / ((double)ch->cycles / (double)ch->num); | 1021 | float ipc = n_insn / ((double)ch->cycles / (double)ch->num); |
| 1022 | 1022 | ||
| 1023 | /* Hide data when there are too many overlaps. */ | 1023 | /* Hide data when there are too many overlaps. */ |
| 1024 | if (ch->reset >= 0x7fff || ch->reset >= ch->num / 2) | 1024 | if (ch->reset >= 0x7fff) |
| 1025 | return; | 1025 | return; |
| 1026 | 1026 | ||
| 1027 | for (offset = start; offset <= end; offset++) { | 1027 | for (offset = start; offset <= end; offset++) { |
diff --git a/tools/perf/util/compress.h b/tools/perf/util/compress.h index 892e92e7e7fc..0cd3369af2a4 100644 --- a/tools/perf/util/compress.h +++ b/tools/perf/util/compress.h | |||
| @@ -2,6 +2,11 @@ | |||
| 2 | #ifndef PERF_COMPRESS_H | 2 | #ifndef PERF_COMPRESS_H |
| 3 | #define PERF_COMPRESS_H | 3 | #define PERF_COMPRESS_H |
| 4 | 4 | ||
| 5 | #include <stdbool.h> | ||
| 6 | #ifdef HAVE_ZSTD_SUPPORT | ||
| 7 | #include <zstd.h> | ||
| 8 | #endif | ||
| 9 | |||
| 5 | #ifdef HAVE_ZLIB_SUPPORT | 10 | #ifdef HAVE_ZLIB_SUPPORT |
| 6 | int gzip_decompress_to_file(const char *input, int output_fd); | 11 | int gzip_decompress_to_file(const char *input, int output_fd); |
| 7 | bool gzip_is_compressed(const char *input); | 12 | bool gzip_is_compressed(const char *input); |
| @@ -12,4 +17,52 @@ int lzma_decompress_to_file(const char *input, int output_fd); | |||
| 12 | bool lzma_is_compressed(const char *input); | 17 | bool lzma_is_compressed(const char *input); |
| 13 | #endif | 18 | #endif |
| 14 | 19 | ||
| 20 | struct zstd_data { | ||
| 21 | #ifdef HAVE_ZSTD_SUPPORT | ||
| 22 | ZSTD_CStream *cstream; | ||
| 23 | ZSTD_DStream *dstream; | ||
| 24 | #endif | ||
| 25 | }; | ||
| 26 | |||
| 27 | #ifdef HAVE_ZSTD_SUPPORT | ||
| 28 | |||
| 29 | int zstd_init(struct zstd_data *data, int level); | ||
| 30 | int zstd_fini(struct zstd_data *data); | ||
| 31 | |||
| 32 | size_t zstd_compress_stream_to_records(struct zstd_data *data, void *dst, size_t dst_size, | ||
| 33 | void *src, size_t src_size, size_t max_record_size, | ||
| 34 | size_t process_header(void *record, size_t increment)); | ||
| 35 | |||
| 36 | size_t zstd_decompress_stream(struct zstd_data *data, void *src, size_t src_size, | ||
| 37 | void *dst, size_t dst_size); | ||
| 38 | #else /* !HAVE_ZSTD_SUPPORT */ | ||
| 39 | |||
| 40 | static inline int zstd_init(struct zstd_data *data __maybe_unused, int level __maybe_unused) | ||
| 41 | { | ||
| 42 | return 0; | ||
| 43 | } | ||
| 44 | |||
| 45 | static inline int zstd_fini(struct zstd_data *data __maybe_unused) | ||
| 46 | { | ||
| 47 | return 0; | ||
| 48 | } | ||
| 49 | |||
| 50 | static inline | ||
| 51 | size_t zstd_compress_stream_to_records(struct zstd_data *data __maybe_unused, | ||
| 52 | void *dst __maybe_unused, size_t dst_size __maybe_unused, | ||
| 53 | void *src __maybe_unused, size_t src_size __maybe_unused, | ||
| 54 | size_t max_record_size __maybe_unused, | ||
| 55 | size_t process_header(void *record, size_t increment) __maybe_unused) | ||
| 56 | { | ||
| 57 | return 0; | ||
| 58 | } | ||
| 59 | |||
| 60 | static inline size_t zstd_decompress_stream(struct zstd_data *data __maybe_unused, void *src __maybe_unused, | ||
| 61 | size_t src_size __maybe_unused, void *dst __maybe_unused, | ||
| 62 | size_t dst_size __maybe_unused) | ||
| 63 | { | ||
| 64 | return 0; | ||
| 65 | } | ||
| 66 | #endif | ||
| 67 | |||
| 15 | #endif /* PERF_COMPRESS_H */ | 68 | #endif /* PERF_COMPRESS_H */ |
diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h index 4f8e2b485c01..271a90b326c4 100644 --- a/tools/perf/util/env.h +++ b/tools/perf/util/env.h | |||
| @@ -62,6 +62,11 @@ struct perf_env { | |||
| 62 | struct cpu_topology_map *cpu; | 62 | struct cpu_topology_map *cpu; |
| 63 | struct cpu_cache_level *caches; | 63 | struct cpu_cache_level *caches; |
| 64 | int caches_cnt; | 64 | int caches_cnt; |
| 65 | u32 comp_ratio; | ||
| 66 | u32 comp_ver; | ||
| 67 | u32 comp_type; | ||
| 68 | u32 comp_level; | ||
| 69 | u32 comp_mmap_len; | ||
| 65 | struct numa_node *numa_nodes; | 70 | struct numa_node *numa_nodes; |
| 66 | struct memory_node *memory_nodes; | 71 | struct memory_node *memory_nodes; |
| 67 | unsigned long long memory_bsize; | 72 | unsigned long long memory_bsize; |
| @@ -80,6 +85,12 @@ struct perf_env { | |||
| 80 | } bpf_progs; | 85 | } bpf_progs; |
| 81 | }; | 86 | }; |
| 82 | 87 | ||
| 88 | enum perf_compress_type { | ||
| 89 | PERF_COMP_NONE = 0, | ||
| 90 | PERF_COMP_ZSTD, | ||
| 91 | PERF_COMP_MAX | ||
| 92 | }; | ||
| 93 | |||
| 83 | struct bpf_prog_info_node; | 94 | struct bpf_prog_info_node; |
| 84 | struct btf_node; | 95 | struct btf_node; |
| 85 | 96 | ||
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index ba7be74fad6e..d1ad6c419724 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c | |||
| @@ -68,6 +68,7 @@ static const char *perf_event__names[] = { | |||
| 68 | [PERF_RECORD_EVENT_UPDATE] = "EVENT_UPDATE", | 68 | [PERF_RECORD_EVENT_UPDATE] = "EVENT_UPDATE", |
| 69 | [PERF_RECORD_TIME_CONV] = "TIME_CONV", | 69 | [PERF_RECORD_TIME_CONV] = "TIME_CONV", |
| 70 | [PERF_RECORD_HEADER_FEATURE] = "FEATURE", | 70 | [PERF_RECORD_HEADER_FEATURE] = "FEATURE", |
| 71 | [PERF_RECORD_COMPRESSED] = "COMPRESSED", | ||
| 71 | }; | 72 | }; |
| 72 | 73 | ||
| 73 | static const char *perf_ns__names[] = { | 74 | static const char *perf_ns__names[] = { |
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 4e908ec1ef64..9e999550f247 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h | |||
| @@ -255,6 +255,7 @@ enum perf_user_event_type { /* above any possible kernel type */ | |||
| 255 | PERF_RECORD_EVENT_UPDATE = 78, | 255 | PERF_RECORD_EVENT_UPDATE = 78, |
| 256 | PERF_RECORD_TIME_CONV = 79, | 256 | PERF_RECORD_TIME_CONV = 79, |
| 257 | PERF_RECORD_HEADER_FEATURE = 80, | 257 | PERF_RECORD_HEADER_FEATURE = 80, |
| 258 | PERF_RECORD_COMPRESSED = 81, | ||
| 258 | PERF_RECORD_HEADER_MAX | 259 | PERF_RECORD_HEADER_MAX |
| 259 | }; | 260 | }; |
| 260 | 261 | ||
| @@ -627,6 +628,11 @@ struct feature_event { | |||
| 627 | char data[]; | 628 | char data[]; |
| 628 | }; | 629 | }; |
| 629 | 630 | ||
| 631 | struct compressed_event { | ||
| 632 | struct perf_event_header header; | ||
| 633 | char data[]; | ||
| 634 | }; | ||
| 635 | |||
| 630 | union perf_event { | 636 | union perf_event { |
| 631 | struct perf_event_header header; | 637 | struct perf_event_header header; |
| 632 | struct mmap_event mmap; | 638 | struct mmap_event mmap; |
| @@ -660,6 +666,7 @@ union perf_event { | |||
| 660 | struct feature_event feat; | 666 | struct feature_event feat; |
| 661 | struct ksymbol_event ksymbol_event; | 667 | struct ksymbol_event ksymbol_event; |
| 662 | struct bpf_event bpf_event; | 668 | struct bpf_event bpf_event; |
| 669 | struct compressed_event pack; | ||
| 663 | }; | 670 | }; |
| 664 | 671 | ||
| 665 | void perf_event__print_totals(void); | 672 | void perf_event__print_totals(void); |
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 4b6783ff5813..69d0fa8ab16f 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c | |||
| @@ -1009,7 +1009,8 @@ int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str, | |||
| 1009 | */ | 1009 | */ |
| 1010 | int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages, | 1010 | int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages, |
| 1011 | unsigned int auxtrace_pages, | 1011 | unsigned int auxtrace_pages, |
| 1012 | bool auxtrace_overwrite, int nr_cblocks, int affinity, int flush) | 1012 | bool auxtrace_overwrite, int nr_cblocks, int affinity, int flush, |
| 1013 | int comp_level) | ||
| 1013 | { | 1014 | { |
| 1014 | struct perf_evsel *evsel; | 1015 | struct perf_evsel *evsel; |
| 1015 | const struct cpu_map *cpus = evlist->cpus; | 1016 | const struct cpu_map *cpus = evlist->cpus; |
| @@ -1019,7 +1020,8 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages, | |||
| 1019 | * Its value is decided by evsel's write_backward. | 1020 | * Its value is decided by evsel's write_backward. |
| 1020 | * So &mp should not be passed through const pointer. | 1021 | * So &mp should not be passed through const pointer. |
| 1021 | */ | 1022 | */ |
| 1022 | struct mmap_params mp = { .nr_cblocks = nr_cblocks, .affinity = affinity, .flush = flush }; | 1023 | struct mmap_params mp = { .nr_cblocks = nr_cblocks, .affinity = affinity, .flush = flush, |
| 1024 | .comp_level = comp_level }; | ||
| 1023 | 1025 | ||
| 1024 | if (!evlist->mmap) | 1026 | if (!evlist->mmap) |
| 1025 | evlist->mmap = perf_evlist__alloc_mmap(evlist, false); | 1027 | evlist->mmap = perf_evlist__alloc_mmap(evlist, false); |
| @@ -1051,7 +1053,7 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages, | |||
| 1051 | 1053 | ||
| 1052 | int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages) | 1054 | int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages) |
| 1053 | { | 1055 | { |
| 1054 | return perf_evlist__mmap_ex(evlist, pages, 0, false, 0, PERF_AFFINITY_SYS, 1); | 1056 | return perf_evlist__mmap_ex(evlist, pages, 0, false, 0, PERF_AFFINITY_SYS, 1, 0); |
| 1055 | } | 1057 | } |
| 1056 | 1058 | ||
| 1057 | int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target) | 1059 | int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target) |
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index c9a0f72677fd..49354fe24d5f 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h | |||
| @@ -178,7 +178,7 @@ unsigned long perf_event_mlock_kb_in_pages(void); | |||
| 178 | int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages, | 178 | int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages, |
| 179 | unsigned int auxtrace_pages, | 179 | unsigned int auxtrace_pages, |
| 180 | bool auxtrace_overwrite, int nr_cblocks, | 180 | bool auxtrace_overwrite, int nr_cblocks, |
| 181 | int affinity, int flush); | 181 | int affinity, int flush, int comp_level); |
| 182 | int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages); | 182 | int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages); |
| 183 | void perf_evlist__munmap(struct perf_evlist *evlist); | 183 | void perf_evlist__munmap(struct perf_evlist *evlist); |
| 184 | 184 | ||
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index a10cf4cde920..a6f572a40deb 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
| @@ -813,6 +813,8 @@ static void apply_config_terms(struct perf_evsel *evsel, | |||
| 813 | break; | 813 | break; |
| 814 | case PERF_EVSEL__CONFIG_TERM_DRV_CFG: | 814 | case PERF_EVSEL__CONFIG_TERM_DRV_CFG: |
| 815 | break; | 815 | break; |
| 816 | case PERF_EVSEL__CONFIG_TERM_PERCORE: | ||
| 817 | break; | ||
| 816 | default: | 818 | default: |
| 817 | break; | 819 | break; |
| 818 | } | 820 | } |
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 6d190cbf1070..cad54e8ba522 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h | |||
| @@ -50,6 +50,7 @@ enum term_type { | |||
| 50 | PERF_EVSEL__CONFIG_TERM_OVERWRITE, | 50 | PERF_EVSEL__CONFIG_TERM_OVERWRITE, |
| 51 | PERF_EVSEL__CONFIG_TERM_DRV_CFG, | 51 | PERF_EVSEL__CONFIG_TERM_DRV_CFG, |
| 52 | PERF_EVSEL__CONFIG_TERM_BRANCH, | 52 | PERF_EVSEL__CONFIG_TERM_BRANCH, |
| 53 | PERF_EVSEL__CONFIG_TERM_PERCORE, | ||
| 53 | }; | 54 | }; |
| 54 | 55 | ||
| 55 | struct perf_evsel_config_term { | 56 | struct perf_evsel_config_term { |
| @@ -67,6 +68,7 @@ struct perf_evsel_config_term { | |||
| 67 | bool overwrite; | 68 | bool overwrite; |
| 68 | char *branch; | 69 | char *branch; |
| 69 | unsigned long max_events; | 70 | unsigned long max_events; |
| 71 | bool percore; | ||
| 70 | } val; | 72 | } val; |
| 71 | bool weak; | 73 | bool weak; |
| 72 | }; | 74 | }; |
| @@ -158,6 +160,7 @@ struct perf_evsel { | |||
| 158 | struct perf_evsel **metric_events; | 160 | struct perf_evsel **metric_events; |
| 159 | bool collect_stat; | 161 | bool collect_stat; |
| 160 | bool weak_group; | 162 | bool weak_group; |
| 163 | bool percore; | ||
| 161 | const char *pmu_name; | 164 | const char *pmu_name; |
| 162 | struct { | 165 | struct { |
| 163 | perf_evsel__sb_cb_t *cb; | 166 | perf_evsel__sb_cb_t *cb; |
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 2d2af2ac2b1e..847ae51a524b 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
| @@ -1344,6 +1344,30 @@ out: | |||
| 1344 | return ret; | 1344 | return ret; |
| 1345 | } | 1345 | } |
| 1346 | 1346 | ||
| 1347 | static int write_compressed(struct feat_fd *ff __maybe_unused, | ||
| 1348 | struct perf_evlist *evlist __maybe_unused) | ||
| 1349 | { | ||
| 1350 | int ret; | ||
| 1351 | |||
| 1352 | ret = do_write(ff, &(ff->ph->env.comp_ver), sizeof(ff->ph->env.comp_ver)); | ||
| 1353 | if (ret) | ||
| 1354 | return ret; | ||
| 1355 | |||
| 1356 | ret = do_write(ff, &(ff->ph->env.comp_type), sizeof(ff->ph->env.comp_type)); | ||
| 1357 | if (ret) | ||
| 1358 | return ret; | ||
| 1359 | |||
| 1360 | ret = do_write(ff, &(ff->ph->env.comp_level), sizeof(ff->ph->env.comp_level)); | ||
| 1361 | if (ret) | ||
| 1362 | return ret; | ||
| 1363 | |||
| 1364 | ret = do_write(ff, &(ff->ph->env.comp_ratio), sizeof(ff->ph->env.comp_ratio)); | ||
| 1365 | if (ret) | ||
| 1366 | return ret; | ||
| 1367 | |||
| 1368 | return do_write(ff, &(ff->ph->env.comp_mmap_len), sizeof(ff->ph->env.comp_mmap_len)); | ||
| 1369 | } | ||
| 1370 | |||
| 1347 | static void print_hostname(struct feat_fd *ff, FILE *fp) | 1371 | static void print_hostname(struct feat_fd *ff, FILE *fp) |
| 1348 | { | 1372 | { |
| 1349 | fprintf(fp, "# hostname : %s\n", ff->ph->env.hostname); | 1373 | fprintf(fp, "# hostname : %s\n", ff->ph->env.hostname); |
| @@ -1688,6 +1712,13 @@ static void print_cache(struct feat_fd *ff, FILE *fp __maybe_unused) | |||
| 1688 | } | 1712 | } |
| 1689 | } | 1713 | } |
| 1690 | 1714 | ||
| 1715 | static void print_compressed(struct feat_fd *ff, FILE *fp) | ||
| 1716 | { | ||
| 1717 | fprintf(fp, "# compressed : %s, level = %d, ratio = %d\n", | ||
| 1718 | ff->ph->env.comp_type == PERF_COMP_ZSTD ? "Zstd" : "Unknown", | ||
| 1719 | ff->ph->env.comp_level, ff->ph->env.comp_ratio); | ||
| 1720 | } | ||
| 1721 | |||
| 1691 | static void print_pmu_mappings(struct feat_fd *ff, FILE *fp) | 1722 | static void print_pmu_mappings(struct feat_fd *ff, FILE *fp) |
| 1692 | { | 1723 | { |
| 1693 | const char *delimiter = "# pmu mappings: "; | 1724 | const char *delimiter = "# pmu mappings: "; |
| @@ -2667,6 +2698,27 @@ out: | |||
| 2667 | return err; | 2698 | return err; |
| 2668 | } | 2699 | } |
| 2669 | 2700 | ||
| 2701 | static int process_compressed(struct feat_fd *ff, | ||
| 2702 | void *data __maybe_unused) | ||
| 2703 | { | ||
| 2704 | if (do_read_u32(ff, &(ff->ph->env.comp_ver))) | ||
| 2705 | return -1; | ||
| 2706 | |||
| 2707 | if (do_read_u32(ff, &(ff->ph->env.comp_type))) | ||
| 2708 | return -1; | ||
| 2709 | |||
| 2710 | if (do_read_u32(ff, &(ff->ph->env.comp_level))) | ||
| 2711 | return -1; | ||
| 2712 | |||
| 2713 | if (do_read_u32(ff, &(ff->ph->env.comp_ratio))) | ||
| 2714 | return -1; | ||
| 2715 | |||
| 2716 | if (do_read_u32(ff, &(ff->ph->env.comp_mmap_len))) | ||
| 2717 | return -1; | ||
| 2718 | |||
| 2719 | return 0; | ||
| 2720 | } | ||
| 2721 | |||
| 2670 | struct feature_ops { | 2722 | struct feature_ops { |
| 2671 | int (*write)(struct feat_fd *ff, struct perf_evlist *evlist); | 2723 | int (*write)(struct feat_fd *ff, struct perf_evlist *evlist); |
| 2672 | void (*print)(struct feat_fd *ff, FILE *fp); | 2724 | void (*print)(struct feat_fd *ff, FILE *fp); |
| @@ -2730,6 +2782,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = { | |||
| 2730 | FEAT_OPN(DIR_FORMAT, dir_format, false), | 2782 | FEAT_OPN(DIR_FORMAT, dir_format, false), |
| 2731 | FEAT_OPR(BPF_PROG_INFO, bpf_prog_info, false), | 2783 | FEAT_OPR(BPF_PROG_INFO, bpf_prog_info, false), |
| 2732 | FEAT_OPR(BPF_BTF, bpf_btf, false), | 2784 | FEAT_OPR(BPF_BTF, bpf_btf, false), |
| 2785 | FEAT_OPR(COMPRESSED, compressed, false), | ||
| 2733 | }; | 2786 | }; |
| 2734 | 2787 | ||
| 2735 | struct header_print_data { | 2788 | struct header_print_data { |
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index 386da49e1bfa..5b3abe4172e2 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h | |||
| @@ -42,6 +42,7 @@ enum { | |||
| 42 | HEADER_DIR_FORMAT, | 42 | HEADER_DIR_FORMAT, |
| 43 | HEADER_BPF_PROG_INFO, | 43 | HEADER_BPF_PROG_INFO, |
| 44 | HEADER_BPF_BTF, | 44 | HEADER_BPF_BTF, |
| 45 | HEADER_COMPRESSED, | ||
| 45 | HEADER_LAST_FEATURE, | 46 | HEADER_LAST_FEATURE, |
| 46 | HEADER_FEAT_BITS = 256, | 47 | HEADER_FEAT_BITS = 256, |
| 47 | }; | 48 | }; |
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c index 872fab163585..f4c3c84b090f 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c | |||
| @@ -58,6 +58,7 @@ enum intel_pt_pkt_state { | |||
| 58 | INTEL_PT_STATE_NO_IP, | 58 | INTEL_PT_STATE_NO_IP, |
| 59 | INTEL_PT_STATE_ERR_RESYNC, | 59 | INTEL_PT_STATE_ERR_RESYNC, |
| 60 | INTEL_PT_STATE_IN_SYNC, | 60 | INTEL_PT_STATE_IN_SYNC, |
| 61 | INTEL_PT_STATE_TNT_CONT, | ||
| 61 | INTEL_PT_STATE_TNT, | 62 | INTEL_PT_STATE_TNT, |
| 62 | INTEL_PT_STATE_TIP, | 63 | INTEL_PT_STATE_TIP, |
| 63 | INTEL_PT_STATE_TIP_PGD, | 64 | INTEL_PT_STATE_TIP_PGD, |
| @@ -72,8 +73,9 @@ static inline bool intel_pt_sample_time(enum intel_pt_pkt_state pkt_state) | |||
| 72 | case INTEL_PT_STATE_NO_IP: | 73 | case INTEL_PT_STATE_NO_IP: |
| 73 | case INTEL_PT_STATE_ERR_RESYNC: | 74 | case INTEL_PT_STATE_ERR_RESYNC: |
| 74 | case INTEL_PT_STATE_IN_SYNC: | 75 | case INTEL_PT_STATE_IN_SYNC: |
| 75 | case INTEL_PT_STATE_TNT: | 76 | case INTEL_PT_STATE_TNT_CONT: |
| 76 | return true; | 77 | return true; |
| 78 | case INTEL_PT_STATE_TNT: | ||
| 77 | case INTEL_PT_STATE_TIP: | 79 | case INTEL_PT_STATE_TIP: |
| 78 | case INTEL_PT_STATE_TIP_PGD: | 80 | case INTEL_PT_STATE_TIP_PGD: |
| 79 | case INTEL_PT_STATE_FUP: | 81 | case INTEL_PT_STATE_FUP: |
| @@ -888,16 +890,20 @@ static uint64_t intel_pt_next_period(struct intel_pt_decoder *decoder) | |||
| 888 | timestamp = decoder->timestamp + decoder->timestamp_insn_cnt; | 890 | timestamp = decoder->timestamp + decoder->timestamp_insn_cnt; |
| 889 | masked_timestamp = timestamp & decoder->period_mask; | 891 | masked_timestamp = timestamp & decoder->period_mask; |
| 890 | if (decoder->continuous_period) { | 892 | if (decoder->continuous_period) { |
| 891 | if (masked_timestamp != decoder->last_masked_timestamp) | 893 | if (masked_timestamp > decoder->last_masked_timestamp) |
| 892 | return 1; | 894 | return 1; |
| 893 | } else { | 895 | } else { |
| 894 | timestamp += 1; | 896 | timestamp += 1; |
| 895 | masked_timestamp = timestamp & decoder->period_mask; | 897 | masked_timestamp = timestamp & decoder->period_mask; |
| 896 | if (masked_timestamp != decoder->last_masked_timestamp) { | 898 | if (masked_timestamp > decoder->last_masked_timestamp) { |
| 897 | decoder->last_masked_timestamp = masked_timestamp; | 899 | decoder->last_masked_timestamp = masked_timestamp; |
| 898 | decoder->continuous_period = true; | 900 | decoder->continuous_period = true; |
| 899 | } | 901 | } |
| 900 | } | 902 | } |
| 903 | |||
| 904 | if (masked_timestamp < decoder->last_masked_timestamp) | ||
| 905 | return decoder->period_ticks; | ||
| 906 | |||
| 901 | return decoder->period_ticks - (timestamp - masked_timestamp); | 907 | return decoder->period_ticks - (timestamp - masked_timestamp); |
| 902 | } | 908 | } |
| 903 | 909 | ||
| @@ -926,7 +932,10 @@ static void intel_pt_sample_insn(struct intel_pt_decoder *decoder) | |||
| 926 | case INTEL_PT_PERIOD_TICKS: | 932 | case INTEL_PT_PERIOD_TICKS: |
| 927 | timestamp = decoder->timestamp + decoder->timestamp_insn_cnt; | 933 | timestamp = decoder->timestamp + decoder->timestamp_insn_cnt; |
| 928 | masked_timestamp = timestamp & decoder->period_mask; | 934 | masked_timestamp = timestamp & decoder->period_mask; |
| 929 | decoder->last_masked_timestamp = masked_timestamp; | 935 | if (masked_timestamp > decoder->last_masked_timestamp) |
| 936 | decoder->last_masked_timestamp = masked_timestamp; | ||
| 937 | else | ||
| 938 | decoder->last_masked_timestamp += decoder->period_ticks; | ||
| 930 | break; | 939 | break; |
| 931 | case INTEL_PT_PERIOD_NONE: | 940 | case INTEL_PT_PERIOD_NONE: |
| 932 | case INTEL_PT_PERIOD_MTC: | 941 | case INTEL_PT_PERIOD_MTC: |
| @@ -1254,7 +1263,9 @@ static int intel_pt_walk_tnt(struct intel_pt_decoder *decoder) | |||
| 1254 | return -ENOENT; | 1263 | return -ENOENT; |
| 1255 | } | 1264 | } |
| 1256 | decoder->tnt.count -= 1; | 1265 | decoder->tnt.count -= 1; |
| 1257 | if (!decoder->tnt.count) | 1266 | if (decoder->tnt.count) |
| 1267 | decoder->pkt_state = INTEL_PT_STATE_TNT_CONT; | ||
| 1268 | else | ||
| 1258 | decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; | 1269 | decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; |
| 1259 | decoder->tnt.payload <<= 1; | 1270 | decoder->tnt.payload <<= 1; |
| 1260 | decoder->state.from_ip = decoder->ip; | 1271 | decoder->state.from_ip = decoder->ip; |
| @@ -1285,7 +1296,9 @@ static int intel_pt_walk_tnt(struct intel_pt_decoder *decoder) | |||
| 1285 | 1296 | ||
| 1286 | if (intel_pt_insn.branch == INTEL_PT_BR_CONDITIONAL) { | 1297 | if (intel_pt_insn.branch == INTEL_PT_BR_CONDITIONAL) { |
| 1287 | decoder->tnt.count -= 1; | 1298 | decoder->tnt.count -= 1; |
| 1288 | if (!decoder->tnt.count) | 1299 | if (decoder->tnt.count) |
| 1300 | decoder->pkt_state = INTEL_PT_STATE_TNT_CONT; | ||
| 1301 | else | ||
| 1289 | decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; | 1302 | decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; |
| 1290 | if (decoder->tnt.payload & BIT63) { | 1303 | if (decoder->tnt.payload & BIT63) { |
| 1291 | decoder->tnt.payload <<= 1; | 1304 | decoder->tnt.payload <<= 1; |
| @@ -1305,8 +1318,11 @@ static int intel_pt_walk_tnt(struct intel_pt_decoder *decoder) | |||
| 1305 | return 0; | 1318 | return 0; |
| 1306 | } | 1319 | } |
| 1307 | decoder->ip += intel_pt_insn.length; | 1320 | decoder->ip += intel_pt_insn.length; |
| 1308 | if (!decoder->tnt.count) | 1321 | if (!decoder->tnt.count) { |
| 1322 | decoder->sample_timestamp = decoder->timestamp; | ||
| 1323 | decoder->sample_insn_cnt = decoder->timestamp_insn_cnt; | ||
| 1309 | return -EAGAIN; | 1324 | return -EAGAIN; |
| 1325 | } | ||
| 1310 | decoder->tnt.payload <<= 1; | 1326 | decoder->tnt.payload <<= 1; |
| 1311 | continue; | 1327 | continue; |
| 1312 | } | 1328 | } |
| @@ -2365,6 +2381,7 @@ const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder) | |||
| 2365 | err = intel_pt_walk_trace(decoder); | 2381 | err = intel_pt_walk_trace(decoder); |
| 2366 | break; | 2382 | break; |
| 2367 | case INTEL_PT_STATE_TNT: | 2383 | case INTEL_PT_STATE_TNT: |
| 2384 | case INTEL_PT_STATE_TNT_CONT: | ||
| 2368 | err = intel_pt_walk_tnt(decoder); | 2385 | err = intel_pt_walk_tnt(decoder); |
| 2369 | if (err == -EAGAIN) | 2386 | if (err == -EAGAIN) |
| 2370 | err = intel_pt_walk_trace(decoder); | 2387 | err = intel_pt_walk_trace(decoder); |
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 3c520baa198c..28a9541c4835 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c | |||
| @@ -1234,8 +1234,9 @@ static char *get_kernel_version(const char *root_dir) | |||
| 1234 | if (!file) | 1234 | if (!file) |
| 1235 | return NULL; | 1235 | return NULL; |
| 1236 | 1236 | ||
| 1237 | version[0] = '\0'; | ||
| 1238 | tmp = fgets(version, sizeof(version), file); | 1237 | tmp = fgets(version, sizeof(version), file); |
| 1238 | if (!tmp) | ||
| 1239 | *version = '\0'; | ||
| 1239 | fclose(file); | 1240 | fclose(file); |
| 1240 | 1241 | ||
| 1241 | name = strstr(version, prefix); | 1242 | name = strstr(version, prefix); |
diff --git a/tools/perf/util/mmap.c b/tools/perf/util/mmap.c index ef3d79b2c90b..868c0b0e909c 100644 --- a/tools/perf/util/mmap.c +++ b/tools/perf/util/mmap.c | |||
| @@ -157,6 +157,10 @@ void __weak auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp __mayb | |||
| 157 | } | 157 | } |
| 158 | 158 | ||
| 159 | #ifdef HAVE_AIO_SUPPORT | 159 | #ifdef HAVE_AIO_SUPPORT |
| 160 | static int perf_mmap__aio_enabled(struct perf_mmap *map) | ||
| 161 | { | ||
| 162 | return map->aio.nr_cblocks > 0; | ||
| 163 | } | ||
| 160 | 164 | ||
| 161 | #ifdef HAVE_LIBNUMA_SUPPORT | 165 | #ifdef HAVE_LIBNUMA_SUPPORT |
| 162 | static int perf_mmap__aio_alloc(struct perf_mmap *map, int idx) | 166 | static int perf_mmap__aio_alloc(struct perf_mmap *map, int idx) |
| @@ -198,7 +202,7 @@ static int perf_mmap__aio_bind(struct perf_mmap *map, int idx, int cpu, int affi | |||
| 198 | 202 | ||
| 199 | return 0; | 203 | return 0; |
| 200 | } | 204 | } |
| 201 | #else | 205 | #else /* !HAVE_LIBNUMA_SUPPORT */ |
| 202 | static int perf_mmap__aio_alloc(struct perf_mmap *map, int idx) | 206 | static int perf_mmap__aio_alloc(struct perf_mmap *map, int idx) |
| 203 | { | 207 | { |
| 204 | map->aio.data[idx] = malloc(perf_mmap__mmap_len(map)); | 208 | map->aio.data[idx] = malloc(perf_mmap__mmap_len(map)); |
| @@ -285,81 +289,12 @@ static void perf_mmap__aio_munmap(struct perf_mmap *map) | |||
| 285 | zfree(&map->aio.cblocks); | 289 | zfree(&map->aio.cblocks); |
| 286 | zfree(&map->aio.aiocb); | 290 | zfree(&map->aio.aiocb); |
| 287 | } | 291 | } |
| 288 | 292 | #else /* !HAVE_AIO_SUPPORT */ | |
| 289 | int perf_mmap__aio_push(struct perf_mmap *md, void *to, int idx, | 293 | static int perf_mmap__aio_enabled(struct perf_mmap *map __maybe_unused) |
| 290 | int push(void *to, struct aiocb *cblock, void *buf, size_t size, off_t off), | ||
| 291 | off_t *off) | ||
| 292 | { | 294 | { |
| 293 | u64 head = perf_mmap__read_head(md); | 295 | return 0; |
| 294 | unsigned char *data = md->base + page_size; | ||
| 295 | unsigned long size, size0 = 0; | ||
| 296 | void *buf; | ||
| 297 | int rc = 0; | ||
| 298 | |||
| 299 | rc = perf_mmap__read_init(md); | ||
| 300 | if (rc < 0) | ||
| 301 | return (rc == -EAGAIN) ? 0 : -1; | ||
| 302 | |||
| 303 | /* | ||
| 304 | * md->base data is copied into md->data[idx] buffer to | ||
| 305 | * release space in the kernel buffer as fast as possible, | ||
| 306 | * thru perf_mmap__consume() below. | ||
| 307 | * | ||
| 308 | * That lets the kernel to proceed with storing more | ||
| 309 | * profiling data into the kernel buffer earlier than other | ||
| 310 | * per-cpu kernel buffers are handled. | ||
| 311 | * | ||
| 312 | * Coping can be done in two steps in case the chunk of | ||
| 313 | * profiling data crosses the upper bound of the kernel buffer. | ||
| 314 | * In this case we first move part of data from md->start | ||
| 315 | * till the upper bound and then the reminder from the | ||
| 316 | * beginning of the kernel buffer till the end of | ||
| 317 | * the data chunk. | ||
| 318 | */ | ||
| 319 | |||
| 320 | size = md->end - md->start; | ||
| 321 | |||
| 322 | if ((md->start & md->mask) + size != (md->end & md->mask)) { | ||
| 323 | buf = &data[md->start & md->mask]; | ||
| 324 | size = md->mask + 1 - (md->start & md->mask); | ||
| 325 | md->start += size; | ||
| 326 | memcpy(md->aio.data[idx], buf, size); | ||
| 327 | size0 = size; | ||
| 328 | } | ||
| 329 | |||
| 330 | buf = &data[md->start & md->mask]; | ||
| 331 | size = md->end - md->start; | ||
| 332 | md->start += size; | ||
| 333 | memcpy(md->aio.data[idx] + size0, buf, size); | ||
| 334 | |||
| 335 | /* | ||
| 336 | * Increment md->refcount to guard md->data[idx] buffer | ||
| 337 | * from premature deallocation because md object can be | ||
| 338 | * released earlier than aio write request started | ||
| 339 | * on mmap->data[idx] is complete. | ||
| 340 | * | ||
| 341 | * perf_mmap__put() is done at record__aio_complete() | ||
| 342 | * after started request completion. | ||
| 343 | */ | ||
| 344 | perf_mmap__get(md); | ||
| 345 | |||
| 346 | md->prev = head; | ||
| 347 | perf_mmap__consume(md); | ||
| 348 | |||
| 349 | rc = push(to, &md->aio.cblocks[idx], md->aio.data[idx], size0 + size, *off); | ||
| 350 | if (!rc) { | ||
| 351 | *off += size0 + size; | ||
| 352 | } else { | ||
| 353 | /* | ||
| 354 | * Decrement md->refcount back if aio write | ||
| 355 | * operation failed to start. | ||
| 356 | */ | ||
| 357 | perf_mmap__put(md); | ||
| 358 | } | ||
| 359 | |||
| 360 | return rc; | ||
| 361 | } | 296 | } |
| 362 | #else | 297 | |
| 363 | static int perf_mmap__aio_mmap(struct perf_mmap *map __maybe_unused, | 298 | static int perf_mmap__aio_mmap(struct perf_mmap *map __maybe_unused, |
| 364 | struct mmap_params *mp __maybe_unused) | 299 | struct mmap_params *mp __maybe_unused) |
| 365 | { | 300 | { |
| @@ -374,6 +309,10 @@ static void perf_mmap__aio_munmap(struct perf_mmap *map __maybe_unused) | |||
| 374 | void perf_mmap__munmap(struct perf_mmap *map) | 309 | void perf_mmap__munmap(struct perf_mmap *map) |
| 375 | { | 310 | { |
| 376 | perf_mmap__aio_munmap(map); | 311 | perf_mmap__aio_munmap(map); |
| 312 | if (map->data != NULL) { | ||
| 313 | munmap(map->data, perf_mmap__mmap_len(map)); | ||
| 314 | map->data = NULL; | ||
| 315 | } | ||
| 377 | if (map->base != NULL) { | 316 | if (map->base != NULL) { |
| 378 | munmap(map->base, perf_mmap__mmap_len(map)); | 317 | munmap(map->base, perf_mmap__mmap_len(map)); |
| 379 | map->base = NULL; | 318 | map->base = NULL; |
| @@ -442,6 +381,19 @@ int perf_mmap__mmap(struct perf_mmap *map, struct mmap_params *mp, int fd, int c | |||
| 442 | 381 | ||
| 443 | map->flush = mp->flush; | 382 | map->flush = mp->flush; |
| 444 | 383 | ||
| 384 | map->comp_level = mp->comp_level; | ||
| 385 | |||
| 386 | if (map->comp_level && !perf_mmap__aio_enabled(map)) { | ||
| 387 | map->data = mmap(NULL, perf_mmap__mmap_len(map), PROT_READ|PROT_WRITE, | ||
| 388 | MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); | ||
| 389 | if (map->data == MAP_FAILED) { | ||
| 390 | pr_debug2("failed to mmap data buffer, error %d\n", | ||
| 391 | errno); | ||
| 392 | map->data = NULL; | ||
| 393 | return -1; | ||
| 394 | } | ||
| 395 | } | ||
| 396 | |||
| 445 | if (auxtrace_mmap__mmap(&map->auxtrace_mmap, | 397 | if (auxtrace_mmap__mmap(&map->auxtrace_mmap, |
| 446 | &mp->auxtrace_mp, map->base, fd)) | 398 | &mp->auxtrace_mp, map->base, fd)) |
| 447 | return -1; | 399 | return -1; |
| @@ -540,7 +492,7 @@ int perf_mmap__push(struct perf_mmap *md, void *to, | |||
| 540 | 492 | ||
| 541 | rc = perf_mmap__read_init(md); | 493 | rc = perf_mmap__read_init(md); |
| 542 | if (rc < 0) | 494 | if (rc < 0) |
| 543 | return (rc == -EAGAIN) ? 0 : -1; | 495 | return (rc == -EAGAIN) ? 1 : -1; |
| 544 | 496 | ||
| 545 | size = md->end - md->start; | 497 | size = md->end - md->start; |
| 546 | 498 | ||
diff --git a/tools/perf/util/mmap.h b/tools/perf/util/mmap.h index b82f8c2d55c4..274ce389cd84 100644 --- a/tools/perf/util/mmap.h +++ b/tools/perf/util/mmap.h | |||
| @@ -40,6 +40,8 @@ struct perf_mmap { | |||
| 40 | #endif | 40 | #endif |
| 41 | cpu_set_t affinity_mask; | 41 | cpu_set_t affinity_mask; |
| 42 | u64 flush; | 42 | u64 flush; |
| 43 | void *data; | ||
| 44 | int comp_level; | ||
| 43 | }; | 45 | }; |
| 44 | 46 | ||
| 45 | /* | 47 | /* |
| @@ -71,7 +73,7 @@ enum bkw_mmap_state { | |||
| 71 | }; | 73 | }; |
| 72 | 74 | ||
| 73 | struct mmap_params { | 75 | struct mmap_params { |
| 74 | int prot, mask, nr_cblocks, affinity, flush; | 76 | int prot, mask, nr_cblocks, affinity, flush, comp_level; |
| 75 | struct auxtrace_mmap_params auxtrace_mp; | 77 | struct auxtrace_mmap_params auxtrace_mp; |
| 76 | }; | 78 | }; |
| 77 | 79 | ||
| @@ -99,18 +101,6 @@ union perf_event *perf_mmap__read_event(struct perf_mmap *map); | |||
| 99 | 101 | ||
| 100 | int perf_mmap__push(struct perf_mmap *md, void *to, | 102 | int perf_mmap__push(struct perf_mmap *md, void *to, |
| 101 | int push(struct perf_mmap *map, void *to, void *buf, size_t size)); | 103 | int push(struct perf_mmap *map, void *to, void *buf, size_t size)); |
| 102 | #ifdef HAVE_AIO_SUPPORT | ||
| 103 | int perf_mmap__aio_push(struct perf_mmap *md, void *to, int idx, | ||
| 104 | int push(void *to, struct aiocb *cblock, void *buf, size_t size, off_t off), | ||
| 105 | off_t *off); | ||
| 106 | #else | ||
| 107 | static inline int perf_mmap__aio_push(struct perf_mmap *md __maybe_unused, void *to __maybe_unused, int idx __maybe_unused, | ||
| 108 | int push(void *to, struct aiocb *cblock, void *buf, size_t size, off_t off) __maybe_unused, | ||
| 109 | off_t *off __maybe_unused) | ||
| 110 | { | ||
| 111 | return 0; | ||
| 112 | } | ||
| 113 | #endif | ||
| 114 | 104 | ||
| 115 | size_t perf_mmap__mmap_len(struct perf_mmap *map); | 105 | size_t perf_mmap__mmap_len(struct perf_mmap *map); |
| 116 | 106 | ||
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 4432bfe039fd..cf0b9b81c5aa 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c | |||
| @@ -950,6 +950,7 @@ static const char *config_term_names[__PARSE_EVENTS__TERM_TYPE_NR] = { | |||
| 950 | [PARSE_EVENTS__TERM_TYPE_OVERWRITE] = "overwrite", | 950 | [PARSE_EVENTS__TERM_TYPE_OVERWRITE] = "overwrite", |
| 951 | [PARSE_EVENTS__TERM_TYPE_NOOVERWRITE] = "no-overwrite", | 951 | [PARSE_EVENTS__TERM_TYPE_NOOVERWRITE] = "no-overwrite", |
| 952 | [PARSE_EVENTS__TERM_TYPE_DRV_CFG] = "driver-config", | 952 | [PARSE_EVENTS__TERM_TYPE_DRV_CFG] = "driver-config", |
| 953 | [PARSE_EVENTS__TERM_TYPE_PERCORE] = "percore", | ||
| 953 | }; | 954 | }; |
| 954 | 955 | ||
| 955 | static bool config_term_shrinked; | 956 | static bool config_term_shrinked; |
| @@ -970,6 +971,7 @@ config_term_avail(int term_type, struct parse_events_error *err) | |||
| 970 | case PARSE_EVENTS__TERM_TYPE_CONFIG2: | 971 | case PARSE_EVENTS__TERM_TYPE_CONFIG2: |
| 971 | case PARSE_EVENTS__TERM_TYPE_NAME: | 972 | case PARSE_EVENTS__TERM_TYPE_NAME: |
| 972 | case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD: | 973 | case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD: |
| 974 | case PARSE_EVENTS__TERM_TYPE_PERCORE: | ||
| 973 | return true; | 975 | return true; |
| 974 | default: | 976 | default: |
| 975 | if (!err) | 977 | if (!err) |
| @@ -1061,6 +1063,14 @@ do { \ | |||
| 1061 | case PARSE_EVENTS__TERM_TYPE_MAX_EVENTS: | 1063 | case PARSE_EVENTS__TERM_TYPE_MAX_EVENTS: |
| 1062 | CHECK_TYPE_VAL(NUM); | 1064 | CHECK_TYPE_VAL(NUM); |
| 1063 | break; | 1065 | break; |
| 1066 | case PARSE_EVENTS__TERM_TYPE_PERCORE: | ||
| 1067 | CHECK_TYPE_VAL(NUM); | ||
| 1068 | if ((unsigned int)term->val.num > 1) { | ||
| 1069 | err->str = strdup("expected 0 or 1"); | ||
| 1070 | err->idx = term->err_val; | ||
| 1071 | return -EINVAL; | ||
| 1072 | } | ||
| 1073 | break; | ||
| 1064 | default: | 1074 | default: |
| 1065 | err->str = strdup("unknown term"); | 1075 | err->str = strdup("unknown term"); |
| 1066 | err->idx = term->err_term; | 1076 | err->idx = term->err_term; |
| @@ -1199,6 +1209,10 @@ do { \ | |||
| 1199 | case PARSE_EVENTS__TERM_TYPE_DRV_CFG: | 1209 | case PARSE_EVENTS__TERM_TYPE_DRV_CFG: |
| 1200 | ADD_CONFIG_TERM(DRV_CFG, drv_cfg, term->val.str); | 1210 | ADD_CONFIG_TERM(DRV_CFG, drv_cfg, term->val.str); |
| 1201 | break; | 1211 | break; |
| 1212 | case PARSE_EVENTS__TERM_TYPE_PERCORE: | ||
| 1213 | ADD_CONFIG_TERM(PERCORE, percore, | ||
| 1214 | term->val.num ? true : false); | ||
| 1215 | break; | ||
| 1202 | default: | 1216 | default: |
| 1203 | break; | 1217 | break; |
| 1204 | } | 1218 | } |
| @@ -1260,6 +1274,18 @@ int parse_events_add_tool(struct parse_events_state *parse_state, | |||
| 1260 | return add_event_tool(list, &parse_state->idx, tool_event); | 1274 | return add_event_tool(list, &parse_state->idx, tool_event); |
| 1261 | } | 1275 | } |
| 1262 | 1276 | ||
| 1277 | static bool config_term_percore(struct list_head *config_terms) | ||
| 1278 | { | ||
| 1279 | struct perf_evsel_config_term *term; | ||
| 1280 | |||
| 1281 | list_for_each_entry(term, config_terms, list) { | ||
| 1282 | if (term->type == PERF_EVSEL__CONFIG_TERM_PERCORE) | ||
| 1283 | return term->val.percore; | ||
| 1284 | } | ||
| 1285 | |||
| 1286 | return false; | ||
| 1287 | } | ||
| 1288 | |||
| 1263 | int parse_events_add_pmu(struct parse_events_state *parse_state, | 1289 | int parse_events_add_pmu(struct parse_events_state *parse_state, |
| 1264 | struct list_head *list, char *name, | 1290 | struct list_head *list, char *name, |
| 1265 | struct list_head *head_config, | 1291 | struct list_head *head_config, |
| @@ -1333,6 +1359,7 @@ int parse_events_add_pmu(struct parse_events_state *parse_state, | |||
| 1333 | evsel->metric_name = info.metric_name; | 1359 | evsel->metric_name = info.metric_name; |
| 1334 | evsel->pmu_name = name; | 1360 | evsel->pmu_name = name; |
| 1335 | evsel->use_uncore_alias = use_uncore_alias; | 1361 | evsel->use_uncore_alias = use_uncore_alias; |
| 1362 | evsel->percore = config_term_percore(&evsel->config_terms); | ||
| 1336 | } | 1363 | } |
| 1337 | 1364 | ||
| 1338 | return evsel ? 0 : -ENOMEM; | 1365 | return evsel ? 0 : -ENOMEM; |
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index a052cd6ac63e..f7139e1a2fd3 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h | |||
| @@ -75,6 +75,7 @@ enum { | |||
| 75 | PARSE_EVENTS__TERM_TYPE_NOOVERWRITE, | 75 | PARSE_EVENTS__TERM_TYPE_NOOVERWRITE, |
| 76 | PARSE_EVENTS__TERM_TYPE_OVERWRITE, | 76 | PARSE_EVENTS__TERM_TYPE_OVERWRITE, |
| 77 | PARSE_EVENTS__TERM_TYPE_DRV_CFG, | 77 | PARSE_EVENTS__TERM_TYPE_DRV_CFG, |
| 78 | PARSE_EVENTS__TERM_TYPE_PERCORE, | ||
| 78 | __PARSE_EVENTS__TERM_TYPE_NR, | 79 | __PARSE_EVENTS__TERM_TYPE_NR, |
| 79 | }; | 80 | }; |
| 80 | 81 | ||
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l index c54bfe88626c..ca6098874fe2 100644 --- a/tools/perf/util/parse-events.l +++ b/tools/perf/util/parse-events.l | |||
| @@ -283,6 +283,7 @@ inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_INHERIT); } | |||
| 283 | no-inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOINHERIT); } | 283 | no-inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOINHERIT); } |
| 284 | overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_OVERWRITE); } | 284 | overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_OVERWRITE); } |
| 285 | no-overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOOVERWRITE); } | 285 | no-overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOOVERWRITE); } |
| 286 | percore { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_PERCORE); } | ||
| 286 | , { return ','; } | 287 | , { return ','; } |
| 287 | "/" { BEGIN(INITIAL); return '/'; } | 288 | "/" { BEGIN(INITIAL); return '/'; } |
| 288 | {name_minus} { return str(yyscanner, PE_NAME); } | 289 | {name_minus} { return str(yyscanner, PE_NAME); } |
diff --git a/tools/perf/util/parse-regs-options.c b/tools/perf/util/parse-regs-options.c index e6599e290f46..08581e276225 100644 --- a/tools/perf/util/parse-regs-options.c +++ b/tools/perf/util/parse-regs-options.c | |||
| @@ -5,13 +5,14 @@ | |||
| 5 | #include <subcmd/parse-options.h> | 5 | #include <subcmd/parse-options.h> |
| 6 | #include "util/parse-regs-options.h" | 6 | #include "util/parse-regs-options.h" |
| 7 | 7 | ||
| 8 | int | 8 | static int |
| 9 | parse_regs(const struct option *opt, const char *str, int unset) | 9 | __parse_regs(const struct option *opt, const char *str, int unset, bool intr) |
| 10 | { | 10 | { |
| 11 | uint64_t *mode = (uint64_t *)opt->value; | 11 | uint64_t *mode = (uint64_t *)opt->value; |
| 12 | const struct sample_reg *r; | 12 | const struct sample_reg *r; |
| 13 | char *s, *os = NULL, *p; | 13 | char *s, *os = NULL, *p; |
| 14 | int ret = -1; | 14 | int ret = -1; |
| 15 | uint64_t mask; | ||
| 15 | 16 | ||
| 16 | if (unset) | 17 | if (unset) |
| 17 | return 0; | 18 | return 0; |
| @@ -22,6 +23,11 @@ parse_regs(const struct option *opt, const char *str, int unset) | |||
| 22 | if (*mode) | 23 | if (*mode) |
| 23 | return -1; | 24 | return -1; |
| 24 | 25 | ||
| 26 | if (intr) | ||
| 27 | mask = arch__intr_reg_mask(); | ||
| 28 | else | ||
| 29 | mask = arch__user_reg_mask(); | ||
| 30 | |||
| 25 | /* str may be NULL in case no arg is passed to -I */ | 31 | /* str may be NULL in case no arg is passed to -I */ |
| 26 | if (str) { | 32 | if (str) { |
| 27 | /* because str is read-only */ | 33 | /* because str is read-only */ |
| @@ -37,19 +43,20 @@ parse_regs(const struct option *opt, const char *str, int unset) | |||
| 37 | if (!strcmp(s, "?")) { | 43 | if (!strcmp(s, "?")) { |
| 38 | fprintf(stderr, "available registers: "); | 44 | fprintf(stderr, "available registers: "); |
| 39 | for (r = sample_reg_masks; r->name; r++) { | 45 | for (r = sample_reg_masks; r->name; r++) { |
| 40 | fprintf(stderr, "%s ", r->name); | 46 | if (r->mask & mask) |
| 47 | fprintf(stderr, "%s ", r->name); | ||
| 41 | } | 48 | } |
| 42 | fputc('\n', stderr); | 49 | fputc('\n', stderr); |
| 43 | /* just printing available regs */ | 50 | /* just printing available regs */ |
| 44 | return -1; | 51 | return -1; |
| 45 | } | 52 | } |
| 46 | for (r = sample_reg_masks; r->name; r++) { | 53 | for (r = sample_reg_masks; r->name; r++) { |
| 47 | if (!strcasecmp(s, r->name)) | 54 | if ((r->mask & mask) && !strcasecmp(s, r->name)) |
| 48 | break; | 55 | break; |
| 49 | } | 56 | } |
| 50 | if (!r->name) { | 57 | if (!r->name) { |
| 51 | ui__warning("unknown register %s," | 58 | ui__warning("Unknown register \"%s\", check man page or run \"perf record %s?\"\n", |
| 52 | " check man page\n", s); | 59 | s, intr ? "-I" : "--user-regs="); |
| 53 | goto error; | 60 | goto error; |
| 54 | } | 61 | } |
| 55 | 62 | ||
| @@ -65,8 +72,20 @@ parse_regs(const struct option *opt, const char *str, int unset) | |||
| 65 | 72 | ||
| 66 | /* default to all possible regs */ | 73 | /* default to all possible regs */ |
| 67 | if (*mode == 0) | 74 | if (*mode == 0) |
| 68 | *mode = PERF_REGS_MASK; | 75 | *mode = mask; |
| 69 | error: | 76 | error: |
| 70 | free(os); | 77 | free(os); |
| 71 | return ret; | 78 | return ret; |
| 72 | } | 79 | } |
| 80 | |||
| 81 | int | ||
| 82 | parse_user_regs(const struct option *opt, const char *str, int unset) | ||
| 83 | { | ||
| 84 | return __parse_regs(opt, str, unset, false); | ||
| 85 | } | ||
| 86 | |||
| 87 | int | ||
| 88 | parse_intr_regs(const struct option *opt, const char *str, int unset) | ||
| 89 | { | ||
| 90 | return __parse_regs(opt, str, unset, true); | ||
| 91 | } | ||
diff --git a/tools/perf/util/parse-regs-options.h b/tools/perf/util/parse-regs-options.h index cdefb1acf6be..2b23d25c6394 100644 --- a/tools/perf/util/parse-regs-options.h +++ b/tools/perf/util/parse-regs-options.h | |||
| @@ -2,5 +2,6 @@ | |||
| 2 | #ifndef _PERF_PARSE_REGS_OPTIONS_H | 2 | #ifndef _PERF_PARSE_REGS_OPTIONS_H |
| 3 | #define _PERF_PARSE_REGS_OPTIONS_H 1 | 3 | #define _PERF_PARSE_REGS_OPTIONS_H 1 |
| 4 | struct option; | 4 | struct option; |
| 5 | int parse_regs(const struct option *opt, const char *str, int unset); | 5 | int parse_user_regs(const struct option *opt, const char *str, int unset); |
| 6 | int parse_intr_regs(const struct option *opt, const char *str, int unset); | ||
| 6 | #endif /* _PERF_PARSE_REGS_OPTIONS_H */ | 7 | #endif /* _PERF_PARSE_REGS_OPTIONS_H */ |
diff --git a/tools/perf/util/perf_regs.c b/tools/perf/util/perf_regs.c index 2acfcc527cac..2774cec1f15f 100644 --- a/tools/perf/util/perf_regs.c +++ b/tools/perf/util/perf_regs.c | |||
| @@ -13,6 +13,16 @@ int __weak arch_sdt_arg_parse_op(char *old_op __maybe_unused, | |||
| 13 | return SDT_ARG_SKIP; | 13 | return SDT_ARG_SKIP; |
| 14 | } | 14 | } |
| 15 | 15 | ||
| 16 | uint64_t __weak arch__intr_reg_mask(void) | ||
| 17 | { | ||
| 18 | return PERF_REGS_MASK; | ||
| 19 | } | ||
| 20 | |||
| 21 | uint64_t __weak arch__user_reg_mask(void) | ||
| 22 | { | ||
| 23 | return PERF_REGS_MASK; | ||
| 24 | } | ||
| 25 | |||
| 16 | #ifdef HAVE_PERF_REGS_SUPPORT | 26 | #ifdef HAVE_PERF_REGS_SUPPORT |
| 17 | int perf_reg_value(u64 *valp, struct regs_dump *regs, int id) | 27 | int perf_reg_value(u64 *valp, struct regs_dump *regs, int id) |
| 18 | { | 28 | { |
diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h index c9319f8d17a6..cb9c246c8962 100644 --- a/tools/perf/util/perf_regs.h +++ b/tools/perf/util/perf_regs.h | |||
| @@ -12,6 +12,7 @@ struct sample_reg { | |||
| 12 | uint64_t mask; | 12 | uint64_t mask; |
| 13 | }; | 13 | }; |
| 14 | #define SMPL_REG(n, b) { .name = #n, .mask = 1ULL << (b) } | 14 | #define SMPL_REG(n, b) { .name = #n, .mask = 1ULL << (b) } |
| 15 | #define SMPL_REG2(n, b) { .name = #n, .mask = 3ULL << (b) } | ||
| 15 | #define SMPL_REG_END { .name = NULL } | 16 | #define SMPL_REG_END { .name = NULL } |
| 16 | 17 | ||
| 17 | extern const struct sample_reg sample_reg_masks[]; | 18 | extern const struct sample_reg sample_reg_masks[]; |
| @@ -22,6 +23,8 @@ enum { | |||
| 22 | }; | 23 | }; |
| 23 | 24 | ||
| 24 | int arch_sdt_arg_parse_op(char *old_op, char **new_op); | 25 | int arch_sdt_arg_parse_op(char *old_op, char **new_op); |
| 26 | uint64_t arch__intr_reg_mask(void); | ||
| 27 | uint64_t arch__user_reg_mask(void); | ||
| 25 | 28 | ||
| 26 | #ifdef HAVE_PERF_REGS_SUPPORT | 29 | #ifdef HAVE_PERF_REGS_SUPPORT |
| 27 | #include <perf_regs.h> | 30 | #include <perf_regs.h> |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index bad5f87ae001..2310a1752983 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
| @@ -29,6 +29,61 @@ | |||
| 29 | #include "stat.h" | 29 | #include "stat.h" |
| 30 | #include "arch/common.h" | 30 | #include "arch/common.h" |
| 31 | 31 | ||
| 32 | #ifdef HAVE_ZSTD_SUPPORT | ||
| 33 | static int perf_session__process_compressed_event(struct perf_session *session, | ||
| 34 | union perf_event *event, u64 file_offset) | ||
| 35 | { | ||
| 36 | void *src; | ||
| 37 | size_t decomp_size, src_size; | ||
| 38 | u64 decomp_last_rem = 0; | ||
| 39 | size_t decomp_len = session->header.env.comp_mmap_len; | ||
| 40 | struct decomp *decomp, *decomp_last = session->decomp_last; | ||
| 41 | |||
| 42 | decomp = mmap(NULL, sizeof(struct decomp) + decomp_len, PROT_READ|PROT_WRITE, | ||
| 43 | MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); | ||
| 44 | if (decomp == MAP_FAILED) { | ||
| 45 | pr_err("Couldn't allocate memory for decompression\n"); | ||
| 46 | return -1; | ||
| 47 | } | ||
| 48 | |||
| 49 | decomp->file_pos = file_offset; | ||
| 50 | decomp->head = 0; | ||
| 51 | |||
| 52 | if (decomp_last) { | ||
| 53 | decomp_last_rem = decomp_last->size - decomp_last->head; | ||
| 54 | memcpy(decomp->data, &(decomp_last->data[decomp_last->head]), decomp_last_rem); | ||
| 55 | decomp->size = decomp_last_rem; | ||
| 56 | } | ||
| 57 | |||
| 58 | src = (void *)event + sizeof(struct compressed_event); | ||
| 59 | src_size = event->pack.header.size - sizeof(struct compressed_event); | ||
| 60 | |||
| 61 | decomp_size = zstd_decompress_stream(&(session->zstd_data), src, src_size, | ||
| 62 | &(decomp->data[decomp_last_rem]), decomp_len - decomp_last_rem); | ||
| 63 | if (!decomp_size) { | ||
| 64 | munmap(decomp, sizeof(struct decomp) + decomp_len); | ||
| 65 | pr_err("Couldn't decompress data\n"); | ||
| 66 | return -1; | ||
| 67 | } | ||
| 68 | |||
| 69 | decomp->size += decomp_size; | ||
| 70 | |||
| 71 | if (session->decomp == NULL) { | ||
| 72 | session->decomp = decomp; | ||
| 73 | session->decomp_last = decomp; | ||
| 74 | } else { | ||
| 75 | session->decomp_last->next = decomp; | ||
| 76 | session->decomp_last = decomp; | ||
| 77 | } | ||
| 78 | |||
| 79 | pr_debug("decomp (B): %ld to %ld\n", src_size, decomp_size); | ||
| 80 | |||
| 81 | return 0; | ||
| 82 | } | ||
| 83 | #else /* !HAVE_ZSTD_SUPPORT */ | ||
| 84 | #define perf_session__process_compressed_event perf_session__process_compressed_event_stub | ||
| 85 | #endif | ||
| 86 | |||
| 32 | static int perf_session__deliver_event(struct perf_session *session, | 87 | static int perf_session__deliver_event(struct perf_session *session, |
| 33 | union perf_event *event, | 88 | union perf_event *event, |
| 34 | struct perf_tool *tool, | 89 | struct perf_tool *tool, |
| @@ -197,6 +252,21 @@ static void perf_session__delete_threads(struct perf_session *session) | |||
| 197 | machine__delete_threads(&session->machines.host); | 252 | machine__delete_threads(&session->machines.host); |
| 198 | } | 253 | } |
| 199 | 254 | ||
| 255 | static void perf_session__release_decomp_events(struct perf_session *session) | ||
| 256 | { | ||
| 257 | struct decomp *next, *decomp; | ||
| 258 | size_t decomp_len; | ||
| 259 | next = session->decomp; | ||
| 260 | decomp_len = session->header.env.comp_mmap_len; | ||
| 261 | do { | ||
| 262 | decomp = next; | ||
| 263 | if (decomp == NULL) | ||
| 264 | break; | ||
| 265 | next = decomp->next; | ||
| 266 | munmap(decomp, decomp_len + sizeof(struct decomp)); | ||
| 267 | } while (1); | ||
| 268 | } | ||
| 269 | |||
| 200 | void perf_session__delete(struct perf_session *session) | 270 | void perf_session__delete(struct perf_session *session) |
| 201 | { | 271 | { |
| 202 | if (session == NULL) | 272 | if (session == NULL) |
| @@ -205,6 +275,7 @@ void perf_session__delete(struct perf_session *session) | |||
| 205 | auxtrace_index__free(&session->auxtrace_index); | 275 | auxtrace_index__free(&session->auxtrace_index); |
| 206 | perf_session__destroy_kernel_maps(session); | 276 | perf_session__destroy_kernel_maps(session); |
| 207 | perf_session__delete_threads(session); | 277 | perf_session__delete_threads(session); |
| 278 | perf_session__release_decomp_events(session); | ||
| 208 | perf_env__exit(&session->header.env); | 279 | perf_env__exit(&session->header.env); |
| 209 | machines__exit(&session->machines); | 280 | machines__exit(&session->machines); |
| 210 | if (session->data) | 281 | if (session->data) |
| @@ -358,6 +429,14 @@ static int process_stat_round_stub(struct perf_session *perf_session __maybe_unu | |||
| 358 | return 0; | 429 | return 0; |
| 359 | } | 430 | } |
| 360 | 431 | ||
| 432 | static int perf_session__process_compressed_event_stub(struct perf_session *session __maybe_unused, | ||
| 433 | union perf_event *event __maybe_unused, | ||
| 434 | u64 file_offset __maybe_unused) | ||
| 435 | { | ||
| 436 | dump_printf(": unhandled!\n"); | ||
| 437 | return 0; | ||
| 438 | } | ||
| 439 | |||
| 361 | void perf_tool__fill_defaults(struct perf_tool *tool) | 440 | void perf_tool__fill_defaults(struct perf_tool *tool) |
| 362 | { | 441 | { |
| 363 | if (tool->sample == NULL) | 442 | if (tool->sample == NULL) |
| @@ -430,6 +509,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool) | |||
| 430 | tool->time_conv = process_event_op2_stub; | 509 | tool->time_conv = process_event_op2_stub; |
| 431 | if (tool->feature == NULL) | 510 | if (tool->feature == NULL) |
| 432 | tool->feature = process_event_op2_stub; | 511 | tool->feature = process_event_op2_stub; |
| 512 | if (tool->compressed == NULL) | ||
| 513 | tool->compressed = perf_session__process_compressed_event; | ||
| 433 | } | 514 | } |
| 434 | 515 | ||
| 435 | static void swap_sample_id_all(union perf_event *event, void *data) | 516 | static void swap_sample_id_all(union perf_event *event, void *data) |
| @@ -1373,7 +1454,9 @@ static s64 perf_session__process_user_event(struct perf_session *session, | |||
| 1373 | int fd = perf_data__fd(session->data); | 1454 | int fd = perf_data__fd(session->data); |
| 1374 | int err; | 1455 | int err; |
| 1375 | 1456 | ||
| 1376 | dump_event(session->evlist, event, file_offset, &sample); | 1457 | if (event->header.type != PERF_RECORD_COMPRESSED || |
| 1458 | tool->compressed == perf_session__process_compressed_event_stub) | ||
| 1459 | dump_event(session->evlist, event, file_offset, &sample); | ||
| 1377 | 1460 | ||
| 1378 | /* These events are processed right away */ | 1461 | /* These events are processed right away */ |
| 1379 | switch (event->header.type) { | 1462 | switch (event->header.type) { |
| @@ -1426,6 +1509,11 @@ static s64 perf_session__process_user_event(struct perf_session *session, | |||
| 1426 | return tool->time_conv(session, event); | 1509 | return tool->time_conv(session, event); |
| 1427 | case PERF_RECORD_HEADER_FEATURE: | 1510 | case PERF_RECORD_HEADER_FEATURE: |
| 1428 | return tool->feature(session, event); | 1511 | return tool->feature(session, event); |
| 1512 | case PERF_RECORD_COMPRESSED: | ||
| 1513 | err = tool->compressed(session, event, file_offset); | ||
| 1514 | if (err) | ||
| 1515 | dump_event(session->evlist, event, file_offset, &sample); | ||
| 1516 | return err; | ||
| 1429 | default: | 1517 | default: |
| 1430 | return -EINVAL; | 1518 | return -EINVAL; |
| 1431 | } | 1519 | } |
| @@ -1708,6 +1796,8 @@ static int perf_session__flush_thread_stacks(struct perf_session *session) | |||
| 1708 | 1796 | ||
| 1709 | volatile int session_done; | 1797 | volatile int session_done; |
| 1710 | 1798 | ||
| 1799 | static int __perf_session__process_decomp_events(struct perf_session *session); | ||
| 1800 | |||
| 1711 | static int __perf_session__process_pipe_events(struct perf_session *session) | 1801 | static int __perf_session__process_pipe_events(struct perf_session *session) |
| 1712 | { | 1802 | { |
| 1713 | struct ordered_events *oe = &session->ordered_events; | 1803 | struct ordered_events *oe = &session->ordered_events; |
| @@ -1788,6 +1878,10 @@ more: | |||
| 1788 | if (skip > 0) | 1878 | if (skip > 0) |
| 1789 | head += skip; | 1879 | head += skip; |
| 1790 | 1880 | ||
| 1881 | err = __perf_session__process_decomp_events(session); | ||
| 1882 | if (err) | ||
| 1883 | goto out_err; | ||
| 1884 | |||
| 1791 | if (!session_done()) | 1885 | if (!session_done()) |
| 1792 | goto more; | 1886 | goto more; |
| 1793 | done: | 1887 | done: |
| @@ -1836,6 +1930,39 @@ fetch_mmaped_event(struct perf_session *session, | |||
| 1836 | return event; | 1930 | return event; |
| 1837 | } | 1931 | } |
| 1838 | 1932 | ||
| 1933 | static int __perf_session__process_decomp_events(struct perf_session *session) | ||
| 1934 | { | ||
| 1935 | s64 skip; | ||
| 1936 | u64 size, file_pos = 0; | ||
| 1937 | struct decomp *decomp = session->decomp_last; | ||
| 1938 | |||
| 1939 | if (!decomp) | ||
| 1940 | return 0; | ||
| 1941 | |||
| 1942 | while (decomp->head < decomp->size && !session_done()) { | ||
| 1943 | union perf_event *event = fetch_mmaped_event(session, decomp->head, decomp->size, decomp->data); | ||
| 1944 | |||
| 1945 | if (!event) | ||
| 1946 | break; | ||
| 1947 | |||
| 1948 | size = event->header.size; | ||
| 1949 | |||
| 1950 | if (size < sizeof(struct perf_event_header) || | ||
| 1951 | (skip = perf_session__process_event(session, event, file_pos)) < 0) { | ||
| 1952 | pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n", | ||
| 1953 | decomp->file_pos + decomp->head, event->header.size, event->header.type); | ||
| 1954 | return -EINVAL; | ||
| 1955 | } | ||
| 1956 | |||
| 1957 | if (skip) | ||
| 1958 | size += skip; | ||
| 1959 | |||
| 1960 | decomp->head += size; | ||
| 1961 | } | ||
| 1962 | |||
| 1963 | return 0; | ||
| 1964 | } | ||
| 1965 | |||
| 1839 | /* | 1966 | /* |
| 1840 | * On 64bit we can mmap the data file in one go. No need for tiny mmap | 1967 | * On 64bit we can mmap the data file in one go. No need for tiny mmap |
| 1841 | * slices. On 32bit we use 32MB. | 1968 | * slices. On 32bit we use 32MB. |
| @@ -1945,6 +2072,10 @@ more: | |||
| 1945 | head += size; | 2072 | head += size; |
| 1946 | file_pos += size; | 2073 | file_pos += size; |
| 1947 | 2074 | ||
| 2075 | err = __perf_session__process_decomp_events(session); | ||
| 2076 | if (err) | ||
| 2077 | goto out; | ||
| 2078 | |||
| 1948 | ui_progress__update(prog, size); | 2079 | ui_progress__update(prog, size); |
| 1949 | 2080 | ||
| 1950 | if (session_done()) | 2081 | if (session_done()) |
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index d96eccd7d27f..dd8920b745bc 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include "machine.h" | 8 | #include "machine.h" |
| 9 | #include "data.h" | 9 | #include "data.h" |
| 10 | #include "ordered-events.h" | 10 | #include "ordered-events.h" |
| 11 | #include "util/compress.h" | ||
| 11 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
| 12 | #include <linux/rbtree.h> | 13 | #include <linux/rbtree.h> |
| 13 | #include <linux/perf_event.h> | 14 | #include <linux/perf_event.h> |
| @@ -35,6 +36,19 @@ struct perf_session { | |||
| 35 | struct ordered_events ordered_events; | 36 | struct ordered_events ordered_events; |
| 36 | struct perf_data *data; | 37 | struct perf_data *data; |
| 37 | struct perf_tool *tool; | 38 | struct perf_tool *tool; |
| 39 | u64 bytes_transferred; | ||
| 40 | u64 bytes_compressed; | ||
| 41 | struct zstd_data zstd_data; | ||
| 42 | struct decomp *decomp; | ||
| 43 | struct decomp *decomp_last; | ||
| 44 | }; | ||
| 45 | |||
| 46 | struct decomp { | ||
| 47 | struct decomp *next; | ||
| 48 | u64 file_pos; | ||
| 49 | u64 head; | ||
| 50 | size_t size; | ||
| 51 | char data[]; | ||
| 38 | }; | 52 | }; |
| 39 | 53 | ||
| 40 | struct perf_tool; | 54 | struct perf_tool; |
diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c index 3324f23c7efc..4c53bae5644b 100644 --- a/tools/perf/util/stat-display.c +++ b/tools/perf/util/stat-display.c | |||
| @@ -88,9 +88,17 @@ static void aggr_printout(struct perf_stat_config *config, | |||
| 88 | config->csv_sep); | 88 | config->csv_sep); |
| 89 | break; | 89 | break; |
| 90 | case AGGR_NONE: | 90 | case AGGR_NONE: |
| 91 | fprintf(config->output, "CPU%*d%s", | 91 | if (evsel->percore) { |
| 92 | config->csv_output ? 0 : -4, | 92 | fprintf(config->output, "S%d-C%*d%s", |
| 93 | perf_evsel__cpus(evsel)->map[id], config->csv_sep); | 93 | cpu_map__id_to_socket(id), |
| 94 | config->csv_output ? 0 : -5, | ||
| 95 | cpu_map__id_to_cpu(id), config->csv_sep); | ||
| 96 | } else { | ||
| 97 | fprintf(config->output, "CPU%*d%s ", | ||
| 98 | config->csv_output ? 0 : -5, | ||
| 99 | perf_evsel__cpus(evsel)->map[id], | ||
| 100 | config->csv_sep); | ||
| 101 | } | ||
| 94 | break; | 102 | break; |
| 95 | case AGGR_THREAD: | 103 | case AGGR_THREAD: |
| 96 | fprintf(config->output, "%*s-%*d%s", | 104 | fprintf(config->output, "%*s-%*d%s", |
| @@ -594,6 +602,41 @@ static void aggr_cb(struct perf_stat_config *config, | |||
| 594 | } | 602 | } |
| 595 | } | 603 | } |
| 596 | 604 | ||
| 605 | static void print_counter_aggrdata(struct perf_stat_config *config, | ||
| 606 | struct perf_evsel *counter, int s, | ||
| 607 | char *prefix, bool metric_only, | ||
| 608 | bool *first) | ||
| 609 | { | ||
| 610 | struct aggr_data ad; | ||
| 611 | FILE *output = config->output; | ||
| 612 | u64 ena, run, val; | ||
| 613 | int id, nr; | ||
| 614 | double uval; | ||
| 615 | |||
| 616 | ad.id = id = config->aggr_map->map[s]; | ||
| 617 | ad.val = ad.ena = ad.run = 0; | ||
| 618 | ad.nr = 0; | ||
| 619 | if (!collect_data(config, counter, aggr_cb, &ad)) | ||
| 620 | return; | ||
| 621 | |||
| 622 | nr = ad.nr; | ||
| 623 | ena = ad.ena; | ||
| 624 | run = ad.run; | ||
| 625 | val = ad.val; | ||
| 626 | if (*first && metric_only) { | ||
| 627 | *first = false; | ||
| 628 | aggr_printout(config, counter, id, nr); | ||
| 629 | } | ||
| 630 | if (prefix && !metric_only) | ||
| 631 | fprintf(output, "%s", prefix); | ||
| 632 | |||
| 633 | uval = val * counter->scale; | ||
| 634 | printout(config, id, nr, counter, uval, prefix, | ||
| 635 | run, ena, 1.0, &rt_stat); | ||
| 636 | if (!metric_only) | ||
| 637 | fputc('\n', output); | ||
| 638 | } | ||
| 639 | |||
| 597 | static void print_aggr(struct perf_stat_config *config, | 640 | static void print_aggr(struct perf_stat_config *config, |
| 598 | struct perf_evlist *evlist, | 641 | struct perf_evlist *evlist, |
| 599 | char *prefix) | 642 | char *prefix) |
| @@ -601,9 +644,7 @@ static void print_aggr(struct perf_stat_config *config, | |||
| 601 | bool metric_only = config->metric_only; | 644 | bool metric_only = config->metric_only; |
| 602 | FILE *output = config->output; | 645 | FILE *output = config->output; |
| 603 | struct perf_evsel *counter; | 646 | struct perf_evsel *counter; |
| 604 | int s, id, nr; | 647 | int s; |
| 605 | double uval; | ||
| 606 | u64 ena, run, val; | ||
| 607 | bool first; | 648 | bool first; |
| 608 | 649 | ||
| 609 | if (!(config->aggr_map || config->aggr_get_id)) | 650 | if (!(config->aggr_map || config->aggr_get_id)) |
| @@ -616,33 +657,14 @@ static void print_aggr(struct perf_stat_config *config, | |||
| 616 | * Without each counter has its own line. | 657 | * Without each counter has its own line. |
| 617 | */ | 658 | */ |
| 618 | for (s = 0; s < config->aggr_map->nr; s++) { | 659 | for (s = 0; s < config->aggr_map->nr; s++) { |
| 619 | struct aggr_data ad; | ||
| 620 | if (prefix && metric_only) | 660 | if (prefix && metric_only) |
| 621 | fprintf(output, "%s", prefix); | 661 | fprintf(output, "%s", prefix); |
| 622 | 662 | ||
| 623 | ad.id = id = config->aggr_map->map[s]; | ||
| 624 | first = true; | 663 | first = true; |
| 625 | evlist__for_each_entry(evlist, counter) { | 664 | evlist__for_each_entry(evlist, counter) { |
| 626 | ad.val = ad.ena = ad.run = 0; | 665 | print_counter_aggrdata(config, counter, s, |
| 627 | ad.nr = 0; | 666 | prefix, metric_only, |
| 628 | if (!collect_data(config, counter, aggr_cb, &ad)) | 667 | &first); |
| 629 | continue; | ||
| 630 | nr = ad.nr; | ||
| 631 | ena = ad.ena; | ||
| 632 | run = ad.run; | ||
| 633 | val = ad.val; | ||
| 634 | if (first && metric_only) { | ||
| 635 | first = false; | ||
| 636 | aggr_printout(config, counter, id, nr); | ||
| 637 | } | ||
| 638 | if (prefix && !metric_only) | ||
| 639 | fprintf(output, "%s", prefix); | ||
| 640 | |||
| 641 | uval = val * counter->scale; | ||
| 642 | printout(config, id, nr, counter, uval, prefix, | ||
| 643 | run, ena, 1.0, &rt_stat); | ||
| 644 | if (!metric_only) | ||
| 645 | fputc('\n', output); | ||
| 646 | } | 668 | } |
| 647 | if (metric_only) | 669 | if (metric_only) |
| 648 | fputc('\n', output); | 670 | fputc('\n', output); |
| @@ -1089,6 +1111,30 @@ static void print_footer(struct perf_stat_config *config) | |||
| 1089 | "the same PMU. Try reorganizing the group.\n"); | 1111 | "the same PMU. Try reorganizing the group.\n"); |
| 1090 | } | 1112 | } |
| 1091 | 1113 | ||
| 1114 | static void print_percore(struct perf_stat_config *config, | ||
| 1115 | struct perf_evsel *counter, char *prefix) | ||
| 1116 | { | ||
| 1117 | bool metric_only = config->metric_only; | ||
| 1118 | FILE *output = config->output; | ||
| 1119 | int s; | ||
| 1120 | bool first = true; | ||
| 1121 | |||
| 1122 | if (!(config->aggr_map || config->aggr_get_id)) | ||
| 1123 | return; | ||
| 1124 | |||
| 1125 | for (s = 0; s < config->aggr_map->nr; s++) { | ||
| 1126 | if (prefix && metric_only) | ||
| 1127 | fprintf(output, "%s", prefix); | ||
| 1128 | |||
| 1129 | print_counter_aggrdata(config, counter, s, | ||
| 1130 | prefix, metric_only, | ||
| 1131 | &first); | ||
| 1132 | } | ||
| 1133 | |||
| 1134 | if (metric_only) | ||
| 1135 | fputc('\n', output); | ||
| 1136 | } | ||
| 1137 | |||
| 1092 | void | 1138 | void |
| 1093 | perf_evlist__print_counters(struct perf_evlist *evlist, | 1139 | perf_evlist__print_counters(struct perf_evlist *evlist, |
| 1094 | struct perf_stat_config *config, | 1140 | struct perf_stat_config *config, |
| @@ -1139,7 +1185,10 @@ perf_evlist__print_counters(struct perf_evlist *evlist, | |||
| 1139 | print_no_aggr_metric(config, evlist, prefix); | 1185 | print_no_aggr_metric(config, evlist, prefix); |
| 1140 | else { | 1186 | else { |
| 1141 | evlist__for_each_entry(evlist, counter) { | 1187 | evlist__for_each_entry(evlist, counter) { |
| 1142 | print_counter(config, counter, prefix); | 1188 | if (counter->percore) |
| 1189 | print_percore(config, counter, prefix); | ||
| 1190 | else | ||
| 1191 | print_counter(config, counter, prefix); | ||
| 1143 | } | 1192 | } |
| 1144 | } | 1193 | } |
| 1145 | break; | 1194 | break; |
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c index 2856cc9d5a31..c3115d939b0b 100644 --- a/tools/perf/util/stat.c +++ b/tools/perf/util/stat.c | |||
| @@ -277,9 +277,11 @@ process_counter_values(struct perf_stat_config *config, struct perf_evsel *evsel | |||
| 277 | if (!evsel->snapshot) | 277 | if (!evsel->snapshot) |
| 278 | perf_evsel__compute_deltas(evsel, cpu, thread, count); | 278 | perf_evsel__compute_deltas(evsel, cpu, thread, count); |
| 279 | perf_counts_values__scale(count, config->scale, NULL); | 279 | perf_counts_values__scale(count, config->scale, NULL); |
| 280 | if (config->aggr_mode == AGGR_NONE) | 280 | if ((config->aggr_mode == AGGR_NONE) && (!evsel->percore)) { |
| 281 | perf_stat__update_shadow_stats(evsel, count->val, cpu, | 281 | perf_stat__update_shadow_stats(evsel, count->val, |
| 282 | &rt_stat); | 282 | cpu, &rt_stat); |
| 283 | } | ||
| 284 | |||
| 283 | if (config->aggr_mode == AGGR_THREAD) { | 285 | if (config->aggr_mode == AGGR_THREAD) { |
| 284 | if (config->stats) | 286 | if (config->stats) |
| 285 | perf_stat__update_shadow_stats(evsel, | 287 | perf_stat__update_shadow_stats(evsel, |
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index 50678d318185..403045a2bbea 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include "map.h" | 15 | #include "map.h" |
| 16 | #include "symbol.h" | 16 | #include "symbol.h" |
| 17 | #include "unwind.h" | 17 | #include "unwind.h" |
| 18 | #include "callchain.h" | ||
| 18 | 19 | ||
| 19 | #include <api/fs/fs.h> | 20 | #include <api/fs/fs.h> |
| 20 | 21 | ||
| @@ -327,7 +328,7 @@ static int thread__prepare_access(struct thread *thread) | |||
| 327 | { | 328 | { |
| 328 | int err = 0; | 329 | int err = 0; |
| 329 | 330 | ||
| 330 | if (symbol_conf.use_callchain) | 331 | if (dwarf_callchain_users) |
| 331 | err = __thread__prepare_access(thread); | 332 | err = __thread__prepare_access(thread); |
| 332 | 333 | ||
| 333 | return err; | 334 | return err; |
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h index 250391672f9f..9096a6e3de59 100644 --- a/tools/perf/util/tool.h +++ b/tools/perf/util/tool.h | |||
| @@ -28,6 +28,7 @@ typedef int (*event_attr_op)(struct perf_tool *tool, | |||
| 28 | 28 | ||
| 29 | typedef int (*event_op2)(struct perf_session *session, union perf_event *event); | 29 | typedef int (*event_op2)(struct perf_session *session, union perf_event *event); |
| 30 | typedef s64 (*event_op3)(struct perf_session *session, union perf_event *event); | 30 | typedef s64 (*event_op3)(struct perf_session *session, union perf_event *event); |
| 31 | typedef int (*event_op4)(struct perf_session *session, union perf_event *event, u64 data); | ||
| 31 | 32 | ||
| 32 | typedef int (*event_oe)(struct perf_tool *tool, union perf_event *event, | 33 | typedef int (*event_oe)(struct perf_tool *tool, union perf_event *event, |
| 33 | struct ordered_events *oe); | 34 | struct ordered_events *oe); |
| @@ -72,6 +73,7 @@ struct perf_tool { | |||
| 72 | stat, | 73 | stat, |
| 73 | stat_round, | 74 | stat_round, |
| 74 | feature; | 75 | feature; |
| 76 | event_op4 compressed; | ||
| 75 | event_op3 auxtrace; | 77 | event_op3 auxtrace; |
| 76 | bool ordered_events; | 78 | bool ordered_events; |
| 77 | bool ordering_requires_timestamps; | 79 | bool ordering_requires_timestamps; |
diff --git a/tools/perf/util/unwind-libunwind-local.c b/tools/perf/util/unwind-libunwind-local.c index f3c666a84e4d..25e1406b1f8b 100644 --- a/tools/perf/util/unwind-libunwind-local.c +++ b/tools/perf/util/unwind-libunwind-local.c | |||
| @@ -617,8 +617,6 @@ static unw_accessors_t accessors = { | |||
| 617 | 617 | ||
| 618 | static int _unwind__prepare_access(struct thread *thread) | 618 | static int _unwind__prepare_access(struct thread *thread) |
| 619 | { | 619 | { |
| 620 | if (!dwarf_callchain_users) | ||
| 621 | return 0; | ||
| 622 | thread->addr_space = unw_create_addr_space(&accessors, 0); | 620 | thread->addr_space = unw_create_addr_space(&accessors, 0); |
| 623 | if (!thread->addr_space) { | 621 | if (!thread->addr_space) { |
| 624 | pr_err("unwind: Can't create unwind address space.\n"); | 622 | pr_err("unwind: Can't create unwind address space.\n"); |
| @@ -631,15 +629,11 @@ static int _unwind__prepare_access(struct thread *thread) | |||
| 631 | 629 | ||
| 632 | static void _unwind__flush_access(struct thread *thread) | 630 | static void _unwind__flush_access(struct thread *thread) |
| 633 | { | 631 | { |
| 634 | if (!dwarf_callchain_users) | ||
| 635 | return; | ||
| 636 | unw_flush_cache(thread->addr_space, 0, 0); | 632 | unw_flush_cache(thread->addr_space, 0, 0); |
| 637 | } | 633 | } |
| 638 | 634 | ||
| 639 | static void _unwind__finish_access(struct thread *thread) | 635 | static void _unwind__finish_access(struct thread *thread) |
| 640 | { | 636 | { |
| 641 | if (!dwarf_callchain_users) | ||
| 642 | return; | ||
| 643 | unw_destroy_addr_space(thread->addr_space); | 637 | unw_destroy_addr_space(thread->addr_space); |
| 644 | } | 638 | } |
| 645 | 639 | ||
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c index 9778b3133b77..c0811977d7d5 100644 --- a/tools/perf/util/unwind-libunwind.c +++ b/tools/perf/util/unwind-libunwind.c | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include "session.h" | 5 | #include "session.h" |
| 6 | #include "debug.h" | 6 | #include "debug.h" |
| 7 | #include "env.h" | 7 | #include "env.h" |
| 8 | #include "callchain.h" | ||
| 8 | 9 | ||
| 9 | struct unwind_libunwind_ops __weak *local_unwind_libunwind_ops; | 10 | struct unwind_libunwind_ops __weak *local_unwind_libunwind_ops; |
| 10 | struct unwind_libunwind_ops __weak *x86_32_unwind_libunwind_ops; | 11 | struct unwind_libunwind_ops __weak *x86_32_unwind_libunwind_ops; |
| @@ -24,6 +25,9 @@ int unwind__prepare_access(struct thread *thread, struct map *map, | |||
| 24 | struct unwind_libunwind_ops *ops = local_unwind_libunwind_ops; | 25 | struct unwind_libunwind_ops *ops = local_unwind_libunwind_ops; |
| 25 | int err; | 26 | int err; |
| 26 | 27 | ||
| 28 | if (!dwarf_callchain_users) | ||
| 29 | return 0; | ||
| 30 | |||
| 27 | if (thread->addr_space) { | 31 | if (thread->addr_space) { |
| 28 | pr_debug("unwind: thread map already set, dso=%s\n", | 32 | pr_debug("unwind: thread map already set, dso=%s\n", |
| 29 | map->dso->name); | 33 | map->dso->name); |
| @@ -65,12 +69,18 @@ out_register: | |||
| 65 | 69 | ||
| 66 | void unwind__flush_access(struct thread *thread) | 70 | void unwind__flush_access(struct thread *thread) |
| 67 | { | 71 | { |
| 72 | if (!dwarf_callchain_users) | ||
| 73 | return; | ||
| 74 | |||
| 68 | if (thread->unwind_libunwind_ops) | 75 | if (thread->unwind_libunwind_ops) |
| 69 | thread->unwind_libunwind_ops->flush_access(thread); | 76 | thread->unwind_libunwind_ops->flush_access(thread); |
| 70 | } | 77 | } |
| 71 | 78 | ||
| 72 | void unwind__finish_access(struct thread *thread) | 79 | void unwind__finish_access(struct thread *thread) |
| 73 | { | 80 | { |
| 81 | if (!dwarf_callchain_users) | ||
| 82 | return; | ||
| 83 | |||
| 74 | if (thread->unwind_libunwind_ops) | 84 | if (thread->unwind_libunwind_ops) |
| 75 | thread->unwind_libunwind_ops->finish_access(thread); | 85 | thread->unwind_libunwind_ops->finish_access(thread); |
| 76 | } | 86 | } |
diff --git a/tools/perf/util/zstd.c b/tools/perf/util/zstd.c new file mode 100644 index 000000000000..23bdb9884576 --- /dev/null +++ b/tools/perf/util/zstd.c | |||
| @@ -0,0 +1,111 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | |||
| 3 | #include <string.h> | ||
| 4 | |||
| 5 | #include "util/compress.h" | ||
| 6 | #include "util/debug.h" | ||
| 7 | |||
| 8 | int zstd_init(struct zstd_data *data, int level) | ||
| 9 | { | ||
| 10 | size_t ret; | ||
| 11 | |||
| 12 | data->dstream = ZSTD_createDStream(); | ||
| 13 | if (data->dstream == NULL) { | ||
| 14 | pr_err("Couldn't create decompression stream.\n"); | ||
| 15 | return -1; | ||
| 16 | } | ||
| 17 | |||
| 18 | ret = ZSTD_initDStream(data->dstream); | ||
| 19 | if (ZSTD_isError(ret)) { | ||
| 20 | pr_err("Failed to initialize decompression stream: %s\n", ZSTD_getErrorName(ret)); | ||
| 21 | return -1; | ||
| 22 | } | ||
| 23 | |||
| 24 | if (!level) | ||
| 25 | return 0; | ||
| 26 | |||
| 27 | data->cstream = ZSTD_createCStream(); | ||
| 28 | if (data->cstream == NULL) { | ||
| 29 | pr_err("Couldn't create compression stream.\n"); | ||
| 30 | return -1; | ||
| 31 | } | ||
| 32 | |||
| 33 | ret = ZSTD_initCStream(data->cstream, level); | ||
| 34 | if (ZSTD_isError(ret)) { | ||
| 35 | pr_err("Failed to initialize compression stream: %s\n", ZSTD_getErrorName(ret)); | ||
| 36 | return -1; | ||
| 37 | } | ||
| 38 | |||
| 39 | return 0; | ||
| 40 | } | ||
| 41 | |||
| 42 | int zstd_fini(struct zstd_data *data) | ||
| 43 | { | ||
| 44 | if (data->dstream) { | ||
| 45 | ZSTD_freeDStream(data->dstream); | ||
| 46 | data->dstream = NULL; | ||
| 47 | } | ||
| 48 | |||
| 49 | if (data->cstream) { | ||
| 50 | ZSTD_freeCStream(data->cstream); | ||
| 51 | data->cstream = NULL; | ||
| 52 | } | ||
| 53 | |||
| 54 | return 0; | ||
| 55 | } | ||
| 56 | |||
| 57 | size_t zstd_compress_stream_to_records(struct zstd_data *data, void *dst, size_t dst_size, | ||
| 58 | void *src, size_t src_size, size_t max_record_size, | ||
| 59 | size_t process_header(void *record, size_t increment)) | ||
| 60 | { | ||
| 61 | size_t ret, size, compressed = 0; | ||
| 62 | ZSTD_inBuffer input = { src, src_size, 0 }; | ||
| 63 | ZSTD_outBuffer output; | ||
| 64 | void *record; | ||
| 65 | |||
| 66 | while (input.pos < input.size) { | ||
| 67 | record = dst; | ||
| 68 | size = process_header(record, 0); | ||
| 69 | compressed += size; | ||
| 70 | dst += size; | ||
| 71 | dst_size -= size; | ||
| 72 | output = (ZSTD_outBuffer){ dst, (dst_size > max_record_size) ? | ||
| 73 | max_record_size : dst_size, 0 }; | ||
| 74 | ret = ZSTD_compressStream(data->cstream, &output, &input); | ||
| 75 | ZSTD_flushStream(data->cstream, &output); | ||
| 76 | if (ZSTD_isError(ret)) { | ||
| 77 | pr_err("failed to compress %ld bytes: %s\n", | ||
| 78 | (long)src_size, ZSTD_getErrorName(ret)); | ||
| 79 | memcpy(dst, src, src_size); | ||
| 80 | return src_size; | ||
| 81 | } | ||
| 82 | size = output.pos; | ||
| 83 | size = process_header(record, size); | ||
| 84 | compressed += size; | ||
| 85 | dst += size; | ||
| 86 | dst_size -= size; | ||
| 87 | } | ||
| 88 | |||
| 89 | return compressed; | ||
| 90 | } | ||
| 91 | |||
| 92 | size_t zstd_decompress_stream(struct zstd_data *data, void *src, size_t src_size, | ||
| 93 | void *dst, size_t dst_size) | ||
| 94 | { | ||
| 95 | size_t ret; | ||
| 96 | ZSTD_inBuffer input = { src, src_size, 0 }; | ||
| 97 | ZSTD_outBuffer output = { dst, dst_size, 0 }; | ||
| 98 | |||
| 99 | while (input.pos < input.size) { | ||
| 100 | ret = ZSTD_decompressStream(data->dstream, &output, &input); | ||
| 101 | if (ZSTD_isError(ret)) { | ||
| 102 | pr_err("failed to decompress (B): %ld -> %ld : %s\n", | ||
| 103 | src_size, output.size, ZSTD_getErrorName(ret)); | ||
| 104 | break; | ||
| 105 | } | ||
| 106 | output.dst = dst + output.pos; | ||
| 107 | output.size = dst_size - output.pos; | ||
| 108 | } | ||
| 109 | |||
| 110 | return output.pos; | ||
| 111 | } | ||
