diff options
599 files changed, 6656 insertions, 4672 deletions
diff --git a/.gitignore b/.gitignore index 9fd4c9533b3d..0bbae167bf93 100644 --- a/.gitignore +++ b/.gitignore @@ -74,7 +74,7 @@ modules.order # # RPM spec file (make rpm-pkg) # -/*.spec +/kernel.spec /rpmbuild/ # diff --git a/Documentation/ABI/testing/sysfs-class-led b/Documentation/ABI/testing/sysfs-class-led index 2e24ac3bd7ef..b2ff0012c0f2 100644 --- a/Documentation/ABI/testing/sysfs-class-led +++ b/Documentation/ABI/testing/sysfs-class-led @@ -59,6 +59,15 @@ Description: brightness. Reading this file when no hw brightness change event has happened will return an ENODATA error. +What: /sys/class/leds/<led>/color +Date: June 2023 +KernelVersion: 6.5 +Description: + Color of the LED. + + This is a read-only file. Reading this file returns the color + of the LED as a string (e.g: "red", "green", "multicolor"). + What: /sys/class/leds/<led>/trigger Date: March 2006 KernelVersion: 2.6.17 diff --git a/Documentation/core-api/printk-formats.rst b/Documentation/core-api/printk-formats.rst index dfe7e75a71de..4451ef501936 100644 --- a/Documentation/core-api/printk-formats.rst +++ b/Documentation/core-api/printk-formats.rst @@ -15,9 +15,10 @@ Integer types If variable is of Type, use printk format specifier: ------------------------------------------------------------ - char %d or %x + signed char %d or %hhx unsigned char %u or %x - short int %d or %x + char %u or %x + short int %d or %hx unsigned short int %u or %x int %d or %x unsigned int %u or %x @@ -27,9 +28,9 @@ Integer types unsigned long long %llu or %llx size_t %zu or %zx ssize_t %zd or %zx - s8 %d or %x + s8 %d or %hhx u8 %u or %x - s16 %d or %x + s16 %d or %hx u16 %u or %x s32 %d or %x u32 %u or %x diff --git a/Documentation/devicetree/bindings/i2c/cdns,i2c-r1p10.yaml b/Documentation/devicetree/bindings/i2c/cdns,i2c-r1p10.yaml index ff57c5416ebc..9f1d35ce1fe8 100644 --- a/Documentation/devicetree/bindings/i2c/cdns,i2c-r1p10.yaml +++ b/Documentation/devicetree/bindings/i2c/cdns,i2c-r1p10.yaml @@ -48,6 +48,9 @@ properties: default: 16 enum: [2, 4, 8, 16, 32, 64, 128, 256] + power-domains: + maxItems: 1 + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/i2c/i2c-arb-gpio-challenge.txt b/Documentation/devicetree/bindings/i2c/i2c-arb-gpio-challenge.txt deleted file mode 100644 index 548a73cde796..000000000000 --- a/Documentation/devicetree/bindings/i2c/i2c-arb-gpio-challenge.txt +++ /dev/null @@ -1,82 +0,0 @@ -GPIO-based I2C Arbitration Using a Challenge & Response Mechanism -================================================================= -This uses GPIO lines and a challenge & response mechanism to arbitrate who is -the master of an I2C bus in a multimaster situation. - -In many cases using GPIOs to arbitrate is not needed and a design can use -the standard I2C multi-master rules. Using GPIOs is generally useful in -the case where there is a device on the bus that has errata and/or bugs -that makes standard multimaster mode not feasible. - -Note that this scheme works well enough but has some downsides: -* It is nonstandard (not using standard I2C multimaster) -* Having two masters on a bus in general makes it relatively hard to debug - problems (hard to tell if i2c issues were caused by one master, another, or - some device on the bus). - - -Algorithm: - -All masters on the bus have a 'bus claim' line which is an output that the -others can see. These are all active low with pull-ups enabled. We'll -describe these lines as: - -- OUR_CLAIM: output from us signaling to other hosts that we want the bus -- THEIR_CLAIMS: output from others signaling that they want the bus - -The basic algorithm is to assert your line when you want the bus, then make -sure that the other side doesn't want it also. A detailed explanation is best -done with an example. - -Let's say we want to claim the bus. We: -1. Assert OUR_CLAIM. -2. Waits a little bit for the other sides to notice (slew time, say 10 - microseconds). -3. Check THEIR_CLAIMS. If none are asserted then the we have the bus and we are - done. -4. Otherwise, wait for a few milliseconds and see if THEIR_CLAIMS are released. -5. If not, back off, release the claim and wait for a few more milliseconds. -6. Go back to 1 (until retry time has expired). - - -Required properties: -- compatible: i2c-arb-gpio-challenge -- our-claim-gpio: The GPIO that we use to claim the bus. -- their-claim-gpios: The GPIOs that the other sides use to claim the bus. - Note that some implementations may only support a single other master. -- I2C arbitration bus node. See i2c-arb.txt in this directory. - -Optional properties: -- slew-delay-us: microseconds to wait for a GPIO to go high. Default is 10 us. -- wait-retry-us: we'll attempt another claim after this many microseconds. - Default is 3000 us. -- wait-free-us: we'll give up after this many microseconds. Default is 50000 us. - - -Example: - i2c@12ca0000 { - compatible = "acme,some-i2c-device"; - #address-cells = <1>; - #size-cells = <0>; - }; - - i2c-arbitrator { - compatible = "i2c-arb-gpio-challenge"; - - i2c-parent = <&{/i2c@12CA0000}>; - - our-claim-gpio = <&gpf0 3 1>; - their-claim-gpios = <&gpe0 4 1>; - slew-delay-us = <10>; - wait-retry-us = <3000>; - wait-free-us = <50000>; - - i2c-arb { - #address-cells = <1>; - #size-cells = <0>; - - i2c@52 { - // Normal I2C device - }; - }; - }; diff --git a/Documentation/devicetree/bindings/i2c/i2c-arb-gpio-challenge.yaml b/Documentation/devicetree/bindings/i2c/i2c-arb-gpio-challenge.yaml new file mode 100644 index 000000000000..b618b5a3433a --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/i2c-arb-gpio-challenge.yaml @@ -0,0 +1,135 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/i2c/i2c-arb-gpio-challenge.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: GPIO-based I2C Arbitration Using a Challenge & Response Mechanism + +maintainers: + - Doug Anderson <dianders@chromium.org> + - Peter Rosin <peda@axentia.se> + +description: | + This uses GPIO lines and a challenge & response mechanism to arbitrate who is + the master of an I2C bus in a multimaster situation. + + In many cases using GPIOs to arbitrate is not needed and a design can use the + standard I2C multi-master rules. Using GPIOs is generally useful in the case + where there is a device on the bus that has errata and/or bugs that makes + standard multimaster mode not feasible. + + Note that this scheme works well enough but has some downsides: + * It is nonstandard (not using standard I2C multimaster) + * Having two masters on a bus in general makes it relatively hard to debug + problems (hard to tell if i2c issues were caused by one master, another, + or some device on the bus). + + Algorithm: + All masters on the bus have a 'bus claim' line which is an output that the + others can see. These are all active low with pull-ups enabled. We'll + describe these lines as: + * OUR_CLAIM: output from us signaling to other hosts that we want the bus + * THEIR_CLAIMS: output from others signaling that they want the bus + + The basic algorithm is to assert your line when you want the bus, then make + sure that the other side doesn't want it also. A detailed explanation is + best done with an example. + + Let's say we want to claim the bus. We: + 1. Assert OUR_CLAIM. + 2. Waits a little bit for the other sides to notice (slew time, say 10 + microseconds). + 3. Check THEIR_CLAIMS. If none are asserted then the we have the bus and we + are done. + 4. Otherwise, wait for a few milliseconds and see if THEIR_CLAIMS are released. + 5. If not, back off, release the claim and wait for a few more milliseconds. + 6. Go back to 1 (until retry time has expired). + +properties: + compatible: + const: i2c-arb-gpio-challenge + + i2c-parent: + $ref: /schemas/types.yaml#/definitions/phandle + description: + The I2C bus that this multiplexer's master-side port is connected to. + + our-claim-gpios: + maxItems: 1 + description: + The GPIO that we use to claim the bus. + + slew-delay-us: + default: 10 + description: + Time to wait for a GPIO to go high. + + their-claim-gpios: + minItems: 1 + maxItems: 8 + description: + The GPIOs that the other sides use to claim the bus. Note that some + implementations may only support a single other master. + + wait-free-us: + default: 50000 + description: + We'll give up after this many microseconds. + + wait-retry-us: + default: 3000 + description: + We'll attempt another claim after this many microseconds. + + i2c-arb: + type: object + $ref: /schemas/i2c/i2c-controller.yaml + unevaluatedProperties: false + description: + I2C arbitration bus node. + +required: + - compatible + - i2c-arb + - our-claim-gpios + - their-claim-gpios + +additionalProperties: false + +examples: + - | + #include <dt-bindings/gpio/gpio.h> + #include <dt-bindings/interrupt-controller/irq.h> + + i2c-arbitrator { + compatible = "i2c-arb-gpio-challenge"; + i2c-parent = <&i2c_4>; + + our-claim-gpios = <&gpf0 3 GPIO_ACTIVE_LOW>; + their-claim-gpios = <&gpe0 4 GPIO_ACTIVE_LOW>; + slew-delay-us = <10>; + wait-retry-us = <3000>; + wait-free-us = <50000>; + + i2c-arb { + #address-cells = <1>; + #size-cells = <0>; + + sbs-battery@b { + compatible = "sbs,sbs-battery"; + reg = <0xb>; + sbs,poll-retry-count = <1>; + }; + + embedded-controller@1e { + compatible = "google,cros-ec-i2c"; + reg = <0x1e>; + interrupts = <6 IRQ_TYPE_LEVEL_HIGH>; + interrupt-parent = <&gpx1>; + pinctrl-names = "default"; + pinctrl-0 = <&ec_irq>; + wakeup-source; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/i2c/i2c-arb.txt b/Documentation/devicetree/bindings/i2c/i2c-arb.txt deleted file mode 100644 index 59abf9277bdc..000000000000 --- a/Documentation/devicetree/bindings/i2c/i2c-arb.txt +++ /dev/null @@ -1,35 +0,0 @@ -Common i2c arbitration bus properties. - -- i2c-arb child node - -Required properties for the i2c-arb child node: -- #address-cells = <1>; -- #size-cells = <0>; - -Optional properties for i2c-arb child node: -- Child nodes conforming to i2c bus binding - - -Example : - - /* - An NXP pca9541 I2C bus master selector at address 0x74 - with a NXP pca8574 GPIO expander attached. - */ - - arb@74 { - compatible = "nxp,pca9541"; - reg = <0x74>; - - i2c-arb { - #address-cells = <1>; - #size-cells = <0>; - - gpio@38 { - compatible = "nxp,pca8574"; - reg = <0x38>; - #gpio-cells = <2>; - gpio-controller; - }; - }; - }; diff --git a/Documentation/devicetree/bindings/i2c/i2c-mux-pca954x.yaml b/Documentation/devicetree/bindings/i2c/i2c-mux-pca954x.yaml index 9f1726d0356b..2d7bb998b0e9 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-mux-pca954x.yaml +++ b/Documentation/devicetree/bindings/i2c/i2c-mux-pca954x.yaml @@ -4,21 +4,29 @@ $id: http://devicetree.org/schemas/i2c/i2c-mux-pca954x.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: NXP PCA954x I2C bus switch +title: NXP PCA954x I2C and compatible bus switches maintainers: - Laurent Pinchart <laurent.pinchart@ideasonboard.com> description: - The binding supports NXP PCA954x and PCA984x I2C mux/switch devices. - -allOf: - - $ref: /schemas/i2c/i2c-mux.yaml# + The NXP PCA954x and compatible devices are I2C bus + multiplexer/switches that share the same functionality + and register layout. + The devices usually have 4 or 8 child buses, which are + attached to the parent bus by using the SMBus "Send Byte" + command. properties: compatible: oneOf: - enum: + - maxim,max7356 + - maxim,max7357 + - maxim,max7358 + - maxim,max7367 + - maxim,max7368 + - maxim,max7369 - nxp,pca9540 - nxp,pca9542 - nxp,pca9543 @@ -59,10 +67,34 @@ properties: description: if present, overrides i2c-mux-idle-disconnect $ref: /schemas/mux/mux-controller.yaml#/properties/idle-state + vdd-supply: + description: A voltage regulator supplying power to the chip. On PCA9846 + the regulator supplies power to VDD2 (core logic) and optionally to VDD1. + required: - compatible - reg +allOf: + - $ref: /schemas/i2c/i2c-mux.yaml# + - if: + not: + properties: + compatible: + contains: + enum: + - maxim,max7367 + - maxim,max7369 + - nxp,pca9542 + - nxp,pca9543 + - nxp,pca9544 + - nxp,pca9545 + then: + properties: + interrupts: false + "#interrupt-cells": false + interrupt-controller: false + unevaluatedProperties: false examples: @@ -74,11 +106,13 @@ examples: #size-cells = <0>; i2c-mux@74 { - compatible = "nxp,pca9548"; + compatible = "nxp,pca9545"; #address-cells = <1>; #size-cells = <0>; reg = <0x74>; + vdd-supply = <&p3v3>; + interrupt-parent = <&ipic>; interrupts = <17 IRQ_TYPE_LEVEL_LOW>; interrupt-controller; diff --git a/Documentation/devicetree/bindings/i2c/nxp,pca9541.txt b/Documentation/devicetree/bindings/i2c/nxp,pca9541.txt deleted file mode 100644 index 42bfc09c8918..000000000000 --- a/Documentation/devicetree/bindings/i2c/nxp,pca9541.txt +++ /dev/null @@ -1,29 +0,0 @@ -* NXP PCA9541 I2C bus master selector - -Required Properties: - - - compatible: Must be "nxp,pca9541" - - - reg: The I2C address of the device. - - The following required properties are defined externally: - - - I2C arbitration bus node. See i2c-arb.txt in this directory. - - -Example: - - i2c-arbitrator@74 { - compatible = "nxp,pca9541"; - reg = <0x74>; - - i2c-arb { - #address-cells = <1>; - #size-cells = <0>; - - eeprom@54 { - compatible = "atmel,24c08"; - reg = <0x54>; - }; - }; - }; diff --git a/Documentation/devicetree/bindings/i2c/nxp,pca9541.yaml b/Documentation/devicetree/bindings/i2c/nxp,pca9541.yaml new file mode 100644 index 000000000000..b65c25c1a435 --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/nxp,pca9541.yaml @@ -0,0 +1,56 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/i2c/nxp,pca9541.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NXP PCA9541 I2C bus master selector + +maintainers: + - Peter Rosin <peda@axentia.se> + +properties: + compatible: + const: nxp,pca9541 + + reg: + maxItems: 1 + + i2c-arb: + type: object + $ref: /schemas/i2c/i2c-controller.yaml + unevaluatedProperties: false + description: + I2C arbitration bus node. + +required: + - compatible + - reg + - i2c-arb + +additionalProperties: false + +examples: + - | + #include <dt-bindings/gpio/gpio.h> + #include <dt-bindings/interrupt-controller/irq.h> + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + i2c-arbitrator@74 { + compatible = "nxp,pca9541"; + reg = <0x74>; + + i2c-arb { + #address-cells = <1>; + #size-cells = <0>; + + eeprom@54 { + compatible = "atmel,24c08"; + reg = <0x54>; + }; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/input/stmpe-keypad.txt b/Documentation/devicetree/bindings/input/stmpe-keypad.txt deleted file mode 100644 index 12bb771d66d4..000000000000 --- a/Documentation/devicetree/bindings/input/stmpe-keypad.txt +++ /dev/null @@ -1,41 +0,0 @@ -* STMPE Keypad - -Required properties: - - compatible : "st,stmpe-keypad" - - linux,keymap : See ./matrix-keymap.txt - -Optional properties: - - debounce-interval : Debouncing interval time in milliseconds - - st,scan-count : Scanning cycles elapsed before key data is updated - - st,no-autorepeat : If specified device will not autorepeat - - keypad,num-rows : See ./matrix-keymap.txt - - keypad,num-columns : See ./matrix-keymap.txt - -Example: - - stmpe_keypad { - compatible = "st,stmpe-keypad"; - - debounce-interval = <64>; - st,scan-count = <8>; - st,no-autorepeat; - - linux,keymap = <0x205006b - 0x4010074 - 0x3050072 - 0x1030004 - 0x502006a - 0x500000a - 0x5008b - 0x706001c - 0x405000b - 0x6070003 - 0x3040067 - 0x303006c - 0x60400e7 - 0x602009e - 0x4020073 - 0x5050002 - 0x4030069 - 0x3020008>; - }; diff --git a/Documentation/devicetree/bindings/input/touchscreen/stmpe.txt b/Documentation/devicetree/bindings/input/touchscreen/stmpe.txt deleted file mode 100644 index 238b51555c04..000000000000 --- a/Documentation/devicetree/bindings/input/touchscreen/stmpe.txt +++ /dev/null @@ -1,108 +0,0 @@ -STMPE Touchscreen ----------------- - -Required properties: - - compatible: "st,stmpe-ts" - -Optional properties: -- st,ave-ctrl : Sample average control - 0 -> 1 sample - 1 -> 2 samples - 2 -> 4 samples - 3 -> 8 samples -- st,touch-det-delay : Touch detect interrupt delay (recommended is 3) - 0 -> 10 us - 1 -> 50 us - 2 -> 100 us - 3 -> 500 us - 4 -> 1 ms - 5 -> 5 ms - 6 -> 10 ms - 7 -> 50 ms -- st,settling : Panel driver settling time (recommended is 2) - 0 -> 10 us - 1 -> 100 us - 2 -> 500 us - 3 -> 1 ms - 4 -> 5 ms - 5 -> 10 ms - 6 -> 50 ms - 7 -> 100 ms -- st,fraction-z : Length of the fractional part in z (recommended is 7) - (fraction-z ([0..7]) = Count of the fractional part) -- st,i-drive : current limit value of the touchscreen drivers - 0 -> 20 mA (typical 35mA max) - 1 -> 50 mA (typical 80 mA max) - -Optional properties common with MFD (deprecated): - - st,sample-time : ADC conversion time in number of clock. - 0 -> 36 clocks - 1 -> 44 clocks - 2 -> 56 clocks - 3 -> 64 clocks - 4 -> 80 clocks (recommended) - 5 -> 96 clocks - 6 -> 124 clocks - - st,mod-12b : ADC Bit mode - 0 -> 10bit ADC - 1 -> 12bit ADC - - st,ref-sel : ADC reference source - 0 -> internal - 1 -> external - - st,adc-freq : ADC Clock speed - 0 -> 1.625 MHz - 1 -> 3.25 MHz - 2 || 3 -> 6.5 MHz - -Node should be child node of stmpe node to which it belongs. - -Note that common ADC settings of stmpe_touchscreen (child) will take precedence -over the settings done in MFD. - -Example: - -stmpe811@41 { - compatible = "st,stmpe811"; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_touch_int>; - #address-cells = <1>; - #size-cells = <0>; - reg = <0x41>; - interrupts = <10 IRQ_TYPE_LEVEL_LOW>; - interrupt-parent = <&gpio4>; - interrupt-controller; - id = <0>; - blocks = <0x5>; - irq-trigger = <0x1>; - /* Common ADC settings */ - /* 3.25 MHz ADC clock speed */ - st,adc-freq = <1>; - /* 12-bit ADC */ - st,mod-12b = <1>; - /* internal ADC reference */ - st,ref-sel = <0>; - /* ADC converstion time: 80 clocks */ - st,sample-time = <4>; - - stmpe_touchscreen { - compatible = "st,stmpe-ts"; - reg = <0>; - /* 8 sample average control */ - st,ave-ctrl = <3>; - /* 5 ms touch detect interrupt delay */ - st,touch-det-delay = <5>; - /* 1 ms panel driver settling time */ - st,settling = <3>; - /* 7 length fractional part in z */ - st,fraction-z = <7>; - /* - * 50 mA typical 80 mA max touchscreen drivers - * current limit value - */ - st,i-drive = <1>; - }; - stmpe_adc { - compatible = "st,stmpe-adc"; - st,norequest-mask = <0x0F>; - }; -}; diff --git a/Documentation/devicetree/bindings/leds/common.yaml b/Documentation/devicetree/bindings/leds/common.yaml index 58b492d00246..5fb7007f3618 100644 --- a/Documentation/devicetree/bindings/leds/common.yaml +++ b/Documentation/devicetree/bindings/leds/common.yaml @@ -83,8 +83,7 @@ properties: - enum: # LED will act as a back-light, controlled by the framebuffer system - backlight - # LED will turn on (but for leds-gpio see "default-state" property in - # Documentation/devicetree/bindings/leds/leds-gpio.yaml) + # LED will turn on (see also "default-state" property) - default-on # LED "double" flashes at a load average based rate - heartbeat @@ -158,6 +157,18 @@ properties: For flash LED controllers with configurable current this property is mandatory for the LEDs in the non-flash modes (e.g. torch or indicator). + max-brightness: + description: + Normally, the maximum brightness is determined by the hardware, and this + property is not required. This property is used to set a software limit. + It could happen that an LED is made so bright that it gets damaged or + causes damage due to restrictions in a specific system, such as mounting + conditions. + Note that this flag is mainly used for PWM-LEDs, where it is not possible + to map brightness to current. Drivers for other controllers should use + led-max-microamp. + $ref: /schemas/types.yaml#definitions/uint32 + panic-indicator: description: This property specifies that the LED should be used, if at all possible, diff --git a/Documentation/devicetree/bindings/leds/leds-an30259a.txt b/Documentation/devicetree/bindings/leds/leds-an30259a.txt deleted file mode 100644 index cbd833906b2b..000000000000 --- a/Documentation/devicetree/bindings/leds/leds-an30259a.txt +++ /dev/null @@ -1,55 +0,0 @@ -* Panasonic AN30259A 3-channel LED driver - -The AN30259A is a LED controller capable of driving three LEDs independently. It supports -constant current output and sloping current output modes. The chip is connected over I2C. - -Required properties: - - compatible: Must be "panasonic,an30259a". - - reg: I2C slave address. - - #address-cells: Must be 1. - - #size-cells: Must be 0. - -Each LED is represented as a sub-node of the panasonic,an30259a node. - -Required sub-node properties: - - reg: Pin that the LED is connected to. Must be 1, 2, or 3. - -Optional sub-node properties: - - function : - see Documentation/devicetree/bindings/leds/common.txt - - color : - see Documentation/devicetree/bindings/leds/common.txt - - label : - see Documentation/devicetree/bindings/leds/common.txt (deprecated) - - linux,default-trigger : - see Documentation/devicetree/bindings/leds/common.txt - -Example: - -#include <dt-bindings/leds/common.h> - -led-controller@30 { - compatible = "panasonic,an30259a"; - reg = <0x30>; - #address-cells = <1>; - #size-cells = <0>; - - led@1 { - reg = <1>; - linux,default-trigger = "heartbeat"; - function = LED_FUNCTION_INDICATOR; - color = <LED_COLOR_ID_RED>; - }; - - led@2 { - reg = <2>; - function = LED_FUNCTION_INDICATOR; - color = <LED_COLOR_ID_GREEN>; - }; - - led@3 { - reg = <3>; - function = LED_FUNCTION_INDICATOR; - color = <LED_COLOR_ID_BLUE>; - }; -}; diff --git a/Documentation/devicetree/bindings/leds/leds-aw2013.yaml b/Documentation/devicetree/bindings/leds/leds-aw2013.yaml index 08f3e1cfc1b1..26238446f2bd 100644 --- a/Documentation/devicetree/bindings/leds/leds-aw2013.yaml +++ b/Documentation/devicetree/bindings/leds/leds-aw2013.yaml @@ -20,9 +20,20 @@ properties: reg: maxItems: 1 + interrupts: + maxItems: 1 + description: Open-drain, low active interrupt pin "INTN". + Used to report completion of operations (power up, LED breath effects). + vcc-supply: description: Regulator providing power to the "VCC" pin. + vio-supply: + description: Regulator providing power for pull-up of the I/O lines. + "VIO1" in the typical application circuit example of the datasheet. + Note that this regulator does not directly connect to AW2013, but is + needed for the correct operation of the interrupt and I2C lines. + "#address-cells": const: 1 @@ -52,6 +63,7 @@ additionalProperties: false examples: - | #include <dt-bindings/gpio/gpio.h> + #include <dt-bindings/interrupt-controller/irq.h> #include <dt-bindings/leds/common.h> i2c { @@ -61,6 +73,7 @@ examples: led-controller@45 { compatible = "awinic,aw2013"; reg = <0x45>; + interrupts = <42 IRQ_TYPE_LEVEL_LOW>; #address-cells = <1>; #size-cells = <0>; diff --git a/Documentation/devicetree/bindings/leds/leds-group-multicolor.yaml b/Documentation/devicetree/bindings/leds/leds-group-multicolor.yaml new file mode 100644 index 000000000000..8ed059a5a724 --- /dev/null +++ b/Documentation/devicetree/bindings/leds/leds-group-multicolor.yaml @@ -0,0 +1,64 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/leds/leds-group-multicolor.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Multi-color LED built with monochromatic LEDs + +maintainers: + - Jean-Jacques Hiblot <jjhiblot@traphandler.com> + +description: | + This driver combines several monochromatic LEDs into one multi-color + LED using the multicolor LED class. + +properties: + compatible: + const: leds-group-multicolor + + leds: + description: + An aray of monochromatic leds + $ref: /schemas/types.yaml#/definitions/phandle-array + +required: + - leds + +allOf: + - $ref: leds-class-multicolor.yaml# + +unevaluatedProperties: false + +examples: + - | + #include <dt-bindings/gpio/gpio.h> + #include <dt-bindings/leds/common.h> + + monochromatic-leds { + compatible = "gpio-leds"; + + led0: led-0 { + gpios = <&mcu_pio 0 GPIO_ACTIVE_LOW>; + color = <LED_COLOR_ID_RED>; + }; + + led1: led-1 { + gpios = <&mcu_pio 1 GPIO_ACTIVE_HIGH>; + color = <LED_COLOR_ID_GREEN>; + }; + + led2: led-2 { + gpios = <&mcu_pio 2 GPIO_ACTIVE_HIGH>; + color = <LED_COLOR_ID_BLUE>; + }; + }; + + multi-led { + compatible = "leds-group-multicolor"; + color = <LED_COLOR_ID_RGB>; + function = LED_FUNCTION_INDICATOR; + leds = <&led0>, <&led1>, <&led2>; + }; + +... diff --git a/Documentation/devicetree/bindings/leds/nxp,pca953x.yaml b/Documentation/devicetree/bindings/leds/nxp,pca953x.yaml index edf6f55df685..9610bca57dd5 100644 --- a/Documentation/devicetree/bindings/leds/nxp,pca953x.yaml +++ b/Documentation/devicetree/bindings/leds/nxp,pca953x.yaml @@ -29,6 +29,10 @@ properties: gpio-controller: true + gpio-line-names: + minItems: 1 + maxItems: 16 + '#gpio-cells': const: 2 diff --git a/Documentation/devicetree/bindings/leds/nxp,pca995x.yaml b/Documentation/devicetree/bindings/leds/nxp,pca995x.yaml new file mode 100644 index 000000000000..654915c1f687 --- /dev/null +++ b/Documentation/devicetree/bindings/leds/nxp,pca995x.yaml @@ -0,0 +1,81 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/leds/nxp,pca995x.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NXP PCA995x LED controllers + +maintainers: + - Isai Gaspar <isaiezequiel.gaspar@nxp.com> + - Marek Vasut <marex@denx.de> + +description: + The NXP PCA9952/PCA9955B are programmable LED controllers connected via I2C + that can drive 16 separate lines. Each of them can be individually switched + on and off, and brightness can be controlled via individual PWM. + + Datasheets are available at + https://www.nxp.com/docs/en/data-sheet/PCA9952_PCA9955.pdf + https://www.nxp.com/docs/en/data-sheet/PCA9955B.pdf + +properties: + compatible: + enum: + - nxp,pca9952 + - nxp,pca9955b + + reg: + maxItems: 1 + + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + +patternProperties: + "^led@[0-9a-f]+$": + type: object + $ref: common.yaml# + unevaluatedProperties: false + + properties: + reg: + minimum: 0 + maximum: 15 + + required: + - reg + +additionalProperties: false + +examples: + - | + #include <dt-bindings/leds/common.h> + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + led-controller@1 { + compatible = "nxp,pca9955b"; + reg = <0x01>; + #address-cells = <1>; + #size-cells = <0>; + + led@0 { + reg = <0x0>; + color = <LED_COLOR_ID_RED>; + function = LED_FUNCTION_POWER; + }; + + led@2 { + reg = <0x2>; + color = <LED_COLOR_ID_WHITE>; + function = LED_FUNCTION_STATUS; + }; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/leds/panasonic,an30259a.yaml b/Documentation/devicetree/bindings/leds/panasonic,an30259a.yaml new file mode 100644 index 000000000000..e918dceea082 --- /dev/null +++ b/Documentation/devicetree/bindings/leds/panasonic,an30259a.yaml @@ -0,0 +1,84 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/leds/panasonic,an30259a.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Panasonic AN30259A 3-channel LED controller + +maintainers: + - Iskren Chernev <me@iskren.info> + +description: + The AN30259A is a LED controller capable of driving three LEDs independently. + It supports constant current output and sloping current output modes. The chip + is connected over I2C. + +properties: + compatible: + const: panasonic,an30259a + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + +patternProperties: + "^led@[1-3]$": + $ref: common.yaml# + unevaluatedProperties: false + + properties: + reg: + enum: [ 1, 2, 3 ] + +required: + - compatible + - reg + - "#address-cells" + - "#size-cells" + +additionalProperties: false + +examples: + - | + #include <dt-bindings/leds/common.h> + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + led-controller@30 { + compatible = "panasonic,an30259a"; + reg = <0x30>; + #address-cells = <1>; + #size-cells = <0>; + + led@1 { + reg = <1>; + linux,default-trigger = "heartbeat"; + function = LED_FUNCTION_INDICATOR; + color = <LED_COLOR_ID_RED>; + }; + + led@2 { + reg = <2>; + function = LED_FUNCTION_INDICATOR; + color = <LED_COLOR_ID_GREEN>; + }; + + led@3 { + reg = <3>; + function = LED_FUNCTION_INDICATOR; + color = <LED_COLOR_ID_BLUE>; + }; + }; + }; +... diff --git a/Documentation/devicetree/bindings/leds/rohm,bd2606mvv.yaml b/Documentation/devicetree/bindings/leds/rohm,bd2606mvv.yaml index 14700a2e5fea..44dd91aa239d 100644 --- a/Documentation/devicetree/bindings/leds/rohm,bd2606mvv.yaml +++ b/Documentation/devicetree/bindings/leds/rohm,bd2606mvv.yaml @@ -35,7 +35,7 @@ properties: description: GPIO pin to enable/disable the device. patternProperties: - "^led@[0-6]$": + "^led@[0-5]$": type: object $ref: common.yaml# unevaluatedProperties: false @@ -43,7 +43,7 @@ patternProperties: properties: reg: minimum: 0 - maximum: 6 + maximum: 5 required: - reg diff --git a/Documentation/devicetree/bindings/leds/rohm,bd71828-leds.yaml b/Documentation/devicetree/bindings/leds/rohm,bd71828-leds.yaml index 58f0d94c6d71..b7a3ef76cbf4 100644 --- a/Documentation/devicetree/bindings/leds/rohm,bd71828-leds.yaml +++ b/Documentation/devicetree/bindings/leds/rohm,bd71828-leds.yaml @@ -18,8 +18,6 @@ description: | The device has two LED outputs referred as GRNLED and AMBLED in data-sheet. -select: false - properties: compatible: const: rohm,bd71828-leds diff --git a/Documentation/devicetree/bindings/mfd/allwinner,sun6i-a31-prcm.yaml b/Documentation/devicetree/bindings/mfd/allwinner,sun6i-a31-prcm.yaml index cf94176fe1eb..8789e3639ff7 100644 --- a/Documentation/devicetree/bindings/mfd/allwinner,sun6i-a31-prcm.yaml +++ b/Documentation/devicetree/bindings/mfd/allwinner,sun6i-a31-prcm.yaml @@ -34,6 +34,9 @@ patternProperties: - allwinner,sun6i-a31-clock-reset - fixed-factor-clock + required: + - compatible + allOf: - if: properties: @@ -55,25 +58,17 @@ patternProperties: "#clock-cells": const: 0 - # Already checked in the main schema - compatible: true - clocks: maxItems: 2 clock-output-names: maxItems: 1 - phandle: true - required: - "#clock-cells" - - compatible - clocks - clock-output-names - additionalProperties: false - - if: properties: compatible: @@ -85,25 +80,17 @@ patternProperties: "#clock-cells": const: 0 - # Already checked in the main schema - compatible: true - clocks: maxItems: 1 clock-output-names: maxItems: 1 - phandle: true - required: - "#clock-cells" - - compatible - clocks - clock-output-names - additionalProperties: false - - if: properties: compatible: @@ -119,9 +106,6 @@ patternProperties: offset of the bit controlling this particular gate in the register. - # Already checked in the main schema - compatible: true - clocks: maxItems: 1 @@ -129,16 +113,11 @@ patternProperties: minItems: 1 maxItems: 32 - phandle: true - required: - "#clock-cells" - - compatible - clocks - clock-output-names - additionalProperties: false - - if: properties: compatible: @@ -150,9 +129,6 @@ patternProperties: "#clock-cells": const: 0 - # Already checked in the main schema - compatible: true - clocks: maxItems: 4 description: > @@ -162,16 +138,11 @@ patternProperties: clock-output-names: maxItems: 1 - phandle: true - required: - "#clock-cells" - - compatible - clocks - clock-output-names - additionalProperties: false - - if: properties: compatible: @@ -183,16 +154,8 @@ patternProperties: "#reset-cells": const: 1 - # Already checked in the main schema - compatible: true - - phandle: true - required: - "#reset-cells" - - compatible - - additionalProperties: false required: - compatible diff --git a/Documentation/devicetree/bindings/mfd/allwinner,sun8i-a23-prcm.yaml b/Documentation/devicetree/bindings/mfd/allwinner,sun8i-a23-prcm.yaml index 16c80a7eec49..e51f85519911 100644 --- a/Documentation/devicetree/bindings/mfd/allwinner,sun8i-a23-prcm.yaml +++ b/Documentation/devicetree/bindings/mfd/allwinner,sun8i-a23-prcm.yaml @@ -57,25 +57,17 @@ patternProperties: "#clock-cells": const: 0 - # Already checked in the main schema - compatible: true - clocks: maxItems: 1 clock-output-names: maxItems: 1 - phandle: true - required: - "#clock-cells" - - compatible - clocks - clock-output-names - additionalProperties: false - - if: properties: compatible: @@ -91,9 +83,6 @@ patternProperties: offset of the bit controlling this particular gate in the register. - # Already checked in the main schema - compatible: true - clocks: maxItems: 1 @@ -101,16 +90,11 @@ patternProperties: minItems: 1 maxItems: 32 - phandle: true - required: - "#clock-cells" - - compatible - clocks - clock-output-names - additionalProperties: false - - if: properties: compatible: @@ -122,34 +106,8 @@ patternProperties: "#reset-cells": const: 1 - # Already checked in the main schema - compatible: true - - phandle: true - required: - "#reset-cells" - - compatible - - additionalProperties: false - - - if: - properties: - compatible: - contains: - const: allwinner,sun8i-a23-codec-analog - - then: - properties: - # Already checked in the main schema - compatible: true - - phandle: true - - required: - - compatible - - additionalProperties: false required: - compatible diff --git a/Documentation/devicetree/bindings/mfd/atmel-flexcom.txt b/Documentation/devicetree/bindings/mfd/atmel-flexcom.txt index 9d837535637b..af692e8833a5 100644 --- a/Documentation/devicetree/bindings/mfd/atmel-flexcom.txt +++ b/Documentation/devicetree/bindings/mfd/atmel-flexcom.txt @@ -6,6 +6,7 @@ at boot time according to the device tree. Required properties: - compatible: Should be "atmel,sama5d2-flexcom" + or "microchip,sam9x7-flexcom", "atmel,sama5d2-flexcom" - reg: Should be the offset/length value for Flexcom dedicated I/O registers (without USART, TWI or SPI registers). - clocks: Should be the Flexcom peripheral clock from PMC. diff --git a/Documentation/devicetree/bindings/mfd/atmel-gpbr.txt b/Documentation/devicetree/bindings/mfd/atmel-gpbr.txt index e8c525569f10..3c989d1760a2 100644 --- a/Documentation/devicetree/bindings/mfd/atmel-gpbr.txt +++ b/Documentation/devicetree/bindings/mfd/atmel-gpbr.txt @@ -6,6 +6,7 @@ Required properties: - compatible: Should be one of the following: "atmel,at91sam9260-gpbr", "syscon" "microchip,sam9x60-gpbr", "syscon" + "microchip,sam9x7-gpbr", "microchip,sam9x60-gpbr", "syscon" - reg: contains offset/length value of the GPBR memory region. diff --git a/Documentation/devicetree/bindings/mfd/atmel-hlcdc.txt b/Documentation/devicetree/bindings/mfd/atmel-hlcdc.txt index 5f8880cc757e..7de696eefaed 100644 --- a/Documentation/devicetree/bindings/mfd/atmel-hlcdc.txt +++ b/Documentation/devicetree/bindings/mfd/atmel-hlcdc.txt @@ -8,6 +8,7 @@ Required properties: "atmel,sama5d3-hlcdc" "atmel,sama5d4-hlcdc" "microchip,sam9x60-hlcdc" + "microchip,sam9x75-xlcdc" - reg: base address and size of the HLCDC device registers. - clock-names: the name of the 3 clocks requested by the HLCDC device. Should contain "periph_clk", "sys_clk" and "slow_clk". diff --git a/Documentation/devicetree/bindings/mfd/atmel-matrix.txt b/Documentation/devicetree/bindings/mfd/atmel-matrix.txt index 89d05c64fb01..6e5f83614e83 100644 --- a/Documentation/devicetree/bindings/mfd/atmel-matrix.txt +++ b/Documentation/devicetree/bindings/mfd/atmel-matrix.txt @@ -14,6 +14,7 @@ Required properties: "atmel,at91sam9x5-matrix", "syscon" "atmel,sama5d3-matrix", "syscon" "microchip,sam9x60-matrix", "syscon" + "microchip,sam9x7-matrix", "atmel,at91sam9x5-matrix", "syscon" - reg: Contains offset/length value of the Bus Matrix memory region. diff --git a/Documentation/devicetree/bindings/mfd/atmel-smc.txt b/Documentation/devicetree/bindings/mfd/atmel-smc.txt index 5696d9fcb5dc..fd62add38a79 100644 --- a/Documentation/devicetree/bindings/mfd/atmel-smc.txt +++ b/Documentation/devicetree/bindings/mfd/atmel-smc.txt @@ -10,6 +10,7 @@ Required properties: "atmel,sama5d3-smc", "syscon" "atmel,sama5d2-smc", "syscon" "microchip,sam9x60-smc", "syscon" + "microchip,sam9x7-smc", "atmel,at91sam9260-smc", "syscon" - reg: Contains offset/length value of the SMC memory region. diff --git a/Documentation/devicetree/bindings/mfd/brcm,bcm6318-gpio-sysctl.yaml b/Documentation/devicetree/bindings/mfd/brcm,bcm6318-gpio-sysctl.yaml index 9f9a14af875e..cb480162f967 100644 --- a/Documentation/devicetree/bindings/mfd/brcm,bcm6318-gpio-sysctl.yaml +++ b/Documentation/devicetree/bindings/mfd/brcm,bcm6318-gpio-sysctl.yaml @@ -35,7 +35,7 @@ patternProperties: "^gpio@[0-9a-f]+$": # Child node type: object - $ref: "../gpio/brcm,bcm63xx-gpio.yaml" + $ref: /schemas/gpio/brcm,bcm63xx-gpio.yaml description: GPIO controller for the SoC GPIOs. This child node definition should follow the bindings specified in @@ -44,7 +44,7 @@ patternProperties: "^pinctrl@[0-9a-f]+$": # Child node type: object - $ref: "../pinctrl/brcm,bcm6318-pinctrl.yaml" + $ref: /schemas/pinctrl/brcm,bcm6318-pinctrl.yaml description: Pin controller for the SoC pins. This child node definition should follow the bindings specified in diff --git a/Documentation/devicetree/bindings/mfd/brcm,bcm63268-gpio-sysctl.yaml b/Documentation/devicetree/bindings/mfd/brcm,bcm63268-gpio-sysctl.yaml index 803277dd2725..c14def1b2ad2 100644 --- a/Documentation/devicetree/bindings/mfd/brcm,bcm63268-gpio-sysctl.yaml +++ b/Documentation/devicetree/bindings/mfd/brcm,bcm63268-gpio-sysctl.yaml @@ -35,7 +35,7 @@ patternProperties: "^gpio@[0-9a-f]+$": # Child node type: object - $ref: "../gpio/brcm,bcm63xx-gpio.yaml" + $ref: /schemas/gpio/brcm,bcm63xx-gpio.yaml description: GPIO controller for the SoC GPIOs. This child node definition should follow the bindings specified in @@ -44,7 +44,7 @@ patternProperties: "^pinctrl@[0-9a-f]+$": # Child node type: object - $ref: "../pinctrl/brcm,bcm63268-pinctrl.yaml" + $ref: /schemas/pinctrl/brcm,bcm63268-pinctrl.yaml description: Pin controller for the SoC pins. This child node definition should follow the bindings specified in diff --git a/Documentation/devicetree/bindings/mfd/brcm,bcm6328-gpio-sysctl.yaml b/Documentation/devicetree/bindings/mfd/brcm,bcm6328-gpio-sysctl.yaml index b9a6856ce970..5f48209ed40f 100644 --- a/Documentation/devicetree/bindings/mfd/brcm,bcm6328-gpio-sysctl.yaml +++ b/Documentation/devicetree/bindings/mfd/brcm,bcm6328-gpio-sysctl.yaml @@ -35,7 +35,7 @@ patternProperties: "^gpio@[0-9a-f]+$": # Child node type: object - $ref: "../gpio/brcm,bcm63xx-gpio.yaml" + $ref: /schemas/gpio/brcm,bcm63xx-gpio.yaml description: GPIO controller for the SoC GPIOs. This child node definition should follow the bindings specified in @@ -44,7 +44,7 @@ patternProperties: "^pinctrl@[0-9a-f]+$": # Child node type: object - $ref: "../pinctrl/brcm,bcm6328-pinctrl.yaml" + $ref: /schemas/pinctrl/brcm,bcm6328-pinctrl.yaml description: Pin controller for the SoC pins. This child node definition should follow the bindings specified in diff --git a/Documentation/devicetree/bindings/mfd/brcm,bcm6358-gpio-sysctl.yaml b/Documentation/devicetree/bindings/mfd/brcm,bcm6358-gpio-sysctl.yaml index 4651fe4dde07..f1f4629565d9 100644 --- a/Documentation/devicetree/bindings/mfd/brcm,bcm6358-gpio-sysctl.yaml +++ b/Documentation/devicetree/bindings/mfd/brcm,bcm6358-gpio-sysctl.yaml @@ -35,7 +35,7 @@ patternProperties: "^gpio@[0-9a-f]+$": # Child node type: object - $ref: "../gpio/brcm,bcm63xx-gpio.yaml" + $ref: /schemas/gpio/brcm,bcm63xx-gpio.yaml description: GPIO controller for the SoC GPIOs. This child node definition should follow the bindings specified in @@ -44,7 +44,7 @@ patternProperties: "^pinctrl@[0-9a-f]+$": # Child node type: object - $ref: "../pinctrl/brcm,bcm6358-pinctrl.yaml" + $ref: /schemas/pinctrl/brcm,bcm6358-pinctrl.yaml description: Pin controller for the SoC pins. This child node definition should follow the bindings specified in diff --git a/Documentation/devicetree/bindings/mfd/brcm,bcm6362-gpio-sysctl.yaml b/Documentation/devicetree/bindings/mfd/brcm,bcm6362-gpio-sysctl.yaml index 0330b621fd38..4d594739b382 100644 --- a/Documentation/devicetree/bindings/mfd/brcm,bcm6362-gpio-sysctl.yaml +++ b/Documentation/devicetree/bindings/mfd/brcm,bcm6362-gpio-sysctl.yaml @@ -35,7 +35,7 @@ patternProperties: "^gpio@[0-9a-f]+$": # Child node type: object - $ref: "../gpio/brcm,bcm63xx-gpio.yaml" + $ref: /schemas/gpio/brcm,bcm63xx-gpio.yaml description: GPIO controller for the SoC GPIOs. This child node definition should follow the bindings specified in @@ -44,7 +44,7 @@ patternProperties: "^pinctrl@[0-9a-f]+$": # Child node type: object - $ref: "../pinctrl/brcm,bcm6362-pinctrl.yaml" + $ref: /schemas/pinctrl/brcm,bcm6362-pinctrl.yaml description: Pin controller for the SoC pins. This child node definition should follow the bindings specified in diff --git a/Documentation/devicetree/bindings/mfd/brcm,bcm6368-gpio-sysctl.yaml b/Documentation/devicetree/bindings/mfd/brcm,bcm6368-gpio-sysctl.yaml index 82d3e4415bda..aae83d432880 100644 --- a/Documentation/devicetree/bindings/mfd/brcm,bcm6368-gpio-sysctl.yaml +++ b/Documentation/devicetree/bindings/mfd/brcm,bcm6368-gpio-sysctl.yaml @@ -35,7 +35,7 @@ patternProperties: "^gpio@[0-9a-f]+$": # Child node type: object - $ref: "../gpio/brcm,bcm63xx-gpio.yaml" + $ref: /schemas/gpio/brcm,bcm63xx-gpio.yaml description: GPIO controller for the SoC GPIOs. This child node definition should follow the bindings specified in @@ -44,7 +44,7 @@ patternProperties: "^pinctrl@[0-9a-f]+$": # Child node type: object - $ref: "../pinctrl/brcm,bcm6368-pinctrl.yaml" + $ref: /schemas/pinctrl/brcm,bcm6368-pinctrl.yaml description: Pin controller for the SoC pins. This child node definition should follow the bindings specified in diff --git a/Documentation/devicetree/bindings/mfd/maxim,max77693.yaml b/Documentation/devicetree/bindings/mfd/maxim,max77693.yaml index 1b06a77ec798..9804d13de648 100644 --- a/Documentation/devicetree/bindings/mfd/maxim,max77693.yaml +++ b/Documentation/devicetree/bindings/mfd/maxim,max77693.yaml @@ -31,12 +31,17 @@ properties: charger: $ref: /schemas/power/supply/maxim,max77693.yaml + connector: + $ref: /schemas/connector/usb-connector.yaml# + unevaluatedProperties: false + led: $ref: /schemas/leds/maxim,max77693.yaml max77693-muic: type: object additionalProperties: false + deprecated: true properties: compatible: @@ -45,6 +50,21 @@ properties: required: - compatible + muic: + type: object + additionalProperties: false + + properties: + compatible: + const: maxim,max77693-muic + + connector: + $ref: /schemas/connector/usb-connector.yaml# + unevaluatedProperties: false + + required: + - compatible + motor-driver: type: object additionalProperties: false @@ -107,6 +127,38 @@ examples: }; }; + muic { + compatible = "maxim,max77693-muic"; + + connector { + compatible = "samsung,usb-connector-11pin", + "usb-b-connector"; + label = "micro-USB"; + type = "micro"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + muic_to_usb: endpoint { + remote-endpoint = <&usb_to_muic>; + }; + }; + + port@3 { + reg = <3>; + + muic_to_mhl: endpoint { + remote-endpoint = <&mhl_to_muic>; + }; + }; + }; + }; + }; + motor-driver { compatible = "maxim,max77693-haptic"; haptic-supply = <&ldo26_reg>; diff --git a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml index 8b9a2008a354..9f03436b1cdc 100644 --- a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml +++ b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml @@ -41,6 +41,7 @@ properties: - qcom,pm660 - qcom,pm660l - qcom,pm7250b + - qcom,pm7550ba - qcom,pm7325 - qcom,pm8004 - qcom,pm8005 @@ -70,6 +71,8 @@ properties: - qcom,pm8994 - qcom,pm8998 - qcom,pma8084 + - qcom,pmc8180 + - qcom,pmc8180c - qcom,pmd9635 - qcom,pmi632 - qcom,pmi8950 @@ -88,6 +91,7 @@ properties: - qcom,pms405 - qcom,pmx55 - qcom,pmx65 + - qcom,pmx75 - qcom,smb2351 - const: qcom,spmi-pmic @@ -127,7 +131,7 @@ patternProperties: "^audio-codec@[0-9a-f]+$": type: object - additionalProperties: true # FIXME qcom,pm8916-wcd-analog-codec binding not converted yet + $ref: /schemas/sound/qcom,pm8916-wcd-analog-codec.yaml# "^charger@[0-9a-f]+$": type: object diff --git a/Documentation/devicetree/bindings/mfd/rohm,bd71847-pmic.yaml b/Documentation/devicetree/bindings/mfd/rohm,bd71847-pmic.yaml index 7ab7b2c7f3e6..d783cc4e4e86 100644 --- a/Documentation/devicetree/bindings/mfd/rohm,bd71847-pmic.yaml +++ b/Documentation/devicetree/bindings/mfd/rohm,bd71847-pmic.yaml @@ -130,7 +130,6 @@ dependencies: examples: - | #include <dt-bindings/interrupt-controller/irq.h> - #include <dt-bindings/leds/common.h> i2c { #address-cells = <1>; diff --git a/Documentation/devicetree/bindings/mfd/st,stmpe.yaml b/Documentation/devicetree/bindings/mfd/st,stmpe.yaml new file mode 100644 index 000000000000..b77cc3f3075d --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/st,stmpe.yaml @@ -0,0 +1,297 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mfd/st,stmpe.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: STMicroelectonics Port Expander (STMPE) + +description: STMicroelectronics Port Expander (STMPE) is a series of slow + bus controllers for various expanded peripherals such as GPIO, keypad, + touchscreen, ADC, PWM or rotator. It can contain one or several different + peripherals connected to SPI or I2C. + +maintainers: + - Linus Walleij <linus.walleij@linaro.org> + +allOf: + - $ref: /schemas/spi/spi-peripheral-props.yaml# + +properties: + compatible: + enum: + - st,stmpe601 + - st,stmpe801 + - st,stmpe811 + - st,stmpe1600 + - st,stmpe1601 + - st,stmpe2401 + - st,stmpe2403 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + vcc-supply: true + + vio-supply: true + + reset-gpios: + maxItems: 1 + + wakeup-source: true + + st,autosleep-timeout: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [ 4, 16, 32, 64, 128, 256, 512, 1024 ] + description: Time idle before going to automatic sleep to save power + + st,sample-time: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [ 0, 1, 2, 3, 4, 5, 6 ] + description: | + Sample time per iteration + 0 = 36 clock ticks + 1 = 44 clock ticks + 2 = 56 clock ticks + 3 = 64 clock ticks + 4 = 80 clock ticks - recommended + 5 = 96 clock ticks + 6 = 124 clock ticks + + st,mod-12b: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [ 0, 1 ] + description: ADC bit mode 0 = 10bit ADC, 1 = 12bit ADC + + st,ref-sel: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [ 0, 1 ] + description: ADC reference source 0 = internal, 1 = external + + st,adc-freq: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [ 0, 1, 2, 3 ] + description: | + ADC clock speed + 0 = 1.625 MHz + 1 = 3.25 MHz + 2, 3 = 6.5 MHz + + adc: + type: object + $ref: /schemas/iio/adc/st,stmpe-adc.yaml# + + gpio: + type: object + $ref: /schemas/gpio/st,stmpe-gpio.yaml# + + keyboard-controller: + type: object + $ref: /schemas/input/matrix-keymap.yaml# + + unevaluatedProperties: false + + properties: + compatible: + const: st,stmpe-keypad + + debounce-interval: + description: Debouncing interval in milliseconds + $ref: /schemas/types.yaml#/definitions/uint32 + + st,no-autorepeat: + description: If present, the keys will not autorepeat when pressed + $ref: /schemas/types.yaml#/definitions/flag + + st,scan-count: + description: Scanning cycles elapsed before key data is updated + $ref: /schemas/types.yaml#/definitions/uint32 + + required: + - compatible + - linux,keymap + + pwm: + type: object + $ref: /schemas/pwm/pwm.yaml# + + unevaluatedProperties: false + + properties: + compatible: + const: st,stmpe-pwm + + "#pwm-cells": + const: 2 + + touchscreen: + type: object + $ref: /schemas/input/touchscreen/touchscreen.yaml# + + unevaluatedProperties: false + + properties: + compatible: + const: st,stmpe-ts + + st,ave-ctrl: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [ 0, 1, 2, 3 ] + description: | + Sample average control + 0 = 1 sample + 1 = 2 samples + 2 = 4 samples + 3 = 8 samples + + st,touch-det-delay: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [ 0, 1, 2, 3, 4, 5, 6, 7 ] + description: | + Touch detection delay + 0 = 10 us + 1 = 50 us + 2 = 100 us + 3 = 500 us - recommended + 4 = 1 ms + 5 = 5 ms + 6 = 10 ms + 7 = 50 ms + + st,settling: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [ 0, 1, 2, 3, 4, 5, 6, 7 ] + description: | + Panel driver settling time + 0 = 10 us + 1 = 100 us + 2 = 500 us - recommended + 3 = 1 ms + 4 = 5 ms + 5 = 10 ms + 6 = 50 ms + 7 = 100 ms + + st,fraction-z: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [ 0, 1, 2, 3, 4, 5, 6, 7 ] + description: Length of the fractional part in z, recommended is 7 + (fraction-z ([0..7]) = Count of the fractional part) + + st,i-drive: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [ 0, 1 ] + description: | + current limit value of the touchscreen drivers + 0 = 20 mA (typical 35 mA max) + 1 = 50 mA (typical 80 mA max) + + required: + - compatible + +additionalProperties: false + +required: + - compatible + - reg + - interrupts + +examples: + - | + #include <dt-bindings/gpio/gpio.h> + #include <dt-bindings/interrupt-controller/irq.h> + #include <dt-bindings/input/input.h> + i2c { + #address-cells = <1>; + #size-cells = <0>; + + port-expander@43 { + compatible = "st,stmpe2401"; + reg = <0x43>; + reset-gpios = <&gpio 13 GPIO_ACTIVE_LOW>; + interrupts = <26 IRQ_TYPE_EDGE_FALLING>; + interrupt-parent = <&gpio>; + vcc-supply = <&db8500_vsmps2_reg>; + vio-supply = <&db8500_vsmps2_reg>; + wakeup-source; + st,autosleep-timeout = <1024>; + + gpio { + compatible = "st,stmpe-gpio"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + st,norequest-mask = <0xf0f002>; + }; + + keyboard-controller { + compatible = "st,stmpe-keypad"; + debounce-interval = <64>; + st,scan-count = <8>; + st,no-autorepeat; + keypad,num-rows = <8>; + keypad,num-columns = <8>; + linux,keymap = < + MATRIX_KEY(0x00, 0x00, KEY_1) + MATRIX_KEY(0x00, 0x01, KEY_2) + MATRIX_KEY(0x00, 0x02, KEY_3) + MATRIX_KEY(0x00, 0x03, KEY_4) + MATRIX_KEY(0x00, 0x04, KEY_5) + MATRIX_KEY(0x00, 0x05, KEY_6) + MATRIX_KEY(0x00, 0x06, KEY_7) + MATRIX_KEY(0x00, 0x07, KEY_8) + MATRIX_KEY(0x00, 0x08, KEY_9) + MATRIX_KEY(0x00, 0x09, KEY_0) + >; + }; + + pwm { + compatible = "st,stmpe-pwm"; + #pwm-cells = <2>; + }; + }; + + port-expander@41 { + compatible = "st,stmpe811"; + reg = <0x41>; + interrupts = <10 IRQ_TYPE_LEVEL_LOW>; + interrupt-parent = <&gpio>; + st,adc-freq = <1>; + st,mod-12b = <1>; + st,ref-sel = <0>; + st,sample-time = <4>; + + adc { + compatible = "st,stmpe-adc"; + st,norequest-mask = <0x0f>; + #io-channel-cells = <1>; + }; + + gpio { + compatible = "st,stmpe-gpio"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + pwm { + compatible = "st,stmpe-pwm"; + #pwm-cells = <2>; + }; + + touchscreen { + compatible = "st,stmpe-ts"; + st,ave-ctrl = <3>; + st,touch-det-delay = <5>; + st,settling = <3>; + st,fraction-z = <7>; + st,i-drive = <1>; + }; + }; + }; +... diff --git a/Documentation/devicetree/bindings/mfd/st,stpmic1.yaml b/Documentation/devicetree/bindings/mfd/st,stpmic1.yaml index 97c61097f9e2..b17ebeb0a42f 100644 --- a/Documentation/devicetree/bindings/mfd/st,stpmic1.yaml +++ b/Documentation/devicetree/bindings/mfd/st,stpmic1.yaml @@ -106,6 +106,7 @@ properties: const: st,stpmic1-regulators ldo3: + $ref: /schemas/regulator/regulator.yaml type: object properties: @@ -128,6 +129,7 @@ properties: additionalProperties: false ldo4: + $ref: /schemas/regulator/regulator.yaml type: object properties: @@ -142,11 +144,14 @@ properties: regulator-name: true regulator-boot-on: true regulator-always-on: true + regulator-min-microvolt: true + regulator-max-microvolt: true regulator-over-current-protection: true additionalProperties: false vref_ddr: + $ref: /schemas/regulator/regulator.yaml type: object properties: @@ -165,6 +170,7 @@ properties: additionalProperties: false boost: + $ref: /schemas/regulator/regulator.yaml type: object properties: @@ -187,10 +193,8 @@ properties: "^(buck[1-4]|ldo[1-6]|vref_ddr|boost|pwr_sw[1-2])-supply$": description: STPMIC1 voltage regulators supplies - "^(buck[1-4]|ldo[1-6]|boost|vref_ddr|pwr_sw[1-2])$": - $ref: ../regulator/regulator.yaml - "^ldo[1-2,5-6]$": + $ref: /schemas/regulator/regulator.yaml type: object properties: @@ -213,6 +217,7 @@ properties: additionalProperties: false "^buck[1-4]$": + $ref: /schemas/regulator/regulator.yaml type: object properties: @@ -237,6 +242,7 @@ properties: additionalProperties: false "^pwr_sw[1-2]$": + $ref: /schemas/regulator/regulator.yaml type: object properties: diff --git a/Documentation/devicetree/bindings/mfd/stericsson,db8500-prcmu.yaml b/Documentation/devicetree/bindings/mfd/stericsson,db8500-prcmu.yaml index a66d58b4d1f2..5e0002f099e4 100644 --- a/Documentation/devicetree/bindings/mfd/stericsson,db8500-prcmu.yaml +++ b/Documentation/devicetree/bindings/mfd/stericsson,db8500-prcmu.yaml @@ -72,44 +72,52 @@ properties: main voltage domain for the chip. type: object $ref: ../regulator/regulator.yaml# + unevaluatedProperties: false db8500_varm: description: The voltage for the ARM Cortex A-9 CPU. type: object $ref: ../regulator/regulator.yaml# + unevaluatedProperties: false db8500_vmodem: description: The voltage for the modem subsystem. type: object $ref: ../regulator/regulator.yaml# + unevaluatedProperties: false db8500_vpll: description: The voltage for the phase locked loop clocks. type: object $ref: ../regulator/regulator.yaml# + unevaluatedProperties: false db8500_vsmps1: description: Also known as VIO12, is a step-down voltage regulator for 1.2V I/O. SMPS means System Management Power Source. type: object $ref: ../regulator/regulator.yaml# + unevaluatedProperties: false db8500_vsmps2: description: Also known as VIO18, is a step-down voltage regulator for 1.8V I/O. SMPS means System Management Power Source. type: object $ref: ../regulator/regulator.yaml# + unevaluatedProperties: false db8500_vsmps3: description: This is a step-down voltage regulator for 0.87 thru 1.875V I/O. SMPS means System Management Power Source. type: object $ref: ../regulator/regulator.yaml# + unevaluatedProperties: false db8500_vrf1: description: RF transceiver voltage regulator. type: object $ref: ../regulator/regulator.yaml# + unevaluatedProperties: false db8500_sva_mmdsp: description: Smart Video Accelerator (SVA) multimedia DSP (MMDSP) @@ -117,18 +125,21 @@ properties: for video encoding and decoding. type: object $ref: ../regulator/regulator.yaml# + unevaluatedProperties: false db8500_sva_mmdsp_ret: description: Smart Video Accelerator (SVA) multimedia DSP (MMDSP) voltage regulator for retention mode. type: object $ref: ../regulator/regulator.yaml# + unevaluatedProperties: false db8500_sva_pipe: description: Smart Video Accelerator (SVA) multimedia DSP (MMDSP) voltage regulator for the data pipe. type: object $ref: ../regulator/regulator.yaml# + unevaluatedProperties: false db8500_sia_mmdsp: description: Smart Image Accelerator (SIA) multimedia DSP (MMDSP) @@ -136,18 +147,21 @@ properties: for image encoding and decoding. type: object $ref: ../regulator/regulator.yaml# + unevaluatedProperties: false db8500_sia_mmdsp_ret: description: Smart Image Accelerator (SIA) multimedia DSP (MMDSP) voltage regulator for retention mode. type: object $ref: ../regulator/regulator.yaml# + unevaluatedProperties: false db8500_sia_pipe: description: Smart Image Accelerator (SIA) multimedia DSP (MMDSP) voltage regulator for the data pipe. type: object $ref: ../regulator/regulator.yaml# + unevaluatedProperties: false db8500_sga: description: Smart Graphics Accelerator (SGA) voltage regulator. @@ -155,6 +169,7 @@ properties: accelerator block. type: object $ref: ../regulator/regulator.yaml# + unevaluatedProperties: false db8500_b2r2_mcde: description: Blit Blend Rotate and Rescale (B2R2), and Multi-Channel @@ -162,28 +177,33 @@ properties: blocks. type: object $ref: ../regulator/regulator.yaml# + unevaluatedProperties: false db8500_esram12: description: Embedded Static RAM (ESRAM) 1 and 2 voltage regulator. type: object $ref: ../regulator/regulator.yaml# + unevaluatedProperties: false db8500_esram12_ret: description: Embedded Static RAM (ESRAM) 1 and 2 voltage regulator for retention mode. type: object $ref: ../regulator/regulator.yaml# + unevaluatedProperties: false db8500_esram34: description: Embedded Static RAM (ESRAM) 3 and 4 voltage regulator. type: object $ref: ../regulator/regulator.yaml# + unevaluatedProperties: false db8500_esram34_ret: description: Embedded Static RAM (ESRAM) 3 and 4 voltage regulator for retention mode. type: object $ref: ../regulator/regulator.yaml# + unevaluatedProperties: false required: - compatible diff --git a/Documentation/devicetree/bindings/mfd/stmpe.txt b/Documentation/devicetree/bindings/mfd/stmpe.txt deleted file mode 100644 index d4408a417193..000000000000 --- a/Documentation/devicetree/bindings/mfd/stmpe.txt +++ /dev/null @@ -1,42 +0,0 @@ -* ST Microelectronics STMPE Multi-Functional Device - -STMPE is an MFD device which may expose the following inbuilt devices: gpio, -keypad, touchscreen, adc, pwm, rotator. - -Required properties: - - compatible : "st,stmpe[610|801|811|1600|1601|2401|2403]" - - reg : I2C/SPI address of the device - -Optional properties: - - interrupts : The interrupt outputs from the controller - - interrupt-controller : Marks the device node as an interrupt controller - - wakeup-source : Marks the input device as wakable - - st,autosleep-timeout : Valid entries (ms); 4, 16, 32, 64, 128, 256, 512 and 1024 - - irq-gpio : If present, which GPIO to use for event IRQ - -Optional properties for devices with touch and ADC (STMPE811|STMPE610): - - st,sample-time : ADC conversion time in number of clock. - 0 -> 36 clocks 4 -> 80 clocks (recommended) - 1 -> 44 clocks 5 -> 96 clocks - 2 -> 56 clocks 6 -> 124 clocks - 3 -> 64 clocks - - st,mod-12b : ADC Bit mode - 0 -> 10bit ADC 1 -> 12bit ADC - - st,ref-sel : ADC reference source - 0 -> internal 1 -> external - - st,adc-freq : ADC Clock speed - 0 -> 1.625 MHz 2 || 3 -> 6.5 MHz - 1 -> 3.25 MHz - -Example: - - stmpe1601: stmpe1601@40 { - compatible = "st,stmpe1601"; - reg = <0x40>; - interrupts = <26 0x4>; - interrupt-parent = <&gpio6>; - interrupt-controller; - - wakeup-source; - st,autosleep-timeout = <1024>; - }; diff --git a/Documentation/devicetree/bindings/remoteproc/fsl,imx-rproc.yaml b/Documentation/devicetree/bindings/remoteproc/fsl,imx-rproc.yaml index 0c3910f152d1..30632efdad8b 100644 --- a/Documentation/devicetree/bindings/remoteproc/fsl,imx-rproc.yaml +++ b/Documentation/devicetree/bindings/remoteproc/fsl,imx-rproc.yaml @@ -20,7 +20,9 @@ properties: - fsl,imx7ulp-cm4 - fsl,imx8mm-cm4 - fsl,imx8mn-cm7 + - fsl,imx8mn-cm7-mmio - fsl,imx8mp-cm7 + - fsl,imx8mp-cm7-mmio - fsl,imx8mq-cm4 - fsl,imx8qm-cm4 - fsl,imx8qxp-cm4 @@ -70,6 +72,11 @@ properties: description: Specify CPU entry address for SCU enabled processor. + fsl,iomuxc-gpr: + $ref: /schemas/types.yaml#/definitions/phandle + description: + Phandle to IOMUXC GPR block which provide access to CM7 CPUWAIT bit. + fsl,resource-id: $ref: /schemas/types.yaml#/definitions/uint32 description: @@ -79,6 +86,19 @@ properties: required: - compatible +allOf: + - if: + properties: + compatible: + not: + contains: + enum: + - fsl,imx8mn-cm7-mmio + - fsl,imx8mp-cm7-mmio + then: + properties: + fsl,iomuxc-gpr: false + additionalProperties: false examples: diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml index 643ee787a81f..a2b0079de039 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml @@ -26,6 +26,7 @@ properties: - qcom,sdm660-adsp-pas - qcom,sdm845-adsp-pas - qcom,sdm845-cdsp-pas + - qcom,sdm845-slpi-pas reg: maxItems: 1 @@ -44,8 +45,13 @@ properties: maxItems: 1 description: Reference to the reserved-memory for the Hexagon core + firmware-name: + maxItems: 1 + description: Firmware name for the Hexagon core + required: - compatible + - memory-region unevaluatedProperties: false @@ -63,6 +69,7 @@ allOf: - qcom,msm8998-adsp-pas - qcom,sdm845-adsp-pas - qcom,sdm845-cdsp-pas + - qcom,sdm845-slpi-pas then: properties: clocks: @@ -104,6 +111,7 @@ allOf: - qcom,msm8998-slpi-pas - qcom,sdm845-adsp-pas - qcom,sdm845-cdsp-pas + - qcom,sdm845-slpi-pas then: properties: interrupts: @@ -160,6 +168,22 @@ allOf: - if: properties: compatible: + enum: + - qcom,sdm845-slpi-pas + then: + properties: + power-domains: + items: + - description: LCX power domain + - description: LMX power domain + power-domain-names: + items: + - const: lcx + - const: lmx + + - if: + properties: + compatible: contains: enum: - qcom,msm8226-adsp-pil diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,msm8996-mss-pil.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,msm8996-mss-pil.yaml index c1ac6ca1e759..0643faae2c39 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,msm8996-mss-pil.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,msm8996-mss-pil.yaml @@ -19,6 +19,7 @@ properties: enum: - qcom,msm8996-mss-pil - qcom,msm8998-mss-pil + - qcom,sdm660-mss-pil - qcom,sdm845-mss-pil reg: @@ -215,13 +216,12 @@ allOf: - description: GCC MSS IFACE clock - description: GCC MSS BUS clock - description: GCC MSS MEM clock - - description: RPMH XO clock + - description: RPM XO clock - description: GCC MSS GPLL0 clock - description: GCC MSS SNOC_AXI clock - description: GCC MSS MNOC_AXI clock - - description: RPMH PNOC clock - - description: GCC MSS PRNG clock - - description: RPMH QDSS clock + - description: RPM PNOC clock + - description: RPM QDSS clock clock-names: items: - const: iface @@ -245,7 +245,9 @@ allOf: - if: properties: compatible: - const: qcom,msm8998-mss-pil + enum: + - qcom,msm8998-mss-pil + - qcom,sdm660-mss-pil then: properties: clocks: diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml index 171ef85de193..63a82e7a8bf8 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml @@ -82,7 +82,6 @@ required: - clock-names - interrupts - interrupt-names - - memory-region - qcom,smem-states - qcom,smem-state-names diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,qcs404-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,qcs404-pas.yaml index 5efa0e5c0439..eb868a7ff4cd 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,qcs404-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,qcs404-pas.yaml @@ -42,7 +42,7 @@ properties: smd-edge: false memory-region: - minItems: 1 + maxItems: 1 description: Reference to the reserved-memory for the Hexagon core firmware-name: @@ -52,6 +52,7 @@ properties: required: - compatible - reg + - memory-region allOf: - $ref: /schemas/remoteproc/qcom,pas-common.yaml# diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sc7180-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sc7180-pas.yaml index 5cefd2c58593..689d5d535331 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sc7180-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sc7180-pas.yaml @@ -51,7 +51,7 @@ properties: - const: mss memory-region: - minItems: 1 + maxItems: 1 description: Reference to the reserved-memory for the Hexagon core qcom,qmp: @@ -67,6 +67,7 @@ properties: required: - compatible - reg + - memory-region allOf: - $ref: /schemas/remoteproc/qcom,pas-common.yaml# diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sc8180x-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sc8180x-pas.yaml index c1f8dd8d0e4c..4744a37b2b5d 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sc8180x-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sc8180x-pas.yaml @@ -38,7 +38,7 @@ properties: smd-edge: false memory-region: - minItems: 1 + maxItems: 1 description: Reference to the reserved-memory for the Hexagon core firmware-name: @@ -48,6 +48,7 @@ properties: required: - compatible - reg + - memory-region allOf: - $ref: /schemas/remoteproc/qcom,pas-common.yaml# diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sc8280xp-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sc8280xp-pas.yaml index f6fbc531dc28..96d53baf6e00 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sc8280xp-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sc8280xp-pas.yaml @@ -38,7 +38,7 @@ properties: smd-edge: false memory-region: - minItems: 1 + maxItems: 1 description: Reference to the reserved-memory for the Hexagon core firmware-name: @@ -48,6 +48,7 @@ properties: required: - compatible - reg + - memory-region allOf: - $ref: /schemas/remoteproc/qcom,pas-common.yaml# diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sdx55-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sdx55-pas.yaml index c66e298462c7..5d463272165f 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sdx55-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sdx55-pas.yaml @@ -46,7 +46,7 @@ properties: - const: mss memory-region: - minItems: 1 + maxItems: 1 description: Reference to the reserved-memory for the Hexagon core qcom,qmp: @@ -62,6 +62,7 @@ properties: required: - compatible - reg + - memory-region allOf: - $ref: /schemas/remoteproc/qcom,pas-common.yaml# diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm6115-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm6115-pas.yaml index f5d1fa9f45f1..028287235912 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm6115-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm6115-pas.yaml @@ -15,10 +15,19 @@ description: properties: compatible: - enum: - - qcom,sm6115-adsp-pas - - qcom,sm6115-cdsp-pas - - qcom,sm6115-mpss-pas + oneOf: + - enum: + - qcom,sm6115-adsp-pas + - qcom,sm6115-cdsp-pas + - qcom,sm6115-mpss-pas + + - items: + - const: qcom,qcm2290-adsp-pas + - const: qcom,sm6115-adsp-pas + + - items: + - const: qcom,qcm2290-mpss-pas + - const: qcom,sm6115-mpss-pas reg: maxItems: 1 @@ -32,7 +41,7 @@ properties: - const: xo memory-region: - minItems: 1 + maxItems: 1 description: Reference to the reserved-memory for the Hexagon core smd-edge: false @@ -44,15 +53,17 @@ properties: required: - compatible - reg + - memory-region allOf: - $ref: /schemas/remoteproc/qcom,pas-common.yaml# - if: properties: compatible: - enum: - - qcom,sm6115-adsp-pas - - qcom,sm6115-cdsp-pas + contains: + enum: + - qcom,sm6115-adsp-pas + - qcom,sm6115-cdsp-pas then: properties: interrupts: @@ -69,9 +80,10 @@ allOf: - if: properties: compatible: - enum: - - qcom,sm6115-cdsp-pas - - qcom,sm6115-mpss-pas + contains: + enum: + - qcom,sm6115-cdsp-pas + - qcom,sm6115-mpss-pas then: properties: power-domains: @@ -84,8 +96,9 @@ allOf: - if: properties: compatible: - enum: - - qcom,sm6115-adsp-pas + contains: + enum: + - qcom,sm6115-adsp-pas then: properties: power-domains: diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm6350-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm6350-pas.yaml index fee02fa800b5..f7e40fb166da 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm6350-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm6350-pas.yaml @@ -36,7 +36,7 @@ properties: description: Reference to the AOSS side-channel message RAM. memory-region: - minItems: 1 + maxItems: 1 description: Reference to the reserved-memory for the Hexagon core smd-edge: false @@ -48,6 +48,7 @@ properties: required: - compatible - reg + - memory-region allOf: - $ref: /schemas/remoteproc/qcom,pas-common.yaml# diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm8150-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm8150-pas.yaml index 2c085ac2c3fb..238c6e5e67c5 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm8150-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm8150-pas.yaml @@ -40,7 +40,7 @@ properties: description: Reference to the AOSS side-channel message RAM. memory-region: - minItems: 1 + maxItems: 1 description: Reference to the reserved-memory for the Hexagon core smd-edge: false @@ -52,6 +52,7 @@ properties: required: - compatible - reg + - memory-region allOf: - $ref: /schemas/remoteproc/qcom,pas-common.yaml# diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm8350-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm8350-pas.yaml index 9a04d192e7e4..53cea8e53a31 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm8350-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm8350-pas.yaml @@ -43,7 +43,7 @@ properties: smd-edge: false memory-region: - minItems: 1 + maxItems: 1 description: Reference to the reserved-memory for the Hexagon core firmware-name: @@ -53,6 +53,7 @@ properties: required: - compatible - reg + - memory-region allOf: - $ref: /schemas/remoteproc/qcom,pas-common.yaml# diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml index fe216aa531ed..58120829fb06 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml @@ -53,6 +53,7 @@ properties: required: - compatible - reg + - memory-region allOf: - $ref: /schemas/remoteproc/qcom,pas-common.yaml# diff --git a/Documentation/devicetree/bindings/thermal/loongson,ls2k-thermal.yaml b/Documentation/devicetree/bindings/thermal/loongson,ls2k-thermal.yaml new file mode 100644 index 000000000000..7538469997f9 --- /dev/null +++ b/Documentation/devicetree/bindings/thermal/loongson,ls2k-thermal.yaml @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/thermal/loongson,ls2k-thermal.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Thermal sensors on Loongson-2 SoCs + +maintainers: + - zhanghongchen <zhanghongchen@loongson.cn> + - Yinbo Zhu <zhuyinbo@loongson.cn> + +properties: + compatible: + oneOf: + - enum: + - loongson,ls2k1000-thermal + - items: + - enum: + - loongson,ls2k2000-thermal + - const: loongson,ls2k1000-thermal + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + +required: + - compatible + - reg + - interrupts + +additionalProperties: false + +examples: + - | + #include <dt-bindings/interrupt-controller/irq.h> + thermal: thermal-sensor@1fe01500 { + compatible = "loongson,ls2k1000-thermal"; + reg = <0x1fe01500 0x30>; + interrupt-parent = <&liointc0>; + interrupts = <7 IRQ_TYPE_LEVEL_LOW>; + }; diff --git a/Documentation/devicetree/bindings/timer/oxsemi,rps-timer.txt b/Documentation/devicetree/bindings/timer/oxsemi,rps-timer.txt deleted file mode 100644 index d191612539e8..000000000000 --- a/Documentation/devicetree/bindings/timer/oxsemi,rps-timer.txt +++ /dev/null @@ -1,17 +0,0 @@ -Oxford Semiconductor OXNAS SoCs Family RPS Timer -================================================ - -Required properties: -- compatible: Should be "oxsemi,ox810se-rps-timer" or "oxsemi,ox820-rps-timer" -- reg : Specifies base physical address and size of the registers. -- interrupts : The interrupts of the two timers -- clocks : The phandle of the timer clock source - -example: - -timer0: timer@200 { - compatible = "oxsemi,ox810se-rps-timer"; - reg = <0x200 0x40>; - clocks = <&rpsclk>; - interrupts = <4 5>; -}; diff --git a/Documentation/filesystems/proc.rst b/Documentation/filesystems/proc.rst index 1f9615553b82..2b59cff8be17 100644 --- a/Documentation/filesystems/proc.rst +++ b/Documentation/filesystems/proc.rst @@ -461,6 +461,7 @@ Memory Area, or VMA) there is a series of lines such as the following:: Private_Dirty: 0 kB Referenced: 892 kB Anonymous: 0 kB + KSM: 0 kB LazyFree: 0 kB AnonHugePages: 0 kB ShmemPmdMapped: 0 kB @@ -501,6 +502,9 @@ accessed. a mapping associated with a file may contain anonymous pages: when MAP_PRIVATE and a page is modified, the file page is replaced by a private anonymous copy. +"KSM" reports how many of the pages are KSM pages. Note that KSM-placed zeropages +are not included, only actual KSM pages. + "LazyFree" shows the amount of memory which is marked by madvise(MADV_FREE). The memory isn't freed immediately with madvise(). It's freed in memory pressure if the memory is clean. Please note that the printed value might diff --git a/Documentation/kbuild/kconfig.rst b/Documentation/kbuild/kconfig.rst index 3ee89dfe4697..c946eb44bd13 100644 --- a/Documentation/kbuild/kconfig.rst +++ b/Documentation/kbuild/kconfig.rst @@ -56,6 +56,15 @@ KCONFIG_OVERWRITECONFIG If you set KCONFIG_OVERWRITECONFIG in the environment, Kconfig will not break symlinks when .config is a symlink to somewhere else. +KCONFIG_WARN_UNKNOWN_SYMBOLS +---------------------------- +This environment variable makes Kconfig warn about all unrecognized +symbols in the config input. + +KCONFIG_WERROR +-------------- +If set, Kconfig treats warnings as errors. + `CONFIG_` --------- If you set `CONFIG_` in the environment, Kconfig will prefix all symbols @@ -212,6 +221,10 @@ Searching in menuconfig: first (and in alphabetical order), then come all other symbols, sorted in alphabetical order. + In this menu, pressing the key in the (#) prefix will jump + directly to that location. You will be returned to the current + search results after exiting this new menu. + ---------------------------------------------------------------------- User interface options for 'menuconfig' @@ -264,6 +277,10 @@ Searching in nconfig: F8 (SymSearch) searches the configuration symbols for the given string or regular expression (regex). + In the SymSearch, pressing the key in the (#) prefix will + jump directly to that location. You will be returned to the + current search results after exiting this new menu. + NCONFIG_MODE ------------ This mode shows all sub-menus in one large tree. diff --git a/Documentation/kbuild/llvm.rst b/Documentation/kbuild/llvm.rst index c3851fe1900d..b1d97fafddcf 100644 --- a/Documentation/kbuild/llvm.rst +++ b/Documentation/kbuild/llvm.rst @@ -25,50 +25,38 @@ objects <https://www.aosabook.org/en/llvm.html>`_. Clang is a front-end to LLVM that supports C and the GNU C extensions required by the kernel, and is pronounced "klang," not "see-lang." -Clang ------ - -The compiler used can be swapped out via ``CC=`` command line argument to ``make``. -``CC=`` should be set when selecting a config and during a build. :: - - make CC=clang defconfig - - make CC=clang +Building with LLVM +------------------ -Cross Compiling ---------------- +Invoke ``make`` via:: -A single Clang compiler binary will typically contain all supported backends, -which can help simplify cross compiling. :: - - make ARCH=arm64 CC=clang CROSS_COMPILE=aarch64-linux-gnu- + make LLVM=1 -``CROSS_COMPILE`` is not used to prefix the Clang compiler binary, instead -``CROSS_COMPILE`` is used to set a command line flag: ``--target=<triple>``. For -example: :: +to compile for the host target. For cross compiling:: - clang --target=aarch64-linux-gnu foo.c + make LLVM=1 ARCH=arm64 -LLVM Utilities --------------- +The LLVM= argument +------------------ -LLVM has substitutes for GNU binutils utilities. They can be enabled individually. -The full list of supported make variables:: +LLVM has substitutes for GNU binutils utilities. They can be enabled +individually. The full list of supported make variables:: make CC=clang LD=ld.lld AR=llvm-ar NM=llvm-nm STRIP=llvm-strip \ OBJCOPY=llvm-objcopy OBJDUMP=llvm-objdump READELF=llvm-readelf \ HOSTCC=clang HOSTCXX=clang++ HOSTAR=llvm-ar HOSTLD=ld.lld -To simplify the above command, Kbuild supports the ``LLVM`` variable:: - - make LLVM=1 +``LLVM=1`` expands to the above. If your LLVM tools are not available in your PATH, you can supply their location using the LLVM variable with a trailing slash:: make LLVM=/path/to/llvm/ -which will use ``/path/to/llvm/clang``, ``/path/to/llvm/ld.lld``, etc. +which will use ``/path/to/llvm/clang``, ``/path/to/llvm/ld.lld``, etc. The +following may also be used:: + + PATH=/path/to/llvm:$PATH make LLVM=1 If your LLVM tools have a version suffix and you want to test with that explicit version rather than the unsuffixed executables like ``LLVM=1``, you @@ -78,31 +66,72 @@ can pass the suffix using the ``LLVM`` variable:: which will use ``clang-14``, ``ld.lld-14``, etc. +To support combinations of out of tree paths with version suffixes, we +recommend:: + + PATH=/path/to/llvm/:$PATH make LLVM=-14 + ``LLVM=0`` is not the same as omitting ``LLVM`` altogether, it will behave like -``LLVM=1``. If you only wish to use certain LLVM utilities, use their respective -make variables. +``LLVM=1``. If you only wish to use certain LLVM utilities, use their +respective make variables. + +The same value used for ``LLVM=`` should be set for each invocation of ``make`` +if configuring and building via distinct commands. ``LLVM=`` should also be set +as an environment variable when running scripts that will eventually run +``make``. -The integrated assembler is enabled by default. You can pass ``LLVM_IAS=0`` to -disable it. +Cross Compiling +--------------- -Omitting CROSS_COMPILE +A single Clang compiler binary (and corresponding LLVM utilities) will +typically contain all supported back ends, which can help simplify cross +compiling especially when ``LLVM=1`` is used. If you use only LLVM tools, +``CROSS_COMPILE`` or target-triple-prefixes become unnecessary. Example:: + + make LLVM=1 ARCH=arm64 + +As an example of mixing LLVM and GNU utilities, for a target like ``ARCH=s390`` +which does not yet have ``ld.lld`` or ``llvm-objcopy`` support, you could +invoke ``make`` via:: + + make LLVM=1 ARCH=s390 LD=s390x-linux-gnu-ld.bfd \ + OBJCOPY=s390x-linux-gnu-objcopy + +This example will invoke ``s390x-linux-gnu-ld.bfd`` as the linker and +``s390x-linux-gnu-objcopy``, so ensure those are reachable in your ``$PATH``. + +``CROSS_COMPILE`` is not used to prefix the Clang compiler binary (or +corresponding LLVM utilities) as is the case for GNU utilities when ``LLVM=1`` +is not set. + +The LLVM_IAS= argument ---------------------- -As explained above, ``CROSS_COMPILE`` is used to set ``--target=<triple>``. +Clang can assemble assembler code. You can pass ``LLVM_IAS=0`` to disable this +behavior and have Clang invoke the corresponding non-integrated assembler +instead. Example:: + + make LLVM=1 LLVM_IAS=0 + +``CROSS_COMPILE`` is necessary when cross compiling and ``LLVM_IAS=0`` +is used in order to set ``--prefix=`` for the compiler to find the +corresponding non-integrated assembler (typically, you don't want to use the +system assembler when targeting another architecture). Example:: -If ``CROSS_COMPILE`` is not specified, the ``--target=<triple>`` is inferred -from ``ARCH``. + make LLVM=1 ARCH=arm LLVM_IAS=0 CROSS_COMPILE=arm-linux-gnueabi- -That means if you use only LLVM tools, ``CROSS_COMPILE`` becomes unnecessary. -For example, to cross-compile the arm64 kernel:: +Ccache +------ - make ARCH=arm64 LLVM=1 +``ccache`` can be used with ``clang`` to improve subsequent builds, (though +KBUILD_BUILD_TIMESTAMP_ should be set to a deterministic value between builds +in order to avoid 100% cache misses, see Reproducible_builds_ for more info): -If ``LLVM_IAS=0`` is specified, ``CROSS_COMPILE`` is also used to derive -``--prefix=<path>`` to search for the GNU assembler and linker. :: + KBUILD_BUILD_TIMESTAMP='' make LLVM=1 CC="ccache clang" - make ARCH=arm64 LLVM=1 LLVM_IAS=0 CROSS_COMPILE=aarch64-linux-gnu- +.. _KBUILD_BUILD_TIMESTAMP: kbuild.html#kbuild-build-timestamp +.. _Reproducible_builds: reproducible-builds.html#timestamps Supported Architectures ----------------------- @@ -135,14 +164,17 @@ yet. Bug reports are always welcome at the issue tracker below! * - hexagon - Maintained - ``LLVM=1`` + * - loongarch + - Maintained + - ``LLVM=1`` * - mips - Maintained - ``LLVM=1`` * - powerpc - Maintained - - ``CC=clang`` + - ``LLVM=1`` * - riscv - - Maintained + - Supported - ``LLVM=1`` * - s390 - Maintained @@ -171,7 +203,11 @@ Getting Help Getting LLVM ------------- -We provide prebuilt stable versions of LLVM on `kernel.org <https://kernel.org/pub/tools/llvm/>`_. +We provide prebuilt stable versions of LLVM on `kernel.org +<https://kernel.org/pub/tools/llvm/>`_. These have been optimized with profile +data for building Linux kernels, which should improve kernel build times +relative to other distributions of LLVM. + Below are links that may be useful for building LLVM from source or procuring it through a distribution's package manager. diff --git a/MAINTAINERS b/MAINTAINERS index 1cc0be8ea75a..0c098d5cbfc8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11382,6 +11382,7 @@ F: scripts/dummy-tools/ F: scripts/mk* F: scripts/mod/ F: scripts/package/ +F: usr/ KERNEL HARDENING (not covered by other areas) M: Kees Cook <keescook@chromium.org> @@ -12390,6 +12391,14 @@ S: Maintained F: Documentation/devicetree/bindings/pinctrl/loongson,ls2k-pinctrl.yaml F: drivers/pinctrl/pinctrl-loongson2.c +LOONGSON-2 SOC SERIES THERMAL DRIVER +M: zhanghongchen <zhanghongchen@loongson.cn> +M: Yinbo Zhu <zhuyinbo@loongson.cn> +L: linux-pm@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/thermal/loongson,ls2k-thermal.yaml +F: drivers/thermal/loongson2_thermal.c + LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI) M: Sathya Prakash <sathya.prakash@broadcom.com> M: Sreekanth Reddy <sreekanth.reddy@broadcom.com> @@ -13734,6 +13743,7 @@ F: include/linux/memory_hotplug.h F: include/linux/mm.h F: include/linux/mmzone.h F: include/linux/pagewalk.h +F: include/linux/rmap.h F: include/trace/events/ksm.h F: mm/ F: tools/mm/ @@ -17176,9 +17186,9 @@ F: kernel/sched/psi.c PRINTK M: Petr Mladek <pmladek@suse.com> -M: Sergey Senozhatsky <senozhatsky@chromium.org> R: Steven Rostedt <rostedt@goodmis.org> R: John Ogness <john.ogness@linutronix.de> +R: Sergey Senozhatsky <senozhatsky@chromium.org> S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/printk/linux.git F: include/linux/printk.h @@ -21796,6 +21806,20 @@ S: Maintained F: Documentation/hwmon/tps546d24.rst F: drivers/hwmon/pmbus/tps546d24.c +TQ SYSTEMS BOARD & DRIVER SUPPORT +L: linux@ew.tq-group.com +S: Supported +W: https://www.tq-group.com/en/products/tq-embedded/ +F: arch/arm/boot/dts/imx*mba*.dts* +F: arch/arm/boot/dts/imx*tqma*.dts* +F: arch/arm/boot/dts/mba*.dtsi +F: arch/arm64/boot/dts/freescale/imx*mba*.dts* +F: arch/arm64/boot/dts/freescale/imx*tqma*.dts* +F: arch/arm64/boot/dts/freescale/mba*.dtsi +F: drivers/gpio/gpio-tqmx86.c +F: drivers/mfd/tqmx86.c +F: drivers/watchdog/tqmx86_wdt.c + TRACING M: Steven Rostedt <rostedt@goodmis.org> M: Masami Hiramatsu <mhiramat@kernel.org> @@ -23072,9 +23096,9 @@ F: drivers/net/vrf.c VSPRINTF M: Petr Mladek <pmladek@suse.com> M: Steven Rostedt <rostedt@goodmis.org> -M: Sergey Senozhatsky <senozhatsky@chromium.org> R: Andy Shevchenko <andriy.shevchenko@linux.intel.com> R: Rasmus Villemoes <linux@rasmusvillemoes.dk> +R: Sergey Senozhatsky <senozhatsky@chromium.org> S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/printk/linux.git F: Documentation/core-api/printk-formats.rst @@ -280,8 +280,8 @@ no-dot-config-targets := $(clean-targets) \ # Installation targets should not require compiler. Unfortunately, vdso_install # is an exception where build artifacts may be updated. This must be fixed. no-compiler-targets := $(no-dot-config-targets) install dtbs_install \ - headers_install modules_install kernelrelease image_name -no-sync-config-targets := $(no-dot-config-targets) %install kernelrelease \ + headers_install modules_install modules_sign kernelrelease image_name +no-sync-config-targets := $(no-dot-config-targets) %install modules_sign kernelrelease \ image_name single-targets := %.a %.i %.ko %.lds %.ll %.lst %.mod %.o %.rsi %.s %.symtypes %/ @@ -510,7 +510,6 @@ LEX = flex YACC = bison AWK = awk INSTALLKERNEL := installkernel -DEPMOD = depmod PERL = perl PYTHON3 = python3 CHECK = sparse @@ -564,14 +563,6 @@ KBUILD_CFLAGS += -funsigned-char KBUILD_CFLAGS += -fno-common KBUILD_CFLAGS += -fno-PIE KBUILD_CFLAGS += -fno-strict-aliasing -KBUILD_CFLAGS += -Wall -KBUILD_CFLAGS += -Wundef -KBUILD_CFLAGS += -Werror=implicit-function-declaration -KBUILD_CFLAGS += -Werror=implicit-int -KBUILD_CFLAGS += -Werror=return-type -KBUILD_CFLAGS += -Werror=strict-prototypes -KBUILD_CFLAGS += -Wno-format-security -KBUILD_CFLAGS += -Wno-trigraphs KBUILD_CPPFLAGS := -D__KERNEL__ KBUILD_RUSTFLAGS := $(rust_common_flags) \ @@ -824,10 +815,6 @@ endif # may-sync-config endif # need-config KBUILD_CFLAGS += -fno-delete-null-pointer-checks -KBUILD_CFLAGS += $(call cc-disable-warning,frame-address,) -KBUILD_CFLAGS += $(call cc-disable-warning, format-truncation) -KBUILD_CFLAGS += $(call cc-disable-warning, format-overflow) -KBUILD_CFLAGS += $(call cc-disable-warning, address-of-packed-member) ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE KBUILD_CFLAGS += -O2 @@ -858,40 +845,15 @@ ifdef CONFIG_READABLE_ASM KBUILD_CFLAGS += -fno-reorder-blocks -fno-ipa-cp-clone -fno-partial-inlining endif -ifneq ($(CONFIG_FRAME_WARN),0) -KBUILD_CFLAGS += -Wframe-larger-than=$(CONFIG_FRAME_WARN) -endif - stackp-flags-y := -fno-stack-protector stackp-flags-$(CONFIG_STACKPROTECTOR) := -fstack-protector stackp-flags-$(CONFIG_STACKPROTECTOR_STRONG) := -fstack-protector-strong KBUILD_CFLAGS += $(stackp-flags-y) -KBUILD_CPPFLAGS-$(CONFIG_WERROR) += -Werror -KBUILD_CPPFLAGS += $(KBUILD_CPPFLAGS-y) -KBUILD_CFLAGS-$(CONFIG_CC_NO_ARRAY_BOUNDS) += -Wno-array-bounds - KBUILD_RUSTFLAGS-$(CONFIG_WERROR) += -Dwarnings KBUILD_RUSTFLAGS += $(KBUILD_RUSTFLAGS-y) -ifdef CONFIG_CC_IS_CLANG -# The kernel builds with '-std=gnu11' so use of GNU extensions is acceptable. -KBUILD_CFLAGS += -Wno-gnu -else - -# gcc inanely warns about local variables called 'main' -KBUILD_CFLAGS += -Wno-main -endif - -# These warnings generated too much noise in a regular build. -# Use make W=1 to enable them (see scripts/Makefile.extrawarn) -KBUILD_CFLAGS += $(call cc-disable-warning, unused-but-set-variable) -KBUILD_CFLAGS += $(call cc-disable-warning, unused-const-variable) - -# These result in bogus false positives -KBUILD_CFLAGS += $(call cc-disable-warning, dangling-pointer) - ifdef CONFIG_FRAME_POINTER KBUILD_CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls KBUILD_RUSTFLAGS += -Cforce-frame-pointers=y @@ -1026,51 +988,12 @@ endif # arch Makefile may override CC so keep this after arch Makefile is included NOSTDINC_FLAGS += -nostdinc -# Variable Length Arrays (VLAs) should not be used anywhere in the kernel -KBUILD_CFLAGS += -Wvla - -# disable pointer signed / unsigned warnings in gcc 4.0 -KBUILD_CFLAGS += -Wno-pointer-sign - -# In order to make sure new function cast mismatches are not introduced -# in the kernel (to avoid tripping CFI checking), the kernel should be -# globally built with -Wcast-function-type. -KBUILD_CFLAGS += $(call cc-option, -Wcast-function-type) - # To gain proper coverage for CONFIG_UBSAN_BOUNDS and CONFIG_FORTIFY_SOURCE, # the kernel uses only C99 flexible arrays for dynamically sized trailing # arrays. Enforce this for everything that may examine structure sizes and # perform bounds checking. KBUILD_CFLAGS += $(call cc-option, -fstrict-flex-arrays=3) -# disable stringop warnings in gcc 8+ -KBUILD_CFLAGS += $(call cc-disable-warning, stringop-truncation) - -# We'll want to enable this eventually, but it's not going away for 5.7 at least -KBUILD_CFLAGS += $(call cc-disable-warning, stringop-overflow) - -# Another good warning that we'll want to enable eventually -KBUILD_CFLAGS += $(call cc-disable-warning, restrict) - -# Enabled with W=2, disabled by default as noisy -ifdef CONFIG_CC_IS_GCC -KBUILD_CFLAGS += -Wno-maybe-uninitialized -endif - -# The allocators already balk at large sizes, so silence the compiler -# warnings for bounds checks involving those possible values. While -# -Wno-alloc-size-larger-than would normally be used here, earlier versions -# of gcc (<9.1) weirdly don't handle the option correctly when _other_ -# warnings are produced (?!). Using -Walloc-size-larger-than=SIZE_MAX -# doesn't work (as it is documented to), silently resolving to "0" prior to -# version 9.1 (and producing an error more recently). Numeric values larger -# than PTRDIFF_MAX also don't work prior to version 9.1, which are silently -# ignored, continuing to default to PTRDIFF_MAX. So, left with no other -# choice, we must perform a versioned check to disable this warning. -# https://lore.kernel.org/lkml/20210824115859.187f272f@canb.auug.org.au -KBUILD_CFLAGS-$(call gcc-min-version, 90100) += -Wno-alloc-size-larger-than -KBUILD_CFLAGS += $(KBUILD_CFLAGS-y) $(CONFIG_CC_IMPLICIT_FALLTHROUGH) - # disable invalid "can't wrap" optimizations for signed / pointers KBUILD_CFLAGS += -fno-strict-overflow @@ -1082,15 +1005,6 @@ ifdef CONFIG_CC_IS_GCC KBUILD_CFLAGS += -fconserve-stack endif -# Prohibit date/time macros, which would make the build non-deterministic -KBUILD_CFLAGS += -Werror=date-time - -# enforce correct pointer usage -KBUILD_CFLAGS += $(call cc-option,-Werror=incompatible-pointer-types) - -# Require designated initializers for all marked structures -KBUILD_CFLAGS += $(call cc-option,-Werror=designated-init) - # change __FILE__ to the relative path from the srctree KBUILD_CPPFLAGS += $(call cc-option,-fmacro-prefix-map=$(srctree)/=) @@ -1548,44 +1462,8 @@ modules: modules_prepare modules_prepare: prepare $(Q)$(MAKE) $(build)=scripts scripts/module.lds -export modules_sign_only := - -ifeq ($(CONFIG_MODULE_SIG),y) -PHONY += modules_sign -modules_sign: modules_install - @: - -# modules_sign is a subset of modules_install. -# 'make modules_install modules_sign' is equivalent to 'make modules_install'. -ifeq ($(filter modules_install,$(MAKECMDGOALS)),) -modules_sign_only := y -endif -endif - endif # CONFIG_MODULES -modinst_pre := -ifneq ($(filter modules_install,$(MAKECMDGOALS)),) -modinst_pre := __modinst_pre -endif - -modules_install: $(modinst_pre) -PHONY += __modinst_pre -__modinst_pre: - @rm -rf $(MODLIB)/kernel - @rm -f $(MODLIB)/source - @mkdir -p $(MODLIB) -ifdef CONFIG_MODULES - @ln -s $(abspath $(srctree)) $(MODLIB)/source - @if [ ! $(objtree) -ef $(MODLIB)/build ]; then \ - rm -f $(MODLIB)/build ; \ - ln -s $(CURDIR) $(MODLIB)/build ; \ - fi - @sed 's:^\(.*\)\.o$$:kernel/\1.ko:' modules.order > $(MODLIB)/modules.order -endif - @cp -f modules.builtin $(MODLIB)/ - @cp -f $(objtree)/modules.builtin.modinfo $(MODLIB)/ - ### # Cleaning is done on three levels. # make clean Delete most generated files @@ -1594,7 +1472,7 @@ endif # make distclean Remove editor backup files, patch leftover files and the like # Directories & files removed with 'make clean' -CLEAN_FILES += include/ksym vmlinux.symvers modules-only.symvers \ +CLEAN_FILES += vmlinux.symvers modules-only.symvers \ modules.builtin modules.builtin.modinfo modules.nsdeps \ compile_commands.json .thinlto-cache rust/test rust/doc \ rust-project.json .vmlinux.objs .vmlinux.export.c @@ -1608,7 +1486,7 @@ MRPROPER_FILES += include/config include/generated \ certs/signing_key.pem \ certs/x509.genkey \ vmlinux-gdb.py \ - *.spec rpmbuild \ + kernel.spec rpmbuild \ rust/libmacros.so # clean - Delete most, but leave enough to build external modules @@ -1675,7 +1553,6 @@ help: @echo ' mrproper - Remove all generated files + config + various backup files' @echo ' distclean - mrproper + remove editor backup and patch files' @echo '' - @echo 'Configuration targets:' @$(MAKE) -f $(srctree)/scripts/kconfig/Makefile help @echo '' @echo 'Other generic targets:' @@ -1923,19 +1800,39 @@ help: @echo ' rust-analyzer - generate rust-project.json rust-analyzer support file' @echo '' +ifndef CONFIG_MODULES +modules modules_install: __external_modules_error __external_modules_error: @echo >&2 '***' @echo >&2 '*** The present kernel disabled CONFIG_MODULES.' @echo >&2 '*** You cannot build or install external modules.' @echo >&2 '***' @false +endif endif # KBUILD_EXTMOD # --------------------------------------------------------------------------- # Modules -PHONY += modules modules_install modules_prepare +PHONY += modules modules_install modules_sign modules_prepare + +modules_install: + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modinst \ + sign-only=$(if $(filter modules_install,$(MAKECMDGOALS)),,y) + +ifeq ($(CONFIG_MODULE_SIG),y) +# modules_sign is a subset of modules_install. +# 'make modules_install modules_sign' is equivalent to 'make modules_install'. +modules_sign: modules_install + @: +else +modules_sign: + @echo >&2 '***' + @echo >&2 '*** CONFIG_MODULE_SIG is disabled. You cannot sign modules.' + @echo >&2 '***' + @false +endif ifdef CONFIG_MODULES @@ -1953,22 +1850,9 @@ PHONY += modules_check modules_check: $(MODORDER) $(Q)$(CONFIG_SHELL) $(srctree)/scripts/modules-check.sh $< -quiet_cmd_depmod = DEPMOD $(MODLIB) - cmd_depmod = $(CONFIG_SHELL) $(srctree)/scripts/depmod.sh $(DEPMOD) \ - $(KERNELRELEASE) - -modules_install: - $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modinst - $(call cmd,depmod) - else # CONFIG_MODULES -# Modules not configured -# --------------------------------------------------------------------------- - -PHONY += __external_modules_error - -modules modules_install: __external_modules_error +modules: @: KBUILD_MODULES := @@ -2147,6 +2031,10 @@ kernelversion: image_name: @echo $(KBUILD_IMAGE) +PHONY += run-command +run-command: + $(Q)$(KBUILD_RUN_COMMAND) + quiet_cmd_rmfiles = $(if $(wildcard $(rm-files)),CLEAN $(wildcard $(rm-files))) cmd_rmfiles = rm -rf $(rm-files) diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild index dd31e97edae8..396caece6d6d 100644 --- a/arch/alpha/include/asm/Kbuild +++ b/arch/alpha/include/asm/Kbuild @@ -3,6 +3,5 @@ generated-y += syscall_table.h generic-y += agp.h generic-y += asm-offsets.h -generic-y += export.h generic-y += kvm_para.h generic-y += mcs_spinlock.h diff --git a/arch/alpha/lib/callback_srm.S b/arch/alpha/lib/callback_srm.S index b13c4a231f1b..36b63f295170 100644 --- a/arch/alpha/lib/callback_srm.S +++ b/arch/alpha/lib/callback_srm.S @@ -3,8 +3,8 @@ * arch/alpha/lib/callback_srm.S */ +#include <linux/export.h> #include <asm/console.h> -#include <asm/export.h> .text #define HWRPB_CRB_OFFSET 0xc0 diff --git a/arch/alpha/lib/clear_page.S b/arch/alpha/lib/clear_page.S index ce02de7b0493..af70ee309a33 100644 --- a/arch/alpha/lib/clear_page.S +++ b/arch/alpha/lib/clear_page.S @@ -4,7 +4,7 @@ * * Zero an entire page. */ -#include <asm/export.h> +#include <linux/export.h> .text .align 4 .global clear_page diff --git a/arch/alpha/lib/clear_user.S b/arch/alpha/lib/clear_user.S index db6c6ca45896..848eb60a0010 100644 --- a/arch/alpha/lib/clear_user.S +++ b/arch/alpha/lib/clear_user.S @@ -10,7 +10,7 @@ * a successful copy). There is also some rather minor exception setup * stuff. */ -#include <asm/export.h> +#include <linux/export.h> /* Allow an exception for an insn; exit if we get one. */ #define EX(x,y...) \ diff --git a/arch/alpha/lib/copy_page.S b/arch/alpha/lib/copy_page.S index 5439a30c77d0..1c444fdad9a5 100644 --- a/arch/alpha/lib/copy_page.S +++ b/arch/alpha/lib/copy_page.S @@ -4,7 +4,7 @@ * * Copy an entire page. */ -#include <asm/export.h> +#include <linux/export.h> .text .align 4 .global copy_page diff --git a/arch/alpha/lib/copy_user.S b/arch/alpha/lib/copy_user.S index 32ab0344b185..ef18faafcad6 100644 --- a/arch/alpha/lib/copy_user.S +++ b/arch/alpha/lib/copy_user.S @@ -12,7 +12,7 @@ * exception setup stuff.. */ -#include <asm/export.h> +#include <linux/export.h> /* Allow an exception for an insn; exit if we get one. */ #define EXI(x,y...) \ diff --git a/arch/alpha/lib/csum_ipv6_magic.S b/arch/alpha/lib/csum_ipv6_magic.S index c7b213ab01ab..273c426c3859 100644 --- a/arch/alpha/lib/csum_ipv6_magic.S +++ b/arch/alpha/lib/csum_ipv6_magic.S @@ -13,7 +13,7 @@ * added by Ivan Kokshaysky <ink@jurassic.park.msu.ru> */ -#include <asm/export.h> +#include <linux/export.h> .globl csum_ipv6_magic .align 4 .ent csum_ipv6_magic diff --git a/arch/alpha/lib/divide.S b/arch/alpha/lib/divide.S index 2b60eb45e50b..db01840d76ec 100644 --- a/arch/alpha/lib/divide.S +++ b/arch/alpha/lib/divide.S @@ -46,7 +46,7 @@ * $28 - compare status */ -#include <asm/export.h> +#include <linux/export.h> #define halt .long 0 /* diff --git a/arch/alpha/lib/ev6-clear_page.S b/arch/alpha/lib/ev6-clear_page.S index 325864c81586..a534d9ff7161 100644 --- a/arch/alpha/lib/ev6-clear_page.S +++ b/arch/alpha/lib/ev6-clear_page.S @@ -4,7 +4,7 @@ * * Zero an entire page. */ -#include <asm/export.h> +#include <linux/export.h> .text .align 4 .global clear_page diff --git a/arch/alpha/lib/ev6-clear_user.S b/arch/alpha/lib/ev6-clear_user.S index 7e644f83cdf2..af776cc45f91 100644 --- a/arch/alpha/lib/ev6-clear_user.S +++ b/arch/alpha/lib/ev6-clear_user.S @@ -29,7 +29,7 @@ * want to leave a hole (and we also want to avoid repeating lots of work) */ -#include <asm/export.h> +#include <linux/export.h> /* Allow an exception for an insn; exit if we get one. */ #define EX(x,y...) \ 99: x,##y; \ diff --git a/arch/alpha/lib/ev6-copy_page.S b/arch/alpha/lib/ev6-copy_page.S index fd7212c8dcf1..36be5113b7b7 100644 --- a/arch/alpha/lib/ev6-copy_page.S +++ b/arch/alpha/lib/ev6-copy_page.S @@ -57,7 +57,7 @@ destination pages are in the dcache, but it is my guess that this is less important than the dcache miss case. */ -#include <asm/export.h> +#include <linux/export.h> .text .align 4 .global copy_page diff --git a/arch/alpha/lib/ev6-copy_user.S b/arch/alpha/lib/ev6-copy_user.S index f3e433754397..b9b19710c364 100644 --- a/arch/alpha/lib/ev6-copy_user.S +++ b/arch/alpha/lib/ev6-copy_user.S @@ -23,7 +23,7 @@ * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1 */ -#include <asm/export.h> +#include <linux/export.h> /* Allow an exception for an insn; exit if we get one. */ #define EXI(x,y...) \ 99: x,##y; \ diff --git a/arch/alpha/lib/ev6-csum_ipv6_magic.S b/arch/alpha/lib/ev6-csum_ipv6_magic.S index 9a73f90700a1..2ee548be98e3 100644 --- a/arch/alpha/lib/ev6-csum_ipv6_magic.S +++ b/arch/alpha/lib/ev6-csum_ipv6_magic.S @@ -53,7 +53,7 @@ * may cause additional delay in rare cases (load-load replay traps). */ -#include <asm/export.h> +#include <linux/export.h> .globl csum_ipv6_magic .align 4 .ent csum_ipv6_magic diff --git a/arch/alpha/lib/ev6-divide.S b/arch/alpha/lib/ev6-divide.S index 137ff1a07356..b73a6d26362e 100644 --- a/arch/alpha/lib/ev6-divide.S +++ b/arch/alpha/lib/ev6-divide.S @@ -56,7 +56,7 @@ * Try not to change the actual algorithm if possible for consistency. */ -#include <asm/export.h> +#include <linux/export.h> #define halt .long 0 /* diff --git a/arch/alpha/lib/ev6-memchr.S b/arch/alpha/lib/ev6-memchr.S index 56bf9e14eeee..f75ba43e61e3 100644 --- a/arch/alpha/lib/ev6-memchr.S +++ b/arch/alpha/lib/ev6-memchr.S @@ -28,7 +28,7 @@ * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1 * Try not to change the actual algorithm if possible for consistency. */ -#include <asm/export.h> +#include <linux/export.h> .set noreorder .set noat diff --git a/arch/alpha/lib/ev6-memcpy.S b/arch/alpha/lib/ev6-memcpy.S index ffbd056b6eb2..3ef43c26c8af 100644 --- a/arch/alpha/lib/ev6-memcpy.S +++ b/arch/alpha/lib/ev6-memcpy.S @@ -20,7 +20,7 @@ * Temp usage notes: * $1,$2, - scratch */ -#include <asm/export.h> +#include <linux/export.h> .set noreorder .set noat diff --git a/arch/alpha/lib/ev6-memset.S b/arch/alpha/lib/ev6-memset.S index 1cfcfbbea6f0..89d7809da4cc 100644 --- a/arch/alpha/lib/ev6-memset.S +++ b/arch/alpha/lib/ev6-memset.S @@ -27,7 +27,7 @@ * as fixes will need to be made in multiple places. The performance gain * is worth it. */ -#include <asm/export.h> +#include <linux/export.h> .set noat .set noreorder .text diff --git a/arch/alpha/lib/ev67-strcat.S b/arch/alpha/lib/ev67-strcat.S index ec3096a9e8d4..f8c7305b11d6 100644 --- a/arch/alpha/lib/ev67-strcat.S +++ b/arch/alpha/lib/ev67-strcat.S @@ -20,7 +20,7 @@ * string once. */ -#include <asm/export.h> +#include <linux/export.h> .text .align 4 diff --git a/arch/alpha/lib/ev67-strchr.S b/arch/alpha/lib/ev67-strchr.S index fbf89e0b6dc3..97a7cb475309 100644 --- a/arch/alpha/lib/ev67-strchr.S +++ b/arch/alpha/lib/ev67-strchr.S @@ -16,7 +16,7 @@ * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1 * Try not to change the actual algorithm if possible for consistency. */ -#include <asm/export.h> +#include <linux/export.h> #include <asm/regdef.h> .set noreorder diff --git a/arch/alpha/lib/ev67-strlen.S b/arch/alpha/lib/ev67-strlen.S index b73106ffbbc7..3d9078807ab4 100644 --- a/arch/alpha/lib/ev67-strlen.S +++ b/arch/alpha/lib/ev67-strlen.S @@ -18,7 +18,7 @@ * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1 * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1 */ -#include <asm/export.h> +#include <linux/export.h> .set noreorder .set noat diff --git a/arch/alpha/lib/ev67-strncat.S b/arch/alpha/lib/ev67-strncat.S index ceb0ca528789..8f313233e3a7 100644 --- a/arch/alpha/lib/ev67-strncat.S +++ b/arch/alpha/lib/ev67-strncat.S @@ -21,7 +21,7 @@ * Try not to change the actual algorithm if possible for consistency. */ -#include <asm/export.h> +#include <linux/export.h> .text .align 4 diff --git a/arch/alpha/lib/ev67-strrchr.S b/arch/alpha/lib/ev67-strrchr.S index 7f80e398530f..ae7355f9ec56 100644 --- a/arch/alpha/lib/ev67-strrchr.S +++ b/arch/alpha/lib/ev67-strrchr.S @@ -19,7 +19,7 @@ * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1 */ -#include <asm/export.h> +#include <linux/export.h> #include <asm/regdef.h> .set noreorder diff --git a/arch/alpha/lib/memchr.S b/arch/alpha/lib/memchr.S index c13d3eca2e05..45366e32feee 100644 --- a/arch/alpha/lib/memchr.S +++ b/arch/alpha/lib/memchr.S @@ -31,7 +31,7 @@ For correctness consider that: - only minimum number of quadwords may be accessed - the third argument is an unsigned long */ -#include <asm/export.h> +#include <linux/export.h> .set noreorder .set noat diff --git a/arch/alpha/lib/memmove.S b/arch/alpha/lib/memmove.S index 42d1922d0edf..3a27689e3390 100644 --- a/arch/alpha/lib/memmove.S +++ b/arch/alpha/lib/memmove.S @@ -7,7 +7,7 @@ * This is hand-massaged output from the original memcpy.c. We defer to * memcpy whenever possible; the backwards copy loops are not unrolled. */ -#include <asm/export.h> +#include <linux/export.h> .set noat .set noreorder .text diff --git a/arch/alpha/lib/memset.S b/arch/alpha/lib/memset.S index 00393e30df25..9075d6918346 100644 --- a/arch/alpha/lib/memset.S +++ b/arch/alpha/lib/memset.S @@ -14,7 +14,7 @@ * The scheduling comments are according to the EV5 documentation (and done by * hand, so they might well be incorrect, please do tell me about it..) */ -#include <asm/export.h> +#include <linux/export.h> .set noat .set noreorder .text diff --git a/arch/alpha/lib/strcat.S b/arch/alpha/lib/strcat.S index 055877dccd27..62b90ebbcf44 100644 --- a/arch/alpha/lib/strcat.S +++ b/arch/alpha/lib/strcat.S @@ -5,7 +5,7 @@ * * Append a null-terminated string from SRC to DST. */ -#include <asm/export.h> +#include <linux/export.h> .text diff --git a/arch/alpha/lib/strchr.S b/arch/alpha/lib/strchr.S index 17871dd00280..68c54ff50dfe 100644 --- a/arch/alpha/lib/strchr.S +++ b/arch/alpha/lib/strchr.S @@ -6,7 +6,7 @@ * Return the address of a given character within a null-terminated * string, or null if it is not found. */ -#include <asm/export.h> +#include <linux/export.h> #include <asm/regdef.h> .set noreorder diff --git a/arch/alpha/lib/strcpy.S b/arch/alpha/lib/strcpy.S index cb74ad23a90d..d8773ba77525 100644 --- a/arch/alpha/lib/strcpy.S +++ b/arch/alpha/lib/strcpy.S @@ -6,7 +6,7 @@ * Copy a null-terminated string from SRC to DST. Return a pointer * to the null-terminator in the source. */ -#include <asm/export.h> +#include <linux/export.h> .text .align 3 diff --git a/arch/alpha/lib/strlen.S b/arch/alpha/lib/strlen.S index dd882fe4d7e3..4fc6a6ff24cd 100644 --- a/arch/alpha/lib/strlen.S +++ b/arch/alpha/lib/strlen.S @@ -12,7 +12,7 @@ * do this instead of the 9 instructions that * binary search needs). */ -#include <asm/export.h> +#include <linux/export.h> .set noreorder .set noat diff --git a/arch/alpha/lib/strncat.S b/arch/alpha/lib/strncat.S index 522fee3e26ac..a913a7c84a39 100644 --- a/arch/alpha/lib/strncat.S +++ b/arch/alpha/lib/strncat.S @@ -10,7 +10,7 @@ * past count, whereas libc may write to count+1. This follows the generic * implementation in lib/string.c and is, IMHO, more sensible. */ -#include <asm/export.h> +#include <linux/export.h> .text .align 3 diff --git a/arch/alpha/lib/strncpy.S b/arch/alpha/lib/strncpy.S index cc57fad8b7ca..cb90cf022df3 100644 --- a/arch/alpha/lib/strncpy.S +++ b/arch/alpha/lib/strncpy.S @@ -11,7 +11,7 @@ * version has cropped that bit o' nastiness as well as assuming that * __stxncpy is in range of a branch. */ -#include <asm/export.h> +#include <linux/export.h> .set noat .set noreorder diff --git a/arch/alpha/lib/strrchr.S b/arch/alpha/lib/strrchr.S index 7650ba99b7e2..dd8e073b6cf2 100644 --- a/arch/alpha/lib/strrchr.S +++ b/arch/alpha/lib/strrchr.S @@ -6,7 +6,7 @@ * Return the address of the last occurrence of a given character * within a null-terminated string, or null if it is not found. */ -#include <asm/export.h> +#include <linux/export.h> #include <asm/regdef.h> .set noreorder diff --git a/arch/alpha/lib/udiv-qrnnd.S b/arch/alpha/lib/udiv-qrnnd.S index b887aa5428e5..96f05918bffe 100644 --- a/arch/alpha/lib/udiv-qrnnd.S +++ b/arch/alpha/lib/udiv-qrnnd.S @@ -25,7 +25,7 @@ # along with GCC; see the file COPYING. If not, write to the # Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, # MA 02111-1307, USA. -#include <asm/export.h> +#include <linux/export.h> .set noreorder .set noat diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index 6f4995ad9873..3162db540ee9 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -27,6 +27,8 @@ config ARC select GENERIC_SCHED_CLOCK select GENERIC_SMP_IDLE_THREAD select GENERIC_IOREMAP + select GENERIC_STRNCPY_FROM_USER if MMU + select GENERIC_STRNLEN_USER if MMU select HAVE_ARCH_KGDB select HAVE_ARCH_TRACEHOOK select HAVE_ARCH_TRANSPARENT_HUGEPAGE if ARC_MMU_V4 @@ -491,11 +493,11 @@ config ARC_KVADDR_SIZE kernel-user gutter) config ARC_CURR_IN_REG - bool "Dedicate Register r25 for current_task pointer" + bool "cache current task pointer in gp" default y help - This reserved Register R25 to point to Current Task in - kernel mode. This saves memory access for each such access + This reserves gp register to point to Current Task in + kernel mode eliding memory access for each access config ARC_EMUL_UNALIGNED diff --git a/arch/arc/Makefile b/arch/arc/Makefile index 329400a1c355..2390dd042e36 100644 --- a/arch/arc/Makefile +++ b/arch/arc/Makefile @@ -28,14 +28,14 @@ cflags-y += $(tune-mcpu-def-y) endif endif - ifdef CONFIG_ARC_CURR_IN_REG # For a global register definition, make sure it gets passed to every file # We had a customer reported bug where some code built in kernel was NOT using -# any kernel headers, and missing the r25 global register +# any kernel headers, and missing the global register # Can't do unconditionally because of recursive include issues # due to <linux/thread_info.h> LINUXINCLUDE += -include $(srctree)/arch/arc/include/asm/current.h +cflags-y += -ffixed-gp endif cflags-y += -fsection-anchors @@ -67,7 +67,7 @@ cflags-$(CONFIG_ARC_DW2_UNWIND) += -fasynchronous-unwind-tables $(cfi) # small data is default for elf32 tool-chain. If not usable, disable it # This also allows repurposing GP as scratch reg to gcc reg allocator disable_small_data := y -cflags-$(disable_small_data) += -mno-sdata -fcall-used-gp +cflags-$(disable_small_data) += -mno-sdata cflags-$(CONFIG_CPU_BIG_ENDIAN) += -mbig-endian ldflags-$(CONFIG_CPU_BIG_ENDIAN) += -EB diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h index 2162023195c5..4b13f60fe7ca 100644 --- a/arch/arc/include/asm/arcregs.h +++ b/arch/arc/include/asm/arcregs.h @@ -23,7 +23,7 @@ #define ARC_REG_ICCM_BUILD 0x78 /* ICCM size (common) */ #define ARC_REG_XY_MEM_BCR 0x79 #define ARC_REG_MAC_BCR 0x7a -#define ARC_REG_MUL_BCR 0x7b +#define ARC_REG_MPY_BCR 0x7b #define ARC_REG_SWAP_BCR 0x7c #define ARC_REG_NORM_BCR 0x7d #define ARC_REG_MIXMAX_BCR 0x7e @@ -177,7 +177,7 @@ struct bcr_isa_arcv2 { #endif }; -struct bcr_uarch_build_arcv2 { +struct bcr_uarch_build { #ifdef CONFIG_CPU_BIG_ENDIAN unsigned int pad:8, prod:8, maj:8, min:8; #else @@ -185,6 +185,59 @@ struct bcr_uarch_build_arcv2 { #endif }; +struct bcr_mmu_3 { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned int ver:8, ways:4, sets:4, res:3, sasid:1, pg_sz:4, + u_itlb:4, u_dtlb:4; +#else + unsigned int u_dtlb:4, u_itlb:4, pg_sz:4, sasid:1, res:3, sets:4, + ways:4, ver:8; +#endif +}; + +struct bcr_mmu_4 { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned int ver:8, sasid:1, sz1:4, sz0:4, res:2, pae:1, + n_ways:2, n_entry:2, n_super:2, u_itlb:3, u_dtlb:3; +#else + /* DTLB ITLB JES JE JA */ + unsigned int u_dtlb:3, u_itlb:3, n_super:2, n_entry:2, n_ways:2, + pae:1, res:2, sz0:4, sz1:4, sasid:1, ver:8; +#endif +}; + +struct bcr_cache { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned int pad:12, line_len:4, sz:4, config:4, ver:8; +#else + unsigned int ver:8, config:4, sz:4, line_len:4, pad:12; +#endif +}; + +struct bcr_slc_cfg { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned int pad:24, way:2, lsz:2, sz:4; +#else + unsigned int sz:4, lsz:2, way:2, pad:24; +#endif +}; + +struct bcr_clust_cfg { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned int pad:7, c:1, num_entries:8, num_cores:8, ver:8; +#else + unsigned int ver:8, num_cores:8, num_entries:8, c:1, pad:7; +#endif +}; + +struct bcr_volatile { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned int start:4, limit:4, pad:22, order:1, disable:1; +#else + unsigned int disable:1, order:1, pad:22, limit:4, start:4; +#endif +}; + struct bcr_mpy { #ifdef CONFIG_CPU_BIG_ENDIAN unsigned int pad:8, x1616:8, dsp:4, cycles:2, type:2, ver:8; @@ -302,48 +355,6 @@ struct bcr_generic { #endif }; -/* - ******************************************************************* - * Generic structures to hold build configuration used at runtime - */ - -struct cpuinfo_arc_mmu { - unsigned int ver:4, pg_sz_k:8, s_pg_sz_m:8, pad:10, sasid:1, pae:1; - unsigned int sets:12, ways:4, u_dtlb:8, u_itlb:8; -}; - -struct cpuinfo_arc_cache { - unsigned int sz_k:14, line_len:8, assoc:4, alias:1, vipt:1, pad:4; -}; - -struct cpuinfo_arc_bpu { - unsigned int ver, full, num_cache, num_pred, ret_stk; -}; - -struct cpuinfo_arc_ccm { - unsigned int base_addr, sz; -}; - -struct cpuinfo_arc { - struct cpuinfo_arc_cache icache, dcache, slc; - struct cpuinfo_arc_mmu mmu; - struct cpuinfo_arc_bpu bpu; - struct bcr_identity core; - struct bcr_isa_arcv2 isa; - const char *release, *name; - unsigned int vec_base; - struct cpuinfo_arc_ccm iccm, dccm; - struct { - unsigned int swap:1, norm:1, minmax:1, barrel:1, crc:1, swape:1, pad1:2, - fpu_sp:1, fpu_dp:1, dual:1, dual_enb:1, pad2:4, - ap_num:4, ap_full:1, smart:1, rtt:1, pad3:1, - timer0:1, timer1:1, rtc:1, gfrc:1, pad4:4; - } extn; - struct bcr_mpy extn_mpy; -}; - -extern struct cpuinfo_arc cpuinfo_arc700[]; - static inline int is_isa_arcv2(void) { return IS_ENABLED(CONFIG_ISA_ARCV2); diff --git a/arch/arc/include/asm/atomic-llsc.h b/arch/arc/include/asm/atomic-llsc.h index 1b0ffaeee16d..5258cb81a16b 100644 --- a/arch/arc/include/asm/atomic-llsc.h +++ b/arch/arc/include/asm/atomic-llsc.h @@ -18,7 +18,7 @@ static inline void arch_atomic_##op(int i, atomic_t *v) \ : [val] "=&r" (val) /* Early clobber to prevent reg reuse */ \ : [ctr] "r" (&v->counter), /* Not "m": llock only supports reg direct addr mode */ \ [i] "ir" (i) \ - : "cc"); \ + : "cc", "memory"); \ } \ #define ATOMIC_OP_RETURN(op, asm_op) \ @@ -34,7 +34,7 @@ static inline int arch_atomic_##op##_return_relaxed(int i, atomic_t *v) \ : [val] "=&r" (val) \ : [ctr] "r" (&v->counter), \ [i] "ir" (i) \ - : "cc"); \ + : "cc", "memory"); \ \ return val; \ } @@ -56,7 +56,7 @@ static inline int arch_atomic_fetch_##op##_relaxed(int i, atomic_t *v) \ [orig] "=&r" (orig) \ : [ctr] "r" (&v->counter), \ [i] "ir" (i) \ - : "cc"); \ + : "cc", "memory"); \ \ return orig; \ } diff --git a/arch/arc/include/asm/atomic64-arcv2.h b/arch/arc/include/asm/atomic64-arcv2.h index 6b6db981967a..9b5791b85471 100644 --- a/arch/arc/include/asm/atomic64-arcv2.h +++ b/arch/arc/include/asm/atomic64-arcv2.h @@ -60,7 +60,7 @@ static inline void arch_atomic64_##op(s64 a, atomic64_t *v) \ " bnz 1b \n" \ : "=&r"(val) \ : "r"(&v->counter), "ir"(a) \ - : "cc"); \ + : "cc", "memory"); \ } \ #define ATOMIC64_OP_RETURN(op, op1, op2) \ @@ -77,7 +77,7 @@ static inline s64 arch_atomic64_##op##_return_relaxed(s64 a, atomic64_t *v) \ " bnz 1b \n" \ : [val] "=&r"(val) \ : "r"(&v->counter), "ir"(a) \ - : "cc"); /* memory clobber comes from smp_mb() */ \ + : "cc", "memory"); \ \ return val; \ } @@ -99,7 +99,7 @@ static inline s64 arch_atomic64_fetch_##op##_relaxed(s64 a, atomic64_t *v) \ " bnz 1b \n" \ : "=&r"(orig), "=&r"(val) \ : "r"(&v->counter), "ir"(a) \ - : "cc"); /* memory clobber comes from smp_mb() */ \ + : "cc", "memory"); \ \ return orig; \ } diff --git a/arch/arc/include/asm/current.h b/arch/arc/include/asm/current.h index 9b9bdd3e6538..06be89f6f2f0 100644 --- a/arch/arc/include/asm/current.h +++ b/arch/arc/include/asm/current.h @@ -13,7 +13,7 @@ #ifdef CONFIG_ARC_CURR_IN_REG -register struct task_struct *curr_arc asm("r25"); +register struct task_struct *curr_arc asm("gp"); #define current (curr_arc) #else diff --git a/arch/arc/include/asm/dwarf.h b/arch/arc/include/asm/dwarf.h index 5f4de05bd4ee..a0d5ebe1bc3f 100644 --- a/arch/arc/include/asm/dwarf.h +++ b/arch/arc/include/asm/dwarf.h @@ -10,23 +10,31 @@ #ifdef ARC_DW2_UNWIND_AS_CFI -#define CFI_STARTPROC .cfi_startproc -#define CFI_ENDPROC .cfi_endproc -#define CFI_DEF_CFA .cfi_def_cfa -#define CFI_REGISTER .cfi_register -#define CFI_REL_OFFSET .cfi_rel_offset -#define CFI_UNDEFINED .cfi_undefined +#define CFI_STARTPROC .cfi_startproc +#define CFI_ENDPROC .cfi_endproc +#define CFI_DEF_CFA .cfi_def_cfa +#define CFI_DEF_CFA_OFFSET .cfi_def_cfa_offset +#define CFI_DEF_CFA_REGISTER .cfi_def_cfa_register +#define CFI_OFFSET .cfi_offset +#define CFI_REL_OFFSET .cfi_rel_offset +#define CFI_REGISTER .cfi_register +#define CFI_RESTORE .cfi_restore +#define CFI_UNDEFINED .cfi_undefined #else #define CFI_IGNORE # -#define CFI_STARTPROC CFI_IGNORE -#define CFI_ENDPROC CFI_IGNORE -#define CFI_DEF_CFA CFI_IGNORE -#define CFI_REGISTER CFI_IGNORE -#define CFI_REL_OFFSET CFI_IGNORE -#define CFI_UNDEFINED CFI_IGNORE +#define CFI_STARTPROC CFI_IGNORE +#define CFI_ENDPROC CFI_IGNORE +#define CFI_DEF_CFA CFI_IGNORE +#define CFI_DEF_CFA_OFFSET CFI_IGNORE +#define CFI_DEF_CFA_REGISTER CFI_IGNORE +#define CFI_OFFSET CFI_IGNORE +#define CFI_REL_OFFSET CFI_IGNORE +#define CFI_REGISTER CFI_IGNORE +#define CFI_RESTORE CFI_IGNORE +#define CFI_UNDEFINED CFI_IGNORE #endif /* !ARC_DW2_UNWIND_AS_CFI */ diff --git a/arch/arc/include/asm/entry-arcv2.h b/arch/arc/include/asm/entry-arcv2.h index 0ff4c0610561..4d13320e0c1b 100644 --- a/arch/arc/include/asm/entry-arcv2.h +++ b/arch/arc/include/asm/entry-arcv2.h @@ -18,7 +18,6 @@ * | orig_r0 | * | event/ECR | * | bta | - * | user_r25 | * | gp | * | fp | * | sp | @@ -49,14 +48,18 @@ /*------------------------------------------------------------------------*/ .macro INTERRUPT_PROLOGUE - ; (A) Before jumping to Interrupt Vector, hardware micro-ops did following: + ; Before jumping to Interrupt Vector, hardware micro-ops did following: ; 1. SP auto-switched to kernel mode stack ; 2. STATUS32.Z flag set if in U mode at time of interrupt (U:1,K:0) ; 3. Auto save: (mandatory) Push PC and STAT32 on stack ; hardware does even if CONFIG_ARC_IRQ_NO_AUTOSAVE - ; 4. Auto save: (optional) r0-r11, blink, LPE,LPS,LPC, JLI,LDI,EI + ; 4a. Auto save: (optional) r0-r11, blink, LPE,LPS,LPC, JLI,LDI,EI ; - ; (B) Manually saved some regs: r12,r25,r30, sp,fp,gp, ACCL pair + ; Now + ; 4b. If Auto-save (optional) not enabled in hw, manually save them + ; 5. Manually save: r12,r30, sp,fp,gp, ACCL pair + ; + ; At the end, SP points to pt_regs #ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE ; carve pt_regs on stack (case #3), PC/STAT32 already on stack @@ -72,15 +75,16 @@ .endm /*------------------------------------------------------------------------*/ -.macro EXCEPTION_PROLOGUE +.macro EXCEPTION_PROLOGUE_KEEP_AE - ; (A) Before jumping to Exception Vector, hardware micro-ops did following: + ; Before jumping to Exception Vector, hardware micro-ops did following: ; 1. SP auto-switched to kernel mode stack ; 2. STATUS32.Z flag set if in U mode at time of exception (U:1,K:0) ; - ; (B) Manually save the complete reg file below + ; Now manually save rest of reg file + ; At the end, SP points to pt_regs - sub sp, sp, SZ_PT_REGS ; carve pt_regs + sub sp, sp, SZ_PT_REGS ; carve space for pt_regs ; _HARD saves r10 clobbered by _SOFT as scratch hence comes first @@ -100,6 +104,16 @@ ; OUTPUT: r10 has ECR expected by EV_Trap .endm +.macro EXCEPTION_PROLOGUE + + EXCEPTION_PROLOGUE_KEEP_AE ; return ECR in r10 + + lr r0, [efa] + mov r1, sp + + FAKE_RET_FROM_EXCPN ; clobbers r9 +.endm + /*------------------------------------------------------------------------ * This macro saves the registers manually which would normally be autosaved * by hardware on taken interrupts. It is used by @@ -135,10 +149,10 @@ */ .macro __SAVE_REGFILE_SOFT - ST2 gp, fp, PT_r26 ; gp (r26), fp (r27) - - st r12, [sp, PT_sp + 4] - st r30, [sp, PT_sp + 8] + st fp, [sp, PT_fp] ; r27 + st r30, [sp, PT_r30] + st r12, [sp, PT_r12] + st r26, [sp, PT_r26] ; gp ; Saving pt_regs->sp correctly requires some extra work due to the way ; Auto stack switch works @@ -153,30 +167,30 @@ ; ISA requires ADD.nz to have same dest and src reg operands mov.nz r10, sp - add.nz r10, r10, SZ_PT_REGS ; K mode SP + add2.nz r10, r10, SZ_PT_REGS/4 ; K mode SP st r10, [sp, PT_sp] ; SP (pt_regs->sp) -#ifdef CONFIG_ARC_CURR_IN_REG - st r25, [sp, PT_user_r25] - GET_CURR_TASK_ON_CPU r25 -#endif - #ifdef CONFIG_ARC_HAS_ACCL_REGS ST2 r58, r59, PT_r58 #endif /* clobbers r10, r11 registers pair */ DSP_SAVE_REGFILE_IRQ + +#ifdef CONFIG_ARC_CURR_IN_REG + GET_CURR_TASK_ON_CPU gp +#endif + .endm /*------------------------------------------------------------------------*/ .macro __RESTORE_REGFILE_SOFT - LD2 gp, fp, PT_r26 ; gp (r26), fp (r27) - - ld r12, [sp, PT_r12] + ld fp, [sp, PT_fp] ld r30, [sp, PT_r30] + ld r12, [sp, PT_r12] + ld r26, [sp, PT_r26] ; Restore SP (into AUX_USER_SP) only if returning to U mode ; - for K mode, it will be implicitly restored as stack is unwound @@ -188,10 +202,6 @@ sr r10, [AUX_USER_SP] 1: -#ifdef CONFIG_ARC_CURR_IN_REG - ld r25, [sp, PT_user_r25] -#endif - /* clobbers r10, r11 registers pair */ DSP_RESTORE_REGFILE_IRQ @@ -249,7 +259,7 @@ btst r0, STATUS_U_BIT ; Z flag set if K, used in restoring SP - ld r10, [sp, PT_event + 4] + ld r10, [sp, PT_bta] sr r10, [erbta] LD2 r10, r11, PT_ret @@ -264,8 +274,8 @@ .macro FAKE_RET_FROM_EXCPN lr r9, [status32] - bic r9, r9, STATUS_AE_MASK - or r9, r9, STATUS_IE_MASK + bclr r9, r9, STATUS_AE_BIT + bset r9, r9, STATUS_IE_BIT kflag r9 .endm diff --git a/arch/arc/include/asm/entry-compact.h b/arch/arc/include/asm/entry-compact.h index 67ff06e15cea..a0e760eb35a8 100644 --- a/arch/arc/include/asm/entry-compact.h +++ b/arch/arc/include/asm/entry-compact.h @@ -140,7 +140,7 @@ * * After this it is safe to call the "C" handlers *-------------------------------------------------------------*/ -.macro EXCEPTION_PROLOGUE +.macro EXCEPTION_PROLOGUE_KEEP_AE /* Need at least 1 reg to code the early exception prologue */ PROLOG_FREEUP_REG r9, @ex_saved_reg1 @@ -151,14 +151,6 @@ /* ARC700 doesn't provide auto-stack switching */ SWITCH_TO_KERNEL_STK -#ifdef CONFIG_ARC_CURR_IN_REG - /* Treat r25 as scratch reg (save on stack) and load with "current" */ - PUSH r25 - GET_CURR_TASK_ON_CPU r25 -#else - sub sp, sp, 4 -#endif - st.a r0, [sp, -8] /* orig_r0 needed for syscall (skip ECR slot) */ sub sp, sp, 4 /* skip pt_regs->sp, already saved above */ @@ -178,7 +170,23 @@ PUSHAX erbta lr r10, [ecr] - st r10, [sp, PT_event] /* EV_Trap expects r10 to have ECR */ + st r10, [sp, PT_event] + +#ifdef CONFIG_ARC_CURR_IN_REG + /* gp already saved on stack: now load with "current" */ + GET_CURR_TASK_ON_CPU gp +#endif + ; OUTPUT: r10 has ECR expected by EV_Trap +.endm + +.macro EXCEPTION_PROLOGUE + + EXCEPTION_PROLOGUE_KEEP_AE ; return ECR in r10 + + lr r0, [efa] + mov r1, sp + + FAKE_RET_FROM_EXCPN ; clobbers r9 .endm /*-------------------------------------------------------------- @@ -208,11 +216,8 @@ POP gp RESTORE_R12_TO_R0 -#ifdef CONFIG_ARC_CURR_IN_REG - ld r25, [sp, 12] -#endif ld sp, [sp] /* restore original sp */ - /* orig_r0, ECR, user_r25 skipped automatically */ + /* orig_r0, ECR skipped automatically */ .endm /* Dummy ECR values for Interrupts */ @@ -229,13 +234,6 @@ SWITCH_TO_KERNEL_STK -#ifdef CONFIG_ARC_CURR_IN_REG - /* Treat r25 as scratch reg (save on stack) and load with "current" */ - PUSH r25 - GET_CURR_TASK_ON_CPU r25 -#else - sub sp, sp, 4 -#endif PUSH 0x003\LVL\()abcd /* Dummy ECR */ sub sp, sp, 8 /* skip orig_r0 (not needed) @@ -255,6 +253,10 @@ PUSHAX lp_start PUSHAX bta_l\LVL\() +#ifdef CONFIG_ARC_CURR_IN_REG + /* gp already saved on stack: now load with "current" */ + GET_CURR_TASK_ON_CPU gp +#endif .endm /*-------------------------------------------------------------- @@ -282,11 +284,7 @@ POP gp RESTORE_R12_TO_R0 -#ifdef CONFIG_ARC_CURR_IN_REG - ld r25, [sp, 12] -#endif - ld sp, [sp] /* restore original sp */ - /* orig_r0, ECR, user_r25 skipped automatically */ + ld sp, [sp] /* restore original sp; orig_r0, ECR skipped implicitly */ .endm /* Get thread_info of "current" tsk */ diff --git a/arch/arc/include/asm/entry.h b/arch/arc/include/asm/entry.h index fcdd59d77f42..49c2e090cb5c 100644 --- a/arch/arc/include/asm/entry.h +++ b/arch/arc/include/asm/entry.h @@ -13,6 +13,8 @@ #include <asm/processor.h> /* For VMALLOC_START */ #include <asm/mmu.h> +#ifdef __ASSEMBLY__ + #ifdef CONFIG_ISA_ARCOMPACT #include <asm/entry-compact.h> /* ISA specific bits */ #else @@ -89,7 +91,7 @@ * Helpers to save/restore callee-saved regs: * used by several macros below *-------------------------------------------------------------*/ -.macro SAVE_R13_TO_R24 +.macro SAVE_R13_TO_R25 PUSH r13 PUSH r14 PUSH r15 @@ -102,9 +104,11 @@ PUSH r22 PUSH r23 PUSH r24 + PUSH r25 .endm -.macro RESTORE_R24_TO_R13 +.macro RESTORE_R25_TO_R13 + POP r25 POP r24 POP r23 POP r22 @@ -119,81 +123,31 @@ POP r13 .endm -/*-------------------------------------------------------------- - * Collect User Mode callee regs as struct callee_regs - needed by - * fork/do_signal/unaligned-access-emulation. - * (By default only scratch regs are saved on entry to kernel) - * - * Special handling for r25 if used for caching Task Pointer. - * It would have been saved in task->thread.user_r25 already, but to keep - * the interface same it is copied into regular r25 placeholder in - * struct callee_regs. - *-------------------------------------------------------------*/ +/* + * save user mode callee regs as struct callee_regs + * - needed by fork/do_signal/unaligned-access-emulation. + */ .macro SAVE_CALLEE_SAVED_USER + SAVE_R13_TO_R25 +.endm - mov r12, sp ; save SP as ref to pt_regs - SAVE_R13_TO_R24 - -#ifdef CONFIG_ARC_CURR_IN_REG - ; Retrieve orig r25 and save it with rest of callee_regs - ld r12, [r12, PT_user_r25] - PUSH r12 -#else - PUSH r25 -#endif - +/* + * restore user mode callee regs as struct callee_regs + * - could have been changed by ptrace tracer or unaligned-access fixup + */ +.macro RESTORE_CALLEE_SAVED_USER + RESTORE_R25_TO_R13 .endm -/*-------------------------------------------------------------- - * Save kernel Mode callee regs at the time of Contect Switch. - * - * Special handling for r25 if used for caching Task Pointer. - * Kernel simply skips saving it since it will be loaded with - * incoming task pointer anyways - *-------------------------------------------------------------*/ +/* + * save/restore kernel mode callee regs at the time of context switch + */ .macro SAVE_CALLEE_SAVED_KERNEL - - SAVE_R13_TO_R24 - -#ifdef CONFIG_ARC_CURR_IN_REG - sub sp, sp, 4 -#else - PUSH r25 -#endif + SAVE_R13_TO_R25 .endm -/*-------------------------------------------------------------- - * Opposite of SAVE_CALLEE_SAVED_KERNEL - *-------------------------------------------------------------*/ .macro RESTORE_CALLEE_SAVED_KERNEL - -#ifdef CONFIG_ARC_CURR_IN_REG - add sp, sp, 4 /* skip usual r25 placeholder */ -#else - POP r25 -#endif - RESTORE_R24_TO_R13 -.endm - -/*-------------------------------------------------------------- - * Opposite of SAVE_CALLEE_SAVED_USER - * - * ptrace tracer or unaligned-access fixup might have changed a user mode - * callee reg which is saved back to usual r25 storage location - *-------------------------------------------------------------*/ -.macro RESTORE_CALLEE_SAVED_USER - -#ifdef CONFIG_ARC_CURR_IN_REG - POP r12 -#else - POP r25 -#endif - RESTORE_R24_TO_R13 - - ; SP is back to start of pt_regs -#ifdef CONFIG_ARC_CURR_IN_REG - st r12, [sp, PT_user_r25] -#endif + RESTORE_R25_TO_R13 .endm /*-------------------------------------------------------------- @@ -229,10 +183,10 @@ #ifdef CONFIG_SMP -/*------------------------------------------------- +/* * Retrieve the current running task on this CPU - * 1. Determine curr CPU id. - * 2. Use it to index into _current_task[ ] + * - loads it from backing _current_task[] (and can't use the + * caching reg for current task */ .macro GET_CURR_TASK_ON_CPU reg GET_CPU_ID \reg @@ -254,7 +208,7 @@ add2 \tmp, @_current_task, \tmp st \tsk, [\tmp] #ifdef CONFIG_ARC_CURR_IN_REG - mov r25, \tsk + mov gp, \tsk #endif .endm @@ -269,21 +223,20 @@ .macro SET_CURR_TASK_ON_CPU tsk, tmp st \tsk, [@_current_task] #ifdef CONFIG_ARC_CURR_IN_REG - mov r25, \tsk + mov gp, \tsk #endif .endm #endif /* SMP / UNI */ -/* ------------------------------------------------------------------ +/* * Get the ptr to some field of Current Task at @off in task struct - * -Uses r25 for Current task ptr if that is enabled + * - Uses current task cached in reg if enabled */ - #ifdef CONFIG_ARC_CURR_IN_REG .macro GET_CURR_TASK_FIELD_PTR off, reg - add \reg, r25, \off + add \reg, gp, \off .endm #else @@ -295,4 +248,23 @@ #endif /* CONFIG_ARC_CURR_IN_REG */ +#else /* !__ASSEMBLY__ */ + +extern void do_signal(struct pt_regs *); +extern void do_notify_resume(struct pt_regs *); +extern int do_privilege_fault(unsigned long, struct pt_regs *); +extern int do_extension_fault(unsigned long, struct pt_regs *); +extern int insterror_is_error(unsigned long, struct pt_regs *); +extern int do_memory_error(unsigned long, struct pt_regs *); +extern int trap_is_brkpt(unsigned long, struct pt_regs *); +extern int do_misaligned_error(unsigned long, struct pt_regs *); +extern int do_trap5_error(unsigned long, struct pt_regs *); +extern int do_misaligned_access(unsigned long, struct pt_regs *, struct callee_regs *); +extern void do_machine_check_fault(unsigned long, struct pt_regs *); +extern void do_non_swi_trap(unsigned long, struct pt_regs *); +extern void do_insterror_or_kprobe(unsigned long, struct pt_regs *); +extern void do_page_fault(unsigned long, struct pt_regs *); + +#endif + #endif /* __ASM_ARC_ENTRY_H */ diff --git a/arch/arc/include/asm/irq.h b/arch/arc/include/asm/irq.h index 0309cb405cfb..c574712ad865 100644 --- a/arch/arc/include/asm/irq.h +++ b/arch/arc/include/asm/irq.h @@ -25,5 +25,6 @@ #include <asm-generic/irq.h> extern void arc_init_IRQ(void); +extern void arch_do_IRQ(unsigned int, struct pt_regs *); #endif diff --git a/arch/arc/include/asm/mmu.h b/arch/arc/include/asm/mmu.h index ca427c30f70e..9febf5bc3de6 100644 --- a/arch/arc/include/asm/mmu.h +++ b/arch/arc/include/asm/mmu.h @@ -14,6 +14,8 @@ typedef struct { unsigned long asid[NR_CPUS]; /* 8 bit MMU PID + Generation cycle */ } mm_context_t; +extern void do_tlb_overlap_fault(unsigned long, unsigned long, struct pt_regs *); + #endif #include <asm/mmu-arcv2.h> diff --git a/arch/arc/include/asm/processor.h b/arch/arc/include/asm/processor.h index fb844fce1ab6..d606658e2fe7 100644 --- a/arch/arc/include/asm/processor.h +++ b/arch/arc/include/asm/processor.h @@ -22,7 +22,6 @@ * struct thread_info */ struct thread_struct { - unsigned long ksp; /* kernel mode stack pointer */ unsigned long callee_reg; /* pointer to callee regs */ unsigned long fault_address; /* dbls as brkpt holder as well */ #ifdef CONFIG_ARC_DSP_SAVE_RESTORE_REGS @@ -33,9 +32,7 @@ struct thread_struct { #endif }; -#define INIT_THREAD { \ - .ksp = sizeof(init_stack) + (unsigned long) init_stack, \ -} +#define INIT_THREAD { } /* Forward declaration, a strange C thing */ struct task_struct; @@ -56,7 +53,7 @@ struct task_struct; * Where about of Task's sp, fp, blink when it was last seen in kernel mode. * Look in process.c for details of kernel stack layout */ -#define TSK_K_ESP(tsk) (tsk->thread.ksp) +#define TSK_K_ESP(tsk) (task_thread_info(tsk)->ksp) #define TSK_K_REG(tsk, off) (*((unsigned long *)(TSK_K_ESP(tsk) + \ sizeof(struct callee_regs) + off))) diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h index 5869a74c0db2..4a2b30fb5a98 100644 --- a/arch/arc/include/asm/ptrace.h +++ b/arch/arc/include/asm/ptrace.h @@ -12,6 +12,17 @@ #ifndef __ASSEMBLY__ +typedef union { + struct { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned long state:8, vec:8, cause:8, param:8; +#else + unsigned long param:8, cause:8, vec:8, state:8; +#endif + }; + unsigned long full; +} ecr_reg; + /* THE pt_regs: Defines how regs are saved during entry into kernel */ #ifdef CONFIG_ISA_ARCOMPACT @@ -40,23 +51,10 @@ struct pt_regs { * Last word used by Linux for extra state mgmt (syscall-restart) * For interrupts, use artificial ECR values to note current prio-level */ - union { - struct { -#ifdef CONFIG_CPU_BIG_ENDIAN - unsigned long state:8, ecr_vec:8, - ecr_cause:8, ecr_param:8; -#else - unsigned long ecr_param:8, ecr_cause:8, - ecr_vec:8, state:8; -#endif - }; - unsigned long event; - }; - - unsigned long user_r25; + ecr_reg ecr; }; -#define MAX_REG_OFFSET offsetof(struct pt_regs, user_r25) +#define MAX_REG_OFFSET offsetof(struct pt_regs, ecr) #else @@ -64,28 +62,14 @@ struct pt_regs { unsigned long orig_r0; - union { - struct { -#ifdef CONFIG_CPU_BIG_ENDIAN - unsigned long state:8, ecr_vec:8, - ecr_cause:8, ecr_param:8; -#else - unsigned long ecr_param:8, ecr_cause:8, - ecr_vec:8, state:8; -#endif - }; - unsigned long event; - }; - - unsigned long bta; /* bta_l1, bta_l2, erbta */ + ecr_reg ecr; /* Exception Cause Reg */ - unsigned long user_r25; + unsigned long bta; /* erbta */ - unsigned long r26; /* gp */ unsigned long fp; - unsigned long sp; /* user/kernel sp depending on where we came from */ - - unsigned long r12, r30; + unsigned long r30; + unsigned long r12; + unsigned long r26; /* gp */ #ifdef CONFIG_ARC_HAS_ACCL_REGS unsigned long r58, r59; /* ACCL/ACCH used by FPU / DSP MPY */ @@ -94,6 +78,8 @@ struct pt_regs { unsigned long DSP_CTRL; #endif + unsigned long sp; /* user/kernel sp depending on entry */ + /*------- Below list auto saved by h/w -----------*/ unsigned long r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11; @@ -134,13 +120,13 @@ struct callee_regs { /* return 1 if PC in delay slot */ #define delay_mode(regs) ((regs->status32 & STATUS_DE_MASK) == STATUS_DE_MASK) -#define in_syscall(regs) ((regs->ecr_vec == ECR_V_TRAP) && !regs->ecr_param) -#define in_brkpt_trap(regs) ((regs->ecr_vec == ECR_V_TRAP) && regs->ecr_param) +#define in_syscall(regs) ((regs->ecr.vec == ECR_V_TRAP) && !regs->ecr.param) +#define in_brkpt_trap(regs) ((regs->ecr.vec == ECR_V_TRAP) && regs->ecr.param) #define STATE_SCALL_RESTARTED 0x01 -#define syscall_wont_restart(reg) (reg->state |= STATE_SCALL_RESTARTED) -#define syscall_restartable(reg) !(reg->state & STATE_SCALL_RESTARTED) +#define syscall_wont_restart(regs) (regs->ecr.state |= STATE_SCALL_RESTARTED) +#define syscall_restartable(regs) !(regs->ecr.state & STATE_SCALL_RESTARTED) #define current_pt_regs() \ ({ \ @@ -181,6 +167,9 @@ static inline unsigned long regs_get_register(struct pt_regs *regs, return *(unsigned long *)((unsigned long)regs + offset); } +extern int syscall_trace_entry(struct pt_regs *); +extern void syscall_trace_exit(struct pt_regs *); + #endif /* !__ASSEMBLY__ */ #endif /* __ASM_PTRACE_H */ diff --git a/arch/arc/include/asm/setup.h b/arch/arc/include/asm/setup.h index 028a8cf76206..1c6db599e1fc 100644 --- a/arch/arc/include/asm/setup.h +++ b/arch/arc/include/asm/setup.h @@ -35,11 +35,11 @@ long __init arc_get_mem_sz(void); #define IS_AVAIL3(v, v2, s) IS_AVAIL1(v, s), IS_AVAIL1(v, IS_DISABLED_RUN(v2)) extern void arc_mmu_init(void); -extern char *arc_mmu_mumbojumbo(int cpu_id, char *buf, int len); -extern void read_decode_mmu_bcr(void); +extern int arc_mmu_mumbojumbo(int cpu_id, char *buf, int len); extern void arc_cache_init(void); -extern char *arc_cache_mumbojumbo(int cpu_id, char *buf, int len); -extern void read_decode_cache_bcr(void); +extern int arc_cache_mumbojumbo(int cpu_id, char *buf, int len); + +extern void __init handle_uboot_args(void); #endif /* __ASMARC_SETUP_H */ diff --git a/arch/arc/include/asm/smp.h b/arch/arc/include/asm/smp.h index d856491606ac..e0913f52c2cd 100644 --- a/arch/arc/include/asm/smp.h +++ b/arch/arc/include/asm/smp.h @@ -29,6 +29,8 @@ extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); extern void __init smp_init_cpus(void); extern void first_lines_of_secondary(void); extern const char *arc_platform_smp_cpuinfo(void); +extern void arc_platform_smp_wait_to_boot(int); +extern void start_kernel_secondary(void); /* * API expected BY platform smp code (FROM arch smp code) diff --git a/arch/arc/include/asm/thread_info.h b/arch/arc/include/asm/thread_info.h index 6ba7fe417095..4c530cf131f3 100644 --- a/arch/arc/include/asm/thread_info.h +++ b/arch/arc/include/asm/thread_info.h @@ -37,16 +37,16 @@ */ struct thread_info { unsigned long flags; /* low level flags */ + unsigned long ksp; /* kernel mode stack top in __switch_to */ int preempt_count; /* 0 => preemptable, <0 => BUG */ - struct task_struct *task; /* main task structure */ - __u32 cpu; /* current CPU */ + int cpu; /* current CPU */ unsigned long thr_ptr; /* TLS ptr */ + struct task_struct *task; /* main task structure */ }; /* - * macros/functions for gaining access to the thread information structure - * - * preempt_count needs to be 1 initially, until the scheduler is functional. + * initilaize thread_info for any @tsk + * - this is not related to init_task per se */ #define INIT_THREAD_INFO(tsk) \ { \ diff --git a/arch/arc/include/asm/uaccess.h b/arch/arc/include/asm/uaccess.h index 99712471c96a..1e8809ea000a 100644 --- a/arch/arc/include/asm/uaccess.h +++ b/arch/arc/include/asm/uaccess.h @@ -146,8 +146,9 @@ raw_copy_from_user(void *to, const void __user *from, unsigned long n) if (n == 0) return 0; - /* unaligned */ - if (((unsigned long)to & 0x3) || ((unsigned long)from & 0x3)) { + /* fallback for unaligned access when hardware doesn't support */ + if (!IS_ENABLED(CONFIG_ARC_USE_UNALIGNED_MEM_ACCESS) && + (((unsigned long)to & 0x3) || ((unsigned long)from & 0x3))) { unsigned char tmp; @@ -373,8 +374,9 @@ raw_copy_to_user(void __user *to, const void *from, unsigned long n) if (n == 0) return 0; - /* unaligned */ - if (((unsigned long)to & 0x3) || ((unsigned long)from & 0x3)) { + /* fallback for unaligned access when hardware doesn't support */ + if (!IS_ENABLED(CONFIG_ARC_USE_UNALIGNED_MEM_ACCESS) && + (((unsigned long)to & 0x3) || ((unsigned long)from & 0x3))) { unsigned char tmp; @@ -584,7 +586,7 @@ raw_copy_to_user(void __user *to, const void *from, unsigned long n) return res; } -static inline unsigned long __arc_clear_user(void __user *to, unsigned long n) +static inline unsigned long __clear_user(void __user *to, unsigned long n) { long res = n; unsigned char *d_char = to; @@ -626,17 +628,10 @@ static inline unsigned long __arc_clear_user(void __user *to, unsigned long n) return res; } -#ifndef CONFIG_CC_OPTIMIZE_FOR_SIZE - #define INLINE_COPY_TO_USER #define INLINE_COPY_FROM_USER -#define __clear_user(d, n) __arc_clear_user(d, n) -#else -extern unsigned long arc_clear_user_noinline(void __user *to, - unsigned long n); -#define __clear_user(d, n) arc_clear_user_noinline(d, n) -#endif +#define __clear_user __clear_user #include <asm-generic/uaccess.h> diff --git a/arch/arc/kernel/Makefile b/arch/arc/kernel/Makefile index 0723d888ac44..95fbf9364c67 100644 --- a/arch/arc/kernel/Makefile +++ b/arch/arc/kernel/Makefile @@ -5,6 +5,8 @@ obj-y := head.o arcksyms.o setup.o irq.o reset.o ptrace.o process.o devtree.o obj-y += signal.o traps.o sys.o troubleshoot.o stacktrace.o disasm.o +obj-y += ctx_sw_asm.o + obj-$(CONFIG_ISA_ARCOMPACT) += entry-compact.o intc-compact.o obj-$(CONFIG_ISA_ARCV2) += entry-arcv2.o intc-arcv2.o @@ -24,11 +26,4 @@ ifdef CONFIG_ISA_ARCOMPACT CFLAGS_fpu.o += -mdpfp endif -ifdef CONFIG_ARC_DW2_UNWIND -CFLAGS_ctx_sw.o += -fno-omit-frame-pointer -obj-y += ctx_sw.o -else -obj-y += ctx_sw_asm.o -endif - extra-y := vmlinux.lds diff --git a/arch/arc/kernel/asm-offsets.c b/arch/arc/kernel/asm-offsets.c index 0e884036ab74..f77deb799175 100644 --- a/arch/arc/kernel/asm-offsets.c +++ b/arch/arc/kernel/asm-offsets.c @@ -20,13 +20,13 @@ int main(void) BLANK(); - DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp)); DEFINE(THREAD_CALLEE_REG, offsetof(struct thread_struct, callee_reg)); DEFINE(THREAD_FAULT_ADDR, offsetof(struct thread_struct, fault_address)); BLANK(); + DEFINE(THREAD_INFO_KSP, offsetof(struct thread_info, ksp)); DEFINE(THREAD_INFO_FLAGS, offsetof(struct thread_info, flags)); DEFINE(THREAD_INFO_PREEMPT_COUNT, offsetof(struct thread_info, preempt_count)); @@ -46,7 +46,8 @@ int main(void) BLANK(); DEFINE(PT_status32, offsetof(struct pt_regs, status32)); - DEFINE(PT_event, offsetof(struct pt_regs, event)); + DEFINE(PT_event, offsetof(struct pt_regs, ecr)); + DEFINE(PT_bta, offsetof(struct pt_regs, bta)); DEFINE(PT_sp, offsetof(struct pt_regs, sp)); DEFINE(PT_r0, offsetof(struct pt_regs, r0)); DEFINE(PT_r1, offsetof(struct pt_regs, r1)); @@ -61,13 +62,9 @@ int main(void) DEFINE(PT_r26, offsetof(struct pt_regs, r26)); DEFINE(PT_ret, offsetof(struct pt_regs, ret)); DEFINE(PT_blink, offsetof(struct pt_regs, blink)); + OFFSET(PT_fp, pt_regs, fp); DEFINE(PT_lpe, offsetof(struct pt_regs, lp_end)); DEFINE(PT_lpc, offsetof(struct pt_regs, lp_count)); - DEFINE(PT_user_r25, offsetof(struct pt_regs, user_r25)); - - DEFINE(SZ_CALLEE_REGS, sizeof(struct callee_regs)); - DEFINE(SZ_PT_REGS, sizeof(struct pt_regs)); - #ifdef CONFIG_ISA_ARCV2 OFFSET(PT_r12, pt_regs, r12); OFFSET(PT_r30, pt_regs, r30); @@ -80,5 +77,8 @@ int main(void) OFFSET(PT_DSP_CTRL, pt_regs, DSP_CTRL); #endif + DEFINE(SZ_CALLEE_REGS, sizeof(struct callee_regs)); + DEFINE(SZ_PT_REGS, sizeof(struct pt_regs)); + return 0; } diff --git a/arch/arc/kernel/ctx_sw.c b/arch/arc/kernel/ctx_sw.c deleted file mode 100644 index 1a76f2d6f694..000000000000 --- a/arch/arc/kernel/ctx_sw.c +++ /dev/null @@ -1,112 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) - * - * Vineetg: Aug 2009 - * -"C" version of lowest level context switch asm macro called by schedular - * gcc doesn't generate the dward CFI info for hand written asm, hence can't - * backtrace out of it (e.g. tasks sleeping in kernel). - * So we cheat a bit by writing almost similar code in inline-asm. - * -This is a hacky way of doing things, but there is no other simple way. - * I don't want/intend to extend unwinding code to understand raw asm - */ - -#include <asm/asm-offsets.h> -#include <linux/sched.h> -#include <linux/sched/debug.h> - -#define KSP_WORD_OFF ((TASK_THREAD + THREAD_KSP) / 4) - -struct task_struct *__sched -__switch_to(struct task_struct *prev_task, struct task_struct *next_task) -{ - unsigned int tmp; - unsigned int prev = (unsigned int)prev_task; - unsigned int next = (unsigned int)next_task; - - __asm__ __volatile__( - /* FP/BLINK save generated by gcc (standard function prologue */ - "st.a r13, [sp, -4] \n\t" - "st.a r14, [sp, -4] \n\t" - "st.a r15, [sp, -4] \n\t" - "st.a r16, [sp, -4] \n\t" - "st.a r17, [sp, -4] \n\t" - "st.a r18, [sp, -4] \n\t" - "st.a r19, [sp, -4] \n\t" - "st.a r20, [sp, -4] \n\t" - "st.a r21, [sp, -4] \n\t" - "st.a r22, [sp, -4] \n\t" - "st.a r23, [sp, -4] \n\t" - "st.a r24, [sp, -4] \n\t" -#ifndef CONFIG_ARC_CURR_IN_REG - "st.a r25, [sp, -4] \n\t" -#else - "sub sp, sp, 4 \n\t" /* usual r25 placeholder */ -#endif - - /* set ksp of outgoing task in tsk->thread.ksp */ -#if KSP_WORD_OFF <= 255 - "st.as sp, [%3, %1] \n\t" -#else - /* - * Workaround for NR_CPUS=4k - * %1 is bigger than 255 (S9 offset for st.as) - */ - "add2 r24, %3, %1 \n\t" - "st sp, [r24] \n\t" -#endif - - /* - * setup _current_task with incoming tsk. - * optionally, set r25 to that as well - * For SMP extra work to get to &_current_task[cpu] - * (open coded SET_CURR_TASK_ON_CPU) - */ -#ifndef CONFIG_SMP - "st %2, [@_current_task] \n\t" -#else - "lr r24, [identity] \n\t" - "lsr r24, r24, 8 \n\t" - "bmsk r24, r24, 7 \n\t" - "add2 r24, @_current_task, r24 \n\t" - "st %2, [r24] \n\t" -#endif -#ifdef CONFIG_ARC_CURR_IN_REG - "mov r25, %2 \n\t" -#endif - - /* get ksp of incoming task from tsk->thread.ksp */ - "ld.as sp, [%2, %1] \n\t" - - /* start loading it's CALLEE reg file */ - -#ifndef CONFIG_ARC_CURR_IN_REG - "ld.ab r25, [sp, 4] \n\t" -#else - "add sp, sp, 4 \n\t" -#endif - "ld.ab r24, [sp, 4] \n\t" - "ld.ab r23, [sp, 4] \n\t" - "ld.ab r22, [sp, 4] \n\t" - "ld.ab r21, [sp, 4] \n\t" - "ld.ab r20, [sp, 4] \n\t" - "ld.ab r19, [sp, 4] \n\t" - "ld.ab r18, [sp, 4] \n\t" - "ld.ab r17, [sp, 4] \n\t" - "ld.ab r16, [sp, 4] \n\t" - "ld.ab r15, [sp, 4] \n\t" - "ld.ab r14, [sp, 4] \n\t" - "ld.ab r13, [sp, 4] \n\t" - - /* last (ret value) = prev : although for ARC it mov r0, r0 */ - "mov %0, %3 \n\t" - - /* FP/BLINK restore generated by gcc (standard func epilogue */ - - : "=r"(tmp) - : "n"(KSP_WORD_OFF), "r"(next), "r"(prev) - : "blink" - ); - - return (struct task_struct *)tmp; -} diff --git a/arch/arc/kernel/ctx_sw_asm.S b/arch/arc/kernel/ctx_sw_asm.S index 02c461484761..48e1f21976ed 100644 --- a/arch/arc/kernel/ctx_sw_asm.S +++ b/arch/arc/kernel/ctx_sw_asm.S @@ -11,50 +11,54 @@ #include <asm/entry.h> /* For the SAVE_* macros */ #include <asm/asm-offsets.h> -#define KSP_WORD_OFF ((TASK_THREAD + THREAD_KSP) / 4) - -;################### Low Level Context Switch ########################## +; IN +; - r0: prev task (also current) +; - r1: next task +; OUT +; - r0: prev task (so r0 not touched) .section .sched.text,"ax",@progbits - .align 4 - .global __switch_to - .type __switch_to, @function -__switch_to: - CFI_STARTPROC - - /* Save regs on kernel mode stack of task */ - st.a blink, [sp, -4] - st.a fp, [sp, -4] - SAVE_CALLEE_SAVED_KERNEL +ENTRY_CFI(__switch_to) - /* Save the now KSP in task->thread.ksp */ -#if KSP_WORD_OFF <= 255 - st.as sp, [r0, KSP_WORD_OFF] -#else - /* Workaround for NR_CPUS=4k as ST.as can only take s9 offset */ - add2 r24, r0, KSP_WORD_OFF - st sp, [r24] -#endif - /* - * Return last task in r0 (return reg) - * On ARC, Return reg = First Arg reg = r0. - * Since we already have last task in r0, - * don't need to do anything special to return it - */ + /* save kernel stack frame regs of @prev task */ + push blink + CFI_DEF_CFA_OFFSET 4 + CFI_OFFSET r31, -4 + + push fp + CFI_DEF_CFA_OFFSET 8 + CFI_OFFSET r27, -8 + + mov fp, sp + CFI_DEF_CFA_REGISTER r27 + + /* kernel mode callee regs of @prev */ + SAVE_CALLEE_SAVED_KERNEL /* - * switch to new task, contained in r1 - * Temp reg r3 is required to get the ptr to store val + * save final SP to @prev->thread_info.ksp + * @prev is "current" so thread_info derived from SP */ - SET_CURR_TASK_ON_CPU r1, r3 + GET_CURR_THR_INFO_FROM_SP r10 + st sp, [r10, THREAD_INFO_KSP] + + /* update @next in _current_task[] and GP register caching it */ + SET_CURR_TASK_ON_CPU r1, r10 - /* reload SP with kernel mode stack pointer in task->thread.ksp */ - ld.as sp, [r1, (TASK_THREAD + THREAD_KSP)/4] + /* load SP from @next->thread_info.ksp */ + ld r10, [r1, TASK_THREAD_INFO] + ld sp, [r10, THREAD_INFO_KSP] - /* restore the registers */ + /* restore callee regs, stack frame regs of @next */ RESTORE_CALLEE_SAVED_KERNEL - ld.ab fp, [sp, 4] - ld.ab blink, [sp, 4] - j [blink] + pop fp + CFI_RESTORE r27 + CFI_DEF_CFA r28, 4 + + pop blink + CFI_RESTORE r31 + CFI_DEF_CFA_OFFSET 0 + + j [blink] END_CFI(__switch_to) diff --git a/arch/arc/kernel/devtree.c b/arch/arc/kernel/devtree.c index 721d465f1580..4c9e61457b2f 100644 --- a/arch/arc/kernel/devtree.c +++ b/arch/arc/kernel/devtree.c @@ -12,6 +12,7 @@ #include <linux/of.h> #include <linux/of_fdt.h> #include <asm/mach_desc.h> +#include <asm/serial.h> #ifdef CONFIG_SERIAL_EARLYCON diff --git a/arch/arc/kernel/entry-arcv2.S b/arch/arc/kernel/entry-arcv2.S index a7e6a2174187..2e49c81c8086 100644 --- a/arch/arc/kernel/entry-arcv2.S +++ b/arch/arc/kernel/entry-arcv2.S @@ -125,11 +125,6 @@ ENTRY(mem_service) EXCEPTION_PROLOGUE - lr r0, [efa] - mov r1, sp - - FAKE_RET_FROM_EXCPN - bl do_memory_error b ret_from_exception END(mem_service) @@ -138,11 +133,6 @@ ENTRY(EV_Misaligned) EXCEPTION_PROLOGUE - lr r0, [efa] ; Faulting Data address - mov r1, sp - - FAKE_RET_FROM_EXCPN - SAVE_CALLEE_SAVED_USER mov r2, sp ; callee_regs @@ -163,11 +153,6 @@ ENTRY(EV_TLBProtV) EXCEPTION_PROLOGUE - lr r0, [efa] ; Faulting Data address - mov r1, sp ; pt_regs - - FAKE_RET_FROM_EXCPN - mov blink, ret_from_exception b do_page_fault diff --git a/arch/arc/kernel/entry-compact.S b/arch/arc/kernel/entry-compact.S index 5cb0cd7e4eab..774c03cc1d1a 100644 --- a/arch/arc/kernel/entry-compact.S +++ b/arch/arc/kernel/entry-compact.S @@ -254,18 +254,7 @@ END(handle_interrupt_level1) ENTRY(EV_TLBProtV) - EXCEPTION_PROLOGUE - - mov r2, r10 ; ECR set into r10 already - lr r0, [efa] ; Faulting Data address (not part of pt_regs saved above) - - ; Exception auto-disables further Intr/exceptions. - ; Re-enable them by pretending to return from exception - ; (so rest of handler executes in pure K mode) - - FAKE_RET_FROM_EXCPN - - mov r1, sp ; Handle to pt_regs + EXCEPTION_PROLOGUE ; ECR returned in r10 ;------ (5) Type of Protection Violation? ---------- ; @@ -273,8 +262,7 @@ ENTRY(EV_TLBProtV) ; -Access Violation : 00_23_(00|01|02|03)_00 ; x r w r+w ; -Unaligned Access : 00_23_04_00 - ; - bbit1 r2, ECR_C_BIT_PROTV_MISALIG_DATA, 4f + bbit1 r10, ECR_C_BIT_PROTV_MISALIG_DATA, 4f ;========= (6a) Access Violation Processing ======== bl do_page_fault @@ -303,9 +291,6 @@ END(EV_TLBProtV) ENTRY(call_do_page_fault) EXCEPTION_PROLOGUE - lr r0, [efa] ; Faulting Data address - mov r1, sp - FAKE_RET_FROM_EXCPN mov blink, ret_from_exception b do_page_fault diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S index 54e91df678dd..089f6680518f 100644 --- a/arch/arc/kernel/entry.S +++ b/arch/arc/kernel/entry.S @@ -80,11 +80,6 @@ ENTRY(instr_service) EXCEPTION_PROLOGUE - lr r0, [efa] - mov r1, sp - - FAKE_RET_FROM_EXCPN - bl do_insterror_or_kprobe b ret_from_exception END(instr_service) @@ -95,16 +90,15 @@ END(instr_service) ENTRY(EV_MachineCheck) - EXCEPTION_PROLOGUE + EXCEPTION_PROLOGUE_KEEP_AE ; ECR returned in r10 - lr r2, [ecr] lr r0, [efa] mov r1, sp ; MC excpetions disable MMU ARC_MMU_REENABLE r3 - lsr r3, r2, 8 + lsr r3, r10, 8 bmsk r3, r3, 7 brne r3, ECR_C_MCHK_DUP_TLB, 1f @@ -129,11 +123,6 @@ ENTRY(EV_PrivilegeV) EXCEPTION_PROLOGUE - lr r0, [efa] - mov r1, sp - - FAKE_RET_FROM_EXCPN - bl do_privilege_fault b ret_from_exception END(EV_PrivilegeV) @@ -145,11 +134,6 @@ ENTRY(EV_Extension) EXCEPTION_PROLOGUE - lr r0, [efa] - mov r1, sp - - FAKE_RET_FROM_EXCPN - bl do_extension_fault b ret_from_exception END(EV_Extension) @@ -160,20 +144,19 @@ END(EV_Extension) ; syscall Tracing ; --------------------------------------------- tracesys: - ; save EFA in case tracer wants the PC of traced task - ; using ERET won't work since next-PC has already committed + ; safekeep EFA (r12) if syscall tracer wanted PC + ; for traps, ERET is pre-commit so points to next-PC GET_CURR_TASK_FIELD_PTR TASK_THREAD, r11 st r12, [r11, THREAD_FAULT_ADDR] ; thread.fault_address - ; PRE Sys Call Ptrace hook - mov r0, sp ; pt_regs needed - bl @syscall_trace_entry + ; PRE syscall trace hook + mov r0, sp ; pt_regs + bl @syscall_trace_enter ; Tracing code now returns the syscall num (orig or modif) mov r8, r0 ; Do the Sys Call as we normally would. - ; Validate the Sys Call number cmp r8, NR_syscalls - 1 mov.hi r0, -ENOSYS bhi tracesys_exit @@ -190,37 +173,36 @@ tracesys: ld r6, [sp, PT_r6] ld r7, [sp, PT_r7] ld.as r9, [sys_call_table, r8] - jl [r9] ; Entry into Sys Call Handler + jl [r9] tracesys_exit: - st r0, [sp, PT_r0] ; sys call return value in pt_regs + st r0, [sp, PT_r0] - ;POST Sys Call Ptrace Hook + ; POST syscall trace hook mov r0, sp ; pt_regs needed bl @syscall_trace_exit - b ret_from_exception ; NOT ret_from_system_call at is saves r0 which - ; we'd done before calling post hook above + + ; don't call ret_from_system_call as it saves r0, already done above + b ret_from_exception ; --------------------------------------------- ; Breakpoint TRAP ; --------------------------------------------- trap_with_param: mov r0, r12 ; EFA in case ptracer/gdb wants stop_pc - mov r1, sp + mov r1, sp ; pt_regs - ; Save callee regs in case gdb wants to have a look - ; SP will grow up by size of CALLEE Reg-File - ; NOTE: clobbers r12 + ; save callee regs in case tracer/gdb wants to peek SAVE_CALLEE_SAVED_USER - ; save location of saved Callee Regs @ thread_struct->pc + ; safekeep ref to callee regs GET_CURR_TASK_FIELD_PTR TASK_THREAD, r10 st sp, [r10, THREAD_CALLEE_REG] - ; Call the trap handler + ; call the non syscall trap handler bl do_non_swi_trap - ; unwind stack to discard Callee saved Regs + ; unwind stack to discard callee regs DISCARD_CALLEE_SAVED_USER b ret_from_exception @@ -232,37 +214,33 @@ trap_with_param: ENTRY(EV_Trap) - EXCEPTION_PROLOGUE + EXCEPTION_PROLOGUE_KEEP_AE lr r12, [efa] FAKE_RET_FROM_EXCPN - ;============ TRAP 1 :breakpoints - ; Check ECR for trap with arg (PROLOGUE ensures r10 has ECR) + ;============ TRAP N : breakpoints, kprobes etc bmsk.f 0, r10, 7 bnz trap_with_param - ;============ TRAP (no param): syscall top level + ;============ TRAP 0 (no param): syscall - ; If syscall tracing ongoing, invoke pre-post-hooks + ; syscall tracing ongoing, invoke pre-post-hooks around syscall GET_CURR_THR_INFO_FLAGS r10 and.f 0, r10, _TIF_SYSCALL_WORK bnz tracesys ; this never comes back ;============ Normal syscall case - ; syscall num shd not exceed the total system calls avail cmp r8, NR_syscalls - 1 mov.hi r0, -ENOSYS bhi .Lret_from_system_call - ; Offset into the syscall_table and call handler ld.as r9,[sys_call_table, r8] - jl [r9] ; Entry into Sys Call Handler + jl [r9] .Lret_from_system_call: - st r0, [sp, PT_r0] ; sys call return value in pt_regs ; fall through to ret_from_exception @@ -318,7 +296,7 @@ resume_user_mode_begin: ; tracer might call PEEKUSR(CALLEE reg) ; ; NOTE: SP will grow up by size of CALLEE Reg-File - SAVE_CALLEE_SAVED_USER ; clobbers r12 + SAVE_CALLEE_SAVED_USER ; save location of saved Callee Regs @ thread_struct->callee GET_CURR_TASK_FIELD_PTR TASK_THREAD, r10 diff --git a/arch/arc/kernel/intc-arcv2.c b/arch/arc/kernel/intc-arcv2.c index 5cda19d0aa91..678898757e47 100644 --- a/arch/arc/kernel/intc-arcv2.c +++ b/arch/arc/kernel/intc-arcv2.c @@ -108,7 +108,7 @@ static void arcv2_irq_unmask(struct irq_data *data) write_aux_reg(AUX_IRQ_ENABLE, 1); } -void arcv2_irq_enable(struct irq_data *data) +static void arcv2_irq_enable(struct irq_data *data) { /* set default priority */ write_aux_reg(AUX_IRQ_SELECT, data->hwirq); diff --git a/arch/arc/kernel/kgdb.c b/arch/arc/kernel/kgdb.c index 345a0000554c..4f2b5951454f 100644 --- a/arch/arc/kernel/kgdb.c +++ b/arch/arc/kernel/kgdb.c @@ -175,7 +175,7 @@ void kgdb_trap(struct pt_regs *regs) * with trap_s 4 (compiled) breakpoints, continuation needs to * start after the breakpoint. */ - if (regs->ecr_param == 3) + if (regs->ecr.param == 3) instruction_pointer(regs) -= BREAK_INSTR_SIZE; kgdb_handle_exception(1, SIGTRAP, 0, regs); diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c index f9fdb557c263..55373ca0d28b 100644 --- a/arch/arc/kernel/mcip.c +++ b/arch/arc/kernel/mcip.c @@ -165,8 +165,6 @@ static void mcip_probe_n_setup(void) IS_AVAIL1(mp.idu, "IDU "), IS_AVAIL1(mp.dbg, "DEBUG "), IS_AVAIL1(mp.gfrc, "GFRC")); - - cpuinfo_arc700[0].extn.gfrc = mp.gfrc; } struct plat_smp_ops plat_smp_ops = { diff --git a/arch/arc/kernel/process.c b/arch/arc/kernel/process.c index 980b71da2f61..186ceab661eb 100644 --- a/arch/arc/kernel/process.c +++ b/arch/arc/kernel/process.c @@ -141,7 +141,7 @@ asmlinkage void ret_from_fork(void); * | unused | * | | * ------------------ - * | r25 | <==== top of Stack (thread.ksp) + * | r25 | <==== top of Stack (thread_info.ksp) * ~ ~ * | --to-- | (CALLEE Regs of kernel mode) * | r13 | @@ -162,7 +162,6 @@ asmlinkage void ret_from_fork(void); * | SP | * | orig_r0 | * | event/ECR | - * | user_r25 | * ------------------ <===== END of PAGE */ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args) @@ -182,14 +181,14 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args) c_callee = ((struct callee_regs *)childksp) - 1; /* - * __switch_to() uses thread.ksp to start unwinding stack + * __switch_to() uses thread_info.ksp to start unwinding stack * For kernel threads we don't need to create callee regs, the * stack layout nevertheless needs to remain the same. * Also, since __switch_to anyways unwinds callee regs, we use * this to populate kernel thread entry-pt/args into callee regs, * so that ret_from_kernel_thread() becomes simpler. */ - p->thread.ksp = (unsigned long)c_callee; /* THREAD_KSP */ + task_thread_info(p)->ksp = (unsigned long)c_callee; /* THREAD_INFO_KSP */ /* __switch_to expects FP(0), BLINK(return addr) at top */ childksp[0] = 0; /* fp */ @@ -243,16 +242,6 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args) */ c_callee->r25 = task_thread_info(p)->thr_ptr; -#ifdef CONFIG_ARC_CURR_IN_REG - /* - * setup usermode thread pointer #2: - * however for this special use of r25 in kernel, __switch_to() sets - * r25 for kernel needs and only in the final return path is usermode - * r25 setup, from pt_regs->user_r25. So set that up as well - */ - c_regs->user_r25 = c_callee->r25; -#endif - return 0; } diff --git a/arch/arc/kernel/ptrace.c b/arch/arc/kernel/ptrace.c index 2abdcd9b09e8..e0c233c178b1 100644 --- a/arch/arc/kernel/ptrace.c +++ b/arch/arc/kernel/ptrace.c @@ -46,8 +46,7 @@ static const struct pt_regs_offset regoffset_table[] = { REG_OFFSET_NAME(r0), REG_OFFSET_NAME(sp), REG_OFFSET_NAME(orig_r0), - REG_OFFSET_NAME(event), - REG_OFFSET_NAME(user_r25), + REG_OFFSET_NAME(ecr), REG_OFFSET_END, }; @@ -55,9 +54,8 @@ static const struct pt_regs_offset regoffset_table[] = { static const struct pt_regs_offset regoffset_table[] = { REG_OFFSET_NAME(orig_r0), - REG_OFFSET_NAME(event), + REG_OFFSET_NAME(ecr), REG_OFFSET_NAME(bta), - REG_OFFSET_NAME(user_r25), REG_OFFSET_NAME(r26), REG_OFFSET_NAME(fp), REG_OFFSET_NAME(sp), @@ -341,7 +339,7 @@ long arch_ptrace(struct task_struct *child, long request, return ret; } -asmlinkage int syscall_trace_entry(struct pt_regs *regs) +asmlinkage int syscall_trace_enter(struct pt_regs *regs) { if (test_thread_flag(TIF_SYSCALL_TRACE)) if (ptrace_report_syscall_entry(regs)) diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c index 41f07b3e594e..4dcf8589b708 100644 --- a/arch/arc/kernel/setup.c +++ b/arch/arc/kernel/setup.c @@ -29,6 +29,7 @@ #include <asm/mach_desc.h> #include <asm/smp.h> #include <asm/dsp-impl.h> +#include <soc/arc/mcip.h> #define FIX_PTR(x) __asm__ __volatile__(";" : "+r"(x)) @@ -43,19 +44,22 @@ const struct machine_desc *machine_desc; struct task_struct *_current_task[NR_CPUS]; /* For stack switching */ -struct cpuinfo_arc cpuinfo_arc700[NR_CPUS]; +struct cpuinfo_arc { + int arcver; + unsigned int t0:1, t1:1; + struct { + unsigned long base; + unsigned int sz; + } iccm, dccm; +}; + +#ifdef CONFIG_ISA_ARCV2 -static const struct id_to_str arc_legacy_rel[] = { +static const struct id_to_str arc_hs_rel[] = { /* ID.ARCVER, Release */ -#ifdef CONFIG_ISA_ARCOMPACT - { 0x34, "R4.10"}, - { 0x35, "R4.11"}, -#else { 0x51, "R2.0" }, { 0x52, "R2.1" }, { 0x53, "R3.0" }, -#endif - { 0x00, NULL } }; static const struct id_to_str arc_hs_ver54_rel[] = { @@ -66,323 +70,296 @@ static const struct id_to_str arc_hs_ver54_rel[] = { { 3, "R4.00a"}, { 0xFF, NULL } }; +#endif -static void read_decode_ccm_bcr(struct cpuinfo_arc *cpu) +static int +arcompact_mumbojumbo(int c, struct cpuinfo_arc *info, char *buf, int len) { - if (is_isa_arcompact()) { - struct bcr_iccm_arcompact iccm; - struct bcr_dccm_arcompact dccm; + int n = 0; +#ifdef CONFIG_ISA_ARCOMPACT + char *cpu_nm, *isa_nm = "ARCompact"; + struct bcr_fp_arcompact fpu_sp, fpu_dp; + int atomic = 0, be, present; + int bpu_full, bpu_cache, bpu_pred; + struct bcr_bpu_arcompact bpu; + struct bcr_iccm_arcompact iccm; + struct bcr_dccm_arcompact dccm; + struct bcr_generic isa; - READ_BCR(ARC_REG_ICCM_BUILD, iccm); - if (iccm.ver) { - cpu->iccm.sz = 4096 << iccm.sz; /* 8K to 512K */ - cpu->iccm.base_addr = iccm.base << 16; - } + READ_BCR(ARC_REG_ISA_CFG_BCR, isa); - READ_BCR(ARC_REG_DCCM_BUILD, dccm); - if (dccm.ver) { - unsigned long base; - cpu->dccm.sz = 2048 << dccm.sz; /* 2K to 256K */ + if (!isa.ver) /* ISA BCR absent, use Kconfig info */ + atomic = IS_ENABLED(CONFIG_ARC_HAS_LLSC); + else { + /* ARC700_BUILD only has 2 bits of isa info */ + atomic = isa.info & 1; + } - base = read_aux_reg(ARC_REG_DCCM_BASE_BUILD); - cpu->dccm.base_addr = base & ~0xF; - } - } else { - struct bcr_iccm_arcv2 iccm; - struct bcr_dccm_arcv2 dccm; - unsigned long region; - - READ_BCR(ARC_REG_ICCM_BUILD, iccm); - if (iccm.ver) { - cpu->iccm.sz = 256 << iccm.sz00; /* 512B to 16M */ - if (iccm.sz00 == 0xF && iccm.sz01 > 0) - cpu->iccm.sz <<= iccm.sz01; - - region = read_aux_reg(ARC_REG_AUX_ICCM); - cpu->iccm.base_addr = region & 0xF0000000; - } + be = IS_ENABLED(CONFIG_CPU_BIG_ENDIAN); - READ_BCR(ARC_REG_DCCM_BUILD, dccm); - if (dccm.ver) { - cpu->dccm.sz = 256 << dccm.sz0; - if (dccm.sz0 == 0xF && dccm.sz1 > 0) - cpu->dccm.sz <<= dccm.sz1; + if (info->arcver < 0x34) + cpu_nm = "ARC750"; + else + cpu_nm = "ARC770"; - region = read_aux_reg(ARC_REG_AUX_DCCM); - cpu->dccm.base_addr = region & 0xF0000000; - } - } -} + n += scnprintf(buf + n, len - n, "processor [%d]\t: %s (%s ISA) %s%s%s\n", + c, cpu_nm, isa_nm, + IS_AVAIL2(atomic, "atomic ", CONFIG_ARC_HAS_LLSC), + IS_AVAIL1(be, "[Big-Endian]")); -static void decode_arc_core(struct cpuinfo_arc *cpu) -{ - struct bcr_uarch_build_arcv2 uarch; - const struct id_to_str *tbl; - - if (cpu->core.family < 0x54) { /* includes arc700 */ + READ_BCR(ARC_REG_FP_BCR, fpu_sp); + READ_BCR(ARC_REG_DPFP_BCR, fpu_dp); - for (tbl = &arc_legacy_rel[0]; tbl->id != 0; tbl++) { - if (cpu->core.family == tbl->id) { - cpu->release = tbl->str; - break; - } - } + if (fpu_sp.ver | fpu_dp.ver) + n += scnprintf(buf + n, len - n, "FPU\t\t: %s%s\n", + IS_AVAIL1(fpu_sp.ver, "SP "), + IS_AVAIL1(fpu_dp.ver, "DP ")); - if (is_isa_arcompact()) - cpu->name = "ARC700"; - else if (tbl->str) - cpu->name = "HS38"; - else - cpu->name = cpu->release = "Unknown"; + READ_BCR(ARC_REG_BPU_BCR, bpu); + bpu_full = bpu.fam ? 1 : 0; + bpu_cache = 256 << (bpu.ent - 1); + bpu_pred = 256 << (bpu.ent - 1); - return; + n += scnprintf(buf + n, len - n, + "BPU\t\t: %s%s match, cache:%d, Predict Table:%d\n", + IS_AVAIL1(bpu_full, "full"), + IS_AVAIL1(!bpu_full, "partial"), + bpu_cache, bpu_pred); + + READ_BCR(ARC_REG_ICCM_BUILD, iccm); + if (iccm.ver) { + info->iccm.sz = 4096 << iccm.sz; /* 8K to 512K */ + info->iccm.base = iccm.base << 16; } - /* - * Initial HS cores bumped AUX IDENTITY.ARCVER for each release until - * ARCVER 0x54 which introduced AUX MICRO_ARCH_BUILD and subsequent - * releases only update it. - */ - READ_BCR(ARC_REG_MICRO_ARCH_BCR, uarch); - - if (uarch.prod == 4) { - cpu->name = "HS48"; - cpu->extn.dual = 1; + READ_BCR(ARC_REG_DCCM_BUILD, dccm); + if (dccm.ver) { + unsigned long base; + info->dccm.sz = 2048 << dccm.sz; /* 2K to 256K */ - } else { - cpu->name = "HS38"; + base = read_aux_reg(ARC_REG_DCCM_BASE_BUILD); + info->dccm.base = base & ~0xF; } - for (tbl = &arc_hs_ver54_rel[0]; tbl->id != 0xFF; tbl++) { - if (uarch.maj == tbl->id) { - cpu->release = tbl->str; - break; - } - } + /* ARCompact ISA specific sanity checks */ + present = fpu_dp.ver; /* SP has no arch visible regs */ + CHK_OPT_STRICT(CONFIG_ARC_FPU_SAVE_RESTORE, present); +#endif + return n; + } -static void read_arc_build_cfg_regs(void) +static int arcv2_mumbojumbo(int c, struct cpuinfo_arc *info, char *buf, int len) { - struct bcr_timer timer; - struct bcr_generic bcr; - struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()]; + int n = 0; +#ifdef CONFIG_ISA_ARCV2 + const char *release, *cpu_nm, *isa_nm = "ARCv2"; + int dual_issue = 0, dual_enb = 0, mpy_opt, present; + int bpu_full, bpu_cache, bpu_pred, bpu_ret_stk; + char mpy_nm[16], lpb_nm[32]; struct bcr_isa_arcv2 isa; - struct bcr_actionpoint ap; - - FIX_PTR(cpu); + struct bcr_mpy mpy; + struct bcr_fp_arcv2 fpu; + struct bcr_bpu_arcv2 bpu; + struct bcr_lpb lpb; + struct bcr_iccm_arcv2 iccm; + struct bcr_dccm_arcv2 dccm; + struct bcr_erp erp; - READ_BCR(AUX_IDENTITY, cpu->core); - decode_arc_core(cpu); - - READ_BCR(ARC_REG_TIMERS_BCR, timer); - cpu->extn.timer0 = timer.t0; - cpu->extn.timer1 = timer.t1; - cpu->extn.rtc = timer.rtc; - - cpu->vec_base = read_aux_reg(AUX_INTR_VEC_BASE); + /* + * Initial HS cores bumped AUX IDENTITY.ARCVER for each release until + * ARCVER 0x54 which introduced AUX MICRO_ARCH_BUILD and subsequent + * releases only update it. + */ - READ_BCR(ARC_REG_MUL_BCR, cpu->extn_mpy); + cpu_nm = "HS38"; - /* Read CCM BCRs for boot reporting even if not enabled in Kconfig */ - read_decode_ccm_bcr(cpu); + if (info->arcver > 0x50 && info->arcver <= 0x53) { + release = arc_hs_rel[info->arcver - 0x51].str; + } else { + const struct id_to_str *tbl; + struct bcr_uarch_build uarch; - read_decode_mmu_bcr(); - read_decode_cache_bcr(); + READ_BCR(ARC_REG_MICRO_ARCH_BCR, uarch); - if (is_isa_arcompact()) { - struct bcr_fp_arcompact sp, dp; - struct bcr_bpu_arcompact bpu; - - READ_BCR(ARC_REG_FP_BCR, sp); - READ_BCR(ARC_REG_DPFP_BCR, dp); - cpu->extn.fpu_sp = sp.ver ? 1 : 0; - cpu->extn.fpu_dp = dp.ver ? 1 : 0; - - READ_BCR(ARC_REG_BPU_BCR, bpu); - cpu->bpu.ver = bpu.ver; - cpu->bpu.full = bpu.fam ? 1 : 0; - if (bpu.ent) { - cpu->bpu.num_cache = 256 << (bpu.ent - 1); - cpu->bpu.num_pred = 256 << (bpu.ent - 1); + for (tbl = &arc_hs_ver54_rel[0]; tbl->id != 0xFF; tbl++) { + if (uarch.maj == tbl->id) { + release = tbl->str; + break; + } } - } else { - struct bcr_fp_arcv2 spdp; - struct bcr_bpu_arcv2 bpu; - - READ_BCR(ARC_REG_FP_V2_BCR, spdp); - cpu->extn.fpu_sp = spdp.sp ? 1 : 0; - cpu->extn.fpu_dp = spdp.dp ? 1 : 0; - - READ_BCR(ARC_REG_BPU_BCR, bpu); - cpu->bpu.ver = bpu.ver; - cpu->bpu.full = bpu.ft; - cpu->bpu.num_cache = 256 << bpu.bce; - cpu->bpu.num_pred = 2048 << bpu.pte; - cpu->bpu.ret_stk = 4 << bpu.rse; - - /* if dual issue hardware, is it enabled ? */ - if (cpu->extn.dual) { + if (uarch.prod == 4) { unsigned int exec_ctrl; + cpu_nm = "HS48"; + dual_issue = 1; + /* if dual issue hardware, is it enabled ? */ READ_BCR(AUX_EXEC_CTRL, exec_ctrl); - cpu->extn.dual_enb = !(exec_ctrl & 1); + dual_enb = !(exec_ctrl & 1); } } - READ_BCR(ARC_REG_AP_BCR, ap); - if (ap.ver) { - cpu->extn.ap_num = 2 << ap.num; - cpu->extn.ap_full = !ap.min; - } - - READ_BCR(ARC_REG_SMART_BCR, bcr); - cpu->extn.smart = bcr.ver ? 1 : 0; - - READ_BCR(ARC_REG_RTT_BCR, bcr); - cpu->extn.rtt = bcr.ver ? 1 : 0; - READ_BCR(ARC_REG_ISA_CFG_BCR, isa); - /* some hacks for lack of feature BCR info in old ARC700 cores */ - if (is_isa_arcompact()) { - if (!isa.ver) /* ISA BCR absent, use Kconfig info */ - cpu->isa.atomic = IS_ENABLED(CONFIG_ARC_HAS_LLSC); - else { - /* ARC700_BUILD only has 2 bits of isa info */ - struct bcr_generic bcr = *(struct bcr_generic *)&isa; - cpu->isa.atomic = bcr.info & 1; - } - - cpu->isa.be = IS_ENABLED(CONFIG_CPU_BIG_ENDIAN); + n += scnprintf(buf + n, len - n, "processor [%d]\t: %s %s (%s ISA) %s%s%s\n", + c, cpu_nm, release, isa_nm, + IS_AVAIL1(isa.be, "[Big-Endian]"), + IS_AVAIL3(dual_issue, dual_enb, " Dual-Issue ")); + + READ_BCR(ARC_REG_MPY_BCR, mpy); + mpy_opt = 2; /* stock MPY/MPYH */ + if (mpy.dsp) /* OPT 7-9 */ + mpy_opt = mpy.dsp + 6; + + scnprintf(mpy_nm, 16, "mpy[opt %d] ", mpy_opt); + + READ_BCR(ARC_REG_FP_V2_BCR, fpu); + + n += scnprintf(buf + n, len - n, "ISA Extn\t: %s%s%s%s%s%s%s%s%s%s%s\n", + IS_AVAIL2(isa.atomic, "atomic ", CONFIG_ARC_HAS_LLSC), + IS_AVAIL2(isa.ldd, "ll64 ", CONFIG_ARC_HAS_LL64), + IS_AVAIL2(isa.unalign, "unalign ", CONFIG_ARC_USE_UNALIGNED_MEM_ACCESS), + IS_AVAIL1(mpy.ver, mpy_nm), + IS_AVAIL1(isa.div_rem, "div_rem "), + IS_AVAIL1((fpu.sp | fpu.dp), " FPU:"), + IS_AVAIL1(fpu.sp, " sp"), + IS_AVAIL1(fpu.dp, " dp")); + + READ_BCR(ARC_REG_BPU_BCR, bpu); + bpu_full = bpu.ft; + bpu_cache = 256 << bpu.bce; + bpu_pred = 2048 << bpu.pte; + bpu_ret_stk = 4 << bpu.rse; + + READ_BCR(ARC_REG_LPB_BUILD, lpb); + if (lpb.ver) { + unsigned int ctl; + ctl = read_aux_reg(ARC_REG_LPB_CTRL); + + scnprintf(lpb_nm, sizeof(lpb_nm), " Loop Buffer:%d %s", + lpb.entries, IS_DISABLED_RUN(!ctl)); + } - /* there's no direct way to distinguish 750 vs. 770 */ - if (unlikely(cpu->core.family < 0x34 || cpu->mmu.ver < 3)) - cpu->name = "ARC750"; - } else { - cpu->isa = isa; + n += scnprintf(buf + n, len - n, + "BPU\t\t: %s%s match, cache:%d, Predict Table:%d Return stk: %d%s\n", + IS_AVAIL1(bpu_full, "full"), + IS_AVAIL1(!bpu_full, "partial"), + bpu_cache, bpu_pred, bpu_ret_stk, + lpb_nm); + + READ_BCR(ARC_REG_ICCM_BUILD, iccm); + if (iccm.ver) { + unsigned long base; + info->iccm.sz = 256 << iccm.sz00; /* 512B to 16M */ + if (iccm.sz00 == 0xF && iccm.sz01 > 0) + info->iccm.sz <<= iccm.sz01; + base = read_aux_reg(ARC_REG_AUX_ICCM); + info->iccm.base = base & 0xF0000000; } -} -static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len) -{ - struct cpuinfo_arc *cpu = &cpuinfo_arc700[cpu_id]; - struct bcr_identity *core = &cpu->core; - char mpy_opt[16]; - int n = 0; + READ_BCR(ARC_REG_DCCM_BUILD, dccm); + if (dccm.ver) { + unsigned long base; + info->dccm.sz = 256 << dccm.sz0; + if (dccm.sz0 == 0xF && dccm.sz1 > 0) + info->dccm.sz <<= dccm.sz1; + base = read_aux_reg(ARC_REG_AUX_DCCM); + info->dccm.base = base & 0xF0000000; + } - FIX_PTR(cpu); + /* Error Protection: ECC/Parity */ + READ_BCR(ARC_REG_ERP_BUILD, erp); + if (erp.ver) { + struct ctl_erp ctl; + READ_BCR(ARC_REG_ERP_CTRL, ctl); + /* inverted bits: 0 means enabled */ + n += scnprintf(buf + n, len - n, "Extn [ECC]\t: %s%s%s%s%s%s\n", + IS_AVAIL3(erp.ic, !ctl.dpi, "IC "), + IS_AVAIL3(erp.dc, !ctl.dpd, "DC "), + IS_AVAIL3(erp.mmu, !ctl.mpd, "MMU ")); + } - n += scnprintf(buf + n, len - n, - "\nIDENTITY\t: ARCVER [%#02x] ARCNUM [%#02x] CHIPID [%#4x]\n", - core->family, core->cpu_id, core->chip_id); + /* ARCv2 ISA specific sanity checks */ + present = fpu.sp | fpu.dp | mpy.dsp; /* DSP and/or FPU */ + CHK_OPT_STRICT(CONFIG_ARC_HAS_ACCL_REGS, present); - n += scnprintf(buf + n, len - n, "processor [%d]\t: %s %s (%s ISA) %s%s%s\n", - cpu_id, cpu->name, cpu->release, - is_isa_arcompact() ? "ARCompact" : "ARCv2", - IS_AVAIL1(cpu->isa.be, "[Big-Endian]"), - IS_AVAIL3(cpu->extn.dual, cpu->extn.dual_enb, " Dual-Issue ")); + dsp_config_check(); +#endif + return n; +} - n += scnprintf(buf + n, len - n, "Timers\t\t: %s%s%s%s%s%s\nISA Extn\t: ", - IS_AVAIL1(cpu->extn.timer0, "Timer0 "), - IS_AVAIL1(cpu->extn.timer1, "Timer1 "), - IS_AVAIL2(cpu->extn.rtc, "RTC [UP 64-bit] ", CONFIG_ARC_TIMERS_64BIT), - IS_AVAIL2(cpu->extn.gfrc, "GFRC [SMP 64-bit] ", CONFIG_ARC_TIMERS_64BIT)); +static char *arc_cpu_mumbojumbo(int c, struct cpuinfo_arc *info, char *buf, int len) +{ + struct bcr_identity ident; + struct bcr_timer timer; + struct bcr_generic bcr; + struct mcip_bcr mp; + struct bcr_actionpoint ap; + unsigned long vec_base; + int ap_num, ap_full, smart, rtt, n; - if (cpu->extn_mpy.ver) { - if (is_isa_arcompact()) { - scnprintf(mpy_opt, 16, "mpy"); - } else { + memset(info, 0, sizeof(struct cpuinfo_arc)); - int opt = 2; /* stock MPY/MPYH */ + READ_BCR(AUX_IDENTITY, ident); + info->arcver = ident.family; - if (cpu->extn_mpy.dsp) /* OPT 7-9 */ - opt = cpu->extn_mpy.dsp + 6; + n = scnprintf(buf, len, + "\nIDENTITY\t: ARCVER [%#02x] ARCNUM [%#02x] CHIPID [%#4x]\n", + ident.family, ident.cpu_id, ident.chip_id); - scnprintf(mpy_opt, 16, "mpy[opt %d] ", opt); - } + if (is_isa_arcompact()) { + n += arcompact_mumbojumbo(c, info, buf + n, len - n); + } else if (is_isa_arcv2()){ + n += arcv2_mumbojumbo(c, info, buf + n, len - n); } - n += scnprintf(buf + n, len - n, "%s%s%s%s%s%s%s%s\n", - IS_AVAIL2(cpu->isa.atomic, "atomic ", CONFIG_ARC_HAS_LLSC), - IS_AVAIL2(cpu->isa.ldd, "ll64 ", CONFIG_ARC_HAS_LL64), - IS_AVAIL2(cpu->isa.unalign, "unalign ", CONFIG_ARC_USE_UNALIGNED_MEM_ACCESS), - IS_AVAIL1(cpu->extn_mpy.ver, mpy_opt), - IS_AVAIL1(cpu->isa.div_rem, "div_rem ")); + n += arc_mmu_mumbojumbo(c, buf + n, len - n); + n += arc_cache_mumbojumbo(c, buf + n, len - n); - if (cpu->bpu.ver) { - n += scnprintf(buf + n, len - n, - "BPU\t\t: %s%s match, cache:%d, Predict Table:%d Return stk: %d", - IS_AVAIL1(cpu->bpu.full, "full"), - IS_AVAIL1(!cpu->bpu.full, "partial"), - cpu->bpu.num_cache, cpu->bpu.num_pred, cpu->bpu.ret_stk); - - if (is_isa_arcv2()) { - struct bcr_lpb lpb; - - READ_BCR(ARC_REG_LPB_BUILD, lpb); - if (lpb.ver) { - unsigned int ctl; - ctl = read_aux_reg(ARC_REG_LPB_CTRL); - - n += scnprintf(buf + n, len - n, " Loop Buffer:%d %s", - lpb.entries, - IS_DISABLED_RUN(!ctl)); - } - } - n += scnprintf(buf + n, len - n, "\n"); - } + READ_BCR(ARC_REG_TIMERS_BCR, timer); + info->t0 = timer.t0; + info->t1 = timer.t1; - return buf; -} + READ_BCR(ARC_REG_MCIP_BCR, mp); + vec_base = read_aux_reg(AUX_INTR_VEC_BASE); -static char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len) -{ - int n = 0; - struct cpuinfo_arc *cpu = &cpuinfo_arc700[cpu_id]; + n += scnprintf(buf + n, len - n, + "Timers\t\t: %s%s%s%s%s%s\nVector Table\t: %#lx\n", + IS_AVAIL1(timer.t0, "Timer0 "), + IS_AVAIL1(timer.t1, "Timer1 "), + IS_AVAIL2(timer.rtc, "RTC [UP 64-bit] ", CONFIG_ARC_TIMERS_64BIT), + IS_AVAIL2(mp.gfrc, "GFRC [SMP 64-bit] ", CONFIG_ARC_TIMERS_64BIT), + vec_base); - FIX_PTR(cpu); + READ_BCR(ARC_REG_AP_BCR, ap); + if (ap.ver) { + ap_num = 2 << ap.num; + ap_full = !ap.min; + } - n += scnprintf(buf + n, len - n, "Vector Table\t: %#x\n", cpu->vec_base); + READ_BCR(ARC_REG_SMART_BCR, bcr); + smart = bcr.ver ? 1 : 0; - if (cpu->extn.fpu_sp || cpu->extn.fpu_dp) - n += scnprintf(buf + n, len - n, "FPU\t\t: %s%s\n", - IS_AVAIL1(cpu->extn.fpu_sp, "SP "), - IS_AVAIL1(cpu->extn.fpu_dp, "DP ")); + READ_BCR(ARC_REG_RTT_BCR, bcr); + rtt = bcr.ver ? 1 : 0; - if (cpu->extn.ap_num | cpu->extn.smart | cpu->extn.rtt) { + if (ap.ver | smart | rtt) { n += scnprintf(buf + n, len - n, "DEBUG\t\t: %s%s", - IS_AVAIL1(cpu->extn.smart, "smaRT "), - IS_AVAIL1(cpu->extn.rtt, "RTT ")); - if (cpu->extn.ap_num) { + IS_AVAIL1(smart, "smaRT "), + IS_AVAIL1(rtt, "RTT ")); + if (ap.ver) { n += scnprintf(buf + n, len - n, "ActionPoint %d/%s", - cpu->extn.ap_num, - cpu->extn.ap_full ? "full":"min"); + ap_num, + ap_full ? "full":"min"); } n += scnprintf(buf + n, len - n, "\n"); } - if (cpu->dccm.sz || cpu->iccm.sz) - n += scnprintf(buf + n, len - n, "Extn [CCM]\t: DCCM @ %x, %d KB / ICCM: @ %x, %d KB\n", - cpu->dccm.base_addr, TO_KB(cpu->dccm.sz), - cpu->iccm.base_addr, TO_KB(cpu->iccm.sz)); - - if (is_isa_arcv2()) { - - /* Error Protection: ECC/Parity */ - struct bcr_erp erp; - READ_BCR(ARC_REG_ERP_BUILD, erp); - - if (erp.ver) { - struct ctl_erp ctl; - READ_BCR(ARC_REG_ERP_CTRL, ctl); - - /* inverted bits: 0 means enabled */ - n += scnprintf(buf + n, len - n, "Extn [ECC]\t: %s%s%s%s%s%s\n", - IS_AVAIL3(erp.ic, !ctl.dpi, "IC "), - IS_AVAIL3(erp.dc, !ctl.dpd, "DC "), - IS_AVAIL3(erp.mmu, !ctl.mpd, "MMU ")); - } - } + if (info->dccm.sz || info->iccm.sz) + n += scnprintf(buf + n, len - n, + "Extn [CCM]\t: DCCM @ %lx, %d KB / ICCM: @ %lx, %d KB\n", + info->dccm.base, TO_KB(info->dccm.sz), + info->iccm.base, TO_KB(info->iccm.sz)); return buf; } @@ -401,15 +378,15 @@ void chk_opt_weak(char *opt_name, bool hw_exists, bool opt_ena) panic("Disable %s, hardware NOT present\n", opt_name); } -static void arc_chk_core_config(void) +/* + * ISA agnostic sanity checks + */ +static void arc_chk_core_config(struct cpuinfo_arc *info) { - struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()]; - int present = 0; - - if (!cpu->extn.timer0) + if (!info->t0) panic("Timer0 is not present!\n"); - if (!cpu->extn.timer1) + if (!info->t1) panic("Timer1 is not present!\n"); #ifdef CONFIG_ARC_HAS_DCCM @@ -417,35 +394,17 @@ static void arc_chk_core_config(void) * DCCM can be arbit placed in hardware. * Make sure it's placement/sz matches what Linux is built with */ - if ((unsigned int)__arc_dccm_base != cpu->dccm.base_addr) + if ((unsigned int)__arc_dccm_base != info->dccm.base) panic("Linux built with incorrect DCCM Base address\n"); - if (CONFIG_ARC_DCCM_SZ * SZ_1K != cpu->dccm.sz) + if (CONFIG_ARC_DCCM_SZ * SZ_1K != info->dccm.sz) panic("Linux built with incorrect DCCM Size\n"); #endif #ifdef CONFIG_ARC_HAS_ICCM - if (CONFIG_ARC_ICCM_SZ * SZ_1K != cpu->iccm.sz) + if (CONFIG_ARC_ICCM_SZ * SZ_1K != info->iccm.sz) panic("Linux built with incorrect ICCM Size\n"); #endif - - /* - * FP hardware/software config sanity - * -If hardware present, kernel needs to save/restore FPU state - * -If not, it will crash trying to save/restore the non-existant regs - */ - - if (is_isa_arcompact()) { - /* only DPDP checked since SP has no arch visible regs */ - present = cpu->extn.fpu_dp; - CHK_OPT_STRICT(CONFIG_ARC_FPU_SAVE_RESTORE, present); - } else { - /* Accumulator Low:High pair (r58:59) present if DSP MPY or FPU */ - present = cpu->extn_mpy.dsp | cpu->extn.fpu_sp | cpu->extn.fpu_dp; - CHK_OPT_STRICT(CONFIG_ARC_HAS_ACCL_REGS, present); - - dsp_config_check(); - } } /* @@ -456,21 +415,19 @@ static void arc_chk_core_config(void) void setup_processor(void) { + struct cpuinfo_arc info; + int c = smp_processor_id(); char str[512]; - int cpu_id = smp_processor_id(); - read_arc_build_cfg_regs(); - arc_init_IRQ(); + pr_info("%s", arc_cpu_mumbojumbo(c, &info, str, sizeof(str))); + pr_info("%s", arc_platform_smp_cpuinfo()); - pr_info("%s", arc_cpu_mumbojumbo(cpu_id, str, sizeof(str))); + arc_chk_core_config(&info); + arc_init_IRQ(); arc_mmu_init(); arc_cache_init(); - pr_info("%s", arc_extn_mumbojumbo(cpu_id, str, sizeof(str))); - pr_info("%s", arc_platform_smp_cpuinfo()); - - arc_chk_core_config(); } static inline bool uboot_arg_invalid(unsigned long addr) @@ -617,6 +574,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) char *str; int cpu_id = ptr_to_cpu(v); struct device *cpu_dev = get_cpu_device(cpu_id); + struct cpuinfo_arc info; struct clk *cpu_clk; unsigned long freq = 0; @@ -629,7 +587,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) if (!str) goto done; - seq_printf(m, arc_cpu_mumbojumbo(cpu_id, str, PAGE_SIZE)); + seq_printf(m, arc_cpu_mumbojumbo(cpu_id, &info, str, PAGE_SIZE)); cpu_clk = clk_get(cpu_dev, NULL); if (IS_ERR(cpu_clk)) { @@ -646,9 +604,6 @@ static int show_cpuinfo(struct seq_file *m, void *v) loops_per_jiffy / (500000 / HZ), (loops_per_jiffy / (5000 / HZ)) % 100); - seq_printf(m, arc_mmu_mumbojumbo(cpu_id, str, PAGE_SIZE)); - seq_printf(m, arc_cache_mumbojumbo(cpu_id, str, PAGE_SIZE)); - seq_printf(m, arc_extn_mumbojumbo(cpu_id, str, PAGE_SIZE)); seq_printf(m, arc_platform_smp_cpuinfo()); free_page((unsigned long)str); diff --git a/arch/arc/kernel/signal.c b/arch/arc/kernel/signal.c index 3c1590c27fae..0b3bb529d246 100644 --- a/arch/arc/kernel/signal.c +++ b/arch/arc/kernel/signal.c @@ -53,6 +53,7 @@ #include <linux/sched/task_stack.h> #include <asm/ucontext.h> +#include <asm/entry.h> struct rt_sigframe { struct siginfo info; diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c index 409cfa4675b4..8d9b188caa27 100644 --- a/arch/arc/kernel/smp.c +++ b/arch/arc/kernel/smp.c @@ -23,9 +23,10 @@ #include <linux/export.h> #include <linux/of_fdt.h> -#include <asm/processor.h> -#include <asm/setup.h> #include <asm/mach_desc.h> +#include <asm/setup.h> +#include <asm/smp.h> +#include <asm/processor.h> #ifndef CONFIG_ARC_HAS_LLSC arch_spinlock_t smp_atomic_ops_lock = __ARCH_SPIN_LOCK_UNLOCKED; @@ -351,7 +352,7 @@ static inline int __do_IPI(unsigned long msg) * arch-common ISR to handle for inter-processor interrupts * Has hooks for platform specific IPI */ -irqreturn_t do_IPI(int irq, void *dev_id) +static irqreturn_t do_IPI(int irq, void *dev_id) { unsigned long pending; unsigned long __maybe_unused copy; diff --git a/arch/arc/kernel/stacktrace.c b/arch/arc/kernel/stacktrace.c index 5372dc04e784..ea99c066ef25 100644 --- a/arch/arc/kernel/stacktrace.c +++ b/arch/arc/kernel/stacktrace.c @@ -29,6 +29,7 @@ #include <asm/arcregs.h> #include <asm/unwind.h> +#include <asm/stacktrace.h> #include <asm/switch_to.h> /*------------------------------------------------------------------------- diff --git a/arch/arc/kernel/traps.c b/arch/arc/kernel/traps.c index 6b83e3f2b41c..9b9570b79362 100644 --- a/arch/arc/kernel/traps.c +++ b/arch/arc/kernel/traps.c @@ -16,6 +16,7 @@ #include <linux/ptrace.h> #include <linux/kprobes.h> #include <linux/kgdb.h> +#include <asm/entry.h> #include <asm/setup.h> #include <asm/unaligned.h> #include <asm/kprobes.h> @@ -109,9 +110,7 @@ void do_machine_check_fault(unsigned long address, struct pt_regs *regs) */ void do_non_swi_trap(unsigned long address, struct pt_regs *regs) { - unsigned int param = regs->ecr_param; - - switch (param) { + switch (regs->ecr.param) { case 1: trap_is_brkpt(address, regs); break; diff --git a/arch/arc/kernel/troubleshoot.c b/arch/arc/kernel/troubleshoot.c index 7654c2e42dc0..d5b3ed2c58f5 100644 --- a/arch/arc/kernel/troubleshoot.c +++ b/arch/arc/kernel/troubleshoot.c @@ -115,8 +115,8 @@ static void show_ecr_verbose(struct pt_regs *regs) /* For Data fault, this is data address not instruction addr */ address = current->thread.fault_address; - vec = regs->ecr_vec; - cause_code = regs->ecr_cause; + vec = regs->ecr.vec; + cause_code = regs->ecr.cause; /* For DTLB Miss or ProtV, display the memory involved too */ if (vec == ECR_V_DTLB_MISS) { @@ -154,7 +154,7 @@ static void show_ecr_verbose(struct pt_regs *regs) pr_cont("Misaligned r/w from 0x%08lx\n", address); #endif } else if (vec == ECR_V_TRAP) { - if (regs->ecr_param == 5) + if (regs->ecr.param == 5) pr_cont("gcc generated __builtin_trap\n"); } else { pr_cont("Check Programmer's Manual\n"); @@ -184,9 +184,10 @@ void show_regs(struct pt_regs *regs) if (user_mode(regs)) show_faulting_vma(regs->ret); /* faulting code, not data */ - pr_info("ECR: 0x%08lx EFA: 0x%08lx ERET: 0x%08lx\nSTAT: 0x%08lx", - regs->event, current->thread.fault_address, regs->ret, - regs->status32); + pr_info("ECR: 0x%08lx EFA: 0x%08lx ERET: 0x%08lx\n", + regs->ecr.full, current->thread.fault_address, regs->ret); + + pr_info("STAT32: 0x%08lx", regs->status32); #define STS_BIT(r, bit) r->status32 & STATUS_##bit##_MASK ? #bit" " : "" diff --git a/arch/arc/lib/memset-archs.S b/arch/arc/lib/memset-archs.S index d2e09fece5bc..d0a5cec4cdca 100644 --- a/arch/arc/lib/memset-archs.S +++ b/arch/arc/lib/memset-archs.S @@ -36,12 +36,13 @@ #endif ENTRY_CFI(memset) - PREFETCHW_INSTR r0, 0 ; Prefetch the first write location mov.f 0, r2 ;;; if size is zero jz.d [blink] mov r3, r0 ; don't clobber ret val + PREFETCHW_INSTR r0, 0 ; Prefetch the first write location + ;;; if length < 8 brls.d.nt r2, 8, .Lsmallchunk mov.f lp_count,r2 diff --git a/arch/arc/mm/cache.c b/arch/arc/mm/cache.c index 3c16ee942a5c..f7e05c146637 100644 --- a/arch/arc/mm/cache.c +++ b/arch/arc/mm/cache.c @@ -28,6 +28,10 @@ int slc_enable = 1, ioc_enable = 1; unsigned long perip_base = ARC_UNCACHED_ADDR_SPACE; /* legacy value for boot */ unsigned long perip_end = 0xFFFFFFFF; /* legacy value */ +static struct cpuinfo_arc_cache { + unsigned int sz_k, line_len, colors; +} ic_info, dc_info, slc_info; + void (*_cache_line_loop_ic_fn)(phys_addr_t paddr, unsigned long vaddr, unsigned long sz, const int op, const int full_page); @@ -35,78 +39,24 @@ void (*__dma_cache_wback_inv)(phys_addr_t start, unsigned long sz); void (*__dma_cache_inv)(phys_addr_t start, unsigned long sz); void (*__dma_cache_wback)(phys_addr_t start, unsigned long sz); -char *arc_cache_mumbojumbo(int c, char *buf, int len) -{ - int n = 0; - struct cpuinfo_arc_cache *p; - -#define PR_CACHE(p, cfg, str) \ - if (!(p)->line_len) \ - n += scnprintf(buf + n, len - n, str"\t\t: N/A\n"); \ - else \ - n += scnprintf(buf + n, len - n, \ - str"\t\t: %uK, %dway/set, %uB Line, %s%s%s\n", \ - (p)->sz_k, (p)->assoc, (p)->line_len, \ - (p)->vipt ? "VIPT" : "PIPT", \ - (p)->alias ? " aliasing" : "", \ - IS_USED_CFG(cfg)); - - PR_CACHE(&cpuinfo_arc700[c].icache, CONFIG_ARC_HAS_ICACHE, "I-Cache"); - PR_CACHE(&cpuinfo_arc700[c].dcache, CONFIG_ARC_HAS_DCACHE, "D-Cache"); - - p = &cpuinfo_arc700[c].slc; - if (p->line_len) - n += scnprintf(buf + n, len - n, - "SLC\t\t: %uK, %uB Line%s\n", - p->sz_k, p->line_len, IS_USED_RUN(slc_enable)); - - n += scnprintf(buf + n, len - n, "Peripherals\t: %#lx%s%s\n", - perip_base, - IS_AVAIL3(ioc_exists, ioc_enable, ", IO-Coherency (per-device) ")); - - return buf; -} - -/* - * Read the Cache Build Confuration Registers, Decode them and save into - * the cpuinfo structure for later use. - * No Validation done here, simply read/convert the BCRs - */ -static void read_decode_cache_bcr_arcv2(int cpu) +static int read_decode_cache_bcr_arcv2(int c, char *buf, int len) { - struct cpuinfo_arc_cache *p_slc = &cpuinfo_arc700[cpu].slc; + struct cpuinfo_arc_cache *p_slc = &slc_info; + struct bcr_identity ident; struct bcr_generic sbcr; - - struct bcr_slc_cfg { -#ifdef CONFIG_CPU_BIG_ENDIAN - unsigned int pad:24, way:2, lsz:2, sz:4; -#else - unsigned int sz:4, lsz:2, way:2, pad:24; -#endif - } slc_cfg; - - struct bcr_clust_cfg { -#ifdef CONFIG_CPU_BIG_ENDIAN - unsigned int pad:7, c:1, num_entries:8, num_cores:8, ver:8; -#else - unsigned int ver:8, num_cores:8, num_entries:8, c:1, pad:7; -#endif - } cbcr; - - struct bcr_volatile { -#ifdef CONFIG_CPU_BIG_ENDIAN - unsigned int start:4, limit:4, pad:22, order:1, disable:1; -#else - unsigned int disable:1, order:1, pad:22, limit:4, start:4; -#endif - } vol; - + struct bcr_clust_cfg cbcr; + struct bcr_volatile vol; + int n = 0; READ_BCR(ARC_REG_SLC_BCR, sbcr); if (sbcr.ver) { + struct bcr_slc_cfg slc_cfg; READ_BCR(ARC_REG_SLC_CFG, slc_cfg); p_slc->sz_k = 128 << slc_cfg.sz; l2_line_sz = p_slc->line_len = (slc_cfg.lsz == 0) ? 128 : 64; + n += scnprintf(buf + n, len - n, + "SLC\t\t: %uK, %uB Line%s\n", + p_slc->sz_k, p_slc->line_len, IS_USED_RUN(slc_enable)); } READ_BCR(ARC_REG_CLUSTER_BCR, cbcr); @@ -129,70 +79,83 @@ static void read_decode_cache_bcr_arcv2(int cpu) ioc_enable = 0; } + READ_BCR(AUX_IDENTITY, ident); + /* HS 2.0 didn't have AUX_VOL */ - if (cpuinfo_arc700[cpu].core.family > 0x51) { + if (ident.family > 0x51) { READ_BCR(AUX_VOL, vol); perip_base = vol.start << 28; /* HS 3.0 has limit and strict-ordering fields */ - if (cpuinfo_arc700[cpu].core.family > 0x52) + if (ident.family > 0x52) perip_end = (vol.limit << 28) - 1; } + + n += scnprintf(buf + n, len - n, "Peripherals\t: %#lx%s%s\n", + perip_base, + IS_AVAIL3(ioc_exists, ioc_enable, ", IO-Coherency (per-device) ")); + + return n; } -void read_decode_cache_bcr(void) +int arc_cache_mumbojumbo(int c, char *buf, int len) { - struct cpuinfo_arc_cache *p_ic, *p_dc; - unsigned int cpu = smp_processor_id(); - struct bcr_cache { -#ifdef CONFIG_CPU_BIG_ENDIAN - unsigned int pad:12, line_len:4, sz:4, config:4, ver:8; -#else - unsigned int ver:8, config:4, sz:4, line_len:4, pad:12; -#endif - } ibcr, dbcr; + struct cpuinfo_arc_cache *p_ic = &ic_info, *p_dc = &dc_info; + struct bcr_cache ibcr, dbcr; + int vipt, assoc; + int n = 0; - p_ic = &cpuinfo_arc700[cpu].icache; READ_BCR(ARC_REG_IC_BCR, ibcr); - if (!ibcr.ver) goto dc_chk; - if (ibcr.ver <= 3) { + if (is_isa_arcompact() && (ibcr.ver <= 3)) { BUG_ON(ibcr.config != 3); - p_ic->assoc = 2; /* Fixed to 2w set assoc */ - } else if (ibcr.ver >= 4) { - p_ic->assoc = 1 << ibcr.config; /* 1,2,4,8 */ + assoc = 2; /* Fixed to 2w set assoc */ + } else if (is_isa_arcv2() && (ibcr.ver >= 4)) { + assoc = 1 << ibcr.config; /* 1,2,4,8 */ } p_ic->line_len = 8 << ibcr.line_len; p_ic->sz_k = 1 << (ibcr.sz - 1); - p_ic->vipt = 1; - p_ic->alias = p_ic->sz_k/p_ic->assoc/TO_KB(PAGE_SIZE) > 1; + p_ic->colors = p_ic->sz_k/assoc/TO_KB(PAGE_SIZE); + + n += scnprintf(buf + n, len - n, + "I-Cache\t\t: %uK, %dway/set, %uB Line, VIPT%s%s\n", + p_ic->sz_k, assoc, p_ic->line_len, + p_ic->colors > 1 ? " aliasing" : "", + IS_USED_CFG(CONFIG_ARC_HAS_ICACHE)); dc_chk: - p_dc = &cpuinfo_arc700[cpu].dcache; READ_BCR(ARC_REG_DC_BCR, dbcr); - if (!dbcr.ver) goto slc_chk; - if (dbcr.ver <= 3) { + if (is_isa_arcompact() && (dbcr.ver <= 3)) { BUG_ON(dbcr.config != 2); - p_dc->assoc = 4; /* Fixed to 4w set assoc */ - p_dc->vipt = 1; - p_dc->alias = p_dc->sz_k/p_dc->assoc/TO_KB(PAGE_SIZE) > 1; - } else if (dbcr.ver >= 4) { - p_dc->assoc = 1 << dbcr.config; /* 1,2,4,8 */ - p_dc->vipt = 0; - p_dc->alias = 0; /* PIPT so can't VIPT alias */ + vipt = 1; + assoc = 4; /* Fixed to 4w set assoc */ + p_dc->colors = p_dc->sz_k/assoc/TO_KB(PAGE_SIZE); + } else if (is_isa_arcv2() && (dbcr.ver >= 4)) { + vipt = 0; + assoc = 1 << dbcr.config; /* 1,2,4,8 */ + p_dc->colors = 1; /* PIPT so can't VIPT alias */ } p_dc->line_len = 16 << dbcr.line_len; p_dc->sz_k = 1 << (dbcr.sz - 1); + n += scnprintf(buf + n, len - n, + "D-Cache\t\t: %uK, %dway/set, %uB Line, %s%s%s\n", + p_dc->sz_k, assoc, p_dc->line_len, + vipt ? "VIPT" : "PIPT", + p_dc->colors > 1 ? " aliasing" : "", + IS_USED_CFG(CONFIG_ARC_HAS_DCACHE)); + slc_chk: if (is_isa_arcv2()) - read_decode_cache_bcr_arcv2(cpu); + n += read_decode_cache_bcr_arcv2(c, buf + n, len - n); + + return n; } /* @@ -581,7 +544,7 @@ static void __ic_line_inv_vaddr(phys_addr_t paddr, unsigned long vaddr, #endif /* CONFIG_ARC_HAS_ICACHE */ -noinline void slc_op_rgn(phys_addr_t paddr, unsigned long sz, const int op) +static noinline void slc_op_rgn(phys_addr_t paddr, unsigned long sz, const int op) { #ifdef CONFIG_ISA_ARCV2 /* @@ -644,7 +607,7 @@ noinline void slc_op_rgn(phys_addr_t paddr, unsigned long sz, const int op) #endif } -noinline void slc_op_line(phys_addr_t paddr, unsigned long sz, const int op) +static __maybe_unused noinline void slc_op_line(phys_addr_t paddr, unsigned long sz, const int op) { #ifdef CONFIG_ISA_ARCV2 /* @@ -1082,7 +1045,7 @@ SYSCALL_DEFINE3(cacheflush, uint32_t, start, uint32_t, sz, uint32_t, flags) * 3. All Caches need to be disabled when setting up IOC to elide any in-flight * Coherency transactions */ -noinline void __init arc_ioc_setup(void) +static noinline void __init arc_ioc_setup(void) { unsigned int ioc_base, mem_sz; @@ -1144,12 +1107,10 @@ noinline void __init arc_ioc_setup(void) * one core suffices for all * - IOC setup / dma callbacks only need to be done once */ -void __init arc_cache_init_master(void) +static noinline void __init arc_cache_init_master(void) { - unsigned int __maybe_unused cpu = smp_processor_id(); - if (IS_ENABLED(CONFIG_ARC_HAS_ICACHE)) { - struct cpuinfo_arc_cache *ic = &cpuinfo_arc700[cpu].icache; + struct cpuinfo_arc_cache *ic = &ic_info; if (!ic->line_len) panic("cache support enabled but non-existent cache\n"); @@ -1162,14 +1123,14 @@ void __init arc_cache_init_master(void) * In MMU v4 (HS38x) the aliasing icache config uses IVIL/PTAG * pair to provide vaddr/paddr respectively, just as in MMU v3 */ - if (is_isa_arcv2() && ic->alias) + if (is_isa_arcv2() && ic->colors > 1) _cache_line_loop_ic_fn = __cache_line_loop_v3; else _cache_line_loop_ic_fn = __cache_line_loop; } if (IS_ENABLED(CONFIG_ARC_HAS_DCACHE)) { - struct cpuinfo_arc_cache *dc = &cpuinfo_arc700[cpu].dcache; + struct cpuinfo_arc_cache *dc = &dc_info; if (!dc->line_len) panic("cache support enabled but non-existent cache\n"); @@ -1181,14 +1142,13 @@ void __init arc_cache_init_master(void) /* check for D-Cache aliasing on ARCompact: ARCv2 has PIPT */ if (is_isa_arcompact()) { int handled = IS_ENABLED(CONFIG_ARC_CACHE_VIPT_ALIASING); - int num_colors = dc->sz_k/dc->assoc/TO_KB(PAGE_SIZE); - if (dc->alias) { + if (dc->colors > 1) { if (!handled) panic("Enable CONFIG_ARC_CACHE_VIPT_ALIASING\n"); - if (CACHE_COLORS_NUM != num_colors) + if (CACHE_COLORS_NUM != dc->colors) panic("CACHE_COLORS_NUM not optimized for config\n"); - } else if (!dc->alias && handled) { + } else if (handled && dc->colors == 1) { panic("Disable CONFIG_ARC_CACHE_VIPT_ALIASING\n"); } } @@ -1231,9 +1191,6 @@ void __init arc_cache_init_master(void) void __ref arc_cache_init(void) { unsigned int __maybe_unused cpu = smp_processor_id(); - char str[256]; - - pr_info("%s", arc_cache_mumbojumbo(0, str, sizeof(str))); if (!cpu) arc_cache_init_master(); diff --git a/arch/arc/mm/extable.c b/arch/arc/mm/extable.c index 4e14c4244ea2..88fa3a4d4906 100644 --- a/arch/arc/mm/extable.c +++ b/arch/arc/mm/extable.c @@ -22,14 +22,3 @@ int fixup_exception(struct pt_regs *regs) return 0; } - -#ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE - -unsigned long arc_clear_user_noinline(void __user *to, - unsigned long n) -{ - return __arc_clear_user(to, n); -} -EXPORT_SYMBOL(arc_clear_user_noinline); - -#endif diff --git a/arch/arc/mm/fault.c b/arch/arc/mm/fault.c index f59e722d147f..95119a5e7761 100644 --- a/arch/arc/mm/fault.c +++ b/arch/arc/mm/fault.c @@ -13,6 +13,7 @@ #include <linux/kdebug.h> #include <linux/perf_event.h> #include <linux/mm_types.h> +#include <asm/entry.h> #include <asm/mmu.h> /* @@ -99,10 +100,10 @@ void do_page_fault(unsigned long address, struct pt_regs *regs) if (faulthandler_disabled() || !mm) goto no_context; - if (regs->ecr_cause & ECR_C_PROTV_STORE) /* ST/EX */ + if (regs->ecr.cause & ECR_C_PROTV_STORE) /* ST/EX */ write = 1; - else if ((regs->ecr_vec == ECR_V_PROTV) && - (regs->ecr_cause == ECR_C_PROTV_INST_FETCH)) + else if ((regs->ecr.vec == ECR_V_PROTV) && + (regs->ecr.cause == ECR_C_PROTV_INST_FETCH)) exec = 1; flags = FAULT_FLAG_DEFAULT; diff --git a/arch/arc/mm/init.c b/arch/arc/mm/init.c index 9f64d729c9f8..6a71b23f1383 100644 --- a/arch/arc/mm/init.c +++ b/arch/arc/mm/init.c @@ -15,6 +15,7 @@ #include <linux/highmem.h> #include <asm/page.h> #include <asm/sections.h> +#include <asm/setup.h> #include <asm/arcregs.h> pgd_t swapper_pg_dir[PTRS_PER_PGD] __aligned(PAGE_SIZE); diff --git a/arch/arc/mm/tlb.c b/arch/arc/mm/tlb.c index 6f40f37e6550..e536b2dcd4b0 100644 --- a/arch/arc/mm/tlb.c +++ b/arch/arc/mm/tlb.c @@ -18,7 +18,9 @@ /* A copy of the ASID from the PID reg is kept in asid_cache */ DEFINE_PER_CPU(unsigned int, asid_cache) = MM_CTXT_FIRST_CYCLE; -static int __read_mostly pae_exists; +static struct cpuinfo_arc_mmu { + unsigned int ver, pg_sz_k, s_pg_sz_m, pae, sets, ways; +} mmuinfo; /* * Utility Routine to erase a J-TLB entry @@ -131,7 +133,7 @@ static void tlb_entry_insert(unsigned int pd0, phys_addr_t pd1) noinline void local_flush_tlb_all(void) { - struct cpuinfo_arc_mmu *mmu = &cpuinfo_arc700[smp_processor_id()].mmu; + struct cpuinfo_arc_mmu *mmu = &mmuinfo; unsigned long flags; unsigned int entry; int num_tlb = mmu->sets * mmu->ways; @@ -389,7 +391,7 @@ void flush_tlb_kernel_range(unsigned long start, unsigned long end) /* * Routine to create a TLB entry */ -void create_tlb(struct vm_area_struct *vma, unsigned long vaddr, pte_t *ptep) +static void create_tlb(struct vm_area_struct *vma, unsigned long vaddr, pte_t *ptep) { unsigned long flags; unsigned int asid_or_sasid, rwx; @@ -564,89 +566,64 @@ void local_flush_pmd_tlb_range(struct vm_area_struct *vma, unsigned long start, * the cpuinfo structure for later use. * No Validation is done here, simply read/convert the BCRs */ -void read_decode_mmu_bcr(void) +int arc_mmu_mumbojumbo(int c, char *buf, int len) { - struct cpuinfo_arc_mmu *mmu = &cpuinfo_arc700[smp_processor_id()].mmu; - unsigned int tmp; - struct bcr_mmu_3 { -#ifdef CONFIG_CPU_BIG_ENDIAN - unsigned int ver:8, ways:4, sets:4, res:3, sasid:1, pg_sz:4, - u_itlb:4, u_dtlb:4; -#else - unsigned int u_dtlb:4, u_itlb:4, pg_sz:4, sasid:1, res:3, sets:4, - ways:4, ver:8; -#endif - } *mmu3; - - struct bcr_mmu_4 { -#ifdef CONFIG_CPU_BIG_ENDIAN - unsigned int ver:8, sasid:1, sz1:4, sz0:4, res:2, pae:1, - n_ways:2, n_entry:2, n_super:2, u_itlb:3, u_dtlb:3; -#else - /* DTLB ITLB JES JE JA */ - unsigned int u_dtlb:3, u_itlb:3, n_super:2, n_entry:2, n_ways:2, - pae:1, res:2, sz0:4, sz1:4, sasid:1, ver:8; -#endif - } *mmu4; + struct cpuinfo_arc_mmu *mmu = &mmuinfo; + unsigned int bcr, u_dtlb, u_itlb, sasid; + struct bcr_mmu_3 *mmu3; + struct bcr_mmu_4 *mmu4; + char super_pg[64] = ""; + int n = 0; - tmp = read_aux_reg(ARC_REG_MMU_BCR); - mmu->ver = (tmp >> 24); + bcr = read_aux_reg(ARC_REG_MMU_BCR); + mmu->ver = (bcr >> 24); if (is_isa_arcompact() && mmu->ver == 3) { - mmu3 = (struct bcr_mmu_3 *)&tmp; + mmu3 = (struct bcr_mmu_3 *)&bcr; mmu->pg_sz_k = 1 << (mmu3->pg_sz - 1); mmu->sets = 1 << mmu3->sets; mmu->ways = 1 << mmu3->ways; - mmu->u_dtlb = mmu3->u_dtlb; - mmu->u_itlb = mmu3->u_itlb; - mmu->sasid = mmu3->sasid; + u_dtlb = mmu3->u_dtlb; + u_itlb = mmu3->u_itlb; + sasid = mmu3->sasid; } else { - mmu4 = (struct bcr_mmu_4 *)&tmp; + mmu4 = (struct bcr_mmu_4 *)&bcr; mmu->pg_sz_k = 1 << (mmu4->sz0 - 1); mmu->s_pg_sz_m = 1 << (mmu4->sz1 - 11); mmu->sets = 64 << mmu4->n_entry; mmu->ways = mmu4->n_ways * 2; - mmu->u_dtlb = mmu4->u_dtlb * 4; - mmu->u_itlb = mmu4->u_itlb * 4; - mmu->sasid = mmu4->sasid; - pae_exists = mmu->pae = mmu4->pae; + u_dtlb = mmu4->u_dtlb * 4; + u_itlb = mmu4->u_itlb * 4; + sasid = mmu4->sasid; + mmu->pae = mmu4->pae; } -} -char *arc_mmu_mumbojumbo(int cpu_id, char *buf, int len) -{ - int n = 0; - struct cpuinfo_arc_mmu *p_mmu = &cpuinfo_arc700[cpu_id].mmu; - char super_pg[64] = ""; - - if (p_mmu->s_pg_sz_m) - scnprintf(super_pg, 64, "%dM Super Page %s", - p_mmu->s_pg_sz_m, - IS_USED_CFG(CONFIG_TRANSPARENT_HUGEPAGE)); + if (mmu->s_pg_sz_m) + scnprintf(super_pg, 64, "/%dM%s", + mmu->s_pg_sz_m, + IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) ? " (THP enabled)":""); n += scnprintf(buf + n, len - n, - "MMU [v%x]\t: %dk PAGE, %s, swalk %d lvl, JTLB %d (%dx%d), uDTLB %d, uITLB %d%s%s\n", - p_mmu->ver, p_mmu->pg_sz_k, super_pg, CONFIG_PGTABLE_LEVELS, - p_mmu->sets * p_mmu->ways, p_mmu->sets, p_mmu->ways, - p_mmu->u_dtlb, p_mmu->u_itlb, - IS_AVAIL2(p_mmu->pae, ", PAE40 ", CONFIG_ARC_HAS_PAE40)); - - return buf; + "MMU [v%x]\t: %dk%s, swalk %d lvl, JTLB %dx%d, uDTLB %d, uITLB %d%s%s%s\n", + mmu->ver, mmu->pg_sz_k, super_pg, CONFIG_PGTABLE_LEVELS, + mmu->sets, mmu->ways, + u_dtlb, u_itlb, + IS_AVAIL1(sasid, ", SASID"), + IS_AVAIL2(mmu->pae, ", PAE40 ", CONFIG_ARC_HAS_PAE40)); + + return n; } int pae40_exist_but_not_enab(void) { - return pae_exists && !is_pae40_enabled(); + return mmuinfo.pae && !is_pae40_enabled(); } void arc_mmu_init(void) { - struct cpuinfo_arc_mmu *mmu = &cpuinfo_arc700[smp_processor_id()].mmu; - char str[256]; + struct cpuinfo_arc_mmu *mmu = &mmuinfo; int compat = 0; - pr_info("%s", arc_mmu_mumbojumbo(0, str, sizeof(str))); - /* * Can't be done in processor.h due to header include dependencies */ @@ -723,7 +700,7 @@ volatile int dup_pd_silent; /* Be silent abt it or complain (default) */ void do_tlb_overlap_fault(unsigned long cause, unsigned long address, struct pt_regs *regs) { - struct cpuinfo_arc_mmu *mmu = &cpuinfo_arc700[smp_processor_id()].mmu; + struct cpuinfo_arc_mmu *mmu = &mmuinfo; unsigned long flags; int set, n_ways = mmu->ways; diff --git a/arch/arc/plat-axs10x/axs10x.c b/arch/arc/plat-axs10x/axs10x.c index b821df7b0089..1feb990a56bc 100644 --- a/arch/arc/plat-axs10x/axs10x.c +++ b/arch/arc/plat-axs10x/axs10x.c @@ -6,7 +6,6 @@ */ #include <linux/of_fdt.h> -#include <linux/of_platform.h> #include <linux/libfdt.h> #include <asm/asm-offsets.h> diff --git a/arch/arm/configs/dram_0x00000000.config b/arch/arm/configs/dram_0x00000000.config index db96dcb420ce..8803a0f58343 100644 --- a/arch/arm/configs/dram_0x00000000.config +++ b/arch/arm/configs/dram_0x00000000.config @@ -1 +1,2 @@ +# Help: DRAM base at 0x00000000 CONFIG_DRAM_BASE=0x00000000 diff --git a/arch/arm/configs/dram_0xc0000000.config b/arch/arm/configs/dram_0xc0000000.config index 343d5333d973..aab8f864686b 100644 --- a/arch/arm/configs/dram_0xc0000000.config +++ b/arch/arm/configs/dram_0xc0000000.config @@ -1 +1,2 @@ +# Help: DRAM base at 0xc0000000 CONFIG_DRAM_BASE=0xc0000000 diff --git a/arch/arm/configs/dram_0xd0000000.config b/arch/arm/configs/dram_0xd0000000.config index 61ba7045f8a1..4aabce4ea3d4 100644 --- a/arch/arm/configs/dram_0xd0000000.config +++ b/arch/arm/configs/dram_0xd0000000.config @@ -1 +1,2 @@ +# Help: DRAM base at 0xd0000000 CONFIG_DRAM_BASE=0xd0000000 diff --git a/arch/arm/configs/lpae.config b/arch/arm/configs/lpae.config index a6d6f7ab3c01..1ab94da8345d 100644 --- a/arch/arm/configs/lpae.config +++ b/arch/arm/configs/lpae.config @@ -1,2 +1,3 @@ +# Help: Enable Large Physical Address Extension mode CONFIG_ARM_LPAE=y CONFIG_VMSPLIT_2G=y diff --git a/arch/arm64/configs/virt.config b/arch/arm64/configs/virt.config index 6865d54e68f8..c47c36f8f67b 100644 --- a/arch/arm64/configs/virt.config +++ b/arch/arm64/configs/virt.config @@ -1,3 +1,4 @@ +# Help: Virtualization guest # # Base options for platforms # diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild index 33733245f42b..aefae2efde9f 100644 --- a/arch/ia64/include/asm/Kbuild +++ b/arch/ia64/include/asm/Kbuild @@ -1,7 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 generated-y += syscall_table.h generic-y += agp.h -generic-y += export.h generic-y += kvm_para.h generic-y += mcs_spinlock.h generic-y += vtime.h diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index 5eba3fb2e311..ac06d44b9b27 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S @@ -37,7 +37,7 @@ * pNonSys: !pSys */ - +#include <linux/export.h> #include <linux/pgtable.h> #include <asm/asmmacro.h> #include <asm/cache.h> @@ -49,7 +49,6 @@ #include <asm/thread_info.h> #include <asm/unistd.h> #include <asm/ftrace.h> -#include <asm/export.h> #include "minstate.h" diff --git a/arch/ia64/kernel/esi_stub.S b/arch/ia64/kernel/esi_stub.S index 821e68d10598..9928c5b2957c 100644 --- a/arch/ia64/kernel/esi_stub.S +++ b/arch/ia64/kernel/esi_stub.S @@ -34,9 +34,9 @@ #define PSR_BITS_TO_SET \ (IA64_PSR_BN) +#include <linux/export.h> #include <asm/processor.h> #include <asm/asmmacro.h> -#include <asm/export.h> /* * Inputs: diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S index c096500590e9..85c8a57da402 100644 --- a/arch/ia64/kernel/head.S +++ b/arch/ia64/kernel/head.S @@ -20,7 +20,7 @@ * Support for CPU Hotplug */ - +#include <linux/export.h> #include <linux/pgtable.h> #include <asm/asmmacro.h> #include <asm/fpu.h> @@ -33,7 +33,6 @@ #include <asm/mca_asm.h> #include <linux/init.h> #include <linux/linkage.h> -#include <asm/export.h> #ifdef CONFIG_HOTPLUG_CPU #define SAL_PSR_BITS_TO_SET \ diff --git a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S index 7a418e324d30..da90c49df628 100644 --- a/arch/ia64/kernel/ivt.S +++ b/arch/ia64/kernel/ivt.S @@ -47,7 +47,7 @@ * Table is based upon EAS2.6 (Oct 1999) */ - +#include <linux/export.h> #include <linux/pgtable.h> #include <asm/asmmacro.h> #include <asm/break.h> @@ -58,7 +58,6 @@ #include <asm/thread_info.h> #include <asm/unistd.h> #include <asm/errno.h> -#include <asm/export.h> #if 0 # define PSR_DEFAULT_BITS psr.ac diff --git a/arch/ia64/kernel/pal.S b/arch/ia64/kernel/pal.S index 06d01a070aae..fb6db6966f70 100644 --- a/arch/ia64/kernel/pal.S +++ b/arch/ia64/kernel/pal.S @@ -13,9 +13,9 @@ * 05/24/2000 eranian Added support for physical mode static calls */ +#include <linux/export.h> #include <asm/asmmacro.h> #include <asm/processor.h> -#include <asm/export.h> .data pal_entry_point: diff --git a/arch/ia64/lib/clear_page.S b/arch/ia64/lib/clear_page.S index 65b75085c8f4..ba0dd2538fa5 100644 --- a/arch/ia64/lib/clear_page.S +++ b/arch/ia64/lib/clear_page.S @@ -10,9 +10,9 @@ * 3/08/02 davidm Some more tweaking */ +#include <linux/export.h> #include <asm/asmmacro.h> #include <asm/page.h> -#include <asm/export.h> #ifdef CONFIG_ITANIUM # define L3_LINE_SIZE 64 // Itanium L3 line size diff --git a/arch/ia64/lib/clear_user.S b/arch/ia64/lib/clear_user.S index a28f39d349eb..1d9e45ccf8e5 100644 --- a/arch/ia64/lib/clear_user.S +++ b/arch/ia64/lib/clear_user.S @@ -12,8 +12,8 @@ * Stephane Eranian <eranian@hpl.hp.com> */ +#include <linux/export.h> #include <asm/asmmacro.h> -#include <asm/export.h> // // arguments diff --git a/arch/ia64/lib/copy_page.S b/arch/ia64/lib/copy_page.S index 176f857c522e..c0a0e6b2af00 100644 --- a/arch/ia64/lib/copy_page.S +++ b/arch/ia64/lib/copy_page.S @@ -15,9 +15,9 @@ * * 4/06/01 davidm Tuned to make it perform well both for cached and uncached copies. */ +#include <linux/export.h> #include <asm/asmmacro.h> #include <asm/page.h> -#include <asm/export.h> #define PIPE_DEPTH 3 #define EPI p[PIPE_DEPTH-1] diff --git a/arch/ia64/lib/copy_page_mck.S b/arch/ia64/lib/copy_page_mck.S index d6fd56e4f1c1..5e8bb4b4b535 100644 --- a/arch/ia64/lib/copy_page_mck.S +++ b/arch/ia64/lib/copy_page_mck.S @@ -60,9 +60,9 @@ * to fetch the second-half of the L2 cache line into L1, and the tX words are copied in * an order that avoids bank conflicts. */ +#include <linux/export.h> #include <asm/asmmacro.h> #include <asm/page.h> -#include <asm/export.h> #define PREFETCH_DIST 8 // McKinley sustains 16 outstanding L2 misses (8 ld, 8 st) diff --git a/arch/ia64/lib/copy_user.S b/arch/ia64/lib/copy_user.S index f681556c6b86..8daab72cfe77 100644 --- a/arch/ia64/lib/copy_user.S +++ b/arch/ia64/lib/copy_user.S @@ -30,8 +30,8 @@ * - fix extraneous stop bit introduced by the EX() macro. */ +#include <linux/export.h> #include <asm/asmmacro.h> -#include <asm/export.h> // // Tuneable parameters diff --git a/arch/ia64/lib/flush.S b/arch/ia64/lib/flush.S index 8573d59c9ed1..f8e795fe45cb 100644 --- a/arch/ia64/lib/flush.S +++ b/arch/ia64/lib/flush.S @@ -8,9 +8,8 @@ * 05/28/05 Zoltan Menyhart Dynamic stride size */ +#include <linux/export.h> #include <asm/asmmacro.h> -#include <asm/export.h> - /* * flush_icache_range(start,end) diff --git a/arch/ia64/lib/idiv32.S b/arch/ia64/lib/idiv32.S index def92b708e6e..83586fbc51ff 100644 --- a/arch/ia64/lib/idiv32.S +++ b/arch/ia64/lib/idiv32.S @@ -15,8 +15,8 @@ * (http://www.goodreads.com/book/show/2019887.Ia_64_and_Elementary_Functions) */ +#include <linux/export.h> #include <asm/asmmacro.h> -#include <asm/export.h> #ifdef MODULO # define OP mod diff --git a/arch/ia64/lib/idiv64.S b/arch/ia64/lib/idiv64.S index a8ba3bd3d4d8..5c9113691f72 100644 --- a/arch/ia64/lib/idiv64.S +++ b/arch/ia64/lib/idiv64.S @@ -15,8 +15,8 @@ * (http://www.goodreads.com/book/show/2019887.Ia_64_and_Elementary_Functions) */ +#include <linux/export.h> #include <asm/asmmacro.h> -#include <asm/export.h> #ifdef MODULO # define OP mod diff --git a/arch/ia64/lib/ip_fast_csum.S b/arch/ia64/lib/ip_fast_csum.S index dc9e6e6fe876..fcc0b812ce2e 100644 --- a/arch/ia64/lib/ip_fast_csum.S +++ b/arch/ia64/lib/ip_fast_csum.S @@ -13,8 +13,8 @@ * Copyright (C) 2002, 2006 Ken Chen <kenneth.w.chen@intel.com> */ +#include <linux/export.h> #include <asm/asmmacro.h> -#include <asm/export.h> /* * Since we know that most likely this function is called with buf aligned diff --git a/arch/ia64/lib/memcpy.S b/arch/ia64/lib/memcpy.S index 91a625fddbf0..35c9069a8345 100644 --- a/arch/ia64/lib/memcpy.S +++ b/arch/ia64/lib/memcpy.S @@ -14,8 +14,8 @@ * Stephane Eranian <eranian@hpl.hp.com> * David Mosberger-Tang <davidm@hpl.hp.com> */ +#include <linux/export.h> #include <asm/asmmacro.h> -#include <asm/export.h> GLOBAL_ENTRY(memcpy) diff --git a/arch/ia64/lib/memcpy_mck.S b/arch/ia64/lib/memcpy_mck.S index cc4e6ac914b6..c0d4362217ae 100644 --- a/arch/ia64/lib/memcpy_mck.S +++ b/arch/ia64/lib/memcpy_mck.S @@ -14,9 +14,9 @@ * Copyright (C) 2002 Intel Corp. * Copyright (C) 2002 Ken Chen <kenneth.w.chen@intel.com> */ +#include <linux/export.h> #include <asm/asmmacro.h> #include <asm/page.h> -#include <asm/export.h> #define EK(y...) EX(y) diff --git a/arch/ia64/lib/memset.S b/arch/ia64/lib/memset.S index 07a8b92c6496..552c5c7e4d06 100644 --- a/arch/ia64/lib/memset.S +++ b/arch/ia64/lib/memset.S @@ -18,8 +18,8 @@ Since a stf.spill f0 can store 16B in one go, we use this instruction to get peak speed when value = 0. */ +#include <linux/export.h> #include <asm/asmmacro.h> -#include <asm/export.h> #undef ret #define dest in0 diff --git a/arch/ia64/lib/strlen.S b/arch/ia64/lib/strlen.S index d66de5966974..1f4a46c15127 100644 --- a/arch/ia64/lib/strlen.S +++ b/arch/ia64/lib/strlen.S @@ -17,8 +17,8 @@ * 09/24/99 S.Eranian add speculation recovery code */ +#include <linux/export.h> #include <asm/asmmacro.h> -#include <asm/export.h> // // diff --git a/arch/ia64/lib/strncpy_from_user.S b/arch/ia64/lib/strncpy_from_user.S index 49eb81b69cd2..a287169bd953 100644 --- a/arch/ia64/lib/strncpy_from_user.S +++ b/arch/ia64/lib/strncpy_from_user.S @@ -17,8 +17,8 @@ * by Andreas Schwab <schwab@suse.de>). */ +#include <linux/export.h> #include <asm/asmmacro.h> -#include <asm/export.h> GLOBAL_ENTRY(__strncpy_from_user) alloc r2=ar.pfs,3,0,0,0 diff --git a/arch/ia64/lib/strnlen_user.S b/arch/ia64/lib/strnlen_user.S index 4b684d4da106..a7eb56e840a9 100644 --- a/arch/ia64/lib/strnlen_user.S +++ b/arch/ia64/lib/strnlen_user.S @@ -13,8 +13,8 @@ * Copyright (C) 1999, 2001 David Mosberger-Tang <davidm@hpl.hp.com> */ +#include <linux/export.h> #include <asm/asmmacro.h> -#include <asm/export.h> GLOBAL_ENTRY(__strnlen_user) .prologue diff --git a/arch/ia64/lib/xor.S b/arch/ia64/lib/xor.S index 5413dafe6b2e..6e2a69662c06 100644 --- a/arch/ia64/lib/xor.S +++ b/arch/ia64/lib/xor.S @@ -5,8 +5,8 @@ * Optimized RAID-5 checksumming functions for IA-64. */ +#include <linux/export.h> #include <asm/asmmacro.h> -#include <asm/export.h> GLOBAL_ENTRY(xor_ia64_2) .prologue diff --git a/arch/m68k/coldfire/dma_timer.c b/arch/m68k/coldfire/dma_timer.c index cbb289439606..91e6728f51ed 100644 --- a/arch/m68k/coldfire/dma_timer.c +++ b/arch/m68k/coldfire/dma_timer.c @@ -48,7 +48,7 @@ static struct clocksource clocksource_cf_dt = { .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; -static int __init init_cf_dt_clocksource(void) +static int __init init_cf_dt_clocksource(void) { /* * We setup DMA timer 0 in free run mode. This incrementing counter is diff --git a/arch/m68k/kernel/pcibios.c b/arch/m68k/kernel/pcibios.c index b0e110d3d2e6..9504eb19d73a 100644 --- a/arch/m68k/kernel/pcibios.c +++ b/arch/m68k/kernel/pcibios.c @@ -92,9 +92,3 @@ void pcibios_fixup_bus(struct pci_bus *bus) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 32); } } - -char *pcibios_setup(char *str) -{ - return str; -} - diff --git a/arch/microblaze/include/asm/page.h b/arch/microblaze/include/asm/page.h index 337f23eabc71..86a4ce07c192 100644 --- a/arch/microblaze/include/asm/page.h +++ b/arch/microblaze/include/asm/page.h @@ -99,9 +99,6 @@ extern int page_is_ram(unsigned long pfn); # define phys_to_pfn(phys) (PFN_DOWN(phys)) # define pfn_to_phys(pfn) (PFN_PHYS(pfn)) -# define virt_to_pfn(vaddr) (phys_to_pfn((__pa(vaddr)))) -# define pfn_to_virt(pfn) __va(pfn_to_phys((pfn))) - # define virt_to_page(kaddr) (pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)) # define page_to_virt(page) __va(page_to_pfn(page) << PAGE_SHIFT) # define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT) @@ -109,11 +106,6 @@ extern int page_is_ram(unsigned long pfn); # define ARCH_PFN_OFFSET (memory_start >> PAGE_SHIFT) # endif /* __ASSEMBLY__ */ -#define virt_addr_valid(vaddr) (pfn_valid(virt_to_pfn(vaddr))) - -# define __pa(x) __virt_to_phys((unsigned long)(x)) -# define __va(x) ((void *)__phys_to_virt((unsigned long)(x))) - /* Convert between virtual and physical address for MMU. */ /* Handle MicroBlaze processor with virtual memory. */ #define __virt_to_phys(addr) \ @@ -125,6 +117,25 @@ extern int page_is_ram(unsigned long pfn); #define tovirt(rd, rs) \ addik rd, rs, (CONFIG_KERNEL_START - CONFIG_KERNEL_BASE_ADDR) +#ifndef __ASSEMBLY__ + +# define __pa(x) __virt_to_phys((unsigned long)(x)) +# define __va(x) ((void *)__phys_to_virt((unsigned long)(x))) + +static inline unsigned long virt_to_pfn(const void *vaddr) +{ + return phys_to_pfn(__pa(vaddr)); +} + +static inline const void *pfn_to_virt(unsigned long pfn) +{ + return __va(pfn_to_phys((pfn))); +} + +#define virt_addr_valid(vaddr) (pfn_valid(virt_to_pfn(vaddr))) + +#endif /* __ASSEMBLY__ */ + #define TOPHYS(addr) __virt_to_phys(addr) #endif /* __KERNEL__ */ diff --git a/arch/microblaze/include/asm/setup.h b/arch/microblaze/include/asm/setup.h index 3657f5e78a3d..bf2600f75959 100644 --- a/arch/microblaze/include/asm/setup.h +++ b/arch/microblaze/include/asm/setup.h @@ -25,7 +25,5 @@ void machine_shutdown(void); void machine_halt(void); void machine_power_off(void); -extern void *zalloc_maybe_bootmem(size_t size, gfp_t mask); - # endif /* __ASSEMBLY__ */ #endif /* _ASM_MICROBLAZE_SETUP_H */ diff --git a/arch/microblaze/kernel/reset.c b/arch/microblaze/kernel/reset.c index 5f4722908164..2f66c7963084 100644 --- a/arch/microblaze/kernel/reset.c +++ b/arch/microblaze/kernel/reset.c @@ -9,7 +9,6 @@ #include <linux/init.h> #include <linux/delay.h> -#include <linux/of_platform.h> #include <linux/reboot.h> void machine_shutdown(void) diff --git a/arch/microblaze/mm/init.c b/arch/microblaze/mm/init.c index 353fabdfcbc5..3827dc76edd8 100644 --- a/arch/microblaze/mm/init.c +++ b/arch/microblaze/mm/init.c @@ -270,22 +270,6 @@ asmlinkage void __init mmu_init(void) memblock_dump_all(); } -void * __ref zalloc_maybe_bootmem(size_t size, gfp_t mask) -{ - void *p; - - if (mem_init_done) { - p = kzalloc(size, mask); - } else { - p = memblock_alloc(size, SMP_CACHE_BYTES); - if (!p) - panic("%s: Failed to allocate %zu bytes\n", - __func__, size); - } - - return p; -} - static const pgprot_t protection_map[16] = { [VM_NONE] = PAGE_NONE, [VM_READ] = PAGE_READONLY_X, diff --git a/arch/openrisc/include/asm/bug.h b/arch/openrisc/include/asm/bug.h new file mode 100644 index 000000000000..6d04776eaf10 --- /dev/null +++ b/arch/openrisc/include/asm/bug.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef __ASM_OPENRISC_BUG_H +#define __ASM_OPENRISC_BUG_H + +#include <asm-generic/bug.h> + +struct pt_regs; + +void __noreturn die(const char *str, struct pt_regs *regs, long err); + +#endif /* __ASM_OPENRISC_BUG_H */ diff --git a/arch/openrisc/include/asm/page.h b/arch/openrisc/include/asm/page.h index 52b0d7e76446..44fc1fd56717 100644 --- a/arch/openrisc/include/asm/page.h +++ b/arch/openrisc/include/asm/page.h @@ -72,8 +72,15 @@ typedef struct page *pgtable_t; #define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET)) #define __pa(x) ((unsigned long) (x) - PAGE_OFFSET) -#define virt_to_pfn(kaddr) (__pa(kaddr) >> PAGE_SHIFT) -#define pfn_to_virt(pfn) __va((pfn) << PAGE_SHIFT) +static inline unsigned long virt_to_pfn(const void *kaddr) +{ + return __pa(kaddr) >> PAGE_SHIFT; +} + +static inline void * pfn_to_virt(unsigned long pfn) +{ + return (void *)((unsigned long)__va(pfn) << PAGE_SHIFT); +} #define virt_to_page(addr) \ (mem_map + (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT)) diff --git a/arch/openrisc/include/asm/processor.h b/arch/openrisc/include/asm/processor.h index ed9efb430afa..3b736e74e6ed 100644 --- a/arch/openrisc/include/asm/processor.h +++ b/arch/openrisc/include/asm/processor.h @@ -73,6 +73,7 @@ struct thread_struct { void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp); unsigned long __get_wchan(struct task_struct *p); +void show_registers(struct pt_regs *regs); #define cpu_relax() barrier() diff --git a/arch/openrisc/kernel/process.c b/arch/openrisc/kernel/process.c index dfa558f98ed8..86e02929f3ac 100644 --- a/arch/openrisc/kernel/process.c +++ b/arch/openrisc/kernel/process.c @@ -14,6 +14,7 @@ */ #define __KERNEL_SYSCALLS__ +#include <linux/cpu.h> #include <linux/errno.h> #include <linux/sched.h> #include <linux/sched/debug.h> @@ -38,6 +39,7 @@ #include <asm/io.h> #include <asm/processor.h> #include <asm/spr_defs.h> +#include <asm/switch_to.h> #include <linux/smp.h> @@ -119,8 +121,6 @@ void flush_thread(void) void show_regs(struct pt_regs *regs) { - extern void show_registers(struct pt_regs *regs); - show_regs_print_info(KERN_DEFAULT); /* __PHX__ cleanup this mess */ show_registers(regs); diff --git a/arch/openrisc/kernel/ptrace.c b/arch/openrisc/kernel/ptrace.c index 0b7d2ca6ba3b..1eeac3b62e9d 100644 --- a/arch/openrisc/kernel/ptrace.c +++ b/arch/openrisc/kernel/ptrace.c @@ -27,6 +27,10 @@ #include <asm/thread_info.h> #include <asm/page.h> +asmlinkage long do_syscall_trace_enter(struct pt_regs *regs); + +asmlinkage void do_syscall_trace_leave(struct pt_regs *regs); + /* * Copy the thread state to a regset that can be interpreted by userspace. * diff --git a/arch/openrisc/kernel/signal.c b/arch/openrisc/kernel/signal.c index 2e7257a433ff..e2f21a5d8ad9 100644 --- a/arch/openrisc/kernel/signal.c +++ b/arch/openrisc/kernel/signal.c @@ -34,6 +34,11 @@ struct rt_sigframe { unsigned char retcode[16]; /* trampoline code */ }; +asmlinkage long _sys_rt_sigreturn(struct pt_regs *regs); + +asmlinkage int do_work_pending(struct pt_regs *regs, unsigned int thread_flags, + int syscall); + static int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) { @@ -224,7 +229,7 @@ handle_signal(struct ksignal *ksig, struct pt_regs *regs) * mode below. */ -int do_signal(struct pt_regs *regs, int syscall) +static int do_signal(struct pt_regs *regs, int syscall) { struct ksignal ksig; unsigned long continue_addr = 0; diff --git a/arch/openrisc/kernel/smp.c b/arch/openrisc/kernel/smp.c index 0a7a059e2dff..1c5a2d71d675 100644 --- a/arch/openrisc/kernel/smp.c +++ b/arch/openrisc/kernel/smp.c @@ -23,6 +23,8 @@ #include <asm/cacheflush.h> #include <asm/time.h> +asmlinkage __init void secondary_start_kernel(void); + static void (*smp_cross_call)(const struct cpumask *, unsigned int); unsigned long secondary_release = -1; diff --git a/arch/openrisc/kernel/time.c b/arch/openrisc/kernel/time.c index 8e26c1af5441..764c7bfb5df3 100644 --- a/arch/openrisc/kernel/time.c +++ b/arch/openrisc/kernel/time.c @@ -25,6 +25,8 @@ #include <asm/cpuinfo.h> #include <asm/time.h> +irqreturn_t __irq_entry timer_interrupt(struct pt_regs *regs); + /* Test the timer ticks to count, used in sync routine */ inline void openrisc_timer_set(unsigned long count) { diff --git a/arch/openrisc/kernel/traps.c b/arch/openrisc/kernel/traps.c index 0aa6b07efda1..9370888c9a7e 100644 --- a/arch/openrisc/kernel/traps.c +++ b/arch/openrisc/kernel/traps.c @@ -30,14 +30,23 @@ #include <linux/kallsyms.h> #include <linux/uaccess.h> +#include <asm/bug.h> #include <asm/io.h> +#include <asm/processor.h> #include <asm/unwinder.h> #include <asm/sections.h> -static int kstack_depth_to_print = 0x180; int lwa_flag; static unsigned long __user *lwa_addr; +asmlinkage void unhandled_exception(struct pt_regs *regs, int ea, int vector); +asmlinkage void do_trap(struct pt_regs *regs, unsigned long address); +asmlinkage void do_fpe_trap(struct pt_regs *regs, unsigned long address); +asmlinkage void do_unaligned_access(struct pt_regs *regs, unsigned long address); +asmlinkage void do_bus_fault(struct pt_regs *regs, unsigned long address); +asmlinkage void do_illegal_instruction(struct pt_regs *regs, + unsigned long address); + static void print_trace(void *data, unsigned long addr, int reliable) { const char *loglvl = data; @@ -143,80 +152,6 @@ bad: printk("\n"); } -void nommu_dump_state(struct pt_regs *regs, - unsigned long ea, unsigned long vector) -{ - int i; - unsigned long addr, stack = regs->sp; - - printk("\n\r[nommu_dump_state] :: ea %lx, vector %lx\n\r", ea, vector); - - printk("CPU #: %d\n" - " PC: %08lx SR: %08lx SP: %08lx\n", - 0, regs->pc, regs->sr, regs->sp); - printk("GPR00: %08lx GPR01: %08lx GPR02: %08lx GPR03: %08lx\n", - 0L, regs->gpr[1], regs->gpr[2], regs->gpr[3]); - printk("GPR04: %08lx GPR05: %08lx GPR06: %08lx GPR07: %08lx\n", - regs->gpr[4], regs->gpr[5], regs->gpr[6], regs->gpr[7]); - printk("GPR08: %08lx GPR09: %08lx GPR10: %08lx GPR11: %08lx\n", - regs->gpr[8], regs->gpr[9], regs->gpr[10], regs->gpr[11]); - printk("GPR12: %08lx GPR13: %08lx GPR14: %08lx GPR15: %08lx\n", - regs->gpr[12], regs->gpr[13], regs->gpr[14], regs->gpr[15]); - printk("GPR16: %08lx GPR17: %08lx GPR18: %08lx GPR19: %08lx\n", - regs->gpr[16], regs->gpr[17], regs->gpr[18], regs->gpr[19]); - printk("GPR20: %08lx GPR21: %08lx GPR22: %08lx GPR23: %08lx\n", - regs->gpr[20], regs->gpr[21], regs->gpr[22], regs->gpr[23]); - printk("GPR24: %08lx GPR25: %08lx GPR26: %08lx GPR27: %08lx\n", - regs->gpr[24], regs->gpr[25], regs->gpr[26], regs->gpr[27]); - printk("GPR28: %08lx GPR29: %08lx GPR30: %08lx GPR31: %08lx\n", - regs->gpr[28], regs->gpr[29], regs->gpr[30], regs->gpr[31]); - printk(" RES: %08lx oGPR11: %08lx\n", - regs->gpr[11], regs->orig_gpr11); - - printk("Process %s (pid: %d, stackpage=%08lx)\n", - ((struct task_struct *)(__pa(current)))->comm, - ((struct task_struct *)(__pa(current)))->pid, - (unsigned long)current); - - printk("\nStack: "); - printk("Stack dump [0x%08lx]:\n", (unsigned long)stack); - for (i = 0; i < kstack_depth_to_print; i++) { - if (((long)stack & (THREAD_SIZE - 1)) == 0) - break; - stack++; - - printk("%lx :: sp + %02d: 0x%08lx\n", stack, i * 4, - *((unsigned long *)(__pa(stack)))); - } - printk("\n"); - - printk("Call Trace: "); - i = 1; - while (((long)stack & (THREAD_SIZE - 1)) != 0) { - addr = *((unsigned long *)__pa(stack)); - stack++; - - if (kernel_text_address(addr)) { - if (i && ((i % 6) == 0)) - printk("\n "); - printk(" [<%08lx>]", addr); - i++; - } - } - printk("\n"); - - printk("\nCode: "); - - for (i = -24; i < 24; i++) { - unsigned long word; - - word = ((unsigned long *)(__pa(regs->pc)))[i]; - - print_data(regs->pc, word, i); - } - printk("\n"); -} - /* This is normally the 'Oops' routine */ void __noreturn die(const char *str, struct pt_regs *regs, long err) { diff --git a/arch/openrisc/mm/fault.c b/arch/openrisc/mm/fault.c index a9dcd4381d1a..29e232d78d82 100644 --- a/arch/openrisc/mm/fault.c +++ b/arch/openrisc/mm/fault.c @@ -18,6 +18,7 @@ #include <linux/perf_event.h> #include <linux/uaccess.h> +#include <asm/bug.h> #include <asm/mmu_context.h> #include <asm/siginfo.h> #include <asm/signal.h> @@ -30,7 +31,8 @@ */ volatile pgd_t *current_pgd[NR_CPUS]; -extern void __noreturn die(char *, struct pt_regs *, long); +asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long address, + unsigned long vector, int write_acc); /* * This routine handles page faults. It determines the address, diff --git a/arch/openrisc/mm/init.c b/arch/openrisc/mm/init.c index d531ab82be12..1dcd78c8f0e9 100644 --- a/arch/openrisc/mm/init.c +++ b/arch/openrisc/mm/init.c @@ -123,8 +123,6 @@ static void __init map_ram(void) void __init paging_init(void) { - extern void tlb_init(void); - int i; printk(KERN_INFO "Setting up paging and PTEs.\n"); diff --git a/arch/openrisc/mm/ioremap.c b/arch/openrisc/mm/ioremap.c index 91c8259d4b7e..f59ea4c10b0f 100644 --- a/arch/openrisc/mm/ioremap.c +++ b/arch/openrisc/mm/ioremap.c @@ -22,7 +22,7 @@ extern int mem_init_done; -/** +/* * OK, this one's a bit tricky... ioremap can get called before memory is * initialized (early serial console does this) and will want to alloc a page * for its mapping. No userspace pages will ever get allocated before memory diff --git a/arch/openrisc/mm/tlb.c b/arch/openrisc/mm/tlb.c index e2f2a3c3bb22..3115f2e4f864 100644 --- a/arch/openrisc/mm/tlb.c +++ b/arch/openrisc/mm/tlb.c @@ -182,12 +182,3 @@ void destroy_context(struct mm_struct *mm) flush_tlb_mm(mm); } - -/* called once during VM initialization, from init.c */ - -void __init tlb_init(void) -{ - /* Do nothing... */ - /* invalidate the entire TLB */ - /* flush_tlb_all(); */ -} diff --git a/arch/powerpc/configs/disable-werror.config b/arch/powerpc/configs/disable-werror.config index 6ea12a12432c..7776b91da37f 100644 --- a/arch/powerpc/configs/disable-werror.config +++ b/arch/powerpc/configs/disable-werror.config @@ -1 +1,2 @@ +# Help: Disable -Werror CONFIG_PPC_DISABLE_WERROR=y diff --git a/arch/powerpc/configs/security.config b/arch/powerpc/configs/security.config index 1c91a35c6a73..0d54e29e2cdf 100644 --- a/arch/powerpc/configs/security.config +++ b/arch/powerpc/configs/security.config @@ -1,3 +1,5 @@ +# Help: Common security options for PowerPC builds + # This is the equivalent of booting with lockdown=integrity CONFIG_SECURITY=y CONFIG_SECURITYFS=y @@ -12,4 +14,4 @@ CONFIG_INIT_ON_ALLOC_DEFAULT_ON=y # UBSAN bounds checking is very cheap and good for hardening CONFIG_UBSAN=y -# CONFIG_UBSAN_MISC is not set
\ No newline at end of file +# CONFIG_UBSAN_MISC is not set diff --git a/arch/riscv/configs/32-bit.config b/arch/riscv/configs/32-bit.config index f6af0f708df4..16ee163847b4 100644 --- a/arch/riscv/configs/32-bit.config +++ b/arch/riscv/configs/32-bit.config @@ -1,3 +1,4 @@ +# Help: Build a 32-bit image CONFIG_ARCH_RV32I=y CONFIG_32BIT=y # CONFIG_PORTABLE is not set diff --git a/arch/riscv/configs/64-bit.config b/arch/riscv/configs/64-bit.config index 313edc554d84..d872a2d533f2 100644 --- a/arch/riscv/configs/64-bit.config +++ b/arch/riscv/configs/64-bit.config @@ -1,2 +1,3 @@ +# Help: Build a 64-bit image CONFIG_ARCH_RV64I=y CONFIG_64BIT=y diff --git a/arch/s390/configs/btf.config b/arch/s390/configs/btf.config index 39227b4511af..eb7f84f5925c 100644 --- a/arch/s390/configs/btf.config +++ b/arch/s390/configs/btf.config @@ -1 +1,2 @@ +# Help: Enable BTF debug info CONFIG_DEBUG_INFO_BTF=y diff --git a/arch/s390/configs/kasan.config b/arch/s390/configs/kasan.config index 700a8b25c3ff..84c2b551e992 100644 --- a/arch/s390/configs/kasan.config +++ b/arch/s390/configs/kasan.config @@ -1,3 +1,4 @@ +# Help: Enable KASan for debugging CONFIG_KASAN=y CONFIG_KASAN_INLINE=y CONFIG_KASAN_VMALLOC=y diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild index 595ca0be286b..43b0ae4c2c21 100644 --- a/arch/sparc/include/asm/Kbuild +++ b/arch/sparc/include/asm/Kbuild @@ -2,6 +2,5 @@ generated-y += syscall_table_32.h generated-y += syscall_table_64.h generic-y += agp.h -generic-y += export.h generic-y += kvm_para.h generic-y += mcs_spinlock.h diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index a269ad2fe6df..a3fdee4cd6fa 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S @@ -8,6 +8,7 @@ * Copyright (C) 1997 Anton Blanchard (anton@progsoc.uts.edu.au) */ +#include <linux/export.h> #include <linux/linkage.h> #include <linux/errno.h> #include <linux/pgtable.h> @@ -30,7 +31,6 @@ #include <asm/unistd.h> #include <asm/asmmacro.h> -#include <asm/export.h> #define curptr g6 diff --git a/arch/sparc/kernel/head_32.S b/arch/sparc/kernel/head_32.S index 6044b82b9767..964c61b5cd03 100644 --- a/arch/sparc/kernel/head_32.S +++ b/arch/sparc/kernel/head_32.S @@ -11,6 +11,7 @@ * CompactPCI platform by Eric Brower, 1999. */ +#include <linux/export.h> #include <linux/version.h> #include <linux/init.h> @@ -25,7 +26,6 @@ #include <asm/thread_info.h> /* TI_UWINMASK */ #include <asm/errno.h> #include <asm/pgtable.h> /* PGDIR_SHIFT */ -#include <asm/export.h> .data /* The following are used with the prom_vector node-ops to figure out diff --git a/arch/sparc/kernel/head_64.S b/arch/sparc/kernel/head_64.S index 72a5bdc833ea..cf0549134234 100644 --- a/arch/sparc/kernel/head_64.S +++ b/arch/sparc/kernel/head_64.S @@ -9,6 +9,7 @@ #include <linux/version.h> #include <linux/errno.h> +#include <linux/export.h> #include <linux/threads.h> #include <linux/init.h> #include <linux/linkage.h> @@ -33,7 +34,6 @@ #include <asm/estate.h> #include <asm/sfafsr.h> #include <asm/unistd.h> -#include <asm/export.h> /* This section from from _start to sparc64_boot_end should fit into * 0x0000000000404000 to 0x0000000000408000. diff --git a/arch/sparc/lib/U1memcpy.S b/arch/sparc/lib/U1memcpy.S index a6f4ee391897..635398ec7540 100644 --- a/arch/sparc/lib/U1memcpy.S +++ b/arch/sparc/lib/U1memcpy.S @@ -6,10 +6,10 @@ */ #ifdef __KERNEL__ +#include <linux/export.h> #include <linux/linkage.h> #include <asm/visasm.h> #include <asm/asi.h> -#include <asm/export.h> #define GLOBAL_SPARE g7 #else #define GLOBAL_SPARE g5 diff --git a/arch/sparc/lib/VISsave.S b/arch/sparc/lib/VISsave.S index 9c8eb2017d5b..31a0c336c185 100644 --- a/arch/sparc/lib/VISsave.S +++ b/arch/sparc/lib/VISsave.S @@ -7,6 +7,7 @@ * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz) */ +#include <linux/export.h> #include <linux/linkage.h> #include <asm/asi.h> @@ -14,7 +15,6 @@ #include <asm/ptrace.h> #include <asm/visasm.h> #include <asm/thread_info.h> -#include <asm/export.h> /* On entry: %o5=current FPRS value, %g7 is callers address */ /* May clobber %o5, %g1, %g2, %g3, %g7, %icc, %xcc */ diff --git a/arch/sparc/lib/ashldi3.S b/arch/sparc/lib/ashldi3.S index 2d72de88af90..2a9e7c4fb260 100644 --- a/arch/sparc/lib/ashldi3.S +++ b/arch/sparc/lib/ashldi3.S @@ -6,8 +6,8 @@ * Copyright (C) 1999 David S. Miller (davem@redhat.com) */ +#include <linux/export.h> #include <linux/linkage.h> -#include <asm/export.h> .text ENTRY(__ashldi3) diff --git a/arch/sparc/lib/ashrdi3.S b/arch/sparc/lib/ashrdi3.S index 05dfda9f5005..8fd0b311722f 100644 --- a/arch/sparc/lib/ashrdi3.S +++ b/arch/sparc/lib/ashrdi3.S @@ -6,8 +6,8 @@ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) */ +#include <linux/export.h> #include <linux/linkage.h> -#include <asm/export.h> .text ENTRY(__ashrdi3) diff --git a/arch/sparc/lib/atomic_64.S b/arch/sparc/lib/atomic_64.S index 8245d4a97301..4f8cab2fb9cd 100644 --- a/arch/sparc/lib/atomic_64.S +++ b/arch/sparc/lib/atomic_64.S @@ -4,10 +4,10 @@ * Copyright (C) 1999, 2007 2012 David S. Miller (davem@davemloft.net) */ +#include <linux/export.h> #include <linux/linkage.h> #include <asm/asi.h> #include <asm/backoff.h> -#include <asm/export.h> .text diff --git a/arch/sparc/lib/bitops.S b/arch/sparc/lib/bitops.S index 9d647f977618..9c91cbb310e7 100644 --- a/arch/sparc/lib/bitops.S +++ b/arch/sparc/lib/bitops.S @@ -4,10 +4,10 @@ * Copyright (C) 2000, 2007 David S. Miller (davem@davemloft.net) */ +#include <linux/export.h> #include <linux/linkage.h> #include <asm/asi.h> #include <asm/backoff.h> -#include <asm/export.h> .text diff --git a/arch/sparc/lib/blockops.S b/arch/sparc/lib/blockops.S index 76ddd1ff6833..5b92959a4d48 100644 --- a/arch/sparc/lib/blockops.S +++ b/arch/sparc/lib/blockops.S @@ -5,9 +5,9 @@ * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) */ +#include <linux/export.h> #include <linux/linkage.h> #include <asm/page.h> -#include <asm/export.h> /* Zero out 64 bytes of memory at (buf + offset). * Assumes %g1 contains zero. diff --git a/arch/sparc/lib/bzero.S b/arch/sparc/lib/bzero.S index 87fec4cbe10c..2bfa44a6b25e 100644 --- a/arch/sparc/lib/bzero.S +++ b/arch/sparc/lib/bzero.S @@ -5,8 +5,8 @@ * Copyright (C) 2005 David S. Miller <davem@davemloft.net> */ +#include <linux/export.h> #include <linux/linkage.h> -#include <asm/export.h> .text diff --git a/arch/sparc/lib/checksum_32.S b/arch/sparc/lib/checksum_32.S index 781e39b3c009..84ad709cbecb 100644 --- a/arch/sparc/lib/checksum_32.S +++ b/arch/sparc/lib/checksum_32.S @@ -14,8 +14,8 @@ * BSD4.4 portable checksum routine */ +#include <linux/export.h> #include <asm/errno.h> -#include <asm/export.h> #define CSUM_BIGCHUNK(buf, offset, sum, t0, t1, t2, t3, t4, t5) \ ldd [buf + offset + 0x00], t0; \ diff --git a/arch/sparc/lib/checksum_64.S b/arch/sparc/lib/checksum_64.S index 9700ef1730df..32b626f3fe4d 100644 --- a/arch/sparc/lib/checksum_64.S +++ b/arch/sparc/lib/checksum_64.S @@ -14,7 +14,7 @@ * BSD4.4 portable checksum routine */ -#include <asm/export.h> +#include <linux/export.h> .text csum_partial_fix_alignment: diff --git a/arch/sparc/lib/clear_page.S b/arch/sparc/lib/clear_page.S index 302d3454a994..e63458194f5a 100644 --- a/arch/sparc/lib/clear_page.S +++ b/arch/sparc/lib/clear_page.S @@ -5,13 +5,13 @@ * Copyright (C) 1997 Jakub Jelinek (jakub@redhat.com) */ +#include <linux/export.h> #include <linux/pgtable.h> #include <asm/visasm.h> #include <asm/thread_info.h> #include <asm/page.h> #include <asm/spitfire.h> #include <asm/head.h> -#include <asm/export.h> /* What we used to do was lock a TLB entry into a specific * TLB slot, clear the page with interrupts disabled, then diff --git a/arch/sparc/lib/copy_in_user.S b/arch/sparc/lib/copy_in_user.S index 66e90bf528e2..e23e6a69ff92 100644 --- a/arch/sparc/lib/copy_in_user.S +++ b/arch/sparc/lib/copy_in_user.S @@ -4,9 +4,9 @@ * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com) */ +#include <linux/export.h> #include <linux/linkage.h> #include <asm/asi.h> -#include <asm/export.h> #define XCC xcc diff --git a/arch/sparc/lib/copy_page.S b/arch/sparc/lib/copy_page.S index 5ebcfd479f4f..7a041f3ebc58 100644 --- a/arch/sparc/lib/copy_page.S +++ b/arch/sparc/lib/copy_page.S @@ -5,13 +5,13 @@ * Copyright (C) 1997 Jakub Jelinek (jakub@redhat.com) */ +#include <linux/export.h> #include <asm/visasm.h> #include <asm/thread_info.h> #include <asm/page.h> #include <linux/pgtable.h> #include <asm/spitfire.h> #include <asm/head.h> -#include <asm/export.h> /* What we used to do was lock a TLB entry into a specific * TLB slot, clear the page with interrupts disabled, then diff --git a/arch/sparc/lib/copy_user.S b/arch/sparc/lib/copy_user.S index 954572c78539..7bb2ef68881d 100644 --- a/arch/sparc/lib/copy_user.S +++ b/arch/sparc/lib/copy_user.S @@ -12,11 +12,11 @@ * Returns 0 if successful, otherwise count of bytes not copied yet */ +#include <linux/export.h> #include <asm/ptrace.h> #include <asm/asmmacro.h> #include <asm/page.h> #include <asm/thread_info.h> -#include <asm/export.h> /* Work around cpp -rob */ #define ALLOC #alloc diff --git a/arch/sparc/lib/csum_copy.S b/arch/sparc/lib/csum_copy.S index d839956407a7..f968e83bc93b 100644 --- a/arch/sparc/lib/csum_copy.S +++ b/arch/sparc/lib/csum_copy.S @@ -4,7 +4,7 @@ * Copyright (C) 2005 David S. Miller <davem@davemloft.net> */ -#include <asm/export.h> +#include <linux/export.h> #ifdef __KERNEL__ #define GLOBAL_SPARE %g7 diff --git a/arch/sparc/lib/divdi3.S b/arch/sparc/lib/divdi3.S index a7389409d9fa..4ba901acd572 100644 --- a/arch/sparc/lib/divdi3.S +++ b/arch/sparc/lib/divdi3.S @@ -5,7 +5,7 @@ This file is part of GNU CC. */ -#include <asm/export.h> +#include <linux/export.h> .text .align 4 .globl __divdi3 diff --git a/arch/sparc/lib/ffs.S b/arch/sparc/lib/ffs.S index 5a11d864fa05..3a9ad8ffdfe8 100644 --- a/arch/sparc/lib/ffs.S +++ b/arch/sparc/lib/ffs.S @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ +#include <linux/export.h> #include <linux/linkage.h> -#include <asm/export.h> .register %g2,#scratch diff --git a/arch/sparc/lib/fls.S b/arch/sparc/lib/fls.S index 06b8d300bcae..ccf97fb7d8cd 100644 --- a/arch/sparc/lib/fls.S +++ b/arch/sparc/lib/fls.S @@ -5,8 +5,8 @@ * and onward. */ +#include <linux/export.h> #include <linux/linkage.h> -#include <asm/export.h> .text .register %g2, #scratch diff --git a/arch/sparc/lib/fls64.S b/arch/sparc/lib/fls64.S index c83e22ae9586..87005b67d378 100644 --- a/arch/sparc/lib/fls64.S +++ b/arch/sparc/lib/fls64.S @@ -5,8 +5,8 @@ * and onward. */ +#include <linux/export.h> #include <linux/linkage.h> -#include <asm/export.h> .text .register %g2, #scratch diff --git a/arch/sparc/lib/hweight.S b/arch/sparc/lib/hweight.S index 0ddbbb031822..eebee59b0655 100644 --- a/arch/sparc/lib/hweight.S +++ b/arch/sparc/lib/hweight.S @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ +#include <linux/export.h> #include <linux/linkage.h> -#include <asm/export.h> .text .align 32 diff --git a/arch/sparc/lib/ipcsum.S b/arch/sparc/lib/ipcsum.S index 531d89c9d5d9..7fa8fd4b795a 100644 --- a/arch/sparc/lib/ipcsum.S +++ b/arch/sparc/lib/ipcsum.S @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ +#include <linux/export.h> #include <linux/linkage.h> -#include <asm/export.h> .text ENTRY(ip_fast_csum) /* %o0 = iph, %o1 = ihl */ diff --git a/arch/sparc/lib/locks.S b/arch/sparc/lib/locks.S index 9a1289a3fb28..47a39f4384a2 100644 --- a/arch/sparc/lib/locks.S +++ b/arch/sparc/lib/locks.S @@ -7,11 +7,11 @@ * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz) */ +#include <linux/export.h> #include <asm/ptrace.h> #include <asm/psr.h> #include <asm/smp.h> #include <asm/spinlock.h> -#include <asm/export.h> .text .align 4 diff --git a/arch/sparc/lib/lshrdi3.S b/arch/sparc/lib/lshrdi3.S index 509ca6682da8..09bf581a0ba5 100644 --- a/arch/sparc/lib/lshrdi3.S +++ b/arch/sparc/lib/lshrdi3.S @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ +#include <linux/export.h> #include <linux/linkage.h> -#include <asm/export.h> ENTRY(__lshrdi3) cmp %o2, 0 diff --git a/arch/sparc/lib/mcount.S b/arch/sparc/lib/mcount.S index deba6fa0bc78..f7f7910eb41e 100644 --- a/arch/sparc/lib/mcount.S +++ b/arch/sparc/lib/mcount.S @@ -6,8 +6,8 @@ * This can also be tweaked for kernel stack overflow detection. */ +#include <linux/export.h> #include <linux/linkage.h> -#include <asm/export.h> /* * This is the main variant and is called by C code. GCC's -pg option diff --git a/arch/sparc/lib/memcmp.S b/arch/sparc/lib/memcmp.S index a18076ef5af1..c87e8000feba 100644 --- a/arch/sparc/lib/memcmp.S +++ b/arch/sparc/lib/memcmp.S @@ -5,9 +5,9 @@ * Copyright (C) 2000, 2008 David S. Miller (davem@davemloft.net) */ +#include <linux/export.h> #include <linux/linkage.h> #include <asm/asm.h> -#include <asm/export.h> .text ENTRY(memcmp) diff --git a/arch/sparc/lib/memcpy.S b/arch/sparc/lib/memcpy.S index ee823d8c9215..57b1ae0f5924 100644 --- a/arch/sparc/lib/memcpy.S +++ b/arch/sparc/lib/memcpy.S @@ -8,7 +8,8 @@ * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz) */ -#include <asm/export.h> +#include <linux/export.h> + #define FUNC(x) \ .globl x; \ .type x,@function; \ diff --git a/arch/sparc/lib/memmove.S b/arch/sparc/lib/memmove.S index 3132b6316144..543dda7b9dac 100644 --- a/arch/sparc/lib/memmove.S +++ b/arch/sparc/lib/memmove.S @@ -5,8 +5,8 @@ * Copyright (C) 1996, 1997, 1998, 1999 Jakub Jelinek (jj@ultra.linux.cz) */ +#include <linux/export.h> #include <linux/linkage.h> -#include <asm/export.h> .text ENTRY(memmove) /* o0=dst o1=src o2=len */ diff --git a/arch/sparc/lib/memscan_32.S b/arch/sparc/lib/memscan_32.S index c4c2d5b3a2e9..5386a3a20019 100644 --- a/arch/sparc/lib/memscan_32.S +++ b/arch/sparc/lib/memscan_32.S @@ -5,7 +5,7 @@ * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) */ -#include <asm/export.h> +#include <linux/export.h> /* In essence, this is just a fancy strlen. */ diff --git a/arch/sparc/lib/memscan_64.S b/arch/sparc/lib/memscan_64.S index 36dd638905c3..70a4f21057f2 100644 --- a/arch/sparc/lib/memscan_64.S +++ b/arch/sparc/lib/memscan_64.S @@ -6,7 +6,7 @@ * Copyright (C) 1998 David S. Miller (davem@redhat.com) */ - #include <asm/export.h> +#include <linux/export.h> #define HI_MAGIC 0x8080808080808080 #define LO_MAGIC 0x0101010101010101 diff --git a/arch/sparc/lib/memset.S b/arch/sparc/lib/memset.S index eaff68213fdf..a33419dbb464 100644 --- a/arch/sparc/lib/memset.S +++ b/arch/sparc/lib/memset.S @@ -9,8 +9,8 @@ * clear_user. */ +#include <linux/export.h> #include <asm/ptrace.h> -#include <asm/export.h> /* Work around cpp -rob */ #define ALLOC #alloc diff --git a/arch/sparc/lib/muldi3.S b/arch/sparc/lib/muldi3.S index 53054dee66d6..7e1e8cd30a22 100644 --- a/arch/sparc/lib/muldi3.S +++ b/arch/sparc/lib/muldi3.S @@ -5,7 +5,7 @@ This file is part of GNU CC. */ -#include <asm/export.h> +#include <linux/export.h> .text .align 4 .globl __muldi3 diff --git a/arch/sparc/lib/multi3.S b/arch/sparc/lib/multi3.S index 2f187b299345..5bb4c122a2cf 100644 --- a/arch/sparc/lib/multi3.S +++ b/arch/sparc/lib/multi3.S @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ +#include <linux/export.h> #include <linux/linkage.h> -#include <asm/export.h> .text .align 4 diff --git a/arch/sparc/lib/strlen.S b/arch/sparc/lib/strlen.S index dd111bbad5df..27478b3f1647 100644 --- a/arch/sparc/lib/strlen.S +++ b/arch/sparc/lib/strlen.S @@ -6,9 +6,9 @@ * Copyright (C) 1996, 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) */ +#include <linux/export.h> #include <linux/linkage.h> #include <asm/asm.h> -#include <asm/export.h> #define LO_MAGIC 0x01010101 #define HI_MAGIC 0x80808080 diff --git a/arch/sparc/lib/strncmp_32.S b/arch/sparc/lib/strncmp_32.S index 794733f036b6..387bbf621548 100644 --- a/arch/sparc/lib/strncmp_32.S +++ b/arch/sparc/lib/strncmp_32.S @@ -4,8 +4,8 @@ * generic strncmp routine. */ +#include <linux/export.h> #include <linux/linkage.h> -#include <asm/export.h> .text ENTRY(strncmp) diff --git a/arch/sparc/lib/strncmp_64.S b/arch/sparc/lib/strncmp_64.S index 3d37d65f674c..76c1207ecf5a 100644 --- a/arch/sparc/lib/strncmp_64.S +++ b/arch/sparc/lib/strncmp_64.S @@ -5,9 +5,9 @@ * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) */ +#include <linux/export.h> #include <linux/linkage.h> #include <asm/asi.h> -#include <asm/export.h> .text ENTRY(strncmp) diff --git a/arch/sparc/lib/xor.S b/arch/sparc/lib/xor.S index f6af7c7ee6fc..35461e3b2a9b 100644 --- a/arch/sparc/lib/xor.S +++ b/arch/sparc/lib/xor.S @@ -9,12 +9,12 @@ * Copyright (C) 2006 David S. Miller <davem@davemloft.net> */ +#include <linux/export.h> #include <linux/linkage.h> #include <asm/visasm.h> #include <asm/asi.h> #include <asm/dcu.h> #include <asm/spitfire.h> -#include <asm/export.h> /* * Requirements: diff --git a/arch/um/Kbuild b/arch/um/Kbuild index a4e40e534e6a..6cf0c1e5927b 100644 --- a/arch/um/Kbuild +++ b/arch/um/Kbuild @@ -1 +1,3 @@ # SPDX-License-Identifier: GPL-2.0-only + +obj-y += kernel/ drivers/ os-Linux/ diff --git a/arch/um/Makefile b/arch/um/Makefile index da4d5256af2f..82f05f250634 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -18,15 +18,10 @@ else endif ARCH_DIR := arch/um -OS := $(shell uname -s) # We require bash because the vmlinux link and loader script cpp use bash # features. SHELL := /bin/bash -core-y += $(ARCH_DIR)/kernel/ \ - $(ARCH_DIR)/drivers/ \ - $(ARCH_DIR)/os-$(OS)/ - MODE_INCLUDE += -I$(srctree)/$(ARCH_DIR)/include/shared/skas HEADER_ARCH := $(SUBARCH) @@ -78,7 +73,7 @@ USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -I%,,$(KBUILD_CFLAGS))) \ -idirafter $(objtree)/include -D__KERNEL__ -D__UM_HOST__ #This will adjust *FLAGS accordingly to the platform. -include $(srctree)/$(ARCH_DIR)/Makefile-os-$(OS) +include $(srctree)/$(ARCH_DIR)/Makefile-os-Linux KBUILD_CPPFLAGS += -I$(srctree)/$(HOST_DIR)/include \ -I$(srctree)/$(HOST_DIR)/include/uapi \ @@ -155,4 +150,4 @@ archclean: @find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \ -o -name '*.gcov' \) -type f -print | xargs rm -f -export HEADER_ARCH SUBARCH USER_CFLAGS CFLAGS_NO_HARDENING OS DEV_NULL_PATH +export HEADER_ARCH SUBARCH USER_CFLAGS CFLAGS_NO_HARDENING DEV_NULL_PATH diff --git a/arch/um/configs/i386_defconfig b/arch/um/configs/i386_defconfig index 630be793759e..e543cbac8792 100644 --- a/arch/um/configs/i386_defconfig +++ b/arch/um/configs/i386_defconfig @@ -34,6 +34,7 @@ CONFIG_TTY_CHAN=y CONFIG_XTERM_CHAN=y CONFIG_CON_CHAN="pts" CONFIG_SSL_CHAN="pts" +CONFIG_SOUND=m CONFIG_UML_SOUND=m CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y diff --git a/arch/um/configs/x86_64_defconfig b/arch/um/configs/x86_64_defconfig index 8540d3370272..939cb12318ca 100644 --- a/arch/um/configs/x86_64_defconfig +++ b/arch/um/configs/x86_64_defconfig @@ -32,6 +32,7 @@ CONFIG_TTY_CHAN=y CONFIG_XTERM_CHAN=y CONFIG_CON_CHAN="pts" CONFIG_SSL_CHAN="pts" +CONFIG_SOUND=m CONFIG_UML_SOUND=m CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y diff --git a/arch/um/drivers/Kconfig b/arch/um/drivers/Kconfig index 36911b1fddcf..b94b2618e7d8 100644 --- a/arch/um/drivers/Kconfig +++ b/arch/um/drivers/Kconfig @@ -111,24 +111,14 @@ config SSL_CHAN config UML_SOUND tristate "Sound support" + depends on SOUND + select SOUND_OSS_CORE help This option enables UML sound support. If enabled, it will pull in - soundcore and the UML hostaudio relay, which acts as a intermediary + the UML hostaudio relay, which acts as a intermediary between the host's dsp and mixer devices and the UML sound system. It is safe to say 'Y' here. -config SOUND - tristate - default UML_SOUND - -config SOUND_OSS_CORE - bool - default UML_SOUND - -config HOSTAUDIO - tristate - default UML_SOUND - endmenu menu "UML Network Devices" diff --git a/arch/um/drivers/Makefile b/arch/um/drivers/Makefile index a461a950f051..0e6af81096fd 100644 --- a/arch/um/drivers/Makefile +++ b/arch/um/drivers/Makefile @@ -54,7 +54,7 @@ obj-$(CONFIG_UML_NET) += net.o obj-$(CONFIG_MCONSOLE) += mconsole.o obj-$(CONFIG_MMAPPER) += mmapper_kern.o obj-$(CONFIG_BLK_DEV_UBD) += ubd.o -obj-$(CONFIG_HOSTAUDIO) += hostaudio.o +obj-$(CONFIG_UML_SOUND) += hostaudio.o obj-$(CONFIG_NULL_CHAN) += null.o obj-$(CONFIG_PORT_CHAN) += port.o obj-$(CONFIG_PTY_CHAN) += pty.o diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c index 5b064d360cb7..c42b793bce65 100644 --- a/arch/um/drivers/hostaudio_kern.c +++ b/arch/um/drivers/hostaudio_kern.c @@ -310,7 +310,7 @@ static const struct file_operations hostmixer_fops = { .release = hostmixer_release, }; -struct { +static struct { int dev_audio; int dev_mixer; } module_data; diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c index efa8b7304090..c52b3ff3c092 100644 --- a/arch/um/drivers/port_kern.c +++ b/arch/um/drivers/port_kern.c @@ -144,7 +144,7 @@ static void port_work_proc(struct work_struct *unused) local_irq_restore(flags); } -DECLARE_WORK(port_work, port_work_proc); +static DECLARE_WORK(port_work, port_work_proc); static irqreturn_t port_interrupt(int irq, void *data) { diff --git a/arch/um/drivers/slirp_kern.c b/arch/um/drivers/slirp_kern.c index 2d9769237f08..0a6151ee9572 100644 --- a/arch/um/drivers/slirp_kern.c +++ b/arch/um/drivers/slirp_kern.c @@ -15,7 +15,7 @@ struct slirp_init { struct arg_list_dummy_wrapper argw; /* XXX should be simpler... */ }; -void slirp_init(struct net_device *dev, void *data) +static void slirp_init(struct net_device *dev, void *data) { struct uml_net_private *private; struct slirp_data *spri; diff --git a/arch/um/drivers/virt-pci.c b/arch/um/drivers/virt-pci.c index 7699ca5f35d4..ffe2ee8a0246 100644 --- a/arch/um/drivers/virt-pci.c +++ b/arch/um/drivers/virt-pci.c @@ -544,6 +544,7 @@ static void um_pci_irq_vq_cb(struct virtqueue *vq) } } +#ifdef CONFIG_OF /* Copied from arch/x86/kernel/devicetree.c */ struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus) { @@ -562,6 +563,7 @@ struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus) } return NULL; } +#endif static int um_pci_init_vqs(struct um_pci_device *dev) { diff --git a/arch/um/drivers/xterm_kern.c b/arch/um/drivers/xterm_kern.c index 50f11b7b4774..8011e51993d5 100644 --- a/arch/um/drivers/xterm_kern.c +++ b/arch/um/drivers/xterm_kern.c @@ -9,6 +9,7 @@ #include <asm/irq.h> #include <irq_kern.h> #include <os.h> +#include "xterm.h" struct xterm_wait { struct completion ready; diff --git a/arch/um/include/shared/irq_kern.h b/arch/um/include/shared/irq_kern.h index f2dc817abb7c..44357fa6ee29 100644 --- a/arch/um/include/shared/irq_kern.h +++ b/arch/um/include/shared/irq_kern.h @@ -76,4 +76,5 @@ static inline bool um_irq_timetravel_handler_used(void) } void um_free_irq(int irq, void *dev_id); +void free_irqs(void); #endif diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c index a8873d9bc28b..635d44606bfe 100644 --- a/arch/um/kernel/irq.c +++ b/arch/um/kernel/irq.c @@ -23,8 +23,6 @@ #include <linux/time-internal.h> -extern void free_irqs(void); - /* When epoll triggers we do not know why it did so * we can also have different IRQs for read and write. * This is why we keep a small irq_reg array for each fd - diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 95315d3474a2..5bfe5caaa444 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -335,9 +335,5 @@ define archhelp echo ' bzdisk/fdimage*/hdimage/isoimage also accept:' echo ' FDARGS="..." arguments for the booted kernel' echo ' FDINITRD=file initrd for the booted kernel' - echo '' - echo ' kvm_guest.config - Enable Kconfig items for running this kernel as a KVM guest' - echo ' xen.config - Enable Kconfig items for running this kernel as a Xen guest' - echo ' x86_debug.config - Enable tip tree debugging options for testing' endef diff --git a/arch/x86/hyperv/hv_apic.c b/arch/x86/hyperv/hv_apic.c index 187e13b15e9a..97bfe5f0531f 100644 --- a/arch/x86/hyperv/hv_apic.c +++ b/arch/x86/hyperv/hv_apic.c @@ -175,8 +175,11 @@ static bool __send_ipi_mask(const struct cpumask *mask, int vector, (exclude_self && weight == 1 && cpumask_test_cpu(this_cpu, mask))) return true; - if (!hv_hypercall_pg) - return false; + /* A fully enlightened TDX VM uses GHCI rather than hv_hypercall_pg. */ + if (!hv_hypercall_pg) { + if (ms_hyperv.paravisor_present || !hv_isolation_type_tdx()) + return false; + } if ((vector < HV_IPI_LOW_VECTOR) || (vector > HV_IPI_HIGH_VECTOR)) return false; @@ -229,9 +232,15 @@ static bool __send_ipi_one(int cpu, int vector) trace_hyperv_send_ipi_one(cpu, vector); - if (!hv_hypercall_pg || (vp == VP_INVAL)) + if (vp == VP_INVAL) return false; + /* A fully enlightened TDX VM uses GHCI rather than hv_hypercall_pg. */ + if (!hv_hypercall_pg) { + if (ms_hyperv.paravisor_present || !hv_isolation_type_tdx()) + return false; + } + if ((vector < HV_IPI_LOW_VECTOR) || (vector > HV_IPI_HIGH_VECTOR)) return false; diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index 507d98331e7c..783ed339f341 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -19,6 +19,7 @@ #include <asm/hyperv-tlfs.h> #include <asm/mshyperv.h> #include <asm/idtentry.h> +#include <asm/set_memory.h> #include <linux/kexec.h> #include <linux/version.h> #include <linux/vmalloc.h> @@ -52,7 +53,7 @@ static int hyperv_init_ghcb(void) void *ghcb_va; void **ghcb_base; - if (!hv_isolation_type_snp()) + if (!ms_hyperv.paravisor_present || !hv_isolation_type_snp()) return 0; if (!hv_ghcb_pg) @@ -80,7 +81,7 @@ static int hyperv_init_ghcb(void) static int hv_cpu_init(unsigned int cpu) { union hv_vp_assist_msr_contents msr = { 0 }; - struct hv_vp_assist_page **hvp = &hv_vp_assist_page[cpu]; + struct hv_vp_assist_page **hvp; int ret; ret = hv_common_cpu_init(cpu); @@ -90,6 +91,7 @@ static int hv_cpu_init(unsigned int cpu) if (!hv_vp_assist_page) return 0; + hvp = &hv_vp_assist_page[cpu]; if (hv_root_partition) { /* * For root partition we get the hypervisor provided VP assist @@ -107,8 +109,21 @@ static int hv_cpu_init(unsigned int cpu) * in hv_cpu_die(), otherwise a CPU may not be stopped in the * case of CPU offlining and the VM will hang. */ - if (!*hvp) + if (!*hvp) { *hvp = __vmalloc(PAGE_SIZE, GFP_KERNEL | __GFP_ZERO); + + /* + * Hyper-V should never specify a VM that is a Confidential + * VM and also running in the root partition. Root partition + * is blocked to run in Confidential VM. So only decrypt assist + * page in non-root partition here. + */ + if (*hvp && !ms_hyperv.paravisor_present && hv_isolation_type_snp()) { + WARN_ON_ONCE(set_memory_decrypted((unsigned long)(*hvp), 1)); + memset(*hvp, 0, PAGE_SIZE); + } + } + if (*hvp) msr.pfn = vmalloc_to_pfn(*hvp); @@ -379,6 +394,36 @@ static void __init hv_get_partition_id(void) local_irq_restore(flags); } +static u8 __init get_vtl(void) +{ + u64 control = HV_HYPERCALL_REP_COMP_1 | HVCALL_GET_VP_REGISTERS; + struct hv_get_vp_registers_input *input; + struct hv_get_vp_registers_output *output; + unsigned long flags; + u64 ret; + + local_irq_save(flags); + input = *this_cpu_ptr(hyperv_pcpu_input_arg); + output = (struct hv_get_vp_registers_output *)input; + + memset(input, 0, struct_size(input, element, 1)); + input->header.partitionid = HV_PARTITION_ID_SELF; + input->header.vpindex = HV_VP_INDEX_SELF; + input->header.inputvtl = 0; + input->element[0].name0 = HV_X64_REGISTER_VSM_VP_STATUS; + + ret = hv_do_hypercall(control, input, output); + if (hv_result_success(ret)) { + ret = output->as64.low & HV_X64_VTL_MASK; + } else { + pr_err("Failed to get VTL(%lld) and set VTL to zero by default.\n", ret); + ret = 0; + } + + local_irq_restore(flags); + return ret; +} + /* * This function is to be invoked early in the boot sequence after the * hypervisor has been detected. @@ -399,14 +444,24 @@ void __init hyperv_init(void) if (hv_common_init()) return; - hv_vp_assist_page = kcalloc(num_possible_cpus(), - sizeof(*hv_vp_assist_page), GFP_KERNEL); + /* + * The VP assist page is useless to a TDX guest: the only use we + * would have for it is lazy EOI, which can not be used with TDX. + */ + if (hv_isolation_type_tdx()) + hv_vp_assist_page = NULL; + else + hv_vp_assist_page = kcalloc(num_possible_cpus(), + sizeof(*hv_vp_assist_page), + GFP_KERNEL); if (!hv_vp_assist_page) { ms_hyperv.hints &= ~HV_X64_ENLIGHTENED_VMCS_RECOMMENDED; - goto common_free; + + if (!hv_isolation_type_tdx()) + goto common_free; } - if (hv_isolation_type_snp()) { + if (ms_hyperv.paravisor_present && hv_isolation_type_snp()) { /* Negotiate GHCB Version. */ if (!hv_ghcb_negotiate_protocol()) hv_ghcb_terminate(SEV_TERM_SET_GEN, @@ -426,12 +481,32 @@ void __init hyperv_init(void) * Setup the hypercall page and enable hypercalls. * 1. Register the guest ID * 2. Enable the hypercall and register the hypercall page + * + * A TDX VM with no paravisor only uses TDX GHCI rather than hv_hypercall_pg: + * when the hypercall input is a page, such a VM must pass a decrypted + * page to Hyper-V, e.g. hv_post_message() uses the per-CPU page + * hyperv_pcpu_input_arg, which is decrypted if no paravisor is present. + * + * A TDX VM with the paravisor uses hv_hypercall_pg for most hypercalls, + * which are handled by the paravisor and the VM must use an encrypted + * input page: in such a VM, the hyperv_pcpu_input_arg is encrypted and + * used in the hypercalls, e.g. see hv_mark_gpa_visibility() and + * hv_arch_irq_unmask(). Such a VM uses TDX GHCI for two hypercalls: + * 1. HVCALL_SIGNAL_EVENT: see vmbus_set_event() and _hv_do_fast_hypercall8(). + * 2. HVCALL_POST_MESSAGE: the input page must be a decrypted page, i.e. + * hv_post_message() in such a VM can't use the encrypted hyperv_pcpu_input_arg; + * instead, hv_post_message() uses the post_msg_page, which is decrypted + * in such a VM and is only used in such a VM. */ guest_id = hv_generate_guest_id(LINUX_VERSION_CODE); wrmsrl(HV_X64_MSR_GUEST_OS_ID, guest_id); - /* Hyper-V requires to write guest os id via ghcb in SNP IVM. */ - hv_ghcb_msr_write(HV_X64_MSR_GUEST_OS_ID, guest_id); + /* With the paravisor, the VM must also write the ID via GHCB/GHCI */ + hv_ivm_msr_write(HV_X64_MSR_GUEST_OS_ID, guest_id); + + /* A TDX VM with no paravisor only uses TDX GHCI rather than hv_hypercall_pg */ + if (hv_isolation_type_tdx() && !ms_hyperv.paravisor_present) + goto skip_hypercall_pg_init; hv_hypercall_pg = __vmalloc_node_range(PAGE_SIZE, 1, VMALLOC_START, VMALLOC_END, GFP_KERNEL, PAGE_KERNEL_ROX, @@ -472,6 +547,7 @@ void __init hyperv_init(void) wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); } +skip_hypercall_pg_init: /* * Some versions of Hyper-V that provide IBT in guest VMs have a bug * in that there's no ENDBR64 instruction at the entry to the @@ -527,11 +603,15 @@ void __init hyperv_init(void) /* Query the VMs extended capability once, so that it can be cached. */ hv_query_ext_cap(0); + /* Find the VTL */ + if (!ms_hyperv.paravisor_present && hv_isolation_type_snp()) + ms_hyperv.vtl = get_vtl(); + return; clean_guest_os_id: wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0); - hv_ghcb_msr_write(HV_X64_MSR_GUEST_OS_ID, 0); + hv_ivm_msr_write(HV_X64_MSR_GUEST_OS_ID, 0); cpuhp_remove_state(cpuhp); free_ghcb_page: free_percpu(hv_ghcb_pg); @@ -552,7 +632,7 @@ void hyperv_cleanup(void) /* Reset our OS id */ wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0); - hv_ghcb_msr_write(HV_X64_MSR_GUEST_OS_ID, 0); + hv_ivm_msr_write(HV_X64_MSR_GUEST_OS_ID, 0); /* * Reset hypercall page reference before reset the page, @@ -615,6 +695,9 @@ bool hv_is_hyperv_initialized(void) if (x86_hyper_type != X86_HYPER_MS_HYPERV) return false; + /* A TDX VM with no paravisor uses TDX GHCI call rather than hv_hypercall_pg */ + if (hv_isolation_type_tdx() && !ms_hyperv.paravisor_present) + return true; /* * Verify that earlier initialization succeeded by checking * that the hypercall page is setup diff --git a/arch/x86/hyperv/ivm.c b/arch/x86/hyperv/ivm.c index 28be6df88063..8c6bf07f7d2b 100644 --- a/arch/x86/hyperv/ivm.c +++ b/arch/x86/hyperv/ivm.c @@ -18,6 +18,11 @@ #include <asm/mshyperv.h> #include <asm/hypervisor.h> #include <asm/mtrr.h> +#include <asm/io_apic.h> +#include <asm/realmode.h> +#include <asm/e820/api.h> +#include <asm/desc.h> +#include <uapi/asm/vmx.h> #ifdef CONFIG_AMD_MEM_ENCRYPT @@ -56,8 +61,10 @@ union hv_ghcb { } hypercall; } __packed __aligned(HV_HYP_PAGE_SIZE); +/* Only used in an SNP VM with the paravisor */ static u16 hv_ghcb_version __ro_after_init; +/* Functions only used in an SNP VM with the paravisor go here. */ u64 hv_ghcb_hypercall(u64 control, void *input, void *output, u32 input_size) { union hv_ghcb *hv_ghcb; @@ -175,7 +182,7 @@ bool hv_ghcb_negotiate_protocol(void) return true; } -void hv_ghcb_msr_write(u64 msr, u64 value) +static void hv_ghcb_msr_write(u64 msr, u64 value) { union hv_ghcb *hv_ghcb; void **ghcb_base; @@ -203,9 +210,8 @@ void hv_ghcb_msr_write(u64 msr, u64 value) local_irq_restore(flags); } -EXPORT_SYMBOL_GPL(hv_ghcb_msr_write); -void hv_ghcb_msr_read(u64 msr, u64 *value) +static void hv_ghcb_msr_read(u64 msr, u64 *value) { union hv_ghcb *hv_ghcb; void **ghcb_base; @@ -235,7 +241,217 @@ void hv_ghcb_msr_read(u64 msr, u64 *value) | ((u64)lower_32_bits(hv_ghcb->ghcb.save.rdx) << 32); local_irq_restore(flags); } -EXPORT_SYMBOL_GPL(hv_ghcb_msr_read); + +/* Only used in a fully enlightened SNP VM, i.e. without the paravisor */ +static u8 ap_start_input_arg[PAGE_SIZE] __bss_decrypted __aligned(PAGE_SIZE); +static u8 ap_start_stack[PAGE_SIZE] __aligned(PAGE_SIZE); +static DEFINE_PER_CPU(struct sev_es_save_area *, hv_sev_vmsa); + +/* Functions only used in an SNP VM without the paravisor go here. */ + +#define hv_populate_vmcb_seg(seg, gdtr_base) \ +do { \ + if (seg.selector) { \ + seg.base = 0; \ + seg.limit = HV_AP_SEGMENT_LIMIT; \ + seg.attrib = *(u16 *)(gdtr_base + seg.selector + 5); \ + seg.attrib = (seg.attrib & 0xFF) | ((seg.attrib >> 4) & 0xF00); \ + } \ +} while (0) \ + +static int snp_set_vmsa(void *va, bool vmsa) +{ + u64 attrs; + + /* + * Running at VMPL0 allows the kernel to change the VMSA bit for a page + * using the RMPADJUST instruction. However, for the instruction to + * succeed it must target the permissions of a lesser privileged + * (higher numbered) VMPL level, so use VMPL1 (refer to the RMPADJUST + * instruction in the AMD64 APM Volume 3). + */ + attrs = 1; + if (vmsa) + attrs |= RMPADJUST_VMSA_PAGE_BIT; + + return rmpadjust((unsigned long)va, RMP_PG_SIZE_4K, attrs); +} + +static void snp_cleanup_vmsa(struct sev_es_save_area *vmsa) +{ + int err; + + err = snp_set_vmsa(vmsa, false); + if (err) + pr_err("clear VMSA page failed (%u), leaking page\n", err); + else + free_page((unsigned long)vmsa); +} + +int hv_snp_boot_ap(int cpu, unsigned long start_ip) +{ + struct sev_es_save_area *vmsa = (struct sev_es_save_area *) + __get_free_page(GFP_KERNEL | __GFP_ZERO); + struct sev_es_save_area *cur_vmsa; + struct desc_ptr gdtr; + u64 ret, retry = 5; + struct hv_enable_vp_vtl *start_vp_input; + unsigned long flags; + + if (!vmsa) + return -ENOMEM; + + native_store_gdt(&gdtr); + + vmsa->gdtr.base = gdtr.address; + vmsa->gdtr.limit = gdtr.size; + + asm volatile("movl %%es, %%eax;" : "=a" (vmsa->es.selector)); + hv_populate_vmcb_seg(vmsa->es, vmsa->gdtr.base); + + asm volatile("movl %%cs, %%eax;" : "=a" (vmsa->cs.selector)); + hv_populate_vmcb_seg(vmsa->cs, vmsa->gdtr.base); + + asm volatile("movl %%ss, %%eax;" : "=a" (vmsa->ss.selector)); + hv_populate_vmcb_seg(vmsa->ss, vmsa->gdtr.base); + + asm volatile("movl %%ds, %%eax;" : "=a" (vmsa->ds.selector)); + hv_populate_vmcb_seg(vmsa->ds, vmsa->gdtr.base); + + vmsa->efer = native_read_msr(MSR_EFER); + + asm volatile("movq %%cr4, %%rax;" : "=a" (vmsa->cr4)); + asm volatile("movq %%cr3, %%rax;" : "=a" (vmsa->cr3)); + asm volatile("movq %%cr0, %%rax;" : "=a" (vmsa->cr0)); + + vmsa->xcr0 = 1; + vmsa->g_pat = HV_AP_INIT_GPAT_DEFAULT; + vmsa->rip = (u64)secondary_startup_64_no_verify; + vmsa->rsp = (u64)&ap_start_stack[PAGE_SIZE]; + + /* + * Set the SNP-specific fields for this VMSA: + * VMPL level + * SEV_FEATURES (matches the SEV STATUS MSR right shifted 2 bits) + */ + vmsa->vmpl = 0; + vmsa->sev_features = sev_status >> 2; + + ret = snp_set_vmsa(vmsa, true); + if (!ret) { + pr_err("RMPADJUST(%llx) failed: %llx\n", (u64)vmsa, ret); + free_page((u64)vmsa); + return ret; + } + + local_irq_save(flags); + start_vp_input = (struct hv_enable_vp_vtl *)ap_start_input_arg; + memset(start_vp_input, 0, sizeof(*start_vp_input)); + start_vp_input->partition_id = -1; + start_vp_input->vp_index = cpu; + start_vp_input->target_vtl.target_vtl = ms_hyperv.vtl; + *(u64 *)&start_vp_input->vp_context = __pa(vmsa) | 1; + + do { + ret = hv_do_hypercall(HVCALL_START_VP, + start_vp_input, NULL); + } while (hv_result(ret) == HV_STATUS_TIME_OUT && retry--); + + local_irq_restore(flags); + + if (!hv_result_success(ret)) { + pr_err("HvCallStartVirtualProcessor failed: %llx\n", ret); + snp_cleanup_vmsa(vmsa); + vmsa = NULL; + } + + cur_vmsa = per_cpu(hv_sev_vmsa, cpu); + /* Free up any previous VMSA page */ + if (cur_vmsa) + snp_cleanup_vmsa(cur_vmsa); + + /* Record the current VMSA page */ + per_cpu(hv_sev_vmsa, cpu) = vmsa; + + return ret; +} + +#else +static inline void hv_ghcb_msr_write(u64 msr, u64 value) {} +static inline void hv_ghcb_msr_read(u64 msr, u64 *value) {} +#endif /* CONFIG_AMD_MEM_ENCRYPT */ + +#ifdef CONFIG_INTEL_TDX_GUEST +static void hv_tdx_msr_write(u64 msr, u64 val) +{ + struct tdx_hypercall_args args = { + .r10 = TDX_HYPERCALL_STANDARD, + .r11 = EXIT_REASON_MSR_WRITE, + .r12 = msr, + .r13 = val, + }; + + u64 ret = __tdx_hypercall(&args); + + WARN_ONCE(ret, "Failed to emulate MSR write: %lld\n", ret); +} + +static void hv_tdx_msr_read(u64 msr, u64 *val) +{ + struct tdx_hypercall_args args = { + .r10 = TDX_HYPERCALL_STANDARD, + .r11 = EXIT_REASON_MSR_READ, + .r12 = msr, + }; + + u64 ret = __tdx_hypercall_ret(&args); + + if (WARN_ONCE(ret, "Failed to emulate MSR read: %lld\n", ret)) + *val = 0; + else + *val = args.r11; +} + +u64 hv_tdx_hypercall(u64 control, u64 param1, u64 param2) +{ + struct tdx_hypercall_args args = { }; + + args.r10 = control; + args.rdx = param1; + args.r8 = param2; + + (void)__tdx_hypercall_ret(&args); + + return args.r11; +} + +#else +static inline void hv_tdx_msr_write(u64 msr, u64 value) {} +static inline void hv_tdx_msr_read(u64 msr, u64 *value) {} +#endif /* CONFIG_INTEL_TDX_GUEST */ + +#if defined(CONFIG_AMD_MEM_ENCRYPT) || defined(CONFIG_INTEL_TDX_GUEST) +void hv_ivm_msr_write(u64 msr, u64 value) +{ + if (!ms_hyperv.paravisor_present) + return; + + if (hv_isolation_type_tdx()) + hv_tdx_msr_write(msr, value); + else if (hv_isolation_type_snp()) + hv_ghcb_msr_write(msr, value); +} + +void hv_ivm_msr_read(u64 msr, u64 *value) +{ + if (!ms_hyperv.paravisor_present) + return; + + if (hv_isolation_type_tdx()) + hv_tdx_msr_read(msr, value); + else if (hv_isolation_type_snp()) + hv_ghcb_msr_read(msr, value); +} /* * hv_mark_gpa_visibility - Set pages visible to host via hvcall. @@ -358,13 +574,34 @@ static bool hv_is_private_mmio(u64 addr) void __init hv_vtom_init(void) { + enum hv_isolation_type type = hv_get_isolation_type(); + + switch (type) { + case HV_ISOLATION_TYPE_VBS: + fallthrough; /* * By design, a VM using vTOM doesn't see the SEV setting, * so SEV initialization is bypassed and sev_status isn't set. * Set it here to indicate a vTOM VM. + * + * Note: if CONFIG_AMD_MEM_ENCRYPT is not set, sev_status is + * defined as 0ULL, to which we can't assigned a value. */ - sev_status = MSR_AMD64_SNP_VTOM; - cc_vendor = CC_VENDOR_AMD; +#ifdef CONFIG_AMD_MEM_ENCRYPT + case HV_ISOLATION_TYPE_SNP: + sev_status = MSR_AMD64_SNP_VTOM; + cc_vendor = CC_VENDOR_AMD; + break; +#endif + + case HV_ISOLATION_TYPE_TDX: + cc_vendor = CC_VENDOR_INTEL; + break; + + default: + panic("hv_vtom_init: unsupported isolation type %d\n", type); + } + cc_set_mask(ms_hyperv.shared_gpa_boundary); physical_mask &= ms_hyperv.shared_gpa_boundary - 1; @@ -377,7 +614,7 @@ void __init hv_vtom_init(void) mtrr_overwrite_state(NULL, 0, MTRR_TYPE_WRBACK); } -#endif /* CONFIG_AMD_MEM_ENCRYPT */ +#endif /* defined(CONFIG_AMD_MEM_ENCRYPT) || defined(CONFIG_INTEL_TDX_GUEST) */ enum hv_isolation_type hv_get_isolation_type(void) { @@ -405,10 +642,20 @@ bool hv_is_isolation_supported(void) DEFINE_STATIC_KEY_FALSE(isolation_type_snp); /* - * hv_isolation_type_snp - Check system runs in the AMD SEV-SNP based + * hv_isolation_type_snp - Check if the system runs in an AMD SEV-SNP based * isolation VM. */ bool hv_isolation_type_snp(void) { return static_branch_unlikely(&isolation_type_snp); } + +DEFINE_STATIC_KEY_FALSE(isolation_type_tdx); +/* + * hv_isolation_type_tdx - Check if the system runs in an Intel TDX based + * isolated VM. + */ +bool hv_isolation_type_tdx(void) +{ + return static_branch_unlikely(&isolation_type_tdx); +} diff --git a/arch/x86/include/asm/hyperv-tlfs.h b/arch/x86/include/asm/hyperv-tlfs.h index cea95dcd27c2..2ff26f53cd62 100644 --- a/arch/x86/include/asm/hyperv-tlfs.h +++ b/arch/x86/include/asm/hyperv-tlfs.h @@ -169,7 +169,8 @@ enum hv_isolation_type { HV_ISOLATION_TYPE_NONE = 0, HV_ISOLATION_TYPE_VBS = 1, - HV_ISOLATION_TYPE_SNP = 2 + HV_ISOLATION_TYPE_SNP = 2, + HV_ISOLATION_TYPE_TDX = 3 }; /* Hyper-V specific model specific registers (MSRs) */ @@ -301,6 +302,13 @@ enum hv_isolation_type { #define HV_X64_MSR_TIME_REF_COUNT HV_REGISTER_TIME_REF_COUNT #define HV_X64_MSR_REFERENCE_TSC HV_REGISTER_REFERENCE_TSC +/* + * Registers are only accessible via HVCALL_GET_VP_REGISTERS hvcall and + * there is not associated MSR address. + */ +#define HV_X64_REGISTER_VSM_VP_STATUS 0x000D0003 +#define HV_X64_VTL_MASK GENMASK(3, 0) + /* Hyper-V memory host visibility */ enum hv_mem_host_visibility { VMBUS_PAGE_NOT_VISIBLE = 0, diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index fa83d88e4c99..033b53f993c6 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -26,6 +26,7 @@ union hv_ghcb; DECLARE_STATIC_KEY_FALSE(isolation_type_snp); +DECLARE_STATIC_KEY_FALSE(isolation_type_tdx); typedef int (*hyperv_fill_flush_list_func)( struct hv_guest_mapping_flush_list *flush, @@ -40,6 +41,7 @@ static inline unsigned char hv_get_nmi_reason(void) #if IS_ENABLED(CONFIG_HYPERV) extern int hyperv_init_cpuhp; +extern bool hyperv_paravisor_present; extern void *hv_hypercall_pg; @@ -47,10 +49,25 @@ extern u64 hv_current_partition_id; extern union hv_ghcb * __percpu *hv_ghcb_pg; +bool hv_isolation_type_snp(void); +bool hv_isolation_type_tdx(void); +u64 hv_tdx_hypercall(u64 control, u64 param1, u64 param2); + +/* + * DEFAULT INIT GPAT and SEGMENT LIMIT value in struct VMSA + * to start AP in enlightened SEV guest. + */ +#define HV_AP_INIT_GPAT_DEFAULT 0x0007040600070406ULL +#define HV_AP_SEGMENT_LIMIT 0xffffffff + int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages); int hv_call_add_logical_proc(int node, u32 lp_index, u32 acpi_id); int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags); +/* + * If the hypercall involves no input or output parameters, the hypervisor + * ignores the corresponding GPA pointer. + */ static inline u64 hv_do_hypercall(u64 control, void *input, void *output) { u64 input_address = input ? virt_to_phys(input) : 0; @@ -58,6 +75,19 @@ static inline u64 hv_do_hypercall(u64 control, void *input, void *output) u64 hv_status; #ifdef CONFIG_X86_64 + if (hv_isolation_type_tdx() && !hyperv_paravisor_present) + return hv_tdx_hypercall(control, input_address, output_address); + + if (hv_isolation_type_snp() && !hyperv_paravisor_present) { + __asm__ __volatile__("mov %4, %%r8\n" + "vmmcall" + : "=a" (hv_status), ASM_CALL_CONSTRAINT, + "+c" (control), "+d" (input_address) + : "r" (output_address) + : "cc", "memory", "r8", "r9", "r10", "r11"); + return hv_status; + } + if (!hv_hypercall_pg) return U64_MAX; @@ -101,7 +131,16 @@ static inline u64 _hv_do_fast_hypercall8(u64 control, u64 input1) u64 hv_status; #ifdef CONFIG_X86_64 - { + if (hv_isolation_type_tdx() && !hyperv_paravisor_present) + return hv_tdx_hypercall(control, input1, 0); + + if (hv_isolation_type_snp() && !hyperv_paravisor_present) { + __asm__ __volatile__( + "vmmcall" + : "=a" (hv_status), ASM_CALL_CONSTRAINT, + "+c" (control), "+d" (input1) + :: "cc", "r8", "r9", "r10", "r11"); + } else { __asm__ __volatile__(CALL_NOSPEC : "=a" (hv_status), ASM_CALL_CONSTRAINT, "+c" (control), "+d" (input1) @@ -146,7 +185,17 @@ static inline u64 _hv_do_fast_hypercall16(u64 control, u64 input1, u64 input2) u64 hv_status; #ifdef CONFIG_X86_64 - { + if (hv_isolation_type_tdx() && !hyperv_paravisor_present) + return hv_tdx_hypercall(control, input1, input2); + + if (hv_isolation_type_snp() && !hyperv_paravisor_present) { + __asm__ __volatile__("mov %4, %%r8\n" + "vmmcall" + : "=a" (hv_status), ASM_CALL_CONSTRAINT, + "+c" (control), "+d" (input1) + : "r" (input2) + : "cc", "r8", "r9", "r10", "r11"); + } else { __asm__ __volatile__("mov %4, %%r8\n" CALL_NOSPEC : "=a" (hv_status), ASM_CALL_CONSTRAINT, @@ -225,20 +274,24 @@ int hv_map_ioapic_interrupt(int ioapic_id, bool level, int vcpu, int vector, int hv_unmap_ioapic_interrupt(int ioapic_id, struct hv_interrupt_entry *entry); #ifdef CONFIG_AMD_MEM_ENCRYPT -void hv_ghcb_msr_write(u64 msr, u64 value); -void hv_ghcb_msr_read(u64 msr, u64 *value); bool hv_ghcb_negotiate_protocol(void); void __noreturn hv_ghcb_terminate(unsigned int set, unsigned int reason); -void hv_vtom_init(void); +int hv_snp_boot_ap(int cpu, unsigned long start_ip); #else -static inline void hv_ghcb_msr_write(u64 msr, u64 value) {} -static inline void hv_ghcb_msr_read(u64 msr, u64 *value) {} static inline bool hv_ghcb_negotiate_protocol(void) { return false; } static inline void hv_ghcb_terminate(unsigned int set, unsigned int reason) {} -static inline void hv_vtom_init(void) {} +static inline int hv_snp_boot_ap(int cpu, unsigned long start_ip) { return 0; } #endif -extern bool hv_isolation_type_snp(void); +#if defined(CONFIG_AMD_MEM_ENCRYPT) || defined(CONFIG_INTEL_TDX_GUEST) +void hv_vtom_init(void); +void hv_ivm_msr_write(u64 msr, u64 value); +void hv_ivm_msr_read(u64 msr, u64 *value); +#else +static inline void hv_vtom_init(void) {} +static inline void hv_ivm_msr_write(u64 msr, u64 value) {} +static inline void hv_ivm_msr_read(u64 msr, u64 *value) {} +#endif static inline bool hv_is_synic_reg(unsigned int reg) { diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index 0100468e72ca..e6bba12c759c 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c @@ -32,6 +32,7 @@ #include <asm/nmi.h> #include <clocksource/hyperv_timer.h> #include <asm/numa.h> +#include <asm/svm.h> /* Is Linux running as the root partition? */ bool hv_root_partition; @@ -39,6 +40,10 @@ bool hv_root_partition; bool hv_nested; struct ms_hyperv_info ms_hyperv; +/* Used in modules via hv_do_hypercall(): see arch/x86/include/asm/mshyperv.h */ +bool hyperv_paravisor_present __ro_after_init; +EXPORT_SYMBOL_GPL(hyperv_paravisor_present); + #if IS_ENABLED(CONFIG_HYPERV) static inline unsigned int hv_get_nested_reg(unsigned int reg) { @@ -65,8 +70,8 @@ u64 hv_get_non_nested_register(unsigned int reg) { u64 value; - if (hv_is_synic_reg(reg) && hv_isolation_type_snp()) - hv_ghcb_msr_read(reg, &value); + if (hv_is_synic_reg(reg) && ms_hyperv.paravisor_present) + hv_ivm_msr_read(reg, &value); else rdmsrl(reg, value); return value; @@ -75,8 +80,8 @@ EXPORT_SYMBOL_GPL(hv_get_non_nested_register); void hv_set_non_nested_register(unsigned int reg, u64 value) { - if (hv_is_synic_reg(reg) && hv_isolation_type_snp()) { - hv_ghcb_msr_write(reg, value); + if (hv_is_synic_reg(reg) && ms_hyperv.paravisor_present) { + hv_ivm_msr_write(reg, value); /* Write proxy bit via wrmsl instruction */ if (hv_is_sint_reg(reg)) @@ -295,6 +300,15 @@ static void __init hv_smp_prepare_cpus(unsigned int max_cpus) native_smp_prepare_cpus(max_cpus); + /* + * Override wakeup_secondary_cpu_64 callback for SEV-SNP + * enlightened guest. + */ + if (!ms_hyperv.paravisor_present && hv_isolation_type_snp()) { + apic->wakeup_secondary_cpu_64 = hv_snp_boot_ap; + return; + } + #ifdef CONFIG_X86_64 for_each_present_cpu(i) { if (i == 0) @@ -313,6 +327,26 @@ static void __init hv_smp_prepare_cpus(unsigned int max_cpus) } #endif +/* + * When a fully enlightened TDX VM runs on Hyper-V, the firmware sets the + * HW_REDUCED flag: refer to acpi_tb_create_local_fadt(). Consequently ttyS0 + * interrupts can't work because request_irq() -> ... -> irq_to_desc() returns + * NULL for ttyS0. This happens because mp_config_acpi_legacy_irqs() sees a + * nr_legacy_irqs() of 0, so it doesn't initialize the array 'mp_irqs[]', and + * later setup_IO_APIC_irqs() -> find_irq_entry() fails to find the legacy irqs + * from the array and hence doesn't create the necessary irq description info. + * + * Clone arch/x86/kernel/acpi/boot.c: acpi_generic_reduced_hw_init() here, + * except don't change 'legacy_pic', which keeps its default value + * 'default_legacy_pic'. This way, mp_config_acpi_legacy_irqs() sees a non-zero + * nr_legacy_irqs() and eventually serial console interrupts works properly. + */ +static void __init reduced_hw_init(void) +{ + x86_init.timers.timer_init = x86_init_noop; + x86_init.irqs.pre_vector_init = x86_init_noop; +} + static void __init ms_hyperv_init_platform(void) { int hv_max_functions_eax; @@ -399,11 +433,33 @@ static void __init ms_hyperv_init_platform(void) ms_hyperv.shared_gpa_boundary = BIT_ULL(ms_hyperv.shared_gpa_boundary_bits); + hyperv_paravisor_present = !!ms_hyperv.paravisor_present; + pr_info("Hyper-V: Isolation Config: Group A 0x%x, Group B 0x%x\n", ms_hyperv.isolation_config_a, ms_hyperv.isolation_config_b); - if (hv_get_isolation_type() == HV_ISOLATION_TYPE_SNP) + + if (hv_get_isolation_type() == HV_ISOLATION_TYPE_SNP) { static_branch_enable(&isolation_type_snp); + } else if (hv_get_isolation_type() == HV_ISOLATION_TYPE_TDX) { + static_branch_enable(&isolation_type_tdx); + + /* A TDX VM must use x2APIC and doesn't use lazy EOI. */ + ms_hyperv.hints &= ~HV_X64_APIC_ACCESS_RECOMMENDED; + + if (!ms_hyperv.paravisor_present) { + /* To be supported: more work is required. */ + ms_hyperv.features &= ~HV_MSR_REFERENCE_TSC_AVAILABLE; + + /* HV_REGISTER_CRASH_CTL is unsupported. */ + ms_hyperv.misc_features &= ~HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE; + + /* Don't trust Hyper-V's TLB-flushing hypercalls. */ + ms_hyperv.hints &= ~HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED; + + x86_init.acpi.reduced_hw_early_init = reduced_hw_init; + } + } } if (hv_max_functions_eax >= HYPERV_CPUID_NESTED_FEATURES) { @@ -473,7 +529,7 @@ static void __init ms_hyperv_init_platform(void) #if IS_ENABLED(CONFIG_HYPERV) if ((hv_get_isolation_type() == HV_ISOLATION_TYPE_VBS) || - (hv_get_isolation_type() == HV_ISOLATION_TYPE_SNP)) + ms_hyperv.paravisor_present) hv_vtom_init(); /* * Setup the hook to get control post apic initialization. @@ -497,7 +553,8 @@ static void __init ms_hyperv_init_platform(void) # ifdef CONFIG_SMP smp_ops.smp_prepare_boot_cpu = hv_smp_prepare_boot_cpu; - if (hv_root_partition) + if (hv_root_partition || + (!ms_hyperv.paravisor_present && hv_isolation_type_snp())) smp_ops.smp_prepare_cpus = hv_smp_prepare_cpus; # endif @@ -560,6 +617,22 @@ static bool __init ms_hyperv_msi_ext_dest_id(void) return eax & HYPERV_VS_PROPERTIES_EAX_EXTENDED_IOAPIC_RTE; } +#ifdef CONFIG_AMD_MEM_ENCRYPT +static void hv_sev_es_hcall_prepare(struct ghcb *ghcb, struct pt_regs *regs) +{ + /* RAX and CPL are already in the GHCB */ + ghcb_set_rcx(ghcb, regs->cx); + ghcb_set_rdx(ghcb, regs->dx); + ghcb_set_r8(ghcb, regs->r8); +} + +static bool hv_sev_es_hcall_finish(struct ghcb *ghcb, struct pt_regs *regs) +{ + /* No checking of the return state needed */ + return true; +} +#endif + const __initconst struct hypervisor_x86 x86_hyper_ms_hyperv = { .name = "Microsoft Hyper-V", .detect = ms_hyperv_platform, @@ -567,4 +640,8 @@ const __initconst struct hypervisor_x86 x86_hyper_ms_hyperv = { .init.x2apic_available = ms_hyperv_x2apic_available, .init.msi_ext_dest_id = ms_hyperv_msi_ext_dest_id, .init.init_platform = ms_hyperv_init_platform, +#ifdef CONFIG_AMD_MEM_ENCRYPT + .runtime.sev_es_hcall_prepare = hv_sev_es_hcall_prepare, + .runtime.sev_es_hcall_finish = hv_sev_es_hcall_finish, +#endif }; diff --git a/arch/x86/um/Makefile b/arch/x86/um/Makefile index ee89f6bb9242..8bc72a51b257 100644 --- a/arch/x86/um/Makefile +++ b/arch/x86/um/Makefile @@ -13,15 +13,16 @@ obj-y = bugs_$(BITS).o delay.o fault.o ldt.o \ ptrace_$(BITS).o ptrace_user.o setjmp_$(BITS).o signal.o \ stub_$(BITS).o stub_segv.o \ sys_call_table_$(BITS).o sysrq_$(BITS).o tls_$(BITS).o \ - mem_$(BITS).o subarch.o os-$(OS)/ + mem_$(BITS).o subarch.o os-Linux/ ifeq ($(CONFIG_X86_32),y) -obj-y += checksum_32.o syscalls_32.o +obj-y += syscalls_32.o obj-$(CONFIG_ELF_CORE) += elfcore.o subarch-y = ../lib/string_32.o ../lib/atomic64_32.o ../lib/atomic64_cx8_32.o subarch-y += ../lib/cmpxchg8b_emu.o ../lib/atomic64_386_32.o +subarch-y += ../lib/checksum_32.o subarch-y += ../kernel/sys_ia32.o else diff --git a/arch/x86/um/asm/mm_context.h b/arch/x86/um/asm/mm_context.h index 4a73d63e4760..dc32dc023c2f 100644 --- a/arch/x86/um/asm/mm_context.h +++ b/arch/x86/um/asm/mm_context.h @@ -11,8 +11,6 @@ #include <linux/mutex.h> #include <asm/ldt.h> -extern void ldt_host_info(void); - #define LDT_PAGES_MAX \ ((LDT_ENTRIES * LDT_ENTRY_SIZE)/PAGE_SIZE) #define LDT_ENTRIES_PER_PAGE \ diff --git a/arch/x86/um/checksum_32.S b/arch/x86/um/checksum_32.S deleted file mode 100644 index aed782ab7721..000000000000 --- a/arch/x86/um/checksum_32.S +++ /dev/null @@ -1,214 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * IP/TCP/UDP checksumming routines - * - * Authors: Jorge Cwik, <jorge@laser.satlink.net> - * Arnt Gulbrandsen, <agulbra@nvg.unit.no> - * Tom May, <ftom@netcom.com> - * Pentium Pro/II routines: - * Alexander Kjeldaas <astor@guardian.no> - * Finn Arne Gangstad <finnag@guardian.no> - * Lots of code moved from tcp.c and ip.c; see those files - * for more names. - * - * Changes: Ingo Molnar, converted csum_partial_copy() to 2.1 exception - * handling. - * Andi Kleen, add zeroing on error - * converted to pure assembler - */ - -#include <asm/errno.h> -#include <asm/asm.h> -#include <asm/export.h> - -/* - * computes a partial checksum, e.g. for TCP/UDP fragments - */ - -/* -unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum) - */ - -.text -.align 4 -.globl csum_partial - -#ifndef CONFIG_X86_USE_PPRO_CHECKSUM - - /* - * Experiments with Ethernet and SLIP connections show that buff - * is aligned on either a 2-byte or 4-byte boundary. We get at - * least a twofold speedup on 486 and Pentium if it is 4-byte aligned. - * Fortunately, it is easy to convert 2-byte alignment to 4-byte - * alignment for the unrolled loop. - */ -csum_partial: - pushl %esi - pushl %ebx - movl 20(%esp),%eax # Function arg: unsigned int sum - movl 16(%esp),%ecx # Function arg: int len - movl 12(%esp),%esi # Function arg: unsigned char *buff - testl $2, %esi # Check alignment. - jz 2f # Jump if alignment is ok. - subl $2, %ecx # Alignment uses up two bytes. - jae 1f # Jump if we had at least two bytes. - addl $2, %ecx # ecx was < 2. Deal with it. - jmp 4f -1: movw (%esi), %bx - addl $2, %esi - addw %bx, %ax - adcl $0, %eax -2: - movl %ecx, %edx - shrl $5, %ecx - jz 2f - testl %esi, %esi -1: movl (%esi), %ebx - adcl %ebx, %eax - movl 4(%esi), %ebx - adcl %ebx, %eax - movl 8(%esi), %ebx - adcl %ebx, %eax - movl 12(%esi), %ebx - adcl %ebx, %eax - movl 16(%esi), %ebx - adcl %ebx, %eax - movl 20(%esi), %ebx - adcl %ebx, %eax - movl 24(%esi), %ebx - adcl %ebx, %eax - movl 28(%esi), %ebx - adcl %ebx, %eax - lea 32(%esi), %esi - dec %ecx - jne 1b - adcl $0, %eax -2: movl %edx, %ecx - andl $0x1c, %edx - je 4f - shrl $2, %edx # This clears CF -3: adcl (%esi), %eax - lea 4(%esi), %esi - dec %edx - jne 3b - adcl $0, %eax -4: andl $3, %ecx - jz 7f - cmpl $2, %ecx - jb 5f - movw (%esi),%cx - leal 2(%esi),%esi - je 6f - shll $16,%ecx -5: movb (%esi),%cl -6: addl %ecx,%eax - adcl $0, %eax -7: - popl %ebx - popl %esi - RET - -#else - -/* Version for PentiumII/PPro */ - -csum_partial: - pushl %esi - pushl %ebx - movl 20(%esp),%eax # Function arg: unsigned int sum - movl 16(%esp),%ecx # Function arg: int len - movl 12(%esp),%esi # Function arg: const unsigned char *buf - - testl $2, %esi - jnz 30f -10: - movl %ecx, %edx - movl %ecx, %ebx - andl $0x7c, %ebx - shrl $7, %ecx - addl %ebx,%esi - shrl $2, %ebx - negl %ebx - lea 45f(%ebx,%ebx,2), %ebx - testl %esi, %esi - jmp *%ebx - - # Handle 2-byte-aligned regions -20: addw (%esi), %ax - lea 2(%esi), %esi - adcl $0, %eax - jmp 10b - -30: subl $2, %ecx - ja 20b - je 32f - movzbl (%esi),%ebx # csumming 1 byte, 2-aligned - addl %ebx, %eax - adcl $0, %eax - jmp 80f -32: - addw (%esi), %ax # csumming 2 bytes, 2-aligned - adcl $0, %eax - jmp 80f - -40: - addl -128(%esi), %eax - adcl -124(%esi), %eax - adcl -120(%esi), %eax - adcl -116(%esi), %eax - adcl -112(%esi), %eax - adcl -108(%esi), %eax - adcl -104(%esi), %eax - adcl -100(%esi), %eax - adcl -96(%esi), %eax - adcl -92(%esi), %eax - adcl -88(%esi), %eax - adcl -84(%esi), %eax - adcl -80(%esi), %eax - adcl -76(%esi), %eax - adcl -72(%esi), %eax - adcl -68(%esi), %eax - adcl -64(%esi), %eax - adcl -60(%esi), %eax - adcl -56(%esi), %eax - adcl -52(%esi), %eax - adcl -48(%esi), %eax - adcl -44(%esi), %eax - adcl -40(%esi), %eax - adcl -36(%esi), %eax - adcl -32(%esi), %eax - adcl -28(%esi), %eax - adcl -24(%esi), %eax - adcl -20(%esi), %eax - adcl -16(%esi), %eax - adcl -12(%esi), %eax - adcl -8(%esi), %eax - adcl -4(%esi), %eax -45: - lea 128(%esi), %esi - adcl $0, %eax - dec %ecx - jge 40b - movl %edx, %ecx -50: andl $3, %ecx - jz 80f - - # Handle the last 1-3 bytes without jumping - notl %ecx # 1->2, 2->1, 3->0, higher bits are masked - movl $0xffffff,%ebx # by the shll and shrl instructions - shll $3,%ecx - shrl %cl,%ebx - andl -128(%esi),%ebx # esi is 4-aligned so should be ok - addl %ebx,%eax - adcl $0,%eax -80: - popl %ebx - popl %esi - RET - -#endif - EXPORT_SYMBOL(csum_partial) diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 419590f41ed5..f14e68266ccd 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -492,26 +492,22 @@ static int thermal_get_temp(struct thermal_zone_device *thermal, int *temp) } static int thermal_get_trend(struct thermal_zone_device *thermal, - int trip_index, enum thermal_trend *trend) + struct thermal_trip *trip, + enum thermal_trend *trend) { struct acpi_thermal *tz = thermal_zone_device_priv(thermal); struct acpi_thermal_trip *acpi_trip; - int t, i; + int t; - if (!tz || trip_index < 0) + if (!tz || !trip) return -EINVAL; - if (tz->trips.critical.valid) - trip_index--; - - if (tz->trips.hot.valid) - trip_index--; - - if (trip_index < 0) + acpi_trip = trip->priv; + if (!acpi_trip || !acpi_trip->valid) return -EINVAL; - acpi_trip = &tz->trips.passive.trip; - if (acpi_trip->valid && !trip_index--) { + switch (trip->type) { + case THERMAL_TRIP_PASSIVE: t = tz->trips.passive.tc1 * (tz->temperature - tz->last_temperature) + tz->trips.passive.tc2 * (tz->temperature - @@ -524,19 +520,18 @@ static int thermal_get_trend(struct thermal_zone_device *thermal, *trend = THERMAL_TREND_STABLE; return 0; - } - - t = acpi_thermal_temp(tz, tz->temperature); - for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { - acpi_trip = &tz->trips.active[i].trip; - if (acpi_trip->valid && !trip_index--) { - if (t > acpi_thermal_temp(tz, acpi_trip->temperature)) { - *trend = THERMAL_TREND_RAISING; - return 0; - } + case THERMAL_TRIP_ACTIVE: + t = acpi_thermal_temp(tz, tz->temperature); + if (t <= trip->temperature) break; - } + + *trend = THERMAL_TREND_RAISING; + + return 0; + + default: + break; } return -EINVAL; diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index c4d671a5a13d..0ba0dc4ecf06 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -461,13 +461,6 @@ config VF_PIT_TIMER help Support for Periodic Interrupt Timer on Freescale Vybrid Family SoCs. -config OXNAS_RPS_TIMER - bool "Oxford Semiconductor OXNAS RPS Timers driver" if COMPILE_TEST - select TIMER_OF - select CLKSRC_MMIO - help - This enables support for the Oxford Semiconductor OXNAS RPS timers. - config SYS_SUPPORTS_SH_CMT bool diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 5d93c9e3fc55..368c3461dab8 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -54,7 +54,6 @@ obj-$(CONFIG_MTK_TIMER) += timer-mediatek.o obj-$(CONFIG_MTK_CPUX_TIMER) += timer-mediatek-cpux.o obj-$(CONFIG_CLKSRC_PISTACHIO) += timer-pistachio.o obj-$(CONFIG_CLKSRC_TI_32K) += timer-ti-32k.o -obj-$(CONFIG_OXNAS_RPS_TIMER) += timer-oxnas-rps.o obj-$(CONFIG_OWL_TIMER) += timer-owl.o obj-$(CONFIG_MILBEAUT_TIMER) += timer-milbeaut.o obj-$(CONFIG_SPRD_TIMER) += timer-sprd.o diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index e733a2a1927a..7dd2c615bce2 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -792,6 +792,13 @@ static __always_inline void set_next_event_mem(const int access, unsigned long e u64 cnt; ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL, clk); + + /* Timer must be disabled before programming CVAL */ + if (ctrl & ARCH_TIMER_CTRL_ENABLE) { + ctrl &= ~ARCH_TIMER_CTRL_ENABLE; + arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk); + } + ctrl |= ARCH_TIMER_CTRL_ENABLE; ctrl &= ~ARCH_TIMER_CTRL_IT_MASK; diff --git a/drivers/clocksource/hyperv_timer.c b/drivers/clocksource/hyperv_timer.c index e56307a81f4d..8ff7cd4e20bb 100644 --- a/drivers/clocksource/hyperv_timer.c +++ b/drivers/clocksource/hyperv_timer.c @@ -390,7 +390,7 @@ static __always_inline u64 read_hv_clock_msr(void) static union { struct ms_hyperv_tsc_page page; u8 reserved[PAGE_SIZE]; -} tsc_pg __aligned(PAGE_SIZE); +} tsc_pg __bss_decrypted __aligned(PAGE_SIZE); static struct ms_hyperv_tsc_page *tsc_page = &tsc_pg.page; static unsigned long tsc_pfn; diff --git a/drivers/clocksource/timer-loongson1-pwm.c b/drivers/clocksource/timer-loongson1-pwm.c index 6335fee03017..244d66835508 100644 --- a/drivers/clocksource/timer-loongson1-pwm.c +++ b/drivers/clocksource/timer-loongson1-pwm.c @@ -28,7 +28,7 @@ #define CNTR_WIDTH 24 -DEFINE_RAW_SPINLOCK(ls1x_timer_lock); +static DEFINE_RAW_SPINLOCK(ls1x_timer_lock); struct ls1x_clocksource { void __iomem *reg_base; diff --git a/drivers/clocksource/timer-oxnas-rps.c b/drivers/clocksource/timer-oxnas-rps.c deleted file mode 100644 index d514b44e67dd..000000000000 --- a/drivers/clocksource/timer-oxnas-rps.c +++ /dev/null @@ -1,288 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * drivers/clocksource/timer-oxnas-rps.c - * - * Copyright (C) 2009 Oxford Semiconductor Ltd - * Copyright (C) 2013 Ma Haijun <mahaijuns@gmail.com> - * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com> - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/init.h> -#include <linux/irq.h> -#include <linux/io.h> -#include <linux/clk.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/of_irq.h> -#include <linux/of_address.h> -#include <linux/clockchips.h> -#include <linux/sched_clock.h> - -/* TIMER1 used as tick - * TIMER2 used as clocksource - */ - -/* Registers definitions */ - -#define TIMER_LOAD_REG 0x0 -#define TIMER_CURR_REG 0x4 -#define TIMER_CTRL_REG 0x8 -#define TIMER_CLRINT_REG 0xC - -#define TIMER_BITS 24 - -#define TIMER_MAX_VAL (BIT(TIMER_BITS) - 1) - -#define TIMER_PERIODIC BIT(6) -#define TIMER_ENABLE BIT(7) - -#define TIMER_DIV1 (0) -#define TIMER_DIV16 (1 << 2) -#define TIMER_DIV256 (2 << 2) - -#define TIMER1_REG_OFFSET 0 -#define TIMER2_REG_OFFSET 0x20 - -/* Clockevent & Clocksource data */ - -struct oxnas_rps_timer { - struct clock_event_device clkevent; - void __iomem *clksrc_base; - void __iomem *clkevt_base; - unsigned long timer_period; - unsigned int timer_prescaler; - struct clk *clk; - int irq; -}; - -static irqreturn_t oxnas_rps_timer_irq(int irq, void *dev_id) -{ - struct oxnas_rps_timer *rps = dev_id; - - writel_relaxed(0, rps->clkevt_base + TIMER_CLRINT_REG); - - rps->clkevent.event_handler(&rps->clkevent); - - return IRQ_HANDLED; -} - -static void oxnas_rps_timer_config(struct oxnas_rps_timer *rps, - unsigned long period, - unsigned int periodic) -{ - uint32_t cfg = rps->timer_prescaler; - - if (period) - cfg |= TIMER_ENABLE; - - if (periodic) - cfg |= TIMER_PERIODIC; - - writel_relaxed(period, rps->clkevt_base + TIMER_LOAD_REG); - writel_relaxed(cfg, rps->clkevt_base + TIMER_CTRL_REG); -} - -static int oxnas_rps_timer_shutdown(struct clock_event_device *evt) -{ - struct oxnas_rps_timer *rps = - container_of(evt, struct oxnas_rps_timer, clkevent); - - oxnas_rps_timer_config(rps, 0, 0); - - return 0; -} - -static int oxnas_rps_timer_set_periodic(struct clock_event_device *evt) -{ - struct oxnas_rps_timer *rps = - container_of(evt, struct oxnas_rps_timer, clkevent); - - oxnas_rps_timer_config(rps, rps->timer_period, 1); - - return 0; -} - -static int oxnas_rps_timer_set_oneshot(struct clock_event_device *evt) -{ - struct oxnas_rps_timer *rps = - container_of(evt, struct oxnas_rps_timer, clkevent); - - oxnas_rps_timer_config(rps, rps->timer_period, 0); - - return 0; -} - -static int oxnas_rps_timer_next_event(unsigned long delta, - struct clock_event_device *evt) -{ - struct oxnas_rps_timer *rps = - container_of(evt, struct oxnas_rps_timer, clkevent); - - oxnas_rps_timer_config(rps, delta, 0); - - return 0; -} - -static int __init oxnas_rps_clockevent_init(struct oxnas_rps_timer *rps) -{ - ulong clk_rate = clk_get_rate(rps->clk); - ulong timer_rate; - - /* Start with prescaler 1 */ - rps->timer_prescaler = TIMER_DIV1; - rps->timer_period = DIV_ROUND_UP(clk_rate, HZ); - timer_rate = clk_rate; - - if (rps->timer_period > TIMER_MAX_VAL) { - rps->timer_prescaler = TIMER_DIV16; - timer_rate = clk_rate / 16; - rps->timer_period = DIV_ROUND_UP(timer_rate, HZ); - } - if (rps->timer_period > TIMER_MAX_VAL) { - rps->timer_prescaler = TIMER_DIV256; - timer_rate = clk_rate / 256; - rps->timer_period = DIV_ROUND_UP(timer_rate, HZ); - } - - rps->clkevent.name = "oxnas-rps"; - rps->clkevent.features = CLOCK_EVT_FEAT_PERIODIC | - CLOCK_EVT_FEAT_ONESHOT | - CLOCK_EVT_FEAT_DYNIRQ; - rps->clkevent.tick_resume = oxnas_rps_timer_shutdown; - rps->clkevent.set_state_shutdown = oxnas_rps_timer_shutdown; - rps->clkevent.set_state_periodic = oxnas_rps_timer_set_periodic; - rps->clkevent.set_state_oneshot = oxnas_rps_timer_set_oneshot; - rps->clkevent.set_next_event = oxnas_rps_timer_next_event; - rps->clkevent.rating = 200; - rps->clkevent.cpumask = cpu_possible_mask; - rps->clkevent.irq = rps->irq; - clockevents_config_and_register(&rps->clkevent, - timer_rate, - 1, - TIMER_MAX_VAL); - - pr_info("Registered clock event rate %luHz prescaler %x period %lu\n", - clk_rate, - rps->timer_prescaler, - rps->timer_period); - - return 0; -} - -/* Clocksource */ - -static void __iomem *timer_sched_base; - -static u64 notrace oxnas_rps_read_sched_clock(void) -{ - return ~readl_relaxed(timer_sched_base); -} - -static int __init oxnas_rps_clocksource_init(struct oxnas_rps_timer *rps) -{ - ulong clk_rate = clk_get_rate(rps->clk); - int ret; - - /* use prescale 16 */ - clk_rate = clk_rate / 16; - - writel_relaxed(TIMER_MAX_VAL, rps->clksrc_base + TIMER_LOAD_REG); - writel_relaxed(TIMER_PERIODIC | TIMER_ENABLE | TIMER_DIV16, - rps->clksrc_base + TIMER_CTRL_REG); - - timer_sched_base = rps->clksrc_base + TIMER_CURR_REG; - sched_clock_register(oxnas_rps_read_sched_clock, - TIMER_BITS, clk_rate); - ret = clocksource_mmio_init(timer_sched_base, - "oxnas_rps_clocksource_timer", - clk_rate, 250, TIMER_BITS, - clocksource_mmio_readl_down); - if (WARN_ON(ret)) { - pr_err("can't register clocksource\n"); - return ret; - } - - pr_info("Registered clocksource rate %luHz\n", clk_rate); - - return 0; -} - -static int __init oxnas_rps_timer_init(struct device_node *np) -{ - struct oxnas_rps_timer *rps; - void __iomem *base; - int ret; - - rps = kzalloc(sizeof(*rps), GFP_KERNEL); - if (!rps) - return -ENOMEM; - - rps->clk = of_clk_get(np, 0); - if (IS_ERR(rps->clk)) { - ret = PTR_ERR(rps->clk); - goto err_alloc; - } - - ret = clk_prepare_enable(rps->clk); - if (ret) - goto err_clk; - - base = of_iomap(np, 0); - if (!base) { - ret = -ENXIO; - goto err_clk_prepare; - } - - rps->irq = irq_of_parse_and_map(np, 0); - if (!rps->irq) { - ret = -EINVAL; - goto err_iomap; - } - - rps->clkevt_base = base + TIMER1_REG_OFFSET; - rps->clksrc_base = base + TIMER2_REG_OFFSET; - - /* Disable timers */ - writel_relaxed(0, rps->clkevt_base + TIMER_CTRL_REG); - writel_relaxed(0, rps->clksrc_base + TIMER_CTRL_REG); - writel_relaxed(0, rps->clkevt_base + TIMER_LOAD_REG); - writel_relaxed(0, rps->clksrc_base + TIMER_LOAD_REG); - writel_relaxed(0, rps->clkevt_base + TIMER_CLRINT_REG); - writel_relaxed(0, rps->clksrc_base + TIMER_CLRINT_REG); - - ret = request_irq(rps->irq, oxnas_rps_timer_irq, - IRQF_TIMER | IRQF_IRQPOLL, - "rps-timer", rps); - if (ret) - goto err_iomap; - - ret = oxnas_rps_clocksource_init(rps); - if (ret) - goto err_irqreq; - - ret = oxnas_rps_clockevent_init(rps); - if (ret) - goto err_irqreq; - - return 0; - -err_irqreq: - free_irq(rps->irq, rps); -err_iomap: - iounmap(base); -err_clk_prepare: - clk_disable_unprepare(rps->clk); -err_clk: - clk_put(rps->clk); -err_alloc: - kfree(rps); - - return ret; -} - -TIMER_OF_DECLARE(ox810se_rps, - "oxsemi,ox810se-rps-timer", oxnas_rps_timer_init); -TIMER_OF_DECLARE(ox820_rps, - "oxsemi,ox820-rps-timer", oxnas_rps_timer_init); diff --git a/drivers/clocksource/timer-sun5i.c b/drivers/clocksource/timer-sun5i.c index 7d5fa9069906..69fee3540d37 100644 --- a/drivers/clocksource/timer-sun5i.c +++ b/drivers/clocksource/timer-sun5i.c @@ -16,9 +16,7 @@ #include <linux/irqreturn.h> #include <linux/reset.h> #include <linux/slab.h> -#include <linux/of.h> -#include <linux/of_address.h> -#include <linux/of_irq.h> +#include <linux/platform_device.h> #define TIMER_IRQ_EN_REG 0x00 #define TIMER_IRQ_EN(val) BIT(val) @@ -40,26 +38,16 @@ struct sun5i_timer { struct clk *clk; struct notifier_block clk_rate_cb; u32 ticks_per_jiffy; -}; - -#define to_sun5i_timer(x) \ - container_of(x, struct sun5i_timer, clk_rate_cb) - -struct sun5i_timer_clksrc { - struct sun5i_timer timer; struct clocksource clksrc; -}; - -#define to_sun5i_timer_clksrc(x) \ - container_of(x, struct sun5i_timer_clksrc, clksrc) - -struct sun5i_timer_clkevt { - struct sun5i_timer timer; struct clock_event_device clkevt; }; -#define to_sun5i_timer_clkevt(x) \ - container_of(x, struct sun5i_timer_clkevt, clkevt) +#define nb_to_sun5i_timer(x) \ + container_of(x, struct sun5i_timer, clk_rate_cb) +#define clksrc_to_sun5i_timer(x) \ + container_of(x, struct sun5i_timer, clksrc) +#define clkevt_to_sun5i_timer(x) \ + container_of(x, struct sun5i_timer, clkevt) /* * When we disable a timer, we need to wait at least for 2 cycles of @@ -67,30 +55,30 @@ struct sun5i_timer_clkevt { * that is already setup and runs at the same frequency than the other * timers, and we never will be disabled. */ -static void sun5i_clkevt_sync(struct sun5i_timer_clkevt *ce) +static void sun5i_clkevt_sync(struct sun5i_timer *ce) { - u32 old = readl(ce->timer.base + TIMER_CNTVAL_LO_REG(1)); + u32 old = readl(ce->base + TIMER_CNTVAL_LO_REG(1)); - while ((old - readl(ce->timer.base + TIMER_CNTVAL_LO_REG(1))) < TIMER_SYNC_TICKS) + while ((old - readl(ce->base + TIMER_CNTVAL_LO_REG(1))) < TIMER_SYNC_TICKS) cpu_relax(); } -static void sun5i_clkevt_time_stop(struct sun5i_timer_clkevt *ce, u8 timer) +static void sun5i_clkevt_time_stop(struct sun5i_timer *ce, u8 timer) { - u32 val = readl(ce->timer.base + TIMER_CTL_REG(timer)); - writel(val & ~TIMER_CTL_ENABLE, ce->timer.base + TIMER_CTL_REG(timer)); + u32 val = readl(ce->base + TIMER_CTL_REG(timer)); + writel(val & ~TIMER_CTL_ENABLE, ce->base + TIMER_CTL_REG(timer)); sun5i_clkevt_sync(ce); } -static void sun5i_clkevt_time_setup(struct sun5i_timer_clkevt *ce, u8 timer, u32 delay) +static void sun5i_clkevt_time_setup(struct sun5i_timer *ce, u8 timer, u32 delay) { - writel(delay, ce->timer.base + TIMER_INTVAL_LO_REG(timer)); + writel(delay, ce->base + TIMER_INTVAL_LO_REG(timer)); } -static void sun5i_clkevt_time_start(struct sun5i_timer_clkevt *ce, u8 timer, bool periodic) +static void sun5i_clkevt_time_start(struct sun5i_timer *ce, u8 timer, bool periodic) { - u32 val = readl(ce->timer.base + TIMER_CTL_REG(timer)); + u32 val = readl(ce->base + TIMER_CTL_REG(timer)); if (periodic) val &= ~TIMER_CTL_ONESHOT; @@ -98,12 +86,12 @@ static void sun5i_clkevt_time_start(struct sun5i_timer_clkevt *ce, u8 timer, boo val |= TIMER_CTL_ONESHOT; writel(val | TIMER_CTL_ENABLE | TIMER_CTL_RELOAD, - ce->timer.base + TIMER_CTL_REG(timer)); + ce->base + TIMER_CTL_REG(timer)); } static int sun5i_clkevt_shutdown(struct clock_event_device *clkevt) { - struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt); + struct sun5i_timer *ce = clkevt_to_sun5i_timer(clkevt); sun5i_clkevt_time_stop(ce, 0); return 0; @@ -111,7 +99,7 @@ static int sun5i_clkevt_shutdown(struct clock_event_device *clkevt) static int sun5i_clkevt_set_oneshot(struct clock_event_device *clkevt) { - struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt); + struct sun5i_timer *ce = clkevt_to_sun5i_timer(clkevt); sun5i_clkevt_time_stop(ce, 0); sun5i_clkevt_time_start(ce, 0, false); @@ -120,10 +108,10 @@ static int sun5i_clkevt_set_oneshot(struct clock_event_device *clkevt) static int sun5i_clkevt_set_periodic(struct clock_event_device *clkevt) { - struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt); + struct sun5i_timer *ce = clkevt_to_sun5i_timer(clkevt); sun5i_clkevt_time_stop(ce, 0); - sun5i_clkevt_time_setup(ce, 0, ce->timer.ticks_per_jiffy); + sun5i_clkevt_time_setup(ce, 0, ce->ticks_per_jiffy); sun5i_clkevt_time_start(ce, 0, true); return 0; } @@ -131,7 +119,7 @@ static int sun5i_clkevt_set_periodic(struct clock_event_device *clkevt) static int sun5i_clkevt_next_event(unsigned long evt, struct clock_event_device *clkevt) { - struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt); + struct sun5i_timer *ce = clkevt_to_sun5i_timer(clkevt); sun5i_clkevt_time_stop(ce, 0); sun5i_clkevt_time_setup(ce, 0, evt - TIMER_SYNC_TICKS); @@ -142,9 +130,9 @@ static int sun5i_clkevt_next_event(unsigned long evt, static irqreturn_t sun5i_timer_interrupt(int irq, void *dev_id) { - struct sun5i_timer_clkevt *ce = dev_id; + struct sun5i_timer *ce = dev_id; - writel(0x1, ce->timer.base + TIMER_IRQ_ST_REG); + writel(0x1, ce->base + TIMER_IRQ_ST_REG); ce->clkevt.event_handler(&ce->clkevt); return IRQ_HANDLED; @@ -152,17 +140,16 @@ static irqreturn_t sun5i_timer_interrupt(int irq, void *dev_id) static u64 sun5i_clksrc_read(struct clocksource *clksrc) { - struct sun5i_timer_clksrc *cs = to_sun5i_timer_clksrc(clksrc); + struct sun5i_timer *cs = clksrc_to_sun5i_timer(clksrc); - return ~readl(cs->timer.base + TIMER_CNTVAL_LO_REG(1)); + return ~readl(cs->base + TIMER_CNTVAL_LO_REG(1)); } -static int sun5i_rate_cb_clksrc(struct notifier_block *nb, - unsigned long event, void *data) +static int sun5i_rate_cb(struct notifier_block *nb, + unsigned long event, void *data) { struct clk_notifier_data *ndata = data; - struct sun5i_timer *timer = to_sun5i_timer(nb); - struct sun5i_timer_clksrc *cs = container_of(timer, struct sun5i_timer_clksrc, timer); + struct sun5i_timer *cs = nb_to_sun5i_timer(nb); switch (event) { case PRE_RATE_CHANGE: @@ -171,6 +158,8 @@ static int sun5i_rate_cb_clksrc(struct notifier_block *nb, case POST_RATE_CHANGE: clocksource_register_hz(&cs->clksrc, ndata->new_rate); + clockevents_update_freq(&cs->clkevt, ndata->new_rate); + cs->ticks_per_jiffy = DIV_ROUND_UP(ndata->new_rate, HZ); break; default: @@ -180,47 +169,18 @@ static int sun5i_rate_cb_clksrc(struct notifier_block *nb, return NOTIFY_DONE; } -static int __init sun5i_setup_clocksource(struct device_node *node, - void __iomem *base, - struct clk *clk, int irq) +static int sun5i_setup_clocksource(struct platform_device *pdev, + unsigned long rate) { - struct sun5i_timer_clksrc *cs; - unsigned long rate; + struct sun5i_timer *cs = platform_get_drvdata(pdev); + void __iomem *base = cs->base; int ret; - cs = kzalloc(sizeof(*cs), GFP_KERNEL); - if (!cs) - return -ENOMEM; - - ret = clk_prepare_enable(clk); - if (ret) { - pr_err("Couldn't enable parent clock\n"); - goto err_free; - } - - rate = clk_get_rate(clk); - if (!rate) { - pr_err("Couldn't get parent clock rate\n"); - ret = -EINVAL; - goto err_disable_clk; - } - - cs->timer.base = base; - cs->timer.clk = clk; - cs->timer.clk_rate_cb.notifier_call = sun5i_rate_cb_clksrc; - cs->timer.clk_rate_cb.next = NULL; - - ret = clk_notifier_register(clk, &cs->timer.clk_rate_cb); - if (ret) { - pr_err("Unable to register clock notifier.\n"); - goto err_disable_clk; - } - writel(~0, base + TIMER_INTVAL_LO_REG(1)); writel(TIMER_CTL_ENABLE | TIMER_CTL_RELOAD, base + TIMER_CTL_REG(1)); - cs->clksrc.name = node->name; + cs->clksrc.name = pdev->dev.of_node->name; cs->clksrc.rating = 340; cs->clksrc.read = sun5i_clksrc_read; cs->clksrc.mask = CLOCKSOURCE_MASK(32); @@ -228,74 +188,23 @@ static int __init sun5i_setup_clocksource(struct device_node *node, ret = clocksource_register_hz(&cs->clksrc, rate); if (ret) { - pr_err("Couldn't register clock source.\n"); - goto err_remove_notifier; + dev_err(&pdev->dev, "Couldn't register clock source.\n"); + return ret; } return 0; - -err_remove_notifier: - clk_notifier_unregister(clk, &cs->timer.clk_rate_cb); -err_disable_clk: - clk_disable_unprepare(clk); -err_free: - kfree(cs); - return ret; } -static int sun5i_rate_cb_clkevt(struct notifier_block *nb, - unsigned long event, void *data) +static int sun5i_setup_clockevent(struct platform_device *pdev, + unsigned long rate, int irq) { - struct clk_notifier_data *ndata = data; - struct sun5i_timer *timer = to_sun5i_timer(nb); - struct sun5i_timer_clkevt *ce = container_of(timer, struct sun5i_timer_clkevt, timer); - - if (event == POST_RATE_CHANGE) { - clockevents_update_freq(&ce->clkevt, ndata->new_rate); - ce->timer.ticks_per_jiffy = DIV_ROUND_UP(ndata->new_rate, HZ); - } - - return NOTIFY_DONE; -} - -static int __init sun5i_setup_clockevent(struct device_node *node, void __iomem *base, - struct clk *clk, int irq) -{ - struct sun5i_timer_clkevt *ce; - unsigned long rate; + struct device *dev = &pdev->dev; + struct sun5i_timer *ce = platform_get_drvdata(pdev); + void __iomem *base = ce->base; int ret; u32 val; - ce = kzalloc(sizeof(*ce), GFP_KERNEL); - if (!ce) - return -ENOMEM; - - ret = clk_prepare_enable(clk); - if (ret) { - pr_err("Couldn't enable parent clock\n"); - goto err_free; - } - - rate = clk_get_rate(clk); - if (!rate) { - pr_err("Couldn't get parent clock rate\n"); - ret = -EINVAL; - goto err_disable_clk; - } - - ce->timer.base = base; - ce->timer.ticks_per_jiffy = DIV_ROUND_UP(rate, HZ); - ce->timer.clk = clk; - ce->timer.clk_rate_cb.notifier_call = sun5i_rate_cb_clkevt; - ce->timer.clk_rate_cb.next = NULL; - - ret = clk_notifier_register(clk, &ce->timer.clk_rate_cb); - if (ret) { - pr_err("Unable to register clock notifier.\n"); - goto err_disable_clk; - } - - ce->clkevt.name = node->name; + ce->clkevt.name = dev->of_node->name; ce->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; ce->clkevt.set_next_event = sun5i_clkevt_next_event; ce->clkevt.set_state_shutdown = sun5i_clkevt_shutdown; @@ -313,60 +222,109 @@ static int __init sun5i_setup_clockevent(struct device_node *node, void __iomem clockevents_config_and_register(&ce->clkevt, rate, TIMER_SYNC_TICKS, 0xffffffff); - ret = request_irq(irq, sun5i_timer_interrupt, IRQF_TIMER | IRQF_IRQPOLL, - "sun5i_timer0", ce); + ret = devm_request_irq(dev, irq, sun5i_timer_interrupt, + IRQF_TIMER | IRQF_IRQPOLL, + "sun5i_timer0", ce); if (ret) { - pr_err("Unable to register interrupt\n"); - goto err_remove_notifier; + dev_err(dev, "Unable to register interrupt\n"); + return ret; } return 0; - -err_remove_notifier: - clk_notifier_unregister(clk, &ce->timer.clk_rate_cb); -err_disable_clk: - clk_disable_unprepare(clk); -err_free: - kfree(ce); - return ret; } -static int __init sun5i_timer_init(struct device_node *node) +static int sun5i_timer_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; + struct sun5i_timer *st; struct reset_control *rstc; void __iomem *timer_base; struct clk *clk; + unsigned long rate; int irq, ret; - timer_base = of_io_request_and_map(node, 0, of_node_full_name(node)); + st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL); + if (!st) + return -ENOMEM; + + platform_set_drvdata(pdev, st); + + timer_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(timer_base)) { - pr_err("Can't map registers\n"); + dev_err(dev, "Can't map registers\n"); return PTR_ERR(timer_base); } - irq = irq_of_parse_and_map(node, 0); - if (irq <= 0) { - pr_err("Can't parse IRQ\n"); - return -EINVAL; + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(dev, "Can't get IRQ\n"); + return irq; } - clk = of_clk_get(node, 0); + clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(clk)) { - pr_err("Can't get timer clock\n"); + dev_err(dev, "Can't get timer clock\n"); return PTR_ERR(clk); } - rstc = of_reset_control_get(node, NULL); - if (!IS_ERR(rstc)) + rate = clk_get_rate(clk); + if (!rate) { + dev_err(dev, "Couldn't get parent clock rate\n"); + return -EINVAL; + } + + st->base = timer_base; + st->ticks_per_jiffy = DIV_ROUND_UP(rate, HZ); + st->clk = clk; + st->clk_rate_cb.notifier_call = sun5i_rate_cb; + st->clk_rate_cb.next = NULL; + + ret = devm_clk_notifier_register(dev, clk, &st->clk_rate_cb); + if (ret) { + dev_err(dev, "Unable to register clock notifier.\n"); + return ret; + } + + rstc = devm_reset_control_get_optional_exclusive(dev, NULL); + if (rstc) reset_control_deassert(rstc); - ret = sun5i_setup_clocksource(node, timer_base, clk, irq); + ret = sun5i_setup_clocksource(pdev, rate); if (ret) return ret; - return sun5i_setup_clockevent(node, timer_base, clk, irq); + ret = sun5i_setup_clockevent(pdev, rate, irq); + if (ret) + goto err_unreg_clocksource; + + return 0; + +err_unreg_clocksource: + clocksource_unregister(&st->clksrc); + return ret; } -TIMER_OF_DECLARE(sun5i_a13, "allwinner,sun5i-a13-hstimer", - sun5i_timer_init); -TIMER_OF_DECLARE(sun7i_a20, "allwinner,sun7i-a20-hstimer", - sun5i_timer_init); + +static void sun5i_timer_remove(struct platform_device *pdev) +{ + struct sun5i_timer *st = platform_get_drvdata(pdev); + + clocksource_unregister(&st->clksrc); +} + +static const struct of_device_id sun5i_timer_of_match[] = { + { .compatible = "allwinner,sun5i-a13-hstimer" }, + { .compatible = "allwinner,sun7i-a20-hstimer" }, + {}, +}; +MODULE_DEVICE_TABLE(of, sun5i_timer_of_match); + +static struct platform_driver sun5i_timer_driver = { + .probe = sun5i_timer_probe, + .remove_new = sun5i_timer_remove, + .driver = { + .name = "sun5i-timer", + .of_match_table = sun5i_timer_of_match, + .suppress_bind_attrs = true, + }, +}; +module_platform_driver(sun5i_timer_driver); diff --git a/drivers/counter/Kconfig b/drivers/counter/Kconfig index 62962ae84b77..497bc05dca4d 100644 --- a/drivers/counter/Kconfig +++ b/drivers/counter/Kconfig @@ -92,7 +92,7 @@ config MICROCHIP_TCB_CAPTURE config RZ_MTU3_CNT tristate "Renesas RZ/G2L MTU3a counter driver" - depends on RZ_MTU3 || COMPILE_TEST + depends on RZ_MTU3 help Enable support for MTU3a counter driver found on Renesas RZ/G2L alike SoCs. This IP supports both 16-bit and 32-bit phase counting mode diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index a757f90aa9d6..60ed89000e82 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -86,6 +86,7 @@ static void cpufreq_governor_limits(struct cpufreq_policy *policy); static int cpufreq_set_policy(struct cpufreq_policy *policy, struct cpufreq_governor *new_gov, unsigned int new_pol); +static bool cpufreq_boost_supported(void); /* * Two notifier lists: the "policy" list is involved in the @@ -455,8 +456,10 @@ void cpufreq_freq_transition_end(struct cpufreq_policy *policy, policy->cur, policy->cpuinfo.max_freq); + spin_lock(&policy->transition_lock); policy->transition_ongoing = false; policy->transition_task = NULL; + spin_unlock(&policy->transition_lock); wake_up(&policy->transition_wait); } @@ -621,6 +624,40 @@ static ssize_t store_boost(struct kobject *kobj, struct kobj_attribute *attr, } define_one_global_rw(boost); +static ssize_t show_local_boost(struct cpufreq_policy *policy, char *buf) +{ + return sysfs_emit(buf, "%d\n", policy->boost_enabled); +} + +static ssize_t store_local_boost(struct cpufreq_policy *policy, + const char *buf, size_t count) +{ + int ret, enable; + + ret = kstrtoint(buf, 10, &enable); + if (ret || enable < 0 || enable > 1) + return -EINVAL; + + if (!cpufreq_driver->boost_enabled) + return -EINVAL; + + if (policy->boost_enabled == enable) + return count; + + cpus_read_lock(); + ret = cpufreq_driver->set_boost(policy, enable); + cpus_read_unlock(); + + if (ret) + return ret; + + policy->boost_enabled = enable; + + return count; +} + +static struct freq_attr local_boost = __ATTR(boost, 0644, show_local_boost, store_local_boost); + static struct cpufreq_governor *find_governor(const char *str_governor) { struct cpufreq_governor *t; @@ -1055,6 +1092,12 @@ static int cpufreq_add_dev_interface(struct cpufreq_policy *policy) return ret; } + if (cpufreq_boost_supported()) { + ret = sysfs_create_file(&policy->kobj, &local_boost.attr); + if (ret) + return ret; + } + return 0; } @@ -1943,16 +1986,16 @@ void cpufreq_resume(void) for_each_active_policy(policy) { if (cpufreq_driver->resume && cpufreq_driver->resume(policy)) { - pr_err("%s: Failed to resume driver: %p\n", __func__, - policy); + pr_err("%s: Failed to resume driver: %s\n", __func__, + cpufreq_driver->name); } else if (has_target()) { down_write(&policy->rwsem); ret = cpufreq_start_governor(policy); up_write(&policy->rwsem); if (ret) - pr_err("%s: Failed to start governor for policy: %p\n", - __func__, policy); + pr_err("%s: Failed to start governor for CPU%u's policy\n", + __func__, policy->cpu); } } } @@ -2716,6 +2759,8 @@ int cpufreq_boost_trigger_state(int state) ret = cpufreq_driver->set_boost(policy, state); if (ret) goto err_reset_state; + + policy->boost_enabled = state; } cpus_read_unlock(); diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c index 85da677c43d6..af44ee6a6430 100644 --- a/drivers/cpufreq/cpufreq_governor.c +++ b/drivers/cpufreq/cpufreq_governor.c @@ -439,7 +439,7 @@ int cpufreq_dbs_governor_init(struct cpufreq_policy *policy) ret = gov->init(dbs_data); if (ret) - goto free_policy_dbs_info; + goto free_dbs_data; /* * The sampling interval should not be less than the transition latency @@ -474,6 +474,8 @@ int cpufreq_dbs_governor_init(struct cpufreq_policy *policy) if (!have_governor_per_policy()) gov->gdbs_data = NULL; gov->exit(dbs_data); + +free_dbs_data: kfree(dbs_data); free_policy_dbs_info: diff --git a/drivers/cpufreq/pcc-cpufreq.c b/drivers/cpufreq/pcc-cpufreq.c index 84fe37def0f1..6f8b5ea7aeae 100644 --- a/drivers/cpufreq/pcc-cpufreq.c +++ b/drivers/cpufreq/pcc-cpufreq.c @@ -232,8 +232,8 @@ static int pcc_cpufreq_target(struct cpufreq_policy *policy, status = ioread16(&pcch_hdr->status); iowrite16(0, &pcch_hdr->status); - cpufreq_freq_transition_end(policy, &freqs, status != CMD_COMPLETE); spin_unlock(&pcc_lock); + cpufreq_freq_transition_end(policy, &freqs, status != CMD_COMPLETE); if (status != CMD_COMPLETE) { pr_debug("target: FAILED for cpu %d, with status: 0x%x\n", diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c index ebf15f31d97e..3cabeeabb1ca 100644 --- a/drivers/hv/connection.c +++ b/drivers/hv/connection.c @@ -98,6 +98,7 @@ int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo, u32 version) */ if (version >= VERSION_WIN10_V5) { msg->msg_sint = VMBUS_MESSAGE_SINT; + msg->msg_vtl = ms_hyperv.vtl; vmbus_connection.msg_conn_id = VMBUS_MESSAGE_CONNECTION_ID_4; } else { msg->interrupt_page = virt_to_phys(vmbus_connection.int_page); @@ -482,10 +483,17 @@ void vmbus_set_event(struct vmbus_channel *channel) ++channel->sig_events; - if (hv_isolation_type_snp()) - hv_ghcb_hypercall(HVCALL_SIGNAL_EVENT, &channel->sig_event, - NULL, sizeof(channel->sig_event)); - else + if (ms_hyperv.paravisor_present) { + if (hv_isolation_type_snp()) + hv_ghcb_hypercall(HVCALL_SIGNAL_EVENT, &channel->sig_event, + NULL, sizeof(channel->sig_event)); + else if (hv_isolation_type_tdx()) + hv_tdx_hypercall(HVCALL_SIGNAL_EVENT | HV_HYPERCALL_FAST_BIT, + channel->sig_event, 0); + else + WARN_ON_ONCE(1); + } else { hv_do_fast_hypercall8(HVCALL_SIGNAL_EVENT, channel->sig_event); + } } EXPORT_SYMBOL_GPL(vmbus_set_event); diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index de6708dbe0df..51e5018ac9b2 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -20,6 +20,7 @@ #include <linux/interrupt.h> #include <clocksource/hyperv_timer.h> #include <asm/mshyperv.h> +#include <linux/set_memory.h> #include "hyperv_vmbus.h" /* The one and only */ @@ -56,20 +57,37 @@ int hv_post_message(union hv_connection_id connection_id, local_irq_save(flags); - aligned_msg = *this_cpu_ptr(hyperv_pcpu_input_arg); + /* + * A TDX VM with the paravisor must use the decrypted post_msg_page: see + * the comment in struct hv_per_cpu_context. A SNP VM with the paravisor + * can use the encrypted hyperv_pcpu_input_arg because it copies the + * input into the GHCB page, which has been decrypted by the paravisor. + */ + if (hv_isolation_type_tdx() && ms_hyperv.paravisor_present) + aligned_msg = this_cpu_ptr(hv_context.cpu_context)->post_msg_page; + else + aligned_msg = *this_cpu_ptr(hyperv_pcpu_input_arg); + aligned_msg->connectionid = connection_id; aligned_msg->reserved = 0; aligned_msg->message_type = message_type; aligned_msg->payload_size = payload_size; memcpy((void *)aligned_msg->payload, payload, payload_size); - if (hv_isolation_type_snp()) - status = hv_ghcb_hypercall(HVCALL_POST_MESSAGE, - (void *)aligned_msg, NULL, - sizeof(*aligned_msg)); - else + if (ms_hyperv.paravisor_present) { + if (hv_isolation_type_tdx()) + status = hv_tdx_hypercall(HVCALL_POST_MESSAGE, + virt_to_phys(aligned_msg), 0); + else if (hv_isolation_type_snp()) + status = hv_ghcb_hypercall(HVCALL_POST_MESSAGE, + aligned_msg, NULL, + sizeof(*aligned_msg)); + else + status = HV_STATUS_INVALID_PARAMETER; + } else { status = hv_do_hypercall(HVCALL_POST_MESSAGE, aligned_msg, NULL); + } local_irq_restore(flags); @@ -78,7 +96,7 @@ int hv_post_message(union hv_connection_id connection_id, int hv_synic_alloc(void) { - int cpu; + int cpu, ret = -ENOMEM; struct hv_per_cpu_context *hv_cpu; /* @@ -104,11 +122,29 @@ int hv_synic_alloc(void) tasklet_init(&hv_cpu->msg_dpc, vmbus_on_msg_dpc, (unsigned long) hv_cpu); + if (ms_hyperv.paravisor_present && hv_isolation_type_tdx()) { + hv_cpu->post_msg_page = (void *)get_zeroed_page(GFP_ATOMIC); + if (hv_cpu->post_msg_page == NULL) { + pr_err("Unable to allocate post msg page\n"); + goto err; + } + + ret = set_memory_decrypted((unsigned long)hv_cpu->post_msg_page, 1); + if (ret) { + pr_err("Failed to decrypt post msg page: %d\n", ret); + /* Just leak the page, as it's unsafe to free the page. */ + hv_cpu->post_msg_page = NULL; + goto err; + } + + memset(hv_cpu->post_msg_page, 0, PAGE_SIZE); + } + /* * Synic message and event pages are allocated by paravisor. * Skip these pages allocation here. */ - if (!hv_isolation_type_snp() && !hv_root_partition) { + if (!ms_hyperv.paravisor_present && !hv_root_partition) { hv_cpu->synic_message_page = (void *)get_zeroed_page(GFP_ATOMIC); if (hv_cpu->synic_message_page == NULL) { @@ -120,29 +156,96 @@ int hv_synic_alloc(void) (void *)get_zeroed_page(GFP_ATOMIC); if (hv_cpu->synic_event_page == NULL) { pr_err("Unable to allocate SYNIC event page\n"); + + free_page((unsigned long)hv_cpu->synic_message_page); + hv_cpu->synic_message_page = NULL; goto err; } } + + if (!ms_hyperv.paravisor_present && + (hv_isolation_type_snp() || hv_isolation_type_tdx())) { + ret = set_memory_decrypted((unsigned long) + hv_cpu->synic_message_page, 1); + if (ret) { + pr_err("Failed to decrypt SYNIC msg page: %d\n", ret); + hv_cpu->synic_message_page = NULL; + + /* + * Free the event page here so that hv_synic_free() + * won't later try to re-encrypt it. + */ + free_page((unsigned long)hv_cpu->synic_event_page); + hv_cpu->synic_event_page = NULL; + goto err; + } + + ret = set_memory_decrypted((unsigned long) + hv_cpu->synic_event_page, 1); + if (ret) { + pr_err("Failed to decrypt SYNIC event page: %d\n", ret); + hv_cpu->synic_event_page = NULL; + goto err; + } + + memset(hv_cpu->synic_message_page, 0, PAGE_SIZE); + memset(hv_cpu->synic_event_page, 0, PAGE_SIZE); + } } return 0; + err: /* * Any memory allocations that succeeded will be freed when * the caller cleans up by calling hv_synic_free() */ - return -ENOMEM; + return ret; } void hv_synic_free(void) { - int cpu; + int cpu, ret; for_each_present_cpu(cpu) { struct hv_per_cpu_context *hv_cpu = per_cpu_ptr(hv_context.cpu_context, cpu); + /* It's better to leak the page if the encryption fails. */ + if (ms_hyperv.paravisor_present && hv_isolation_type_tdx()) { + if (hv_cpu->post_msg_page) { + ret = set_memory_encrypted((unsigned long) + hv_cpu->post_msg_page, 1); + if (ret) { + pr_err("Failed to encrypt post msg page: %d\n", ret); + hv_cpu->post_msg_page = NULL; + } + } + } + + if (!ms_hyperv.paravisor_present && + (hv_isolation_type_snp() || hv_isolation_type_tdx())) { + if (hv_cpu->synic_message_page) { + ret = set_memory_encrypted((unsigned long) + hv_cpu->synic_message_page, 1); + if (ret) { + pr_err("Failed to encrypt SYNIC msg page: %d\n", ret); + hv_cpu->synic_message_page = NULL; + } + } + + if (hv_cpu->synic_event_page) { + ret = set_memory_encrypted((unsigned long) + hv_cpu->synic_event_page, 1); + if (ret) { + pr_err("Failed to encrypt SYNIC event page: %d\n", ret); + hv_cpu->synic_event_page = NULL; + } + } + } + + free_page((unsigned long)hv_cpu->post_msg_page); free_page((unsigned long)hv_cpu->synic_event_page); free_page((unsigned long)hv_cpu->synic_message_page); } @@ -170,7 +273,7 @@ void hv_synic_enable_regs(unsigned int cpu) simp.as_uint64 = hv_get_register(HV_REGISTER_SIMP); simp.simp_enabled = 1; - if (hv_isolation_type_snp() || hv_root_partition) { + if (ms_hyperv.paravisor_present || hv_root_partition) { /* Mask out vTOM bit. ioremap_cache() maps decrypted */ u64 base = (simp.base_simp_gpa << HV_HYP_PAGE_SHIFT) & ~ms_hyperv.shared_gpa_boundary; @@ -189,7 +292,7 @@ void hv_synic_enable_regs(unsigned int cpu) siefp.as_uint64 = hv_get_register(HV_REGISTER_SIEFP); siefp.siefp_enabled = 1; - if (hv_isolation_type_snp() || hv_root_partition) { + if (ms_hyperv.paravisor_present || hv_root_partition) { /* Mask out vTOM bit. ioremap_cache() maps decrypted */ u64 base = (siefp.base_siefp_gpa << HV_HYP_PAGE_SHIFT) & ~ms_hyperv.shared_gpa_boundary; @@ -272,7 +375,7 @@ void hv_synic_disable_regs(unsigned int cpu) * addresses. */ simp.simp_enabled = 0; - if (hv_isolation_type_snp() || hv_root_partition) { + if (ms_hyperv.paravisor_present || hv_root_partition) { iounmap(hv_cpu->synic_message_page); hv_cpu->synic_message_page = NULL; } else { @@ -284,7 +387,7 @@ void hv_synic_disable_regs(unsigned int cpu) siefp.as_uint64 = hv_get_register(HV_REGISTER_SIEFP); siefp.siefp_enabled = 0; - if (hv_isolation_type_snp() || hv_root_partition) { + if (ms_hyperv.paravisor_present || hv_root_partition) { iounmap(hv_cpu->synic_event_page); hv_cpu->synic_event_page = NULL; } else { diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c index 0d7a3ba66396..e000fa3b9f97 100644 --- a/drivers/hv/hv_balloon.c +++ b/drivers/hv/hv_balloon.c @@ -8,6 +8,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include <linux/cleanup.h> #include <linux/kernel.h> #include <linux/jiffies.h> #include <linux/mman.h> @@ -646,7 +647,7 @@ static int hv_memory_notifier(struct notifier_block *nb, unsigned long val, void *v) { struct memory_notify *mem = (struct memory_notify *)v; - unsigned long flags, pfn_count; + unsigned long pfn_count; switch (val) { case MEM_ONLINE: @@ -655,21 +656,22 @@ static int hv_memory_notifier(struct notifier_block *nb, unsigned long val, break; case MEM_OFFLINE: - spin_lock_irqsave(&dm_device.ha_lock, flags); - pfn_count = hv_page_offline_check(mem->start_pfn, - mem->nr_pages); - if (pfn_count <= dm_device.num_pages_onlined) { - dm_device.num_pages_onlined -= pfn_count; - } else { - /* - * We're offlining more pages than we managed to online. - * This is unexpected. In any case don't let - * num_pages_onlined wrap around zero. - */ - WARN_ON_ONCE(1); - dm_device.num_pages_onlined = 0; + scoped_guard(spinlock_irqsave, &dm_device.ha_lock) { + pfn_count = hv_page_offline_check(mem->start_pfn, + mem->nr_pages); + if (pfn_count <= dm_device.num_pages_onlined) { + dm_device.num_pages_onlined -= pfn_count; + } else { + /* + * We're offlining more pages than we + * managed to online. This is + * unexpected. In any case don't let + * num_pages_onlined wrap around zero. + */ + WARN_ON_ONCE(1); + dm_device.num_pages_onlined = 0; + } } - spin_unlock_irqrestore(&dm_device.ha_lock, flags); break; case MEM_GOING_ONLINE: case MEM_GOING_OFFLINE: @@ -721,24 +723,23 @@ static void hv_mem_hot_add(unsigned long start, unsigned long size, unsigned long start_pfn; unsigned long processed_pfn; unsigned long total_pfn = pfn_count; - unsigned long flags; for (i = 0; i < (size/HA_CHUNK); i++) { start_pfn = start + (i * HA_CHUNK); - spin_lock_irqsave(&dm_device.ha_lock, flags); - has->ha_end_pfn += HA_CHUNK; + scoped_guard(spinlock_irqsave, &dm_device.ha_lock) { + has->ha_end_pfn += HA_CHUNK; - if (total_pfn > HA_CHUNK) { - processed_pfn = HA_CHUNK; - total_pfn -= HA_CHUNK; - } else { - processed_pfn = total_pfn; - total_pfn = 0; - } + if (total_pfn > HA_CHUNK) { + processed_pfn = HA_CHUNK; + total_pfn -= HA_CHUNK; + } else { + processed_pfn = total_pfn; + total_pfn = 0; + } - has->covered_end_pfn += processed_pfn; - spin_unlock_irqrestore(&dm_device.ha_lock, flags); + has->covered_end_pfn += processed_pfn; + } reinit_completion(&dm_device.ol_waitevent); @@ -758,10 +759,10 @@ static void hv_mem_hot_add(unsigned long start, unsigned long size, */ do_hot_add = false; } - spin_lock_irqsave(&dm_device.ha_lock, flags); - has->ha_end_pfn -= HA_CHUNK; - has->covered_end_pfn -= processed_pfn; - spin_unlock_irqrestore(&dm_device.ha_lock, flags); + scoped_guard(spinlock_irqsave, &dm_device.ha_lock) { + has->ha_end_pfn -= HA_CHUNK; + has->covered_end_pfn -= processed_pfn; + } break; } @@ -781,10 +782,9 @@ static void hv_mem_hot_add(unsigned long start, unsigned long size, static void hv_online_page(struct page *pg, unsigned int order) { struct hv_hotadd_state *has; - unsigned long flags; unsigned long pfn = page_to_pfn(pg); - spin_lock_irqsave(&dm_device.ha_lock, flags); + guard(spinlock_irqsave)(&dm_device.ha_lock); list_for_each_entry(has, &dm_device.ha_region_list, list) { /* The page belongs to a different HAS. */ if ((pfn < has->start_pfn) || @@ -794,7 +794,6 @@ static void hv_online_page(struct page *pg, unsigned int order) hv_bring_pgs_online(has, pfn, 1UL << order); break; } - spin_unlock_irqrestore(&dm_device.ha_lock, flags); } static int pfn_covered(unsigned long start_pfn, unsigned long pfn_cnt) @@ -803,9 +802,8 @@ static int pfn_covered(unsigned long start_pfn, unsigned long pfn_cnt) struct hv_hotadd_gap *gap; unsigned long residual, new_inc; int ret = 0; - unsigned long flags; - spin_lock_irqsave(&dm_device.ha_lock, flags); + guard(spinlock_irqsave)(&dm_device.ha_lock); list_for_each_entry(has, &dm_device.ha_region_list, list) { /* * If the pfn range we are dealing with is not in the current @@ -852,7 +850,6 @@ static int pfn_covered(unsigned long start_pfn, unsigned long pfn_cnt) ret = 1; break; } - spin_unlock_irqrestore(&dm_device.ha_lock, flags); return ret; } @@ -947,7 +944,6 @@ static unsigned long process_hot_add(unsigned long pg_start, { struct hv_hotadd_state *ha_region = NULL; int covered; - unsigned long flags; if (pfn_cnt == 0) return 0; @@ -979,9 +975,9 @@ static unsigned long process_hot_add(unsigned long pg_start, ha_region->covered_end_pfn = pg_start; ha_region->end_pfn = rg_start + rg_size; - spin_lock_irqsave(&dm_device.ha_lock, flags); - list_add_tail(&ha_region->list, &dm_device.ha_region_list); - spin_unlock_irqrestore(&dm_device.ha_lock, flags); + scoped_guard(spinlock_irqsave, &dm_device.ha_lock) { + list_add_tail(&ha_region->list, &dm_device.ha_region_list); + } } do_pg_range: @@ -2047,7 +2043,6 @@ static void balloon_remove(struct hv_device *dev) struct hv_dynmem_device *dm = hv_get_drvdata(dev); struct hv_hotadd_state *has, *tmp; struct hv_hotadd_gap *gap, *tmp_gap; - unsigned long flags; if (dm->num_pages_ballooned != 0) pr_warn("Ballooned pages: %d\n", dm->num_pages_ballooned); @@ -2073,7 +2068,7 @@ static void balloon_remove(struct hv_device *dev) #endif } - spin_lock_irqsave(&dm_device.ha_lock, flags); + guard(spinlock_irqsave)(&dm_device.ha_lock); list_for_each_entry_safe(has, tmp, &dm->ha_region_list, list) { list_for_each_entry_safe(gap, tmp_gap, &has->gap_list, list) { list_del(&gap->list); @@ -2082,7 +2077,6 @@ static void balloon_remove(struct hv_device *dev) list_del(&has->list); kfree(has); } - spin_unlock_irqrestore(&dm_device.ha_lock, flags); } static int balloon_suspend(struct hv_device *hv_dev) diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c index 6a2258fef1fe..ccad7bca3fd3 100644 --- a/drivers/hv/hv_common.c +++ b/drivers/hv/hv_common.c @@ -24,6 +24,7 @@ #include <linux/kmsg_dump.h> #include <linux/slab.h> #include <linux/dma-map-ops.h> +#include <linux/set_memory.h> #include <asm/hyperv-tlfs.h> #include <asm/mshyperv.h> @@ -359,6 +360,8 @@ int hv_common_cpu_init(unsigned int cpu) u64 msr_vp_index; gfp_t flags; int pgcount = hv_root_partition ? 2 : 1; + void *mem; + int ret; /* hv_cpu_init() can be called with IRQs disabled from hv_resume() */ flags = irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL; @@ -370,14 +373,41 @@ int hv_common_cpu_init(unsigned int cpu) * allocated if this CPU was previously online and then taken offline */ if (!*inputarg) { - *inputarg = kmalloc(pgcount * HV_HYP_PAGE_SIZE, flags); - if (!(*inputarg)) + mem = kmalloc(pgcount * HV_HYP_PAGE_SIZE, flags); + if (!mem) return -ENOMEM; if (hv_root_partition) { outputarg = (void **)this_cpu_ptr(hyperv_pcpu_output_arg); - *outputarg = (char *)(*inputarg) + HV_HYP_PAGE_SIZE; + *outputarg = (char *)mem + HV_HYP_PAGE_SIZE; + } + + if (!ms_hyperv.paravisor_present && + (hv_isolation_type_snp() || hv_isolation_type_tdx())) { + ret = set_memory_decrypted((unsigned long)mem, pgcount); + if (ret) { + /* It may be unsafe to free 'mem' */ + return ret; + } + + memset(mem, 0x00, pgcount * HV_HYP_PAGE_SIZE); } + + /* + * In a fully enlightened TDX/SNP VM with more than 64 VPs, if + * hyperv_pcpu_input_arg is not NULL, set_memory_decrypted() -> + * ... -> cpa_flush()-> ... -> __send_ipi_mask_ex() tries to + * use hyperv_pcpu_input_arg as the hypercall input page, which + * must be a decrypted page in such a VM, but the page is still + * encrypted before set_memory_decrypted() returns. Fix this by + * setting *inputarg after the above set_memory_decrypted(): if + * hyperv_pcpu_input_arg is NULL, __send_ipi_mask_ex() returns + * HV_STATUS_INVALID_PARAMETER immediately, and the function + * hv_send_ipi_mask() falls back to orig_apic.send_IPI_mask(), + * which may be slightly slower than the hypercall, but still + * works correctly in such a VM. + */ + *inputarg = mem; } msr_vp_index = hv_get_register(HV_REGISTER_VP_INDEX); @@ -502,6 +532,12 @@ bool __weak hv_isolation_type_snp(void) } EXPORT_SYMBOL_GPL(hv_isolation_type_snp); +bool __weak hv_isolation_type_tdx(void) +{ + return false; +} +EXPORT_SYMBOL_GPL(hv_isolation_type_tdx); + void __weak hv_setup_vmbus_handler(void (*handler)(void)) { } @@ -542,3 +578,9 @@ u64 __weak hv_ghcb_hypercall(u64 control, void *input, void *output, u32 input_s return HV_STATUS_INVALID_PARAMETER; } EXPORT_SYMBOL_GPL(hv_ghcb_hypercall); + +u64 __weak hv_tdx_hypercall(u64 control, u64 param1, u64 param2) +{ + return HV_STATUS_INVALID_PARAMETER; +} +EXPORT_SYMBOL_GPL(hv_tdx_hypercall); diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index 55f2086841ae..f6b1e710f805 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -124,6 +124,17 @@ struct hv_per_cpu_context { void *synic_event_page; /* + * The page is only used in hv_post_message() for a TDX VM (with the + * paravisor) to post a messages to Hyper-V: when such a VM calls + * HVCALL_POST_MESSAGE, it can't use the hyperv_pcpu_input_arg (which + * is encrypted in such a VM) as the hypercall input page, because + * the input page for HVCALL_POST_MESSAGE must be decrypted in such a + * VM, so post_msg_page (which is decrypted in hv_synic_alloc()) is + * introduced for this purpose. See hyperv_init() for more comments. + */ + void *post_msg_page; + + /* * Starting with win8, we can take channel interrupts on any CPU; * we will manage the tasklet that handles events messages on a per CPU * basis. diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 67f95a29aeca..edbb38f6956b 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -2287,7 +2287,8 @@ static int vmbus_acpi_add(struct platform_device *pdev) * Some ancestor of the vmbus acpi device (Gen1 or Gen2 * firmware) is the VMOD that has the mmio ranges. Get that. */ - for (ancestor = acpi_dev_parent(device); ancestor; + for (ancestor = acpi_dev_parent(device); + ancestor && ancestor->handle != ACPI_ROOT_OBJECT; ancestor = acpi_dev_parent(ancestor)) { result = acpi_walk_resources(ancestor->handle, METHOD_NAME__CRS, vmbus_walk_resources, NULL); diff --git a/drivers/hwspinlock/omap_hwspinlock.c b/drivers/hwspinlock/omap_hwspinlock.c index dfe82952671b..a9fd9ca45f2a 100644 --- a/drivers/hwspinlock/omap_hwspinlock.c +++ b/drivers/hwspinlock/omap_hwspinlock.c @@ -145,7 +145,7 @@ runtime_err: return ret; } -static int omap_hwspinlock_remove(struct platform_device *pdev) +static void omap_hwspinlock_remove(struct platform_device *pdev) { struct hwspinlock_device *bank = platform_get_drvdata(pdev); int ret; @@ -153,12 +153,10 @@ static int omap_hwspinlock_remove(struct platform_device *pdev) ret = hwspin_lock_unregister(bank); if (ret) { dev_err(&pdev->dev, "%s failed: %d\n", __func__, ret); - return ret; + return; } pm_runtime_disable(&pdev->dev); - - return 0; } static const struct of_device_id omap_hwspinlock_of_match[] = { @@ -171,7 +169,7 @@ MODULE_DEVICE_TABLE(of, omap_hwspinlock_of_match); static struct platform_driver omap_hwspinlock_driver = { .probe = omap_hwspinlock_probe, - .remove = omap_hwspinlock_remove, + .remove_new = omap_hwspinlock_remove, .driver = { .name = "omap_hwspinlock", .of_match_table = omap_hwspinlock_of_match, diff --git a/drivers/hwspinlock/qcom_hwspinlock.c b/drivers/hwspinlock/qcom_hwspinlock.c index 9cf186362ae2..a0fd67fd2934 100644 --- a/drivers/hwspinlock/qcom_hwspinlock.c +++ b/drivers/hwspinlock/qcom_hwspinlock.c @@ -69,9 +69,18 @@ static const struct hwspinlock_ops qcom_hwspinlock_ops = { .unlock = qcom_hwspinlock_unlock, }; +static const struct regmap_config sfpb_mutex_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x100, + .fast_io = true, +}; + static const struct qcom_hwspinlock_of_data of_sfpb_mutex = { .offset = 0x4, .stride = 0x4, + .regmap_config = &sfpb_mutex_config, }; static const struct regmap_config tcsr_msm8226_mutex_config = { @@ -197,6 +206,8 @@ static int qcom_hwspinlock_probe(struct platform_device *pdev) bank->lock[i].priv = devm_regmap_field_alloc(&pdev->dev, regmap, field); + if (IS_ERR(bank->lock[i].priv)) + return PTR_ERR(bank->lock[i].priv); } return devm_hwspin_lock_register(&pdev->dev, bank, &qcom_hwspinlock_ops, diff --git a/drivers/hwspinlock/u8500_hsem.c b/drivers/hwspinlock/u8500_hsem.c index 67845c0c9701..1edca1092f29 100644 --- a/drivers/hwspinlock/u8500_hsem.c +++ b/drivers/hwspinlock/u8500_hsem.c @@ -120,20 +120,18 @@ static int u8500_hsem_probe(struct platform_device *pdev) pdata->base_id, num_locks); } -static int u8500_hsem_remove(struct platform_device *pdev) +static void u8500_hsem_remove(struct platform_device *pdev) { struct hwspinlock_device *bank = platform_get_drvdata(pdev); void __iomem *io_base = bank->lock[0].priv - HSEM_REGISTER_OFFSET; /* clear all interrupts */ writel(0xFFFF, io_base + HSEM_ICRALL); - - return 0; } static struct platform_driver u8500_hsem_driver = { .probe = u8500_hsem_probe, - .remove = u8500_hsem_remove, + .remove_new = u8500_hsem_remove, .driver = { .name = "u8500_hsem", }, diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 9cfe8fc509d7..169607e80331 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -1384,7 +1384,7 @@ config I2C_ICY config I2C_MLXCPLD tristate "Mellanox I2C driver" - depends on X86_64 || COMPILE_TEST + depends on X86_64 || ARM64 || COMPILE_TEST help This exposes the Mellanox platform I2C busses to the linux I2C layer for X86 based systems. diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c index cc58feacd082..0231c5be6354 100644 --- a/drivers/i2c/busses/i2c-ali15x3.c +++ b/drivers/i2c/busses/i2c-ali15x3.c @@ -165,14 +165,15 @@ static int ali15x3_setup(struct pci_dev *ALI15X3_dev) } if(force_addr) { + int ret; + dev_info(&ALI15X3_dev->dev, "forcing ISA address 0x%04X\n", ali15x3_smba); - if (PCIBIOS_SUCCESSFUL != pci_write_config_word(ALI15X3_dev, - SMBBA, - ali15x3_smba)) + ret = pci_write_config_word(ALI15X3_dev, SMBBA, ali15x3_smba); + if (ret != PCIBIOS_SUCCESSFUL) goto error; - if (PCIBIOS_SUCCESSFUL != pci_read_config_word(ALI15X3_dev, - SMBBA, &a)) + ret = pci_read_config_word(ALI15X3_dev, SMBBA, &a); + if (ret != PCIBIOS_SUCCESSFUL) goto error; if ((a & ~(ALI15X3_SMB_IOSIZE - 1)) != ali15x3_smba) { /* make sure it works */ diff --git a/drivers/i2c/busses/i2c-at91-core.c b/drivers/i2c/busses/i2c-at91-core.c index 05ad3bc3578a..db45554327ae 100644 --- a/drivers/i2c/busses/i2c-at91-core.c +++ b/drivers/i2c/busses/i2c-at91-core.c @@ -19,7 +19,6 @@ #include <linux/io.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/pinctrl/consumer.h> @@ -207,19 +206,15 @@ static int at91_twi_probe(struct platform_device *pdev) dev->dev = &pdev->dev; - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem) - return -ENODEV; + dev->base = devm_platform_get_and_ioremap_resource(pdev, 0, &mem); + if (IS_ERR(dev->base)) + return PTR_ERR(dev->base); phy_addr = mem->start; dev->pdata = at91_twi_get_driver_data(pdev); if (!dev->pdata) return -ENODEV; - dev->base = devm_ioremap_resource(&pdev->dev, mem); - if (IS_ERR(dev->base)) - return PTR_ERR(dev->base); - dev->irq = platform_get_irq(pdev, 0); if (dev->irq < 0) return dev->irq; @@ -227,10 +222,9 @@ static int at91_twi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, dev); dev->clk = devm_clk_get(dev->dev, NULL); - if (IS_ERR(dev->clk)) { - dev_err(dev->dev, "no clock defined\n"); - return -ENODEV; - } + if (IS_ERR(dev->clk)) + return dev_err_probe(dev->dev, PTR_ERR(dev->clk), "no clock defined\n"); + clk_prepare_enable(dev->clk); snprintf(dev->adapter.name, sizeof(dev->adapter.name), "AT91"); diff --git a/drivers/i2c/busses/i2c-at91-master.c b/drivers/i2c/busses/i2c-at91-master.c index c0c35785a0dc..d311981d3e60 100644 --- a/drivers/i2c/busses/i2c-at91-master.c +++ b/drivers/i2c/busses/i2c-at91-master.c @@ -23,7 +23,6 @@ #include <linux/interrupt.h> #include <linux/io.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/pinctrl/consumer.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> @@ -832,7 +831,11 @@ static int at91_init_twi_recovery_gpio(struct platform_device *pdev, struct i2c_bus_recovery_info *rinfo = &dev->rinfo; rinfo->pinctrl = devm_pinctrl_get(&pdev->dev); - if (!rinfo->pinctrl || IS_ERR(rinfo->pinctrl)) { + if (!rinfo->pinctrl) { + dev_info(dev->dev, "pinctrl unavailable, bus recovery not supported\n"); + return 0; + } + if (IS_ERR(rinfo->pinctrl)) { dev_info(dev->dev, "can't get pinctrl, bus recovery not supported\n"); return PTR_ERR(rinfo->pinctrl); } diff --git a/drivers/i2c/busses/i2c-au1550.c b/drivers/i2c/busses/i2c-au1550.c index e66c12ecf270..8e43f25c117e 100644 --- a/drivers/i2c/busses/i2c-au1550.c +++ b/drivers/i2c/busses/i2c-au1550.c @@ -342,7 +342,6 @@ static void i2c_au1550_remove(struct platform_device *pdev) i2c_au1550_disable(priv); } -#ifdef CONFIG_PM static int i2c_au1550_suspend(struct device *dev) { struct i2c_au1550_data *priv = dev_get_drvdata(dev); @@ -361,21 +360,13 @@ static int i2c_au1550_resume(struct device *dev) return 0; } -static const struct dev_pm_ops i2c_au1550_pmops = { - .suspend = i2c_au1550_suspend, - .resume = i2c_au1550_resume, -}; - -#define AU1XPSC_SMBUS_PMOPS (&i2c_au1550_pmops) - -#else -#define AU1XPSC_SMBUS_PMOPS NULL -#endif +static DEFINE_SIMPLE_DEV_PM_OPS(i2c_au1550_pmops, + i2c_au1550_suspend, i2c_au1550_resume); static struct platform_driver au1xpsc_smbus_driver = { .driver = { .name = "au1xpsc_smbus", - .pm = AU1XPSC_SMBUS_PMOPS, + .pm = pm_sleep_ptr(&i2c_au1550_pmops), }, .probe = i2c_au1550_probe, .remove_new = i2c_au1550_remove, diff --git a/drivers/i2c/busses/i2c-bcm-iproc.c b/drivers/i2c/busses/i2c-bcm-iproc.c index 05c80680dff4..51aab662050b 100644 --- a/drivers/i2c/busses/i2c-bcm-iproc.c +++ b/drivers/i2c/busses/i2c-bcm-iproc.c @@ -7,7 +7,7 @@ #include <linux/io.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/slab.h> @@ -1029,7 +1029,6 @@ static int bcm_iproc_i2c_probe(struct platform_device *pdev) int irq, ret = 0; struct bcm_iproc_i2c_dev *iproc_i2c; struct i2c_adapter *adap; - struct resource *res; iproc_i2c = devm_kzalloc(&pdev->dev, sizeof(*iproc_i2c), GFP_KERNEL); @@ -1042,15 +1041,12 @@ static int bcm_iproc_i2c_probe(struct platform_device *pdev) (enum bcm_iproc_i2c_type)of_device_get_match_data(&pdev->dev); init_completion(&iproc_i2c->done); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - iproc_i2c->base = devm_ioremap_resource(iproc_i2c->device, res); + iproc_i2c->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(iproc_i2c->base)) return PTR_ERR(iproc_i2c->base); if (iproc_i2c->type == IPROC_I2C_NIC) { - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - iproc_i2c->idm_base = devm_ioremap_resource(iproc_i2c->device, - res); + iproc_i2c->idm_base = devm_platform_ioremap_resource(pdev, 1); if (IS_ERR(iproc_i2c->idm_base)) return PTR_ERR(iproc_i2c->idm_base); @@ -1128,8 +1124,6 @@ static void bcm_iproc_i2c_remove(struct platform_device *pdev) bcm_iproc_i2c_enable_disable(iproc_i2c, false); } -#ifdef CONFIG_PM_SLEEP - static int bcm_iproc_i2c_suspend(struct device *dev) { struct bcm_iproc_i2c_dev *iproc_i2c = dev_get_drvdata(dev); @@ -1180,12 +1174,6 @@ static const struct dev_pm_ops bcm_iproc_i2c_pm_ops = { .resume_early = &bcm_iproc_i2c_resume }; -#define BCM_IPROC_I2C_PM_OPS (&bcm_iproc_i2c_pm_ops) -#else -#define BCM_IPROC_I2C_PM_OPS NULL -#endif /* CONFIG_PM_SLEEP */ - - static int bcm_iproc_i2c_reg_slave(struct i2c_client *slave) { struct bcm_iproc_i2c_dev *iproc_i2c = i2c_get_adapdata(slave->adapter); @@ -1258,7 +1246,7 @@ static struct platform_driver bcm_iproc_i2c_driver = { .driver = { .name = "bcm-iproc-i2c", .of_match_table = bcm_iproc_i2c_of_match, - .pm = BCM_IPROC_I2C_PM_OPS, + .pm = pm_sleep_ptr(&bcm_iproc_i2c_pm_ops), }, .probe = bcm_iproc_i2c_probe, .remove_new = bcm_iproc_i2c_remove, diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c index 8ce6d3f49551..b92de1944221 100644 --- a/drivers/i2c/busses/i2c-bcm2835.c +++ b/drivers/i2c/busses/i2c-bcm2835.c @@ -12,7 +12,7 @@ #include <linux/interrupt.h> #include <linux/io.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/slab.h> @@ -430,10 +430,9 @@ static int bcm2835_i2c_probe(struct platform_device *pdev) i2c_dev->bus_clk = bcm2835_i2c_register_div(&pdev->dev, mclk, i2c_dev); - if (IS_ERR(i2c_dev->bus_clk)) { - dev_err(&pdev->dev, "Could not register clock\n"); - return PTR_ERR(i2c_dev->bus_clk); - } + if (IS_ERR(i2c_dev->bus_clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(i2c_dev->bus_clk), + "Could not register clock\n"); ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency", &bus_clk_rate); @@ -444,10 +443,9 @@ static int bcm2835_i2c_probe(struct platform_device *pdev) } ret = clk_set_rate_exclusive(i2c_dev->bus_clk, bus_clk_rate); - if (ret < 0) { - dev_err(&pdev->dev, "Could not set clock frequency\n"); - return ret; - } + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, + "Could not set clock frequency\n"); ret = clk_prepare_enable(i2c_dev->bus_clk); if (ret) { diff --git a/drivers/i2c/busses/i2c-brcmstb.c b/drivers/i2c/busses/i2c-brcmstb.c index cf92cbcb8c86..acee76732544 100644 --- a/drivers/i2c/busses/i2c-brcmstb.c +++ b/drivers/i2c/busses/i2c-brcmstb.c @@ -594,11 +594,10 @@ static int bcm2711_release_bsc(struct brcmstb_i2c_dev *dev) static int brcmstb_i2c_probe(struct platform_device *pdev) { - int rc = 0; struct brcmstb_i2c_dev *dev; struct i2c_adapter *adap; - struct resource *iomem; const char *int_name; + int rc; /* Allocate memory for private data structure */ dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); @@ -614,18 +613,15 @@ static int brcmstb_i2c_probe(struct platform_device *pdev) init_completion(&dev->done); /* Map hardware registers */ - iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - dev->base = devm_ioremap_resource(dev->device, iomem); - if (IS_ERR(dev->base)) { - rc = -ENOMEM; - goto probe_errorout; - } + dev->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(dev->base)) + return PTR_ERR(dev->base); if (of_device_is_compatible(dev->device->of_node, "brcm,bcm2711-hdmi-i2c")) { rc = bcm2711_release_bsc(dev); if (rc) - goto probe_errorout; + return rc; } rc = of_property_read_string(dev->device->of_node, "interrupt-names", @@ -678,16 +674,13 @@ static int brcmstb_i2c_probe(struct platform_device *pdev) adap->dev.of_node = pdev->dev.of_node; rc = i2c_add_adapter(adap); if (rc) - goto probe_errorout; + return rc; dev_info(dev->device, "%s@%dhz registered in %s mode\n", int_name ? int_name : " ", dev->clk_freq_hz, (dev->irq >= 0) ? "interrupt" : "polling"); return 0; - -probe_errorout: - return rc; } static void brcmstb_i2c_remove(struct platform_device *pdev) @@ -697,7 +690,6 @@ static void brcmstb_i2c_remove(struct platform_device *pdev) i2c_del_adapter(&dev->adapter); } -#ifdef CONFIG_PM_SLEEP static int brcmstb_i2c_suspend(struct device *dev) { struct brcmstb_i2c_dev *i2c_dev = dev_get_drvdata(dev); @@ -715,10 +707,9 @@ static int brcmstb_i2c_resume(struct device *dev) return 0; } -#endif -static SIMPLE_DEV_PM_OPS(brcmstb_i2c_pm, brcmstb_i2c_suspend, - brcmstb_i2c_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(brcmstb_i2c_pm, brcmstb_i2c_suspend, + brcmstb_i2c_resume); static const struct of_device_id brcmstb_i2c_of_match[] = { {.compatible = "brcm,brcmstb-i2c"}, @@ -732,7 +723,7 @@ static struct platform_driver brcmstb_i2c_driver = { .driver = { .name = "brcmstb-i2c", .of_match_table = brcmstb_i2c_of_match, - .pm = &brcmstb_i2c_pm, + .pm = pm_sleep_ptr(&brcmstb_i2c_pm), }, .probe = brcmstb_i2c_probe, .remove_new = brcmstb_i2c_remove, diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c index 732daf6a932b..9a664abf734d 100644 --- a/drivers/i2c/busses/i2c-cpm.c +++ b/drivers/i2c/busses/i2c-cpm.c @@ -26,10 +26,10 @@ #include <linux/i2c.h> #include <linux/io.h> #include <linux/dma-mapping.h> +#include <linux/of.h> #include <linux/of_address.h> -#include <linux/of_device.h> #include <linux/of_irq.h> -#include <linux/of_platform.h> +#include <linux/platform_device.h> #include <sysdev/fsl_soc.h> #include <asm/cpm.h> diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index 71b60778c643..02b3b1160fb0 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -25,7 +25,7 @@ #include <linux/slab.h> #include <linux/cpufreq.h> #include <linux/gpio/consumer.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_data/i2c-davinci.h> #include <linux/pm_runtime.h> @@ -765,7 +765,7 @@ static int davinci_i2c_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) - return dev_err_probe(&pdev->dev, irq, "can't get irq resource\n"); + return irq; dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); if (!dev) @@ -902,7 +902,6 @@ static void davinci_i2c_remove(struct platform_device *pdev) pm_runtime_disable(dev->dev); } -#ifdef CONFIG_PM static int davinci_i2c_suspend(struct device *dev) { struct davinci_i2c_dev *i2c_dev = dev_get_drvdata(dev); @@ -926,15 +925,10 @@ static int davinci_i2c_resume(struct device *dev) static const struct dev_pm_ops davinci_i2c_pm = { .suspend = davinci_i2c_suspend, .resume = davinci_i2c_resume, - SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) + NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) }; -#define davinci_i2c_pm_ops (&davinci_i2c_pm) -#else -#define davinci_i2c_pm_ops NULL -#endif - static const struct platform_device_id davinci_i2c_driver_ids[] = { { .name = "i2c_davinci", }, { /* sentinel */ } @@ -947,7 +941,7 @@ static struct platform_driver davinci_i2c_driver = { .id_table = davinci_i2c_driver_ids, .driver = { .name = "i2c_davinci", - .pm = davinci_i2c_pm_ops, + .pm = pm_sleep_ptr(&davinci_i2c_pm), .of_match_table = davinci_i2c_of_match, }, }; diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c index 24bef0025c98..ca1035e010c7 100644 --- a/drivers/i2c/busses/i2c-designware-master.c +++ b/drivers/i2c/busses/i2c-designware-master.c @@ -17,6 +17,7 @@ #include <linux/interrupt.h> #include <linux/io.h> #include <linux/module.h> +#include <linux/pinctrl/consumer.h> #include <linux/pm_runtime.h> #include <linux/regmap.h> #include <linux/reset.h> @@ -917,6 +918,17 @@ static int i2c_dw_init_recovery_info(struct dw_i2c_dev *dev) return PTR_ERR(gpio); rinfo->sda_gpiod = gpio; + rinfo->pinctrl = devm_pinctrl_get(dev->dev); + if (IS_ERR(rinfo->pinctrl)) { + if (PTR_ERR(rinfo->pinctrl) == -EPROBE_DEFER) + return PTR_ERR(rinfo->pinctrl); + + rinfo->pinctrl = NULL; + dev_err(dev->dev, "getting pinctrl info failed: bus recovery might not work\n"); + } else if (!rinfo->pinctrl) { + dev_dbg(dev->dev, "pinctrl is disabled, bus recovery might not work\n"); + } + rinfo->recover_bus = i2c_generic_scl_recovery; rinfo->prepare_recovery = i2c_dw_prepare_recovery; rinfo->unprepare_recovery = i2c_dw_unprepare_recovery; diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index 970c1c3b0402..855b698e99c0 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -418,7 +418,6 @@ static void dw_i2c_plat_remove(struct platform_device *pdev) reset_control_assert(dev->rst); } -#ifdef CONFIG_PM_SLEEP static int dw_i2c_plat_prepare(struct device *dev) { /* @@ -429,11 +428,7 @@ static int dw_i2c_plat_prepare(struct device *dev) */ return !has_acpi_companion(dev); } -#else -#define dw_i2c_plat_prepare NULL -#endif -#ifdef CONFIG_PM static int dw_i2c_plat_runtime_suspend(struct device *dev) { struct dw_i2c_dev *i_dev = dev_get_drvdata(dev); @@ -447,7 +442,7 @@ static int dw_i2c_plat_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused dw_i2c_plat_suspend(struct device *dev) +static int dw_i2c_plat_suspend(struct device *dev) { struct dw_i2c_dev *i_dev = dev_get_drvdata(dev); @@ -468,7 +463,7 @@ static int dw_i2c_plat_runtime_resume(struct device *dev) return 0; } -static int __maybe_unused dw_i2c_plat_resume(struct device *dev) +static int dw_i2c_plat_resume(struct device *dev) { struct dw_i2c_dev *i_dev = dev_get_drvdata(dev); @@ -479,16 +474,11 @@ static int __maybe_unused dw_i2c_plat_resume(struct device *dev) } static const struct dev_pm_ops dw_i2c_dev_pm_ops = { - .prepare = dw_i2c_plat_prepare, - SET_LATE_SYSTEM_SLEEP_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume) - SET_RUNTIME_PM_OPS(dw_i2c_plat_runtime_suspend, dw_i2c_plat_runtime_resume, NULL) + .prepare = pm_sleep_ptr(dw_i2c_plat_prepare), + LATE_SYSTEM_SLEEP_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume) + RUNTIME_PM_OPS(dw_i2c_plat_runtime_suspend, dw_i2c_plat_runtime_resume, NULL) }; -#define DW_I2C_DEV_PMOPS (&dw_i2c_dev_pm_ops) -#else -#define DW_I2C_DEV_PMOPS NULL -#endif - /* Work with hotplug and coldplug */ MODULE_ALIAS("platform:i2c_designware"); @@ -499,7 +489,7 @@ static struct platform_driver dw_i2c_driver = { .name = "i2c_designware", .of_match_table = of_match_ptr(dw_i2c_of_match), .acpi_match_table = ACPI_PTR(dw_i2c_acpi_match), - .pm = DW_I2C_DEV_PMOPS, + .pm = pm_ptr(&dw_i2c_dev_pm_ops), }, }; diff --git a/drivers/i2c/busses/i2c-dln2.c b/drivers/i2c/busses/i2c-dln2.c index 4f02cc2fb567..631109c7a098 100644 --- a/drivers/i2c/busses/i2c-dln2.c +++ b/drivers/i2c/busses/i2c-dln2.c @@ -218,10 +218,8 @@ static int dln2_i2c_probe(struct platform_device *pdev) /* initialize the i2c interface */ ret = dln2_i2c_enable(dln2, true); - if (ret < 0) { - dev_err(dev, "failed to initialize adapter: %d\n", ret); - return ret; - } + if (ret < 0) + return dev_err_probe(dev, ret, "failed to initialize adapter\n"); /* and finally attach to i2c layer */ ret = i2c_add_adapter(&dln2->adapter); diff --git a/drivers/i2c/busses/i2c-emev2.c b/drivers/i2c/busses/i2c-emev2.c index 4ba93cd91c0f..557409410445 100644 --- a/drivers/i2c/busses/i2c-emev2.c +++ b/drivers/i2c/busses/i2c-emev2.c @@ -16,7 +16,7 @@ #include <linux/io.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/sched.h> diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c index f378cd479e55..2b0b9cdffa86 100644 --- a/drivers/i2c/busses/i2c-exynos5.c +++ b/drivers/i2c/busses/i2c-exynos5.c @@ -18,9 +18,7 @@ #include <linux/clk.h> #include <linux/slab.h> #include <linux/io.h> -#include <linux/of_address.h> -#include <linux/of_device.h> -#include <linux/of_irq.h> +#include <linux/of.h> #include <linux/spinlock.h> /* @@ -892,7 +890,6 @@ static void exynos5_i2c_remove(struct platform_device *pdev) clk_unprepare(i2c->pclk); } -#ifdef CONFIG_PM_SLEEP static int exynos5_i2c_suspend_noirq(struct device *dev) { struct exynos5_i2c *i2c = dev_get_drvdata(dev); @@ -934,11 +931,10 @@ err_pclk: clk_disable_unprepare(i2c->pclk); return ret; } -#endif static const struct dev_pm_ops exynos5_i2c_dev_pm_ops = { - SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(exynos5_i2c_suspend_noirq, - exynos5_i2c_resume_noirq) + NOIRQ_SYSTEM_SLEEP_PM_OPS(exynos5_i2c_suspend_noirq, + exynos5_i2c_resume_noirq) }; static struct platform_driver exynos5_i2c_driver = { @@ -946,7 +942,7 @@ static struct platform_driver exynos5_i2c_driver = { .remove_new = exynos5_i2c_remove, .driver = { .name = "exynos5-hsi2c", - .pm = &exynos5_i2c_dev_pm_ops, + .pm = pm_sleep_ptr(&exynos5_i2c_dev_pm_ops), .of_match_table = exynos5_i2c_match, }, }; diff --git a/drivers/i2c/busses/i2c-gxp.c b/drivers/i2c/busses/i2c-gxp.c index 70b0de07ed99..efafc0528c44 100644 --- a/drivers/i2c/busses/i2c-gxp.c +++ b/drivers/i2c/busses/i2c-gxp.c @@ -4,8 +4,9 @@ #include <linux/err.h> #include <linux/io.h> #include <linux/i2c.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/mfd/syscon.h> diff --git a/drivers/i2c/busses/i2c-hisi.c b/drivers/i2c/busses/i2c-hisi.c index 0980c773cb5b..dfad5bad5075 100644 --- a/drivers/i2c/busses/i2c-hisi.c +++ b/drivers/i2c/busses/i2c-hisi.c @@ -470,18 +470,14 @@ static int hisi_i2c_probe(struct platform_device *pdev) hisi_i2c_disable_int(ctlr, HISI_I2C_INT_ALL); ret = devm_request_irq(dev, ctlr->irq, hisi_i2c_irq, 0, "hisi-i2c", ctlr); - if (ret) { - dev_err(dev, "failed to request irq handler, ret = %d\n", ret); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "failed to request irq handler\n"); ctlr->clk = devm_clk_get_optional_enabled(&pdev->dev, NULL); if (IS_ERR_OR_NULL(ctlr->clk)) { ret = device_property_read_u64(dev, "clk_rate", &clk_rate_hz); - if (ret) { - dev_err(dev, "failed to get clock frequency, ret = %d\n", ret); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "failed to get clock frequency\n"); } else { clk_rate_hz = clk_get_rate(ctlr->clk); } diff --git a/drivers/i2c/busses/i2c-hix5hd2.c b/drivers/i2c/busses/i2c-hix5hd2.c index 784a5f56eb76..8e75515c3ca4 100644 --- a/drivers/i2c/busses/i2c-hix5hd2.c +++ b/drivers/i2c/busses/i2c-hix5hd2.c @@ -475,7 +475,6 @@ static void hix5hd2_i2c_remove(struct platform_device *pdev) pm_runtime_set_suspended(priv->dev); } -#ifdef CONFIG_PM static int hix5hd2_i2c_runtime_suspend(struct device *dev) { struct hix5hd2_i2c_priv *priv = dev_get_drvdata(dev); @@ -494,12 +493,11 @@ static int hix5hd2_i2c_runtime_resume(struct device *dev) return 0; } -#endif static const struct dev_pm_ops hix5hd2_i2c_pm_ops = { - SET_RUNTIME_PM_OPS(hix5hd2_i2c_runtime_suspend, - hix5hd2_i2c_runtime_resume, - NULL) + RUNTIME_PM_OPS(hix5hd2_i2c_runtime_suspend, + hix5hd2_i2c_runtime_resume, + NULL) }; static const struct of_device_id hix5hd2_i2c_match[] = { @@ -513,7 +511,7 @@ static struct platform_driver hix5hd2_i2c_driver = { .remove_new = hix5hd2_i2c_remove, .driver = { .name = "hix5hd2-i2c", - .pm = &hix5hd2_i2c_pm_ops, + .pm = pm_ptr(&hix5hd2_i2c_pm_ops), .of_match_table = hix5hd2_i2c_match, }, }; diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 943b8e6d026d..73ae06432133 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -1808,7 +1808,6 @@ static void i801_shutdown(struct pci_dev *dev) pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg); } -#ifdef CONFIG_PM_SLEEP static int i801_suspend(struct device *dev) { struct i801_priv *priv = dev_get_drvdata(dev); @@ -1827,9 +1826,8 @@ static int i801_resume(struct device *dev) return 0; } -#endif -static SIMPLE_DEV_PM_OPS(i801_pm_ops, i801_suspend, i801_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(i801_pm_ops, i801_suspend, i801_resume); static struct pci_driver i801_driver = { .name = DRV_NAME, @@ -1838,7 +1836,7 @@ static struct pci_driver i801_driver = { .remove = i801_remove, .shutdown = i801_shutdown, .driver = { - .pm = &i801_pm_ops, + .pm = pm_sleep_ptr(&i801_pm_ops), .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, }; diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c index 1ad9d3b26dd3..408820319ec4 100644 --- a/drivers/i2c/busses/i2c-ibm_iic.c +++ b/drivers/i2c/busses/i2c-ibm_iic.c @@ -37,9 +37,10 @@ #include <asm/irq.h> #include <linux/io.h> #include <linux/i2c.h> +#include <linux/of.h> #include <linux/of_address.h> #include <linux/of_irq.h> -#include <linux/of_platform.h> +#include <linux/platform_device.h> #include "i2c-ibm_iic.h" diff --git a/drivers/i2c/busses/i2c-img-scb.c b/drivers/i2c/busses/i2c-img-scb.c index 66ba36949ab5..f9d4bfef511c 100644 --- a/drivers/i2c/busses/i2c-img-scb.c +++ b/drivers/i2c/busses/i2c-img-scb.c @@ -1454,7 +1454,6 @@ static int img_i2c_runtime_resume(struct device *dev) return 0; } -#ifdef CONFIG_PM_SLEEP static int img_i2c_suspend(struct device *dev) { struct img_i2c *i2c = dev_get_drvdata(dev); @@ -1482,13 +1481,10 @@ static int img_i2c_resume(struct device *dev) return 0; } -#endif /* CONFIG_PM_SLEEP */ static const struct dev_pm_ops img_i2c_pm = { - SET_RUNTIME_PM_OPS(img_i2c_runtime_suspend, - img_i2c_runtime_resume, - NULL) - SET_SYSTEM_SLEEP_PM_OPS(img_i2c_suspend, img_i2c_resume) + RUNTIME_PM_OPS(img_i2c_runtime_suspend, img_i2c_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(img_i2c_suspend, img_i2c_resume) }; static const struct of_device_id img_scb_i2c_match[] = { @@ -1501,7 +1497,7 @@ static struct platform_driver img_scb_i2c_driver = { .driver = { .name = "img-i2c-scb", .of_match_table = img_scb_i2c_match, - .pm = &img_i2c_pm, + .pm = pm_ptr(&img_i2c_pm), }, .probe = img_i2c_probe, .remove_new = img_i2c_remove, diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c b/drivers/i2c/busses/i2c-imx-lpi2c.c index 150d923ca7f1..678b30e90492 100644 --- a/drivers/i2c/busses/i2c-imx-lpi2c.c +++ b/drivers/i2c/busses/i2c-imx-lpi2c.c @@ -17,7 +17,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/pinctrl/consumer.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> @@ -517,14 +516,12 @@ static irqreturn_t lpi2c_imx_isr(int irq, void *dev_id) temp = readl(lpi2c_imx->base + LPI2C_MSR); temp &= enabled; - if (temp & MSR_RDF) - lpi2c_imx_read_rxfifo(lpi2c_imx); - - if (temp & MSR_TDF) - lpi2c_imx_write_txfifo(lpi2c_imx); - if (temp & MSR_NDF) complete(&lpi2c_imx->complete); + else if (temp & MSR_RDF) + lpi2c_imx_read_rxfifo(lpi2c_imx); + else if (temp & MSR_TDF) + lpi2c_imx_write_txfifo(lpi2c_imx); return IRQ_HANDLED; } @@ -572,10 +569,8 @@ static int lpi2c_imx_probe(struct platform_device *pdev) sizeof(lpi2c_imx->adapter.name)); ret = devm_clk_bulk_get_all(&pdev->dev, &lpi2c_imx->clks); - if (ret < 0) { - dev_err(&pdev->dev, "can't get I2C peripheral clock, ret=%d\n", ret); - return ret; - } + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, "can't get I2C peripheral clock\n"); lpi2c_imx->num_clks = ret; ret = of_property_read_u32(pdev->dev.of_node, @@ -585,10 +580,8 @@ static int lpi2c_imx_probe(struct platform_device *pdev) ret = devm_request_irq(&pdev->dev, irq, lpi2c_imx_isr, 0, pdev->name, lpi2c_imx); - if (ret) { - dev_err(&pdev->dev, "can't claim irq %d\n", irq); - return ret; - } + if (ret) + return dev_err_probe(&pdev->dev, ret, "can't claim irq %d\n", irq); i2c_set_adapdata(&lpi2c_imx->adapter, lpi2c_imx); platform_set_drvdata(pdev, lpi2c_imx); diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index 65128a73e8a3..1775a79aeba2 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -41,7 +41,6 @@ #include <linux/hrtimer.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/of_dma.h> #include <linux/pinctrl/consumer.h> #include <linux/platform_data/i2c-imx.h> @@ -1389,7 +1388,11 @@ static int i2c_imx_init_recovery_info(struct imx_i2c_struct *i2c_imx, struct i2c_bus_recovery_info *rinfo = &i2c_imx->rinfo; i2c_imx->pinctrl = devm_pinctrl_get(&pdev->dev); - if (!i2c_imx->pinctrl || IS_ERR(i2c_imx->pinctrl)) { + if (!i2c_imx->pinctrl) { + dev_info(&pdev->dev, "pinctrl unavailable, bus recovery not supported\n"); + return 0; + } + if (IS_ERR(i2c_imx->pinctrl)) { dev_info(&pdev->dev, "can't get pinctrl, bus recovery not supported\n"); return PTR_ERR(i2c_imx->pinctrl); } @@ -1506,8 +1509,7 @@ static int i2c_imx_probe(struct platform_device *pdev) goto rpm_disable; /* Request IRQ */ - ret = request_threaded_irq(irq, i2c_imx_isr, NULL, IRQF_SHARED, - pdev->name, i2c_imx); + ret = request_irq(irq, i2c_imx_isr, IRQF_SHARED, pdev->name, i2c_imx); if (ret) { dev_err(&pdev->dev, "can't claim irq %d\n", irq); goto rpm_disable; diff --git a/drivers/i2c/busses/i2c-jz4780.c b/drivers/i2c/busses/i2c-jz4780.c index 0dfe60399521..55035cca0ae5 100644 --- a/drivers/i2c/busses/i2c-jz4780.c +++ b/drivers/i2c/busses/i2c-jz4780.c @@ -18,7 +18,7 @@ #include <linux/io.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/sched.h> #include <linux/slab.h> diff --git a/drivers/i2c/busses/i2c-kempld.c b/drivers/i2c/busses/i2c-kempld.c index 281058e3ea46..e01d75308288 100644 --- a/drivers/i2c/busses/i2c-kempld.c +++ b/drivers/i2c/busses/i2c-kempld.c @@ -350,10 +350,9 @@ static void kempld_i2c_remove(struct platform_device *pdev) i2c_del_adapter(&i2c->adap); } -#ifdef CONFIG_PM -static int kempld_i2c_suspend(struct platform_device *pdev, pm_message_t state) +static int kempld_i2c_suspend(struct device *dev) { - struct kempld_i2c_data *i2c = platform_get_drvdata(pdev); + struct kempld_i2c_data *i2c = dev_get_drvdata(dev); struct kempld_device_data *pld = i2c->pld; u8 ctrl; @@ -366,9 +365,9 @@ static int kempld_i2c_suspend(struct platform_device *pdev, pm_message_t state) return 0; } -static int kempld_i2c_resume(struct platform_device *pdev) +static int kempld_i2c_resume(struct device *dev) { - struct kempld_i2c_data *i2c = platform_get_drvdata(pdev); + struct kempld_i2c_data *i2c = dev_get_drvdata(dev); struct kempld_device_data *pld = i2c->pld; kempld_get_mutex(pld); @@ -377,19 +376,17 @@ static int kempld_i2c_resume(struct platform_device *pdev) return 0; } -#else -#define kempld_i2c_suspend NULL -#define kempld_i2c_resume NULL -#endif + +static DEFINE_SIMPLE_DEV_PM_OPS(kempld_i2c_pm_ops, + kempld_i2c_suspend, kempld_i2c_resume); static struct platform_driver kempld_i2c_driver = { .driver = { .name = "kempld-i2c", + .pm = pm_sleep_ptr(&kempld_i2c_pm_ops), }, .probe = kempld_i2c_probe, .remove_new = kempld_i2c_remove, - .suspend = kempld_i2c_suspend, - .resume = kempld_i2c_resume, }; module_platform_driver(kempld_i2c_driver); diff --git a/drivers/i2c/busses/i2c-lpc2k.c b/drivers/i2c/busses/i2c-lpc2k.c index 5c6d96554753..e3660333e91c 100644 --- a/drivers/i2c/busses/i2c-lpc2k.c +++ b/drivers/i2c/busses/i2c-lpc2k.c @@ -20,7 +20,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/sched.h> #include <linux/time.h> @@ -431,7 +430,6 @@ static void i2c_lpc2k_remove(struct platform_device *dev) i2c_del_adapter(&i2c->adap); } -#ifdef CONFIG_PM static int i2c_lpc2k_suspend(struct device *dev) { struct lpc2k_i2c *i2c = dev_get_drvdata(dev); @@ -456,11 +454,6 @@ static const struct dev_pm_ops i2c_lpc2k_dev_pm_ops = { .resume_noirq = i2c_lpc2k_resume, }; -#define I2C_LPC2K_DEV_PM_OPS (&i2c_lpc2k_dev_pm_ops) -#else -#define I2C_LPC2K_DEV_PM_OPS NULL -#endif - static const struct of_device_id lpc2k_i2c_match[] = { { .compatible = "nxp,lpc1788-i2c" }, {}, @@ -472,7 +465,7 @@ static struct platform_driver i2c_lpc2k_driver = { .remove_new = i2c_lpc2k_remove, .driver = { .name = "lpc2k-i2c", - .pm = I2C_LPC2K_DEV_PM_OPS, + .pm = pm_sleep_ptr(&i2c_lpc2k_dev_pm_ops), .of_match_table = lpc2k_i2c_match, }, }; diff --git a/drivers/i2c/busses/i2c-meson.c b/drivers/i2c/busses/i2c-meson.c index 16026c895bb6..c7b203cc4434 100644 --- a/drivers/i2c/busses/i2c-meson.c +++ b/drivers/i2c/busses/i2c-meson.c @@ -15,7 +15,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/types.h> diff --git a/drivers/i2c/busses/i2c-microchip-corei2c.c b/drivers/i2c/busses/i2c-microchip-corei2c.c index 7f58f7eaabb6..0b0a1c4d17ca 100644 --- a/drivers/i2c/busses/i2c-microchip-corei2c.c +++ b/drivers/i2c/busses/i2c-microchip-corei2c.c @@ -378,9 +378,8 @@ static int mchp_corei2c_probe(struct platform_device *pdev) return PTR_ERR(idev->base); irq = platform_get_irq(pdev, 0); - if (irq <= 0) - return dev_err_probe(&pdev->dev, -ENXIO, - "invalid IRQ %d for I2C controller\n", irq); + if (irq < 0) + return irq; idev->i2c_clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(idev->i2c_clk)) diff --git a/drivers/i2c/busses/i2c-mlxbf.c b/drivers/i2c/busses/i2c-mlxbf.c index ae66bdd1b737..b3a73921ab69 100644 --- a/drivers/i2c/busses/i2c-mlxbf.c +++ b/drivers/i2c/busses/i2c-mlxbf.c @@ -15,7 +15,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/mutex.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/string.h> @@ -1080,13 +1080,7 @@ static int mlxbf_i2c_init_resource(struct platform_device *pdev, if (!tmp_res) return -ENOMEM; - tmp_res->params = platform_get_resource(pdev, IORESOURCE_MEM, type); - if (!tmp_res->params) { - devm_kfree(dev, tmp_res); - return -EIO; - } - - tmp_res->io = devm_ioremap_resource(dev, tmp_res->params); + tmp_res->io = devm_platform_get_and_ioremap_resource(pdev, type, &tmp_res->params); if (IS_ERR(tmp_res->io)) { devm_kfree(dev, tmp_res); return PTR_ERR(tmp_res->io); @@ -2323,10 +2317,8 @@ static int mlxbf_i2c_probe(struct platform_device *pdev) ret = mlxbf_i2c_init_resource(pdev, &priv->smbus, MLXBF_I2C_SMBUS_RES); - if (ret < 0) { - dev_err(dev, "Cannot fetch smbus resource info"); - return ret; - } + if (ret < 0) + return dev_err_probe(dev, ret, "Cannot fetch smbus resource info"); priv->timer->io = priv->smbus->io; priv->mst->io = priv->smbus->io + MLXBF_I2C_MST_ADDR_OFFSET; @@ -2334,39 +2326,29 @@ static int mlxbf_i2c_probe(struct platform_device *pdev) } else { ret = mlxbf_i2c_init_resource(pdev, &priv->timer, MLXBF_I2C_SMBUS_TIMER_RES); - if (ret < 0) { - dev_err(dev, "Cannot fetch timer resource info"); - return ret; - } + if (ret < 0) + return dev_err_probe(dev, ret, "Cannot fetch timer resource info"); ret = mlxbf_i2c_init_resource(pdev, &priv->mst, MLXBF_I2C_SMBUS_MST_RES); - if (ret < 0) { - dev_err(dev, "Cannot fetch master resource info"); - return ret; - } + if (ret < 0) + return dev_err_probe(dev, ret, "Cannot fetch master resource info"); ret = mlxbf_i2c_init_resource(pdev, &priv->slv, MLXBF_I2C_SMBUS_SLV_RES); - if (ret < 0) { - dev_err(dev, "Cannot fetch slave resource info"); - return ret; - } + if (ret < 0) + return dev_err_probe(dev, ret, "Cannot fetch slave resource info"); } ret = mlxbf_i2c_init_resource(pdev, &priv->mst_cause, MLXBF_I2C_MST_CAUSE_RES); - if (ret < 0) { - dev_err(dev, "Cannot fetch cause master resource info"); - return ret; - } + if (ret < 0) + return dev_err_probe(dev, ret, "Cannot fetch cause master resource info"); ret = mlxbf_i2c_init_resource(pdev, &priv->slv_cause, MLXBF_I2C_SLV_CAUSE_RES); - if (ret < 0) { - dev_err(dev, "Cannot fetch cause slave resource info"); - return ret; - } + if (ret < 0) + return dev_err_probe(dev, ret, "Cannot fetch cause slave resource info"); adap = &priv->adap; adap->owner = THIS_MODULE; @@ -2397,11 +2379,9 @@ static int mlxbf_i2c_probe(struct platform_device *pdev) * does not really hurt, then keep the code as is. */ ret = mlxbf_i2c_init_master(pdev, priv); - if (ret < 0) { - dev_err(dev, "failed to initialize smbus master %d", - priv->bus); - return ret; - } + if (ret < 0) + return dev_err_probe(dev, ret, "failed to initialize smbus master %d", + priv->bus); mlxbf_i2c_init_timings(pdev, priv); @@ -2413,10 +2393,8 @@ static int mlxbf_i2c_probe(struct platform_device *pdev) ret = devm_request_irq(dev, irq, mlxbf_i2c_irq, IRQF_SHARED | IRQF_PROBE_SHARED, dev_name(dev), priv); - if (ret < 0) { - dev_err(dev, "Cannot get irq %d\n", irq); - return ret; - } + if (ret < 0) + return dev_err_probe(dev, ret, "Cannot get irq %d\n", irq); priv->irq = irq; diff --git a/drivers/i2c/busses/i2c-mlxcpld.c b/drivers/i2c/busses/i2c-mlxcpld.c index c42fd4b329e4..6fec64ea67fb 100644 --- a/drivers/i2c/busses/i2c-mlxcpld.c +++ b/drivers/i2c/busses/i2c-mlxcpld.c @@ -22,6 +22,7 @@ #define MLXCPLD_I2C_BUS_NUM 1 #define MLXCPLD_I2C_DATA_REG_SZ 36 #define MLXCPLD_I2C_DATA_SZ_BIT BIT(5) +#define MLXCPLD_I2C_DATA_EXT2_SZ_BIT BIT(6) #define MLXCPLD_I2C_DATA_SZ_MASK GENMASK(6, 5) #define MLXCPLD_I2C_SMBUS_BLK_BIT BIT(7) #define MLXCPLD_I2C_MAX_ADDR_LEN 4 @@ -466,6 +467,13 @@ static const struct i2c_adapter_quirks mlxcpld_i2c_quirks_ext = { .max_comb_1st_msg_len = 4, }; +static const struct i2c_adapter_quirks mlxcpld_i2c_quirks_ext2 = { + .flags = I2C_AQ_COMB_WRITE_THEN_READ, + .max_read_len = (MLXCPLD_I2C_DATA_REG_SZ - 4) * 4, + .max_write_len = (MLXCPLD_I2C_DATA_REG_SZ - 4) * 4 + MLXCPLD_I2C_MAX_ADDR_LEN, + .max_comb_1st_msg_len = 4, +}; + static struct i2c_adapter mlxcpld_i2c_adapter = { .owner = THIS_MODULE, .name = "i2c-mlxcpld", @@ -547,6 +555,8 @@ static int mlxcpld_i2c_probe(struct platform_device *pdev) /* Check support for extended transaction length */ if ((val & MLXCPLD_I2C_DATA_SZ_MASK) == MLXCPLD_I2C_DATA_SZ_BIT) mlxcpld_i2c_adapter.quirks = &mlxcpld_i2c_quirks_ext; + else if ((val & MLXCPLD_I2C_DATA_SZ_MASK) == MLXCPLD_I2C_DATA_EXT2_SZ_BIT) + mlxcpld_i2c_adapter.quirks = &mlxcpld_i2c_quirks_ext2; /* Check support for smbus block transaction */ if (val & MLXCPLD_I2C_SMBUS_BLK_BIT) priv->smbus_block = true; diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index f460a7fb4eae..e4e4995ab224 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -11,9 +11,10 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/sched/signal.h> +#include <linux/of.h> #include <linux/of_address.h> #include <linux/of_irq.h> -#include <linux/of_platform.h> +#include <linux/platform_device.h> #include <linux/property.h> #include <linux/slab.h> diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c index 7ca3f2221ba6..1a9b5a068ef1 100644 --- a/drivers/i2c/busses/i2c-mt65xx.c +++ b/drivers/i2c/busses/i2c-mt65xx.c @@ -19,9 +19,7 @@ #include <linux/kernel.h> #include <linux/mm.h> #include <linux/module.h> -#include <linux/of_address.h> -#include <linux/of_device.h> -#include <linux/of_irq.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/scatterlist.h> #include <linux/sched.h> @@ -1514,7 +1512,6 @@ static void mtk_i2c_remove(struct platform_device *pdev) clk_bulk_unprepare(I2C_MT65XX_CLK_MAX, i2c->clocks); } -#ifdef CONFIG_PM_SLEEP static int mtk_i2c_suspend_noirq(struct device *dev) { struct mtk_i2c *i2c = dev_get_drvdata(dev); @@ -1544,11 +1541,10 @@ static int mtk_i2c_resume_noirq(struct device *dev) return 0; } -#endif static const struct dev_pm_ops mtk_i2c_pm = { - SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(mtk_i2c_suspend_noirq, - mtk_i2c_resume_noirq) + NOIRQ_SYSTEM_SLEEP_PM_OPS(mtk_i2c_suspend_noirq, + mtk_i2c_resume_noirq) }; static struct platform_driver mtk_i2c_driver = { @@ -1556,7 +1552,7 @@ static struct platform_driver mtk_i2c_driver = { .remove_new = mtk_i2c_remove, .driver = { .name = I2C_DRV_NAME, - .pm = &mtk_i2c_pm, + .pm = pm_sleep_ptr(&mtk_i2c_pm), .of_match_table = mtk_i2c_of_match, }, }; diff --git a/drivers/i2c/busses/i2c-mt7621.c b/drivers/i2c/busses/i2c-mt7621.c index 104bb194e990..81d46169bc1f 100644 --- a/drivers/i2c/busses/i2c-mt7621.c +++ b/drivers/i2c/busses/i2c-mt7621.c @@ -16,7 +16,8 @@ #include <linux/io.h> #include <linux/iopoll.h> #include <linux/module.h> -#include <linux/of_platform.h> +#include <linux/of.h> +#include <linux/platform_device.h> #include <linux/reset.h> #define REG_SM0CFG2_REG 0x28 diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c index 1d76f1c4dc06..36def0a9c95c 100644 --- a/drivers/i2c/busses/i2c-mxs.c +++ b/drivers/i2c/busses/i2c-mxs.c @@ -22,7 +22,6 @@ #include <linux/io.h> #include <linux/stmp_device.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/dma-mapping.h> #include <linux/dmaengine.h> #include <linux/dma/mxs-dma.h> diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c index 777278386f58..38d203d93eee 100644 --- a/drivers/i2c/busses/i2c-nforce2.c +++ b/drivers/i2c/busses/i2c-nforce2.c @@ -327,8 +327,8 @@ static int nforce2_probe_smb(struct pci_dev *dev, int bar, int alt_reg, /* Older incarnations of the device used non-standard BARs */ u16 iobase; - if (pci_read_config_word(dev, alt_reg, &iobase) - != PCIBIOS_SUCCESSFUL) { + error = pci_read_config_word(dev, alt_reg, &iobase); + if (error != PCIBIOS_SUCCESSFUL) { dev_err(&dev->dev, "Error reading PCI config for %s\n", name); return -EIO; diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index 212f412f1c74..b10574d42b7a 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -873,7 +873,6 @@ static irqreturn_t i2c_irq_handler(int irq, void *arg) return IRQ_HANDLED; } -#ifdef CONFIG_PM_SLEEP static int nmk_i2c_suspend_late(struct device *dev) { int ret; @@ -890,9 +889,7 @@ static int nmk_i2c_resume_early(struct device *dev) { return pm_runtime_force_resume(dev); } -#endif -#ifdef CONFIG_PM static int nmk_i2c_runtime_suspend(struct device *dev) { struct amba_device *adev = to_amba_device(dev); @@ -925,13 +922,10 @@ static int nmk_i2c_runtime_resume(struct device *dev) return ret; } -#endif static const struct dev_pm_ops nmk_i2c_pm = { - SET_LATE_SYSTEM_SLEEP_PM_OPS(nmk_i2c_suspend_late, nmk_i2c_resume_early) - SET_RUNTIME_PM_OPS(nmk_i2c_runtime_suspend, - nmk_i2c_runtime_resume, - NULL) + LATE_SYSTEM_SLEEP_PM_OPS(nmk_i2c_suspend_late, nmk_i2c_resume_early) + RUNTIME_PM_OPS(nmk_i2c_runtime_suspend, nmk_i2c_runtime_resume, NULL) }; static unsigned int nmk_i2c_functionality(struct i2c_adapter *adap) @@ -1078,7 +1072,7 @@ static struct amba_driver nmk_i2c_driver = { .drv = { .owner = THIS_MODULE, .name = DRIVER_NAME, - .pm = &nmk_i2c_pm, + .pm = pm_ptr(&nmk_i2c_pm), }, .id_table = nmk_i2c_ids, .probe = nmk_i2c_probe, diff --git a/drivers/i2c/busses/i2c-npcm7xx.c b/drivers/i2c/busses/i2c-npcm7xx.c index 53b65ffb6a64..495a8b5f6a2b 100644 --- a/drivers/i2c/busses/i2c-npcm7xx.c +++ b/drivers/i2c/busses/i2c-npcm7xx.c @@ -17,7 +17,6 @@ #include <linux/mfd/syscon.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/regmap.h> diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c index 4ac77e57bbbf..041a76f71a49 100644 --- a/drivers/i2c/busses/i2c-ocores.c +++ b/drivers/i2c/busses/i2c-ocores.c @@ -743,7 +743,6 @@ static void ocores_i2c_remove(struct platform_device *pdev) i2c_del_adapter(&i2c->adap); } -#ifdef CONFIG_PM_SLEEP static int ocores_i2c_suspend(struct device *dev) { struct ocores_i2c *i2c = dev_get_drvdata(dev); @@ -772,11 +771,8 @@ static int ocores_i2c_resume(struct device *dev) return ocores_init(dev, i2c); } -static SIMPLE_DEV_PM_OPS(ocores_i2c_pm, ocores_i2c_suspend, ocores_i2c_resume); -#define OCORES_I2C_PM (&ocores_i2c_pm) -#else -#define OCORES_I2C_PM NULL -#endif +static DEFINE_SIMPLE_DEV_PM_OPS(ocores_i2c_pm, + ocores_i2c_suspend, ocores_i2c_resume); static struct platform_driver ocores_i2c_driver = { .probe = ocores_i2c_probe, @@ -784,7 +780,7 @@ static struct platform_driver ocores_i2c_driver = { .driver = { .name = "ocores-i2c", .of_match_table = ocores_i2c_match, - .pm = OCORES_I2C_PM, + .pm = pm_sleep_ptr(&ocores_i2c_pm), }, }; diff --git a/drivers/i2c/busses/i2c-owl.c b/drivers/i2c/busses/i2c-owl.c index 5f0ef8c35141..777f1a0278c7 100644 --- a/drivers/i2c/busses/i2c-owl.c +++ b/drivers/i2c/busses/i2c-owl.c @@ -16,7 +16,8 @@ #include <linux/io.h> #include <linux/iopoll.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> +#include <linux/platform_device.h> /* I2C registers */ #define OWL_I2C_REG_CTL 0x0000 diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c index d2a9e7b61c1a..b8d5480c54f6 100644 --- a/drivers/i2c/busses/i2c-pca-platform.c +++ b/drivers/i2c/busses/i2c-pca-platform.c @@ -22,7 +22,6 @@ #include <linux/gpio/consumer.h> #include <linux/io.h> #include <linux/of.h> -#include <linux/of_device.h> #include <asm/irq.h> diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c index 82400057f810..a12525b3186b 100644 --- a/drivers/i2c/busses/i2c-pnx.c +++ b/drivers/i2c/busses/i2c-pnx.c @@ -613,7 +613,6 @@ static const struct i2c_algorithm pnx_algorithm = { .functionality = i2c_pnx_func, }; -#ifdef CONFIG_PM_SLEEP static int i2c_pnx_controller_suspend(struct device *dev) { struct i2c_pnx_algo_data *alg_data = dev_get_drvdata(dev); @@ -630,12 +629,9 @@ static int i2c_pnx_controller_resume(struct device *dev) return clk_prepare_enable(alg_data->clk); } -static SIMPLE_DEV_PM_OPS(i2c_pnx_pm, - i2c_pnx_controller_suspend, i2c_pnx_controller_resume); -#define PNX_I2C_PM (&i2c_pnx_pm) -#else -#define PNX_I2C_PM NULL -#endif +static DEFINE_SIMPLE_DEV_PM_OPS(i2c_pnx_pm, + i2c_pnx_controller_suspend, + i2c_pnx_controller_resume); static int i2c_pnx_probe(struct platform_device *pdev) { @@ -683,8 +679,7 @@ static int i2c_pnx_probe(struct platform_device *pdev) "%s", pdev->name); /* Register I/O resource */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - alg_data->ioaddr = devm_ioremap_resource(&pdev->dev, res); + alg_data->ioaddr = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(alg_data->ioaddr)) return PTR_ERR(alg_data->ioaddr); @@ -763,7 +758,7 @@ static struct platform_driver i2c_pnx_driver = { .driver = { .name = "pnx-i2c", .of_match_table = of_match_ptr(i2c_pnx_of_match), - .pm = PNX_I2C_PM, + .pm = pm_sleep_ptr(&i2c_pnx_pm), }, .probe = i2c_pnx_probe, .remove_new = i2c_pnx_remove, diff --git a/drivers/i2c/busses/i2c-pxa-pci.c b/drivers/i2c/busses/i2c-pxa-pci.c index 30e38bc8b6db..08b3229c443d 100644 --- a/drivers/i2c/busses/i2c-pxa-pci.c +++ b/drivers/i2c/busses/i2c-pxa-pci.c @@ -12,7 +12,6 @@ #include <linux/platform_device.h> #include <linux/platform_data/i2c-pxa.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/of_address.h> #define CE4100_PCI_I2C_DEVS 3 diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 937f7eebe906..29be05af826b 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -1362,7 +1362,7 @@ static int i2c_pxa_probe(struct platform_device *dev) struct i2c_pxa_platform_data *plat = dev_get_platdata(&dev->dev); enum pxa_i2c_types i2c_type; struct pxa_i2c *i2c; - struct resource *res = NULL; + struct resource *res; int ret, irq; i2c = devm_kzalloc(&dev->dev, sizeof(struct pxa_i2c), GFP_KERNEL); @@ -1379,8 +1379,7 @@ static int i2c_pxa_probe(struct platform_device *dev) i2c->adap.dev.of_node = dev->dev.of_node; #endif - res = platform_get_resource(dev, IORESOURCE_MEM, 0); - i2c->reg_base = devm_ioremap_resource(&dev->dev, res); + i2c->reg_base = devm_platform_get_and_ioremap_resource(dev, 0, &res); if (IS_ERR(i2c->reg_base)) return PTR_ERR(i2c->reg_base); @@ -1404,10 +1403,9 @@ static int i2c_pxa_probe(struct platform_device *dev) strscpy(i2c->adap.name, "pxa_i2c-i2c", sizeof(i2c->adap.name)); i2c->clk = devm_clk_get(&dev->dev, NULL); - if (IS_ERR(i2c->clk)) { - dev_err(&dev->dev, "failed to get the clk: %ld\n", PTR_ERR(i2c->clk)); - return PTR_ERR(i2c->clk); - } + if (IS_ERR(i2c->clk)) + return dev_err_probe(&dev->dev, PTR_ERR(i2c->clk), + "failed to get the clk\n"); i2c->reg_ibmr = i2c->reg_base + pxa_reg_layout[i2c_type].ibmr; i2c->reg_idbr = i2c->reg_base + pxa_reg_layout[i2c_type].idbr; @@ -1491,7 +1489,6 @@ static void i2c_pxa_remove(struct platform_device *dev) clk_disable_unprepare(i2c->clk); } -#ifdef CONFIG_PM static int i2c_pxa_suspend_noirq(struct device *dev) { struct pxa_i2c *i2c = dev_get_drvdata(dev); @@ -1516,17 +1513,12 @@ static const struct dev_pm_ops i2c_pxa_dev_pm_ops = { .resume_noirq = i2c_pxa_resume_noirq, }; -#define I2C_PXA_DEV_PM_OPS (&i2c_pxa_dev_pm_ops) -#else -#define I2C_PXA_DEV_PM_OPS NULL -#endif - static struct platform_driver i2c_pxa_driver = { .probe = i2c_pxa_probe, .remove_new = i2c_pxa_remove, .driver = { .name = "pxa2xx-i2c", - .pm = I2C_PXA_DEV_PM_OPS, + .pm = pm_sleep_ptr(&i2c_pxa_dev_pm_ops), .of_match_table = i2c_pxa_dt_ids, }, .id_table = i2c_pxa_id_table, diff --git a/drivers/i2c/busses/i2c-qcom-cci.c b/drivers/i2c/busses/i2c-qcom-cci.c index 622dc14add9d..414882c57d7f 100644 --- a/drivers/i2c/busses/i2c-qcom-cci.c +++ b/drivers/i2c/busses/i2c-qcom-cci.c @@ -588,10 +588,10 @@ static int cci_probe(struct platform_device *pdev) /* Clocks */ ret = devm_clk_bulk_get_all(dev, &cci->clocks); - if (ret < 1) { - dev_err(dev, "failed to get clocks %d\n", ret); - return ret; - } + if (ret < 0) + return dev_err_probe(dev, ret, "failed to get clocks\n"); + else if (!ret) + return dev_err_probe(dev, -EINVAL, "not enough clocks in DT\n"); cci->nclocks = ret; /* Retrieve CCI clock rate */ diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index b670a67c4fdd..229353e96e09 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -767,7 +767,6 @@ err_tx: static int geni_i2c_probe(struct platform_device *pdev) { struct geni_i2c_dev *gi2c; - struct resource *res; u32 proto, tx_depth, fifo_disable; int ret; struct device *dev = &pdev->dev; @@ -779,8 +778,7 @@ static int geni_i2c_probe(struct platform_device *pdev) gi2c->se.dev = dev; gi2c->se.wrapper = dev_get_drvdata(dev->parent); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - gi2c->se.base = devm_ioremap_resource(dev, res); + gi2c->se.base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(gi2c->se.base)) return PTR_ERR(gi2c->se.base); diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c index ae90170023b0..598102d16677 100644 --- a/drivers/i2c/busses/i2c-qup.c +++ b/drivers/i2c/busses/i2c-qup.c @@ -1927,7 +1927,6 @@ static void qup_i2c_remove(struct platform_device *pdev) pm_runtime_set_suspended(qup->dev); } -#ifdef CONFIG_PM static int qup_i2c_pm_suspend_runtime(struct device *device) { struct qup_i2c_dev *qup = dev_get_drvdata(device); @@ -1945,9 +1944,7 @@ static int qup_i2c_pm_resume_runtime(struct device *device) qup_i2c_enable_clocks(qup); return 0; } -#endif -#ifdef CONFIG_PM_SLEEP static int qup_i2c_suspend(struct device *device) { if (!pm_runtime_suspended(device)) @@ -1962,16 +1959,11 @@ static int qup_i2c_resume(struct device *device) pm_request_autosuspend(device); return 0; } -#endif static const struct dev_pm_ops qup_i2c_qup_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS( - qup_i2c_suspend, - qup_i2c_resume) - SET_RUNTIME_PM_OPS( - qup_i2c_pm_suspend_runtime, - qup_i2c_pm_resume_runtime, - NULL) + SYSTEM_SLEEP_PM_OPS(qup_i2c_suspend, qup_i2c_resume) + RUNTIME_PM_OPS(qup_i2c_pm_suspend_runtime, + qup_i2c_pm_resume_runtime, NULL) }; static const struct of_device_id qup_i2c_dt_match[] = { @@ -1987,7 +1979,7 @@ static struct platform_driver qup_i2c_driver = { .remove_new = qup_i2c_remove, .driver = { .name = "i2c_qup", - .pm = &qup_i2c_qup_pm_ops, + .pm = pm_ptr(&qup_i2c_qup_pm_ops), .of_match_table = qup_i2c_dt_match, .acpi_match_table = ACPI_PTR(qup_i2c_acpi_match), }, diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c index 2d9c37410ebd..a32a93f9a60d 100644 --- a/drivers/i2c/busses/i2c-rcar.c +++ b/drivers/i2c/busses/i2c-rcar.c @@ -24,7 +24,7 @@ #include <linux/i2c-smbus.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/reset.h> @@ -1169,7 +1169,6 @@ static void rcar_i2c_remove(struct platform_device *pdev) pm_runtime_disable(dev); } -#ifdef CONFIG_PM_SLEEP static int rcar_i2c_suspend(struct device *dev) { struct rcar_i2c_priv *priv = dev_get_drvdata(dev); @@ -1187,19 +1186,14 @@ static int rcar_i2c_resume(struct device *dev) } static const struct dev_pm_ops rcar_i2c_pm_ops = { - SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(rcar_i2c_suspend, rcar_i2c_resume) + NOIRQ_SYSTEM_SLEEP_PM_OPS(rcar_i2c_suspend, rcar_i2c_resume) }; -#define DEV_PM_OPS (&rcar_i2c_pm_ops) -#else -#define DEV_PM_OPS NULL -#endif /* CONFIG_PM_SLEEP */ - static struct platform_driver rcar_i2c_driver = { .driver = { .name = "i2c-rcar", .of_match_table = rcar_i2c_dt_ids, - .pm = DEV_PM_OPS, + .pm = pm_sleep_ptr(&rcar_i2c_pm_ops), }, .probe = rcar_i2c_probe, .remove_new = rcar_i2c_remove, diff --git a/drivers/i2c/busses/i2c-riic.c b/drivers/i2c/busses/i2c-riic.c index 5f8c0bd508d2..f0ee8871d5ae 100644 --- a/drivers/i2c/busses/i2c-riic.c +++ b/drivers/i2c/busses/i2c-riic.c @@ -42,7 +42,6 @@ #include <linux/io.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/reset.h> diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 28f0e5c64f32..127eb3805fac 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -24,7 +24,6 @@ #include <linux/slab.h> #include <linux/io.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/gpio/consumer.h> #include <linux/pinctrl/consumer.h> #include <linux/mfd/syscon.h> @@ -1034,9 +1033,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "clock source %p\n", i2c->clk); /* map the registers */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - i2c->regs = devm_ioremap_resource(&pdev->dev, res); - + i2c->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(i2c->regs)) return PTR_ERR(i2c->regs); @@ -1076,7 +1073,6 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) if (!(i2c->quirks & QUIRK_POLL)) { i2c->irq = ret = platform_get_irq(pdev, 0); if (ret < 0) { - dev_err(&pdev->dev, "cannot find IRQ\n"); clk_unprepare(i2c->clk); return ret; } @@ -1125,7 +1121,6 @@ static void s3c24xx_i2c_remove(struct platform_device *pdev) i2c_del_adapter(&i2c->adap); } -#ifdef CONFIG_PM_SLEEP static int s3c24xx_i2c_suspend_noirq(struct device *dev) { struct s3c24xx_i2c *i2c = dev_get_drvdata(dev); @@ -1155,26 +1150,19 @@ static int s3c24xx_i2c_resume_noirq(struct device *dev) return 0; } -#endif -#ifdef CONFIG_PM static const struct dev_pm_ops s3c24xx_i2c_dev_pm_ops = { - SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(s3c24xx_i2c_suspend_noirq, - s3c24xx_i2c_resume_noirq) + NOIRQ_SYSTEM_SLEEP_PM_OPS(s3c24xx_i2c_suspend_noirq, + s3c24xx_i2c_resume_noirq) }; -#define S3C24XX_DEV_PM_OPS (&s3c24xx_i2c_dev_pm_ops) -#else -#define S3C24XX_DEV_PM_OPS NULL -#endif - static struct platform_driver s3c24xx_i2c_driver = { .probe = s3c24xx_i2c_probe, .remove_new = s3c24xx_i2c_remove, .id_table = s3c24xx_driver_ids, .driver = { .name = "s3c-i2c", - .pm = S3C24XX_DEV_PM_OPS, + .pm = pm_sleep_ptr(&s3c24xx_i2c_dev_pm_ops), .of_match_table = of_match_ptr(s3c24xx_i2c_match), }, }; diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index 21717b943a9e..5adbe62cf621 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -20,7 +20,7 @@ #include <linux/io.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/slab.h> @@ -871,7 +871,6 @@ static int sh_mobile_i2c_probe(struct platform_device *dev) { struct sh_mobile_i2c_data *pd; struct i2c_adapter *adap; - struct resource *res; const struct sh_mobile_dt_config *config; int ret; u32 bus_speed; @@ -893,10 +892,7 @@ static int sh_mobile_i2c_probe(struct platform_device *dev) pd->dev = &dev->dev; platform_set_drvdata(dev, pd); - res = platform_get_resource(dev, IORESOURCE_MEM, 0); - - pd->res = res; - pd->reg = devm_ioremap_resource(&dev->dev, res); + pd->reg = devm_platform_get_and_ioremap_resource(dev, 0, &pd->res); if (IS_ERR(pd->reg)) return PTR_ERR(pd->reg); @@ -905,7 +901,7 @@ static int sh_mobile_i2c_probe(struct platform_device *dev) pd->clks_per_count = 1; /* Newer variants come with two new bits in ICIC */ - if (resource_size(res) > 0x17) + if (resource_size(pd->res) > 0x17) pd->flags |= IIC_FLAG_HAS_ICIC67; pm_runtime_enable(&dev->dev); @@ -965,7 +961,6 @@ static void sh_mobile_i2c_remove(struct platform_device *dev) pm_runtime_disable(&dev->dev); } -#ifdef CONFIG_PM_SLEEP static int sh_mobile_i2c_suspend(struct device *dev) { struct sh_mobile_i2c_data *pd = dev_get_drvdata(dev); @@ -983,20 +978,15 @@ static int sh_mobile_i2c_resume(struct device *dev) } static const struct dev_pm_ops sh_mobile_i2c_pm_ops = { - SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(sh_mobile_i2c_suspend, - sh_mobile_i2c_resume) + NOIRQ_SYSTEM_SLEEP_PM_OPS(sh_mobile_i2c_suspend, + sh_mobile_i2c_resume) }; -#define DEV_PM_OPS (&sh_mobile_i2c_pm_ops) -#else -#define DEV_PM_OPS NULL -#endif /* CONFIG_PM_SLEEP */ - static struct platform_driver sh_mobile_i2c_driver = { .driver = { .name = "i2c-sh_mobile", .of_match_table = sh_mobile_i2c_dt_ids, - .pm = DEV_PM_OPS, + .pm = pm_sleep_ptr(&sh_mobile_i2c_pm_ops), }, .probe = sh_mobile_i2c_probe, .remove_new = sh_mobile_i2c_remove, diff --git a/drivers/i2c/busses/i2c-sis5595.c b/drivers/i2c/busses/i2c-sis5595.c index c793a5c14cda..486f1e9dfb74 100644 --- a/drivers/i2c/busses/i2c-sis5595.c +++ b/drivers/i2c/busses/i2c-sis5595.c @@ -175,11 +175,11 @@ static int sis5595_setup(struct pci_dev *SIS5595_dev) if (force_addr) { dev_info(&SIS5595_dev->dev, "forcing ISA address 0x%04X\n", sis5595_base); - if (pci_write_config_word(SIS5595_dev, ACPI_BASE, sis5595_base) - != PCIBIOS_SUCCESSFUL) + retval = pci_write_config_word(SIS5595_dev, ACPI_BASE, sis5595_base); + if (retval != PCIBIOS_SUCCESSFUL) goto error; - if (pci_read_config_word(SIS5595_dev, ACPI_BASE, &a) - != PCIBIOS_SUCCESSFUL) + retval = pci_read_config_word(SIS5595_dev, ACPI_BASE, &a); + if (retval != PCIBIOS_SUCCESSFUL) goto error; if ((a & ~(SIS5595_EXTENT - 1)) != sis5595_base) { /* doesn't work for some chips! */ @@ -188,16 +188,16 @@ static int sis5595_setup(struct pci_dev *SIS5595_dev) } } - if (pci_read_config_byte(SIS5595_dev, SIS5595_ENABLE_REG, &val) - != PCIBIOS_SUCCESSFUL) + retval = pci_read_config_byte(SIS5595_dev, SIS5595_ENABLE_REG, &val); + if (retval != PCIBIOS_SUCCESSFUL) goto error; if ((val & 0x80) == 0) { dev_info(&SIS5595_dev->dev, "enabling ACPI\n"); - if (pci_write_config_byte(SIS5595_dev, SIS5595_ENABLE_REG, val | 0x80) - != PCIBIOS_SUCCESSFUL) + retval = pci_write_config_byte(SIS5595_dev, SIS5595_ENABLE_REG, val | 0x80); + if (retval != PCIBIOS_SUCCESSFUL) goto error; - if (pci_read_config_byte(SIS5595_dev, SIS5595_ENABLE_REG, &val) - != PCIBIOS_SUCCESSFUL) + retval = pci_read_config_byte(SIS5595_dev, SIS5595_ENABLE_REG, &val); + if (retval != PCIBIOS_SUCCESSFUL) goto error; if ((val & 0x80) == 0) { /* doesn't work for some chips? */ diff --git a/drivers/i2c/busses/i2c-sprd.c b/drivers/i2c/busses/i2c-sprd.c index ffc54fbf814d..c52d1bec60b4 100644 --- a/drivers/i2c/busses/i2c-sprd.c +++ b/drivers/i2c/busses/i2c-sprd.c @@ -14,7 +14,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> diff --git a/drivers/i2c/busses/i2c-st.c b/drivers/i2c/busses/i2c-st.c index 25c3521cae0e..ce2333408904 100644 --- a/drivers/i2c/busses/i2c-st.c +++ b/drivers/i2c/busses/i2c-st.c @@ -812,8 +812,7 @@ static int st_i2c_probe(struct platform_device *pdev) if (!i2c_dev) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - i2c_dev->base = devm_ioremap_resource(&pdev->dev, res); + i2c_dev->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(i2c_dev->base)) return PTR_ERR(i2c_dev->base); diff --git a/drivers/i2c/busses/i2c-stm32f4.c b/drivers/i2c/busses/i2c-stm32f4.c index 6ad06a5a22b4..ecc54792a66f 100644 --- a/drivers/i2c/busses/i2c-stm32f4.c +++ b/drivers/i2c/busses/i2c-stm32f4.c @@ -767,8 +767,7 @@ static int stm32f4_i2c_probe(struct platform_device *pdev) if (!i2c_dev) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - i2c_dev->base = devm_ioremap_resource(&pdev->dev, res); + i2c_dev->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(i2c_dev->base)) return PTR_ERR(i2c_dev->base); diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c index e897d9101434..579b30581725 100644 --- a/drivers/i2c/busses/i2c-stm32f7.c +++ b/drivers/i2c/busses/i2c-stm32f7.c @@ -2121,12 +2121,12 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) phy_addr = (dma_addr_t)res->start; irq_event = platform_get_irq(pdev, 0); - if (irq_event <= 0) - return irq_event ? : -ENOENT; + if (irq_event < 0) + return irq_event; irq_error = platform_get_irq(pdev, 1); - if (irq_error <= 0) - return irq_error ? : -ENOENT; + if (irq_error < 0) + return irq_error; i2c_dev->wakeup_src = of_property_read_bool(pdev->dev.of_node, "wakeup-source"); diff --git a/drivers/i2c/busses/i2c-synquacer.c b/drivers/i2c/busses/i2c-synquacer.c index 4cc196ca8f6d..bbea521b05dd 100644 --- a/drivers/i2c/busses/i2c-synquacer.c +++ b/drivers/i2c/busses/i2c-synquacer.c @@ -557,20 +557,16 @@ static int synquacer_i2c_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "clock source %p\n", i2c->pclk); ret = clk_prepare_enable(i2c->pclk); - if (ret) { - dev_err(&pdev->dev, "failed to enable clock (%d)\n", - ret); - return ret; - } + if (ret) + return dev_err_probe(&pdev->dev, ret, "failed to enable clock\n"); i2c->pclkrate = clk_get_rate(i2c->pclk); } if (i2c->pclkrate < SYNQUACER_I2C_MIN_CLK_RATE || - i2c->pclkrate > SYNQUACER_I2C_MAX_CLK_RATE) { - dev_err(&pdev->dev, "PCLK missing or out of range (%d)\n", - i2c->pclkrate); - return -EINVAL; - } + i2c->pclkrate > SYNQUACER_I2C_MAX_CLK_RATE) + return dev_err_probe(&pdev->dev, -EINVAL, + "PCLK missing or out of range (%d)\n", + i2c->pclkrate); i2c->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(i2c->base)) @@ -582,10 +578,8 @@ static int synquacer_i2c_probe(struct platform_device *pdev) ret = devm_request_irq(&pdev->dev, i2c->irq, synquacer_i2c_isr, 0, dev_name(&pdev->dev), i2c); - if (ret < 0) { - dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq); - return ret; - } + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, "cannot claim IRQ %d\n", i2c->irq); i2c->state = STATE_IDLE; i2c->dev = &pdev->dev; @@ -605,10 +599,8 @@ static int synquacer_i2c_probe(struct platform_device *pdev) synquacer_i2c_hw_init(i2c); ret = i2c_add_numbered_adapter(&i2c->adapter); - if (ret) { - dev_err(&pdev->dev, "failed to add bus to i2c core\n"); - return ret; - } + if (ret) + return dev_err_probe(&pdev->dev, ret, "failed to add bus to i2c core\n"); platform_set_drvdata(pdev, i2c); diff --git a/drivers/i2c/busses/i2c-tegra-bpmp.c b/drivers/i2c/busses/i2c-tegra-bpmp.c index bc3f94561746..b0840fa0f53e 100644 --- a/drivers/i2c/busses/i2c-tegra-bpmp.c +++ b/drivers/i2c/busses/i2c-tegra-bpmp.c @@ -12,7 +12,7 @@ #include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 03fc10b45bd6..920d5a8cbf4c 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -22,7 +22,7 @@ #include <linux/kernel.h> #include <linux/ktime.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/pinctrl/consumer.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> diff --git a/drivers/i2c/busses/i2c-tiny-usb.c b/drivers/i2c/busses/i2c-tiny-usb.c index d1fa9ff5aeab..1bffe36c40ad 100644 --- a/drivers/i2c/busses/i2c-tiny-usb.c +++ b/drivers/i2c/busses/i2c-tiny-usb.c @@ -222,6 +222,10 @@ static int i2c_tiny_usb_probe(struct usb_interface *interface, int retval = -ENOMEM; u16 version; + if (interface->intf_assoc && + interface->intf_assoc->bFunctionClass != USB_CLASS_VENDOR_SPEC) + return -ENODEV; + dev_dbg(&interface->dev, "probing usb device\n"); /* allocate memory for our device state and initialize it */ diff --git a/drivers/i2c/busses/i2c-virtio.c b/drivers/i2c/busses/i2c-virtio.c index 4b9536f50800..c60ae531ba57 100644 --- a/drivers/i2c/busses/i2c-virtio.c +++ b/drivers/i2c/busses/i2c-virtio.c @@ -243,7 +243,6 @@ static struct virtio_device_id id_table[] = { }; MODULE_DEVICE_TABLE(virtio, id_table); -#ifdef CONFIG_PM_SLEEP static int virtio_i2c_freeze(struct virtio_device *vdev) { virtio_i2c_del_vqs(vdev); @@ -254,7 +253,6 @@ static int virtio_i2c_restore(struct virtio_device *vdev) { return virtio_i2c_setup_vqs(vdev->priv); } -#endif static const unsigned int features[] = { VIRTIO_I2C_F_ZERO_LENGTH_REQUEST, @@ -269,10 +267,8 @@ static struct virtio_driver virtio_i2c_driver = { .driver = { .name = "i2c_virtio", }, -#ifdef CONFIG_PM_SLEEP - .freeze = virtio_i2c_freeze, - .restore = virtio_i2c_restore, -#endif + .freeze = pm_sleep_ptr(virtio_i2c_freeze), + .restore = pm_sleep_ptr(virtio_i2c_restore), }; module_virtio_driver(virtio_i2c_driver); diff --git a/drivers/i2c/busses/i2c-xlp9xx.c b/drivers/i2c/busses/i2c-xlp9xx.c index f59e8c544f36..08a59a920929 100644 --- a/drivers/i2c/busses/i2c-xlp9xx.c +++ b/drivers/i2c/busses/i2c-xlp9xx.c @@ -529,10 +529,8 @@ static int xlp9xx_i2c_probe(struct platform_device *pdev) err = devm_request_irq(&pdev->dev, priv->irq, xlp9xx_i2c_isr, 0, pdev->name, priv); - if (err) { - dev_err(&pdev->dev, "IRQ request failed!\n"); - return err; - } + if (err) + return dev_err_probe(&pdev->dev, err, "IRQ request failed!\n"); init_completion(&priv->msg_complete); priv->adapter.dev.parent = &pdev->dev; diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig index ea838dbae32e..db1b9057612a 100644 --- a/drivers/i2c/muxes/Kconfig +++ b/drivers/i2c/muxes/Kconfig @@ -65,11 +65,11 @@ config I2C_MUX_PCA9541 will be called i2c-mux-pca9541. config I2C_MUX_PCA954x - tristate "NXP PCA954x and PCA984x I2C Mux/switches" + tristate "NXP PCA954x/PCA984x and Maxim MAX735x/MAX736x I2C Mux/switches" depends on GPIOLIB || COMPILE_TEST help - If you say yes here you get support for the NXP PCA954x - and PCA984x I2C mux/switch devices. + If you say yes here you get support for NXP PCA954x/PCA984x + and Maxim MAX735x/MAX736x I2C mux/switch devices. This driver can also be built as a module. If so, the module will be called i2c-mux-pca954x. diff --git a/drivers/i2c/muxes/i2c-mux-gpmux.c b/drivers/i2c/muxes/i2c-mux-gpmux.c index 0405af0e1510..baccf4bfaf02 100644 --- a/drivers/i2c/muxes/i2c-mux-gpmux.c +++ b/drivers/i2c/muxes/i2c-mux-gpmux.c @@ -11,7 +11,7 @@ #include <linux/i2c-mux.h> #include <linux/module.h> #include <linux/mux/consumer.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> struct mux { diff --git a/drivers/i2c/muxes/i2c-mux-ltc4306.c b/drivers/i2c/muxes/i2c-mux-ltc4306.c index 5a03031519be..23766d853e76 100644 --- a/drivers/i2c/muxes/i2c-mux-ltc4306.c +++ b/drivers/i2c/muxes/i2c-mux-ltc4306.c @@ -15,7 +15,6 @@ #include <linux/i2c.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/property.h> #include <linux/regmap.h> #include <linux/slab.h> @@ -62,7 +61,7 @@ static const struct chip_desc chips[] = { static bool ltc4306_is_volatile_reg(struct device *dev, unsigned int reg) { - return (reg == LTC_REG_CONFIG) ? true : false; + return reg == LTC_REG_CONFIG; } static const struct regmap_config ltc4306_regmap_config = { diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c index 0ccee2ae5720..2219062104fb 100644 --- a/drivers/i2c/muxes/i2c-mux-pca954x.c +++ b/drivers/i2c/muxes/i2c-mux-pca954x.c @@ -11,6 +11,12 @@ * PCA9540, PCA9542, PCA9543, PCA9544, PCA9545, PCA9546, PCA9547, * PCA9548, PCA9846, PCA9847, PCA9848 and PCA9849. * + * It's also compatible to Maxims MAX735x I2C switch chips, which are controlled + * as the NXP PCA9548 and the MAX736x chips that act like the PCA9544. + * + * This includes the: + * MAX7356, MAX7357, MAX7358, MAX7367, MAX7368 and MAX7369 + * * These chips are all controlled via the I2C bus itself, and all have a * single 8-bit register. The upstream "parent" bus fans out to two, * four, or eight downstream busses or channels; which of these @@ -42,6 +48,7 @@ #include <linux/module.h> #include <linux/pm.h> #include <linux/property.h> +#include <linux/regulator/consumer.h> #include <linux/slab.h> #include <linux/spinlock.h> #include <dt-bindings/mux/mux.h> @@ -51,6 +58,12 @@ #define PCA954X_IRQ_OFFSET 4 enum pca_type { + max_7356, + max_7357, + max_7358, + max_7367, + max_7368, + max_7369, pca_9540, pca_9542, pca_9543, @@ -88,10 +101,52 @@ struct pca954x { struct irq_domain *irq; unsigned int irq_mask; raw_spinlock_t lock; + struct regulator *supply; }; -/* Provide specs for the PCA954x types we know about */ +/* Provide specs for the MAX735x, PCA954x and PCA984x types we know about */ static const struct chip_desc chips[] = { + [max_7356] = { + .nchans = 8, + .muxtype = pca954x_isswi, + .id = { .manufacturer_id = I2C_DEVICE_ID_NONE }, + }, + [max_7357] = { + .nchans = 8, + .muxtype = pca954x_isswi, + .id = { .manufacturer_id = I2C_DEVICE_ID_NONE }, + /* + * No interrupt controller support. The interrupt + * provides information about stuck channels. + */ + }, + [max_7358] = { + .nchans = 8, + .muxtype = pca954x_isswi, + .id = { .manufacturer_id = I2C_DEVICE_ID_NONE }, + /* + * No interrupt controller support. The interrupt + * provides information about stuck channels. + */ + }, + [max_7367] = { + .nchans = 4, + .muxtype = pca954x_isswi, + .has_irq = 1, + .id = { .manufacturer_id = I2C_DEVICE_ID_NONE }, + }, + [max_7368] = { + .nchans = 4, + .muxtype = pca954x_isswi, + .id = { .manufacturer_id = I2C_DEVICE_ID_NONE }, + }, + [max_7369] = { + .nchans = 4, + .enable = 0x4, + .muxtype = pca954x_ismux, + .has_irq = 1, + .id = { .manufacturer_id = I2C_DEVICE_ID_NONE }, + }, [pca_9540] = { .nchans = 2, .enable = 0x4, @@ -177,6 +232,12 @@ static const struct chip_desc chips[] = { }; static const struct i2c_device_id pca954x_id[] = { + { "max7356", max_7356 }, + { "max7357", max_7357 }, + { "max7358", max_7358 }, + { "max7367", max_7367 }, + { "max7368", max_7368 }, + { "max7369", max_7369 }, { "pca9540", pca_9540 }, { "pca9542", pca_9542 }, { "pca9543", pca_9543 }, @@ -194,6 +255,12 @@ static const struct i2c_device_id pca954x_id[] = { MODULE_DEVICE_TABLE(i2c, pca954x_id); static const struct of_device_id pca954x_of_match[] = { + { .compatible = "maxim,max7356", .data = &chips[max_7356] }, + { .compatible = "maxim,max7357", .data = &chips[max_7357] }, + { .compatible = "maxim,max7358", .data = &chips[max_7358] }, + { .compatible = "maxim,max7367", .data = &chips[max_7367] }, + { .compatible = "maxim,max7368", .data = &chips[max_7368] }, + { .compatible = "maxim,max7369", .data = &chips[max_7369] }, { .compatible = "nxp,pca9540", .data = &chips[pca_9540] }, { .compatible = "nxp,pca9542", .data = &chips[pca_9542] }, { .compatible = "nxp,pca9543", .data = &chips[pca_9543] }, @@ -382,6 +449,8 @@ static void pca954x_cleanup(struct i2c_mux_core *muxc) struct pca954x *data = i2c_mux_priv(muxc); int c, irq; + regulator_disable(data->supply); + if (data->irq) { for (c = 0; c < data->chip->nchans; c++) { irq = irq_find_mapping(data->irq, c); @@ -434,10 +503,22 @@ static int pca954x_probe(struct i2c_client *client) i2c_set_clientdata(client, muxc); data->client = client; + data->supply = devm_regulator_get(dev, "vdd"); + if (IS_ERR(data->supply)) + return dev_err_probe(dev, PTR_ERR(data->supply), + "Failed to request regulator\n"); + + ret = regulator_enable(data->supply); + if (ret) + return dev_err_probe(dev, ret, + "Failed to enable vdd supply\n"); + /* Reset the mux if a reset GPIO is specified. */ gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); - if (IS_ERR(gpio)) - return PTR_ERR(gpio); + if (IS_ERR(gpio)) { + ret = PTR_ERR(gpio); + goto fail_cleanup; + } if (gpio) { udelay(1); gpiod_set_value_cansleep(gpio, 0); @@ -454,7 +535,7 @@ static int pca954x_probe(struct i2c_client *client) ret = i2c_get_device_id(client, &id); if (ret && ret != -EOPNOTSUPP) - return ret; + goto fail_cleanup; if (!ret && (id.manufacturer_id != data->chip->id.manufacturer_id || @@ -462,7 +543,8 @@ static int pca954x_probe(struct i2c_client *client) dev_warn(dev, "unexpected device id %03x-%03x-%x\n", id.manufacturer_id, id.part_id, id.die_revision); - return -ENODEV; + ret = -ENODEV; + goto fail_cleanup; } } @@ -481,7 +563,8 @@ static int pca954x_probe(struct i2c_client *client) ret = pca954x_init(client, data); if (ret < 0) { dev_warn(dev, "probe failed\n"); - return -ENODEV; + ret = -ENODEV; + goto fail_cleanup; } ret = pca954x_irq_setup(muxc); @@ -530,7 +613,6 @@ static void pca954x_remove(struct i2c_client *client) pca954x_cleanup(muxc); } -#ifdef CONFIG_PM_SLEEP static int pca954x_resume(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); @@ -544,14 +626,13 @@ static int pca954x_resume(struct device *dev) return ret; } -#endif -static SIMPLE_DEV_PM_OPS(pca954x_pm, NULL, pca954x_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(pca954x_pm, NULL, pca954x_resume); static struct i2c_driver pca954x_driver = { .driver = { .name = "pca954x", - .pm = &pca954x_pm, + .pm = pm_sleep_ptr(&pca954x_pm), .of_match_table = pca954x_of_match, }, .probe = pca954x_probe, diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 6046dfeca16f..b92208eccdea 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -521,6 +521,15 @@ config LEDS_PCA963X LED driver chip accessed via the I2C bus. Supported devices include PCA9633 and PCA9634 +config LEDS_PCA995X + tristate "LED Support for PCA995x I2C chips" + depends on LEDS_CLASS + depends on I2C + help + This option enables support for LEDs connected to PCA995x + LED driver chips accessed via the I2C bus. Supported + devices include PCA9955BTW, PCA9952TW and PCA9955TW. + config LEDS_WM831X_STATUS tristate "LED support for status LEDs on WM831x PMICs" depends on LEDS_CLASS diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index d71f1226540c..d7348e8bc019 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -72,6 +72,7 @@ obj-$(CONFIG_LEDS_OT200) += leds-ot200.o obj-$(CONFIG_LEDS_PCA9532) += leds-pca9532.o obj-$(CONFIG_LEDS_PCA955X) += leds-pca955x.o obj-$(CONFIG_LEDS_PCA963X) += leds-pca963x.o +obj-$(CONFIG_LEDS_PCA995X) += leds-pca995x.o obj-$(CONFIG_LEDS_PM8058) += leds-pm8058.o obj-$(CONFIG_LEDS_POWERNV) += leds-powernv.o obj-$(CONFIG_LEDS_PWM) += leds-pwm.o diff --git a/drivers/leds/blink/Kconfig b/drivers/leds/blink/Kconfig index 945c84286a4e..bdcb7377cd4e 100644 --- a/drivers/leds/blink/Kconfig +++ b/drivers/leds/blink/Kconfig @@ -1,10 +1,10 @@ config LEDS_BCM63138 tristate "LED Support for Broadcom BCM63138 SoC" depends on LEDS_CLASS - depends on ARCH_BCM4908 || ARCH_BCM_5301X || BCM63XX || COMPILE_TEST + depends on ARCH_BCMBCA || ARCH_BCM_5301X || BCM63XX || COMPILE_TEST depends on HAS_IOMEM depends on OF - default ARCH_BCM4908 + default ARCH_BCMBCA help This option enables support for LED controller that is part of BCM63138 SoC. The same hardware block is known to be also used diff --git a/drivers/leds/flash/Kconfig b/drivers/leds/flash/Kconfig index 4ed2efc65434..4e08dbc05709 100644 --- a/drivers/leds/flash/Kconfig +++ b/drivers/leds/flash/Kconfig @@ -89,6 +89,8 @@ config LEDS_QCOM_FLASH the total LED current will be split symmetrically on each channel and they will be enabled/disabled at the same time. + This driver can be built as a module, it will be called "leds-qcom-flash". + config LEDS_RT4505 tristate "LED support for RT4505 flashlight controller" depends on I2C && OF diff --git a/drivers/leds/flash/leds-qcom-flash.c b/drivers/leds/flash/leds-qcom-flash.c index b089ca1a1901..a73d3ea5c97a 100644 --- a/drivers/leds/flash/leds-qcom-flash.c +++ b/drivers/leds/flash/leds-qcom-flash.c @@ -309,6 +309,10 @@ static int qcom_flash_strobe_set(struct led_classdev_flash *fled_cdev, bool stat struct qcom_flash_led *led = flcdev_to_qcom_fled(fled_cdev); int rc; + rc = set_flash_strobe(led, SW_STROBE, false); + if (rc) + return rc; + rc = set_flash_current(led, led->flash_current_ma, FLASH_MODE); if (rc) return rc; @@ -745,6 +749,7 @@ static int qcom_flash_led_probe(struct platform_device *pdev) return 0; release: + fwnode_handle_put(child); while (flash_data->v4l2_flash[flash_data->leds_count] && flash_data->leds_count) v4l2_flash_release(flash_data->v4l2_flash[flash_data->leds_count--]); return rc; diff --git a/drivers/leds/led-class-multicolor.c b/drivers/leds/led-class-multicolor.c index e317408583df..ec62a4811613 100644 --- a/drivers/leds/led-class-multicolor.c +++ b/drivers/leds/led-class-multicolor.c @@ -6,6 +6,7 @@ #include <linux/device.h> #include <linux/init.h> #include <linux/led-class-multicolor.h> +#include <linux/math.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/uaccess.h> @@ -19,9 +20,10 @@ int led_mc_calc_color_components(struct led_classdev_mc *mcled_cdev, int i; for (i = 0; i < mcled_cdev->num_colors; i++) - mcled_cdev->subled_info[i].brightness = brightness * - mcled_cdev->subled_info[i].intensity / - led_cdev->max_brightness; + mcled_cdev->subled_info[i].brightness = + DIV_ROUND_CLOSEST(brightness * + mcled_cdev->subled_info[i].intensity, + led_cdev->max_brightness); return 0; } diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index 6dae56b914fe..974b84f6bd6a 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c @@ -22,7 +22,6 @@ #include <linux/of.h> #include "leds.h" -static struct class *leds_class; static DEFINE_MUTEX(leds_lookup_lock); static LIST_HEAD(leds_lookup_list); @@ -76,6 +75,19 @@ static ssize_t max_brightness_show(struct device *dev, } static DEVICE_ATTR_RO(max_brightness); +static ssize_t color_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + const char *color_text = "invalid"; + struct led_classdev *led_cdev = dev_get_drvdata(dev); + + if (led_cdev->color < LED_COLOR_ID_MAX) + color_text = led_colors[led_cdev->color]; + + return sysfs_emit(buf, "%s\n", color_text); +} +static DEVICE_ATTR_RO(color); + #ifdef CONFIG_LEDS_TRIGGERS static BIN_ATTR(trigger, 0644, led_trigger_read, led_trigger_write, 0); static struct bin_attribute *led_trigger_bin_attrs[] = { @@ -90,6 +102,7 @@ static const struct attribute_group led_trigger_group = { static struct attribute *led_class_attrs[] = { &dev_attr_brightness.attr, &dev_attr_max_brightness.attr, + &dev_attr_color.attr, NULL, }; @@ -234,6 +247,12 @@ static struct led_classdev *led_module_get(struct device *led_dev) return led_cdev; } +static const struct class leds_class = { + .name = "leds", + .dev_groups = led_groups, + .pm = &leds_class_dev_pm_ops, +}; + /** * of_led_get() - request a LED device via the LED framework * @np: device node to get the LED device from @@ -251,7 +270,7 @@ struct led_classdev *of_led_get(struct device_node *np, int index) if (!led_node) return ERR_PTR(-ENOENT); - led_dev = class_find_device_by_of_node(leds_class, led_node); + led_dev = class_find_device_by_of_node(&leds_class, led_node); of_node_put(led_node); put_device(led_dev); @@ -346,7 +365,7 @@ struct led_classdev *led_get(struct device *dev, char *con_id) if (!provider) return ERR_PTR(-ENOENT); - led_dev = class_find_device_by_name(leds_class, provider); + led_dev = class_find_device_by_name(&leds_class, provider); kfree_const(provider); return led_module_get(led_dev); @@ -402,6 +421,31 @@ void led_remove_lookup(struct led_lookup_data *led_lookup) } EXPORT_SYMBOL_GPL(led_remove_lookup); +/** + * devm_of_led_get_optional - Resource-managed request of an optional LED device + * @dev: LED consumer + * @index: index of the LED to obtain in the consumer + * + * The device node of the device is parsed to find the requested LED device. + * The LED device returned from this function is automatically released + * on driver detach. + * + * @return a pointer to a LED device, ERR_PTR(errno) on failure and NULL if the + * led was not found. + */ +struct led_classdev *__must_check devm_of_led_get_optional(struct device *dev, + int index) +{ + struct led_classdev *led; + + led = devm_of_led_get(dev, index); + if (IS_ERR(led) && PTR_ERR(led) == -ENOENT) + return NULL; + + return led; +} +EXPORT_SYMBOL_GPL(devm_of_led_get_optional); + static int led_classdev_next_name(const char *init_name, char *name, size_t len) { @@ -412,7 +456,7 @@ static int led_classdev_next_name(const char *init_name, char *name, strscpy(name, init_name, len); while ((ret < len) && - (dev = class_find_device_by_name(leds_class, name))) { + (dev = class_find_device_by_name(&leds_class, name))) { put_device(dev); ret = snprintf(name, len, "%s_%u", init_name, ++i); } @@ -457,6 +501,14 @@ int led_classdev_register_ext(struct device *parent, if (fwnode_property_present(init_data->fwnode, "retain-state-shutdown")) led_cdev->flags |= LED_RETAIN_AT_SHUTDOWN; + + fwnode_property_read_u32(init_data->fwnode, + "max-brightness", + &led_cdev->max_brightness); + + if (fwnode_property_present(init_data->fwnode, "color")) + fwnode_property_read_u32(init_data->fwnode, "color", + &led_cdev->color); } } else { proposed_name = led_cdev->name; @@ -466,10 +518,13 @@ int led_classdev_register_ext(struct device *parent, if (ret < 0) return ret; + if (led_cdev->color >= LED_COLOR_ID_MAX) + dev_warn(parent, "LED %s color identifier out of range\n", final_name); + mutex_init(&led_cdev->led_access); mutex_lock(&led_cdev->led_access); - led_cdev->dev = device_create_with_groups(leds_class, parent, 0, - led_cdev, led_cdev->groups, "%s", final_name); + led_cdev->dev = device_create_with_groups(&leds_class, parent, 0, + led_cdev, led_cdev->groups, "%s", final_name); if (IS_ERR(led_cdev->dev)) { mutex_unlock(&led_cdev->led_access); return PTR_ERR(led_cdev->dev); @@ -626,17 +681,12 @@ EXPORT_SYMBOL_GPL(devm_led_classdev_unregister); static int __init leds_init(void) { - leds_class = class_create("leds"); - if (IS_ERR(leds_class)) - return PTR_ERR(leds_class); - leds_class->pm = &leds_class_dev_pm_ops; - leds_class->dev_groups = led_groups; - return 0; + return class_register(&leds_class); } static void __exit leds_exit(void) { - class_destroy(leds_class); + class_unregister(&leds_class); } subsys_initcall(leds_init); diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c index b9b1295833c9..04f9ea675f2c 100644 --- a/drivers/leds/led-core.c +++ b/drivers/leds/led-core.c @@ -474,15 +474,15 @@ int led_compose_name(struct device *dev, struct led_init_data *init_data, struct fwnode_handle *fwnode = init_data->fwnode; const char *devicename = init_data->devicename; - /* We want to label LEDs that can produce full range of colors - * as RGB, not multicolor */ - BUG_ON(props.color == LED_COLOR_ID_MULTI); - if (!led_classdev_name) return -EINVAL; led_parse_fwnode_props(dev, fwnode, &props); + /* We want to label LEDs that can produce full range of colors + * as RGB, not multicolor */ + BUG_ON(props.color == LED_COLOR_ID_MULTI); + if (props.label) { /* * If init_data.devicename is NULL, then it indicates that diff --git a/drivers/leds/leds-an30259a.c b/drivers/leds/leds-an30259a.c index 24b1041213c2..0216afed3b6e 100644 --- a/drivers/leds/leds-an30259a.c +++ b/drivers/leds/leds-an30259a.c @@ -344,7 +344,7 @@ MODULE_DEVICE_TABLE(i2c, an30259a_id); static struct i2c_driver an30259a_driver = { .driver = { .name = "leds-an30259a", - .of_match_table = of_match_ptr(an30259a_match_table), + .of_match_table = an30259a_match_table, }, .probe = an30259a_probe, .remove = an30259a_remove, diff --git a/drivers/leds/leds-ariel.c b/drivers/leds/leds-ariel.c index 49e1bddaa15e..dd319c7e385f 100644 --- a/drivers/leds/leds-ariel.c +++ b/drivers/leds/leds-ariel.c @@ -7,8 +7,8 @@ #include <linux/module.h> #include <linux/leds.h> +#include <linux/platform_device.h> #include <linux/regmap.h> -#include <linux/of_platform.h> enum ec_index { EC_BLUE_LED = 0x01, diff --git a/drivers/leds/leds-aw200xx.c b/drivers/leds/leds-aw200xx.c index 96979b8e09b7..691a743cc9b0 100644 --- a/drivers/leds/leds-aw200xx.c +++ b/drivers/leds/leds-aw200xx.c @@ -368,7 +368,7 @@ static int aw200xx_probe_fw(struct device *dev, struct aw200xx *chip) if (!chip->display_rows || chip->display_rows > chip->cdef->display_size_rows_max) { - return dev_err_probe(dev, ret, + return dev_err_probe(dev, -EINVAL, "Invalid leds display size %u\n", chip->display_rows); } @@ -583,7 +583,7 @@ static struct i2c_driver aw200xx_driver = { .name = "aw200xx", .of_match_table = aw200xx_match_table, }, - .probe_new = aw200xx_probe, + .probe = aw200xx_probe, .remove = aw200xx_remove, .id_table = aw200xx_id, }; diff --git a/drivers/leds/leds-aw2013.c b/drivers/leds/leds-aw2013.c index 59765640b70f..91f44b23cb11 100644 --- a/drivers/leds/leds-aw2013.c +++ b/drivers/leds/leds-aw2013.c @@ -62,7 +62,7 @@ struct aw2013_led { struct aw2013 { struct mutex mutex; /* held when writing to registers */ - struct regulator *vcc_regulator; + struct regulator_bulk_data regulators[2]; struct i2c_client *client; struct aw2013_led leds[AW2013_MAX_LEDS]; struct regmap *regmap; @@ -106,10 +106,11 @@ static void aw2013_chip_disable(struct aw2013 *chip) regmap_write(chip->regmap, AW2013_GCR, 0); - ret = regulator_disable(chip->vcc_regulator); + ret = regulator_bulk_disable(ARRAY_SIZE(chip->regulators), + chip->regulators); if (ret) { dev_err(&chip->client->dev, - "Failed to disable regulator: %d\n", ret); + "Failed to disable regulators: %d\n", ret); return; } @@ -123,10 +124,11 @@ static int aw2013_chip_enable(struct aw2013 *chip) if (chip->enabled) return 0; - ret = regulator_enable(chip->vcc_regulator); + ret = regulator_bulk_enable(ARRAY_SIZE(chip->regulators), + chip->regulators); if (ret) { dev_err(&chip->client->dev, - "Failed to enable regulator: %d\n", ret); + "Failed to enable regulators: %d\n", ret); return ret; } chip->enabled = true; @@ -348,19 +350,23 @@ static int aw2013_probe(struct i2c_client *client) goto error; } - chip->vcc_regulator = devm_regulator_get(&client->dev, "vcc"); - ret = PTR_ERR_OR_ZERO(chip->vcc_regulator); - if (ret) { + chip->regulators[0].supply = "vcc"; + chip->regulators[1].supply = "vio"; + ret = devm_regulator_bulk_get(&client->dev, + ARRAY_SIZE(chip->regulators), + chip->regulators); + if (ret < 0) { if (ret != -EPROBE_DEFER) dev_err(&client->dev, - "Failed to request regulator: %d\n", ret); + "Failed to request regulators: %d\n", ret); goto error; } - ret = regulator_enable(chip->vcc_regulator); + ret = regulator_bulk_enable(ARRAY_SIZE(chip->regulators), + chip->regulators); if (ret) { dev_err(&client->dev, - "Failed to enable regulator: %d\n", ret); + "Failed to enable regulators: %d\n", ret); goto error; } @@ -382,10 +388,11 @@ static int aw2013_probe(struct i2c_client *client) if (ret < 0) goto error_reg; - ret = regulator_disable(chip->vcc_regulator); + ret = regulator_bulk_disable(ARRAY_SIZE(chip->regulators), + chip->regulators); if (ret) { dev_err(&client->dev, - "Failed to disable regulator: %d\n", ret); + "Failed to disable regulators: %d\n", ret); goto error; } @@ -394,7 +401,8 @@ static int aw2013_probe(struct i2c_client *client) return 0; error_reg: - regulator_disable(chip->vcc_regulator); + regulator_bulk_disable(ARRAY_SIZE(chip->regulators), + chip->regulators); error: mutex_destroy(&chip->mutex); @@ -420,7 +428,7 @@ MODULE_DEVICE_TABLE(of, aw2013_match_table); static struct i2c_driver aw2013_driver = { .driver = { .name = "leds-aw2013", - .of_match_table = of_match_ptr(aw2013_match_table), + .of_match_table = aw2013_match_table, }, .probe = aw2013_probe, .remove = aw2013_remove, diff --git a/drivers/leds/leds-cpcap.c b/drivers/leds/leds-cpcap.c index 7d41ce8c9bb1..87354f17644b 100644 --- a/drivers/leds/leds-cpcap.c +++ b/drivers/leds/leds-cpcap.c @@ -7,7 +7,7 @@ #include <linux/mfd/motorola-cpcap.h> #include <linux/module.h> #include <linux/mutex.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/regulator/consumer.h> diff --git a/drivers/leds/leds-cr0014114.c b/drivers/leds/leds-cr0014114.c index c87686bd7c18..b33bca397ea6 100644 --- a/drivers/leds/leds-cr0014114.c +++ b/drivers/leds/leds-cr0014114.c @@ -4,8 +4,8 @@ #include <linux/delay.h> #include <linux/leds.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> -#include <linux/of_device.h> #include <linux/spi/spi.h> #include <linux/workqueue.h> diff --git a/drivers/leds/leds-ip30.c b/drivers/leds/leds-ip30.c index 1f952bad0fe8..2df24c303366 100644 --- a/drivers/leds/leds-ip30.c +++ b/drivers/leds/leds-ip30.c @@ -27,22 +27,16 @@ static void ip30led_set(struct led_classdev *led_cdev, static int ip30led_create(struct platform_device *pdev, int num) { - struct resource *res; struct ip30_led *data; - res = platform_get_resource(pdev, IORESOURCE_MEM, num); - if (!res) - return -EBUSY; - data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; - data->reg = devm_ioremap_resource(&pdev->dev, res); + data->reg = devm_platform_ioremap_resource(pdev, num); if (IS_ERR(data->reg)) return PTR_ERR(data->reg); - switch (num) { case IP30_LED_SYSTEM: data->cdev.name = "white:power"; diff --git a/drivers/leds/leds-is31fl32xx.c b/drivers/leds/leds-is31fl32xx.c index 72cb56d305c4..b0a0be77bb33 100644 --- a/drivers/leds/leds-is31fl32xx.c +++ b/drivers/leds/leds-is31fl32xx.c @@ -15,7 +15,6 @@ #include <linux/leds.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> /* Used to indicate a device has no such register */ #define IS31FL32XX_REG_NONE 0xFF diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c index 030c040fdf6d..2ef19ad23b1d 100644 --- a/drivers/leds/leds-lp5521.c +++ b/drivers/leds/leds-lp5521.c @@ -594,18 +594,17 @@ static const struct i2c_device_id lp5521_id[] = { }; MODULE_DEVICE_TABLE(i2c, lp5521_id); -#ifdef CONFIG_OF static const struct of_device_id of_lp5521_leds_match[] = { { .compatible = "national,lp5521", }, {}, }; MODULE_DEVICE_TABLE(of, of_lp5521_leds_match); -#endif + static struct i2c_driver lp5521_driver = { .driver = { .name = "lp5521", - .of_match_table = of_match_ptr(of_lp5521_leds_match), + .of_match_table = of_lp5521_leds_match, }, .probe = lp5521_probe, .remove = lp5521_remove, diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c index daa6a165fba6..38de853f9939 100644 --- a/drivers/leds/leds-lp5523.c +++ b/drivers/leds/leds-lp5523.c @@ -972,7 +972,6 @@ static const struct i2c_device_id lp5523_id[] = { MODULE_DEVICE_TABLE(i2c, lp5523_id); -#ifdef CONFIG_OF static const struct of_device_id of_lp5523_leds_match[] = { { .compatible = "national,lp5523", }, { .compatible = "ti,lp55231", }, @@ -980,12 +979,11 @@ static const struct of_device_id of_lp5523_leds_match[] = { }; MODULE_DEVICE_TABLE(of, of_lp5523_leds_match); -#endif static struct i2c_driver lp5523_driver = { .driver = { .name = "lp5523x", - .of_match_table = of_match_ptr(of_lp5523_leds_match), + .of_match_table = of_lp5523_leds_match, }, .probe = lp5523_probe, .remove = lp5523_remove, diff --git a/drivers/leds/leds-lp5562.c b/drivers/leds/leds-lp5562.c index 4565cc12cea8..39db9aeb67c5 100644 --- a/drivers/leds/leds-lp5562.c +++ b/drivers/leds/leds-lp5562.c @@ -589,19 +589,17 @@ static const struct i2c_device_id lp5562_id[] = { }; MODULE_DEVICE_TABLE(i2c, lp5562_id); -#ifdef CONFIG_OF static const struct of_device_id of_lp5562_leds_match[] = { { .compatible = "ti,lp5562", }, {}, }; MODULE_DEVICE_TABLE(of, of_lp5562_leds_match); -#endif static struct i2c_driver lp5562_driver = { .driver = { .name = "lp5562", - .of_match_table = of_match_ptr(of_lp5562_leds_match), + .of_match_table = of_lp5562_leds_match, }, .probe = lp5562_probe, .remove = lp5562_remove, diff --git a/drivers/leds/leds-lp8501.c b/drivers/leds/leds-lp8501.c index f11886aa8965..ac50aa88939a 100644 --- a/drivers/leds/leds-lp8501.c +++ b/drivers/leds/leds-lp8501.c @@ -380,19 +380,17 @@ static const struct i2c_device_id lp8501_id[] = { }; MODULE_DEVICE_TABLE(i2c, lp8501_id); -#ifdef CONFIG_OF static const struct of_device_id of_lp8501_leds_match[] = { { .compatible = "ti,lp8501", }, {}, }; MODULE_DEVICE_TABLE(of, of_lp8501_leds_match); -#endif static struct i2c_driver lp8501_driver = { .driver = { .name = "lp8501", - .of_match_table = of_match_ptr(of_lp8501_leds_match), + .of_match_table = of_lp8501_leds_match, }, .probe = lp8501_probe, .remove = lp8501_remove, diff --git a/drivers/leds/leds-mlxreg.c b/drivers/leds/leds-mlxreg.c index b7855c93bd72..39210653acf7 100644 --- a/drivers/leds/leds-mlxreg.c +++ b/drivers/leds/leds-mlxreg.c @@ -8,7 +8,6 @@ #include <linux/io.h> #include <linux/leds.h> #include <linux/module.h> -#include <linux/of_device.h> #include <linux/platform_data/mlxreg.h> #include <linux/platform_device.h> #include <linux/regmap.h> diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c index 1677d66d8b0e..f3010c472bbd 100644 --- a/drivers/leds/leds-ns2.c +++ b/drivers/leds/leds-ns2.c @@ -247,7 +247,7 @@ static int ns2_led_probe(struct platform_device *pdev) if (!count) return -ENODEV; - leds = devm_kzalloc(dev, array_size(sizeof(*leds), count), GFP_KERNEL); + leds = devm_kcalloc(dev, count, sizeof(*leds), GFP_KERNEL); if (!leds) return -ENOMEM; diff --git a/drivers/leds/leds-pca9532.c b/drivers/leds/leds-pca9532.c index 8b5c62083e50..bf8bb8fc007c 100644 --- a/drivers/leds/leds-pca9532.c +++ b/drivers/leds/leds-pca9532.c @@ -18,7 +18,6 @@ #include <linux/leds-pca9532.h> #include <linux/gpio/driver.h> #include <linux/of.h> -#include <linux/of_device.h> /* m = num_leds*/ #define PCA9532_REG_INPUT(i) ((i) >> 3) diff --git a/drivers/leds/leds-pca995x.c b/drivers/leds/leds-pca995x.c new file mode 100644 index 000000000000..78215dff1499 --- /dev/null +++ b/drivers/leds/leds-pca995x.c @@ -0,0 +1,204 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * LED driver for PCA995x I2C LED drivers + * + * Copyright 2011 bct electronic GmbH + * Copyright 2013 Qtechnology/AS + * Copyright 2022 NXP + * Copyright 2023 Marek Vasut + */ + +#include <linux/i2c.h> +#include <linux/leds.h> +#include <linux/module.h> +#include <linux/mod_devicetable.h> +#include <linux/property.h> +#include <linux/regmap.h> + +/* Register definition */ +#define PCA995X_MODE1 0x00 +#define PCA995X_MODE2 0x01 +#define PCA995X_LEDOUT0 0x02 +#define PCA9955B_PWM0 0x08 +#define PCA9952_PWM0 0x0A +#define PCA9952_IREFALL 0x43 +#define PCA9955B_IREFALL 0x45 + +/* Auto-increment disabled. Normal mode */ +#define PCA995X_MODE1_CFG 0x00 + +/* LED select registers determine the source that drives LED outputs */ +#define PCA995X_LED_OFF 0x0 +#define PCA995X_LED_ON 0x1 +#define PCA995X_LED_PWM_MODE 0x2 +#define PCA995X_LDRX_MASK 0x3 +#define PCA995X_LDRX_BITS 2 + +#define PCA995X_MAX_OUTPUTS 16 +#define PCA995X_OUTPUTS_PER_REG 4 + +#define PCA995X_IREFALL_FULL_CFG 0xFF +#define PCA995X_IREFALL_HALF_CFG (PCA995X_IREFALL_FULL_CFG / 2) + +#define PCA995X_TYPE_NON_B 0 +#define PCA995X_TYPE_B 1 + +#define ldev_to_led(c) container_of(c, struct pca995x_led, ldev) + +struct pca995x_led { + unsigned int led_no; + struct led_classdev ldev; + struct pca995x_chip *chip; +}; + +struct pca995x_chip { + struct regmap *regmap; + struct pca995x_led leds[PCA995X_MAX_OUTPUTS]; + int btype; +}; + +static int pca995x_brightness_set(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct pca995x_led *led = ldev_to_led(led_cdev); + struct pca995x_chip *chip = led->chip; + u8 ledout_addr, pwmout_addr; + int shift, ret; + + pwmout_addr = (chip->btype ? PCA9955B_PWM0 : PCA9952_PWM0) + led->led_no; + ledout_addr = PCA995X_LEDOUT0 + (led->led_no / PCA995X_OUTPUTS_PER_REG); + shift = PCA995X_LDRX_BITS * (led->led_no % PCA995X_OUTPUTS_PER_REG); + + switch (brightness) { + case LED_FULL: + return regmap_update_bits(chip->regmap, ledout_addr, + PCA995X_LDRX_MASK << shift, + PCA995X_LED_ON << shift); + case LED_OFF: + return regmap_update_bits(chip->regmap, ledout_addr, + PCA995X_LDRX_MASK << shift, 0); + default: + /* Adjust brightness as per user input by changing individual PWM */ + ret = regmap_write(chip->regmap, pwmout_addr, brightness); + if (ret) + return ret; + + /* + * Change LDRx configuration to individual brightness via PWM. + * LED will stop blinking if it's doing so. + */ + return regmap_update_bits(chip->regmap, ledout_addr, + PCA995X_LDRX_MASK << shift, + PCA995X_LED_PWM_MODE << shift); + } +} + +static const struct regmap_config pca995x_regmap = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 0x49, +}; + +static int pca995x_probe(struct i2c_client *client) +{ + struct fwnode_handle *led_fwnodes[PCA995X_MAX_OUTPUTS] = { 0 }; + struct fwnode_handle *np, *child; + struct device *dev = &client->dev; + struct pca995x_chip *chip; + struct pca995x_led *led; + int i, btype, reg, ret; + + btype = (unsigned long)device_get_match_data(&client->dev); + + np = dev_fwnode(dev); + if (!np) + return -ENODEV; + + chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + chip->btype = btype; + chip->regmap = devm_regmap_init_i2c(client, &pca995x_regmap); + if (IS_ERR(chip->regmap)) + return PTR_ERR(chip->regmap); + + i2c_set_clientdata(client, chip); + + fwnode_for_each_available_child_node(np, child) { + ret = fwnode_property_read_u32(child, "reg", ®); + if (ret) { + fwnode_handle_put(child); + return ret; + } + + if (reg < 0 || reg >= PCA995X_MAX_OUTPUTS || led_fwnodes[reg]) { + fwnode_handle_put(child); + return -EINVAL; + } + + led = &chip->leds[reg]; + led_fwnodes[reg] = child; + led->chip = chip; + led->led_no = reg; + led->ldev.brightness_set_blocking = pca995x_brightness_set; + led->ldev.max_brightness = 255; + } + + for (i = 0; i < PCA995X_MAX_OUTPUTS; i++) { + struct led_init_data init_data = {}; + + if (!led_fwnodes[i]) + continue; + + init_data.fwnode = led_fwnodes[i]; + + ret = devm_led_classdev_register_ext(dev, + &chip->leds[i].ldev, + &init_data); + if (ret < 0) { + fwnode_handle_put(child); + return dev_err_probe(dev, ret, + "Could not register LED %s\n", + chip->leds[i].ldev.name); + } + } + + /* Disable LED all-call address and set normal mode */ + ret = regmap_write(chip->regmap, PCA995X_MODE1, PCA995X_MODE1_CFG); + if (ret) + return ret; + + /* IREF Output current value for all LEDn outputs */ + return regmap_write(chip->regmap, + btype ? PCA9955B_IREFALL : PCA9952_IREFALL, + PCA995X_IREFALL_HALF_CFG); +} + +static const struct i2c_device_id pca995x_id[] = { + { "pca9952", .driver_data = (kernel_ulong_t)PCA995X_TYPE_NON_B }, + { "pca9955b", .driver_data = (kernel_ulong_t)PCA995X_TYPE_B }, + {} +}; +MODULE_DEVICE_TABLE(i2c, pca995x_id); + +static const struct of_device_id pca995x_of_match[] = { + { .compatible = "nxp,pca9952", .data = (void *)PCA995X_TYPE_NON_B }, + { .compatible = "nxp,pca9955b", .data = (void *)PCA995X_TYPE_B }, + {}, +}; +MODULE_DEVICE_TABLE(of, pca995x_of_match); + +static struct i2c_driver pca995x_driver = { + .driver = { + .name = "leds-pca995x", + .of_match_table = pca995x_of_match, + }, + .probe = pca995x_probe, + .id_table = pca995x_id, +}; +module_i2c_driver(pca995x_driver); + +MODULE_AUTHOR("Isai Gaspar <isaiezequiel.gaspar@nxp.com>"); +MODULE_DESCRIPTION("PCA995x LED driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/leds/leds-pm8058.c b/drivers/leds/leds-pm8058.c index b9233f14b646..3f49a5181892 100644 --- a/drivers/leds/leds-pm8058.c +++ b/drivers/leds/leds-pm8058.c @@ -4,7 +4,6 @@ #include <linux/leds.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/pm.h> #include <linux/regmap.h> diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c index 29194cc382af..419b710984ab 100644 --- a/drivers/leds/leds-pwm.c +++ b/drivers/leds/leds-pwm.c @@ -12,7 +12,7 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/platform_device.h> -#include <linux/of_platform.h> +#include <linux/of.h> #include <linux/leds.h> #include <linux/err.h> #include <linux/pwm.h> @@ -146,7 +146,7 @@ static int led_pwm_create_fwnode(struct device *dev, struct led_pwm_priv *priv) led.name = to_of_node(fwnode)->name; if (!led.name) { - ret = EINVAL; + ret = -EINVAL; goto err_child_out; } diff --git a/drivers/leds/leds-spi-byte.c b/drivers/leds/leds-spi-byte.c index 2c7ffc3c78e6..9d91f21842f2 100644 --- a/drivers/leds/leds-spi-byte.c +++ b/drivers/leds/leds-spi-byte.c @@ -30,7 +30,7 @@ #include <linux/leds.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/spi/spi.h> #include <linux/mutex.h> #include <uapi/linux/uleds.h> diff --git a/drivers/leds/leds-syscon.c b/drivers/leds/leds-syscon.c index e38abb5e60c1..360a376fa738 100644 --- a/drivers/leds/leds-syscon.c +++ b/drivers/leds/leds-syscon.c @@ -7,8 +7,7 @@ */ #include <linux/io.h> #include <linux/init.h> -#include <linux/of_device.h> -#include <linux/of_address.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/stat.h> #include <linux/slab.h> diff --git a/drivers/leds/leds-ti-lmu-common.c b/drivers/leds/leds-ti-lmu-common.c index d7f10ad721ba..b2491666b5dc 100644 --- a/drivers/leds/leds-ti-lmu-common.c +++ b/drivers/leds/leds-ti-lmu-common.c @@ -7,7 +7,7 @@ #include <linux/bitops.h> #include <linux/err.h> -#include <linux/of_device.h> +#include <linux/property.h> #include <linux/leds-ti-lmu-common.h> diff --git a/drivers/leds/leds-tlc591xx.c b/drivers/leds/leds-tlc591xx.c index dfc6fb2b3e52..945e831ef4ac 100644 --- a/drivers/leds/leds-tlc591xx.c +++ b/drivers/leds/leds-tlc591xx.c @@ -8,7 +8,6 @@ #include <linux/leds.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/regmap.h> #include <linux/slab.h> diff --git a/drivers/leds/leds-turris-omnia.c b/drivers/leds/leds-turris-omnia.c index 64b2d7b6d3f3..b8a95a917cfa 100644 --- a/drivers/leds/leds-turris-omnia.c +++ b/drivers/leds/leds-turris-omnia.c @@ -156,24 +156,20 @@ static ssize_t brightness_show(struct device *dev, struct device_attribute *a, char *buf) { struct i2c_client *client = to_i2c_client(dev); - struct omnia_leds *leds = i2c_get_clientdata(client); int ret; - mutex_lock(&leds->lock); ret = i2c_smbus_read_byte_data(client, CMD_LED_GET_BRIGHTNESS); - mutex_unlock(&leds->lock); if (ret < 0) return ret; - return sprintf(buf, "%d\n", ret); + return sysfs_emit(buf, "%d\n", ret); } static ssize_t brightness_store(struct device *dev, struct device_attribute *a, const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); - struct omnia_leds *leds = i2c_get_clientdata(client); unsigned long brightness; int ret; @@ -183,15 +179,10 @@ static ssize_t brightness_store(struct device *dev, struct device_attribute *a, if (brightness > 100) return -EINVAL; - mutex_lock(&leds->lock); ret = i2c_smbus_write_byte_data(client, CMD_LED_SET_BRIGHTNESS, (u8)brightness); - mutex_unlock(&leds->lock); - - if (ret < 0) - return ret; - return count; + return ret < 0 ? ret : count; } static DEVICE_ATTR_RW(brightness); diff --git a/drivers/leds/rgb/Kconfig b/drivers/leds/rgb/Kconfig index 360c8679c6e2..183bccc06cf3 100644 --- a/drivers/leds/rgb/Kconfig +++ b/drivers/leds/rgb/Kconfig @@ -2,6 +2,18 @@ if LEDS_CLASS_MULTICOLOR +config LEDS_GROUP_MULTICOLOR + tristate "LEDs group multi-color support" + depends on OF || COMPILE_TEST + help + This option enables support for monochrome LEDs that are grouped + into multicolor LEDs which is useful in the case where LEDs of + different colors are physically grouped in a single multi-color LED + and driven by a controller that doesn't have multi-color support. + + To compile this driver as a module, choose M here: the module + will be called leds-group-multicolor. + config LEDS_PWM_MULTICOLOR tristate "PWM driven multi-color LED Support" depends on PWM diff --git a/drivers/leds/rgb/Makefile b/drivers/leds/rgb/Makefile index 8c01daf63f61..c11cc56384e7 100644 --- a/drivers/leds/rgb/Makefile +++ b/drivers/leds/rgb/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_LEDS_GROUP_MULTICOLOR) += leds-group-multicolor.o obj-$(CONFIG_LEDS_PWM_MULTICOLOR) += leds-pwm-multicolor.o obj-$(CONFIG_LEDS_QCOM_LPG) += leds-qcom-lpg.o obj-$(CONFIG_LEDS_MT6370_RGB) += leds-mt6370-rgb.o diff --git a/drivers/leds/rgb/leds-group-multicolor.c b/drivers/leds/rgb/leds-group-multicolor.c new file mode 100644 index 000000000000..39f58be32af5 --- /dev/null +++ b/drivers/leds/rgb/leds-group-multicolor.c @@ -0,0 +1,169 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Multi-color LED built with monochromatic LED devices + * + * This driver groups several monochromatic LED devices in a single multicolor LED device. + * + * Compared to handling this grouping in user-space, the benefits are: + * - The state of the monochromatic LED relative to each other is always consistent. + * - The sysfs interface of the LEDs can be used for the group as a whole. + * + * Copyright 2023 Jean-Jacques Hiblot <jjhiblot@traphandler.com> + */ + +#include <linux/err.h> +#include <linux/leds.h> +#include <linux/led-class-multicolor.h> +#include <linux/math.h> +#include <linux/module.h> +#include <linux/mod_devicetable.h> +#include <linux/platform_device.h> +#include <linux/property.h> + +struct leds_multicolor { + struct led_classdev_mc mc_cdev; + struct led_classdev **monochromatics; +}; + +static int leds_gmc_set(struct led_classdev *cdev, enum led_brightness brightness) +{ + struct led_classdev_mc *mc_cdev = lcdev_to_mccdev(cdev); + struct leds_multicolor *priv = container_of(mc_cdev, struct leds_multicolor, mc_cdev); + const unsigned int group_max_brightness = mc_cdev->led_cdev.max_brightness; + int i; + + for (i = 0; i < mc_cdev->num_colors; i++) { + struct led_classdev *mono = priv->monochromatics[i]; + const unsigned int mono_max_brightness = mono->max_brightness; + unsigned int intensity = mc_cdev->subled_info[i].intensity; + int mono_brightness; + + /* + * Scale the brightness according to relative intensity of the + * color AND the max brightness of the monochromatic LED. + */ + mono_brightness = DIV_ROUND_CLOSEST(brightness * intensity * mono_max_brightness, + group_max_brightness * group_max_brightness); + + led_set_brightness(mono, mono_brightness); + } + + return 0; +} + +static void restore_sysfs_write_access(void *data) +{ + struct led_classdev *led_cdev = data; + + /* Restore the write acccess to the LED */ + mutex_lock(&led_cdev->led_access); + led_sysfs_enable(led_cdev); + mutex_unlock(&led_cdev->led_access); +} + +static int leds_gmc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct led_init_data init_data = {}; + struct led_classdev *cdev; + struct mc_subled *subled; + struct leds_multicolor *priv; + unsigned int max_brightness = 0; + int i, ret, count = 0; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + for (;;) { + struct led_classdev *led_cdev; + + led_cdev = devm_of_led_get_optional(dev, count); + if (IS_ERR(led_cdev)) + return dev_err_probe(dev, PTR_ERR(led_cdev), "Unable to get LED #%d", + count); + if (!led_cdev) + break; + + priv->monochromatics = devm_krealloc_array(dev, priv->monochromatics, + count + 1, sizeof(*priv->monochromatics), + GFP_KERNEL); + if (!priv->monochromatics) + return -ENOMEM; + + priv->monochromatics[count] = led_cdev; + + max_brightness = max(max_brightness, led_cdev->max_brightness); + + count++; + } + + subled = devm_kcalloc(dev, count, sizeof(*subled), GFP_KERNEL); + if (!subled) + return -ENOMEM; + priv->mc_cdev.subled_info = subled; + + for (i = 0; i < count; i++) { + struct led_classdev *led_cdev = priv->monochromatics[i]; + + subled[i].color_index = led_cdev->color; + + /* Configure the LED intensity to its maximum */ + subled[i].intensity = max_brightness; + } + + /* Initialise the multicolor's LED class device */ + cdev = &priv->mc_cdev.led_cdev; + cdev->flags = LED_CORE_SUSPENDRESUME; + cdev->brightness_set_blocking = leds_gmc_set; + cdev->max_brightness = max_brightness; + cdev->color = LED_COLOR_ID_MULTI; + priv->mc_cdev.num_colors = count; + + init_data.fwnode = dev_fwnode(dev); + ret = devm_led_classdev_multicolor_register_ext(dev, &priv->mc_cdev, &init_data); + if (ret) + return dev_err_probe(dev, ret, "failed to register multicolor LED for %s.\n", + cdev->name); + + ret = leds_gmc_set(cdev, cdev->brightness); + if (ret) + return dev_err_probe(dev, ret, "failed to set LED value for %s.", cdev->name); + + for (i = 0; i < count; i++) { + struct led_classdev *led_cdev = priv->monochromatics[i]; + + /* + * Make the individual LED sysfs interface read-only to prevent the user + * to change the brightness of the individual LEDs of the group. + */ + mutex_lock(&led_cdev->led_access); + led_sysfs_disable(led_cdev); + mutex_unlock(&led_cdev->led_access); + + /* Restore the write access to the LED sysfs when the group is destroyed */ + devm_add_action_or_reset(dev, restore_sysfs_write_access, led_cdev); + } + + return 0; +} + +static const struct of_device_id of_leds_group_multicolor_match[] = { + { .compatible = "leds-group-multicolor" }, + {} +}; +MODULE_DEVICE_TABLE(of, of_leds_group_multicolor_match); + +static struct platform_driver leds_group_multicolor_driver = { + .probe = leds_gmc_probe, + .driver = { + .name = "leds_group_multicolor", + .of_match_table = of_leds_group_multicolor_match, + } +}; +module_platform_driver(leds_group_multicolor_driver); + +MODULE_AUTHOR("Jean-Jacques Hiblot <jjhiblot@traphandler.com>"); +MODULE_DESCRIPTION("LEDs group multicolor driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:leds-group-multicolor"); diff --git a/drivers/leds/rgb/leds-qcom-lpg.c b/drivers/leds/rgb/leds-qcom-lpg.c index 59581b3e25ca..df469aaa7e6e 100644 --- a/drivers/leds/rgb/leds-qcom-lpg.c +++ b/drivers/leds/rgb/leds-qcom-lpg.c @@ -9,7 +9,6 @@ #include <linux/led-class-multicolor.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/pwm.h> #include <linux/regmap.h> @@ -1093,7 +1092,6 @@ static int lpg_add_pwm(struct lpg *lpg) { int ret; - lpg->pwm.base = -1; lpg->pwm.dev = lpg->dev; lpg->pwm.npwm = lpg->num_channels; lpg->pwm.ops = &lpg_pwm_ops; diff --git a/drivers/leds/simple/Kconfig b/drivers/leds/simple/Kconfig index 609e438af9f6..e616cc6d6051 100644 --- a/drivers/leds/simple/Kconfig +++ b/drivers/leds/simple/Kconfig @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only config LEDS_SIEMENS_SIMATIC_IPC tristate "LED driver for Siemens Simatic IPCs" + depends on LEDS_CLASS depends on SIEMENS_SIMATIC_IPC default y help @@ -35,3 +36,16 @@ config LEDS_SIEMENS_SIMATIC_IPC_F7188X To compile this driver as a module, choose M here: the module will be called simatic-ipc-leds-gpio-f7188x. + +config LEDS_SIEMENS_SIMATIC_IPC_ELKHARTLAKE + tristate "LED driver for Siemens Simatic IPCs based on Intel Elkhart Lake GPIO" + depends on LEDS_GPIO + depends on PINCTRL_ELKHARTLAKE + depends on SIEMENS_SIMATIC_IPC + default LEDS_SIEMENS_SIMATIC_IPC + help + This option enables support for the LEDs of several Industrial PCs + from Siemens based on Elkhart Lake GPIO i.e. BX-21A. + + To compile this driver as a module, choose M here: the module + will be called simatic-ipc-leds-gpio-elkhartlake. diff --git a/drivers/leds/simple/Makefile b/drivers/leds/simple/Makefile index e3e840cea275..783578f11bb0 100644 --- a/drivers/leds/simple/Makefile +++ b/drivers/leds/simple/Makefile @@ -2,3 +2,4 @@ obj-$(CONFIG_LEDS_SIEMENS_SIMATIC_IPC) += simatic-ipc-leds.o obj-$(CONFIG_LEDS_SIEMENS_SIMATIC_IPC_APOLLOLAKE) += simatic-ipc-leds-gpio-core.o simatic-ipc-leds-gpio-apollolake.o obj-$(CONFIG_LEDS_SIEMENS_SIMATIC_IPC_F7188X) += simatic-ipc-leds-gpio-core.o simatic-ipc-leds-gpio-f7188x.o +obj-$(CONFIG_LEDS_SIEMENS_SIMATIC_IPC_ELKHARTLAKE) += simatic-ipc-leds-gpio-core.o simatic-ipc-leds-gpio-elkhartlake.o diff --git a/drivers/leds/simple/simatic-ipc-leds-gpio-core.c b/drivers/leds/simple/simatic-ipc-leds-gpio-core.c index 2a21b663df87..c552ea73ed9d 100644 --- a/drivers/leds/simple/simatic-ipc-leds-gpio-core.c +++ b/drivers/leds/simple/simatic-ipc-leds-gpio-core.c @@ -57,6 +57,7 @@ int simatic_ipc_leds_gpio_probe(struct platform_device *pdev, switch (plat->devmode) { case SIMATIC_IPC_DEVICE_127E: case SIMATIC_IPC_DEVICE_227G: + case SIMATIC_IPC_DEVICE_BX_21A: break; default: return -ENODEV; @@ -72,6 +73,9 @@ int simatic_ipc_leds_gpio_probe(struct platform_device *pdev, goto out; } + if (!table_extra) + return 0; + table_extra->dev_id = dev_name(dev); gpiod_add_lookup_table(table_extra); diff --git a/drivers/leds/simple/simatic-ipc-leds-gpio-elkhartlake.c b/drivers/leds/simple/simatic-ipc-leds-gpio-elkhartlake.c new file mode 100644 index 000000000000..6ba21dbb3ba0 --- /dev/null +++ b/drivers/leds/simple/simatic-ipc-leds-gpio-elkhartlake.c @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Siemens SIMATIC IPC driver for GPIO based LEDs + * + * Copyright (c) Siemens AG, 2023 + * + * Author: + * Henning Schild <henning.schild@siemens.com> + */ + +#include <linux/gpio/machine.h> +#include <linux/gpio/consumer.h> +#include <linux/leds.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/platform_data/x86/simatic-ipc-base.h> + +#include "simatic-ipc-leds-gpio.h" + +static struct gpiod_lookup_table simatic_ipc_led_gpio_table = { + .dev_id = "leds-gpio", + .table = { + GPIO_LOOKUP_IDX("INTC1020:04", 72, NULL, 0, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("INTC1020:04", 77, NULL, 1, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("INTC1020:04", 78, NULL, 2, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("INTC1020:04", 58, NULL, 3, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("INTC1020:04", 60, NULL, 4, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("INTC1020:04", 62, NULL, 5, GPIO_ACTIVE_HIGH), + {} /* Terminating entry */ + }, +}; + +static int simatic_ipc_leds_gpio_elkhartlake_probe(struct platform_device *pdev) +{ + return simatic_ipc_leds_gpio_probe(pdev, &simatic_ipc_led_gpio_table, + NULL); +} + +static int simatic_ipc_leds_gpio_elkhartlake_remove(struct platform_device *pdev) +{ + return simatic_ipc_leds_gpio_remove(pdev, &simatic_ipc_led_gpio_table, + NULL); +} + +static struct platform_driver simatic_ipc_led_gpio_elkhartlake_driver = { + .probe = simatic_ipc_leds_gpio_elkhartlake_probe, + .remove = simatic_ipc_leds_gpio_elkhartlake_remove, + .driver = { + .name = KBUILD_MODNAME, + }, +}; +module_platform_driver(simatic_ipc_led_gpio_elkhartlake_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" KBUILD_MODNAME); +MODULE_SOFTDEP("pre: simatic-ipc-leds-gpio-core platform:elkhartlake-pinctrl"); +MODULE_AUTHOR("Henning Schild <henning.schild@siemens.com>"); diff --git a/drivers/leds/simple/simatic-ipc-leds-gpio.h b/drivers/leds/simple/simatic-ipc-leds-gpio.h index bf258c32f83d..3d4877aa4e0c 100644 --- a/drivers/leds/simple/simatic-ipc-leds-gpio.h +++ b/drivers/leds/simple/simatic-ipc-leds-gpio.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * Siemens SIMATIC IPC driver for GPIO based LEDs * diff --git a/drivers/leds/trigger/ledtrig-netdev.c b/drivers/leds/trigger/ledtrig-netdev.c index cc3261543a5e..58f3352539e8 100644 --- a/drivers/leds/trigger/ledtrig-netdev.c +++ b/drivers/leds/trigger/ledtrig-netdev.c @@ -609,18 +609,7 @@ static struct led_trigger netdev_led_trigger = { .groups = netdev_trig_groups, }; -static int __init netdev_trig_init(void) -{ - return led_trigger_register(&netdev_led_trigger); -} - -static void __exit netdev_trig_exit(void) -{ - led_trigger_unregister(&netdev_led_trigger); -} - -module_init(netdev_trig_init); -module_exit(netdev_trig_exit); +module_led_trigger(netdev_led_trigger); MODULE_AUTHOR("Ben Whitten <ben.whitten@gmail.com>"); MODULE_AUTHOR("Oliver Jowett <oliver@opencloud.com>"); diff --git a/drivers/leds/trigger/ledtrig-tty.c b/drivers/leds/trigger/ledtrig-tty.c index f62db7e520b5..8ae0d2d284af 100644 --- a/drivers/leds/trigger/ledtrig-tty.c +++ b/drivers/leds/trigger/ledtrig-tty.c @@ -7,6 +7,8 @@ #include <linux/tty.h> #include <uapi/linux/serial.h> +#define LEDTRIG_TTY_INTERVAL 50 + struct ledtrig_tty_data { struct led_classdev *led_cdev; struct delayed_work dwork; @@ -122,17 +124,19 @@ static void ledtrig_tty_work(struct work_struct *work) if (icount.rx != trigger_data->rx || icount.tx != trigger_data->tx) { - led_set_brightness_sync(trigger_data->led_cdev, LED_ON); + unsigned long interval = LEDTRIG_TTY_INTERVAL; + + led_blink_set_oneshot(trigger_data->led_cdev, &interval, + &interval, 0); trigger_data->rx = icount.rx; trigger_data->tx = icount.tx; - } else { - led_set_brightness_sync(trigger_data->led_cdev, LED_OFF); } out: mutex_unlock(&trigger_data->mutex); - schedule_delayed_work(&trigger_data->dwork, msecs_to_jiffies(100)); + schedule_delayed_work(&trigger_data->dwork, + msecs_to_jiffies(LEDTRIG_TTY_INTERVAL * 2)); } static struct attribute *ledtrig_tty_attrs[] = { diff --git a/drivers/leds/uleds.c b/drivers/leds/uleds.c index 7320337b22d2..3d361c920030 100644 --- a/drivers/leds/uleds.c +++ b/drivers/leds/uleds.c @@ -209,17 +209,7 @@ static struct miscdevice uleds_misc = { .name = ULEDS_NAME, }; -static int __init uleds_init(void) -{ - return misc_register(&uleds_misc); -} -module_init(uleds_init); - -static void __exit uleds_exit(void) -{ - misc_deregister(&uleds_misc); -} -module_exit(uleds_exit); +module_misc_device(uleds_misc); MODULE_AUTHOR("David Lechner <david@lechnology.com>"); MODULE_DESCRIPTION("Userspace driver for the LED subsystem"); diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 85be64579fc9..aea95745c73f 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -1220,7 +1220,7 @@ config MFD_RC5T583 different functionality of the device. config MFD_RK8XX - bool + tristate select MFD_CORE config MFD_RK8XX_I2C @@ -1371,8 +1371,9 @@ config MFD_SC27XX_PMIC and it also adds the irq_chip parts for handling the PMIC chip events. config RZ_MTU3 - bool "Renesas RZ/G2L MTU3a core driver" + tristate "Renesas RZ/G2L MTU3a core driver" depends on (ARCH_RZG2L && OF) || COMPILE_TEST + select MFD_CORE help Select this option to enable Renesas RZ/G2L MTU3a core driver for the Multi-Function Timer Pulse Unit 3 (MTU3a) hardware available diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index 9d9e9787d5e8..15c95828b09a 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -21,7 +21,6 @@ #include <linux/mfd/abx500/ab8500.h> #include <linux/mfd/dbx500-prcmu.h> #include <linux/of.h> -#include <linux/of_device.h> /* * Interrupt register offsets diff --git a/drivers/mfd/acer-ec-a500.c b/drivers/mfd/acer-ec-a500.c index feb757e90dc3..79405835ff8e 100644 --- a/drivers/mfd/acer-ec-a500.c +++ b/drivers/mfd/acer-ec-a500.c @@ -9,7 +9,7 @@ #include <linux/i2c.h> #include <linux/mfd/core.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/reboot.h> #include <linux/regmap.h> diff --git a/drivers/mfd/act8945a.c b/drivers/mfd/act8945a.c index 2406fcdff5f9..4e32ac3d573e 100644 --- a/drivers/mfd/act8945a.c +++ b/drivers/mfd/act8945a.c @@ -10,7 +10,7 @@ #include <linux/i2c.h> #include <linux/mfd/core.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/regmap.h> static const struct mfd_cell act8945a_devs[] = { @@ -68,7 +68,7 @@ MODULE_DEVICE_TABLE(of, act8945a_of_match); static struct i2c_driver act8945a_i2c_driver = { .driver = { .name = "act8945a", - .of_match_table = of_match_ptr(act8945a_of_match), + .of_match_table = act8945a_of_match, }, .probe = act8945a_i2c_probe, .id_table = act8945a_i2c_id, diff --git a/drivers/mfd/altera-a10sr.c b/drivers/mfd/altera-a10sr.c index 34ef526f4aee..d53e433ab5c1 100644 --- a/drivers/mfd/altera-a10sr.c +++ b/drivers/mfd/altera-a10sr.c @@ -163,7 +163,7 @@ static struct spi_driver altr_a10sr_spi_driver = { .probe = altr_a10sr_spi_probe, .driver = { .name = "altr_a10sr", - .of_match_table = of_match_ptr(altr_a10sr_spi_of_match), + .of_match_table = altr_a10sr_spi_of_match, }, .id_table = altr_a10sr_spi_ids, }; diff --git a/drivers/mfd/altera-sysmgr.c b/drivers/mfd/altera-sysmgr.c index af205813b281..0e52bd2ebd74 100644 --- a/drivers/mfd/altera-sysmgr.c +++ b/drivers/mfd/altera-sysmgr.c @@ -14,8 +14,7 @@ #include <linux/mfd/syscon.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_address.h> -#include <linux/of_platform.h> +#include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/slab.h> diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index c166fcd331f1..19a0adf8ce3d 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -15,7 +15,6 @@ #include <linux/mfd/core.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/pm_runtime.h> #include <linux/regmap.h> #include <linux/regulator/consumer.h> diff --git a/drivers/mfd/atc260x-core.c b/drivers/mfd/atc260x-core.c index 7c5de3ae776e..67473b58b03d 100644 --- a/drivers/mfd/atc260x-core.c +++ b/drivers/mfd/atc260x-core.c @@ -11,7 +11,6 @@ #include <linux/mfd/core.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/regmap.h> #define ATC260X_CHIP_REV_MAX 31 diff --git a/drivers/mfd/atmel-hlcdc.c b/drivers/mfd/atmel-hlcdc.c index 3c2414ba4b01..20de7f49a830 100644 --- a/drivers/mfd/atmel-hlcdc.c +++ b/drivers/mfd/atmel-hlcdc.c @@ -83,7 +83,6 @@ static int atmel_hlcdc_probe(struct platform_device *pdev) struct atmel_hlcdc_regmap *hregmap; struct device *dev = &pdev->dev; struct atmel_hlcdc *hlcdc; - struct resource *res; hregmap = devm_kzalloc(dev, sizeof(*hregmap), GFP_KERNEL); if (!hregmap) @@ -93,8 +92,7 @@ static int atmel_hlcdc_probe(struct platform_device *pdev) if (!hlcdc) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - hregmap->regs = devm_ioremap_resource(dev, res); + hregmap->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(hregmap->regs)) return PTR_ERR(hregmap->regs); diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c index c03bc5cda080..87603eeaa277 100644 --- a/drivers/mfd/axp20x.c +++ b/drivers/mfd/axp20x.c @@ -342,7 +342,7 @@ static const struct regmap_config axp152_regmap_config = { .wr_table = &axp152_writeable_table, .volatile_table = &axp152_volatile_table, .max_register = AXP152_PWM1_DUTY_CYCLE, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; static const struct regmap_config axp192_regmap_config = { @@ -360,7 +360,7 @@ static const struct regmap_config axp20x_regmap_config = { .wr_table = &axp20x_writeable_table, .volatile_table = &axp20x_volatile_table, .max_register = AXP20X_OCV(AXP20X_OCV_MAX), - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; static const struct regmap_config axp22x_regmap_config = { @@ -369,7 +369,7 @@ static const struct regmap_config axp22x_regmap_config = { .wr_table = &axp22x_writeable_table, .volatile_table = &axp22x_volatile_table, .max_register = AXP22X_BATLOW_THRES1, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; static const struct regmap_config axp288_regmap_config = { @@ -378,7 +378,7 @@ static const struct regmap_config axp288_regmap_config = { .wr_table = &axp288_writeable_table, .volatile_table = &axp288_volatile_table, .max_register = AXP288_FG_TUNE5, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; static const struct regmap_config axp313a_regmap_config = { @@ -396,7 +396,7 @@ static const struct regmap_config axp806_regmap_config = { .wr_table = &axp806_writeable_table, .volatile_table = &axp806_volatile_table, .max_register = AXP806_REG_ADDR_EXT, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; static const struct regmap_config axp15060_regmap_config = { @@ -405,7 +405,7 @@ static const struct regmap_config axp15060_regmap_config = { .wr_table = &axp15060_writeable_table, .volatile_table = &axp15060_volatile_table, .max_register = AXP15060_IRQ2_STATE, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; #define INIT_REGMAP_IRQ(_variant, _irq, _off, _mask) \ diff --git a/drivers/mfd/bcm590xx.c b/drivers/mfd/bcm590xx.c index 9f39b46b87f4..92eede9a5e61 100644 --- a/drivers/mfd/bcm590xx.c +++ b/drivers/mfd/bcm590xx.c @@ -14,7 +14,6 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/regmap.h> #include <linux/slab.h> diff --git a/drivers/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c index 92f4dfccc3cc..79d393b602bf 100644 --- a/drivers/mfd/cros_ec_dev.c +++ b/drivers/mfd/cros_ec_dev.c @@ -10,7 +10,7 @@ #include <linux/mfd/core.h> #include <linux/module.h> #include <linux/mod_devicetable.h> -#include <linux/of_platform.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/platform_data/cros_ec_chardev.h> #include <linux/platform_data/cros_ec_commands.h> diff --git a/drivers/mfd/cs47l15-tables.c b/drivers/mfd/cs47l15-tables.c index 3c77f0a24e9b..59b005cc1e33 100644 --- a/drivers/mfd/cs47l15-tables.c +++ b/drivers/mfd/cs47l15-tables.c @@ -1249,7 +1249,7 @@ const struct regmap_config cs47l15_16bit_spi_regmap = { .readable_reg = &cs47l15_16bit_readable_register, .volatile_reg = &cs47l15_16bit_volatile_register, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .reg_defaults = cs47l15_reg_default, .num_reg_defaults = ARRAY_SIZE(cs47l15_reg_default), }; @@ -1264,7 +1264,7 @@ const struct regmap_config cs47l15_16bit_i2c_regmap = { .readable_reg = &cs47l15_16bit_readable_register, .volatile_reg = &cs47l15_16bit_volatile_register, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .reg_defaults = cs47l15_reg_default, .num_reg_defaults = ARRAY_SIZE(cs47l15_reg_default), }; @@ -1281,7 +1281,7 @@ const struct regmap_config cs47l15_32bit_spi_regmap = { .readable_reg = &cs47l15_32bit_readable_register, .volatile_reg = &cs47l15_32bit_volatile_register, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; EXPORT_SYMBOL_GPL(cs47l15_32bit_spi_regmap); @@ -1295,6 +1295,6 @@ const struct regmap_config cs47l15_32bit_i2c_regmap = { .readable_reg = &cs47l15_32bit_readable_register, .volatile_reg = &cs47l15_32bit_volatile_register, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; EXPORT_SYMBOL_GPL(cs47l15_32bit_i2c_regmap); diff --git a/drivers/mfd/cs47l24-tables.c b/drivers/mfd/cs47l24-tables.c index c289d92a5c1d..878dfd298a17 100644 --- a/drivers/mfd/cs47l24-tables.c +++ b/drivers/mfd/cs47l24-tables.c @@ -1616,7 +1616,7 @@ const struct regmap_config cs47l24_spi_regmap = { .readable_reg = cs47l24_readable_register, .volatile_reg = cs47l24_volatile_register, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .reg_defaults = cs47l24_reg_default, .num_reg_defaults = ARRAY_SIZE(cs47l24_reg_default), }; diff --git a/drivers/mfd/cs47l35-tables.c b/drivers/mfd/cs47l35-tables.c index a0bc6c5100d6..274f4b05850a 100644 --- a/drivers/mfd/cs47l35-tables.c +++ b/drivers/mfd/cs47l35-tables.c @@ -1498,7 +1498,7 @@ const struct regmap_config cs47l35_16bit_spi_regmap = { .readable_reg = cs47l35_16bit_readable_register, .volatile_reg = cs47l35_16bit_volatile_register, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .reg_defaults = cs47l35_reg_default, .num_reg_defaults = ARRAY_SIZE(cs47l35_reg_default), }; @@ -1515,7 +1515,7 @@ const struct regmap_config cs47l35_16bit_i2c_regmap = { .readable_reg = cs47l35_16bit_readable_register, .volatile_reg = cs47l35_16bit_volatile_register, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .reg_defaults = cs47l35_reg_default, .num_reg_defaults = ARRAY_SIZE(cs47l35_reg_default), }; @@ -1534,7 +1534,7 @@ const struct regmap_config cs47l35_32bit_spi_regmap = { .readable_reg = cs47l35_32bit_readable_register, .volatile_reg = cs47l35_32bit_volatile_register, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; EXPORT_SYMBOL_GPL(cs47l35_32bit_spi_regmap); @@ -1550,6 +1550,6 @@ const struct regmap_config cs47l35_32bit_i2c_regmap = { .readable_reg = cs47l35_32bit_readable_register, .volatile_reg = cs47l35_32bit_volatile_register, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; EXPORT_SYMBOL_GPL(cs47l35_32bit_i2c_regmap); diff --git a/drivers/mfd/cs47l85-tables.c b/drivers/mfd/cs47l85-tables.c index 270d8eda3f5f..f397894827ce 100644 --- a/drivers/mfd/cs47l85-tables.c +++ b/drivers/mfd/cs47l85-tables.c @@ -2836,7 +2836,7 @@ const struct regmap_config cs47l85_16bit_spi_regmap = { .readable_reg = cs47l85_16bit_readable_register, .volatile_reg = cs47l85_16bit_volatile_register, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .reg_defaults = cs47l85_reg_default, .num_reg_defaults = ARRAY_SIZE(cs47l85_reg_default), }; @@ -2853,7 +2853,7 @@ const struct regmap_config cs47l85_16bit_i2c_regmap = { .readable_reg = cs47l85_16bit_readable_register, .volatile_reg = cs47l85_16bit_volatile_register, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .reg_defaults = cs47l85_reg_default, .num_reg_defaults = ARRAY_SIZE(cs47l85_reg_default), }; @@ -2872,7 +2872,7 @@ const struct regmap_config cs47l85_32bit_spi_regmap = { .readable_reg = cs47l85_32bit_readable_register, .volatile_reg = cs47l85_32bit_volatile_register, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; EXPORT_SYMBOL_GPL(cs47l85_32bit_spi_regmap); @@ -2888,6 +2888,6 @@ const struct regmap_config cs47l85_32bit_i2c_regmap = { .readable_reg = cs47l85_32bit_readable_register, .volatile_reg = cs47l85_32bit_volatile_register, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; EXPORT_SYMBOL_GPL(cs47l85_32bit_i2c_regmap); diff --git a/drivers/mfd/cs47l90-tables.c b/drivers/mfd/cs47l90-tables.c index 7345fc09c0bb..6f9ceb36c533 100644 --- a/drivers/mfd/cs47l90-tables.c +++ b/drivers/mfd/cs47l90-tables.c @@ -2539,7 +2539,7 @@ const struct regmap_config cs47l90_16bit_spi_regmap = { .readable_reg = cs47l90_16bit_readable_register, .volatile_reg = cs47l90_16bit_volatile_register, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .reg_defaults = cs47l90_reg_default, .num_reg_defaults = ARRAY_SIZE(cs47l90_reg_default), }; @@ -2556,7 +2556,7 @@ const struct regmap_config cs47l90_16bit_i2c_regmap = { .readable_reg = cs47l90_16bit_readable_register, .volatile_reg = cs47l90_16bit_volatile_register, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .reg_defaults = cs47l90_reg_default, .num_reg_defaults = ARRAY_SIZE(cs47l90_reg_default), }; @@ -2575,7 +2575,7 @@ const struct regmap_config cs47l90_32bit_spi_regmap = { .readable_reg = cs47l90_32bit_readable_register, .volatile_reg = cs47l90_32bit_volatile_register, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; EXPORT_SYMBOL_GPL(cs47l90_32bit_spi_regmap); @@ -2591,6 +2591,6 @@ const struct regmap_config cs47l90_32bit_i2c_regmap = { .readable_reg = cs47l90_32bit_readable_register, .volatile_reg = cs47l90_32bit_volatile_register, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; EXPORT_SYMBOL_GPL(cs47l90_32bit_i2c_regmap); diff --git a/drivers/mfd/cs47l92-tables.c b/drivers/mfd/cs47l92-tables.c index f296e355df4d..4d9ba865aaf6 100644 --- a/drivers/mfd/cs47l92-tables.c +++ b/drivers/mfd/cs47l92-tables.c @@ -1890,7 +1890,7 @@ const struct regmap_config cs47l92_16bit_spi_regmap = { .readable_reg = &cs47l92_16bit_readable_register, .volatile_reg = &cs47l92_16bit_volatile_register, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .reg_defaults = cs47l92_reg_default, .num_reg_defaults = ARRAY_SIZE(cs47l92_reg_default), }; @@ -1907,7 +1907,7 @@ const struct regmap_config cs47l92_16bit_i2c_regmap = { .readable_reg = &cs47l92_16bit_readable_register, .volatile_reg = &cs47l92_16bit_volatile_register, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .reg_defaults = cs47l92_reg_default, .num_reg_defaults = ARRAY_SIZE(cs47l92_reg_default), }; @@ -1926,7 +1926,7 @@ const struct regmap_config cs47l92_32bit_spi_regmap = { .readable_reg = &cs47l92_32bit_readable_register, .volatile_reg = &cs47l92_32bit_volatile_register, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; EXPORT_SYMBOL_GPL(cs47l92_32bit_spi_regmap); @@ -1942,6 +1942,6 @@ const struct regmap_config cs47l92_32bit_i2c_regmap = { .readable_reg = &cs47l92_32bit_readable_register, .volatile_reg = &cs47l92_32bit_volatile_register, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; EXPORT_SYMBOL_GPL(cs47l92_32bit_i2c_regmap); diff --git a/drivers/mfd/da9052-i2c.c b/drivers/mfd/da9052-i2c.c index 541e2d47677e..fd000a21bcba 100644 --- a/drivers/mfd/da9052-i2c.c +++ b/drivers/mfd/da9052-i2c.c @@ -13,14 +13,11 @@ #include <linux/mfd/core.h> #include <linux/i2c.h> #include <linux/err.h> +#include <linux/of.h> #include <linux/mfd/da9052/da9052.h> #include <linux/mfd/da9052/reg.h> -#ifdef CONFIG_OF -#include <linux/of.h> -#include <linux/of_device.h> -#endif /* I2C safe register check */ static inline bool i2c_safe_reg(unsigned char reg) diff --git a/drivers/mfd/da9055-i2c.c b/drivers/mfd/da9055-i2c.c index bbaf4f07f274..9a5f51b60bad 100644 --- a/drivers/mfd/da9055-i2c.c +++ b/drivers/mfd/da9055-i2c.c @@ -11,7 +11,6 @@ #include <linux/i2c.h> #include <linux/err.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/mfd/da9055/core.h> diff --git a/drivers/mfd/da9062-core.c b/drivers/mfd/da9062-core.c index 48f58b6f5629..45da007d3e70 100644 --- a/drivers/mfd/da9062-core.c +++ b/drivers/mfd/da9062-core.c @@ -9,7 +9,7 @@ #include <linux/init.h> #include <linux/device.h> #include <linux/interrupt.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/regmap.h> #include <linux/irq.h> #include <linux/mfd/core.h> diff --git a/drivers/mfd/exynos-lpass.c b/drivers/mfd/exynos-lpass.c index 166cd21088cd..1506d8d352b1 100644 --- a/drivers/mfd/exynos-lpass.c +++ b/drivers/mfd/exynos-lpass.c @@ -109,14 +109,12 @@ static int exynos_lpass_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct exynos_lpass *lpass; void __iomem *base_top; - struct resource *res; lpass = devm_kzalloc(dev, sizeof(*lpass), GFP_KERNEL); if (!lpass) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base_top = devm_ioremap_resource(dev, res); + base_top = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base_top)) return PTR_ERR(base_top); diff --git a/drivers/mfd/hi6421-pmic-core.c b/drivers/mfd/hi6421-pmic-core.c index cb5cf4a81c06..a6a890537a1e 100644 --- a/drivers/mfd/hi6421-pmic-core.c +++ b/drivers/mfd/hi6421-pmic-core.c @@ -59,7 +59,7 @@ static int hi6421_pmic_probe(struct platform_device *pdev) id = of_match_device(of_hi6421_pmic_match, &pdev->dev); if (!id) return -EINVAL; - type = (enum hi6421_type)id->data; + type = (uintptr_t)id->data; pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL); if (!pmic) diff --git a/drivers/mfd/hi655x-pmic.c b/drivers/mfd/hi655x-pmic.c index a58e42ddcd0c..8feae8d8fd9d 100644 --- a/drivers/mfd/hi655x-pmic.c +++ b/drivers/mfd/hi655x-pmic.c @@ -16,7 +16,7 @@ #include <linux/mfd/hi655x-pmic.h> #include <linux/module.h> #include <linux/gpio/consumer.h> -#include <linux/of_platform.h> +#include <linux/mod_devicetable.h> #include <linux/platform_device.h> #include <linux/regmap.h> @@ -100,8 +100,7 @@ static int hi655x_pmic_probe(struct platform_device *pdev) return -ENOMEM; pmic->dev = dev; - pmic->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(dev, pmic->res); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); @@ -163,7 +162,7 @@ MODULE_DEVICE_TABLE(of, hi655x_pmic_match); static struct platform_driver hi655x_pmic_driver = { .driver = { .name = "hi655x-pmic", - .of_match_table = of_match_ptr(hi655x_pmic_match), + .of_match_table = hi655x_pmic_match, }, .probe = hi655x_pmic_probe, .remove = hi655x_pmic_remove, diff --git a/drivers/mfd/ipaq-micro.c b/drivers/mfd/ipaq-micro.c index 6d3968458e81..c964ea6539aa 100644 --- a/drivers/mfd/ipaq-micro.c +++ b/drivers/mfd/ipaq-micro.c @@ -78,8 +78,6 @@ EXPORT_SYMBOL(ipaq_micro_tx_msg); static void micro_rx_msg(struct ipaq_micro *micro, u8 id, int len, u8 *data) { - int i; - dev_dbg(micro->dev, "RX msg: %02x, %d bytes\n", id, len); spin_lock(µ->lock); @@ -131,10 +129,7 @@ static void micro_rx_msg(struct ipaq_micro *micro, u8 id, int len, u8 *data) break; default: dev_err(micro->dev, - "unknown msg %d [%d] ", id, len); - for (i = 0; i < len; ++i) - pr_cont("0x%02x ", data[i]); - pr_cont("\n"); + "unknown msg %d [%d] %*ph\n", id, len, len, data); } spin_unlock(µ->lock); } diff --git a/drivers/mfd/iqs62x.c b/drivers/mfd/iqs62x.c index dfe9cb79e6a1..e03b4d38fbb0 100644 --- a/drivers/mfd/iqs62x.c +++ b/drivers/mfd/iqs62x.c @@ -27,7 +27,7 @@ #include <linux/mfd/iqs62x.h> #include <linux/module.h> #include <linux/notifier.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/property.h> #include <linux/regmap.h> #include <linux/slab.h> diff --git a/drivers/mfd/lochnagar-i2c.c b/drivers/mfd/lochnagar-i2c.c index 3c8843117080..59092f839d65 100644 --- a/drivers/mfd/lochnagar-i2c.c +++ b/drivers/mfd/lochnagar-i2c.c @@ -379,7 +379,7 @@ static int lochnagar_i2c_probe(struct i2c_client *i2c) static struct i2c_driver lochnagar_i2c_driver = { .driver = { .name = "lochnagar", - .of_match_table = of_match_ptr(lochnagar_of_match), + .of_match_table = lochnagar_of_match, .suppress_bind_attrs = true, }, .probe = lochnagar_i2c_probe, diff --git a/drivers/mfd/lp873x.c b/drivers/mfd/lp873x.c index 6639f0fad4ea..de7ab7aed3c6 100644 --- a/drivers/mfd/lp873x.c +++ b/drivers/mfd/lp873x.c @@ -7,8 +7,8 @@ #include <linux/interrupt.h> #include <linux/mfd/core.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> -#include <linux/of_device.h> #include <linux/regmap.h> #include <linux/mfd/lp873x.h> diff --git a/drivers/mfd/lp87565.c b/drivers/mfd/lp87565.c index 88ce4d7c50a7..1b7f8349911d 100644 --- a/drivers/mfd/lp87565.c +++ b/drivers/mfd/lp87565.c @@ -92,7 +92,7 @@ static int lp87565_probe(struct i2c_client *client) of_id = of_match_device(of_lp87565_match_table, &client->dev); if (of_id) - lp87565->dev_type = (enum lp87565_device_type)of_id->data; + lp87565->dev_type = (uintptr_t)of_id->data; i2c_set_clientdata(client, lp87565); diff --git a/drivers/mfd/madera-i2c.c b/drivers/mfd/madera-i2c.c index 0968aa9733ac..a404ea26bc79 100644 --- a/drivers/mfd/madera-i2c.c +++ b/drivers/mfd/madera-i2c.c @@ -10,7 +10,6 @@ #include <linux/i2c.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/regmap.h> #include <linux/mfd/madera/core.h> diff --git a/drivers/mfd/madera-spi.c b/drivers/mfd/madera-spi.c index da84eb50e53a..ad07ebe29e59 100644 --- a/drivers/mfd/madera-spi.c +++ b/drivers/mfd/madera-spi.c @@ -9,7 +9,6 @@ #include <linux/err.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/regmap.h> #include <linux/spi/spi.h> diff --git a/drivers/mfd/max14577.c b/drivers/mfd/max14577.c index 25ed8846b7fb..1f4f5002595c 100644 --- a/drivers/mfd/max14577.c +++ b/drivers/mfd/max14577.c @@ -402,8 +402,7 @@ static int max14577_i2c_probe(struct i2c_client *i2c) of_id = of_match_device(max14577_dt_match, &i2c->dev); if (of_id) - max14577->dev_type = - (enum maxim_device_type)of_id->data; + max14577->dev_type = (uintptr_t)of_id->data; } else { max14577->dev_type = id->driver_data; } diff --git a/drivers/mfd/max77541.c b/drivers/mfd/max77541.c index e147e949c2b3..10c2e274b4af 100644 --- a/drivers/mfd/max77541.c +++ b/drivers/mfd/max77541.c @@ -173,7 +173,7 @@ static int max77541_probe(struct i2c_client *client) i2c_set_clientdata(client, max77541); max77541->i2c = client; - max77541->id = (enum max7754x_ids)device_get_match_data(dev); + max77541->id = (uintptr_t)device_get_match_data(dev); if (!max77541->id) max77541->id = (enum max7754x_ids)id->driver_data; diff --git a/drivers/mfd/max77620.c b/drivers/mfd/max77620.c index 5811ed8f4840..e63e8e47d908 100644 --- a/drivers/mfd/max77620.c +++ b/drivers/mfd/max77620.c @@ -30,7 +30,6 @@ #include <linux/mfd/max77620.h> #include <linux/init.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/regmap.h> #include <linux/slab.h> diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c index 01833086ca7d..91c286c4571c 100644 --- a/drivers/mfd/max77686.c +++ b/drivers/mfd/max77686.c @@ -20,7 +20,6 @@ #include <linux/mfd/max77686-private.h> #include <linux/err.h> #include <linux/of.h> -#include <linux/of_device.h> static const struct mfd_cell max77686_devs[] = { { .name = "max77686-pmic", }, diff --git a/drivers/mfd/max77843.c b/drivers/mfd/max77843.c index b3689c13a14d..fcff0c498c0f 100644 --- a/drivers/mfd/max77843.c +++ b/drivers/mfd/max77843.c @@ -13,7 +13,7 @@ #include <linux/mfd/core.h> #include <linux/mfd/max77693-common.h> #include <linux/mfd/max77843-private.h> -#include <linux/of_device.h> +#include <linux/mod_devicetable.h> #include <linux/platform_device.h> static const struct mfd_cell max77843_devs[] = { diff --git a/drivers/mfd/max8907.c b/drivers/mfd/max8907.c index 78b5ee688dec..8bbe7979db91 100644 --- a/drivers/mfd/max8907.c +++ b/drivers/mfd/max8907.c @@ -15,7 +15,6 @@ #include <linux/mfd/max8907.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/regmap.h> #include <linux/slab.h> diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c index 0246bbe80354..105d79b91493 100644 --- a/drivers/mfd/max8925-core.c +++ b/drivers/mfd/max8925-core.c @@ -17,7 +17,6 @@ #include <linux/mfd/core.h> #include <linux/mfd/max8925.h> #include <linux/of.h> -#include <linux/of_platform.h> static const struct resource bk_resources[] = { { 0x84, 0x84, "mode control", IORESOURCE_REG, }, diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c index 94c09a5eab32..110bef71f208 100644 --- a/drivers/mfd/max8997.c +++ b/drivers/mfd/max8997.c @@ -11,7 +11,6 @@ #include <linux/slab.h> #include <linux/i2c.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/of_irq.h> #include <linux/interrupt.h> #include <linux/pm_runtime.h> diff --git a/drivers/mfd/max8998.c b/drivers/mfd/max8998.c index 33a3ec5464fb..4cc426a6c767 100644 --- a/drivers/mfd/max8998.c +++ b/drivers/mfd/max8998.c @@ -12,7 +12,6 @@ #include <linux/i2c.h> #include <linux/interrupt.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/of_irq.h> #include <linux/pm_runtime.h> #include <linux/mutex.h> diff --git a/drivers/mfd/mc13xxx-i2c.c b/drivers/mfd/mc13xxx-i2c.c index de59b498c925..6bc0e755ba34 100644 --- a/drivers/mfd/mc13xxx-i2c.c +++ b/drivers/mfd/mc13xxx-i2c.c @@ -53,7 +53,6 @@ static const struct regmap_config mc13xxx_regmap_i2c_config = { static int mc13xxx_i2c_probe(struct i2c_client *client) { - const struct i2c_device_id *id = i2c_client_get_device_id(client); struct mc13xxx *mc13xxx; int ret; @@ -73,13 +72,7 @@ static int mc13xxx_i2c_probe(struct i2c_client *client) return ret; } - if (client->dev.of_node) { - const struct of_device_id *of_id = - of_match_device(mc13xxx_dt_ids, &client->dev); - mc13xxx->variant = of_id->data; - } else { - mc13xxx->variant = (void *)id->driver_data; - } + mc13xxx->variant = i2c_get_match_data(client); return mc13xxx_common_init(&client->dev); } diff --git a/drivers/mfd/mt6358-irq.c b/drivers/mfd/mt6358-irq.c index 389756436af6..49830b526ee8 100644 --- a/drivers/mfd/mt6358-irq.c +++ b/drivers/mfd/mt6358-irq.c @@ -3,6 +3,8 @@ // Copyright (c) 2020 MediaTek Inc. #include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/irqdomain.h> #include <linux/mfd/mt6357/core.h> #include <linux/mfd/mt6357/registers.h> #include <linux/mfd/mt6358/core.h> @@ -11,9 +13,6 @@ #include <linux/mfd/mt6359/registers.h> #include <linux/mfd/mt6397/core.h> #include <linux/module.h> -#include <linux/of.h> -#include <linux/of_device.h> -#include <linux/of_irq.h> #include <linux/platform_device.h> #include <linux/regmap.h> diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c index f6c1f80f94a4..4449dde05021 100644 --- a/drivers/mfd/mt6397-core.c +++ b/drivers/mfd/mt6397-core.c @@ -6,9 +6,10 @@ #include <linux/interrupt.h> #include <linux/ioport.h> +#include <linux/irqdomain.h> #include <linux/module.h> -#include <linux/of_device.h> -#include <linux/of_irq.h> +#include <linux/of.h> +#include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/mfd/core.h> #include <linux/mfd/mt6323/core.h> diff --git a/drivers/mfd/mt6397-irq.c b/drivers/mfd/mt6397-irq.c index 72f923e47752..886745b5b607 100644 --- a/drivers/mfd/mt6397-irq.c +++ b/drivers/mfd/mt6397-irq.c @@ -3,10 +3,9 @@ // Copyright (c) 2019 MediaTek Inc. #include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/irqdomain.h> #include <linux/module.h> -#include <linux/of.h> -#include <linux/of_device.h> -#include <linux/of_irq.h> #include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/suspend.h> diff --git a/drivers/mfd/mxs-lradc.c b/drivers/mfd/mxs-lradc.c index 111d11fd25aa..21f3033d6eb5 100644 --- a/drivers/mfd/mxs-lradc.c +++ b/drivers/mfd/mxs-lradc.c @@ -142,7 +142,7 @@ static int mxs_lradc_probe(struct platform_device *pdev) if (!of_id) return -EINVAL; - lradc->soc = (enum mxs_lradc_id)of_id->data; + lradc->soc = (uintptr_t)of_id->data; lradc->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(lradc->clk)) { diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c index 7f5775109593..78f1bb55dbc0 100644 --- a/drivers/mfd/omap-usb-host.c +++ b/drivers/mfd/omap-usb-host.c @@ -534,7 +534,6 @@ static int usbhs_omap_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct usbhs_omap_platform_data *pdata = dev_get_platdata(dev); struct usbhs_hcd_omap *omap; - struct resource *res; int ret = 0; int i; bool need_logic_fck; @@ -569,8 +568,7 @@ static int usbhs_omap_probe(struct platform_device *pdev) return -ENOMEM; } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - omap->uhh_base = devm_ioremap_resource(dev, res); + omap->uhh_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(omap->uhh_base)) return PTR_ERR(omap->uhh_base); diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c index 69cbc2097911..906353735c78 100644 --- a/drivers/mfd/omap-usb-tll.c +++ b/drivers/mfd/omap-usb-tll.c @@ -200,15 +200,13 @@ static unsigned ohci_omap3_fslsmode(enum usbhs_omap_port_mode mode) static int usbtll_omap_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct resource *res; struct usbtll_omap *tll; void __iomem *base; int i, nch, ver; dev_dbg(dev, "starting TI HSUSB TLL Controller\n"); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(dev, res); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c index a36f12402987..6e562bab62e4 100644 --- a/drivers/mfd/palmas.c +++ b/drivers/mfd/palmas.c @@ -18,7 +18,8 @@ #include <linux/err.h> #include <linux/mfd/core.h> #include <linux/mfd/palmas.h> -#include <linux/of_device.h> +#include <linux/of.h> +#include <linux/of_platform.h> static const struct regmap_config palmas_regmap_config[PALMAS_NUM_CLIENTS] = { { diff --git a/drivers/mfd/qcom-pm8008.c b/drivers/mfd/qcom-pm8008.c index 94a8cca1d955..3ac3742f438b 100644 --- a/drivers/mfd/qcom-pm8008.c +++ b/drivers/mfd/qcom-pm8008.c @@ -9,7 +9,7 @@ #include <linux/irq.h> #include <linux/irqdomain.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/of_platform.h> #include <linux/pinctrl/consumer.h> #include <linux/regmap.h> diff --git a/drivers/mfd/qcom-pm8xxx.c b/drivers/mfd/qcom-pm8xxx.c index 9a948df8c28d..07c531bd1236 100644 --- a/drivers/mfd/qcom-pm8xxx.c +++ b/drivers/mfd/qcom-pm8xxx.c @@ -103,8 +103,9 @@ static int pm8xxx_config_irq(struct pm_irq_chip *chip, unsigned int bp, unsigned int cp) { int rc; + unsigned long flags; - spin_lock(&chip->pm_irq_lock); + spin_lock_irqsave(&chip->pm_irq_lock, flags); rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_BLK_SEL, bp); if (rc) { pr_err("Failed Selecting Block %d rc=%d\n", bp, rc); @@ -116,7 +117,7 @@ pm8xxx_config_irq(struct pm_irq_chip *chip, unsigned int bp, unsigned int cp) if (rc) pr_err("Failed Configuring IRQ rc=%d\n", rc); bail: - spin_unlock(&chip->pm_irq_lock); + spin_unlock_irqrestore(&chip->pm_irq_lock, flags); return rc; } @@ -321,6 +322,7 @@ static int pm8xxx_irq_get_irqchip_state(struct irq_data *d, struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d); unsigned int pmirq = irqd_to_hwirq(d); unsigned int bits; + unsigned long flags; int irq_bit; u8 block; int rc; @@ -331,7 +333,7 @@ static int pm8xxx_irq_get_irqchip_state(struct irq_data *d, block = pmirq / 8; irq_bit = pmirq % 8; - spin_lock(&chip->pm_irq_lock); + spin_lock_irqsave(&chip->pm_irq_lock, flags); rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_BLK_SEL, block); if (rc) { pr_err("Failed Selecting Block %d rc=%d\n", block, rc); @@ -346,7 +348,7 @@ static int pm8xxx_irq_get_irqchip_state(struct irq_data *d, *state = !!(bits & BIT(irq_bit)); bail: - spin_unlock(&chip->pm_irq_lock); + spin_unlock_irqrestore(&chip->pm_irq_lock, flags); return rc; } diff --git a/drivers/mfd/rave-sp.c b/drivers/mfd/rave-sp.c index 545196c85b5c..da50eba10014 100644 --- a/drivers/mfd/rave-sp.c +++ b/drivers/mfd/rave-sp.c @@ -18,7 +18,7 @@ #include <linux/mfd/rave-sp.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> +#include <linux/of_platform.h> #include <linux/sched.h> #include <linux/serdev.h> #include <asm/unaligned.h> diff --git a/drivers/mfd/rk8xx-core.c b/drivers/mfd/rk8xx-core.c index e8fc9e2ab1d0..11a831e92da8 100644 --- a/drivers/mfd/rk8xx-core.c +++ b/drivers/mfd/rk8xx-core.c @@ -14,7 +14,7 @@ #include <linux/mfd/rk808.h> #include <linux/mfd/core.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/property.h> #include <linux/regmap.h> #include <linux/reboot.h> diff --git a/drivers/mfd/rn5t618.c b/drivers/mfd/rn5t618.c index 333fef8729a5..0fe616b2db8e 100644 --- a/drivers/mfd/rn5t618.c +++ b/drivers/mfd/rn5t618.c @@ -277,7 +277,7 @@ static SIMPLE_DEV_PM_OPS(rn5t618_i2c_dev_pm_ops, static struct i2c_driver rn5t618_i2c_driver = { .driver = { .name = "rn5t618", - .of_match_table = of_match_ptr(rn5t618_of_match), + .of_match_table = rn5t618_of_match, .pm = &rn5t618_i2c_dev_pm_ops, }, .probe = rn5t618_i2c_probe, diff --git a/drivers/mfd/rohm-bd71828.c b/drivers/mfd/rohm-bd71828.c index 93d80a79b901..594718f7e8e1 100644 --- a/drivers/mfd/rohm-bd71828.c +++ b/drivers/mfd/rohm-bd71828.c @@ -15,7 +15,7 @@ #include <linux/mfd/rohm-bd71828.h> #include <linux/mfd/rohm-generic.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/regmap.h> #include <linux/types.h> diff --git a/drivers/mfd/rohm-bd718x7.c b/drivers/mfd/rohm-bd718x7.c index 0b58ecc78334..4798bdf27afb 100644 --- a/drivers/mfd/rohm-bd718x7.c +++ b/drivers/mfd/rohm-bd718x7.c @@ -14,7 +14,7 @@ #include <linux/mfd/rohm-bd718x7.h> #include <linux/mfd/core.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/regmap.h> #include <linux/types.h> diff --git a/drivers/mfd/rohm-bd9576.c b/drivers/mfd/rohm-bd9576.c index 645673322ec0..bceac7016740 100644 --- a/drivers/mfd/rohm-bd9576.c +++ b/drivers/mfd/rohm-bd9576.c @@ -13,7 +13,7 @@ #include <linux/mfd/rohm-bd957x.h> #include <linux/mfd/rohm-generic.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/regmap.h> #include <linux/types.h> diff --git a/drivers/mfd/rsmu_i2c.c b/drivers/mfd/rsmu_i2c.c index 26972a5aff45..06d78a1cf1cc 100644 --- a/drivers/mfd/rsmu_i2c.c +++ b/drivers/mfd/rsmu_i2c.c @@ -277,7 +277,7 @@ MODULE_DEVICE_TABLE(of, rsmu_i2c_of_match); static struct i2c_driver rsmu_i2c_driver = { .driver = { .name = "rsmu-i2c", - .of_match_table = of_match_ptr(rsmu_i2c_of_match), + .of_match_table = rsmu_i2c_of_match, }, .probe = rsmu_i2c_probe, .remove = rsmu_i2c_remove, diff --git a/drivers/mfd/rsmu_spi.c b/drivers/mfd/rsmu_spi.c index a4a595bb8d0d..ca0a1202c3ce 100644 --- a/drivers/mfd/rsmu_spi.c +++ b/drivers/mfd/rsmu_spi.c @@ -262,7 +262,7 @@ MODULE_DEVICE_TABLE(of, rsmu_spi_of_match); static struct spi_driver rsmu_spi_driver = { .driver = { .name = "rsmu-spi", - .of_match_table = of_match_ptr(rsmu_spi_of_match), + .of_match_table = rsmu_spi_of_match, }, .probe = rsmu_spi_probe, .remove = rsmu_spi_remove, diff --git a/drivers/mfd/rt5033.c b/drivers/mfd/rt5033.c index 67b0a228db24..7e23ab3d5842 100644 --- a/drivers/mfd/rt5033.c +++ b/drivers/mfd/rt5033.c @@ -10,9 +10,9 @@ */ #include <linux/err.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> #include <linux/interrupt.h> -#include <linux/of_device.h> #include <linux/mfd/core.h> #include <linux/mfd/rt5033.h> #include <linux/mfd/rt5033-private.h> diff --git a/drivers/mfd/rz-mtu3.c b/drivers/mfd/rz-mtu3.c index 04006f4aa702..f3dac4a29a83 100644 --- a/drivers/mfd/rz-mtu3.c +++ b/drivers/mfd/rz-mtu3.c @@ -11,7 +11,9 @@ #include <linux/irq.h> #include <linux/mfd/core.h> #include <linux/mfd/rz-mtu3.h> -#include <linux/of_platform.h> +#include <linux/module.h> +#include <linux/mod_devicetable.h> +#include <linux/platform_device.h> #include <linux/reset.h> #include <linux/spinlock.h> @@ -20,7 +22,7 @@ struct rz_mtu3_priv { void __iomem *mmio; struct reset_control *rstc; - raw_spinlock_t lock; + spinlock_t lock; }; /******* MTU3 registers (original offset is +0x1200) *******/ @@ -174,11 +176,11 @@ void rz_mtu3_shared_reg_update_bit(struct rz_mtu3_channel *ch, u16 offset, struct rz_mtu3_priv *priv = mtu->priv_data; unsigned long tmdr, flags; - raw_spin_lock_irqsave(&priv->lock, flags); + spin_lock_irqsave(&priv->lock, flags); tmdr = rz_mtu3_shared_reg_read(ch, offset); __assign_bit(pos, &tmdr, !!val); rz_mtu3_shared_reg_write(ch, offset, tmdr); - raw_spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); } EXPORT_SYMBOL_GPL(rz_mtu3_shared_reg_update_bit); @@ -250,16 +252,17 @@ static void rz_mtu3_start_stop_ch(struct rz_mtu3_channel *ch, bool start) u16 offset; u8 bitpos; - /* start stop register shared by multiple timer channels */ - raw_spin_lock_irqsave(&priv->lock, flags); - offset = rz_mtu3_get_tstr_offset(ch); bitpos = rz_mtu3_get_tstr_bit_pos(ch); + + /* start stop register shared by multiple timer channels */ + spin_lock_irqsave(&priv->lock, flags); + tstr = rz_mtu3_shared_reg_read(ch, offset); __assign_bit(bitpos, &tstr, start); rz_mtu3_shared_reg_write(ch, offset, tstr); - raw_spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); } bool rz_mtu3_is_enabled(struct rz_mtu3_channel *ch) @@ -267,21 +270,18 @@ bool rz_mtu3_is_enabled(struct rz_mtu3_channel *ch) struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent); struct rz_mtu3_priv *priv = mtu->priv_data; unsigned long flags, tstr; - bool ret = false; u16 offset; u8 bitpos; - /* start stop register shared by multiple timer channels */ - raw_spin_lock_irqsave(&priv->lock, flags); - offset = rz_mtu3_get_tstr_offset(ch); bitpos = rz_mtu3_get_tstr_bit_pos(ch); - tstr = rz_mtu3_shared_reg_read(ch, offset); - ret = tstr & BIT(bitpos); - raw_spin_unlock_irqrestore(&priv->lock, flags); + /* start stop register shared by multiple timer channels */ + spin_lock_irqsave(&priv->lock, flags); + tstr = rz_mtu3_shared_reg_read(ch, offset); + spin_unlock_irqrestore(&priv->lock, flags); - return ret; + return tstr & BIT(bitpos); } EXPORT_SYMBOL_GPL(rz_mtu3_is_enabled); @@ -349,7 +349,7 @@ static int rz_mtu3_probe(struct platform_device *pdev) return PTR_ERR(ddata->clk); reset_control_deassert(priv->rstc); - raw_spin_lock_init(&priv->lock); + spin_lock_init(&priv->lock); platform_set_drvdata(pdev, ddata); for (i = 0; i < RZ_MTU_NUM_CHANNELS; i++) { diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index d2f631901886..a6b0d7300b2d 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-core.c @@ -10,8 +10,6 @@ #include <linux/slab.h> #include <linux/i2c.h> #include <linux/of.h> -#include <linux/of_device.h> -#include <linux/of_irq.h> #include <linux/interrupt.h> #include <linux/pm_runtime.h> #include <linux/mutex.h> diff --git a/drivers/mfd/sprd-sc27xx-spi.c b/drivers/mfd/sprd-sc27xx-spi.c index d21f32cc784d..81e517cdfb27 100644 --- a/drivers/mfd/sprd-sc27xx-spi.c +++ b/drivers/mfd/sprd-sc27xx-spi.c @@ -8,7 +8,7 @@ #include <linux/module.h> #include <linux/mfd/core.h> #include <linux/mfd/sc27xx-pmic.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/of_platform.h> #include <linux/regmap.h> #include <linux/spi/spi.h> diff --git a/drivers/mfd/ssbi.c b/drivers/mfd/ssbi.c index dee89db3471d..b0b0be483dbf 100644 --- a/drivers/mfd/ssbi.c +++ b/drivers/mfd/ssbi.c @@ -14,12 +14,12 @@ #include <linux/err.h> #include <linux/io.h> #include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_platform.h> #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/ssbi.h> -#include <linux/module.h> -#include <linux/of.h> -#include <linux/of_device.h> /* SSBI 2.0 controller registers */ #define SSBI2_CMD 0x0008 diff --git a/drivers/mfd/stm32-lptimer.c b/drivers/mfd/stm32-lptimer.c index fa322f4412c8..b2704a9809c7 100644 --- a/drivers/mfd/stm32-lptimer.c +++ b/drivers/mfd/stm32-lptimer.c @@ -9,6 +9,7 @@ #include <linux/mfd/stm32-lptimer.h> #include <linux/module.h> #include <linux/of_platform.h> +#include <linux/platform_device.h> #define STM32_LPTIM_MAX_REGISTER 0x3fc diff --git a/drivers/mfd/stm32-timers.c b/drivers/mfd/stm32-timers.c index 44ed2fce0319..732a28db80fa 100644 --- a/drivers/mfd/stm32-timers.c +++ b/drivers/mfd/stm32-timers.c @@ -8,6 +8,7 @@ #include <linux/mfd/stm32-timers.h> #include <linux/module.h> #include <linux/of_platform.h> +#include <linux/platform_device.h> #include <linux/reset.h> #define STM32_TIMERS_MAX_REGISTERS 0x3fc @@ -226,8 +227,7 @@ static int stm32_timers_probe(struct platform_device *pdev) if (!ddata) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - mmio = devm_ioremap_resource(dev, res); + mmio = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(mmio)) return PTR_ERR(mmio); diff --git a/drivers/mfd/stmpe-i2c.c b/drivers/mfd/stmpe-i2c.c index 1d7b401776d1..fe018bedab98 100644 --- a/drivers/mfd/stmpe-i2c.c +++ b/drivers/mfd/stmpe-i2c.c @@ -87,7 +87,7 @@ stmpe_i2c_probe(struct i2c_client *i2c) dev_info(&i2c->dev, "matching on node name, compatible is preferred\n"); partnum = id->driver_data; } else - partnum = (enum stmpe_partnum)of_id->data; + partnum = (uintptr_t)of_id->data; return stmpe_probe(&i2c_ci, partnum); } diff --git a/drivers/mfd/stpmic1.c b/drivers/mfd/stpmic1.c index 3cc7492f828f..c5128fe96cc7 100644 --- a/drivers/mfd/stpmic1.c +++ b/drivers/mfd/stpmic1.c @@ -219,7 +219,7 @@ MODULE_DEVICE_TABLE(of, stpmic1_of_match); static struct i2c_driver stpmic1_driver = { .driver = { .name = "stpmic1", - .of_match_table = of_match_ptr(stpmic1_of_match), + .of_match_table = stpmic1_of_match, .pm = pm_sleep_ptr(&stpmic1_pm), }, .probe = stpmic1_probe, diff --git a/drivers/mfd/sun4i-gpadc.c b/drivers/mfd/sun4i-gpadc.c index d1cbea27b136..3029d48e982c 100644 --- a/drivers/mfd/sun4i-gpadc.c +++ b/drivers/mfd/sun4i-gpadc.c @@ -8,8 +8,8 @@ #include <linux/kernel.h> #include <linux/mfd/core.h> #include <linux/module.h> -#include <linux/of_device.h> -#include <linux/of_irq.h> +#include <linux/of.h> +#include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/mfd/sun4i-gpadc.h> diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c index 16df64e3c0be..db28eb0c8995 100644 --- a/drivers/mfd/tc3589x.c +++ b/drivers/mfd/tc3589x.c @@ -340,7 +340,7 @@ tc3589x_of_probe(struct device *dev, enum tc3589x_version *version) of_id = of_match_device(tc3589x_match, dev); if (!of_id) return ERR_PTR(-ENODEV); - *version = (enum tc3589x_version) of_id->data; + *version = (uintptr_t) of_id->data; for_each_child_of_node(np, child) { if (of_device_is_compatible(child, "toshiba,tc3589x-gpio")) @@ -483,7 +483,7 @@ static struct i2c_driver tc3589x_driver = { .driver = { .name = "tc3589x", .pm = pm_sleep_ptr(&tc3589x_dev_pm_ops), - .of_match_table = of_match_ptr(tc3589x_match), + .of_match_table = tc3589x_match, }, .probe = tc3589x_probe, .remove = tc3589x_remove, diff --git a/drivers/mfd/ti-lmu.c b/drivers/mfd/ti-lmu.c index 4f06adad7b5e..cfc9f88b9842 100644 --- a/drivers/mfd/ti-lmu.c +++ b/drivers/mfd/ti-lmu.c @@ -17,7 +17,6 @@ #include <linux/mfd/ti-lmu-register.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/slab.h> struct ti_lmu_data { diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index 07825cfd8aa8..b88eb70c17b3 100644 --- a/drivers/mfd/ti_am335x_tscadc.c +++ b/drivers/mfd/ti_am335x_tscadc.c @@ -14,7 +14,7 @@ #include <linux/mfd/core.h> #include <linux/pm_runtime.h> #include <linux/of.h> -#include <linux/of_device.h> +#include <linux/platform_device.h> #include <linux/sched.h> #include <linux/mfd/ti_am335x_tscadc.h> @@ -201,8 +201,7 @@ static int ti_tscadc_probe(struct platform_device *pdev) else tscadc->irq = err; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - tscadc->tscadc_base = devm_ioremap_resource(&pdev->dev, res); + tscadc->tscadc_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(tscadc->tscadc_base)) return PTR_ERR(tscadc->tscadc_base); diff --git a/drivers/mfd/tps6507x.c b/drivers/mfd/tps6507x.c index 9716bf703c7a..95dafb0e9f00 100644 --- a/drivers/mfd/tps6507x.c +++ b/drivers/mfd/tps6507x.c @@ -20,7 +20,6 @@ #include <linux/slab.h> #include <linux/i2c.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/mfd/core.h> #include <linux/mfd/tps6507x.h> diff --git a/drivers/mfd/tps65090.c b/drivers/mfd/tps65090.c index a35ad70755fb..9245e11219f3 100644 --- a/drivers/mfd/tps65090.c +++ b/drivers/mfd/tps65090.c @@ -17,7 +17,6 @@ #include <linux/mfd/core.h> #include <linux/mfd/tps65090.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/err.h> #define NUM_INT_REG 2 diff --git a/drivers/mfd/tps65217.c b/drivers/mfd/tps65217.c index 60599291b315..029ecc32f078 100644 --- a/drivers/mfd/tps65217.c +++ b/drivers/mfd/tps65217.c @@ -17,7 +17,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/slab.h> diff --git a/drivers/mfd/tps65218.c b/drivers/mfd/tps65218.c index 619bf7adb20c..11e4e52b56be 100644 --- a/drivers/mfd/tps65218.c +++ b/drivers/mfd/tps65218.c @@ -15,7 +15,6 @@ #include <linux/regmap.h> #include <linux/err.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/irq.h> #include <linux/interrupt.h> #include <linux/mutex.h> diff --git a/drivers/mfd/tps6594-core.c b/drivers/mfd/tps6594-core.c index 15f314833207..0fb9c5cf213a 100644 --- a/drivers/mfd/tps6594-core.c +++ b/drivers/mfd/tps6594-core.c @@ -9,7 +9,7 @@ #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/mfd/core.h> #include <linux/mfd/tps6594.h> diff --git a/drivers/mfd/twl6040.c b/drivers/mfd/twl6040.c index d85675a4d9a8..9ce34dfd99b3 100644 --- a/drivers/mfd/twl6040.c +++ b/drivers/mfd/twl6040.c @@ -16,8 +16,6 @@ #include <linux/err.h> #include <linux/platform_device.h> #include <linux/of.h> -#include <linux/of_irq.h> -#include <linux/of_platform.h> #include <linux/gpio/consumer.h> #include <linux/delay.h> #include <linux/i2c.h> diff --git a/drivers/mfd/wm5102-tables.c b/drivers/mfd/wm5102-tables.c index 6bba39657991..f77ecc635b6f 100644 --- a/drivers/mfd/wm5102-tables.c +++ b/drivers/mfd/wm5102-tables.c @@ -1938,7 +1938,7 @@ const struct regmap_config wm5102_i2c_regmap = { .readable_reg = wm5102_readable_register, .volatile_reg = wm5102_volatile_register, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .reg_defaults = wm5102_reg_default, .num_reg_defaults = ARRAY_SIZE(wm5102_reg_default), }; diff --git a/drivers/mfd/wm5110-tables.c b/drivers/mfd/wm5110-tables.c index 65b9b1d6daec..eba324875afd 100644 --- a/drivers/mfd/wm5110-tables.c +++ b/drivers/mfd/wm5110-tables.c @@ -3218,7 +3218,7 @@ const struct regmap_config wm5110_i2c_regmap = { .readable_reg = wm5110_readable_register, .volatile_reg = wm5110_volatile_register, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .reg_defaults = wm5110_reg_default, .num_reg_defaults = ARRAY_SIZE(wm5110_reg_default), }; diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c index e86b6a4896a6..e7e68929275e 100644 --- a/drivers/mfd/wm831x-core.c +++ b/drivers/mfd/wm831x-core.c @@ -15,8 +15,7 @@ #include <linux/mfd/core.h> #include <linux/slab.h> #include <linux/err.h> -#include <linux/of.h> -#include <linux/of_device.h> +#include <linux/mod_devicetable.h> #include <linux/mfd/wm831x/core.h> #include <linux/mfd/wm831x/pdata.h> diff --git a/drivers/mfd/wm831x-i2c.c b/drivers/mfd/wm831x-i2c.c index 997837f13180..694ddbbf0372 100644 --- a/drivers/mfd/wm831x-i2c.c +++ b/drivers/mfd/wm831x-i2c.c @@ -36,7 +36,7 @@ static int wm831x_i2c_probe(struct i2c_client *i2c) dev_err(&i2c->dev, "Failed to match device\n"); return -ENODEV; } - type = (enum wm831x_parent)of_id->data; + type = (uintptr_t)of_id->data; } else { type = (enum wm831x_parent)id->driver_data; } diff --git a/drivers/mfd/wm831x-spi.c b/drivers/mfd/wm831x-spi.c index 7bcddccbf155..76be7ef5c970 100644 --- a/drivers/mfd/wm831x-spi.c +++ b/drivers/mfd/wm831x-spi.c @@ -33,7 +33,7 @@ static int wm831x_spi_probe(struct spi_device *spi) dev_err(&spi->dev, "Failed to match device\n"); return -ENODEV; } - type = (enum wm831x_parent)of_id->data; + type = (uintptr_t)of_id->data; } else { type = (enum wm831x_parent)id->driver_data; } diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c index 1e4f1694f065..aba7af688175 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c @@ -628,7 +628,7 @@ static int wm8994_i2c_probe(struct i2c_client *i2c) if (i2c->dev.of_node) { of_id = of_match_device(wm8994_of_match, &i2c->dev); if (of_id) - wm8994->type = (enum wm8994_type)of_id->data; + wm8994->type = (uintptr_t)of_id->data; } else { wm8994->type = id->driver_data; } diff --git a/drivers/mfd/wm8994-regmap.c b/drivers/mfd/wm8994-regmap.c index cd4fef7df336..ee2ed6773afd 100644 --- a/drivers/mfd/wm8994-regmap.c +++ b/drivers/mfd/wm8994-regmap.c @@ -1238,7 +1238,7 @@ struct regmap_config wm1811_regmap_config = { .reg_bits = 16, .val_bits = 16, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .reg_defaults = wm1811_defaults, .num_reg_defaults = ARRAY_SIZE(wm1811_defaults), @@ -1253,7 +1253,7 @@ struct regmap_config wm8994_regmap_config = { .reg_bits = 16, .val_bits = 16, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .reg_defaults = wm8994_defaults, .num_reg_defaults = ARRAY_SIZE(wm8994_defaults), @@ -1268,7 +1268,7 @@ struct regmap_config wm8958_regmap_config = { .reg_bits = 16, .val_bits = 16, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .reg_defaults = wm8958_defaults, .num_reg_defaults = ARRAY_SIZE(wm8958_defaults), diff --git a/drivers/mfd/wm8997-tables.c b/drivers/mfd/wm8997-tables.c index 3476787c485e..288c57b2d21e 100644 --- a/drivers/mfd/wm8997-tables.c +++ b/drivers/mfd/wm8997-tables.c @@ -1523,7 +1523,7 @@ const struct regmap_config wm8997_i2c_regmap = { .readable_reg = wm8997_readable_register, .volatile_reg = wm8997_volatile_register, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .reg_defaults = wm8997_reg_default, .num_reg_defaults = ARRAY_SIZE(wm8997_reg_default), }; diff --git a/drivers/mfd/wm8998-tables.c b/drivers/mfd/wm8998-tables.c index 9b34a6d76094..b3e6e85bee89 100644 --- a/drivers/mfd/wm8998-tables.c +++ b/drivers/mfd/wm8998-tables.c @@ -1556,7 +1556,7 @@ const struct regmap_config wm8998_i2c_regmap = { .readable_reg = wm8998_readable_register, .volatile_reg = wm8998_volatile_register, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .reg_defaults = wm8998_reg_default, .num_reg_defaults = ARRAY_SIZE(wm8998_reg_default), }; diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index 153fb8d0008e..df589d9b4d70 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -32,7 +32,6 @@ #include <linux/interrupt.h> #include <linux/reboot.h> #include <linux/of.h> -#include <linux/of_platform.h> #include <linux/mtd/map.h> #include <linux/mtd/mtd.h> #include <linux/mtd/cfi.h> @@ -650,7 +649,7 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) /* * Valid primary extension versions are: 1.0, 1.1, 1.2, 1.3, 1.4, 1.5 - * see: http://cs.ozerki.net/zap/pub/axim-x5/docs/cfi_r20.pdf, page 19 + * see: http://cs.ozerki.net/zap/pub/axim-x5/docs/cfi_r20.pdf, page 19 * http://www.spansion.com/Support/AppNotes/cfi_100_20011201.pdf * http://www.spansion.com/Support/Datasheets/s29ws-p_00_a12_e.pdf * http://www.spansion.com/Support/Datasheets/S29GL_128S_01GS_00_02_e.pdf diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 231ad91a919d..fe7f314d65c9 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -132,6 +132,14 @@ struct virtnet_interrupt_coalesce { u32 max_usecs; }; +/* The dma information of pages allocated at a time. */ +struct virtnet_rq_dma { + dma_addr_t addr; + u32 ref; + u16 len; + u16 need_sync; +}; + /* Internal representation of a send virtqueue */ struct send_queue { /* Virtqueue associated with this send _queue */ @@ -185,6 +193,12 @@ struct receive_queue { char name[16]; struct xdp_rxq_info xdp_rxq; + + /* Record the last dma info to free after new pages is allocated. */ + struct virtnet_rq_dma *last_dma; + + /* Do dma by self */ + bool do_dma; }; /* This structure can contain rss message with maximum settings for indirection table and keysize @@ -580,6 +594,156 @@ ok: return skb; } +static void virtnet_rq_unmap(struct receive_queue *rq, void *buf, u32 len) +{ + struct page *page = virt_to_head_page(buf); + struct virtnet_rq_dma *dma; + void *head; + int offset; + + head = page_address(page); + + dma = head; + + --dma->ref; + + if (dma->ref) { + if (dma->need_sync && len) { + offset = buf - (head + sizeof(*dma)); + + virtqueue_dma_sync_single_range_for_cpu(rq->vq, dma->addr, offset, + len, DMA_FROM_DEVICE); + } + + return; + } + + virtqueue_dma_unmap_single_attrs(rq->vq, dma->addr, dma->len, + DMA_FROM_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); + put_page(page); +} + +static void *virtnet_rq_get_buf(struct receive_queue *rq, u32 *len, void **ctx) +{ + void *buf; + + buf = virtqueue_get_buf_ctx(rq->vq, len, ctx); + if (buf && rq->do_dma) + virtnet_rq_unmap(rq, buf, *len); + + return buf; +} + +static void *virtnet_rq_detach_unused_buf(struct receive_queue *rq) +{ + void *buf; + + buf = virtqueue_detach_unused_buf(rq->vq); + if (buf && rq->do_dma) + virtnet_rq_unmap(rq, buf, 0); + + return buf; +} + +static void virtnet_rq_init_one_sg(struct receive_queue *rq, void *buf, u32 len) +{ + struct virtnet_rq_dma *dma; + dma_addr_t addr; + u32 offset; + void *head; + + if (!rq->do_dma) { + sg_init_one(rq->sg, buf, len); + return; + } + + head = page_address(rq->alloc_frag.page); + + offset = buf - head; + + dma = head; + + addr = dma->addr - sizeof(*dma) + offset; + + sg_init_table(rq->sg, 1); + rq->sg[0].dma_address = addr; + rq->sg[0].length = len; +} + +static void *virtnet_rq_alloc(struct receive_queue *rq, u32 size, gfp_t gfp) +{ + struct page_frag *alloc_frag = &rq->alloc_frag; + struct virtnet_rq_dma *dma; + void *buf, *head; + dma_addr_t addr; + + if (unlikely(!skb_page_frag_refill(size, alloc_frag, gfp))) + return NULL; + + head = page_address(alloc_frag->page); + + if (rq->do_dma) { + dma = head; + + /* new pages */ + if (!alloc_frag->offset) { + if (rq->last_dma) { + /* Now, the new page is allocated, the last dma + * will not be used. So the dma can be unmapped + * if the ref is 0. + */ + virtnet_rq_unmap(rq, rq->last_dma, 0); + rq->last_dma = NULL; + } + + dma->len = alloc_frag->size - sizeof(*dma); + + addr = virtqueue_dma_map_single_attrs(rq->vq, dma + 1, + dma->len, DMA_FROM_DEVICE, 0); + if (virtqueue_dma_mapping_error(rq->vq, addr)) + return NULL; + + dma->addr = addr; + dma->need_sync = virtqueue_dma_need_sync(rq->vq, addr); + + /* Add a reference to dma to prevent the entire dma from + * being released during error handling. This reference + * will be freed after the pages are no longer used. + */ + get_page(alloc_frag->page); + dma->ref = 1; + alloc_frag->offset = sizeof(*dma); + + rq->last_dma = dma; + } + + ++dma->ref; + } + + buf = head + alloc_frag->offset; + + get_page(alloc_frag->page); + alloc_frag->offset += size; + + return buf; +} + +static void virtnet_rq_set_premapped(struct virtnet_info *vi) +{ + int i; + + /* disable for big mode */ + if (!vi->mergeable_rx_bufs && vi->big_packets) + return; + + for (i = 0; i < vi->max_queue_pairs; i++) { + if (virtqueue_set_dma_premapped(vi->rq[i].vq)) + continue; + + vi->rq[i].do_dma = true; + } +} + static void free_old_xmit_skbs(struct send_queue *sq, bool in_napi) { unsigned int len; @@ -935,7 +1099,7 @@ static struct page *xdp_linearize_page(struct receive_queue *rq, void *buf; int off; - buf = virtqueue_get_buf(rq->vq, &buflen); + buf = virtnet_rq_get_buf(rq, &buflen, NULL); if (unlikely(!buf)) goto err_buf; @@ -1155,7 +1319,7 @@ static void mergeable_buf_free(struct receive_queue *rq, int num_buf, int len; while (num_buf-- > 1) { - buf = virtqueue_get_buf(rq->vq, &len); + buf = virtnet_rq_get_buf(rq, &len, NULL); if (unlikely(!buf)) { pr_debug("%s: rx error: %d buffers missing\n", dev->name, num_buf); @@ -1263,7 +1427,7 @@ static int virtnet_build_xdp_buff_mrg(struct net_device *dev, return -EINVAL; while (--*num_buf > 0) { - buf = virtqueue_get_buf_ctx(rq->vq, &len, &ctx); + buf = virtnet_rq_get_buf(rq, &len, &ctx); if (unlikely(!buf)) { pr_debug("%s: rx error: %d buffers out of %d missing\n", dev->name, *num_buf, @@ -1492,7 +1656,7 @@ static struct sk_buff *receive_mergeable(struct net_device *dev, while (--num_buf) { int num_skb_frags; - buf = virtqueue_get_buf_ctx(rq->vq, &len, &ctx); + buf = virtnet_rq_get_buf(rq, &len, &ctx); if (unlikely(!buf)) { pr_debug("%s: rx error: %d buffers out of %d missing\n", dev->name, num_buf, @@ -1651,7 +1815,6 @@ frame_err: static int add_recvbuf_small(struct virtnet_info *vi, struct receive_queue *rq, gfp_t gfp) { - struct page_frag *alloc_frag = &rq->alloc_frag; char *buf; unsigned int xdp_headroom = virtnet_get_headroom(vi); void *ctx = (void *)(unsigned long)xdp_headroom; @@ -1660,17 +1823,21 @@ static int add_recvbuf_small(struct virtnet_info *vi, struct receive_queue *rq, len = SKB_DATA_ALIGN(len) + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); - if (unlikely(!skb_page_frag_refill(len, alloc_frag, gfp))) + + buf = virtnet_rq_alloc(rq, len, gfp); + if (unlikely(!buf)) return -ENOMEM; - buf = (char *)page_address(alloc_frag->page) + alloc_frag->offset; - get_page(alloc_frag->page); - alloc_frag->offset += len; - sg_init_one(rq->sg, buf + VIRTNET_RX_PAD + xdp_headroom, - vi->hdr_len + GOOD_PACKET_LEN); + virtnet_rq_init_one_sg(rq, buf + VIRTNET_RX_PAD + xdp_headroom, + vi->hdr_len + GOOD_PACKET_LEN); + err = virtqueue_add_inbuf_ctx(rq->vq, rq->sg, 1, buf, ctx, gfp); - if (err < 0) + if (err < 0) { + if (rq->do_dma) + virtnet_rq_unmap(rq, buf, 0); put_page(virt_to_head_page(buf)); + } + return err; } @@ -1747,23 +1914,22 @@ static int add_recvbuf_mergeable(struct virtnet_info *vi, unsigned int headroom = virtnet_get_headroom(vi); unsigned int tailroom = headroom ? sizeof(struct skb_shared_info) : 0; unsigned int room = SKB_DATA_ALIGN(headroom + tailroom); - char *buf; + unsigned int len, hole; void *ctx; + char *buf; int err; - unsigned int len, hole; /* Extra tailroom is needed to satisfy XDP's assumption. This * means rx frags coalescing won't work, but consider we've * disabled GSO for XDP, it won't be a big issue. */ len = get_mergeable_buf_len(rq, &rq->mrg_avg_pkt_len, room); - if (unlikely(!skb_page_frag_refill(len + room, alloc_frag, gfp))) + + buf = virtnet_rq_alloc(rq, len + room, gfp); + if (unlikely(!buf)) return -ENOMEM; - buf = (char *)page_address(alloc_frag->page) + alloc_frag->offset; buf += headroom; /* advance address leaving hole at front of pkt */ - get_page(alloc_frag->page); - alloc_frag->offset += len + room; hole = alloc_frag->size - alloc_frag->offset; if (hole < len + room) { /* To avoid internal fragmentation, if there is very likely not @@ -1777,11 +1943,15 @@ static int add_recvbuf_mergeable(struct virtnet_info *vi, alloc_frag->offset += hole; } - sg_init_one(rq->sg, buf, len); + virtnet_rq_init_one_sg(rq, buf, len); + ctx = mergeable_len_to_ctx(len + room, headroom); err = virtqueue_add_inbuf_ctx(rq->vq, rq->sg, 1, buf, ctx, gfp); - if (err < 0) + if (err < 0) { + if (rq->do_dma) + virtnet_rq_unmap(rq, buf, 0); put_page(virt_to_head_page(buf)); + } return err; } @@ -1902,13 +2072,13 @@ static int virtnet_receive(struct receive_queue *rq, int budget, void *ctx; while (stats.packets < budget && - (buf = virtqueue_get_buf_ctx(rq->vq, &len, &ctx))) { + (buf = virtnet_rq_get_buf(rq, &len, &ctx))) { receive_buf(vi, rq, buf, len, ctx, xdp_xmit, &stats); stats.packets++; } } else { while (stats.packets < budget && - (buf = virtqueue_get_buf(rq->vq, &len)) != NULL) { + (buf = virtnet_rq_get_buf(rq, &len, NULL)) != NULL) { receive_buf(vi, rq, buf, len, NULL, xdp_xmit, &stats); stats.packets++; } @@ -3808,8 +3978,11 @@ static void free_receive_page_frags(struct virtnet_info *vi) { int i; for (i = 0; i < vi->max_queue_pairs; i++) - if (vi->rq[i].alloc_frag.page) + if (vi->rq[i].alloc_frag.page) { + if (vi->rq[i].do_dma && vi->rq[i].last_dma) + virtnet_rq_unmap(&vi->rq[i], vi->rq[i].last_dma, 0); put_page(vi->rq[i].alloc_frag.page); + } } static void virtnet_sq_free_unused_buf(struct virtqueue *vq, void *buf) @@ -3846,9 +4019,10 @@ static void free_unused_bufs(struct virtnet_info *vi) } for (i = 0; i < vi->max_queue_pairs; i++) { - struct virtqueue *vq = vi->rq[i].vq; - while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) - virtnet_rq_free_unused_buf(vq, buf); + struct receive_queue *rq = &vi->rq[i]; + + while ((buf = virtnet_rq_detach_unused_buf(rq)) != NULL) + virtnet_rq_free_unused_buf(rq->vq, buf); cond_resched(); } } @@ -4022,6 +4196,8 @@ static int init_vqs(struct virtnet_info *vi) if (ret) goto err_free; + virtnet_rq_set_premapped(vi); + cpus_read_lock(); virtnet_set_affinity(vi); cpus_read_unlock(); diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 6210babb0741..8ebcddf91f7b 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -505,7 +505,7 @@ config PWM_ROCKCHIP config PWM_RZ_MTU3 tristate "Renesas RZ/G2L MTU3a PWM Timer support" - depends on RZ_MTU3 || COMPILE_TEST + depends on RZ_MTU3 depends on HAS_IOMEM help This driver exposes the MTU3a PWM Timer controller found in Renesas diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c index d95fa5586189..8fcda9b74545 100644 --- a/drivers/remoteproc/imx_dsp_rproc.c +++ b/drivers/remoteproc/imx_dsp_rproc.c @@ -12,8 +12,7 @@ #include <linux/mailbox_client.h> #include <linux/mfd/syscon.h> #include <linux/module.h> -#include <linux/of_address.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/of_reserved_mem.h> #include <linux/platform_device.h> #include <linux/pm_domain.h> diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c index f9874fc5a80f..8bb293b9f327 100644 --- a/drivers/remoteproc/imx_rproc.c +++ b/drivers/remoteproc/imx_rproc.c @@ -13,9 +13,9 @@ #include <linux/mailbox_client.h> #include <linux/mfd/syscon.h> #include <linux/module.h> +#include <linux/of.h> #include <linux/of_address.h> #include <linux/of_reserved_mem.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/pm_domain.h> #include <linux/regmap.h> @@ -40,6 +40,12 @@ #define IMX7D_M4_STOP (IMX7D_ENABLE_M4 | IMX7D_SW_M4C_RST | \ IMX7D_SW_M4C_NON_SCLR_RST) +#define IMX8M_M7_STOP (IMX7D_ENABLE_M4 | IMX7D_SW_M4C_RST) +#define IMX8M_M7_POLL IMX7D_ENABLE_M4 + +#define IMX8M_GPR22 0x58 +#define IMX8M_GPR22_CM7_CPUWAIT BIT(0) + /* Address: 0x020D8000 */ #define IMX6SX_SRC_SCR 0x00 #define IMX6SX_ENABLE_M4 BIT(22) @@ -91,6 +97,7 @@ static int imx_rproc_detach_pd(struct rproc *rproc); struct imx_rproc { struct device *dev; struct regmap *regmap; + struct regmap *gpr; struct rproc *rproc; const struct imx_rproc_dcfg *dcfg; struct imx_rproc_mem mem[IMX_RPROC_MEM_MAX]; @@ -285,6 +292,18 @@ static const struct imx_rproc_att imx_rproc_att_imx6sx[] = { { 0x80000000, 0x80000000, 0x60000000, 0 }, }; +static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mn_mmio = { + .src_reg = IMX7D_SRC_SCR, + .src_mask = IMX7D_M4_RST_MASK, + .src_start = IMX7D_M4_START, + .src_stop = IMX8M_M7_STOP, + .gpr_reg = IMX8M_GPR22, + .gpr_wait = IMX8M_GPR22_CM7_CPUWAIT, + .att = imx_rproc_att_imx8mn, + .att_size = ARRAY_SIZE(imx_rproc_att_imx8mn), + .method = IMX_RPROC_MMIO, +}; + static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mn = { .att = imx_rproc_att_imx8mn, .att_size = ARRAY_SIZE(imx_rproc_att_imx8mn), @@ -365,8 +384,14 @@ static int imx_rproc_start(struct rproc *rproc) switch (dcfg->method) { case IMX_RPROC_MMIO: - ret = regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask, - dcfg->src_start); + if (priv->gpr) { + ret = regmap_clear_bits(priv->gpr, dcfg->gpr_reg, + dcfg->gpr_wait); + } else { + ret = regmap_update_bits(priv->regmap, dcfg->src_reg, + dcfg->src_mask, + dcfg->src_start); + } break; case IMX_RPROC_SMC: arm_smccc_smc(IMX_SIP_RPROC, IMX_SIP_RPROC_START, 0, 0, 0, 0, 0, 0, &res); @@ -395,6 +420,16 @@ static int imx_rproc_stop(struct rproc *rproc) switch (dcfg->method) { case IMX_RPROC_MMIO: + if (priv->gpr) { + ret = regmap_set_bits(priv->gpr, dcfg->gpr_reg, + dcfg->gpr_wait); + if (ret) { + dev_err(priv->dev, + "Failed to quiescence M4 platform!\n"); + return ret; + } + } + ret = regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask, dcfg->src_stop); break; @@ -725,13 +760,22 @@ static int imx_rproc_addr_init(struct imx_rproc *priv, return 0; } +static int imx_rproc_notified_idr_cb(int id, void *ptr, void *data) +{ + struct rproc *rproc = data; + + rproc_vq_interrupt(rproc, id); + + return 0; +} + static void imx_rproc_vq_work(struct work_struct *work) { struct imx_rproc *priv = container_of(work, struct imx_rproc, rproc_work); + struct rproc *rproc = priv->rproc; - rproc_vq_interrupt(priv->rproc, 0); - rproc_vq_interrupt(priv->rproc, 1); + idr_for_each(&rproc->notifyids, imx_rproc_notified_idr_cb, rproc); } static void imx_rproc_rx_callback(struct mbox_client *cl, void *msg) @@ -983,6 +1027,10 @@ static int imx_rproc_detect_mode(struct imx_rproc *priv) break; } + priv->gpr = syscon_regmap_lookup_by_phandle(dev->of_node, "fsl,iomuxc-gpr"); + if (IS_ERR(priv->gpr)) + priv->gpr = NULL; + regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon"); if (IS_ERR(regmap)) { dev_err(dev, "failed to find syscon\n"); @@ -992,6 +1040,19 @@ static int imx_rproc_detect_mode(struct imx_rproc *priv) priv->regmap = regmap; regmap_attach_dev(dev, regmap, &config); + if (priv->gpr) { + ret = regmap_read(priv->gpr, dcfg->gpr_reg, &val); + if (val & dcfg->gpr_wait) { + /* + * After cold boot, the CM indicates its in wait + * state, but not fully powered off. Power it off + * fully so firmware can be loaded into it. + */ + imx_rproc_stop(priv->rproc); + return 0; + } + } + ret = regmap_read(regmap, dcfg->src_reg, &val); if (ret) { dev_err(dev, "Failed to read src\n"); @@ -1133,6 +1194,8 @@ static const struct of_device_id imx_rproc_of_match[] = { { .compatible = "fsl,imx8mm-cm4", .data = &imx_rproc_cfg_imx8mq }, { .compatible = "fsl,imx8mn-cm7", .data = &imx_rproc_cfg_imx8mn }, { .compatible = "fsl,imx8mp-cm7", .data = &imx_rproc_cfg_imx8mn }, + { .compatible = "fsl,imx8mn-cm7-mmio", .data = &imx_rproc_cfg_imx8mn_mmio }, + { .compatible = "fsl,imx8mp-cm7-mmio", .data = &imx_rproc_cfg_imx8mn_mmio }, { .compatible = "fsl,imx8qxp-cm4", .data = &imx_rproc_cfg_imx8qxp }, { .compatible = "fsl,imx8qm-cm4", .data = &imx_rproc_cfg_imx8qm }, { .compatible = "fsl,imx8ulp-cm33", .data = &imx_rproc_cfg_imx8ulp }, diff --git a/drivers/remoteproc/imx_rproc.h b/drivers/remoteproc/imx_rproc.h index 1c7e2127c758..79a1b8956d14 100644 --- a/drivers/remoteproc/imx_rproc.h +++ b/drivers/remoteproc/imx_rproc.h @@ -31,6 +31,8 @@ struct imx_rproc_dcfg { u32 src_mask; u32 src_start; u32 src_stop; + u32 gpr_reg; + u32 gpr_wait; const struct imx_rproc_att *att; size_t att_size; enum imx_rproc_method method; diff --git a/drivers/remoteproc/omap_remoteproc.c b/drivers/remoteproc/omap_remoteproc.c index 82ed90f03d91..8f50ab80e56f 100644 --- a/drivers/remoteproc/omap_remoteproc.c +++ b/drivers/remoteproc/omap_remoteproc.c @@ -19,7 +19,8 @@ #include <linux/clk/ti.h> #include <linux/err.h> #include <linux/io.h> -#include <linux/of_device.h> +#include <linux/of.h> +#include <linux/of_platform.h> #include <linux/of_reserved_mem.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> diff --git a/drivers/remoteproc/pru_rproc.c b/drivers/remoteproc/pru_rproc.c index 2874c8d324f7..327f0c7ee3d6 100644 --- a/drivers/remoteproc/pru_rproc.c +++ b/drivers/remoteproc/pru_rproc.c @@ -16,8 +16,9 @@ #include <linux/debugfs.h> #include <linux/irqdomain.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/of_irq.h> +#include <linux/platform_device.h> #include <linux/remoteproc/pruss.h> #include <linux/pruss_driver.h> #include <linux/remoteproc.h> @@ -109,6 +110,7 @@ struct pru_private_data { * @dbg_single_step: debug state variable to set PRU into single step mode * @dbg_continuous: debug state variable to restore PRU execution mode * @evt_count: number of mapped events + * @gpmux_save: saved value for gpmux config */ struct pru_rproc { int id; @@ -127,6 +129,7 @@ struct pru_rproc { u32 dbg_single_step; u32 dbg_continuous; u8 evt_count; + u8 gpmux_save; }; static inline u32 pru_control_read_reg(struct pru_rproc *pru, unsigned int reg) @@ -228,6 +231,7 @@ struct rproc *pru_rproc_get(struct device_node *np, int index, struct device *dev; const char *fw_name; int ret; + u32 mux; rproc = __pru_rproc_get(np, index); if (IS_ERR(rproc)) @@ -252,6 +256,23 @@ struct rproc *pru_rproc_get(struct device_node *np, int index, if (pru_id) *pru_id = pru->id; + ret = pruss_cfg_get_gpmux(pru->pruss, pru->id, &pru->gpmux_save); + if (ret) { + dev_err(dev, "failed to get cfg gpmux: %d\n", ret); + goto err; + } + + /* An error here is acceptable for backward compatibility */ + ret = of_property_read_u32_index(np, "ti,pruss-gp-mux-sel", index, + &mux); + if (!ret) { + ret = pruss_cfg_set_gpmux(pru->pruss, pru->id, mux); + if (ret) { + dev_err(dev, "failed to set cfg gpmux: %d\n", ret); + goto err; + } + } + ret = of_property_read_string_index(np, "firmware-name", index, &fw_name); if (!ret) { @@ -290,6 +311,8 @@ void pru_rproc_put(struct rproc *rproc) pru = rproc->priv; + pruss_cfg_set_gpmux(pru->pruss, pru->id, pru->gpmux_save); + pru_rproc_set_firmware(rproc, NULL); mutex_lock(&pru->lock); diff --git a/drivers/remoteproc/qcom_common.c b/drivers/remoteproc/qcom_common.c index a0d4238492e9..03e5f5d533eb 100644 --- a/drivers/remoteproc/qcom_common.c +++ b/drivers/remoteproc/qcom_common.c @@ -29,9 +29,9 @@ #define MAX_NUM_OF_SS 10 #define MAX_REGION_NAME_LENGTH 16 #define SBL_MINIDUMP_SMEM_ID 602 -#define MD_REGION_VALID ('V' << 24 | 'A' << 16 | 'L' << 8 | 'I' << 0) -#define MD_SS_ENCR_DONE ('D' << 24 | 'O' << 16 | 'N' << 8 | 'E' << 0) -#define MD_SS_ENABLED ('E' << 24 | 'N' << 16 | 'B' << 8 | 'L' << 0) +#define MINIDUMP_REGION_VALID ('V' << 24 | 'A' << 16 | 'L' << 8 | 'I' << 0) +#define MINIDUMP_SS_ENCR_DONE ('D' << 24 | 'O' << 16 | 'N' << 8 | 'E' << 0) +#define MINIDUMP_SS_ENABLED ('E' << 24 | 'N' << 16 | 'B' << 8 | 'L' << 0) /** * struct minidump_region - Minidump region @@ -125,7 +125,7 @@ static int qcom_add_minidump_segments(struct rproc *rproc, struct minidump_subsy for (i = 0; i < seg_cnt; i++) { memcpy_fromio(®ion, ptr + i, sizeof(region)); - if (le32_to_cpu(region.valid) == MD_REGION_VALID) { + if (le32_to_cpu(region.valid) == MINIDUMP_REGION_VALID) { name = kstrndup(region.name, MAX_REGION_NAME_LENGTH - 1, GFP_KERNEL); if (!name) { iounmap(ptr); @@ -168,12 +168,21 @@ void qcom_minidump(struct rproc *rproc, unsigned int minidump_id, */ if (subsystem->regions_baseptr == 0 || le32_to_cpu(subsystem->status) != 1 || - le32_to_cpu(subsystem->enabled) != MD_SS_ENABLED || - le32_to_cpu(subsystem->encryption_status) != MD_SS_ENCR_DONE) { + le32_to_cpu(subsystem->enabled) != MINIDUMP_SS_ENABLED) { + return rproc_coredump(rproc); + } + + if (le32_to_cpu(subsystem->encryption_status) != MINIDUMP_SS_ENCR_DONE) { dev_err(&rproc->dev, "Minidump not ready, skipping\n"); return; } + /** + * Clear out the dump segments populated by parse_fw before + * re-populating them with minidump segments. + */ + rproc_coredump_cleanup(rproc); + ret = qcom_add_minidump_segments(rproc, subsystem, rproc_dumpfn_t); if (ret) { dev_err(&rproc->dev, "Failed with error: %d while adding minidump entries\n", ret); diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c index 6777a3bd6226..6c67514cc493 100644 --- a/drivers/remoteproc/qcom_q6v5_adsp.c +++ b/drivers/remoteproc/qcom_q6v5_adsp.c @@ -14,8 +14,8 @@ #include <linux/kernel.h> #include <linux/mfd/syscon.h> #include <linux/module.h> -#include <linux/of_address.h> -#include <linux/of_device.h> +#include <linux/of.h> +#include <linux/of_reserved_mem.h> #include <linux/platform_device.h> #include <linux/pm_domain.h> #include <linux/pm_runtime.h> @@ -637,28 +637,26 @@ static int adsp_init_mmio(struct qcom_adsp *adsp, static int adsp_alloc_memory_region(struct qcom_adsp *adsp) { + struct reserved_mem *rmem = NULL; struct device_node *node; - struct resource r; - int ret; node = of_parse_phandle(adsp->dev->of_node, "memory-region", 0); - if (!node) { - dev_err(adsp->dev, "no memory-region specified\n"); + if (node) + rmem = of_reserved_mem_lookup(node); + of_node_put(node); + + if (!rmem) { + dev_err(adsp->dev, "unable to resolve memory-region\n"); return -EINVAL; } - ret = of_address_to_resource(node, 0, &r); - of_node_put(node); - if (ret) - return ret; - - adsp->mem_phys = adsp->mem_reloc = r.start; - adsp->mem_size = resource_size(&r); + adsp->mem_phys = adsp->mem_reloc = rmem->base; + adsp->mem_size = rmem->size; adsp->mem_region = devm_ioremap_wc(adsp->dev, adsp->mem_phys, adsp->mem_size); if (!adsp->mem_region) { dev_err(adsp->dev, "unable to map memory region: %pa+%zx\n", - &r.start, adsp->mem_size); + &rmem->base, adsp->mem_size); return -EBUSY; } diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c index 70bffc9f33f6..22fe7b5f5236 100644 --- a/drivers/remoteproc/qcom_q6v5_mss.c +++ b/drivers/remoteproc/qcom_q6v5_mss.c @@ -15,9 +15,9 @@ #include <linux/kernel.h> #include <linux/mfd/syscon.h> #include <linux/module.h> -#include <linux/of_address.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/of_reserved_mem.h> +#include <linux/of_platform.h> #include <linux/platform_device.h> #include <linux/pm_domain.h> #include <linux/pm_runtime.h> @@ -71,6 +71,7 @@ #define QDSP6SS_MEM_PWR_CTL 0x0B0 #define QDSP6V6SS_MEM_PWR_CTL 0x034 #define QDSP6SS_STRAP_ACC 0x110 +#define QDSP6V62SS_BHS_STATUS 0x0C4 /* AXI Halt Register Offsets */ #define AXI_HALTREQ_REG 0x0 @@ -123,6 +124,7 @@ #define QDSP6v56_CLAMP_QMC_MEM BIT(22) #define QDSP6SS_XO_CBCR 0x0038 #define QDSP6SS_ACC_OVERRIDE_VAL 0x20 +#define QDSP6v55_BHS_EN_REST_ACK BIT(0) /* QDSP6v65 parameters */ #define QDSP6SS_CORE_CBCR 0x20 @@ -130,6 +132,7 @@ #define QDSP6SS_BOOT_CORE_START 0x400 #define QDSP6SS_BOOT_CMD 0x404 #define BOOT_FSM_TIMEOUT 10000 +#define BHS_CHECK_MAX_LOOPS 200 struct reg_info { struct regulator *reg; @@ -250,6 +253,7 @@ enum { MSS_MSM8998, MSS_SC7180, MSS_SC7280, + MSS_SDM660, MSS_SDM845, }; @@ -700,7 +704,8 @@ static int q6v5proc_reset(struct q6v5 *qproc) } else if (qproc->version == MSS_MSM8909 || qproc->version == MSS_MSM8953 || qproc->version == MSS_MSM8996 || - qproc->version == MSS_MSM8998) { + qproc->version == MSS_MSM8998 || + qproc->version == MSS_SDM660) { if (qproc->version != MSS_MSM8909 && qproc->version != MSS_MSM8953) @@ -734,6 +739,16 @@ static int q6v5proc_reset(struct q6v5 *qproc) val |= readl(qproc->reg_base + QDSP6SS_PWR_CTL_REG); udelay(1); + if (qproc->version == MSS_SDM660) { + ret = readl_relaxed_poll_timeout(qproc->reg_base + QDSP6V62SS_BHS_STATUS, + i, (i & QDSP6v55_BHS_EN_REST_ACK), + 1, BHS_CHECK_MAX_LOOPS); + if (ret == -ETIMEDOUT) { + dev_err(qproc->dev, "BHS_EN_REST_ACK not set!\n"); + return -ETIMEDOUT; + } + } + /* Put LDO in bypass mode */ val |= QDSP6v56_LDO_BYP; writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG); @@ -756,7 +771,7 @@ static int q6v5proc_reset(struct q6v5 *qproc) mem_pwr_ctl = QDSP6SS_MEM_PWR_CTL; i = 19; } else { - /* MSS_MSM8998 */ + /* MSS_MSM8998, MSS_SDM660 */ mem_pwr_ctl = QDSP6V6SS_MEM_PWR_CTL; i = 28; } @@ -1875,8 +1890,6 @@ static int q6v5_alloc_memory_region(struct q6v5 *qproc) struct device_node *child; struct reserved_mem *rmem; struct device_node *node; - struct resource r; - int ret; /* * In the absence of mba/mpss sub-child, extract the mba and mpss @@ -1891,15 +1904,20 @@ static int q6v5_alloc_memory_region(struct q6v5 *qproc) of_node_put(child); } - ret = of_address_to_resource(node, 0, &r); + if (!node) { + dev_err(qproc->dev, "no mba memory-region specified\n"); + return -EINVAL; + } + + rmem = of_reserved_mem_lookup(node); of_node_put(node); - if (ret) { + if (!rmem) { dev_err(qproc->dev, "unable to resolve mba region\n"); - return ret; + return -EINVAL; } - qproc->mba_phys = r.start; - qproc->mba_size = resource_size(&r); + qproc->mba_phys = rmem->base; + qproc->mba_size = rmem->size; if (!child) { node = of_parse_phandle(qproc->dev->of_node, @@ -1910,15 +1928,20 @@ static int q6v5_alloc_memory_region(struct q6v5 *qproc) of_node_put(child); } - ret = of_address_to_resource(node, 0, &r); + if (!node) { + dev_err(qproc->dev, "no mpss memory-region specified\n"); + return -EINVAL; + } + + rmem = of_reserved_mem_lookup(node); of_node_put(node); - if (ret) { + if (!rmem) { dev_err(qproc->dev, "unable to resolve mpss region\n"); - return ret; + return -EINVAL; } - qproc->mpss_phys = qproc->mpss_reloc = r.start; - qproc->mpss_size = resource_size(&r); + qproc->mpss_phys = qproc->mpss_reloc = rmem->base; + qproc->mpss_size = rmem->size; if (!child) { node = of_parse_phandle(qproc->dev->of_node, "memory-region", 2); @@ -2191,6 +2214,37 @@ static const struct rproc_hexagon_res sc7280_mss = { .version = MSS_SC7280, }; +static const struct rproc_hexagon_res sdm660_mss = { + .hexagon_mba_image = "mba.mbn", + .proxy_clk_names = (char*[]){ + "xo", + "qdss", + "mem", + NULL + }, + .active_clk_names = (char*[]){ + "iface", + "bus", + "gpll0_mss", + "mnoc_axi", + "snoc_axi", + NULL + }, + .proxy_pd_names = (char*[]){ + "cx", + "mx", + NULL + }, + .need_mem_protection = true, + .has_alt_reset = false, + .has_mba_logs = false, + .has_spare_reg = false, + .has_qaccept_regs = false, + .has_ext_cntl_regs = false, + .has_vq6 = false, + .version = MSS_SDM660, +}; + static const struct rproc_hexagon_res sdm845_mss = { .hexagon_mba_image = "mba.mbn", .proxy_clk_names = (char*[]){ @@ -2473,6 +2527,7 @@ static const struct of_device_id q6v5_of_match[] = { { .compatible = "qcom,msm8998-mss-pil", .data = &msm8998_mss}, { .compatible = "qcom,sc7180-mss-pil", .data = &sc7180_mss}, { .compatible = "qcom,sc7280-mss-pil", .data = &sc7280_mss}, + { .compatible = "qcom,sdm660-mss-pil", .data = &sdm660_mss}, { .compatible = "qcom,sdm845-mss-pil", .data = &sdm845_mss}, { }, }; diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c index 3153d82037e7..b5447dd2dd35 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -13,8 +13,9 @@ #include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/module.h> +#include <linux/of.h> #include <linux/of_address.h> -#include <linux/of_device.h> +#include <linux/of_reserved_mem.h> #include <linux/platform_device.h> #include <linux/pm_domain.h> #include <linux/pm_runtime.h> @@ -425,6 +426,7 @@ static const struct rproc_ops adsp_minidump_ops = { .start = adsp_start, .stop = adsp_stop, .da_to_va = adsp_da_to_va, + .parse_fw = qcom_register_dump_segments, .load = adsp_load, .panic = adsp_panic, .coredump = adsp_minidump, @@ -533,9 +535,8 @@ static void adsp_pds_detach(struct qcom_adsp *adsp, struct device **pds, static int adsp_alloc_memory_region(struct qcom_adsp *adsp) { + struct reserved_mem *rmem; struct device_node *node; - struct resource r; - int ret; node = of_parse_phandle(adsp->dev->of_node, "memory-region", 0); if (!node) { @@ -543,17 +544,19 @@ static int adsp_alloc_memory_region(struct qcom_adsp *adsp) return -EINVAL; } - ret = of_address_to_resource(node, 0, &r); + rmem = of_reserved_mem_lookup(node); of_node_put(node); - if (ret) - return ret; + if (!rmem) { + dev_err(adsp->dev, "unable to resolve memory-region\n"); + return -EINVAL; + } - adsp->mem_phys = adsp->mem_reloc = r.start; - adsp->mem_size = resource_size(&r); + adsp->mem_phys = adsp->mem_reloc = rmem->base; + adsp->mem_size = rmem->size; adsp->mem_region = devm_ioremap_wc(adsp->dev, adsp->mem_phys, adsp->mem_size); if (!adsp->mem_region) { dev_err(adsp->dev, "unable to map memory region: %pa+%zx\n", - &r.start, adsp->mem_size); + &rmem->base, adsp->mem_size); return -EBUSY; } @@ -566,16 +569,19 @@ static int adsp_alloc_memory_region(struct qcom_adsp *adsp) return -EINVAL; } - ret = of_address_to_resource(node, 0, &r); - if (ret) - return ret; + rmem = of_reserved_mem_lookup(node); + of_node_put(node); + if (!rmem) { + dev_err(adsp->dev, "unable to resolve dtb memory-region\n"); + return -EINVAL; + } - adsp->dtb_mem_phys = adsp->dtb_mem_reloc = r.start; - adsp->dtb_mem_size = resource_size(&r); + adsp->dtb_mem_phys = adsp->dtb_mem_reloc = rmem->base; + adsp->dtb_mem_size = rmem->size; adsp->dtb_mem_region = devm_ioremap_wc(adsp->dev, adsp->dtb_mem_phys, adsp->dtb_mem_size); if (!adsp->dtb_mem_region) { dev_err(adsp->dev, "unable to map dtb memory region: %pa+%zx\n", - &r.start, adsp->dtb_mem_size); + &rmem->base, adsp->dtb_mem_size); return -EBUSY; } @@ -584,29 +590,28 @@ static int adsp_alloc_memory_region(struct qcom_adsp *adsp) static int adsp_assign_memory_region(struct qcom_adsp *adsp) { + struct reserved_mem *rmem = NULL; struct qcom_scm_vmperm perm; struct device_node *node; - struct resource r; int ret; if (!adsp->region_assign_idx) return 0; node = of_parse_phandle(adsp->dev->of_node, "memory-region", adsp->region_assign_idx); - if (!node) { - dev_err(adsp->dev, "missing shareable memory-region\n"); + if (node) + rmem = of_reserved_mem_lookup(node); + of_node_put(node); + if (!rmem) { + dev_err(adsp->dev, "unable to resolve shareable memory-region\n"); return -EINVAL; } - ret = of_address_to_resource(node, 0, &r); - if (ret) - return ret; - perm.vmid = QCOM_SCM_VMID_MSS_MSA; perm.perm = QCOM_SCM_PERM_RW; - adsp->region_assign_phys = r.start; - adsp->region_assign_size = resource_size(&r); + adsp->region_assign_phys = rmem->base; + adsp->region_assign_size = rmem->size; adsp->region_assign_perms = BIT(QCOM_SCM_VMID_HLOS); ret = qcom_scm_assign_mem(adsp->region_assign_phys, @@ -1012,7 +1017,7 @@ static const struct adsp_data sc8180x_mpss_resource = { .ssctl_id = 0x12, }; -static const struct adsp_data slpi_resource_init = { +static const struct adsp_data msm8996_slpi_resource_init = { .crash_reason_smem = 424, .firmware_name = "slpi.mdt", .pas_id = 12, @@ -1026,7 +1031,7 @@ static const struct adsp_data slpi_resource_init = { .ssctl_id = 0x16, }; -static const struct adsp_data sm8150_slpi_resource = { +static const struct adsp_data sdm845_slpi_resource_init = { .crash_reason_smem = 424, .firmware_name = "slpi.mdt", .pas_id = 12, @@ -1042,38 +1047,6 @@ static const struct adsp_data sm8150_slpi_resource = { .ssctl_id = 0x16, }; -static const struct adsp_data sm8250_slpi_resource = { - .crash_reason_smem = 424, - .firmware_name = "slpi.mdt", - .pas_id = 12, - .auto_boot = true, - .proxy_pd_names = (char*[]){ - "lcx", - "lmx", - NULL - }, - .load_state = "slpi", - .ssr_name = "dsps", - .sysmon_name = "slpi", - .ssctl_id = 0x16, -}; - -static const struct adsp_data sm8350_slpi_resource = { - .crash_reason_smem = 424, - .firmware_name = "slpi.mdt", - .pas_id = 12, - .auto_boot = true, - .proxy_pd_names = (char*[]){ - "lcx", - "lmx", - NULL - }, - .load_state = "slpi", - .ssr_name = "dsps", - .sysmon_name = "slpi", - .ssctl_id = 0x16, -}; - static const struct adsp_data wcss_resource_init = { .crash_reason_smem = 421, .firmware_name = "wcnss.mdt", @@ -1182,9 +1155,9 @@ static const struct of_device_id adsp_of_match[] = { { .compatible = "qcom,msm8953-adsp-pil", .data = &msm8996_adsp_resource}, { .compatible = "qcom,msm8974-adsp-pil", .data = &adsp_resource_init}, { .compatible = "qcom,msm8996-adsp-pil", .data = &msm8996_adsp_resource}, - { .compatible = "qcom,msm8996-slpi-pil", .data = &slpi_resource_init}, + { .compatible = "qcom,msm8996-slpi-pil", .data = &msm8996_slpi_resource_init}, { .compatible = "qcom,msm8998-adsp-pas", .data = &msm8996_adsp_resource}, - { .compatible = "qcom,msm8998-slpi-pas", .data = &slpi_resource_init}, + { .compatible = "qcom,msm8998-slpi-pas", .data = &msm8996_slpi_resource_init}, { .compatible = "qcom,qcs404-adsp-pas", .data = &adsp_resource_init }, { .compatible = "qcom,qcs404-cdsp-pas", .data = &cdsp_resource_init }, { .compatible = "qcom,qcs404-wcss-pas", .data = &wcss_resource_init }, @@ -1199,6 +1172,7 @@ static const struct of_device_id adsp_of_match[] = { { .compatible = "qcom,sdm660-adsp-pas", .data = &adsp_resource_init}, { .compatible = "qcom,sdm845-adsp-pas", .data = &sdm845_adsp_resource_init}, { .compatible = "qcom,sdm845-cdsp-pas", .data = &sdm845_cdsp_resource_init}, + { .compatible = "qcom,sdm845-slpi-pas", .data = &sdm845_slpi_resource_init}, { .compatible = "qcom,sdx55-mpss-pas", .data = &sdx55_mpss_resource}, { .compatible = "qcom,sm6115-adsp-pas", .data = &adsp_resource_init}, { .compatible = "qcom,sm6115-cdsp-pas", .data = &cdsp_resource_init}, @@ -1209,17 +1183,17 @@ static const struct of_device_id adsp_of_match[] = { { .compatible = "qcom,sm8150-adsp-pas", .data = &sm8150_adsp_resource}, { .compatible = "qcom,sm8150-cdsp-pas", .data = &sm8150_cdsp_resource}, { .compatible = "qcom,sm8150-mpss-pas", .data = &mpss_resource_init}, - { .compatible = "qcom,sm8150-slpi-pas", .data = &sm8150_slpi_resource}, + { .compatible = "qcom,sm8150-slpi-pas", .data = &sdm845_slpi_resource_init}, { .compatible = "qcom,sm8250-adsp-pas", .data = &sm8250_adsp_resource}, { .compatible = "qcom,sm8250-cdsp-pas", .data = &sm8250_cdsp_resource}, - { .compatible = "qcom,sm8250-slpi-pas", .data = &sm8250_slpi_resource}, + { .compatible = "qcom,sm8250-slpi-pas", .data = &sdm845_slpi_resource_init}, { .compatible = "qcom,sm8350-adsp-pas", .data = &sm8350_adsp_resource}, { .compatible = "qcom,sm8350-cdsp-pas", .data = &sm8350_cdsp_resource}, - { .compatible = "qcom,sm8350-slpi-pas", .data = &sm8350_slpi_resource}, + { .compatible = "qcom,sm8350-slpi-pas", .data = &sdm845_slpi_resource_init}, { .compatible = "qcom,sm8350-mpss-pas", .data = &mpss_resource_init}, { .compatible = "qcom,sm8450-adsp-pas", .data = &sm8350_adsp_resource}, { .compatible = "qcom,sm8450-cdsp-pas", .data = &sm8350_cdsp_resource}, - { .compatible = "qcom,sm8450-slpi-pas", .data = &sm8350_slpi_resource}, + { .compatible = "qcom,sm8450-slpi-pas", .data = &sdm845_slpi_resource_init}, { .compatible = "qcom,sm8450-mpss-pas", .data = &sm8450_mpss_resource}, { .compatible = "qcom,sm8550-adsp-pas", .data = &sm8550_adsp_resource}, { .compatible = "qcom,sm8550-cdsp-pas", .data = &sm8550_cdsp_resource}, diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c index b437044aa126..cff1fa07d1de 100644 --- a/drivers/remoteproc/qcom_q6v5_wcss.c +++ b/drivers/remoteproc/qcom_q6v5_wcss.c @@ -837,8 +837,7 @@ static int q6v5_wcss_init_mmio(struct q6v5_wcss *wcss, return -ENOMEM; if (wcss->version == WCSS_IPQ8074) { - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rmb"); - wcss->rmb_base = devm_ioremap_resource(&pdev->dev, res); + wcss->rmb_base = devm_platform_ioremap_resource_byname(pdev, "rmb"); if (IS_ERR(wcss->rmb_base)) return PTR_ERR(wcss->rmb_base); } diff --git a/drivers/remoteproc/qcom_sysmon.c b/drivers/remoteproc/qcom_sysmon.c index 746f56b4bafb..c24e4a882873 100644 --- a/drivers/remoteproc/qcom_sysmon.c +++ b/drivers/remoteproc/qcom_sysmon.c @@ -9,7 +9,6 @@ #include <linux/interrupt.h> #include <linux/io.h> #include <linux/of_irq.h> -#include <linux/of_platform.h> #include <linux/platform_device.h> #include <linux/remoteproc/qcom_rproc.h> #include <linux/rpmsg.h> diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c index 1ed0647bc962..90de22c81da9 100644 --- a/drivers/remoteproc/qcom_wcnss.c +++ b/drivers/remoteproc/qcom_wcnss.c @@ -14,8 +14,8 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/io.h> -#include <linux/of_address.h> -#include <linux/of_device.h> +#include <linux/of.h> +#include <linux/of_reserved_mem.h> #include <linux/platform_device.h> #include <linux/pm_domain.h> #include <linux/pm_runtime.h> @@ -506,27 +506,25 @@ static int wcnss_request_irq(struct qcom_wcnss *wcnss, static int wcnss_alloc_memory_region(struct qcom_wcnss *wcnss) { + struct reserved_mem *rmem = NULL; struct device_node *node; - struct resource r; - int ret; node = of_parse_phandle(wcnss->dev->of_node, "memory-region", 0); - if (!node) { - dev_err(wcnss->dev, "no memory-region specified\n"); + if (node) + rmem = of_reserved_mem_lookup(node); + of_node_put(node); + + if (!rmem) { + dev_err(wcnss->dev, "unable to resolve memory-region\n"); return -EINVAL; } - ret = of_address_to_resource(node, 0, &r); - of_node_put(node); - if (ret) - return ret; - - wcnss->mem_phys = wcnss->mem_reloc = r.start; - wcnss->mem_size = resource_size(&r); + wcnss->mem_phys = wcnss->mem_reloc = rmem->base; + wcnss->mem_size = rmem->size; wcnss->mem_region = devm_ioremap_wc(wcnss->dev, wcnss->mem_phys, wcnss->mem_size); if (!wcnss->mem_region) { dev_err(wcnss->dev, "unable to map memory region: %pa+%zx\n", - &r.start, wcnss->mem_size); + &rmem->base, wcnss->mem_size); return -EBUSY; } @@ -538,7 +536,6 @@ static int wcnss_probe(struct platform_device *pdev) const char *fw_name = WCNSS_FIRMWARE_NAME; const struct wcnss_data *data; struct qcom_wcnss *wcnss; - struct resource *res; struct rproc *rproc; void __iomem *mmio; int ret; @@ -576,8 +573,7 @@ static int wcnss_probe(struct platform_device *pdev) mutex_init(&wcnss->iris_lock); - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pmu"); - mmio = devm_ioremap_resource(&pdev->dev, res); + mmio = devm_platform_ioremap_resource_byname(pdev, "pmu"); if (IS_ERR(mmio)) { ret = PTR_ERR(mmio); goto free_rproc; diff --git a/drivers/remoteproc/qcom_wcnss_iris.c b/drivers/remoteproc/qcom_wcnss_iris.c index 09720ddddc85..dd36fd077911 100644 --- a/drivers/remoteproc/qcom_wcnss_iris.c +++ b/drivers/remoteproc/qcom_wcnss_iris.c @@ -10,6 +10,7 @@ #include <linux/clk.h> #include <linux/kernel.h> #include <linux/module.h> +#include <linux/of.h> #include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/regulator/consumer.h> diff --git a/drivers/remoteproc/rcar_rproc.c b/drivers/remoteproc/rcar_rproc.c index 90e8769d5624..cc17e8421f65 100644 --- a/drivers/remoteproc/rcar_rproc.c +++ b/drivers/remoteproc/rcar_rproc.c @@ -5,8 +5,9 @@ #include <linux/limits.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/of_reserved_mem.h> +#include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/remoteproc.h> #include <linux/reset.h> diff --git a/drivers/remoteproc/remoteproc_coredump.c b/drivers/remoteproc/remoteproc_coredump.c index bc0e1603a7a3..6ede8c0c93ad 100644 --- a/drivers/remoteproc/remoteproc_coredump.c +++ b/drivers/remoteproc/remoteproc_coredump.c @@ -32,6 +32,7 @@ void rproc_coredump_cleanup(struct rproc *rproc) kfree(entry); } } +EXPORT_SYMBOL_GPL(rproc_coredump_cleanup); /** * rproc_coredump_add_segment() - add segment of device memory to coredump @@ -327,6 +328,7 @@ void rproc_coredump(struct rproc *rproc) */ wait_for_completion(&dump_state.dump_done); } +EXPORT_SYMBOL_GPL(rproc_coredump); /** * rproc_coredump_using_sections() - perform coredump using section headers diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h index d4dbb8d1d80c..f62a82d71dfa 100644 --- a/drivers/remoteproc/remoteproc_internal.h +++ b/drivers/remoteproc/remoteproc_internal.h @@ -76,10 +76,6 @@ extern struct class rproc_class; int rproc_init_sysfs(void); void rproc_exit_sysfs(void); -/* from remoteproc_coredump.c */ -void rproc_coredump_cleanup(struct rproc *rproc); -void rproc_coredump(struct rproc *rproc); - #ifdef CONFIG_REMOTEPROC_CDEV void rproc_init_cdev(void); void rproc_exit_cdev(void); diff --git a/drivers/remoteproc/st_slim_rproc.c b/drivers/remoteproc/st_slim_rproc.c index 4ed9467897e5..d17719384c16 100644 --- a/drivers/remoteproc/st_slim_rproc.c +++ b/drivers/remoteproc/st_slim_rproc.c @@ -12,7 +12,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/remoteproc.h> #include <linux/remoteproc/st_slim_rproc.h> diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c index cf073bac79f7..9d9b13530f78 100644 --- a/drivers/remoteproc/stm32_rproc.c +++ b/drivers/remoteproc/stm32_rproc.c @@ -12,9 +12,9 @@ #include <linux/mailbox_client.h> #include <linux/mfd/syscon.h> #include <linux/module.h> -#include <linux/of_address.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/of_reserved_mem.h> +#include <linux/platform_device.h> #include <linux/pm_wakeirq.h> #include <linux/regmap.h> #include <linux/remoteproc.h> @@ -921,7 +921,7 @@ static void stm32_rproc_remove(struct platform_device *pdev) rproc_free(rproc); } -static int __maybe_unused stm32_rproc_suspend(struct device *dev) +static int stm32_rproc_suspend(struct device *dev) { struct rproc *rproc = dev_get_drvdata(dev); struct stm32_rproc *ddata = rproc->priv; @@ -932,7 +932,7 @@ static int __maybe_unused stm32_rproc_suspend(struct device *dev) return 0; } -static int __maybe_unused stm32_rproc_resume(struct device *dev) +static int stm32_rproc_resume(struct device *dev) { struct rproc *rproc = dev_get_drvdata(dev); struct stm32_rproc *ddata = rproc->priv; @@ -943,16 +943,16 @@ static int __maybe_unused stm32_rproc_resume(struct device *dev) return 0; } -static SIMPLE_DEV_PM_OPS(stm32_rproc_pm_ops, - stm32_rproc_suspend, stm32_rproc_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(stm32_rproc_pm_ops, + stm32_rproc_suspend, stm32_rproc_resume); static struct platform_driver stm32_rproc_driver = { .probe = stm32_rproc_probe, .remove_new = stm32_rproc_remove, .driver = { .name = "stm32-rproc", - .pm = &stm32_rproc_pm_ops, - .of_match_table = of_match_ptr(stm32_rproc_match), + .pm = pm_ptr(&stm32_rproc_pm_ops), + .of_match_table = stm32_rproc_match, }, }; module_platform_driver(stm32_rproc_driver); diff --git a/drivers/remoteproc/ti_k3_dsp_remoteproc.c b/drivers/remoteproc/ti_k3_dsp_remoteproc.c index ec626a37fef6..ef8415a7cd54 100644 --- a/drivers/remoteproc/ti_k3_dsp_remoteproc.c +++ b/drivers/remoteproc/ti_k3_dsp_remoteproc.c @@ -9,7 +9,7 @@ #include <linux/io.h> #include <linux/mailbox_client.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/of_reserved_mem.h> #include <linux/omap-mailbox.h> #include <linux/platform_device.h> diff --git a/drivers/remoteproc/ti_k3_r5_remoteproc.c b/drivers/remoteproc/ti_k3_r5_remoteproc.c index 23fe44d4d7a5..ad3415a3851b 100644 --- a/drivers/remoteproc/ti_k3_r5_remoteproc.c +++ b/drivers/remoteproc/ti_k3_r5_remoteproc.c @@ -12,9 +12,10 @@ #include <linux/kernel.h> #include <linux/mailbox_client.h> #include <linux/module.h> +#include <linux/of.h> #include <linux/of_address.h> -#include <linux/of_device.h> #include <linux/of_reserved_mem.h> +#include <linux/of_platform.h> #include <linux/omap-mailbox.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> diff --git a/drivers/remoteproc/wkup_m3_rproc.c b/drivers/remoteproc/wkup_m3_rproc.c index 120dc7d2dac1..36a55f7ffa64 100644 --- a/drivers/remoteproc/wkup_m3_rproc.c +++ b/drivers/remoteproc/wkup_m3_rproc.c @@ -12,7 +12,7 @@ #include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/of_address.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index 1beb40a1d3df..82d460ff4777 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -200,9 +200,15 @@ static const struct rpmsg_endpoint_ops glink_endpoint_ops; #define GLINK_CMD_TX_DATA_CONT 12 #define GLINK_CMD_READ_NOTIF 13 #define GLINK_CMD_RX_DONE_W_REUSE 14 +#define GLINK_CMD_SIGNALS 15 #define GLINK_FEATURE_INTENTLESS BIT(1) +#define NATIVE_DTR_SIG NATIVE_DSR_SIG +#define NATIVE_DSR_SIG BIT(31) +#define NATIVE_RTS_SIG NATIVE_CTS_SIG +#define NATIVE_CTS_SIG BIT(30) + static void qcom_glink_rx_done_work(struct work_struct *work); static struct glink_channel *qcom_glink_alloc_channel(struct qcom_glink *glink, @@ -221,6 +227,10 @@ static struct glink_channel *qcom_glink_alloc_channel(struct qcom_glink *glink, channel->glink = glink; channel->name = kstrdup(name, GFP_KERNEL); + if (!channel->name) { + kfree(channel); + return ERR_PTR(-ENOMEM); + } init_completion(&channel->open_req); init_completion(&channel->open_ack); @@ -1025,6 +1035,52 @@ static int qcom_glink_rx_open_ack(struct qcom_glink *glink, unsigned int lcid) return 0; } +/** + * qcom_glink_set_flow_control() - convert a signal cmd to wire format and transmit + * @ept: Rpmsg endpoint for channel. + * @pause: Pause transmission + * @dst: destination address of the endpoint + * + * Return: 0 on success or standard Linux error code. + */ +static int qcom_glink_set_flow_control(struct rpmsg_endpoint *ept, bool pause, u32 dst) +{ + struct glink_channel *channel = to_glink_channel(ept); + struct qcom_glink *glink = channel->glink; + struct glink_msg msg; + u32 sigs = 0; + + if (pause) + sigs |= NATIVE_DTR_SIG | NATIVE_RTS_SIG; + + msg.cmd = cpu_to_le16(GLINK_CMD_SIGNALS); + msg.param1 = cpu_to_le16(channel->lcid); + msg.param2 = cpu_to_le32(sigs); + + return qcom_glink_tx(glink, &msg, sizeof(msg), NULL, 0, true); +} + +static void qcom_glink_handle_signals(struct qcom_glink *glink, + unsigned int rcid, unsigned int sigs) +{ + struct glink_channel *channel; + unsigned long flags; + bool enable; + + spin_lock_irqsave(&glink->idr_lock, flags); + channel = idr_find(&glink->rcids, rcid); + spin_unlock_irqrestore(&glink->idr_lock, flags); + if (!channel) { + dev_err(glink->dev, "signal for non-existing channel\n"); + return; + } + + enable = sigs & NATIVE_DSR_SIG || sigs & NATIVE_CTS_SIG; + + if (channel->ept.flow_cb) + channel->ept.flow_cb(channel->ept.rpdev, channel->ept.priv, enable); +} + void qcom_glink_native_rx(struct qcom_glink *glink) { struct glink_msg msg; @@ -1086,6 +1142,10 @@ void qcom_glink_native_rx(struct qcom_glink *glink) qcom_glink_handle_intent_req_ack(glink, param1, param2); qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8)); break; + case GLINK_CMD_SIGNALS: + qcom_glink_handle_signals(glink, param1, param2); + qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8)); + break; default: dev_err(glink->dev, "unhandled rx cmd: %d\n", cmd); ret = -EINVAL; @@ -1446,6 +1506,7 @@ static const struct rpmsg_endpoint_ops glink_endpoint_ops = { .sendto = qcom_glink_sendto, .trysend = qcom_glink_trysend, .trysendto = qcom_glink_trysendto, + .set_flow_control = qcom_glink_set_flow_control, }; static void qcom_glink_rpdev_release(struct device *dev) diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c index a271fceb16f4..09833ad05da7 100644 --- a/drivers/rpmsg/rpmsg_char.c +++ b/drivers/rpmsg/rpmsg_char.c @@ -52,6 +52,8 @@ static DEFINE_IDA(rpmsg_minor_ida); * @readq: wait object for incoming queue * @default_ept: set to channel default endpoint if the default endpoint should be re-used * on device open to prevent endpoint address update. + * remote_flow_restricted: to indicate if the remote has requested for flow to be limited + * remote_flow_updated: to indicate if the flow control has been requested */ struct rpmsg_eptdev { struct device dev; @@ -68,6 +70,8 @@ struct rpmsg_eptdev { struct sk_buff_head queue; wait_queue_head_t readq; + bool remote_flow_restricted; + bool remote_flow_updated; }; int rpmsg_chrdev_eptdev_destroy(struct device *dev, void *data) @@ -116,6 +120,18 @@ static int rpmsg_ept_cb(struct rpmsg_device *rpdev, void *buf, int len, return 0; } +static int rpmsg_ept_flow_cb(struct rpmsg_device *rpdev, void *priv, bool enable) +{ + struct rpmsg_eptdev *eptdev = priv; + + eptdev->remote_flow_restricted = enable; + eptdev->remote_flow_updated = true; + + wake_up_interruptible(&eptdev->readq); + + return 0; +} + static int rpmsg_eptdev_open(struct inode *inode, struct file *filp) { struct rpmsg_eptdev *eptdev = cdev_to_eptdev(inode->i_cdev); @@ -152,6 +168,7 @@ static int rpmsg_eptdev_open(struct inode *inode, struct file *filp) return -EINVAL; } + ept->flow_cb = rpmsg_ept_flow_cb; eptdev->ept = ept; filp->private_data = eptdev; mutex_unlock(&eptdev->ept_lock); @@ -172,6 +189,7 @@ static int rpmsg_eptdev_release(struct inode *inode, struct file *filp) eptdev->ept = NULL; } mutex_unlock(&eptdev->ept_lock); + eptdev->remote_flow_updated = false; /* Discard all SKBs */ skb_queue_purge(&eptdev->queue); @@ -285,6 +303,9 @@ static __poll_t rpmsg_eptdev_poll(struct file *filp, poll_table *wait) if (!skb_queue_empty(&eptdev->queue)) mask |= EPOLLIN | EPOLLRDNORM; + if (eptdev->remote_flow_updated) + mask |= EPOLLPRI; + mutex_lock(&eptdev->ept_lock); mask |= rpmsg_poll(eptdev->ept, filp, wait); mutex_unlock(&eptdev->ept_lock); @@ -297,14 +318,35 @@ static long rpmsg_eptdev_ioctl(struct file *fp, unsigned int cmd, { struct rpmsg_eptdev *eptdev = fp->private_data; - if (cmd != RPMSG_DESTROY_EPT_IOCTL) - return -EINVAL; + bool set; + int ret; - /* Don't allow to destroy a default endpoint. */ - if (eptdev->default_ept) - return -EINVAL; + switch (cmd) { + case RPMSG_GET_OUTGOING_FLOWCONTROL: + eptdev->remote_flow_updated = false; + ret = put_user(eptdev->remote_flow_restricted, (int __user *)arg); + break; + case RPMSG_SET_INCOMING_FLOWCONTROL: + if (arg > 1) { + ret = -EINVAL; + break; + } + set = !!arg; + ret = rpmsg_set_flow_control(eptdev->ept, set, eptdev->chinfo.dst); + break; + case RPMSG_DESTROY_EPT_IOCTL: + /* Don't allow to destroy a default endpoint. */ + if (eptdev->default_ept) { + ret = -EINVAL; + break; + } + ret = rpmsg_chrdev_eptdev_destroy(&eptdev->dev, NULL); + break; + default: + ret = -EINVAL; + } - return rpmsg_chrdev_eptdev_destroy(&eptdev->dev, NULL); + return ret; } static const struct file_operations rpmsg_eptdev_fops = { diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c index 5039df757127..32b550c91d9f 100644 --- a/drivers/rpmsg/rpmsg_core.c +++ b/drivers/rpmsg/rpmsg_core.c @@ -331,6 +331,25 @@ int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst, EXPORT_SYMBOL(rpmsg_trysend_offchannel); /** + * rpmsg_set_flow_control() - request remote to pause/resume transmission + * @ept: the rpmsg endpoint + * @pause: pause transmission + * @dst: destination address of the endpoint + * + * Return: 0 on success and an appropriate error value on failure. + */ +int rpmsg_set_flow_control(struct rpmsg_endpoint *ept, bool pause, u32 dst) +{ + if (WARN_ON(!ept)) + return -EINVAL; + if (!ept->ops->set_flow_control) + return -EOPNOTSUPP; + + return ept->ops->set_flow_control(ept, pause, dst); +} +EXPORT_SYMBOL_GPL(rpmsg_set_flow_control); + +/** * rpmsg_get_mtu() - get maximum transmission buffer size for sending message. * @ept: the rpmsg endpoint * @@ -539,6 +558,8 @@ static int rpmsg_dev_probe(struct device *dev) rpdev->ept = ept; rpdev->src = ept->addr; + + ept->flow_cb = rpdrv->flowcontrol; } err = rpdrv->probe(rpdev); diff --git a/drivers/rpmsg/rpmsg_internal.h b/drivers/rpmsg/rpmsg_internal.h index 39b646d0d40d..b950d6f790a3 100644 --- a/drivers/rpmsg/rpmsg_internal.h +++ b/drivers/rpmsg/rpmsg_internal.h @@ -55,6 +55,7 @@ struct rpmsg_device_ops { * @trysendto: see @rpmsg_trysendto(), optional * @trysend_offchannel: see @rpmsg_trysend_offchannel(), optional * @poll: see @rpmsg_poll(), optional + * @set_flow_control: see @rpmsg_set_flow_control(), optional * @get_mtu: see @rpmsg_get_mtu(), optional * * Indirection table for the operations that a rpmsg backend should implement. @@ -75,6 +76,7 @@ struct rpmsg_endpoint_ops { void *data, int len); __poll_t (*poll)(struct rpmsg_endpoint *ept, struct file *filp, poll_table *wait); + int (*set_flow_control)(struct rpmsg_endpoint *ept, bool pause, u32 dst); ssize_t (*get_mtu)(struct rpmsg_endpoint *ept); }; diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index 19a4b33cb564..c81a00fbca7d 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -510,4 +510,16 @@ config KHADAS_MCU_FAN_THERMAL If you say yes here you get support for the FAN controlled by the Microcontroller found on the Khadas VIM boards. +config LOONGSON2_THERMAL + tristate "Loongson-2 SoC series thermal driver" + depends on LOONGARCH || COMPILE_TEST + depends on OF + help + Support for Thermal driver found on Loongson-2 SoC series platforms. + The thermal driver realizes get_temp and set_trips function, which + are used to obtain the temperature of the current node and set the + temperature range to trigger the interrupt. When the input temperature + is higher than the high temperature threshold or lower than the low + temperature threshold, the interrupt will occur. + endif diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile index 058664bc3ec0..c934cab309ae 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile @@ -63,3 +63,4 @@ obj-$(CONFIG_UNIPHIER_THERMAL) += uniphier_thermal.o obj-$(CONFIG_AMLOGIC_THERMAL) += amlogic_thermal.o obj-$(CONFIG_SPRD_THERMAL) += sprd_thermal.o obj-$(CONFIG_KHADAS_MCU_FAN_THERMAL) += khadas_mcu_fan.o +obj-$(CONFIG_LOONGSON2_THERMAL) += loongson2_thermal.o diff --git a/drivers/thermal/broadcom/brcmstb_thermal.c b/drivers/thermal/broadcom/brcmstb_thermal.c index 0b73abdaa792..9674e5ffcfa2 100644 --- a/drivers/thermal/broadcom/brcmstb_thermal.c +++ b/drivers/thermal/broadcom/brcmstb_thermal.c @@ -334,7 +334,6 @@ static int brcmstb_thermal_probe(struct platform_device *pdev) return PTR_ERR(priv->tmon_base); priv->dev = &pdev->dev; - platform_set_drvdata(pdev, priv); of_ops = priv->temp_params->of_ops; thermal = devm_thermal_of_zone_register(&pdev->dev, 0, priv, diff --git a/drivers/thermal/broadcom/sr-thermal.c b/drivers/thermal/broadcom/sr-thermal.c index 747915890022..9a29dfd4c7fe 100644 --- a/drivers/thermal/broadcom/sr-thermal.c +++ b/drivers/thermal/broadcom/sr-thermal.c @@ -91,7 +91,6 @@ static int sr_thermal_probe(struct platform_device *pdev) dev_dbg(dev, "thermal sensor %d registered\n", i); } - platform_set_drvdata(pdev, sr_thermal); return 0; } diff --git a/drivers/thermal/db8500_thermal.c b/drivers/thermal/db8500_thermal.c index fca5c2c93bf9..576f88b6a1b3 100644 --- a/drivers/thermal/db8500_thermal.c +++ b/drivers/thermal/db8500_thermal.c @@ -229,7 +229,7 @@ MODULE_DEVICE_TABLE(of, db8500_thermal_match); static struct platform_driver db8500_thermal_driver = { .driver = { .name = "db8500-thermal", - .of_match_table = of_match_ptr(db8500_thermal_match), + .of_match_table = db8500_thermal_match, }, .probe = db8500_thermal_probe, .suspend = db8500_thermal_suspend, diff --git a/drivers/thermal/imx8mm_thermal.c b/drivers/thermal/imx8mm_thermal.c index e89b11b3f2b9..14111ccf6e4c 100644 --- a/drivers/thermal/imx8mm_thermal.c +++ b/drivers/thermal/imx8mm_thermal.c @@ -178,10 +178,8 @@ static int imx8mm_tmu_probe_set_calib_v1(struct platform_device *pdev, int ret; ret = nvmem_cell_read_u32(&pdev->dev, "calib", &ana0); - if (ret) { - dev_warn(dev, "Failed to read OCOTP nvmem cell (%d).\n", ret); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "Failed to read OCOTP nvmem cell\n"); writel(FIELD_PREP(TASR_BUF_VREF_MASK, FIELD_GET(ANA0_BUF_VREF_MASK, ana0)) | diff --git a/drivers/thermal/k3_bandgap.c b/drivers/thermal/k3_bandgap.c index 68f59b3735d3..4a918c1e92f9 100644 --- a/drivers/thermal/k3_bandgap.c +++ b/drivers/thermal/k3_bandgap.c @@ -225,7 +225,6 @@ static int k3_bandgap_probe(struct platform_device *pdev) devm_thermal_add_hwmon_sysfs(dev, data[id].tzd); } - platform_set_drvdata(pdev, bgp); return 0; diff --git a/drivers/thermal/k3_j72xx_bandgap.c b/drivers/thermal/k3_j72xx_bandgap.c index a5a0fc9b9356..2fc799b07b90 100644 --- a/drivers/thermal/k3_j72xx_bandgap.c +++ b/drivers/thermal/k3_j72xx_bandgap.c @@ -502,8 +502,6 @@ static int k3_j72xx_bandgap_probe(struct platform_device *pdev) writel(K3_VTM_ANYMAXT_OUTRG_ALERT_EN, data[0].bgp->cfg2_base + K3_VTM_MISC_CTRL_OFFSET); - platform_set_drvdata(pdev, bgp); - print_look_up_table(dev, ref_table); /* * Now that the derived_table has the appropriate look up values diff --git a/drivers/thermal/loongson2_thermal.c b/drivers/thermal/loongson2_thermal.c new file mode 100644 index 000000000000..133098dc0854 --- /dev/null +++ b/drivers/thermal/loongson2_thermal.c @@ -0,0 +1,169 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Author: zhanghongchen <zhanghongchen@loongson.cn> + * Yinbo Zhu <zhuyinbo@loongson.cn> + * Copyright (C) 2022-2023 Loongson Technology Corporation Limited + */ + +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/minmax.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/thermal.h> +#include <linux/units.h> +#include "thermal_hwmon.h" + +#define LOONGSON2_MAX_SENSOR_SEL_NUM 3 + +#define LOONGSON2_THSENS_CTRL_HI_REG 0x0 +#define LOONGSON2_THSENS_CTRL_LOW_REG 0x8 +#define LOONGSON2_THSENS_STATUS_REG 0x10 +#define LOONGSON2_THSENS_OUT_REG 0x14 + +#define LOONGSON2_THSENS_INT_LO BIT(0) +#define LOONGSON2_THSENS_INT_HIGH BIT(1) +#define LOONGSON2_THSENS_OUT_MASK 0xFF + +struct loongson2_thermal_chip_data { + unsigned int thermal_sensor_sel; +}; + +struct loongson2_thermal_data { + void __iomem *regs; + const struct loongson2_thermal_chip_data *chip_data; +}; + +static int loongson2_thermal_set(struct loongson2_thermal_data *data, + int low, int high, bool enable) +{ + u64 reg_ctrl = 0; + int reg_off = data->chip_data->thermal_sensor_sel * 2; + + low = clamp(-40, low, high); + high = clamp(125, low, high); + + low += HECTO; + high += HECTO; + + reg_ctrl = low; + reg_ctrl |= enable ? 0x100 : 0; + writew(reg_ctrl, data->regs + LOONGSON2_THSENS_CTRL_LOW_REG + reg_off); + + reg_ctrl = high; + reg_ctrl |= enable ? 0x100 : 0; + writew(reg_ctrl, data->regs + LOONGSON2_THSENS_CTRL_HI_REG + reg_off); + + return 0; +} + +static int loongson2_thermal_get_temp(struct thermal_zone_device *tz, int *temp) +{ + u32 reg_val; + struct loongson2_thermal_data *data = thermal_zone_device_priv(tz); + + reg_val = readl(data->regs + LOONGSON2_THSENS_OUT_REG); + *temp = ((reg_val & LOONGSON2_THSENS_OUT_MASK) - HECTO) * KILO; + + return 0; +} + +static irqreturn_t loongson2_thermal_irq_thread(int irq, void *dev) +{ + struct thermal_zone_device *tzd = dev; + struct loongson2_thermal_data *data = thermal_zone_device_priv(tzd); + + writeb(LOONGSON2_THSENS_INT_LO | LOONGSON2_THSENS_INT_HIGH, data->regs + + LOONGSON2_THSENS_STATUS_REG); + + thermal_zone_device_update(tzd, THERMAL_EVENT_UNSPECIFIED); + + return IRQ_HANDLED; +} + +static int loongson2_thermal_set_trips(struct thermal_zone_device *tz, int low, int high) +{ + struct loongson2_thermal_data *data = thermal_zone_device_priv(tz); + + return loongson2_thermal_set(data, low/MILLI, high/MILLI, true); +} + +static const struct thermal_zone_device_ops loongson2_of_thermal_ops = { + .get_temp = loongson2_thermal_get_temp, + .set_trips = loongson2_thermal_set_trips, +}; + +static int loongson2_thermal_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct loongson2_thermal_data *data; + struct thermal_zone_device *tzd; + int ret, irq, i; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->chip_data = device_get_match_data(dev); + + data->regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(data->regs)) + return PTR_ERR(data->regs); + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + writeb(LOONGSON2_THSENS_INT_LO | LOONGSON2_THSENS_INT_HIGH, data->regs + + LOONGSON2_THSENS_STATUS_REG); + + loongson2_thermal_set(data, 0, 0, false); + + for (i = 0; i <= LOONGSON2_MAX_SENSOR_SEL_NUM; i++) { + tzd = devm_thermal_of_zone_register(dev, i, data, + &loongson2_of_thermal_ops); + + if (!IS_ERR(tzd)) + break; + + if (PTR_ERR(tzd) != ENODEV) + continue; + + return dev_err_probe(dev, PTR_ERR(tzd), "failed to register"); + } + + ret = devm_request_threaded_irq(dev, irq, NULL, loongson2_thermal_irq_thread, + IRQF_ONESHOT, "loongson2_thermal", tzd); + if (ret < 0) + return dev_err_probe(dev, ret, "failed to request alarm irq\n"); + + devm_thermal_add_hwmon_sysfs(dev, tzd); + + return 0; +} + +static const struct loongson2_thermal_chip_data loongson2_thermal_ls2k1000_data = { + .thermal_sensor_sel = 0, +}; + +static const struct of_device_id of_loongson2_thermal_match[] = { + { + .compatible = "loongson,ls2k1000-thermal", + .data = &loongson2_thermal_ls2k1000_data, + }, + { /* end */ } +}; +MODULE_DEVICE_TABLE(of, of_loongson2_thermal_match); + +static struct platform_driver loongson2_thermal_driver = { + .driver = { + .name = "loongson2_thermal", + .of_match_table = of_loongson2_thermal_match, + }, + .probe = loongson2_thermal_probe, +}; +module_platform_driver(loongson2_thermal_driver); + +MODULE_DESCRIPTION("Loongson2 thermal driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/thermal/max77620_thermal.c b/drivers/thermal/max77620_thermal.c index 61c7622d9945..919b6ee208d8 100644 --- a/drivers/thermal/max77620_thermal.c +++ b/drivers/thermal/max77620_thermal.c @@ -139,8 +139,6 @@ static int max77620_thermal_probe(struct platform_device *pdev) return ret; } - platform_set_drvdata(pdev, mtherm); - return 0; } diff --git a/drivers/thermal/mediatek/auxadc_thermal.c b/drivers/thermal/mediatek/auxadc_thermal.c index c537aed71017..843214d30bd8 100644 --- a/drivers/thermal/mediatek/auxadc_thermal.c +++ b/drivers/thermal/mediatek/auxadc_thermal.c @@ -1282,8 +1282,6 @@ static int mtk_thermal_probe(struct platform_device *pdev) mtk_thermal_init_bank(mt, i, apmixed_phys_base, auxadc_phys_base, ctrl_id); - platform_set_drvdata(pdev, mt); - tzdev = devm_thermal_of_zone_register(&pdev->dev, 0, mt, &mtk_thermal_ops); if (IS_ERR(tzdev)) diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c index 054c965ae5e1..effd9b00a424 100644 --- a/drivers/thermal/mediatek/lvts_thermal.c +++ b/drivers/thermal/mediatek/lvts_thermal.c @@ -58,14 +58,19 @@ #define LVTS_PROTTC(__base) (__base + 0x00CC) #define LVTS_CLKEN(__base) (__base + 0x00E4) -#define LVTS_PERIOD_UNIT ((118 * 1000) / (256 * 38)) -#define LVTS_GROUP_INTERVAL 1 -#define LVTS_FILTER_INTERVAL 1 -#define LVTS_SENSOR_INTERVAL 1 -#define LVTS_HW_FILTER 0x2 +#define LVTS_PERIOD_UNIT 0 +#define LVTS_GROUP_INTERVAL 0 +#define LVTS_FILTER_INTERVAL 0 +#define LVTS_SENSOR_INTERVAL 0 +#define LVTS_HW_FILTER 0x0 #define LVTS_TSSEL_CONF 0x13121110 #define LVTS_CALSCALE_CONF 0x300 -#define LVTS_MONINT_CONF 0x9FBF7BDE +#define LVTS_MONINT_CONF 0x8300318C + +#define LVTS_MONINT_OFFSET_SENSOR0 0xC +#define LVTS_MONINT_OFFSET_SENSOR1 0x180 +#define LVTS_MONINT_OFFSET_SENSOR2 0x3000 +#define LVTS_MONINT_OFFSET_SENSOR3 0x3000000 #define LVTS_INT_SENSOR0 0x0009001F #define LVTS_INT_SENSOR1 0x001203E0 @@ -81,8 +86,13 @@ #define LVTS_MSR_IMMEDIATE_MODE 0 #define LVTS_MSR_FILTERED_MODE 1 +#define LVTS_MSR_READ_TIMEOUT_US 400 +#define LVTS_MSR_READ_WAIT_US (LVTS_MSR_READ_TIMEOUT_US / 2) + #define LVTS_HW_SHUTDOWN_MT8195 105000 +#define LVTS_MINIMUM_THRESHOLD 20000 + static int golden_temp = LVTS_GOLDEN_TEMP_DEFAULT; static int coeff_b = LVTS_COEFF_B; @@ -110,6 +120,8 @@ struct lvts_sensor { void __iomem *base; int id; int dt_id; + int low_thresh; + int high_thresh; }; struct lvts_ctrl { @@ -119,6 +131,8 @@ struct lvts_ctrl { int num_lvts_sensor; int mode; void __iomem *base; + int low_thresh; + int high_thresh; }; struct lvts_domain { @@ -190,7 +204,7 @@ static int lvts_debugfs_init(struct device *dev, struct lvts_domain *lvts_td) int i; lvts_td->dom_dentry = debugfs_create_dir(dev_name(dev), NULL); - if (!lvts_td->dom_dentry) + if (IS_ERR(lvts_td->dom_dentry)) return 0; for (i = 0; i < lvts_td->num_lvts_ctrl; i++) { @@ -257,6 +271,7 @@ static int lvts_get_temp(struct thermal_zone_device *tz, int *temp) struct lvts_sensor *lvts_sensor = thermal_zone_device_priv(tz); void __iomem *msr = lvts_sensor->msr; u32 value; + int rc; /* * Measurement registers: @@ -269,7 +284,8 @@ static int lvts_get_temp(struct thermal_zone_device *tz, int *temp) * 16 : Valid temperature * 15-0 : Raw temperature */ - value = readl(msr); + rc = readl_poll_timeout(msr, value, value & BIT(16), + LVTS_MSR_READ_WAIT_US, LVTS_MSR_READ_TIMEOUT_US); /* * As the thermal zone temperature will read before the @@ -282,7 +298,7 @@ static int lvts_get_temp(struct thermal_zone_device *tz, int *temp) * functionning temperature and directly jump to a system * shutdown. */ - if (!(value & BIT(16))) + if (rc) return -EAGAIN; *temp = lvts_raw_to_temp(value & 0xFFFF); @@ -290,32 +306,84 @@ static int lvts_get_temp(struct thermal_zone_device *tz, int *temp) return 0; } +static void lvts_update_irq_mask(struct lvts_ctrl *lvts_ctrl) +{ + u32 masks[] = { + LVTS_MONINT_OFFSET_SENSOR0, + LVTS_MONINT_OFFSET_SENSOR1, + LVTS_MONINT_OFFSET_SENSOR2, + LVTS_MONINT_OFFSET_SENSOR3, + }; + u32 value = 0; + int i; + + value = readl(LVTS_MONINT(lvts_ctrl->base)); + + for (i = 0; i < ARRAY_SIZE(masks); i++) { + if (lvts_ctrl->sensors[i].high_thresh == lvts_ctrl->high_thresh + && lvts_ctrl->sensors[i].low_thresh == lvts_ctrl->low_thresh) + value |= masks[i]; + else + value &= ~masks[i]; + } + + writel(value, LVTS_MONINT(lvts_ctrl->base)); +} + +static bool lvts_should_update_thresh(struct lvts_ctrl *lvts_ctrl, int high) +{ + int i; + + if (high > lvts_ctrl->high_thresh) + return true; + + for (i = 0; i < lvts_ctrl->num_lvts_sensor; i++) + if (lvts_ctrl->sensors[i].high_thresh == lvts_ctrl->high_thresh + && lvts_ctrl->sensors[i].low_thresh == lvts_ctrl->low_thresh) + return false; + + return true; +} + static int lvts_set_trips(struct thermal_zone_device *tz, int low, int high) { struct lvts_sensor *lvts_sensor = thermal_zone_device_priv(tz); + struct lvts_ctrl *lvts_ctrl = container_of(lvts_sensor, struct lvts_ctrl, sensors[lvts_sensor->id]); void __iomem *base = lvts_sensor->base; - u32 raw_low = lvts_temp_to_raw(low); + u32 raw_low = lvts_temp_to_raw(low != -INT_MAX ? low : LVTS_MINIMUM_THRESHOLD); u32 raw_high = lvts_temp_to_raw(high); + bool should_update_thresh; + + lvts_sensor->low_thresh = low; + lvts_sensor->high_thresh = high; + + should_update_thresh = lvts_should_update_thresh(lvts_ctrl, high); + if (should_update_thresh) { + lvts_ctrl->high_thresh = high; + lvts_ctrl->low_thresh = low; + } + lvts_update_irq_mask(lvts_ctrl); + + if (!should_update_thresh) + return 0; /* - * Hot to normal temperature threshold + * Low offset temperature threshold * - * LVTS_H2NTHRE + * LVTS_OFFSETL * * Bits: * * 14-0 : Raw temperature for threshold */ - if (low != -INT_MAX) { - pr_debug("%s: Setting low limit temperature interrupt: %d\n", - thermal_zone_device_type(tz), low); - writel(raw_low, LVTS_H2NTHRE(base)); - } + pr_debug("%s: Setting low limit temperature interrupt: %d\n", + thermal_zone_device_type(tz), low); + writel(raw_low, LVTS_OFFSETL(base)); /* - * Hot temperature threshold + * High offset temperature threshold * - * LVTS_HTHRE + * LVTS_OFFSETH * * Bits: * @@ -323,7 +391,7 @@ static int lvts_set_trips(struct thermal_zone_device *tz, int low, int high) */ pr_debug("%s: Setting high limit temperature interrupt: %d\n", thermal_zone_device_type(tz), high); - writel(raw_high, LVTS_HTHRE(base)); + writel(raw_high, LVTS_OFFSETH(base)); return 0; } @@ -451,7 +519,7 @@ static irqreturn_t lvts_irq_handler(int irq, void *data) for (i = 0; i < lvts_td->num_lvts_ctrl; i++) { - aux = lvts_ctrl_irq_handler(lvts_td->lvts_ctrl); + aux = lvts_ctrl_irq_handler(&lvts_td->lvts_ctrl[i]); if (aux != IRQ_HANDLED) continue; @@ -521,6 +589,9 @@ static int lvts_sensor_init(struct device *dev, struct lvts_ctrl *lvts_ctrl, */ lvts_sensor[i].msr = lvts_ctrl_data->mode == LVTS_MSR_IMMEDIATE_MODE ? imm_regs[i] : msr_regs[i]; + + lvts_sensor[i].low_thresh = INT_MIN; + lvts_sensor[i].high_thresh = INT_MIN; }; lvts_ctrl->num_lvts_sensor = lvts_ctrl_data->num_lvts_sensor; @@ -688,6 +759,9 @@ static int lvts_ctrl_init(struct device *dev, struct lvts_domain *lvts_td, */ lvts_ctrl[i].hw_tshut_raw_temp = lvts_temp_to_raw(lvts_data->lvts_ctrl[i].hw_tshut_temp); + + lvts_ctrl[i].low_thresh = INT_MIN; + lvts_ctrl[i].high_thresh = INT_MIN; } /* @@ -897,24 +971,6 @@ static int lvts_ctrl_configure(struct device *dev, struct lvts_ctrl *lvts_ctrl) writel(value, LVTS_MSRCTL0(lvts_ctrl->base)); /* - * LVTS_MSRCTL1 : Measurement control - * - * Bits: - * - * 9: Ignore MSRCTL0 config and do immediate measurement on sensor3 - * 6: Ignore MSRCTL0 config and do immediate measurement on sensor2 - * 5: Ignore MSRCTL0 config and do immediate measurement on sensor1 - * 4: Ignore MSRCTL0 config and do immediate measurement on sensor0 - * - * That configuration will ignore the filtering and the delays - * introduced below in MONCTL1 and MONCTL2 - */ - if (lvts_ctrl->mode == LVTS_MSR_IMMEDIATE_MODE) { - value = BIT(9) | BIT(6) | BIT(5) | BIT(4); - writel(value, LVTS_MSRCTL1(lvts_ctrl->base)); - } - - /* * LVTS_MONCTL1 : Period unit and group interval configuration * * The clock source of LVTS thermal controller is 26MHz. @@ -979,6 +1035,15 @@ static int lvts_ctrl_start(struct device *dev, struct lvts_ctrl *lvts_ctrl) struct thermal_zone_device *tz; u32 sensor_map = 0; int i; + /* + * Bitmaps to enable each sensor on immediate and filtered modes, as + * described in MSRCTL1 and MONCTL0 registers below, respectively. + */ + u32 sensor_imm_bitmap[] = { BIT(4), BIT(5), BIT(6), BIT(9) }; + u32 sensor_filt_bitmap[] = { BIT(0), BIT(1), BIT(2), BIT(3) }; + + u32 *sensor_bitmap = lvts_ctrl->mode == LVTS_MSR_IMMEDIATE_MODE ? + sensor_imm_bitmap : sensor_filt_bitmap; for (i = 0; i < lvts_ctrl->num_lvts_sensor; i++) { @@ -1016,20 +1081,38 @@ static int lvts_ctrl_start(struct device *dev, struct lvts_ctrl *lvts_ctrl) * map, so we can enable the temperature monitoring in * the hardware thermal controller. */ - sensor_map |= BIT(i); + sensor_map |= sensor_bitmap[i]; } /* - * Bits: - * 9: Single point access flow - * 0-3: Enable sensing point 0-3 - * * The initialization of the thermal zones give us * which sensor point to enable. If any thermal zone * was not described in the device tree, it won't be * enabled here in the sensor map. */ - writel(sensor_map | BIT(9), LVTS_MONCTL0(lvts_ctrl->base)); + if (lvts_ctrl->mode == LVTS_MSR_IMMEDIATE_MODE) { + /* + * LVTS_MSRCTL1 : Measurement control + * + * Bits: + * + * 9: Ignore MSRCTL0 config and do immediate measurement on sensor3 + * 6: Ignore MSRCTL0 config and do immediate measurement on sensor2 + * 5: Ignore MSRCTL0 config and do immediate measurement on sensor1 + * 4: Ignore MSRCTL0 config and do immediate measurement on sensor0 + * + * That configuration will ignore the filtering and the delays + * introduced in MONCTL1 and MONCTL2 + */ + writel(sensor_map, LVTS_MSRCTL1(lvts_ctrl->base)); + } else { + /* + * Bits: + * 9: Single point access flow + * 0-3: Enable sensing point 0-3 + */ + writel(sensor_map | BIT(9), LVTS_MONCTL0(lvts_ctrl->base)); + } return 0; } @@ -1138,7 +1221,7 @@ static int lvts_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) - return dev_err_probe(dev, irq, "No irq resource\n"); + return irq; ret = lvts_domain_init(dev, lvts_td, lvts_data); if (ret) diff --git a/drivers/thermal/qcom/tsens-v0_1.c b/drivers/thermal/qcom/tsens-v0_1.c index a941b4241b0a..87c09f62ee81 100644 --- a/drivers/thermal/qcom/tsens-v0_1.c +++ b/drivers/thermal/qcom/tsens-v0_1.c @@ -23,7 +23,7 @@ #define BIT_APPEND 0x3 -struct tsens_legacy_calibration_format tsens_8916_nvmem = { +static struct tsens_legacy_calibration_format tsens_8916_nvmem = { .base_len = 7, .base_shift = 3, .sp_len = 5, @@ -39,7 +39,7 @@ struct tsens_legacy_calibration_format tsens_8916_nvmem = { }, }; -struct tsens_legacy_calibration_format tsens_8974_nvmem = { +static struct tsens_legacy_calibration_format tsens_8974_nvmem = { .base_len = 8, .base_shift = 2, .sp_len = 6, @@ -61,7 +61,7 @@ struct tsens_legacy_calibration_format tsens_8974_nvmem = { }, }; -struct tsens_legacy_calibration_format tsens_8974_backup_nvmem = { +static struct tsens_legacy_calibration_format tsens_8974_backup_nvmem = { .base_len = 8, .base_shift = 2, .sp_len = 6, diff --git a/drivers/thermal/qcom/tsens-v1.c b/drivers/thermal/qcom/tsens-v1.c index 51322430f1fe..dc1c4ae2d8b0 100644 --- a/drivers/thermal/qcom/tsens-v1.c +++ b/drivers/thermal/qcom/tsens-v1.c @@ -21,7 +21,7 @@ #define TM_HIGH_LOW_INT_STATUS_OFF 0x0088 #define TM_HIGH_LOW_Sn_INT_THRESHOLD_OFF 0x0090 -struct tsens_legacy_calibration_format tsens_qcs404_nvmem = { +static struct tsens_legacy_calibration_format tsens_qcs404_nvmem = { .base_len = 8, .base_shift = 2, .sp_len = 6, diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index 58f4d8f7a3fd..e5bc2c82010f 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -887,7 +887,7 @@ static int exynos_map_dt_data(struct platform_device *pdev) return -EADDRNOTAVAIL; } - data->soc = (enum soc_type)of_device_get_match_data(&pdev->dev); + data->soc = (uintptr_t)of_device_get_match_data(&pdev->dev); switch (data->soc) { case SOC_ARCH_EXYNOS4210: diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c index cca16d632d9f..f989b55a8aa8 100644 --- a/drivers/thermal/sun8i_thermal.c +++ b/drivers/thermal/sun8i_thermal.c @@ -56,8 +56,6 @@ #define SUN50I_H6_THS_PC_TEMP_PERIOD(x) ((GENMASK(19, 0) & (x)) << 12) #define SUN50I_H6_THS_DATA_IRQ_STS(x) BIT(x) -/* millidegree celsius */ - struct tsensor { struct ths_device *tmdev; struct thermal_zone_device *tzd; @@ -286,7 +284,7 @@ static int sun8i_ths_calibrate(struct ths_device *tmdev) size_t callen; int ret = 0; - calcell = devm_nvmem_cell_get(dev, "calibration"); + calcell = nvmem_cell_get(dev, "calibration"); if (IS_ERR(calcell)) { if (PTR_ERR(calcell) == -EPROBE_DEFER) return -EPROBE_DEFER; @@ -316,6 +314,8 @@ static int sun8i_ths_calibrate(struct ths_device *tmdev) kfree(caldata); out: + if (!IS_ERR(calcell)) + nvmem_cell_put(calcell); return ret; } @@ -489,8 +489,6 @@ static int sun8i_ths_probe(struct platform_device *pdev) if (!tmdev->chip) return -EINVAL; - platform_set_drvdata(pdev, tmdev); - ret = sun8i_ths_resource_init(tmdev); if (ret) return ret; diff --git a/drivers/thermal/tegra/tegra-bpmp-thermal.c b/drivers/thermal/tegra/tegra-bpmp-thermal.c index a2879d624945..4ffc3bb3bf35 100644 --- a/drivers/thermal/tegra/tegra-bpmp-thermal.c +++ b/drivers/thermal/tegra/tegra-bpmp-thermal.c @@ -167,19 +167,69 @@ static int tegra_bpmp_thermal_get_num_zones(struct tegra_bpmp *bpmp, return 0; } +static int tegra_bpmp_thermal_trips_supported(struct tegra_bpmp *bpmp, bool *supported) +{ + struct mrq_thermal_host_to_bpmp_request req; + union mrq_thermal_bpmp_to_host_response reply; + struct tegra_bpmp_message msg; + int err; + + memset(&req, 0, sizeof(req)); + req.type = CMD_THERMAL_QUERY_ABI; + req.query_abi.type = CMD_THERMAL_SET_TRIP; + + memset(&msg, 0, sizeof(msg)); + msg.mrq = MRQ_THERMAL; + msg.tx.data = &req; + msg.tx.size = sizeof(req); + msg.rx.data = &reply; + msg.rx.size = sizeof(reply); + + err = tegra_bpmp_transfer(bpmp, &msg); + if (err) + return err; + + if (msg.rx.ret == 0) { + *supported = true; + return 0; + } else if (msg.rx.ret == -BPMP_ENODEV) { + *supported = false; + return 0; + } else { + return -EINVAL; + } +} + static const struct thermal_zone_device_ops tegra_bpmp_of_thermal_ops = { .get_temp = tegra_bpmp_thermal_get_temp, .set_trips = tegra_bpmp_thermal_set_trips, }; +static const struct thermal_zone_device_ops tegra_bpmp_of_thermal_ops_notrips = { + .get_temp = tegra_bpmp_thermal_get_temp, +}; + static int tegra_bpmp_thermal_probe(struct platform_device *pdev) { struct tegra_bpmp *bpmp = dev_get_drvdata(pdev->dev.parent); + const struct thermal_zone_device_ops *thermal_ops; struct tegra_bpmp_thermal *tegra; struct thermal_zone_device *tzd; unsigned int i, max_num_zones; + bool supported; int err; + err = tegra_bpmp_thermal_trips_supported(bpmp, &supported); + if (err) { + dev_err(&pdev->dev, "failed to determine if trip points are supported\n"); + return err; + } + + if (supported) + thermal_ops = &tegra_bpmp_of_thermal_ops; + else + thermal_ops = &tegra_bpmp_of_thermal_ops_notrips; + tegra = devm_kzalloc(&pdev->dev, sizeof(*tegra), GFP_KERNEL); if (!tegra) return -ENOMEM; @@ -222,7 +272,7 @@ static int tegra_bpmp_thermal_probe(struct platform_device *pdev) } tzd = devm_thermal_of_zone_register( - &pdev->dev, i, zone, &tegra_bpmp_of_thermal_ops); + &pdev->dev, i, zone, thermal_ops); if (IS_ERR(tzd)) { if (PTR_ERR(tzd) == -EPROBE_DEFER) return -EPROBE_DEFER; diff --git a/drivers/thermal/thermal-generic-adc.c b/drivers/thermal/thermal-generic-adc.c index f4f1a04f8c0f..1717e4a19dcb 100644 --- a/drivers/thermal/thermal-generic-adc.c +++ b/drivers/thermal/thermal-generic-adc.c @@ -142,7 +142,6 @@ static int gadc_thermal_probe(struct platform_device *pdev) return ret; gti->dev = &pdev->dev; - platform_set_drvdata(pdev, gti); gti->tz_dev = devm_thermal_of_zone_register(&pdev->dev, 0, gti, &gadc_thermal_ops); diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index a59700593d32..0bdde1ab5d8b 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -1266,7 +1266,7 @@ thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *t return ERR_PTR(-EINVAL); } - if (num_trips > 0 && (!ops->get_trip_type || !ops->get_trip_temp) && !trips) + if (num_trips > 0 && !trips) return ERR_PTR(-EINVAL); if (!thermal_class) diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h index 04513f9fbfa1..de884bea28b6 100644 --- a/drivers/thermal/thermal_core.h +++ b/drivers/thermal/thermal_core.h @@ -70,7 +70,7 @@ static inline bool cdev_is_power_actor(struct thermal_cooling_device *cdev) void thermal_cdev_update(struct thermal_cooling_device *); void __thermal_cdev_update(struct thermal_cooling_device *cdev); -int get_tz_trend(struct thermal_zone_device *tz, int trip); +int get_tz_trend(struct thermal_zone_device *tz, int trip_index); struct thermal_instance * get_thermal_instance(struct thermal_zone_device *tz, diff --git a/drivers/thermal/thermal_helpers.c b/drivers/thermal/thermal_helpers.c index cfba0965a22d..4d66372c9629 100644 --- a/drivers/thermal/thermal_helpers.c +++ b/drivers/thermal/thermal_helpers.c @@ -22,8 +22,9 @@ #include "thermal_core.h" #include "thermal_trace.h" -int get_tz_trend(struct thermal_zone_device *tz, int trip) +int get_tz_trend(struct thermal_zone_device *tz, int trip_index) { + struct thermal_trip *trip = tz->trips ? &tz->trips[trip_index] : NULL; enum thermal_trend trend; if (tz->emul_temperature || !tz->ops->get_trend || diff --git a/drivers/thermal/thermal_trip.c b/drivers/thermal/thermal_trip.c index 53115cfdfd42..024e2e365a26 100644 --- a/drivers/thermal/thermal_trip.c +++ b/drivers/thermal/thermal_trip.c @@ -101,29 +101,11 @@ void __thermal_zone_set_trips(struct thermal_zone_device *tz) int __thermal_zone_get_trip(struct thermal_zone_device *tz, int trip_id, struct thermal_trip *trip) { - int ret; - - if (!tz || trip_id < 0 || trip_id >= tz->num_trips || !trip) + if (!tz || !tz->trips || trip_id < 0 || trip_id >= tz->num_trips || !trip) return -EINVAL; - if (tz->trips) { - *trip = tz->trips[trip_id]; - return 0; - } - - if (tz->ops->get_trip_hyst) { - ret = tz->ops->get_trip_hyst(tz, trip_id, &trip->hysteresis); - if (ret) - return ret; - } else { - trip->hysteresis = 0; - } - - ret = tz->ops->get_trip_temp(tz, trip_id, &trip->temperature); - if (ret) - return ret; - - return tz->ops->get_trip_type(tz, trip_id, &trip->type); + *trip = tz->trips[trip_id]; + return 0; } EXPORT_SYMBOL_GPL(__thermal_zone_get_trip); diff --git a/drivers/thermal/ti-soc-thermal/ti-bandgap.c b/drivers/thermal/ti-soc-thermal/ti-bandgap.c index a1c9a1530183..0c2eb9c6e58b 100644 --- a/drivers/thermal/ti-soc-thermal/ti-bandgap.c +++ b/drivers/thermal/ti-soc-thermal/ti-bandgap.c @@ -314,7 +314,7 @@ int ti_bandgap_adc_to_mcelsius(struct ti_bandgap *bgp, int adc_val, int *t) */ static inline int ti_bandgap_validate(struct ti_bandgap *bgp, int id) { - if (!bgp || IS_ERR(bgp)) { + if (IS_ERR_OR_NULL(bgp)) { pr_err("%s: invalid bandgap pointer\n", __func__); return -EINVAL; } diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c index d414a4b7a94a..6ba2613627e1 100644 --- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c +++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c @@ -109,7 +109,8 @@ static inline int __ti_thermal_get_temp(struct thermal_zone_device *tz, int *tem return ret; } -static int __ti_thermal_get_trend(struct thermal_zone_device *tz, int trip, enum thermal_trend *trend) +static int __ti_thermal_get_trend(struct thermal_zone_device *tz, + struct thermal_trip *trip, enum thermal_trend *trend) { struct ti_thermal_data *data = thermal_zone_device_priv(tz); struct ti_bandgap *bgp; diff --git a/drivers/vdpa/mlx5/core/mlx5_vdpa.h b/drivers/vdpa/mlx5/core/mlx5_vdpa.h index b53420e874ac..ca56242972b3 100644 --- a/drivers/vdpa/mlx5/core/mlx5_vdpa.h +++ b/drivers/vdpa/mlx5/core/mlx5_vdpa.h @@ -100,9 +100,6 @@ struct mlx5_vdpa_dev { bool suspended; }; -int mlx5_vdpa_alloc_pd(struct mlx5_vdpa_dev *dev, u32 *pdn, u16 uid); -int mlx5_vdpa_dealloc_pd(struct mlx5_vdpa_dev *dev, u32 pdn, u16 uid); -int mlx5_vdpa_get_null_mkey(struct mlx5_vdpa_dev *dev, u32 *null_mkey); int mlx5_vdpa_create_tis(struct mlx5_vdpa_dev *mvdev, void *in, u32 *tisn); void mlx5_vdpa_destroy_tis(struct mlx5_vdpa_dev *mvdev, u32 tisn); int mlx5_vdpa_create_rqt(struct mlx5_vdpa_dev *mvdev, void *in, int inlen, u32 *rqtn); diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim.c b/drivers/vdpa/vdpa_sim/vdpa_sim.c index d343af4fa60e..76d41058add9 100644 --- a/drivers/vdpa/vdpa_sim/vdpa_sim.c +++ b/drivers/vdpa/vdpa_sim/vdpa_sim.c @@ -18,6 +18,7 @@ #include <linux/vdpa.h> #include <linux/vhost_iotlb.h> #include <uapi/linux/vdpa.h> +#include <uapi/linux/vhost_types.h> #include "vdpa_sim.h" @@ -410,6 +411,11 @@ static u64 vdpasim_get_device_features(struct vdpa_device *vdpa) return vdpasim->dev_attr.supported_features; } +static u64 vdpasim_get_backend_features(const struct vdpa_device *vdpa) +{ + return BIT_ULL(VHOST_BACKEND_F_ENABLE_AFTER_DRIVER_OK); +} + static int vdpasim_set_driver_features(struct vdpa_device *vdpa, u64 features) { struct vdpasim *vdpasim = vdpa_to_sim(vdpa); @@ -733,6 +739,7 @@ static const struct vdpa_config_ops vdpasim_config_ops = { .get_vq_align = vdpasim_get_vq_align, .get_vq_group = vdpasim_get_vq_group, .get_device_features = vdpasim_get_device_features, + .get_backend_features = vdpasim_get_backend_features, .set_driver_features = vdpasim_set_driver_features, .get_driver_features = vdpasim_get_driver_features, .set_config_cb = vdpasim_set_config_cb, @@ -770,6 +777,7 @@ static const struct vdpa_config_ops vdpasim_batch_config_ops = { .get_vq_align = vdpasim_get_vq_align, .get_vq_group = vdpasim_get_vq_group, .get_device_features = vdpasim_get_device_features, + .get_backend_features = vdpasim_get_backend_features, .set_driver_features = vdpasim_set_driver_features, .get_driver_features = vdpasim_get_driver_features, .set_config_cb = vdpasim_set_config_cb, diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c index b43e8680eee8..78379ffd2336 100644 --- a/drivers/vhost/vdpa.c +++ b/drivers/vhost/vdpa.c @@ -403,6 +403,17 @@ static long vhost_vdpa_get_features(struct vhost_vdpa *v, u64 __user *featurep) return 0; } +static u64 vhost_vdpa_get_backend_features(const struct vhost_vdpa *v) +{ + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + + if (!ops->get_backend_features) + return 0; + else + return ops->get_backend_features(vdpa); +} + static long vhost_vdpa_set_features(struct vhost_vdpa *v, u64 __user *featurep) { struct vdpa_device *vdpa = v->vdpa; @@ -680,7 +691,8 @@ static long vhost_vdpa_unlocked_ioctl(struct file *filep, return -EFAULT; if (features & ~(VHOST_VDPA_BACKEND_FEATURES | BIT_ULL(VHOST_BACKEND_F_SUSPEND) | - BIT_ULL(VHOST_BACKEND_F_RESUME))) + BIT_ULL(VHOST_BACKEND_F_RESUME) | + BIT_ULL(VHOST_BACKEND_F_ENABLE_AFTER_DRIVER_OK))) return -EOPNOTSUPP; if ((features & BIT_ULL(VHOST_BACKEND_F_SUSPEND)) && !vhost_vdpa_can_suspend(v)) @@ -741,6 +753,7 @@ static long vhost_vdpa_unlocked_ioctl(struct file *filep, features |= BIT_ULL(VHOST_BACKEND_F_SUSPEND); if (vhost_vdpa_can_resume(v)) features |= BIT_ULL(VHOST_BACKEND_F_RESUME); + features |= vhost_vdpa_get_backend_features(v); if (copy_to_user(featurep, &features, sizeof(features))) r = -EFAULT; break; diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index c5310eaf8b46..51d8f3299c10 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -172,6 +172,14 @@ struct vring_virtqueue { /* Host publishes avail event idx */ bool event; + /* Do DMA mapping by driver */ + bool premapped; + + /* Do unmap or not for desc. Just when premapped is False and + * use_dma_api is true, this is true. + */ + bool do_unmap; + /* Head of free buffer list. */ unsigned int free_head; /* Number we've added since last sync. */ @@ -355,10 +363,14 @@ static struct device *vring_dma_dev(const struct vring_virtqueue *vq) } /* Map one sg entry. */ -static dma_addr_t vring_map_one_sg(const struct vring_virtqueue *vq, - struct scatterlist *sg, - enum dma_data_direction direction) +static int vring_map_one_sg(const struct vring_virtqueue *vq, struct scatterlist *sg, + enum dma_data_direction direction, dma_addr_t *addr) { + if (vq->premapped) { + *addr = sg_dma_address(sg); + return 0; + } + if (!vq->use_dma_api) { /* * If DMA is not used, KMSAN doesn't know that the scatterlist @@ -366,7 +378,8 @@ static dma_addr_t vring_map_one_sg(const struct vring_virtqueue *vq, * depending on the direction. */ kmsan_handle_dma(sg_page(sg), sg->offset, sg->length, direction); - return (dma_addr_t)sg_phys(sg); + *addr = (dma_addr_t)sg_phys(sg); + return 0; } /* @@ -374,9 +387,14 @@ static dma_addr_t vring_map_one_sg(const struct vring_virtqueue *vq, * the way it expects (we don't guarantee that the scatterlist * will exist for the lifetime of the mapping). */ - return dma_map_page(vring_dma_dev(vq), + *addr = dma_map_page(vring_dma_dev(vq), sg_page(sg), sg->offset, sg->length, direction); + + if (dma_mapping_error(vring_dma_dev(vq), *addr)) + return -ENOMEM; + + return 0; } static dma_addr_t vring_map_single(const struct vring_virtqueue *vq, @@ -427,7 +445,7 @@ static void vring_unmap_one_split_indirect(const struct vring_virtqueue *vq, { u16 flags; - if (!vq->use_dma_api) + if (!vq->do_unmap) return; flags = virtio16_to_cpu(vq->vq.vdev, desc->flags); @@ -445,18 +463,21 @@ static unsigned int vring_unmap_one_split(const struct vring_virtqueue *vq, struct vring_desc_extra *extra = vq->split.desc_extra; u16 flags; - if (!vq->use_dma_api) - goto out; - flags = extra[i].flags; if (flags & VRING_DESC_F_INDIRECT) { + if (!vq->use_dma_api) + goto out; + dma_unmap_single(vring_dma_dev(vq), extra[i].addr, extra[i].len, (flags & VRING_DESC_F_WRITE) ? DMA_FROM_DEVICE : DMA_TO_DEVICE); } else { + if (!vq->do_unmap) + goto out; + dma_unmap_page(vring_dma_dev(vq), extra[i].addr, extra[i].len, @@ -588,8 +609,9 @@ static inline int virtqueue_add_split(struct virtqueue *_vq, for (n = 0; n < out_sgs; n++) { for (sg = sgs[n]; sg; sg = sg_next(sg)) { - dma_addr_t addr = vring_map_one_sg(vq, sg, DMA_TO_DEVICE); - if (vring_mapping_error(vq, addr)) + dma_addr_t addr; + + if (vring_map_one_sg(vq, sg, DMA_TO_DEVICE, &addr)) goto unmap_release; prev = i; @@ -603,8 +625,9 @@ static inline int virtqueue_add_split(struct virtqueue *_vq, } for (; n < (out_sgs + in_sgs); n++) { for (sg = sgs[n]; sg; sg = sg_next(sg)) { - dma_addr_t addr = vring_map_one_sg(vq, sg, DMA_FROM_DEVICE); - if (vring_mapping_error(vq, addr)) + dma_addr_t addr; + + if (vring_map_one_sg(vq, sg, DMA_FROM_DEVICE, &addr)) goto unmap_release; prev = i; @@ -620,7 +643,7 @@ static inline int virtqueue_add_split(struct virtqueue *_vq, } /* Last one doesn't continue. */ desc[prev].flags &= cpu_to_virtio16(_vq->vdev, ~VRING_DESC_F_NEXT); - if (!indirect && vq->use_dma_api) + if (!indirect && vq->do_unmap) vq->split.desc_extra[prev & (vq->split.vring.num - 1)].flags &= ~VRING_DESC_F_NEXT; @@ -629,8 +652,12 @@ static inline int virtqueue_add_split(struct virtqueue *_vq, dma_addr_t addr = vring_map_single( vq, desc, total_sg * sizeof(struct vring_desc), DMA_TO_DEVICE); - if (vring_mapping_error(vq, addr)) + if (vring_mapping_error(vq, addr)) { + if (vq->premapped) + goto free_indirect; + goto unmap_release; + } virtqueue_add_desc_split(_vq, vq->split.vring.desc, head, addr, @@ -696,6 +723,7 @@ unmap_release: i = vring_unmap_one_split(vq, i); } +free_indirect: if (indirect) kfree(desc); @@ -774,8 +802,10 @@ static void detach_buf_split(struct vring_virtqueue *vq, unsigned int head, VRING_DESC_F_INDIRECT)); BUG_ON(len == 0 || len % sizeof(struct vring_desc)); - for (j = 0; j < len / sizeof(struct vring_desc); j++) - vring_unmap_one_split_indirect(vq, &indir_desc[j]); + if (vq->do_unmap) { + for (j = 0; j < len / sizeof(struct vring_desc); j++) + vring_unmap_one_split_indirect(vq, &indir_desc[j]); + } kfree(indir_desc); vq->split.desc_state[head].indir_desc = NULL; @@ -1195,17 +1225,20 @@ static void vring_unmap_extra_packed(const struct vring_virtqueue *vq, { u16 flags; - if (!vq->use_dma_api) - return; - flags = extra->flags; if (flags & VRING_DESC_F_INDIRECT) { + if (!vq->use_dma_api) + return; + dma_unmap_single(vring_dma_dev(vq), extra->addr, extra->len, (flags & VRING_DESC_F_WRITE) ? DMA_FROM_DEVICE : DMA_TO_DEVICE); } else { + if (!vq->do_unmap) + return; + dma_unmap_page(vring_dma_dev(vq), extra->addr, extra->len, (flags & VRING_DESC_F_WRITE) ? @@ -1218,7 +1251,7 @@ static void vring_unmap_desc_packed(const struct vring_virtqueue *vq, { u16 flags; - if (!vq->use_dma_api) + if (!vq->do_unmap) return; flags = le16_to_cpu(desc->flags); @@ -1279,9 +1312,8 @@ static int virtqueue_add_indirect_packed(struct vring_virtqueue *vq, for (n = 0; n < out_sgs + in_sgs; n++) { for (sg = sgs[n]; sg; sg = sg_next(sg)) { - addr = vring_map_one_sg(vq, sg, n < out_sgs ? - DMA_TO_DEVICE : DMA_FROM_DEVICE); - if (vring_mapping_error(vq, addr)) + if (vring_map_one_sg(vq, sg, n < out_sgs ? + DMA_TO_DEVICE : DMA_FROM_DEVICE, &addr)) goto unmap_release; desc[i].flags = cpu_to_le16(n < out_sgs ? @@ -1296,15 +1328,19 @@ static int virtqueue_add_indirect_packed(struct vring_virtqueue *vq, addr = vring_map_single(vq, desc, total_sg * sizeof(struct vring_packed_desc), DMA_TO_DEVICE); - if (vring_mapping_error(vq, addr)) + if (vring_mapping_error(vq, addr)) { + if (vq->premapped) + goto free_desc; + goto unmap_release; + } vq->packed.vring.desc[head].addr = cpu_to_le64(addr); vq->packed.vring.desc[head].len = cpu_to_le32(total_sg * sizeof(struct vring_packed_desc)); vq->packed.vring.desc[head].id = cpu_to_le16(id); - if (vq->use_dma_api) { + if (vq->do_unmap) { vq->packed.desc_extra[id].addr = addr; vq->packed.desc_extra[id].len = total_sg * sizeof(struct vring_packed_desc); @@ -1355,6 +1391,7 @@ unmap_release: for (i = 0; i < err_idx; i++) vring_unmap_desc_packed(vq, &desc[i]); +free_desc: kfree(desc); END_USE(vq); @@ -1426,9 +1463,10 @@ static inline int virtqueue_add_packed(struct virtqueue *_vq, c = 0; for (n = 0; n < out_sgs + in_sgs; n++) { for (sg = sgs[n]; sg; sg = sg_next(sg)) { - dma_addr_t addr = vring_map_one_sg(vq, sg, n < out_sgs ? - DMA_TO_DEVICE : DMA_FROM_DEVICE); - if (vring_mapping_error(vq, addr)) + dma_addr_t addr; + + if (vring_map_one_sg(vq, sg, n < out_sgs ? + DMA_TO_DEVICE : DMA_FROM_DEVICE, &addr)) goto unmap_release; flags = cpu_to_le16(vq->packed.avail_used_flags | @@ -1443,7 +1481,7 @@ static inline int virtqueue_add_packed(struct virtqueue *_vq, desc[i].len = cpu_to_le32(sg->length); desc[i].id = cpu_to_le16(id); - if (unlikely(vq->use_dma_api)) { + if (unlikely(vq->do_unmap)) { vq->packed.desc_extra[curr].addr = addr; vq->packed.desc_extra[curr].len = sg->length; vq->packed.desc_extra[curr].flags = @@ -1461,7 +1499,7 @@ static inline int virtqueue_add_packed(struct virtqueue *_vq, } } - if (i < head) + if (i <= head) vq->packed.avail_wrap_counter ^= 1; /* We're using some buffers from the free list. */ @@ -1577,7 +1615,7 @@ static void detach_buf_packed(struct vring_virtqueue *vq, vq->free_head = id; vq->vq.num_free += state->num; - if (unlikely(vq->use_dma_api)) { + if (unlikely(vq->do_unmap)) { curr = id; for (i = 0; i < state->num; i++) { vring_unmap_extra_packed(vq, @@ -1594,7 +1632,7 @@ static void detach_buf_packed(struct vring_virtqueue *vq, if (!desc) return; - if (vq->use_dma_api) { + if (vq->do_unmap) { len = vq->packed.desc_extra[id].len; for (i = 0; i < len / sizeof(struct vring_packed_desc); i++) @@ -2052,6 +2090,8 @@ static struct virtqueue *vring_create_virtqueue_packed( vq->packed_ring = true; vq->dma_dev = dma_dev; vq->use_dma_api = vring_use_dma_api(vdev); + vq->premapped = false; + vq->do_unmap = vq->use_dma_api; vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) && !context; @@ -2112,6 +2152,43 @@ err_ring: return -ENOMEM; } +static int virtqueue_disable_and_recycle(struct virtqueue *_vq, + void (*recycle)(struct virtqueue *vq, void *buf)) +{ + struct vring_virtqueue *vq = to_vvq(_vq); + struct virtio_device *vdev = vq->vq.vdev; + void *buf; + int err; + + if (!vq->we_own_ring) + return -EPERM; + + if (!vdev->config->disable_vq_and_reset) + return -ENOENT; + + if (!vdev->config->enable_vq_after_reset) + return -ENOENT; + + err = vdev->config->disable_vq_and_reset(_vq); + if (err) + return err; + + while ((buf = virtqueue_detach_unused_buf(_vq)) != NULL) + recycle(_vq, buf); + + return 0; +} + +static int virtqueue_enable_after_reset(struct virtqueue *_vq) +{ + struct vring_virtqueue *vq = to_vvq(_vq); + struct virtio_device *vdev = vq->vq.vdev; + + if (vdev->config->enable_vq_after_reset(_vq)) + return -EBUSY; + + return 0; +} /* * Generic functions and exported symbols. @@ -2238,6 +2315,23 @@ int virtqueue_add_inbuf_ctx(struct virtqueue *vq, EXPORT_SYMBOL_GPL(virtqueue_add_inbuf_ctx); /** + * virtqueue_dma_dev - get the dma dev + * @_vq: the struct virtqueue we're talking about. + * + * Returns the dma dev. That can been used for dma api. + */ +struct device *virtqueue_dma_dev(struct virtqueue *_vq) +{ + struct vring_virtqueue *vq = to_vvq(_vq); + + if (vq->use_dma_api) + return vring_dma_dev(vq); + else + return NULL; +} +EXPORT_SYMBOL_GPL(virtqueue_dma_dev); + +/** * virtqueue_kick_prepare - first half of split virtqueue_kick call. * @_vq: the struct virtqueue * @@ -2541,6 +2635,8 @@ static struct virtqueue *__vring_new_virtqueue(unsigned int index, #endif vq->dma_dev = dma_dev; vq->use_dma_api = vring_use_dma_api(vdev); + vq->premapped = false; + vq->do_unmap = vq->use_dma_api; vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) && !context; @@ -2619,7 +2715,7 @@ EXPORT_SYMBOL_GPL(vring_create_virtqueue_dma); * virtqueue_resize - resize the vring of vq * @_vq: the struct virtqueue we're talking about. * @num: new ring num - * @recycle: callback for recycle the useless buffer + * @recycle: callback to recycle unused buffers * * When it is really necessary to create a new vring, it will set the current vq * into the reset state. Then call the passed callback to recycle the buffer @@ -2643,13 +2739,8 @@ int virtqueue_resize(struct virtqueue *_vq, u32 num, void (*recycle)(struct virtqueue *vq, void *buf)) { struct vring_virtqueue *vq = to_vvq(_vq); - struct virtio_device *vdev = vq->vq.vdev; - void *buf; int err; - if (!vq->we_own_ring) - return -EPERM; - if (num > vq->vq.num_max) return -E2BIG; @@ -2659,31 +2750,101 @@ int virtqueue_resize(struct virtqueue *_vq, u32 num, if ((vq->packed_ring ? vq->packed.vring.num : vq->split.vring.num) == num) return 0; - if (!vdev->config->disable_vq_and_reset) - return -ENOENT; - - if (!vdev->config->enable_vq_after_reset) - return -ENOENT; - - err = vdev->config->disable_vq_and_reset(_vq); + err = virtqueue_disable_and_recycle(_vq, recycle); if (err) return err; - while ((buf = virtqueue_detach_unused_buf(_vq)) != NULL) - recycle(_vq, buf); - if (vq->packed_ring) err = virtqueue_resize_packed(_vq, num); else err = virtqueue_resize_split(_vq, num); - if (vdev->config->enable_vq_after_reset(_vq)) - return -EBUSY; - - return err; + return virtqueue_enable_after_reset(_vq); } EXPORT_SYMBOL_GPL(virtqueue_resize); +/** + * virtqueue_set_dma_premapped - set the vring premapped mode + * @_vq: the struct virtqueue we're talking about. + * + * Enable the premapped mode of the vq. + * + * The vring in premapped mode does not do dma internally, so the driver must + * do dma mapping in advance. The driver must pass the dma_address through + * dma_address of scatterlist. When the driver got a used buffer from + * the vring, it has to unmap the dma address. + * + * This function must be called immediately after creating the vq, or after vq + * reset, and before adding any buffers to it. + * + * Caller must ensure we don't call this with other virtqueue operations + * at the same time (except where noted). + * + * Returns zero or a negative error. + * 0: success. + * -EINVAL: vring does not use the dma api, so we can not enable premapped mode. + */ +int virtqueue_set_dma_premapped(struct virtqueue *_vq) +{ + struct vring_virtqueue *vq = to_vvq(_vq); + u32 num; + + START_USE(vq); + + num = vq->packed_ring ? vq->packed.vring.num : vq->split.vring.num; + + if (num != vq->vq.num_free) { + END_USE(vq); + return -EINVAL; + } + + if (!vq->use_dma_api) { + END_USE(vq); + return -EINVAL; + } + + vq->premapped = true; + vq->do_unmap = false; + + END_USE(vq); + + return 0; +} +EXPORT_SYMBOL_GPL(virtqueue_set_dma_premapped); + +/** + * virtqueue_reset - detach and recycle all unused buffers + * @_vq: the struct virtqueue we're talking about. + * @recycle: callback to recycle unused buffers + * + * Caller must ensure we don't call this with other virtqueue operations + * at the same time (except where noted). + * + * Returns zero or a negative error. + * 0: success. + * -EBUSY: Failed to sync with device, vq may not work properly + * -ENOENT: Transport or device not supported + * -EPERM: Operation not permitted + */ +int virtqueue_reset(struct virtqueue *_vq, + void (*recycle)(struct virtqueue *vq, void *buf)) +{ + struct vring_virtqueue *vq = to_vvq(_vq); + int err; + + err = virtqueue_disable_and_recycle(_vq, recycle); + if (err) + return err; + + if (vq->packed_ring) + virtqueue_reinit_packed(vq); + else + virtqueue_reinit_split(vq); + + return virtqueue_enable_after_reset(_vq); +} +EXPORT_SYMBOL_GPL(virtqueue_reset); + /* Only available for split ring */ struct virtqueue *vring_new_virtqueue(unsigned int index, unsigned int num, @@ -2945,4 +3106,149 @@ const struct vring *virtqueue_get_vring(const struct virtqueue *vq) } EXPORT_SYMBOL_GPL(virtqueue_get_vring); +/** + * virtqueue_dma_map_single_attrs - map DMA for _vq + * @_vq: the struct virtqueue we're talking about. + * @ptr: the pointer of the buffer to do dma + * @size: the size of the buffer to do dma + * @dir: DMA direction + * @attrs: DMA Attrs + * + * The caller calls this to do dma mapping in advance. The DMA address can be + * passed to this _vq when it is in pre-mapped mode. + * + * return DMA address. Caller should check that by virtqueue_dma_mapping_error(). + */ +dma_addr_t virtqueue_dma_map_single_attrs(struct virtqueue *_vq, void *ptr, + size_t size, + enum dma_data_direction dir, + unsigned long attrs) +{ + struct vring_virtqueue *vq = to_vvq(_vq); + + if (!vq->use_dma_api) + return (dma_addr_t)virt_to_phys(ptr); + + return dma_map_single_attrs(vring_dma_dev(vq), ptr, size, dir, attrs); +} +EXPORT_SYMBOL_GPL(virtqueue_dma_map_single_attrs); + +/** + * virtqueue_dma_unmap_single_attrs - unmap DMA for _vq + * @_vq: the struct virtqueue we're talking about. + * @addr: the dma address to unmap + * @size: the size of the buffer + * @dir: DMA direction + * @attrs: DMA Attrs + * + * Unmap the address that is mapped by the virtqueue_dma_map_* APIs. + * + */ +void virtqueue_dma_unmap_single_attrs(struct virtqueue *_vq, dma_addr_t addr, + size_t size, enum dma_data_direction dir, + unsigned long attrs) +{ + struct vring_virtqueue *vq = to_vvq(_vq); + + if (!vq->use_dma_api) + return; + + dma_unmap_single_attrs(vring_dma_dev(vq), addr, size, dir, attrs); +} +EXPORT_SYMBOL_GPL(virtqueue_dma_unmap_single_attrs); + +/** + * virtqueue_dma_mapping_error - check dma address + * @_vq: the struct virtqueue we're talking about. + * @addr: DMA address + * + * Returns 0 means dma valid. Other means invalid dma address. + */ +int virtqueue_dma_mapping_error(struct virtqueue *_vq, dma_addr_t addr) +{ + struct vring_virtqueue *vq = to_vvq(_vq); + + if (!vq->use_dma_api) + return 0; + + return dma_mapping_error(vring_dma_dev(vq), addr); +} +EXPORT_SYMBOL_GPL(virtqueue_dma_mapping_error); + +/** + * virtqueue_dma_need_sync - check a dma address needs sync + * @_vq: the struct virtqueue we're talking about. + * @addr: DMA address + * + * Check if the dma address mapped by the virtqueue_dma_map_* APIs needs to be + * synchronized + * + * return bool + */ +bool virtqueue_dma_need_sync(struct virtqueue *_vq, dma_addr_t addr) +{ + struct vring_virtqueue *vq = to_vvq(_vq); + + if (!vq->use_dma_api) + return false; + + return dma_need_sync(vring_dma_dev(vq), addr); +} +EXPORT_SYMBOL_GPL(virtqueue_dma_need_sync); + +/** + * virtqueue_dma_sync_single_range_for_cpu - dma sync for cpu + * @_vq: the struct virtqueue we're talking about. + * @addr: DMA address + * @offset: DMA address offset + * @size: buf size for sync + * @dir: DMA direction + * + * Before calling this function, use virtqueue_dma_need_sync() to confirm that + * the DMA address really needs to be synchronized + * + */ +void virtqueue_dma_sync_single_range_for_cpu(struct virtqueue *_vq, + dma_addr_t addr, + unsigned long offset, size_t size, + enum dma_data_direction dir) +{ + struct vring_virtqueue *vq = to_vvq(_vq); + struct device *dev = vring_dma_dev(vq); + + if (!vq->use_dma_api) + return; + + dma_sync_single_range_for_cpu(dev, addr, offset, size, + DMA_BIDIRECTIONAL); +} +EXPORT_SYMBOL_GPL(virtqueue_dma_sync_single_range_for_cpu); + +/** + * virtqueue_dma_sync_single_range_for_device - dma sync for device + * @_vq: the struct virtqueue we're talking about. + * @addr: DMA address + * @offset: DMA address offset + * @size: buf size for sync + * @dir: DMA direction + * + * Before calling this function, use virtqueue_dma_need_sync() to confirm that + * the DMA address really needs to be synchronized + */ +void virtqueue_dma_sync_single_range_for_device(struct virtqueue *_vq, + dma_addr_t addr, + unsigned long offset, size_t size, + enum dma_data_direction dir) +{ + struct vring_virtqueue *vq = to_vvq(_vq); + struct device *dev = vring_dma_dev(vq); + + if (!vq->use_dma_api) + return; + + dma_sync_single_range_for_device(dev, addr, offset, size, + DMA_BIDIRECTIONAL); +} +EXPORT_SYMBOL_GPL(virtqueue_dma_sync_single_range_for_device); + MODULE_LICENSE("GPL"); diff --git a/drivers/virtio/virtio_vdpa.c b/drivers/virtio/virtio_vdpa.c index 961161da5900..06ce6d8c2e00 100644 --- a/drivers/virtio/virtio_vdpa.c +++ b/drivers/virtio/virtio_vdpa.c @@ -366,11 +366,14 @@ static int virtio_vdpa_find_vqs(struct virtio_device *vdev, unsigned int nvqs, struct irq_affinity default_affd = { 0 }; struct cpumask *masks; struct vdpa_callback cb; + bool has_affinity = desc && ops->set_vq_affinity; int i, err, queue_idx = 0; - masks = create_affinity_masks(nvqs, desc ? desc : &default_affd); - if (!masks) - return -ENOMEM; + if (has_affinity) { + masks = create_affinity_masks(nvqs, desc ? desc : &default_affd); + if (!masks) + return -ENOMEM; + } for (i = 0; i < nvqs; ++i) { if (!names[i]) { @@ -386,20 +389,22 @@ static int virtio_vdpa_find_vqs(struct virtio_device *vdev, unsigned int nvqs, goto err_setup_vq; } - if (ops->set_vq_affinity) + if (has_affinity) ops->set_vq_affinity(vdpa, i, &masks[i]); } cb.callback = virtio_vdpa_config_cb; cb.private = vd_dev; ops->set_config_cb(vdpa, &cb); - kfree(masks); + if (has_affinity) + kfree(masks); return 0; err_setup_vq: virtio_vdpa_del_vqs(vdev); - kfree(masks); + if (has_affinity) + kfree(masks); return err; } diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 0f2aa36a9913..3dd5be96691b 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -4,6 +4,7 @@ #include <linux/hugetlb.h> #include <linux/huge_mm.h> #include <linux/mount.h> +#include <linux/ksm.h> #include <linux/seq_file.h> #include <linux/highmem.h> #include <linux/ptrace.h> @@ -396,6 +397,7 @@ struct mem_size_stats { unsigned long swap; unsigned long shared_hugetlb; unsigned long private_hugetlb; + unsigned long ksm; u64 pss; u64 pss_anon; u64 pss_file; @@ -452,6 +454,9 @@ static void smaps_account(struct mem_size_stats *mss, struct page *page, mss->lazyfree += size; } + if (PageKsm(page)) + mss->ksm += size; + mss->resident += size; /* Accumulate the size in pages that have been accessed. */ if (young || page_is_young(page) || PageReferenced(page)) @@ -825,6 +830,7 @@ static void __show_smap(struct seq_file *m, const struct mem_size_stats *mss, SEQ_PUT_DEC(" kB\nPrivate_Dirty: ", mss->private_dirty); SEQ_PUT_DEC(" kB\nReferenced: ", mss->referenced); SEQ_PUT_DEC(" kB\nAnonymous: ", mss->anonymous); + SEQ_PUT_DEC(" kB\nKSM: ", mss->ksm); SEQ_PUT_DEC(" kB\nLazyFree: ", mss->lazyfree); SEQ_PUT_DEC(" kB\nAnonHugePages: ", mss->anonymous_thp); SEQ_PUT_DEC(" kB\nShmemPmdMapped: ", mss->shmem_thp); diff --git a/include/asm-generic/current.h b/include/asm-generic/current.h index 3a2e224b9fa0..9c2aeecbd05a 100644 --- a/include/asm-generic/current.h +++ b/include/asm-generic/current.h @@ -2,9 +2,11 @@ #ifndef __ASM_GENERIC_CURRENT_H #define __ASM_GENERIC_CURRENT_H +#ifndef __ASSEMBLY__ #include <linux/thread_info.h> #define get_current() (current_thread_info()->task) #define current get_current() +#endif #endif /* __ASM_GENERIC_CURRENT_H */ diff --git a/include/asm-generic/hyperv-tlfs.h b/include/asm-generic/hyperv-tlfs.h index f4e4cc4f965f..fdac4a1714ec 100644 --- a/include/asm-generic/hyperv-tlfs.h +++ b/include/asm-generic/hyperv-tlfs.h @@ -223,6 +223,7 @@ enum HV_GENERIC_SET_FORMAT { #define HV_STATUS_INVALID_PORT_ID 17 #define HV_STATUS_INVALID_CONNECTION_ID 18 #define HV_STATUS_INSUFFICIENT_BUFFERS 19 +#define HV_STATUS_TIME_OUT 120 #define HV_STATUS_VTL_ALREADY_ENABLED 134 /* diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h index a8f4b653ef4e..cecd2b7bd033 100644 --- a/include/asm-generic/mshyperv.h +++ b/include/asm-generic/mshyperv.h @@ -36,18 +36,25 @@ struct ms_hyperv_info { u32 nested_features; u32 max_vp_index; u32 max_lp_index; - u32 isolation_config_a; + union { + u32 isolation_config_a; + struct { + u32 paravisor_present : 1; + u32 reserved_a1 : 31; + }; + }; union { u32 isolation_config_b; struct { u32 cvm_type : 4; - u32 reserved1 : 1; + u32 reserved_b1 : 1; u32 shared_gpa_boundary_active : 1; u32 shared_gpa_boundary_bits : 6; - u32 reserved2 : 20; + u32 reserved_b2 : 20; }; }; u64 shared_gpa_boundary; + u8 vtl; }; extern struct ms_hyperv_info ms_hyperv; extern bool hv_nested; @@ -57,7 +64,8 @@ extern void * __percpu *hyperv_pcpu_output_arg; extern u64 hv_do_hypercall(u64 control, void *inputaddr, void *outputaddr); extern u64 hv_do_fast_hypercall8(u16 control, u64 input8); -extern bool hv_isolation_type_snp(void); +bool hv_isolation_type_snp(void); +bool hv_isolation_type_tdx(void); /* Helper functions that provide a consistent pattern for checking Hyper-V hypercall status. */ static inline int hv_result(u64 status) @@ -274,6 +282,7 @@ enum hv_isolation_type hv_get_isolation_type(void); bool hv_is_isolation_supported(void); bool hv_isolation_type_snp(void); u64 hv_ghcb_hypercall(u64 control, void *input, void *output, u32 input_size); +u64 hv_tdx_hypercall(u64 control, u64 param1, u64 param2); void hyperv_cleanup(void); bool hv_query_ext_cap(u64 cap_query); void hv_setup_dma_ops(struct device *dev, bool coherent); diff --git a/include/linux/console.h b/include/linux/console.h index d3195664baa5..7de11c763eb3 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -154,6 +154,8 @@ static inline int con_debug_leave(void) * receiving the printk spam for obvious reasons. * @CON_EXTENDED: The console supports the extended output format of * /dev/kmesg which requires a larger output buffer. + * @CON_SUSPENDED: Indicates if a console is suspended. If true, the + * printing callbacks must not be called. */ enum cons_flags { CON_PRINTBUFFER = BIT(0), @@ -163,6 +165,7 @@ enum cons_flags { CON_ANYTIME = BIT(4), CON_BRL = BIT(5), CON_EXTENDED = BIT(6), + CON_SUSPENDED = BIT(7), }; /** diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 43b363a99215..71d186d6933a 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -141,6 +141,9 @@ struct cpufreq_policy { */ bool dvfs_possible_from_any_cpu; + /* Per policy boost enabled flag. */ + bool boost_enabled; + /* Cached frequency lookup from cpufreq_driver_resolve_freq. */ unsigned int cached_target_freq; unsigned int cached_resolved_idx; diff --git a/include/linux/export.h b/include/linux/export.h index beed8387e0a4..9911508a9604 100644 --- a/include/linux/export.h +++ b/include/linux/export.h @@ -50,7 +50,7 @@ extern struct module __this_module; __EXPORT_SYMBOL_REF(sym) ASM_NL \ .previous -#if !defined(CONFIG_MODULES) || defined(__DISABLE_EXPORTS) +#if defined(__DISABLE_EXPORTS) /* * Allow symbol exports to be disabled completely so that C code may @@ -75,7 +75,7 @@ extern struct module __this_module; __ADDRESSABLE(sym) \ asm(__stringify(___EXPORT_SYMBOL(sym, license, ns))) -#endif /* CONFIG_MODULES */ +#endif #ifdef DEFAULT_SYMBOL_NAMESPACE #define _EXPORT_SYMBOL(sym, license) __EXPORT_SYMBOL(sym, license, __stringify(DEFAULT_SYMBOL_NAMESPACE)) diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index 3ac3974b3c78..2b00faf98017 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -348,7 +348,7 @@ struct vmtransfer_page_packet_header { u8 sender_owns_set; u8 reserved; u32 range_cnt; - struct vmtransfer_page_range ranges[1]; + struct vmtransfer_page_range ranges[]; } __packed; struct vmgpadl_packet_header { @@ -665,8 +665,8 @@ struct vmbus_channel_initiate_contact { u64 interrupt_page; struct { u8 msg_sint; - u8 padding1[3]; - u32 padding2; + u8 msg_vtl; + u8 reserved[6]; }; }; u64 monitor_page1; diff --git a/include/linux/leds.h b/include/linux/leds.h index 7d428100b42b..aa16dc2a8230 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -100,6 +100,7 @@ struct led_classdev { const char *name; unsigned int brightness; unsigned int max_brightness; + unsigned int color; int flags; /* Lower 16 bits reflect status */ @@ -313,6 +314,8 @@ extern struct led_classdev *of_led_get(struct device_node *np, int index); extern void led_put(struct led_classdev *led_cdev); struct led_classdev *__must_check devm_of_led_get(struct device *dev, int index); +struct led_classdev *__must_check devm_of_led_get_optional(struct device *dev, + int index); /** * led_blink_set - set blinking with software fallback diff --git a/include/linux/mfd/88pm860x.h b/include/linux/mfd/88pm860x.h index 473545a2c425..6fa21791fc85 100644 --- a/include/linux/mfd/88pm860x.h +++ b/include/linux/mfd/88pm860x.h @@ -472,13 +472,7 @@ extern int pm860x_bulk_read(struct i2c_client *, int, int, unsigned char *); extern int pm860x_bulk_write(struct i2c_client *, int, int, unsigned char *); extern int pm860x_set_bits(struct i2c_client *, int, unsigned char, unsigned char); -extern int pm860x_page_reg_read(struct i2c_client *, int); extern int pm860x_page_reg_write(struct i2c_client *, int, unsigned char); extern int pm860x_page_bulk_read(struct i2c_client *, int, int, unsigned char *); -extern int pm860x_page_bulk_write(struct i2c_client *, int, int, - unsigned char *); -extern int pm860x_page_set_bits(struct i2c_client *, int, unsigned char, - unsigned char); - #endif /* __LINUX_MFD_88PM860X_H */ diff --git a/include/linux/mfd/abx500/ab8500.h b/include/linux/mfd/abx500/ab8500.h index 302a330c5c84..09fb3c56e7d7 100644 --- a/include/linux/mfd/abx500/ab8500.h +++ b/include/linux/mfd/abx500/ab8500.h @@ -382,10 +382,6 @@ struct ab8500_platform_data { struct ab8500_sysctrl_platform_data *sysctrl; }; -extern int ab8500_init(struct ab8500 *ab8500, - enum ab8500_version version); -extern int ab8500_exit(struct ab8500 *ab8500); - extern int ab8500_suspend(struct ab8500 *ab8500); static inline int is_ab8500(struct ab8500 *ab) diff --git a/include/linux/mfd/dbx500-prcmu.h b/include/linux/mfd/dbx500-prcmu.h index e7a7e70fdb38..dd0fc891b228 100644 --- a/include/linux/mfd/dbx500-prcmu.h +++ b/include/linux/mfd/dbx500-prcmu.h @@ -556,16 +556,6 @@ static inline void prcmu_clear(unsigned int reg, u32 bits) #define PRCMU_QOS_ARM_OPP 3 #define PRCMU_QOS_DEFAULT_VALUE -1 -static inline unsigned long prcmu_qos_get_cpufreq_opp_delay(void) -{ - return 0; -} - -static inline int prcmu_qos_requirement(int prcmu_qos_class) -{ - return 0; -} - static inline int prcmu_qos_add_requirement(int prcmu_qos_class, char *name, s32 value) { @@ -582,15 +572,4 @@ static inline void prcmu_qos_remove_requirement(int prcmu_qos_class, char *name) { } -static inline int prcmu_qos_add_notifier(int prcmu_qos_class, - struct notifier_block *notifier) -{ - return 0; -} -static inline int prcmu_qos_remove_notifier(int prcmu_qos_class, - struct notifier_block *notifier) -{ - return 0; -} - #endif /* __MACH_PRCMU_H */ diff --git a/include/linux/mfd/hi655x-pmic.h b/include/linux/mfd/hi655x-pmic.h index 6a012784dd1b..194556851ccf 100644 --- a/include/linux/mfd/hi655x-pmic.h +++ b/include/linux/mfd/hi655x-pmic.h @@ -52,7 +52,6 @@ #define OTMP_D1R_INT_MASK BIT(OTMP_D1R_INT) struct hi655x_pmic { - struct resource *res; struct device *dev; struct regmap *regmap; struct gpio_desc *gpio; diff --git a/include/linux/mfd/max77686-private.h b/include/linux/mfd/max77686-private.h index 3acceeedbaba..ea635d12a741 100644 --- a/include/linux/mfd/max77686-private.h +++ b/include/linux/mfd/max77686-private.h @@ -441,8 +441,4 @@ enum max77686_types { TYPE_MAX77802, }; -extern int max77686_irq_init(struct max77686_dev *max77686); -extern void max77686_irq_exit(struct max77686_dev *max77686); -extern int max77686_irq_resume(struct max77686_dev *max77686); - #endif /* __LINUX_MFD_MAX77686_PRIV_H */ diff --git a/include/linux/mfd/rz-mtu3.h b/include/linux/mfd/rz-mtu3.h index c5173bc06270..8421d49500bf 100644 --- a/include/linux/mfd/rz-mtu3.h +++ b/include/linux/mfd/rz-mtu3.h @@ -151,7 +151,6 @@ struct rz_mtu3 { void *priv_data; }; -#if IS_ENABLED(CONFIG_RZ_MTU3) static inline bool rz_mtu3_request_channel(struct rz_mtu3_channel *ch) { mutex_lock(&ch->lock); @@ -188,70 +187,5 @@ void rz_mtu3_32bit_ch_write(struct rz_mtu3_channel *ch, u16 off, u32 val); void rz_mtu3_shared_reg_write(struct rz_mtu3_channel *ch, u16 off, u16 val); void rz_mtu3_shared_reg_update_bit(struct rz_mtu3_channel *ch, u16 off, u16 pos, u8 val); -#else -static inline bool rz_mtu3_request_channel(struct rz_mtu3_channel *ch) -{ - return false; -} - -static inline void rz_mtu3_release_channel(struct rz_mtu3_channel *ch) -{ -} - -static inline bool rz_mtu3_is_enabled(struct rz_mtu3_channel *ch) -{ - return false; -} - -static inline void rz_mtu3_disable(struct rz_mtu3_channel *ch) -{ -} - -static inline int rz_mtu3_enable(struct rz_mtu3_channel *ch) -{ - return 0; -} - -static inline u8 rz_mtu3_8bit_ch_read(struct rz_mtu3_channel *ch, u16 off) -{ - return 0; -} - -static inline u16 rz_mtu3_16bit_ch_read(struct rz_mtu3_channel *ch, u16 off) -{ - return 0; -} - -static inline u32 rz_mtu3_32bit_ch_read(struct rz_mtu3_channel *ch, u16 off) -{ - return 0; -} - -static inline u16 rz_mtu3_shared_reg_read(struct rz_mtu3_channel *ch, u16 off) -{ - return 0; -} - -static inline void rz_mtu3_8bit_ch_write(struct rz_mtu3_channel *ch, u16 off, u8 val) -{ -} - -static inline void rz_mtu3_16bit_ch_write(struct rz_mtu3_channel *ch, u16 off, u16 val) -{ -} - -static inline void rz_mtu3_32bit_ch_write(struct rz_mtu3_channel *ch, u16 off, u32 val) -{ -} - -static inline void rz_mtu3_shared_reg_write(struct rz_mtu3_channel *ch, u16 off, u16 val) -{ -} - -static inline void rz_mtu3_shared_reg_update_bit(struct rz_mtu3_channel *ch, - u16 off, u16 pos, u8 val) -{ -} -#endif #endif /* __MFD_RZ_MTU3_H__ */ diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h index fe8978eb69f1..b4795698d8c2 100644 --- a/include/linux/remoteproc.h +++ b/include/linux/remoteproc.h @@ -690,6 +690,10 @@ int rproc_detach(struct rproc *rproc); int rproc_set_firmware(struct rproc *rproc, const char *fw_name); void rproc_report_crash(struct rproc *rproc, enum rproc_crash_type type); void *rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem); + +/* from remoteproc_coredump.c */ +void rproc_coredump_cleanup(struct rproc *rproc); +void rproc_coredump(struct rproc *rproc); void rproc_coredump_using_sections(struct rproc *rproc); int rproc_coredump_add_segment(struct rproc *rproc, dma_addr_t da, size_t size); int rproc_coredump_add_custom_segment(struct rproc *rproc, diff --git a/include/linux/rmap.h b/include/linux/rmap.h index a3825ce81102..51cc21ebb568 100644 --- a/include/linux/rmap.h +++ b/include/linux/rmap.h @@ -479,7 +479,6 @@ struct anon_vma *folio_lock_anon_vma_read(struct folio *folio, #define anon_vma_init() do {} while (0) #define anon_vma_prepare(vma) (0) -#define anon_vma_link(vma) do {} while (0) static inline int folio_referenced(struct folio *folio, int is_locked, struct mem_cgroup *memcg, diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h index 523c98b96cb4..90d8e4475f80 100644 --- a/include/linux/rpmsg.h +++ b/include/linux/rpmsg.h @@ -64,12 +64,14 @@ struct rpmsg_device { }; typedef int (*rpmsg_rx_cb_t)(struct rpmsg_device *, void *, int, void *, u32); +typedef int (*rpmsg_flowcontrol_cb_t)(struct rpmsg_device *, void *, bool); /** * struct rpmsg_endpoint - binds a local rpmsg address to its user * @rpdev: rpmsg channel device * @refcount: when this drops to zero, the ept is deallocated * @cb: rx callback handler + * @flow_cb: remote flow control callback handler * @cb_lock: must be taken before accessing/changing @cb * @addr: local rpmsg address * @priv: private data for the driver's use @@ -92,6 +94,7 @@ struct rpmsg_endpoint { struct rpmsg_device *rpdev; struct kref refcount; rpmsg_rx_cb_t cb; + rpmsg_flowcontrol_cb_t flow_cb; struct mutex cb_lock; u32 addr; void *priv; @@ -106,6 +109,7 @@ struct rpmsg_endpoint { * @probe: invoked when a matching rpmsg channel (i.e. device) is found * @remove: invoked when the rpmsg channel is removed * @callback: invoked when an inbound message is received on the channel + * @flowcontrol: invoked when remote side flow control request is received */ struct rpmsg_driver { struct device_driver drv; @@ -113,6 +117,7 @@ struct rpmsg_driver { int (*probe)(struct rpmsg_device *dev); void (*remove)(struct rpmsg_device *dev); int (*callback)(struct rpmsg_device *, void *, int, void *, u32); + int (*flowcontrol)(struct rpmsg_device *, void *, bool); }; static inline u16 rpmsg16_to_cpu(struct rpmsg_device *rpdev, __rpmsg16 val) @@ -192,6 +197,8 @@ __poll_t rpmsg_poll(struct rpmsg_endpoint *ept, struct file *filp, ssize_t rpmsg_get_mtu(struct rpmsg_endpoint *ept); +int rpmsg_set_flow_control(struct rpmsg_endpoint *ept, bool pause, u32 dst); + #else static inline int rpmsg_register_device_override(struct rpmsg_device *rpdev, @@ -316,6 +323,14 @@ static inline ssize_t rpmsg_get_mtu(struct rpmsg_endpoint *ept) return -ENXIO; } +static inline int rpmsg_set_flow_control(struct rpmsg_endpoint *ept, bool pause, u32 dst) +{ + /* This shouldn't be possible */ + WARN_ON(1); + + return -ENXIO; +} + #endif /* IS_ENABLED(CONFIG_RPMSG) */ /* use a macro to avoid include chaining to get THIS_MODULE */ diff --git a/include/linux/thermal.h b/include/linux/thermal.h index b449a46766f5..eb17495c8acc 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -53,6 +53,20 @@ enum thermal_notify_event { THERMAL_EVENT_KEEP_ALIVE, /* Request for user space handler to respond */ }; +/** + * struct thermal_trip - representation of a point in temperature domain + * @temperature: temperature value in miliCelsius + * @hysteresis: relative hysteresis in miliCelsius + * @type: trip point type + * @priv: pointer to driver data associated with this trip + */ +struct thermal_trip { + int temperature; + int hysteresis; + enum thermal_trip_type type; + void *priv; +}; + struct thermal_zone_device_ops { int (*bind) (struct thermal_zone_device *, struct thermal_cooling_device *); @@ -62,34 +76,16 @@ struct thermal_zone_device_ops { int (*set_trips) (struct thermal_zone_device *, int, int); int (*change_mode) (struct thermal_zone_device *, enum thermal_device_mode); - int (*get_trip_type) (struct thermal_zone_device *, int, - enum thermal_trip_type *); - int (*get_trip_temp) (struct thermal_zone_device *, int, int *); int (*set_trip_temp) (struct thermal_zone_device *, int, int); - int (*get_trip_hyst) (struct thermal_zone_device *, int, int *); int (*set_trip_hyst) (struct thermal_zone_device *, int, int); int (*get_crit_temp) (struct thermal_zone_device *, int *); int (*set_emul_temp) (struct thermal_zone_device *, int); - int (*get_trend) (struct thermal_zone_device *, int, + int (*get_trend) (struct thermal_zone_device *, struct thermal_trip *, enum thermal_trend *); void (*hot)(struct thermal_zone_device *); void (*critical)(struct thermal_zone_device *); }; -/** - * struct thermal_trip - representation of a point in temperature domain - * @temperature: temperature value in miliCelsius - * @hysteresis: relative hysteresis in miliCelsius - * @type: trip point type - * @priv: pointer to driver data associated with this trip - */ -struct thermal_trip { - int temperature; - int hysteresis; - enum thermal_trip_type type; - void *priv; -}; - struct thermal_cooling_device_ops { int (*get_max_state) (struct thermal_cooling_device *, unsigned long *); int (*get_cur_state) (struct thermal_cooling_device *, unsigned long *); diff --git a/include/linux/vdpa.h b/include/linux/vdpa.h index db1b0eaef4eb..0e652026b776 100644 --- a/include/linux/vdpa.h +++ b/include/linux/vdpa.h @@ -208,6 +208,9 @@ struct vdpa_map_file { * @vdev: vdpa device * Returns the virtio features support by the * device + * @get_backend_features: Get parent-specific backend features (optional) + * Returns the vdpa features supported by the + * device. * @set_driver_features: Set virtio features supported by the driver * @vdev: vdpa device * @features: feature support by the driver @@ -358,6 +361,7 @@ struct vdpa_config_ops { u32 (*get_vq_align)(struct vdpa_device *vdev); u32 (*get_vq_group)(struct vdpa_device *vdev, u16 idx); u64 (*get_device_features)(struct vdpa_device *vdev); + u64 (*get_backend_features)(const struct vdpa_device *vdev); int (*set_driver_features)(struct vdpa_device *vdev, u64 features); u64 (*get_driver_features)(struct vdpa_device *vdev); void (*set_config_cb)(struct vdpa_device *vdev, diff --git a/include/linux/virtio.h b/include/linux/virtio.h index de6041deee37..4cc614a38376 100644 --- a/include/linux/virtio.h +++ b/include/linux/virtio.h @@ -9,6 +9,7 @@ #include <linux/device.h> #include <linux/mod_devicetable.h> #include <linux/gfp.h> +#include <linux/dma-mapping.h> /** * struct virtqueue - a queue to register buffers for sending or receiving. @@ -61,6 +62,8 @@ int virtqueue_add_sgs(struct virtqueue *vq, void *data, gfp_t gfp); +struct device *virtqueue_dma_dev(struct virtqueue *vq); + bool virtqueue_kick(struct virtqueue *vq); bool virtqueue_kick_prepare(struct virtqueue *vq); @@ -78,6 +81,8 @@ bool virtqueue_enable_cb(struct virtqueue *vq); unsigned virtqueue_enable_cb_prepare(struct virtqueue *vq); +int virtqueue_set_dma_premapped(struct virtqueue *_vq); + bool virtqueue_poll(struct virtqueue *vq, unsigned); bool virtqueue_enable_cb_delayed(struct virtqueue *vq); @@ -95,6 +100,8 @@ dma_addr_t virtqueue_get_used_addr(const struct virtqueue *vq); int virtqueue_resize(struct virtqueue *vq, u32 num, void (*recycle)(struct virtqueue *vq, void *buf)); +int virtqueue_reset(struct virtqueue *vq, + void (*recycle)(struct virtqueue *vq, void *buf)); /** * struct virtio_device - representation of a device using virtio @@ -184,10 +191,8 @@ struct virtio_driver { void (*scan)(struct virtio_device *dev); void (*remove)(struct virtio_device *dev); void (*config_changed)(struct virtio_device *dev); -#ifdef CONFIG_PM int (*freeze)(struct virtio_device *dev); int (*restore)(struct virtio_device *dev); -#endif }; static inline struct virtio_driver *drv_to_virtio(struct device_driver *drv) @@ -206,4 +211,19 @@ void unregister_virtio_driver(struct virtio_driver *drv); #define module_virtio_driver(__virtio_driver) \ module_driver(__virtio_driver, register_virtio_driver, \ unregister_virtio_driver) + +dma_addr_t virtqueue_dma_map_single_attrs(struct virtqueue *_vq, void *ptr, size_t size, + enum dma_data_direction dir, unsigned long attrs); +void virtqueue_dma_unmap_single_attrs(struct virtqueue *_vq, dma_addr_t addr, + size_t size, enum dma_data_direction dir, + unsigned long attrs); +int virtqueue_dma_mapping_error(struct virtqueue *_vq, dma_addr_t addr); + +bool virtqueue_dma_need_sync(struct virtqueue *_vq, dma_addr_t addr); +void virtqueue_dma_sync_single_range_for_cpu(struct virtqueue *_vq, dma_addr_t addr, + unsigned long offset, size_t size, + enum dma_data_direction dir); +void virtqueue_dma_sync_single_range_for_device(struct virtqueue *_vq, dma_addr_t addr, + unsigned long offset, size_t size, + enum dma_data_direction dir); #endif /* _LINUX_VIRTIO_H */ diff --git a/include/uapi/linux/rpmsg.h b/include/uapi/linux/rpmsg.h index 1637e68177d9..f0c8da2b185b 100644 --- a/include/uapi/linux/rpmsg.h +++ b/include/uapi/linux/rpmsg.h @@ -43,4 +43,14 @@ struct rpmsg_endpoint_info { */ #define RPMSG_RELEASE_DEV_IOCTL _IOW(0xb5, 0x4, struct rpmsg_endpoint_info) +/** + * Get the flow control state of the remote rpmsg char device. + */ +#define RPMSG_GET_OUTGOING_FLOWCONTROL _IOR(0xb5, 0x5, int) + +/** + * Set the flow control state of the local rpmsg char device. + */ +#define RPMSG_SET_INCOMING_FLOWCONTROL _IOR(0xb5, 0x6, int) + #endif diff --git a/include/uapi/linux/vhost_types.h b/include/uapi/linux/vhost_types.h index d3aad12ad1fa..2d827d22cd99 100644 --- a/include/uapi/linux/vhost_types.h +++ b/include/uapi/linux/vhost_types.h @@ -181,5 +181,9 @@ struct vhost_vdpa_iova_range { #define VHOST_BACKEND_F_SUSPEND 0x4 /* Device can be resumed */ #define VHOST_BACKEND_F_RESUME 0x5 +/* Device supports the driver enabling virtqueues both before and after + * DRIVER_OK + */ +#define VHOST_BACKEND_F_ENABLE_AFTER_DRIVER_OK 0x6 #endif diff --git a/kernel/configs/debug.config b/kernel/configs/debug.config index e8db8d938661..4722b998a324 100644 --- a/kernel/configs/debug.config +++ b/kernel/configs/debug.config @@ -1,3 +1,5 @@ +# Help: Debugging for CI systems and finding regressions +# # The config is based on running daily CI for enterprise Linux distros to # seek regressions on linux-next builds on different bare-metal and virtual # platforms. It can be used for example, diff --git a/kernel/configs/kvm_guest.config b/kernel/configs/kvm_guest.config index 208481d91090..d0877063d925 100644 --- a/kernel/configs/kvm_guest.config +++ b/kernel/configs/kvm_guest.config @@ -1,3 +1,4 @@ +# Help: Bootable as a KVM guest CONFIG_NET=y CONFIG_NET_CORE=y CONFIG_NETDEVICES=y diff --git a/kernel/configs/nopm.config b/kernel/configs/nopm.config index 81ff07863576..ebfdc3d8aa9a 100644 --- a/kernel/configs/nopm.config +++ b/kernel/configs/nopm.config @@ -1,3 +1,5 @@ +# Help: Disable Power Management + CONFIG_PM=n CONFIG_SUSPEND=n CONFIG_HIBERNATION=n diff --git a/kernel/configs/rust.config b/kernel/configs/rust.config index 38a7c5362c9c..2c6e001a7284 100644 --- a/kernel/configs/rust.config +++ b/kernel/configs/rust.config @@ -1 +1,2 @@ +# Help: Enable Rust CONFIG_RUST=y diff --git a/kernel/configs/x86_debug.config b/kernel/configs/x86_debug.config index 6fac5b405334..35f48671b8d5 100644 --- a/kernel/configs/x86_debug.config +++ b/kernel/configs/x86_debug.config @@ -1,3 +1,4 @@ +# Help: Debugging options for tip tree testing CONFIG_X86_DEBUG_FPU=y CONFIG_LOCK_STAT=y CONFIG_DEBUG_VM=y diff --git a/kernel/configs/xen.config b/kernel/configs/xen.config index 436f806aa1ed..6878b9a49be8 100644 --- a/kernel/configs/xen.config +++ b/kernel/configs/xen.config @@ -1,3 +1,5 @@ +# Help: Bootable as a Xen guest +# # global stuff - these enable us to allow some # of the not so generic stuff below for xen CONFIG_PARAVIRT=y diff --git a/kernel/debug/kdb/kdb_io.c b/kernel/debug/kdb/kdb_io.c index 813cb6cf72d6..9443bc63c5a2 100644 --- a/kernel/debug/kdb/kdb_io.c +++ b/kernel/debug/kdb/kdb_io.c @@ -590,6 +590,8 @@ static void kdb_msg_write(const char *msg, int msg_len) continue; if (c == dbg_io_ops->cons) continue; + if (!c->write) + continue; /* * Set oops_in_progress to encourage the console drivers to * disregard their internal spin locks: in the current calling diff --git a/kernel/printk/internal.h b/kernel/printk/internal.h index 2a17704136f1..7d4979d5c3ce 100644 --- a/kernel/printk/internal.h +++ b/kernel/printk/internal.h @@ -103,3 +103,5 @@ struct printk_message { u64 seq; unsigned long dropped; }; + +bool other_cpu_in_panic(void); diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 357a4d18f638..96fc38cb2e84 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -88,7 +88,7 @@ EXPORT_SYMBOL(oops_in_progress); static DEFINE_MUTEX(console_mutex); /* - * console_sem protects updates to console->seq and console_suspended, + * console_sem protects updates to console->seq * and also provides serialization for console printing. */ static DEFINE_SEMAPHORE(console_sem, 1); @@ -361,7 +361,7 @@ static bool panic_in_progress(void) * paths in the console code where we end up in places I want * locked without the console semaphore held). */ -static int console_locked, console_suspended; +static int console_locked; /* * Array of consoles built from command line options (console=) @@ -538,12 +538,14 @@ char *log_buf_addr_get(void) { return log_buf; } +EXPORT_SYMBOL_GPL(log_buf_addr_get); /* Return log buffer size */ u32 log_buf_len_get(void) { return log_buf_len; } +EXPORT_SYMBOL_GPL(log_buf_len_get); /* * Define how much of the log buffer we could take at maximum. The value @@ -2308,7 +2310,11 @@ asmlinkage int vprintk_emit(int facility, int level, preempt_enable(); } - wake_up_klogd(); + if (in_sched) + defer_console_output(); + else + wake_up_klogd(); + return printed_len; } EXPORT_SYMBOL(vprintk_emit); @@ -2547,22 +2553,46 @@ MODULE_PARM_DESC(console_no_auto_verbose, "Disable console loglevel raise to hig */ void suspend_console(void) { + struct console *con; + if (!console_suspend_enabled) return; pr_info("Suspending console(s) (use no_console_suspend to debug)\n"); pr_flush(1000, true); - console_lock(); - console_suspended = 1; - up_console_sem(); + + console_list_lock(); + for_each_console(con) + console_srcu_write_flags(con, con->flags | CON_SUSPENDED); + console_list_unlock(); + + /* + * Ensure that all SRCU list walks have completed. All printing + * contexts must be able to see that they are suspended so that it + * is guaranteed that all printing has stopped when this function + * completes. + */ + synchronize_srcu(&console_srcu); } void resume_console(void) { + struct console *con; + if (!console_suspend_enabled) return; - down_console_sem(); - console_suspended = 0; - console_unlock(); + + console_list_lock(); + for_each_console(con) + console_srcu_write_flags(con, con->flags & ~CON_SUSPENDED); + console_list_unlock(); + + /* + * Ensure that all SRCU list walks have completed. All printing + * contexts must be able to see they are no longer suspended so + * that they are guaranteed to wake up and resume printing. + */ + synchronize_srcu(&console_srcu); + pr_flush(1000, true); } @@ -2585,6 +2615,26 @@ static int console_cpu_notify(unsigned int cpu) return 0; } +/* + * Return true if a panic is in progress on a remote CPU. + * + * On true, the local CPU should immediately release any printing resources + * that may be needed by the panic CPU. + */ +bool other_cpu_in_panic(void) +{ + if (!panic_in_progress()) + return false; + + /* + * We can use raw_smp_processor_id() here because it is impossible for + * the task to be migrated to the panic_cpu, or away from it. If + * panic_cpu has already been set, and we're not currently executing on + * that CPU, then we never will be. + */ + return atomic_read(&panic_cpu) != raw_smp_processor_id(); +} + /** * console_lock - block the console subsystem from printing * @@ -2597,9 +2647,11 @@ void console_lock(void) { might_sleep(); + /* On panic, the console_lock must be left to the panic cpu. */ + while (other_cpu_in_panic()) + msleep(1000); + down_console_sem(); - if (console_suspended) - return; console_locked = 1; console_may_schedule = 1; } @@ -2615,12 +2667,11 @@ EXPORT_SYMBOL(console_lock); */ int console_trylock(void) { - if (down_trylock_console_sem()) + /* On panic, the console_lock must be left to the panic cpu. */ + if (other_cpu_in_panic()) return 0; - if (console_suspended) { - up_console_sem(); + if (down_trylock_console_sem()) return 0; - } console_locked = 1; console_may_schedule = 0; return 1; @@ -2634,25 +2685,6 @@ int is_console_locked(void) EXPORT_SYMBOL(is_console_locked); /* - * Return true when this CPU should unlock console_sem without pushing all - * messages to the console. This reduces the chance that the console is - * locked when the panic CPU tries to use it. - */ -static bool abandon_console_lock_in_panic(void) -{ - if (!panic_in_progress()) - return false; - - /* - * We can use raw_smp_processor_id() here because it is impossible for - * the task to be migrated to the panic_cpu, or away from it. If - * panic_cpu has already been set, and we're not currently executing on - * that CPU, then we never will be. - */ - return atomic_read(&panic_cpu) != raw_smp_processor_id(); -} - -/* * Check if the given console is currently capable and allowed to print * records. * @@ -2665,6 +2697,9 @@ static inline bool console_is_usable(struct console *con) if (!(flags & CON_ENABLED)) return false; + if ((flags & CON_SUSPENDED)) + return false; + if (!con->write) return false; @@ -2948,7 +2983,7 @@ static bool console_flush_all(bool do_cond_resched, u64 *next_seq, bool *handove any_progress = true; /* Allow panic_cpu to take over the consoles safely. */ - if (abandon_console_lock_in_panic()) + if (other_cpu_in_panic()) goto abandon; if (do_cond_resched) @@ -2983,11 +3018,6 @@ void console_unlock(void) bool flushed; u64 next_seq; - if (console_suspended) { - up_console_sem(); - return; - } - /* * Console drivers are called with interrupts disabled, so * @console_may_schedule should be cleared before; however, we may @@ -3045,10 +3075,28 @@ EXPORT_SYMBOL(console_conditional_schedule); void console_unblank(void) { + bool found_unblank = false; struct console *c; int cookie; /* + * First check if there are any consoles implementing the unblank() + * callback. If not, there is no reason to continue and take the + * console lock, which in particular can be dangerous if + * @oops_in_progress is set. + */ + cookie = console_srcu_read_lock(); + for_each_console_srcu(c) { + if ((console_srcu_read_flags(c) & CON_ENABLED) && c->unblank) { + found_unblank = true; + break; + } + } + console_srcu_read_unlock(cookie); + if (!found_unblank) + return; + + /* * Stop console printing because the unblank() callback may * assume the console is not within its write() callback. * @@ -3056,6 +3104,16 @@ void console_unblank(void) * In that case, attempt a trylock as best-effort. */ if (oops_in_progress) { + /* Semaphores are not NMI-safe. */ + if (in_nmi()) + return; + + /* + * Attempting to trylock the console lock can deadlock + * if another CPU was stopped while modifying the + * semaphore. "Hope and pray" that this is not the + * current situation. + */ if (down_trylock_console_sem() != 0) return; } else @@ -3085,14 +3143,24 @@ void console_unblank(void) */ void console_flush_on_panic(enum con_flush_mode mode) { + bool handover; + u64 next_seq; + /* - * If someone else is holding the console lock, trylock will fail - * and may_schedule may be set. Ignore and proceed to unlock so - * that messages are flushed out. As this can be called from any - * context and we don't want to get preempted while flushing, - * ensure may_schedule is cleared. + * Ignore the console lock and flush out the messages. Attempting a + * trylock would not be useful because: + * + * - if it is contended, it must be ignored anyway + * - console_lock() and console_trylock() block and fail + * respectively in panic for non-panic CPUs + * - semaphores are not NMI-safe + */ + + /* + * If another context is holding the console lock, + * @console_may_schedule might be set. Clear it so that + * this context does not call cond_resched() while flushing. */ - console_trylock(); console_may_schedule = 0; if (mode == CONSOLE_REPLAY_ALL) { @@ -3105,15 +3173,15 @@ void console_flush_on_panic(enum con_flush_mode mode) cookie = console_srcu_read_lock(); for_each_console_srcu(c) { /* - * If the above console_trylock() failed, this is an - * unsynchronized assignment. But in that case, the + * This is an unsynchronized assignment, but the * kernel is in "hope and pray" mode anyway. */ c->seq = seq; } console_srcu_read_unlock(cookie); } - console_unlock(); + + console_flush_all(false, &next_seq, &handover); } /* @@ -3679,8 +3747,7 @@ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progre /* * Hold the console_lock to guarantee safe access to - * console->seq and to prevent changes to @console_suspended - * until all consoles have been processed. + * console->seq. */ console_lock(); @@ -3688,6 +3755,11 @@ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progre for_each_console_srcu(c) { if (con && con != c) continue; + /* + * If consoles are not usable, it cannot be expected + * that they make forward progress, so only increment + * @diff for usable consoles. + */ if (!console_is_usable(c)) continue; printk_seq = c->seq; @@ -3696,18 +3768,12 @@ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progre } console_srcu_read_unlock(cookie); - /* - * If consoles are suspended, it cannot be expected that they - * make forward progress, so timeout immediately. @diff is - * still used to return a valid flush status. - */ - if (console_suspended) - remaining = 0; - else if (diff != last_diff && reset_on_progress) + if (diff != last_diff && reset_on_progress) remaining = timeout_ms; console_unlock(); + /* Note: @diff is 0 if there are no usable consoles. */ if (diff == 0 || remaining == 0) break; @@ -3741,7 +3807,7 @@ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progre * printer has been seen to make some forward progress. * * Context: Process context. May sleep while acquiring console lock. - * Return: true if all enabled printers are caught up. + * Return: true if all usable printers are caught up. */ static bool pr_flush(int timeout_ms, bool reset_on_progress) { @@ -3798,11 +3864,33 @@ static void __wake_up_klogd(int val) preempt_enable(); } +/** + * wake_up_klogd - Wake kernel logging daemon + * + * Use this function when new records have been added to the ringbuffer + * and the console printing of those records has already occurred or is + * known to be handled by some other context. This function will only + * wake the logging daemon. + * + * Context: Any context. + */ void wake_up_klogd(void) { __wake_up_klogd(PRINTK_PENDING_WAKEUP); } +/** + * defer_console_output - Wake kernel logging daemon and trigger + * console printing in a deferred context + * + * Use this function when new records have been added to the ringbuffer, + * this context is responsible for console printing those records, but + * the current context is not allowed to perform the console printing. + * Trigger an irq_work context to perform the console printing. This + * function also wakes the logging daemon. + * + * Context: Any context. + */ void defer_console_output(void) { /* @@ -3819,12 +3907,7 @@ void printk_trigger_flush(void) int vprintk_deferred(const char *fmt, va_list args) { - int r; - - r = vprintk_emit(0, LOGLEVEL_SCHED, NULL, fmt, args); - defer_console_output(); - - return r; + return vprintk_emit(0, LOGLEVEL_SCHED, NULL, fmt, args); } int _printk_deferred(const char *fmt, ...) diff --git a/kernel/printk/printk_ringbuffer.c b/kernel/printk/printk_ringbuffer.c index 2dc4d5a1f1ff..fde338606ce8 100644 --- a/kernel/printk/printk_ringbuffer.c +++ b/kernel/printk/printk_ringbuffer.c @@ -1735,7 +1735,7 @@ static bool copy_data(struct prb_data_ring *data_ring, if (!buf || !buf_size) return true; - data_size = min_t(u16, buf_size, len); + data_size = min_t(unsigned int, buf_size, len); memcpy(&buf[0], data, data_size); /* LMM(copy_data:A) */ return true; diff --git a/kernel/printk/printk_safe.c b/kernel/printk/printk_safe.c index ef0f9a2044da..6d10927a07d8 100644 --- a/kernel/printk/printk_safe.c +++ b/kernel/printk/printk_safe.c @@ -38,13 +38,8 @@ asmlinkage int vprintk(const char *fmt, va_list args) * Use the main logbuf even in NMI. But avoid calling console * drivers that might have their own locks. */ - if (this_cpu_read(printk_context) || in_nmi()) { - int len; - - len = vprintk_store(0, LOGLEVEL_DEFAULT, NULL, fmt, args); - defer_console_output(); - return len; - } + if (this_cpu_read(printk_context) || in_nmi()) + return vprintk_deferred(fmt, args); /* No obstacles. */ return vprintk_default(fmt, args); diff --git a/lib/test_scanf.c b/lib/test_scanf.c index b620cf7de503..a2707af2951a 100644 --- a/lib/test_scanf.c +++ b/lib/test_scanf.c @@ -606,7 +606,7 @@ static void __init numbers_slice(void) #define test_number_prefix(T, str, scan_fmt, expect0, expect1, n_args, fn) \ do { \ const T expect[2] = { expect0, expect1 }; \ - T result[2] = {~expect[0], ~expect[1]}; \ + T result[2] = { (T)~expect[0], (T)~expect[1] }; \ \ _test(fn, &expect, str, scan_fmt, n_args, &result[0], &result[1]); \ } while (0) diff --git a/mm/kmemleak.c b/mm/kmemleak.c index 2918150e31bd..54c2c90d3abc 100644 --- a/mm/kmemleak.c +++ b/mm/kmemleak.c @@ -1584,6 +1584,9 @@ static void kmemleak_scan(void) for (pfn = start_pfn; pfn < end_pfn; pfn++) { struct page *page = pfn_to_online_page(pfn); + if (!(pfn & 63)) + cond_resched(); + if (!page) continue; @@ -1594,8 +1597,6 @@ static void kmemleak_scan(void) if (page_count(page) == 0) continue; scan_block(page, page + 1, NULL); - if (!(pfn & 63)) - cond_resched(); } } put_online_mems(); diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 881c35ef1daa..7b01fffe7a79 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -717,7 +717,7 @@ static void collect_procs(struct page *page, struct list_head *tokill, collect_procs_file(page, tokill, force_early); } -struct hwp_walk { +struct hwpoison_walk { struct to_kill tk; unsigned long pfn; int flags; @@ -752,7 +752,7 @@ static int check_hwpoisoned_entry(pte_t pte, unsigned long addr, short shift, #ifdef CONFIG_TRANSPARENT_HUGEPAGE static int check_hwpoisoned_pmd_entry(pmd_t *pmdp, unsigned long addr, - struct hwp_walk *hwp) + struct hwpoison_walk *hwp) { pmd_t pmd = *pmdp; unsigned long pfn; @@ -770,7 +770,7 @@ static int check_hwpoisoned_pmd_entry(pmd_t *pmdp, unsigned long addr, } #else static int check_hwpoisoned_pmd_entry(pmd_t *pmdp, unsigned long addr, - struct hwp_walk *hwp) + struct hwpoison_walk *hwp) { return 0; } @@ -779,7 +779,7 @@ static int check_hwpoisoned_pmd_entry(pmd_t *pmdp, unsigned long addr, static int hwpoison_pte_range(pmd_t *pmdp, unsigned long addr, unsigned long end, struct mm_walk *walk) { - struct hwp_walk *hwp = walk->private; + struct hwpoison_walk *hwp = walk->private; int ret = 0; pte_t *ptep, *mapped_pte; spinlock_t *ptl; @@ -813,7 +813,7 @@ static int hwpoison_hugetlb_range(pte_t *ptep, unsigned long hmask, unsigned long addr, unsigned long end, struct mm_walk *walk) { - struct hwp_walk *hwp = walk->private; + struct hwpoison_walk *hwp = walk->private; pte_t pte = huge_ptep_get(ptep); struct hstate *h = hstate_vma(walk->vma); @@ -824,7 +824,7 @@ static int hwpoison_hugetlb_range(pte_t *ptep, unsigned long hmask, #define hwpoison_hugetlb_range NULL #endif -static const struct mm_walk_ops hwp_walk_ops = { +static const struct mm_walk_ops hwpoison_walk_ops = { .pmd_entry = hwpoison_pte_range, .hugetlb_entry = hwpoison_hugetlb_range, .walk_lock = PGWALK_RDLOCK, @@ -847,7 +847,7 @@ static int kill_accessing_process(struct task_struct *p, unsigned long pfn, int flags) { int ret; - struct hwp_walk priv = { + struct hwpoison_walk priv = { .pfn = pfn, }; priv.tk.tsk = p; @@ -856,7 +856,7 @@ static int kill_accessing_process(struct task_struct *p, unsigned long pfn, return -EFAULT; mmap_read_lock(p->mm); - ret = walk_page_range(p->mm, 0, TASK_SIZE, &hwp_walk_ops, + ret = walk_page_range(p->mm, 0, TASK_SIZE, &hwpoison_walk_ops, (void *)&priv); if (ret == 1 && priv.tk.addr) kill_proc(&priv.tk, pfn, flags); @@ -1562,7 +1562,7 @@ static bool hwpoison_user_mappings(struct page *p, unsigned long pfn, * Here we are interested only in user-mapped pages, so skip any * other types of pages. */ - if (PageReserved(p) || PageSlab(p) || PageTable(p)) + if (PageReserved(p) || PageSlab(p) || PageTable(p) || PageOffline(p)) return true; if (!(PageLRU(hpage) || PageHuge(p))) return true; @@ -2533,7 +2533,8 @@ int unpoison_memory(unsigned long pfn) goto unlock_mutex; } - if (folio_test_slab(folio) || PageTable(&folio->page) || folio_test_reserved(folio)) + if (folio_test_slab(folio) || PageTable(&folio->page) || + folio_test_reserved(folio) || PageOffline(&folio->page)) goto unlock_mutex; /* diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 452459836b71..0c5be12f9336 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -2641,12 +2641,6 @@ struct page *rmqueue_buddy(struct zone *preferred_zone, struct zone *zone, do { page = NULL; spin_lock_irqsave(&zone->lock, flags); - /* - * order-0 request can reach here when the pcplist is skipped - * due to non-CMA allocation context. HIGHATOMIC area is - * reserved for high-order atomic allocation, so order-0 - * request should skip it. - */ if (alloc_flags & ALLOC_HIGHATOMIC) page = __rmqueue_smallest(zone, order, MIGRATE_HIGHATOMIC); if (!page) { @@ -2780,17 +2774,10 @@ struct page *rmqueue(struct zone *preferred_zone, WARN_ON_ONCE((gfp_flags & __GFP_NOFAIL) && (order > 1)); if (likely(pcp_allowed_order(order))) { - /* - * MIGRATE_MOVABLE pcplist could have the pages on CMA area and - * we need to skip it when CMA area isn't allowed. - */ - if (!IS_ENABLED(CONFIG_CMA) || alloc_flags & ALLOC_CMA || - migratetype != MIGRATE_MOVABLE) { - page = rmqueue_pcplist(preferred_zone, zone, order, - migratetype, alloc_flags); - if (likely(page)) - goto out; - } + page = rmqueue_pcplist(preferred_zone, zone, order, + migratetype, alloc_flags); + if (likely(page)) + goto out; } page = rmqueue_buddy(preferred_zone, zone, order, alloc_flags, diff --git a/scripts/Makefile.extrawarn b/scripts/Makefile.extrawarn index 40cd13eca82e..2fe6f2828d37 100644 --- a/scripts/Makefile.extrawarn +++ b/scripts/Makefile.extrawarn @@ -6,7 +6,79 @@ # They are independent, and can be combined like W=12 or W=123e. # ========================================================================== -KBUILD_CFLAGS += $(call cc-disable-warning, packed-not-aligned) +# Default set of warnings, always enabled +KBUILD_CFLAGS += -Wall +KBUILD_CFLAGS += -Wundef +KBUILD_CFLAGS += -Werror=implicit-function-declaration +KBUILD_CFLAGS += -Werror=implicit-int +KBUILD_CFLAGS += -Werror=return-type +KBUILD_CFLAGS += -Werror=strict-prototypes +KBUILD_CFLAGS += -Wno-format-security +KBUILD_CFLAGS += -Wno-trigraphs +KBUILD_CFLAGS += $(call cc-disable-warning,frame-address,) +KBUILD_CFLAGS += $(call cc-disable-warning, address-of-packed-member) + +ifneq ($(CONFIG_FRAME_WARN),0) +KBUILD_CFLAGS += -Wframe-larger-than=$(CONFIG_FRAME_WARN) +endif + +KBUILD_CPPFLAGS-$(CONFIG_WERROR) += -Werror +KBUILD_CPPFLAGS += $(KBUILD_CPPFLAGS-y) +KBUILD_CFLAGS-$(CONFIG_CC_NO_ARRAY_BOUNDS) += -Wno-array-bounds + +ifdef CONFIG_CC_IS_CLANG +# The kernel builds with '-std=gnu11' so use of GNU extensions is acceptable. +KBUILD_CFLAGS += -Wno-gnu +else + +# gcc inanely warns about local variables called 'main' +KBUILD_CFLAGS += -Wno-main +endif + +# These warnings generated too much noise in a regular build. +# Use make W=1 to enable them (see scripts/Makefile.extrawarn) +KBUILD_CFLAGS += $(call cc-disable-warning, unused-but-set-variable) +KBUILD_CFLAGS += $(call cc-disable-warning, unused-const-variable) + +# These result in bogus false positives +KBUILD_CFLAGS += $(call cc-disable-warning, dangling-pointer) + +# Variable Length Arrays (VLAs) should not be used anywhere in the kernel +KBUILD_CFLAGS += -Wvla + +# disable pointer signed / unsigned warnings in gcc 4.0 +KBUILD_CFLAGS += -Wno-pointer-sign + +# In order to make sure new function cast mismatches are not introduced +# in the kernel (to avoid tripping CFI checking), the kernel should be +# globally built with -Wcast-function-type. +KBUILD_CFLAGS += $(call cc-option, -Wcast-function-type) + +# The allocators already balk at large sizes, so silence the compiler +# warnings for bounds checks involving those possible values. While +# -Wno-alloc-size-larger-than would normally be used here, earlier versions +# of gcc (<9.1) weirdly don't handle the option correctly when _other_ +# warnings are produced (?!). Using -Walloc-size-larger-than=SIZE_MAX +# doesn't work (as it is documented to), silently resolving to "0" prior to +# version 9.1 (and producing an error more recently). Numeric values larger +# than PTRDIFF_MAX also don't work prior to version 9.1, which are silently +# ignored, continuing to default to PTRDIFF_MAX. So, left with no other +# choice, we must perform a versioned check to disable this warning. +# https://lore.kernel.org/lkml/20210824115859.187f272f@canb.auug.org.au +KBUILD_CFLAGS-$(call gcc-min-version, 90100) += -Wno-alloc-size-larger-than +KBUILD_CFLAGS += $(KBUILD_CFLAGS-y) $(CONFIG_CC_IMPLICIT_FALLTHROUGH) + +# Prohibit date/time macros, which would make the build non-deterministic +KBUILD_CFLAGS += -Werror=date-time + +# enforce correct pointer usage +KBUILD_CFLAGS += $(call cc-option,-Werror=incompatible-pointer-types) + +# Require designated initializers for all marked structures +KBUILD_CFLAGS += $(call cc-option,-Werror=designated-init) + +# Warn if there is an enum types mismatch +KBUILD_CFLAGS += $(call cc-option,-Wenum-conversion) # backward compatibility KBUILD_EXTRA_WARN ?= $(KBUILD_ENABLE_EXTRA_GCC_CHECKS) @@ -24,6 +96,7 @@ ifneq ($(findstring 1, $(KBUILD_EXTRA_WARN)),) KBUILD_CFLAGS += -Wextra -Wunused -Wno-unused-parameter KBUILD_CFLAGS += -Wmissing-declarations +KBUILD_CFLAGS += $(call cc-option, -Wrestrict) KBUILD_CFLAGS += -Wmissing-format-attribute KBUILD_CFLAGS += -Wmissing-prototypes KBUILD_CFLAGS += -Wold-style-definition @@ -31,12 +104,10 @@ KBUILD_CFLAGS += -Wmissing-include-dirs KBUILD_CFLAGS += $(call cc-option, -Wunused-but-set-variable) KBUILD_CFLAGS += $(call cc-option, -Wunused-const-variable) KBUILD_CFLAGS += $(call cc-option, -Wpacked-not-aligned) +KBUILD_CFLAGS += $(call cc-option, -Wformat-overflow) +KBUILD_CFLAGS += $(call cc-option, -Wformat-truncation) +KBUILD_CFLAGS += $(call cc-option, -Wstringop-overflow) KBUILD_CFLAGS += $(call cc-option, -Wstringop-truncation) -# The following turn off the warnings enabled by -Wextra -KBUILD_CFLAGS += -Wno-missing-field-initializers -KBUILD_CFLAGS += -Wno-sign-compare -KBUILD_CFLAGS += -Wno-type-limits -KBUILD_CFLAGS += -Wno-shift-negative-value KBUILD_CPPFLAGS += -Wundef KBUILD_CPPFLAGS += -DKBUILD_EXTRA_WARN1 @@ -45,9 +116,16 @@ else # Some diagnostics enabled by default are noisy. # Suppress them by using -Wno... except for W=1. +KBUILD_CFLAGS += $(call cc-disable-warning, unused-but-set-variable) +KBUILD_CFLAGS += $(call cc-disable-warning, unused-const-variable) +KBUILD_CFLAGS += $(call cc-disable-warning, restrict) +KBUILD_CFLAGS += $(call cc-disable-warning, packed-not-aligned) +KBUILD_CFLAGS += $(call cc-disable-warning, format-overflow) +KBUILD_CFLAGS += $(call cc-disable-warning, format-truncation) +KBUILD_CFLAGS += $(call cc-disable-warning, stringop-overflow) +KBUILD_CFLAGS += $(call cc-disable-warning, stringop-truncation) ifdef CONFIG_CC_IS_CLANG -KBUILD_CFLAGS += -Wno-initializer-overrides # Clang before clang-16 would warn on default argument promotions. ifneq ($(call clang-min-version, 160000),y) # Disable -Wformat @@ -61,7 +139,6 @@ ifeq ($(call clang-min-version, 120000),y) KBUILD_CFLAGS += -Wformat-insufficient-args endif endif -KBUILD_CFLAGS += -Wno-sign-compare KBUILD_CFLAGS += $(call cc-disable-warning, pointer-to-enum-cast) KBUILD_CFLAGS += -Wno-tautological-constant-out-of-range-compare KBUILD_CFLAGS += $(call cc-disable-warning, unaligned-access) @@ -83,8 +160,25 @@ KBUILD_CFLAGS += -Wtype-limits KBUILD_CFLAGS += $(call cc-option, -Wmaybe-uninitialized) KBUILD_CFLAGS += $(call cc-option, -Wunused-macros) +ifdef CONFIG_CC_IS_CLANG +KBUILD_CFLAGS += -Winitializer-overrides +endif + KBUILD_CPPFLAGS += -DKBUILD_EXTRA_WARN2 +else + +# The following turn off the warnings enabled by -Wextra +KBUILD_CFLAGS += -Wno-missing-field-initializers +KBUILD_CFLAGS += -Wno-type-limits +KBUILD_CFLAGS += -Wno-shift-negative-value + +ifdef CONFIG_CC_IS_CLANG +KBUILD_CFLAGS += -Wno-initializer-overrides +else +KBUILD_CFLAGS += -Wno-maybe-uninitialized +endif + endif # @@ -106,6 +200,11 @@ KBUILD_CFLAGS += $(call cc-option, -Wpacked-bitfield-compat) KBUILD_CPPFLAGS += -DKBUILD_EXTRA_WARN3 +else + +# The following turn off the warnings enabled by -Wextra +KBUILD_CFLAGS += -Wno-sign-compare + endif # diff --git a/scripts/Makefile.modinst b/scripts/Makefile.modinst index ab0c5bd1a60f..c59cc57286ba 100644 --- a/scripts/Makefile.modinst +++ b/scripts/Makefile.modinst @@ -9,6 +9,35 @@ __modinst: include include/config/auto.conf include $(srctree)/scripts/Kbuild.include +install-y := + +ifeq ($(KBUILD_EXTMOD)$(sign-only),) + +# remove the old directory and symlink +$(shell rm -fr $(MODLIB)/kernel $(MODLIB)/build) + +install-$(CONFIG_MODULES) += $(addprefix $(MODLIB)/, build modules.order) + +$(MODLIB)/build: FORCE + $(call cmd,symlink) + +quiet_cmd_symlink = SYMLINK $@ + cmd_symlink = ln -s $(CURDIR) $@ + +$(MODLIB)/modules.order: modules.order FORCE + $(call cmd,install_modorder) + +quiet_cmd_install_modorder = INSTALL $@ + cmd_install_modorder = sed 's:^\(.*\)\.o$$:kernel/\1.ko:' $< > $@ + +# Install modules.builtin(.modinfo) even when CONFIG_MODULES is disabled. +install-y += $(addprefix $(MODLIB)/, modules.builtin modules.builtin.modinfo) + +$(addprefix $(MODLIB)/, modules.builtin modules.builtin.modinfo): $(MODLIB)/%: % FORCE + $(call cmd,install) + +endif + modules := $(call read-file, $(MODORDER)) ifeq ($(KBUILD_EXTMOD),) @@ -27,15 +56,16 @@ suffix-$(CONFIG_MODULE_COMPRESS_XZ) := .xz suffix-$(CONFIG_MODULE_COMPRESS_ZSTD) := .zst modules := $(patsubst $(extmod_prefix)%.o, $(dst)/%.ko$(suffix-y), $(modules)) +install-$(CONFIG_MODULES) += $(modules) -__modinst: $(modules) +__modinst: $(install-y) @: # # Installation # quiet_cmd_install = INSTALL $@ - cmd_install = mkdir -p $(dir $@); cp $< $@ + cmd_install = cp $< $@ # Strip # @@ -65,7 +95,6 @@ endif # Signing # Don't stop modules_install even if we can't sign external modules. # -ifeq ($(CONFIG_MODULE_SIG_ALL),y) ifeq ($(filter pkcs11:%, $(CONFIG_MODULE_SIG_KEY)),) sig-key := $(if $(wildcard $(CONFIG_MODULE_SIG_KEY)),,$(srctree)/)$(CONFIG_MODULE_SIG_KEY) else @@ -74,18 +103,34 @@ endif quiet_cmd_sign = SIGN $@ cmd_sign = scripts/sign-file $(CONFIG_MODULE_SIG_HASH) "$(sig-key)" certs/signing_key.x509 $@ \ $(if $(KBUILD_EXTMOD),|| true) -else + +ifeq ($(sign-only),) + +# During modules_install, modules are signed only when CONFIG_MODULE_SIG_ALL=y. +ifndef CONFIG_MODULE_SIG_ALL quiet_cmd_sign := cmd_sign := : endif -ifeq ($(modules_sign_only),) +# Create necessary directories +$(shell mkdir -p $(sort $(dir $(install-y)))) $(dst)/%.ko: $(extmod_prefix)%.ko FORCE $(call cmd,install) $(call cmd,strip) $(call cmd,sign) +ifdef CONFIG_MODULES +__modinst: depmod + +PHONY += depmod +depmod: $(install-y) + $(call cmd,depmod) + +quiet_cmd_depmod = DEPMOD $(MODLIB) + cmd_depmod = $(srctree)/scripts/depmod.sh $(KERNELRELEASE) +endif + else $(dst)/%.ko: FORCE diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost index 39472e834b63..739402f45509 100644 --- a/scripts/Makefile.modpost +++ b/scripts/Makefile.modpost @@ -41,6 +41,7 @@ include $(srctree)/scripts/Kbuild.include MODPOST = scripts/mod/modpost modpost-args = \ + $(if $(CONFIG_MODULES),-M) \ $(if $(CONFIG_MODVERSIONS),-m) \ $(if $(CONFIG_MODULE_SRCVERSION_ALL),-a) \ $(if $(CONFIG_SECTION_MISMATCH_WARN_ONLY),,-E) \ diff --git a/scripts/Makefile.package b/scripts/Makefile.package index 92dbc889bd7c..2bcab02da965 100644 --- a/scripts/Makefile.package +++ b/scripts/Makefile.package @@ -11,7 +11,6 @@ TAR_CONTENT := Documentation LICENSES arch block certs crypto drivers fs \ samples scripts security sound tools usr virt \ .config Makefile \ Kbuild Kconfig COPYING $(wildcard localversion*) -MKSPEC := $(srctree)/scripts/package/mkspec quiet_cmd_src_tar = TAR $(2).tar.gz cmd_src_tar = \ @@ -66,30 +65,38 @@ $(linux-tarballs): archive-args = --prefix=linux/ $$(cat $<) $(linux-tarballs): .tmp_HEAD FORCE $(call if_changed,archive) -# rpm-pkg +# rpm-pkg srcrpm-pkg binrpm-pkg # --------------------------------------------------------------------------- -PHONY += rpm-pkg -rpm-pkg: srpm = $(shell rpmspec --srpm --query --queryformat='%{name}-%{VERSION}-%{RELEASE}.src.rpm' kernel.spec) -rpm-pkg: srcrpm-pkg - +rpmbuild $(RPMOPTS) --target $(UTS_MACHINE)-linux -rb $(srpm) \ - --define='_smp_mflags %{nil}' -# srcrpm-pkg -# --------------------------------------------------------------------------- -PHONY += srcrpm-pkg -srcrpm-pkg: linux.tar.gz - $(CONFIG_SHELL) $(MKSPEC) >$(objtree)/kernel.spec - +rpmbuild $(RPMOPTS) --target $(UTS_MACHINE)-linux -bs kernel.spec \ - --define='_smp_mflags %{nil}' --define='_sourcedir rpmbuild/SOURCES' --define='_srcrpmdir .' +quiet_cmd_mkspec = GEN $@ + cmd_mkspec = $(srctree)/scripts/package/mkspec > $@ -# binrpm-pkg -# --------------------------------------------------------------------------- -PHONY += binrpm-pkg -binrpm-pkg: - $(MAKE) -f $(srctree)/Makefile - $(CONFIG_SHELL) $(MKSPEC) prebuilt > $(objtree)/binkernel.spec - +rpmbuild $(RPMOPTS) --define "_builddir $(objtree)" --target \ - $(UTS_MACHINE)-linux -bb $(objtree)/binkernel.spec +kernel.spec: FORCE + $(call cmd,mkspec) + +PHONY += rpm-sources +rpm-sources: linux.tar.gz + $(Q)mkdir -p rpmbuild/SOURCES + $(Q)ln -f linux.tar.gz rpmbuild/SOURCES/linux.tar.gz + $(Q)cp $(KCONFIG_CONFIG) rpmbuild/SOURCES/config + $(Q)$(srctree)/scripts/package/gen-diff-patch rpmbuild/SOURCES/diff.patch + +PHONY += rpm-pkg srcrpm-pkg binrpm-pkg + +rpm-pkg: private build-type := a +srcrpm-pkg: private build-type := s +binrpm-pkg: private build-type := b + +rpm-pkg srcrpm-pkg: rpm-sources +rpm-pkg srcrpm-pkg binrpm-pkg: kernel.spec + +$(strip rpmbuild -b$(build-type) kernel.spec \ + --define='_topdir $(abspath rpmbuild)' \ + $(if $(filter a b, $(build-type)), \ + --target $(UTS_MACHINE)-linux --build-in-place --noprep --define='_smp_mflags %{nil}' \ + $$(rpm -q rpm >/dev/null 2>&1 || echo --nodeps)) \ + $(if $(filter b, $(build-type)), \ + --without devel) \ + $(RPMOPTS)) # deb-pkg srcdeb-pkg bindeb-pkg # --------------------------------------------------------------------------- @@ -141,14 +148,10 @@ deb-pkg srcdeb-pkg bindeb-pkg: $(if $(findstring source, $(build-type)), \ --unsigned-source --compression=$(KDEB_SOURCE_COMPRESS)) \ $(if $(findstring binary, $(build-type)), \ - -r$(KBUILD_PKG_ROOTCMD) -a$$(cat debian/arch), \ + --rules-file='$(MAKE) -f debian/rules' --jobs=1 -r$(KBUILD_PKG_ROOTCMD) -a$$(cat debian/arch), \ --no-check-builddeps) \ $(DPKG_FLAGS)) -PHONY += intdeb-pkg -intdeb-pkg: - +$(CONFIG_SHELL) $(srctree)/scripts/package/builddeb - # snap-pkg # --------------------------------------------------------------------------- PHONY += snap-pkg diff --git a/scripts/depmod.sh b/scripts/depmod.sh index 3643b4f896ed..e22da27fe13e 100755 --- a/scripts/depmod.sh +++ b/scripts/depmod.sh @@ -1,14 +1,16 @@ #!/bin/sh # SPDX-License-Identifier: GPL-2.0 # -# A depmod wrapper used by the toplevel Makefile +# A depmod wrapper -if test $# -ne 2; then - echo "Usage: $0 /sbin/depmod <kernelrelease>" >&2 +if test $# -ne 1; then + echo "Usage: $0 <kernelrelease>" >&2 exit 1 fi -DEPMOD=$1 -KERNELRELEASE=$2 + +KERNELRELEASE=$1 + +: ${DEPMOD:=depmod} if ! test -r System.map ; then echo "Warning: modules_install: missing 'System.map' file. Skipping depmod." >&2 @@ -23,33 +25,8 @@ if [ -z $(command -v $DEPMOD) ]; then exit 0 fi -# older versions of depmod require the version string to start with three -# numbers, so we cheat with a symlink here -depmod_hack_needed=true -tmp_dir=$(mktemp -d ${TMPDIR:-/tmp}/depmod.XXXXXX) -mkdir -p "$tmp_dir/lib/modules/$KERNELRELEASE" -if "$DEPMOD" -b "$tmp_dir" $KERNELRELEASE 2>/dev/null; then - if test -e "$tmp_dir/lib/modules/$KERNELRELEASE/modules.dep" -o \ - -e "$tmp_dir/lib/modules/$KERNELRELEASE/modules.dep.bin"; then - depmod_hack_needed=false - fi -fi -rm -rf "$tmp_dir" -if $depmod_hack_needed; then - symlink="$INSTALL_MOD_PATH/lib/modules/99.98.$KERNELRELEASE" - ln -s "$KERNELRELEASE" "$symlink" - KERNELRELEASE=99.98.$KERNELRELEASE -fi - set -- -ae -F System.map if test -n "$INSTALL_MOD_PATH"; then set -- "$@" -b "$INSTALL_MOD_PATH" fi -"$DEPMOD" "$@" "$KERNELRELEASE" -ret=$? - -if $depmod_hack_needed; then - rm -f "$symlink" -fi - -exit $ret +exec "$DEPMOD" "$@" "$KERNELRELEASE" diff --git a/scripts/dummy-tools/gcc b/scripts/dummy-tools/gcc index 1db1889f6d81..07f6dc4c5cf6 100755 --- a/scripts/dummy-tools/gcc +++ b/scripts/dummy-tools/gcc @@ -85,8 +85,7 @@ if arg_contain -S "$@"; then fi # For arch/powerpc/tools/gcc-check-mprofile-kernel.sh - if arg_contain -m64 "$@" && arg_contain -mlittle-endian "$@" && - arg_contain -mprofile-kernel "$@"; then + if arg_contain -m64 "$@" && arg_contain -mprofile-kernel "$@"; then if ! test -t 0 && ! grep -q notrace; then echo "_mcount" fi diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile index af1c96198f49..4eee155121a8 100644 --- a/scripts/kconfig/Makefile +++ b/scripts/kconfig/Makefile @@ -93,11 +93,13 @@ endif %_defconfig: $(obj)/conf $(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig) -configfiles=$(wildcard $(srctree)/kernel/configs/$@ $(srctree)/arch/$(SRCARCH)/configs/$@) +configfiles = $(wildcard $(srctree)/kernel/configs/$(1) $(srctree)/arch/$(SRCARCH)/configs/$(1)) +all-config-fragments = $(call configfiles,*.config) +config-fragments = $(call configfiles,$@) %.config: $(obj)/conf - $(if $(call configfiles),, $(error No configuration exists for this target on this architecture)) - $(Q)$(CONFIG_SHELL) $(srctree)/scripts/kconfig/merge_config.sh -m .config $(configfiles) + $(if $(config-fragments),, $(error $@ fragment does not exists on this architecture)) + $(Q)$(CONFIG_SHELL) $(srctree)/scripts/kconfig/merge_config.sh -m .config $(config-fragments) $(Q)$(MAKE) -f $(srctree)/Makefile olddefconfig PHONY += tinyconfig @@ -115,6 +117,7 @@ clean-files += tests/.cache # Help text used by make help help: + @echo 'Configuration targets:' @echo ' config - Update current config utilising a line-oriented program' @echo ' nconfig - Update current config utilising a ncurses menu based program' @echo ' menuconfig - Update current config utilising a menu based program' @@ -141,6 +144,12 @@ help: @echo ' default value without prompting' @echo ' tinyconfig - Configure the tiniest possible kernel' @echo ' testconfig - Run Kconfig unit tests (requires python3 and pytest)' + @echo '' + @echo 'Configuration topic targets:' + @$(foreach f, $(all-config-fragments), \ + if help=$$(grep -m1 '^# Help: ' $(f)); then \ + printf ' %-25s - %s\n' '$(notdir $(f))' "$${help#*: }"; \ + fi;) # =========================================================================== # object files used by all kconfig flavours diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index 992575f1e976..4a6811d77d18 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c @@ -349,7 +349,11 @@ int conf_read_simple(const char *name, int def) char *p, *p2; struct symbol *sym; int i, def_flags; + const char *warn_unknown; + const char *werror; + warn_unknown = getenv("KCONFIG_WARN_UNKNOWN_SYMBOLS"); + werror = getenv("KCONFIG_WERROR"); if (name) { in = zconf_fopen(name); } else { @@ -437,6 +441,10 @@ load: if (def == S_DEF_USER) { sym = sym_find(line + 2 + strlen(CONFIG_)); if (!sym) { + if (warn_unknown) + conf_warning("unknown symbol: %s", + line + 2 + strlen(CONFIG_)); + conf_set_changed(true); continue; } @@ -471,7 +479,7 @@ load: sym = sym_find(line + strlen(CONFIG_)); if (!sym) { - if (def == S_DEF_AUTO) + if (def == S_DEF_AUTO) { /* * Reading from include/config/auto.conf * If CONFIG_FOO previously existed in @@ -479,8 +487,13 @@ load: * include/config/FOO must be touched. */ conf_touch_dep(line + strlen(CONFIG_)); - else + } else { + if (warn_unknown) + conf_warning("unknown symbol: %s", + line + strlen(CONFIG_)); + conf_set_changed(true); + } continue; } @@ -519,6 +532,10 @@ load: } free(line); fclose(in); + + if (conf_warnings && werror) + exit(1); + return 0; } diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h index 9c9caca5bd5f..4a9a23b1b7e1 100644 --- a/scripts/kconfig/expr.h +++ b/scripts/kconfig/expr.h @@ -275,7 +275,6 @@ struct jump_key { struct list_head entries; size_t offset; struct menu *target; - int index; }; extern struct file *file_list; diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h index e7118d62a45f..471a59acecec 100644 --- a/scripts/kconfig/lkc.h +++ b/scripts/kconfig/lkc.h @@ -101,6 +101,7 @@ const char *menu_get_prompt(struct menu *menu); struct menu *menu_get_parent_menu(struct menu *menu); bool menu_has_help(struct menu *menu); const char *menu_get_help(struct menu *menu); +int get_jump_key_char(void); struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head); void menu_get_ext_help(struct menu *menu, struct gstr *help); diff --git a/scripts/kconfig/lxdialog/dialog.h b/scripts/kconfig/lxdialog/dialog.h index 347daf25fdc8..a501abf9fa31 100644 --- a/scripts/kconfig/lxdialog/dialog.h +++ b/scripts/kconfig/lxdialog/dialog.h @@ -196,13 +196,9 @@ int first_alpha(const char *string, const char *exempt); int dialog_yesno(const char *title, const char *prompt, int height, int width); int dialog_msgbox(const char *title, const char *prompt, int height, int width, int pause); - - -typedef void (*update_text_fn)(char *buf, size_t start, size_t end, void - *_data); -int dialog_textbox(const char *title, char *tbuf, int initial_height, - int initial_width, int *keys, int *_vscroll, int *_hscroll, - update_text_fn update_text, void *data); +int dialog_textbox(const char *title, const char *tbuf, int initial_height, + int initial_width, int *_vscroll, int *_hscroll, + int (*extra_key_cb)(int, size_t, size_t, void *), void *data); int dialog_menu(const char *title, const char *prompt, const void *selected, int *s_scroll); int dialog_checklist(const char *title, const char *prompt, int height, diff --git a/scripts/kconfig/lxdialog/textbox.c b/scripts/kconfig/lxdialog/textbox.c index bc4d4fb1dc75..058ed0e5bbd5 100644 --- a/scripts/kconfig/lxdialog/textbox.c +++ b/scripts/kconfig/lxdialog/textbox.c @@ -10,8 +10,8 @@ static int hscroll; static int begin_reached, end_reached, page_length; -static char *buf; -static char *page; +static const char *buf, *page; +static size_t start, end; /* * Go back 'n' lines in text. Called by dialog_textbox(). @@ -98,21 +98,10 @@ static void print_line(WINDOW *win, int row, int width) /* * Print a new page of text. */ -static void print_page(WINDOW *win, int height, int width, update_text_fn - update_text, void *data) +static void print_page(WINDOW *win, int height, int width) { int i, passed_end = 0; - if (update_text) { - char *end; - - for (i = 0; i < height; i++) - get_line(); - end = page; - back_lines(height); - update_text(buf, page - buf, end - buf, data); - } - page_length = 0; for (i = 0; i < height; i++) { print_line(win, i, width); @@ -142,24 +131,26 @@ static void print_position(WINDOW *win) * refresh window content */ static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw, - int cur_y, int cur_x, update_text_fn update_text, - void *data) + int cur_y, int cur_x) { - print_page(box, boxh, boxw, update_text, data); + start = page - buf; + + print_page(box, boxh, boxw); print_position(dialog); wmove(dialog, cur_y, cur_x); /* Restore cursor position */ wrefresh(dialog); + + end = page - buf; } /* * Display text from a file in a dialog box. * * keys is a null-terminated array - * update_text() may not add or remove any '\n' or '\0' in tbuf */ -int dialog_textbox(const char *title, char *tbuf, int initial_height, - int initial_width, int *keys, int *_vscroll, int *_hscroll, - update_text_fn update_text, void *data) +int dialog_textbox(const char *title, const char *tbuf, int initial_height, + int initial_width, int *_vscroll, int *_hscroll, + int (*extra_key_cb)(int, size_t, size_t, void *), void *data) { int i, x, y, cur_x, cur_y, key = 0; int height, width, boxh, boxw; @@ -239,8 +230,7 @@ do_resize: /* Print first page of text */ attr_clear(box, boxh, boxw, dlg.dialog.atr); - refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x, update_text, - data); + refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x); while (!done) { key = wgetch(dialog); @@ -259,8 +249,7 @@ do_resize: begin_reached = 1; page = buf; refresh_text_box(dialog, box, boxh, boxw, - cur_y, cur_x, update_text, - data); + cur_y, cur_x); } break; case 'G': /* Last page */ @@ -270,8 +259,7 @@ do_resize: /* point to last char in buf */ page = buf + strlen(buf); back_lines(boxh); - refresh_text_box(dialog, box, boxh, boxw, cur_y, - cur_x, update_text, data); + refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x); break; case 'K': /* Previous line */ case 'k': @@ -280,8 +268,7 @@ do_resize: break; back_lines(page_length + 1); - refresh_text_box(dialog, box, boxh, boxw, cur_y, - cur_x, update_text, data); + refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x); break; case 'B': /* Previous page */ case 'b': @@ -290,8 +277,7 @@ do_resize: if (begin_reached) break; back_lines(page_length + boxh); - refresh_text_box(dialog, box, boxh, boxw, cur_y, - cur_x, update_text, data); + refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x); break; case 'J': /* Next line */ case 'j': @@ -300,8 +286,7 @@ do_resize: break; back_lines(page_length - 1); - refresh_text_box(dialog, box, boxh, boxw, cur_y, - cur_x, update_text, data); + refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x); break; case KEY_NPAGE: /* Next page */ case ' ': @@ -310,8 +295,7 @@ do_resize: break; begin_reached = 0; - refresh_text_box(dialog, box, boxh, boxw, cur_y, - cur_x, update_text, data); + refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x); break; case '0': /* Beginning of line */ case 'H': /* Scroll left */ @@ -326,8 +310,7 @@ do_resize: hscroll--; /* Reprint current page to scroll horizontally */ back_lines(page_length); - refresh_text_box(dialog, box, boxh, boxw, cur_y, - cur_x, update_text, data); + refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x); break; case 'L': /* Scroll right */ case 'l': @@ -337,8 +320,7 @@ do_resize: hscroll++; /* Reprint current page to scroll horizontally */ back_lines(page_length); - refresh_text_box(dialog, box, boxh, boxw, cur_y, - cur_x, update_text, data); + refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x); break; case KEY_ESC: if (on_key_esc(dialog) == KEY_ESC) @@ -351,11 +333,9 @@ do_resize: on_key_resize(); goto do_resize; default: - for (i = 0; keys[i]; i++) { - if (key == keys[i]) { - done = true; - break; - } + if (extra_key_cb && extra_key_cb(key, start, end, data)) { + done = true; + break; } } } diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c index 53d8834d12fe..eccc87a441e7 100644 --- a/scripts/kconfig/mconf.c +++ b/scripts/kconfig/mconf.c @@ -22,8 +22,6 @@ #include "lkc.h" #include "lxdialog/dialog.h" -#define JUMP_NB 9 - static const char mconf_readme[] = "Overview\n" "--------\n" @@ -288,6 +286,7 @@ static int single_menu_mode; static int show_all_options; static int save_and_exit; static int silent; +static int jump_key_char; static void conf(struct menu *menu, struct menu *active_menu); @@ -348,19 +347,19 @@ static void reset_subtitle(void) set_dialog_subtitles(subtitles); } -static int show_textbox_ext(const char *title, char *text, int r, int c, int - *keys, int *vscroll, int *hscroll, update_text_fn - update_text, void *data) +static int show_textbox_ext(const char *title, const char *text, int r, int c, + int *vscroll, int *hscroll, + int (*extra_key_cb)(int, size_t, size_t, void *), + void *data) { dialog_clear(); - return dialog_textbox(title, text, r, c, keys, vscroll, hscroll, - update_text, data); + return dialog_textbox(title, text, r, c, vscroll, hscroll, + extra_key_cb, data); } static void show_textbox(const char *title, const char *text, int r, int c) { - show_textbox_ext(title, (char *) text, r, c, (int []) {0}, NULL, NULL, - NULL, NULL); + show_textbox_ext(title, text, r, c, NULL, NULL, NULL, NULL); } static void show_helptext(const char *title, const char *text) @@ -381,35 +380,54 @@ static void show_help(struct menu *menu) struct search_data { struct list_head *head; - struct menu **targets; - int *keys; + struct menu *target; }; -static void update_text(char *buf, size_t start, size_t end, void *_data) +static int next_jump_key(int key) +{ + if (key < '1' || key > '9') + return '1'; + + key++; + + if (key > '9') + key = '1'; + + return key; +} + +static int handle_search_keys(int key, size_t start, size_t end, void *_data) { struct search_data *data = _data; struct jump_key *pos; - int k = 0; + int index = 0; + + if (key < '1' || key > '9') + return 0; list_for_each_entry(pos, data->head, entries) { - if (pos->offset >= start && pos->offset < end) { - char header[4]; + index = next_jump_key(index); - if (k < JUMP_NB) { - int key = '0' + (pos->index % JUMP_NB) + 1; + if (pos->offset < start) + continue; - sprintf(header, "(%c)", key); - data->keys[k] = key; - data->targets[k] = pos->target; - k++; - } else { - sprintf(header, " "); - } + if (pos->offset >= end) + break; - memcpy(buf + pos->offset, header, sizeof(header) - 1); + if (key == index) { + data->target = pos->target; + return 1; } } - data->keys[k] = 0; + + return 0; +} + +int get_jump_key_char(void) +{ + jump_key_char = next_jump_key(jump_key_char); + + return jump_key_char; } static void search_conf(void) @@ -456,26 +474,23 @@ again: sym_arr = sym_re_search(dialog_input); do { LIST_HEAD(head); - struct menu *targets[JUMP_NB]; - int keys[JUMP_NB + 1], i; struct search_data data = { .head = &head, - .targets = targets, - .keys = keys, }; struct jump_key *pos, *tmp; + jump_key_char = 0; res = get_relations_str(sym_arr, &head); set_subtitle(); dres = show_textbox_ext("Search Results", str_get(&res), 0, 0, - keys, &vscroll, &hscroll, &update_text, - &data); + &vscroll, &hscroll, + handle_search_keys, &data); again = false; - for (i = 0; i < JUMP_NB && keys[i]; i++) - if (dres == keys[i]) { - conf(targets[i]->parent, targets[i]); - again = true; - } + if (dres >= '1' && dres <= '9') { + assert(data.target != NULL); + conf(data.target->parent, data.target); + again = true; + } str_free(&res); list_for_each_entry_safe(pos, tmp, &head, entries) free(pos); diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c index b90fff833588..61c442d84aef 100644 --- a/scripts/kconfig/menu.c +++ b/scripts/kconfig/menu.c @@ -701,6 +701,11 @@ static void get_dep_str(struct gstr *r, struct expr *expr, const char *prefix) } } +int __attribute__((weak)) get_jump_key_char(void) +{ + return -1; +} + static void get_prompt_str(struct gstr *r, struct property *prop, struct list_head *head) { @@ -730,24 +735,27 @@ static void get_prompt_str(struct gstr *r, struct property *prop, } if (head && location) { jump = xmalloc(sizeof(struct jump_key)); - jump->target = location; - - if (list_empty(head)) - jump->index = 0; - else - jump->index = list_entry(head->prev, struct jump_key, - entries)->index + 1; - list_add_tail(&jump->entries, head); } str_printf(r, " Location:\n"); - for (j = 4; --i >= 0; j += 2) { + for (j = 0; --i >= 0; j++) { + int jk = -1; + int indent = 2 * j + 4; + menu = submenu[i]; - if (jump && menu == location) + if (jump && menu == location) { jump->offset = strlen(r->s); - str_printf(r, "%*c-> %s", j, ' ', menu_get_prompt(menu)); + jk = get_jump_key_char(); + } + + if (jk >= 0) { + str_printf(r, "(%c)", jk); + indent -= 3; + } + + str_printf(r, "%*c-> %s", indent, ' ', menu_get_prompt(menu)); if (menu->sym) { str_printf(r, " (%s [=%s])", menu->sym->name ? menu->sym->name : "<choice>", diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c index 3ba8b1af390f..143a2c351d57 100644 --- a/scripts/kconfig/nconf.c +++ b/scripts/kconfig/nconf.c @@ -220,7 +220,7 @@ search_help[] = "Location:\n" " -> Bus options (PCI, PCMCIA, EISA, ISA)\n" " -> PCI support (PCI [ = y])\n" -" -> PCI access mode (<choice> [ = y])\n" +"(1) -> PCI access mode (<choice> [ = y])\n" "Selects: LIBCRC32\n" "Selected by: BAR\n" "-----------------------------------------------------------------\n" @@ -231,9 +231,13 @@ search_help[] = "o The 'Depends on:' line lists symbols that need to be defined for\n" " this symbol to be visible and selectable in the menu.\n" "o The 'Location:' lines tell, where in the menu structure this symbol\n" -" is located. A location followed by a [ = y] indicates that this is\n" -" a selectable menu item, and the current value is displayed inside\n" -" brackets.\n" +" is located.\n" +" A location followed by a [ = y] indicates that this is\n" +" a selectable menu item, and the current value is displayed inside\n" +" brackets.\n" +" Press the key in the (#) prefix to jump directly to that\n" +" location. You will be returned to the current search results\n" +" after exiting this new menu.\n" "o The 'Selects:' line tells, what symbol will be automatically selected\n" " if this symbol is selected (y or m).\n" "o The 'Selected by' line tells what symbol has selected this symbol.\n" @@ -275,7 +279,9 @@ static const char *current_instructions = menu_instructions; static char *dialog_input_result; static int dialog_input_result_len; +static int jump_key_char; +static void selected_conf(struct menu *menu, struct menu *active_menu); static void conf(struct menu *menu); static void conf_choice(struct menu *menu); static void conf_string(struct menu *menu); @@ -685,6 +691,57 @@ static int do_exit(void) return 0; } +struct search_data { + struct list_head *head; + struct menu *target; +}; + +static int next_jump_key(int key) +{ + if (key < '1' || key > '9') + return '1'; + + key++; + + if (key > '9') + key = '1'; + + return key; +} + +static int handle_search_keys(int key, size_t start, size_t end, void *_data) +{ + struct search_data *data = _data; + struct jump_key *pos; + int index = 0; + + if (key < '1' || key > '9') + return 0; + + list_for_each_entry(pos, data->head, entries) { + index = next_jump_key(index); + + if (pos->offset < start) + continue; + + if (pos->offset >= end) + break; + + if (key == index) { + data->target = pos->target; + return 1; + } + } + + return 0; +} + +int get_jump_key_char(void) +{ + jump_key_char = next_jump_key(jump_key_char); + + return jump_key_char; +} static void search_conf(void) { @@ -692,7 +749,8 @@ static void search_conf(void) struct gstr res; struct gstr title; char *dialog_input; - int dres; + int dres, vscroll = 0, hscroll = 0; + bool again; title = str_new(); str_printf( &title, "Enter (sub)string or regexp to search for " @@ -721,11 +779,28 @@ again: dialog_input += strlen(CONFIG_); sym_arr = sym_re_search(dialog_input); - res = get_relations_str(sym_arr, NULL); + + do { + LIST_HEAD(head); + struct search_data data = { + .head = &head, + .target = NULL, + }; + jump_key_char = 0; + res = get_relations_str(sym_arr, &head); + dres = show_scroll_win_ext(main_window, + "Search Results", str_get(&res), + &vscroll, &hscroll, + handle_search_keys, &data); + again = false; + if (dres >= '1' && dres <= '9') { + assert(data.target != NULL); + selected_conf(data.target->parent, data.target); + again = true; + } + str_free(&res); + } while (again); free(sym_arr); - show_scroll_win(main_window, - "Search Results", str_get(&res)); - str_free(&res); str_free(&title); } @@ -1063,9 +1138,14 @@ static int do_match(int key, struct match_state *state, int *ans) static void conf(struct menu *menu) { + selected_conf(menu, NULL); +} + +static void selected_conf(struct menu *menu, struct menu *active_menu) +{ struct menu *submenu = NULL; struct symbol *sym; - int res; + int i, res; int current_index = 0; int last_top_row = 0; struct match_state match_state = { @@ -1081,6 +1161,19 @@ static void conf(struct menu *menu) if (!child_count) break; + if (active_menu != NULL) { + for (i = 0; i < items_num; i++) { + struct mitem *mcur; + + mcur = (struct mitem *) item_userptr(curses_menu_items[i]); + if ((struct menu *) mcur->usrptr == active_menu) { + current_index = i; + break; + } + } + active_menu = NULL; + } + show_menu(menu_get_prompt(menu), menu_instructions, current_index, &last_top_row); keypad((menu_win(curses_menu)), TRUE); diff --git a/scripts/kconfig/nconf.gui.c b/scripts/kconfig/nconf.gui.c index 9aedf40f1dc0..25a7263ef3c8 100644 --- a/scripts/kconfig/nconf.gui.c +++ b/scripts/kconfig/nconf.gui.c @@ -497,11 +497,18 @@ void refresh_all_windows(WINDOW *main_window) refresh(); } -/* layman's scrollable window... */ void show_scroll_win(WINDOW *main_window, const char *title, const char *text) { + (void)show_scroll_win_ext(main_window, title, (char *)text, NULL, NULL, NULL, NULL); +} + +/* layman's scrollable window... */ +int show_scroll_win_ext(WINDOW *main_window, const char *title, char *text, + int *vscroll, int *hscroll, + extra_key_cb_fn extra_key_cb, void *data) +{ int res; int total_lines = get_line_no(text); int x, y, lines, columns; @@ -514,6 +521,12 @@ void show_scroll_win(WINDOW *main_window, WINDOW *win; WINDOW *pad; PANEL *panel; + bool done = false; + + if (hscroll) + start_x = *hscroll; + if (vscroll) + start_y = *vscroll; getmaxyx(stdscr, lines, columns); @@ -549,8 +562,7 @@ void show_scroll_win(WINDOW *main_window, panel = new_panel(win); /* handle scrolling */ - do { - + while (!done) { copywin(pad, win, start_y, start_x, 2, 2, text_lines, text_cols, 0); print_in_middle(win, @@ -593,8 +605,18 @@ void show_scroll_win(WINDOW *main_window, case 'l': start_x++; break; + default: + if (extra_key_cb) { + size_t start = (get_line(text, start_y) - text); + size_t end = (get_line(text, start_y + text_lines) - text); + + if (extra_key_cb(res, start, end, data)) { + done = true; + break; + } + } } - if (res == 10 || res == 27 || res == 'q' || + if (res == 0 || res == 10 || res == 27 || res == 'q' || res == KEY_F(F_HELP) || res == KEY_F(F_BACK) || res == KEY_F(F_EXIT)) break; @@ -606,9 +628,14 @@ void show_scroll_win(WINDOW *main_window, start_x = 0; if (start_x >= total_cols-text_cols) start_x = total_cols-text_cols; - } while (res); + } + if (hscroll) + *hscroll = start_x; + if (vscroll) + *vscroll = start_y; del_panel(panel); delwin(win); refresh_all_windows(main_window); + return res; } diff --git a/scripts/kconfig/nconf.h b/scripts/kconfig/nconf.h index 6f925bc74eb3..ab836d582664 100644 --- a/scripts/kconfig/nconf.h +++ b/scripts/kconfig/nconf.h @@ -67,6 +67,8 @@ typedef enum { void set_colors(void); +typedef int (*extra_key_cb_fn)(int, size_t, size_t, void *); + /* this changes the windows attributes !!! */ void print_in_middle(WINDOW *win, int y, int width, const char *str, int attrs); int get_line_length(const char *line); @@ -78,6 +80,9 @@ int dialog_inputbox(WINDOW *main_window, const char *title, const char *prompt, const char *init, char **resultp, int *result_len); void refresh_all_windows(WINDOW *main_window); +int show_scroll_win_ext(WINDOW *main_window, const char *title, char *text, + int *vscroll, int *hscroll, + extra_key_cb_fn extra_key_cb, void *data); void show_scroll_win(WINDOW *main_window, const char *title, const char *text); diff --git a/scripts/kconfig/preprocess.c b/scripts/kconfig/preprocess.c index 748da578b418..d1f5bcff4b62 100644 --- a/scripts/kconfig/preprocess.c +++ b/scripts/kconfig/preprocess.c @@ -396,6 +396,9 @@ static char *eval_clause(const char *str, size_t len, int argc, char *argv[]) p++; } + + if (new_argc >= FUNCTION_MAX_ARGS) + pperror("too many function arguments"); new_argv[new_argc++] = prev; /* diff --git a/scripts/kconfig/qconf-cfg.sh b/scripts/kconfig/qconf-cfg.sh index 117f36e568fc..0e113b0f2455 100755 --- a/scripts/kconfig/qconf-cfg.sh +++ b/scripts/kconfig/qconf-cfg.sh @@ -5,7 +5,8 @@ cflags=$1 libs=$2 bin=$3 -PKG="Qt5Core Qt5Gui Qt5Widgets" +PKG5="Qt5Core Qt5Gui Qt5Widgets" +PKG6="Qt6Core Qt6Gui Qt6Widgets" if [ -z "$(command -v ${HOSTPKG_CONFIG})" ]; then echo >&2 "*" @@ -14,16 +15,26 @@ if [ -z "$(command -v ${HOSTPKG_CONFIG})" ]; then exit 1 fi -if ${HOSTPKG_CONFIG} --exists $PKG; then - ${HOSTPKG_CONFIG} --cflags ${PKG} > ${cflags} - ${HOSTPKG_CONFIG} --libs ${PKG} > ${libs} +if ${HOSTPKG_CONFIG} --exists $PKG6; then + ${HOSTPKG_CONFIG} --cflags ${PKG6} > ${cflags} + # Qt6 requires C++17. + echo -std=c++17 >> ${cflags} + ${HOSTPKG_CONFIG} --libs ${PKG6} > ${libs} + ${HOSTPKG_CONFIG} --variable=libexecdir Qt6Core > ${bin} + exit 0 +fi + +if ${HOSTPKG_CONFIG} --exists $PKG5; then + ${HOSTPKG_CONFIG} --cflags ${PKG5} > ${cflags} + ${HOSTPKG_CONFIG} --libs ${PKG5} > ${libs} ${HOSTPKG_CONFIG} --variable=host_bins Qt5Core > ${bin} exit 0 fi echo >&2 "*" -echo >&2 "* Could not find Qt5 via ${HOSTPKG_CONFIG}." -echo >&2 "* Please install Qt5 and make sure it's in PKG_CONFIG_PATH" -echo >&2 "* You need $PKG" +echo >&2 "* Could not find Qt6 or Qt5 via ${HOSTPKG_CONFIG}." +echo >&2 "* Please install Qt6 or Qt5 and make sure it's in PKG_CONFIG_PATH" +echo >&2 "* You need $PKG6 for Qt6" +echo >&2 "* You need $PKG5 for Qt5" echo >&2 "*" exit 1 diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc index 78087b2d9ac6..620a3527c767 100644 --- a/scripts/kconfig/qconf.cc +++ b/scripts/kconfig/qconf.cc @@ -5,10 +5,10 @@ */ #include <QAction> +#include <QActionGroup> #include <QApplication> #include <QCloseEvent> #include <QDebug> -#include <QDesktopWidget> #include <QFileDialog> #include <QLabel> #include <QLayout> @@ -16,6 +16,8 @@ #include <QMenu> #include <QMenuBar> #include <QMessageBox> +#include <QRegularExpression> +#include <QScreen> #include <QToolBar> #include <stdlib.h> @@ -1126,7 +1128,7 @@ QString ConfigInfoView::debug_info(struct symbol *sym) QString ConfigInfoView::print_filter(const QString &str) { - QRegExp re("[<>&\"\\n]"); + QRegularExpression re("[<>&\"\\n]"); QString res = str; for (int i = 0; (i = res.indexOf(re, i)) >= 0;) { switch (res[i].toLatin1()) { @@ -1322,15 +1324,15 @@ ConfigMainWindow::ConfigMainWindow(void) int width, height; char title[256]; - QDesktopWidget *d = configApp->desktop(); snprintf(title, sizeof(title), "%s%s", rootmenu.prompt->text, "" ); setWindowTitle(title); - width = configSettings->value("/window width", d->width() - 64).toInt(); - height = configSettings->value("/window height", d->height() - 64).toInt(); + QRect g = configApp->primaryScreen()->geometry(); + width = configSettings->value("/window width", g.width() - 64).toInt(); + height = configSettings->value("/window height", g.height() - 64).toInt(); resize(width, height); x = configSettings->value("/window x"); y = configSettings->value("/window y"); @@ -1379,17 +1381,17 @@ ConfigMainWindow::ConfigMainWindow(void) this, &ConfigMainWindow::goBack); QAction *quitAction = new QAction("&Quit", this); - quitAction->setShortcut(Qt::CTRL + Qt::Key_Q); + quitAction->setShortcut(Qt::CTRL | Qt::Key_Q); connect(quitAction, &QAction::triggered, this, &ConfigMainWindow::close); QAction *loadAction = new QAction(QPixmap(xpm_load), "&Load", this); - loadAction->setShortcut(Qt::CTRL + Qt::Key_L); + loadAction->setShortcut(Qt::CTRL | Qt::Key_L); connect(loadAction, &QAction::triggered, this, &ConfigMainWindow::loadConfig); saveAction = new QAction(QPixmap(xpm_save), "&Save", this); - saveAction->setShortcut(Qt::CTRL + Qt::Key_S); + saveAction->setShortcut(Qt::CTRL | Qt::Key_S); connect(saveAction, &QAction::triggered, this, &ConfigMainWindow::saveConfig); @@ -1403,7 +1405,7 @@ ConfigMainWindow::ConfigMainWindow(void) connect(saveAsAction, &QAction::triggered, this, &ConfigMainWindow::saveConfigAs); QAction *searchAction = new QAction("&Find", this); - searchAction->setShortcut(Qt::CTRL + Qt::Key_F); + searchAction->setShortcut(Qt::CTRL | Qt::Key_F); connect(searchAction, &QAction::triggered, this, &ConfigMainWindow::searchConfig); singleViewAction = new QAction(QPixmap(xpm_single_view), "Single View", this); @@ -1750,11 +1752,21 @@ void ConfigMainWindow::closeEvent(QCloseEvent* e) e->accept(); return; } - QMessageBox mb("qconf", "Save configuration?", QMessageBox::Warning, - QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape); - mb.setButtonText(QMessageBox::Yes, "&Save Changes"); - mb.setButtonText(QMessageBox::No, "&Discard Changes"); - mb.setButtonText(QMessageBox::Cancel, "Cancel Exit"); + + QMessageBox mb(QMessageBox::Icon::Warning, "qconf", + "Save configuration?"); + + QPushButton *yb = mb.addButton(QMessageBox::Yes); + QPushButton *db = mb.addButton(QMessageBox::No); + QPushButton *cb = mb.addButton(QMessageBox::Cancel); + + yb->setText("&Save Changes"); + db->setText("&Discard Changes"); + cb->setText("Cancel Exit"); + + mb.setDefaultButton(yb); + mb.setEscapeButton(cb); + switch (mb.exec()) { case QMessageBox::Yes: if (saveConfig()) diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index b29b29707f10..34a5386d444a 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -24,6 +24,7 @@ #include "../../include/linux/license.h" #include "../../include/linux/module_symbol.h" +static bool module_enabled; /* Are we using CONFIG_MODVERSIONS? */ static bool modversions; /* Is CONFIG_MODULE_SRCVERSION_ALL set? */ @@ -761,6 +762,7 @@ static const char *const section_white_list[] = ".fmt_slot*", /* EZchip */ ".gnu.lto*", ".discard.*", + ".llvm.call-graph-profile", /* call graph */ NULL }; @@ -1242,7 +1244,7 @@ static void check_section_mismatch(struct module *mod, struct elf_info *elf, const char *tosec = sec_name(elf, get_secindex(elf, sym)); const struct sectioncheck *mismatch; - if (elf->export_symbol_secndx == fsecndx) { + if (module_enabled && elf->export_symbol_secndx == fsecndx) { check_export_symbol(mod, elf, faddr, tosec, sym); return; } @@ -1256,21 +1258,16 @@ static void check_section_mismatch(struct module *mod, struct elf_info *elf, tosec, taddr); } -static int addend_386_rel(uint32_t *location, Elf_Rela *r) +static Elf_Addr addend_386_rel(uint32_t *location, unsigned int r_type) { - unsigned int r_typ = ELF_R_TYPE(r->r_info); - - switch (r_typ) { + switch (r_type) { case R_386_32: - r->r_addend = TO_NATIVE(*location); - break; + return TO_NATIVE(*location); case R_386_PC32: - r->r_addend = TO_NATIVE(*location) + 4; - break; - default: - r->r_addend = (Elf_Addr)(-1); + return TO_NATIVE(*location) + 4; } - return 0; + + return (Elf_Addr)(-1); } #ifndef R_ARM_CALL @@ -1314,32 +1311,28 @@ static int32_t sign_extend32(int32_t value, int index) return (int32_t)(value << shift) >> shift; } -static int addend_arm_rel(void *loc, Elf_Sym *sym, Elf_Rela *r) +static Elf_Addr addend_arm_rel(void *loc, Elf_Sym *sym, unsigned int r_type) { - unsigned int r_typ = ELF_R_TYPE(r->r_info); uint32_t inst, upper, lower, sign, j1, j2; int32_t offset; - switch (r_typ) { + switch (r_type) { case R_ARM_ABS32: case R_ARM_REL32: inst = TO_NATIVE(*(uint32_t *)loc); - r->r_addend = inst + sym->st_value; - break; + return inst + sym->st_value; case R_ARM_MOVW_ABS_NC: case R_ARM_MOVT_ABS: inst = TO_NATIVE(*(uint32_t *)loc); offset = sign_extend32(((inst & 0xf0000) >> 4) | (inst & 0xfff), 15); - r->r_addend = offset + sym->st_value; - break; + return offset + sym->st_value; case R_ARM_PC24: case R_ARM_CALL: case R_ARM_JUMP24: inst = TO_NATIVE(*(uint32_t *)loc); offset = sign_extend32((inst & 0x00ffffff) << 2, 25); - r->r_addend = offset + sym->st_value + 8; - break; + return offset + sym->st_value + 8; case R_ARM_THM_MOVW_ABS_NC: case R_ARM_THM_MOVT_ABS: upper = TO_NATIVE(*(uint16_t *)loc); @@ -1349,8 +1342,7 @@ static int addend_arm_rel(void *loc, Elf_Sym *sym, Elf_Rela *r) ((lower & 0x7000) >> 4) | (lower & 0x00ff), 15); - r->r_addend = offset + sym->st_value; - break; + return offset + sym->st_value; case R_ARM_THM_JUMP19: /* * Encoding T3: @@ -1371,8 +1363,7 @@ static int addend_arm_rel(void *loc, Elf_Sym *sym, Elf_Rela *r) ((upper & 0x03f) << 12) | ((lower & 0x07ff) << 1), 20); - r->r_addend = offset + sym->st_value + 4; - break; + return offset + sym->st_value + 4; case R_ARM_THM_CALL: case R_ARM_THM_JUMP24: /* @@ -1398,34 +1389,26 @@ static int addend_arm_rel(void *loc, Elf_Sym *sym, Elf_Rela *r) ((upper & 0x03ff) << 12) | ((lower & 0x07ff) << 1), 24); - r->r_addend = offset + sym->st_value + 4; - break; - default: - r->r_addend = (Elf_Addr)(-1); + return offset + sym->st_value + 4; } - return 0; + + return (Elf_Addr)(-1); } -static int addend_mips_rel(uint32_t *location, Elf_Rela *r) +static Elf_Addr addend_mips_rel(uint32_t *location, unsigned int r_type) { - unsigned int r_typ = ELF_R_TYPE(r->r_info); uint32_t inst; inst = TO_NATIVE(*location); - switch (r_typ) { + switch (r_type) { case R_MIPS_LO16: - r->r_addend = inst & 0xffff; - break; + return inst & 0xffff; case R_MIPS_26: - r->r_addend = (inst & 0x03ffffff) << 2; - break; + return (inst & 0x03ffffff) << 2; case R_MIPS_32: - r->r_addend = inst; - break; - default: - r->r_addend = (Elf_Addr)(-1); + return inst; } - return 0; + return (Elf_Addr)(-1); } #ifndef EM_RISCV @@ -1444,12 +1427,45 @@ static int addend_mips_rel(uint32_t *location, Elf_Rela *r) #define R_LARCH_SUB32 55 #endif +static void get_rel_type_and_sym(struct elf_info *elf, uint64_t r_info, + unsigned int *r_type, unsigned int *r_sym) +{ + typedef struct { + Elf64_Word r_sym; /* Symbol index */ + unsigned char r_ssym; /* Special symbol for 2nd relocation */ + unsigned char r_type3; /* 3rd relocation type */ + unsigned char r_type2; /* 2nd relocation type */ + unsigned char r_type; /* 1st relocation type */ + } Elf64_Mips_R_Info; + + bool is_64bit = (elf->hdr->e_ident[EI_CLASS] == ELFCLASS64); + + if (elf->hdr->e_machine == EM_MIPS && is_64bit) { + Elf64_Mips_R_Info *mips64_r_info = (void *)&r_info; + + *r_type = mips64_r_info->r_type; + *r_sym = TO_NATIVE(mips64_r_info->r_sym); + return; + } + + if (is_64bit) { + Elf64_Xword r_info64 = r_info; + + r_info = TO_NATIVE(r_info64); + } else { + Elf32_Word r_info32 = r_info; + + r_info = TO_NATIVE(r_info32); + } + + *r_type = ELF_R_TYPE(r_info); + *r_sym = ELF_R_SYM(r_info); +} + static void section_rela(struct module *mod, struct elf_info *elf, Elf_Shdr *sechdr) { Elf_Rela *rela; - Elf_Rela r; - unsigned int r_sym; unsigned int fsecndx = sechdr->sh_info; const char *fromsec = sec_name(elf, fsecndx); Elf_Rela *start = (void *)elf->hdr + sechdr->sh_offset; @@ -1460,38 +1476,29 @@ static void section_rela(struct module *mod, struct elf_info *elf, return; for (rela = start; rela < stop; rela++) { - r.r_offset = TO_NATIVE(rela->r_offset); -#if KERNEL_ELFCLASS == ELFCLASS64 - if (elf->hdr->e_machine == EM_MIPS) { - unsigned int r_typ; - r_sym = ELF64_MIPS_R_SYM(rela->r_info); - r_sym = TO_NATIVE(r_sym); - r_typ = ELF64_MIPS_R_TYPE(rela->r_info); - r.r_info = ELF64_R_INFO(r_sym, r_typ); - } else { - r.r_info = TO_NATIVE(rela->r_info); - r_sym = ELF_R_SYM(r.r_info); - } -#else - r.r_info = TO_NATIVE(rela->r_info); - r_sym = ELF_R_SYM(r.r_info); -#endif - r.r_addend = TO_NATIVE(rela->r_addend); + Elf_Addr taddr, r_offset; + unsigned int r_type, r_sym; + + r_offset = TO_NATIVE(rela->r_offset); + get_rel_type_and_sym(elf, rela->r_info, &r_type, &r_sym); + + taddr = TO_NATIVE(rela->r_addend); + switch (elf->hdr->e_machine) { case EM_RISCV: if (!strcmp("__ex_table", fromsec) && - ELF_R_TYPE(r.r_info) == R_RISCV_SUB32) + r_type == R_RISCV_SUB32) continue; break; case EM_LOONGARCH: if (!strcmp("__ex_table", fromsec) && - ELF_R_TYPE(r.r_info) == R_LARCH_SUB32) + r_type == R_LARCH_SUB32) continue; break; } check_section_mismatch(mod, elf, elf->symtab_start + r_sym, - fsecndx, fromsec, r.r_offset, r.r_addend); + fsecndx, fromsec, r_offset, taddr); } } @@ -1499,8 +1506,6 @@ static void section_rel(struct module *mod, struct elf_info *elf, Elf_Shdr *sechdr) { Elf_Rel *rel; - Elf_Rela r; - unsigned int r_sym; unsigned int fsecndx = sechdr->sh_info; const char *fromsec = sec_name(elf, fsecndx); Elf_Rel *start = (void *)elf->hdr + sechdr->sh_offset; @@ -1512,45 +1517,32 @@ static void section_rel(struct module *mod, struct elf_info *elf, for (rel = start; rel < stop; rel++) { Elf_Sym *tsym; + Elf_Addr taddr = 0, r_offset; + unsigned int r_type, r_sym; void *loc; - r.r_offset = TO_NATIVE(rel->r_offset); -#if KERNEL_ELFCLASS == ELFCLASS64 - if (elf->hdr->e_machine == EM_MIPS) { - unsigned int r_typ; - r_sym = ELF64_MIPS_R_SYM(rel->r_info); - r_sym = TO_NATIVE(r_sym); - r_typ = ELF64_MIPS_R_TYPE(rel->r_info); - r.r_info = ELF64_R_INFO(r_sym, r_typ); - } else { - r.r_info = TO_NATIVE(rel->r_info); - r_sym = ELF_R_SYM(r.r_info); - } -#else - r.r_info = TO_NATIVE(rel->r_info); - r_sym = ELF_R_SYM(r.r_info); -#endif - r.r_addend = 0; + r_offset = TO_NATIVE(rel->r_offset); + get_rel_type_and_sym(elf, rel->r_info, &r_type, &r_sym); - loc = sym_get_data_by_offset(elf, fsecndx, r.r_offset); + loc = sym_get_data_by_offset(elf, fsecndx, r_offset); tsym = elf->symtab_start + r_sym; switch (elf->hdr->e_machine) { case EM_386: - addend_386_rel(loc, &r); + taddr = addend_386_rel(loc, r_type); break; case EM_ARM: - addend_arm_rel(loc, tsym, &r); + taddr = addend_arm_rel(loc, tsym, r_type); break; case EM_MIPS: - addend_mips_rel(loc, &r); + taddr = addend_mips_rel(loc, r_type); break; default: fatal("Please add code to calculate addend for this architecture\n"); } check_section_mismatch(mod, elf, tsym, - fsecndx, fromsec, r.r_offset, r.r_addend); + fsecndx, fromsec, r_offset, taddr); } } @@ -2272,7 +2264,7 @@ int main(int argc, char **argv) LIST_HEAD(dump_lists); struct dump_list *dl, *dl2; - while ((opt = getopt(argc, argv, "ei:mnT:to:au:WwENd:")) != -1) { + while ((opt = getopt(argc, argv, "ei:MmnT:to:au:WwENd:")) != -1) { switch (opt) { case 'e': external_module = true; @@ -2282,6 +2274,9 @@ int main(int argc, char **argv) dl->file = optarg; list_add_tail(&dl->list, &dump_lists); break; + case 'M': + module_enabled = true; + break; case 'm': modversions = true; break; diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h index dfdb9484e325..5f94c2c9f2d9 100644 --- a/scripts/mod/modpost.h +++ b/scripts/mod/modpost.h @@ -50,28 +50,6 @@ #define ELF_R_TYPE ELF64_R_TYPE #endif -/* The 64-bit MIPS ELF ABI uses an unusual reloc format. */ -typedef struct -{ - Elf32_Word r_sym; /* Symbol index */ - unsigned char r_ssym; /* Special symbol for 2nd relocation */ - unsigned char r_type3; /* 3rd relocation type */ - unsigned char r_type2; /* 2nd relocation type */ - unsigned char r_type1; /* 1st relocation type */ -} _Elf64_Mips_R_Info; - -typedef union -{ - Elf64_Xword r_info_number; - _Elf64_Mips_R_Info r_info_fields; -} _Elf64_Mips_R_Info_union; - -#define ELF64_MIPS_R_SYM(i) \ - ((__extension__ (_Elf64_Mips_R_Info_union)(i)).r_info_fields.r_sym) - -#define ELF64_MIPS_R_TYPE(i) \ - ((__extension__ (_Elf64_Mips_R_Info_union)(i)).r_info_fields.r_type1) - #if KERNEL_ELFDATA != HOST_ELFDATA static inline void __endian(const void *src, void *dest, unsigned int size) diff --git a/scripts/package/builddeb b/scripts/package/builddeb index 032774eb061e..bf3f8561aa68 100755 --- a/scripts/package/builddeb +++ b/scripts/package/builddeb @@ -162,34 +162,7 @@ install_kernel_headers () { rm -rf $pdir - ( - cd $srctree - find . arch/$SRCARCH -maxdepth 1 -name Makefile\* - find include scripts -type f -o -type l - find arch/$SRCARCH -name Kbuild.platforms -o -name Platform - find $(find arch/$SRCARCH -name include -o -name scripts -type d) -type f - ) > debian/hdrsrcfiles - - { - if is_enabled CONFIG_OBJTOOL; then - echo tools/objtool/objtool - fi - - find arch/$SRCARCH/include Module.symvers include scripts -type f - - if is_enabled CONFIG_GCC_PLUGINS; then - find scripts/gcc-plugins -name \*.so - fi - } > debian/hdrobjfiles - - destdir=$pdir/usr/src/linux-headers-$version - mkdir -p $destdir - tar -c -f - -C $srctree -T debian/hdrsrcfiles | tar -xf - -C $destdir - tar -c -f - -T debian/hdrobjfiles | tar -xf - -C $destdir - rm -f debian/hdrsrcfiles debian/hdrobjfiles - - # copy .config manually to be where it's expected to be - cp $KCONFIG_CONFIG $destdir/.config + "${srctree}/scripts/package/install-extmod-build" "${pdir}/usr/src/linux-headers-${version}" mkdir -p $pdir/lib/modules/$version/ ln -s /usr/src/linux-headers-$version $pdir/lib/modules/$version/build diff --git a/scripts/package/debian/rules b/scripts/package/debian/rules new file mode 100755 index 000000000000..3dafa9496c63 --- /dev/null +++ b/scripts/package/debian/rules @@ -0,0 +1,33 @@ +#!/usr/bin/make -f +# SPDX-License-Identifier: GPL-2.0-only + +include debian/rules.vars + +srctree ?= . + +ifneq (,$(filter-out parallel=1,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))) + NUMJOBS = $(patsubst parallel=%,%,$(filter parallel=%,$(DEB_BUILD_OPTIONS))) + MAKEFLAGS += -j$(NUMJOBS) +endif + +.PHONY: binary binary-indep binary-arch +binary: binary-arch binary-indep +binary-indep: build-indep +binary-arch: build-arch + $(MAKE) -f $(srctree)/Makefile ARCH=$(ARCH) \ + KERNELRELEASE=$(KERNELRELEASE) \ + run-command KBUILD_RUN_COMMAND=+$(srctree)/scripts/package/builddeb + +.PHONY: build build-indep build-arch +build: build-arch build-indep +build-indep: +build-arch: + $(MAKE) -f $(srctree)/Makefile ARCH=$(ARCH) \ + KERNELRELEASE=$(KERNELRELEASE) \ + $(shell $(srctree)/scripts/package/deb-build-option) \ + olddefconfig all + +.PHONY: clean +clean: + rm -rf debian/files debian/linux-* + $(MAKE) -f $(srctree)/Makefile ARCH=$(ARCH) clean diff --git a/scripts/package/install-extmod-build b/scripts/package/install-extmod-build new file mode 100755 index 000000000000..af7fe9f5b1e4 --- /dev/null +++ b/scripts/package/install-extmod-build @@ -0,0 +1,39 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0-only + +set -e + +destdir=${1} + +test -n "${srctree}" +test -n "${SRCARCH}" + +is_enabled() { + grep -q "^$1=y" include/config/auto.conf +} + +mkdir -p "${destdir}" + +( + cd "${srctree}" + echo Makefile + find "arch/${SRCARCH}" -maxdepth 1 -name 'Makefile*' + find include scripts -type f -o -type l + find "arch/${SRCARCH}" -name Kbuild.platforms -o -name Platform + find "$(find "arch/${SRCARCH}" -name include -o -name scripts -type d)" -type f +) | tar -c -f - -C "${srctree}" -T - | tar -xf - -C "${destdir}" + +{ + if is_enabled CONFIG_OBJTOOL; then + echo tools/objtool/objtool + fi + + find "arch/${SRCARCH}/include" Module.symvers include scripts -type f + + if is_enabled CONFIG_GCC_PLUGINS; then + find scripts/gcc-plugins -name '*.so' + fi +} | tar -c -f - -T - | tar -xf - -C "${destdir}" + +# copy .config manually to be where it's expected to be +cp "${KCONFIG_CONFIG}" "${destdir}/.config" diff --git a/scripts/package/kernel.spec b/scripts/package/kernel.spec new file mode 100644 index 000000000000..ac3f2ee6d7a0 --- /dev/null +++ b/scripts/package/kernel.spec @@ -0,0 +1,117 @@ +# _arch is undefined if /usr/lib/rpm/platform/*/macros was not included. +%{!?_arch: %define _arch dummy} +%{!?make: %define make make} +%define makeflags %{?_smp_mflags} ARCH=%{ARCH} +%define __spec_install_post /usr/lib/rpm/brp-compress || : +%define debug_package %{nil} + +Name: kernel +Summary: The Linux Kernel +Version: %(echo %{KERNELRELEASE} | sed -e 's/-/_/g') +Release: %{pkg_release} +License: GPL +Group: System Environment/Kernel +Vendor: The Linux Community +URL: https://www.kernel.org +Source0: linux.tar.gz +Source1: config +Source2: diff.patch +Provides: kernel-%{KERNELRELEASE} +BuildRequires: bc binutils bison dwarves +BuildRequires: (elfutils-libelf-devel or libelf-devel) flex +BuildRequires: gcc make openssl openssl-devel perl python3 rsync + +%description +The Linux Kernel, the operating system core itself + +%package headers +Summary: Header files for the Linux kernel for use by glibc +Group: Development/System +Obsoletes: kernel-headers +Provides: kernel-headers = %{version} +%description headers +Kernel-headers includes the C header files that specify the interface +between the Linux kernel and userspace libraries and programs. The +header files define structures and constants that are needed for +building most standard programs and are also needed for rebuilding the +glibc package. + +%if %{with_devel} +%package devel +Summary: Development package for building kernel modules to match the %{version} kernel +Group: System Environment/Kernel +AutoReqProv: no +%description -n kernel-devel +This package provides kernel headers and makefiles sufficient to build modules +against the %{version} kernel package. +%endif + +%prep +%setup -q -n linux +cp %{SOURCE1} .config +patch -p1 < %{SOURCE2} + +%build +%{make} %{makeflags} KERNELRELEASE=%{KERNELRELEASE} KBUILD_BUILD_VERSION=%{release} + +%install +mkdir -p %{buildroot}/boot +%ifarch ia64 +mkdir -p %{buildroot}/boot/efi +cp $(%{make} %{makeflags} -s image_name) %{buildroot}/boot/efi/vmlinuz-%{KERNELRELEASE} +ln -s efi/vmlinuz-%{KERNELRELEASE} %{buildroot}/boot/ +%else +cp $(%{make} %{makeflags} -s image_name) %{buildroot}/boot/vmlinuz-%{KERNELRELEASE} +%endif +%{make} %{makeflags} INSTALL_MOD_PATH=%{buildroot} modules_install +%{make} %{makeflags} INSTALL_HDR_PATH=%{buildroot}/usr headers_install +cp System.map %{buildroot}/boot/System.map-%{KERNELRELEASE} +cp .config %{buildroot}/boot/config-%{KERNELRELEASE} +ln -fns /usr/src/kernels/%{KERNELRELEASE} %{buildroot}/lib/modules/%{KERNELRELEASE}/build +ln -fns /usr/src/kernels/%{KERNELRELEASE} %{buildroot}/lib/modules/%{KERNELRELEASE}/source +%if %{with_devel} +%{make} %{makeflags} run-command KBUILD_RUN_COMMAND='${srctree}/scripts/package/install-extmod-build %{buildroot}/usr/src/kernels/%{KERNELRELEASE}' +%endif + +%clean +rm -rf %{buildroot} + +%post +if [ -x /sbin/installkernel -a -r /boot/vmlinuz-%{KERNELRELEASE} -a -r /boot/System.map-%{KERNELRELEASE} ]; then +cp /boot/vmlinuz-%{KERNELRELEASE} /boot/.vmlinuz-%{KERNELRELEASE}-rpm +cp /boot/System.map-%{KERNELRELEASE} /boot/.System.map-%{KERNELRELEASE}-rpm +rm -f /boot/vmlinuz-%{KERNELRELEASE} /boot/System.map-%{KERNELRELEASE} +/sbin/installkernel %{KERNELRELEASE} /boot/.vmlinuz-%{KERNELRELEASE}-rpm /boot/.System.map-%{KERNELRELEASE}-rpm +rm -f /boot/.vmlinuz-%{KERNELRELEASE}-rpm /boot/.System.map-%{KERNELRELEASE}-rpm +fi + +%preun +if [ -x /sbin/new-kernel-pkg ]; then +new-kernel-pkg --remove %{KERNELRELEASE} --rminitrd --initrdfile=/boot/initramfs-%{KERNELRELEASE}.img +elif [ -x /usr/bin/kernel-install ]; then +kernel-install remove %{KERNELRELEASE} +fi + +%postun +if [ -x /sbin/update-bootloader ]; then +/sbin/update-bootloader --remove %{KERNELRELEASE} +fi + +%files +%defattr (-, root, root) +/lib/modules/%{KERNELRELEASE} +%exclude /lib/modules/%{KERNELRELEASE}/build +%exclude /lib/modules/%{KERNELRELEASE}/source +/boot/* + +%files headers +%defattr (-, root, root) +/usr/include + +%if %{with_devel} +%files devel +%defattr (-, root, root) +/usr/src/kernels/%{KERNELRELEASE} +/lib/modules/%{KERNELRELEASE}/build +/lib/modules/%{KERNELRELEASE}/source +%endif diff --git a/scripts/package/mkdebian b/scripts/package/mkdebian index ba2453e08d40..5044224cf671 100755 --- a/scripts/package/mkdebian +++ b/scripts/package/mkdebian @@ -263,34 +263,11 @@ Description: Linux kernel debugging symbols for $version EOF fi -cat <<EOF > debian/rules -#!$(command -v $MAKE) -f - -srctree ?= . -KERNELRELEASE = ${KERNELRELEASE} - -.PHONY: clean build build-arch build-indep binary binary-arch binary-indep - -build-indep: -build-arch: - \$(MAKE) -f \$(srctree)/Makefile ARCH=${ARCH} \ - KERNELRELEASE=\$(KERNELRELEASE) \ - \$(shell \$(srctree)/scripts/package/deb-build-option) \ - olddefconfig all - -build: build-arch - -binary-indep: -binary-arch: build-arch - \$(MAKE) -f \$(srctree)/Makefile ARCH=${ARCH} \ - KERNELRELEASE=\$(KERNELRELEASE) intdeb-pkg - -clean: - rm -rf debian/files debian/linux-* - \$(MAKE) -f \$(srctree)/Makefile ARCH=${ARCH} clean - -binary: binary-arch +cat <<EOF > debian/rules.vars +ARCH := ${ARCH} +KERNELRELEASE := ${KERNELRELEASE} EOF -chmod +x debian/rules + +cp "${srctree}/scripts/package/debian/rules" debian/ exit 0 diff --git a/scripts/package/mkspec b/scripts/package/mkspec index 8049f0e2c110..d41608efb747 100755 --- a/scripts/package/mkspec +++ b/scripts/package/mkspec @@ -9,148 +9,16 @@ # Patched for non-x86 by Opencon (L) 2002 <opencon@rio.skydome.net> # -# how we were called determines which rpms we build and how we build them -if [ "$1" = prebuilt ]; then - S=DEL - MAKE="$MAKE -f $srctree/Makefile" -else - S= - - mkdir -p rpmbuild/SOURCES - cp linux.tar.gz rpmbuild/SOURCES - cp "${KCONFIG_CONFIG}" rpmbuild/SOURCES/config - "${srctree}/scripts/package/gen-diff-patch" rpmbuild/SOURCES/diff.patch -fi - if grep -q CONFIG_MODULES=y include/config/auto.conf; then - M= +echo '%define with_devel %{?_without_devel: 0} %{?!_without_devel: 1}' else - M=DEL +echo '%define with_devel 0' fi -__KERNELRELEASE=$(echo $KERNELRELEASE | sed -e "s/-/_/g") -EXCLUDES="$RCS_TAR_IGNORE --exclude=*vmlinux* --exclude=*.mod \ ---exclude=*.o --exclude=*.ko --exclude=*.cmd --exclude=Documentation \ ---exclude=.config.old --exclude=.missing-syscalls.d --exclude=*.s" - -# We can label the here-doc lines for conditional output to the spec file -# -# Labels: -# $S: this line is enabled only when building source package -# $M: this line is enabled only when CONFIG_MODULES is enabled -sed -e '/^DEL/d' -e 's/^\t*//' <<EOF - Name: kernel - Summary: The Linux Kernel - Version: $__KERNELRELEASE - Release: $(cat .version 2>/dev/null || echo 1) - License: GPL - Group: System Environment/Kernel - Vendor: The Linux Community - URL: https://www.kernel.org -$S Source0: linux.tar.gz -$S Source1: config -$S Source2: diff.patch - Provides: kernel-$KERNELRELEASE -$S BuildRequires: bc binutils bison dwarves -$S BuildRequires: (elfutils-libelf-devel or libelf-devel) flex -$S BuildRequires: gcc make openssl openssl-devel perl python3 rsync - - # $UTS_MACHINE as a fallback of _arch in case - # /usr/lib/rpm/platform/*/macros was not included. - %define _arch %{?_arch:$UTS_MACHINE} - %define __spec_install_post /usr/lib/rpm/brp-compress || : - %define debug_package %{nil} - - %description - The Linux Kernel, the operating system core itself - - %package headers - Summary: Header files for the Linux kernel for use by glibc - Group: Development/System - Obsoletes: kernel-headers - Provides: kernel-headers = %{version} - %description headers - Kernel-headers includes the C header files that specify the interface - between the Linux kernel and userspace libraries and programs. The - header files define structures and constants that are needed for - building most standard programs and are also needed for rebuilding the - glibc package. - -$S$M %package devel -$S$M Summary: Development package for building kernel modules to match the $__KERNELRELEASE kernel -$S$M Group: System Environment/Kernel -$S$M AutoReqProv: no -$S$M %description -n kernel-devel -$S$M This package provides kernel headers and makefiles sufficient to build modules -$S$M against the $__KERNELRELEASE kernel package. -$S$M -$S %prep -$S %setup -q -n linux -$S cp %{SOURCE1} .config -$S patch -p1 < %{SOURCE2} -$S -$S %build -$S $MAKE %{?_smp_mflags} KERNELRELEASE=$KERNELRELEASE KBUILD_BUILD_VERSION=%{release} -$S - %install - mkdir -p %{buildroot}/boot - %ifarch ia64 - mkdir -p %{buildroot}/boot/efi - cp \$($MAKE -s image_name) %{buildroot}/boot/efi/vmlinuz-$KERNELRELEASE - ln -s efi/vmlinuz-$KERNELRELEASE %{buildroot}/boot/ - %else - cp \$($MAKE -s image_name) %{buildroot}/boot/vmlinuz-$KERNELRELEASE - %endif -$M $MAKE %{?_smp_mflags} INSTALL_MOD_PATH=%{buildroot} modules_install - $MAKE %{?_smp_mflags} INSTALL_HDR_PATH=%{buildroot}/usr headers_install - cp System.map %{buildroot}/boot/System.map-$KERNELRELEASE - cp .config %{buildroot}/boot/config-$KERNELRELEASE -$S$M rm -f %{buildroot}/lib/modules/$KERNELRELEASE/build -$S$M rm -f %{buildroot}/lib/modules/$KERNELRELEASE/source -$S$M mkdir -p %{buildroot}/usr/src/kernels/$KERNELRELEASE -$S$M tar cf - $EXCLUDES . | tar xf - -C %{buildroot}/usr/src/kernels/$KERNELRELEASE -$S$M cd %{buildroot}/lib/modules/$KERNELRELEASE -$S$M ln -sf /usr/src/kernels/$KERNELRELEASE build -$S$M ln -sf /usr/src/kernels/$KERNELRELEASE source - - %clean - rm -rf %{buildroot} - - %post - if [ -x /sbin/installkernel -a -r /boot/vmlinuz-$KERNELRELEASE -a -r /boot/System.map-$KERNELRELEASE ]; then - cp /boot/vmlinuz-$KERNELRELEASE /boot/.vmlinuz-$KERNELRELEASE-rpm - cp /boot/System.map-$KERNELRELEASE /boot/.System.map-$KERNELRELEASE-rpm - rm -f /boot/vmlinuz-$KERNELRELEASE /boot/System.map-$KERNELRELEASE - /sbin/installkernel $KERNELRELEASE /boot/.vmlinuz-$KERNELRELEASE-rpm /boot/.System.map-$KERNELRELEASE-rpm - rm -f /boot/.vmlinuz-$KERNELRELEASE-rpm /boot/.System.map-$KERNELRELEASE-rpm - fi - - %preun - if [ -x /sbin/new-kernel-pkg ]; then - new-kernel-pkg --remove $KERNELRELEASE --rminitrd --initrdfile=/boot/initramfs-$KERNELRELEASE.img - elif [ -x /usr/bin/kernel-install ]; then - kernel-install remove $KERNELRELEASE - fi - - %postun - if [ -x /sbin/update-bootloader ]; then - /sbin/update-bootloader --remove $KERNELRELEASE - fi - - %files - %defattr (-, root, root) -$M /lib/modules/$KERNELRELEASE -$M %exclude /lib/modules/$KERNELRELEASE/build -$M %exclude /lib/modules/$KERNELRELEASE/source - /boot/* - - %files headers - %defattr (-, root, root) - /usr/include -$S$M -$S$M %files devel -$S$M %defattr (-, root, root) -$S$M /usr/src/kernels/$KERNELRELEASE -$S$M /lib/modules/$KERNELRELEASE/build -$S$M /lib/modules/$KERNELRELEASE/source +cat<<EOF +%define ARCH ${ARCH} +%define KERNELRELEASE ${KERNELRELEASE} +%define pkg_release $("${srctree}/init/build-version") EOF + +cat "${srctree}/scripts/package/kernel.spec" diff --git a/scripts/remove-stale-files b/scripts/remove-stale-files index f3659ea0335b..8b1a636f8543 100755 --- a/scripts/remove-stale-files +++ b/scripts/remove-stale-files @@ -37,3 +37,5 @@ rm -f .scmversion rm -rf include/ksym find . -name '*.usyms' | xargs rm -f + +rm -f binkernel.spec diff --git a/scripts/setlocalversion b/scripts/setlocalversion index 3d3babac8298..38b96c6797f4 100755 --- a/scripts/setlocalversion +++ b/scripts/setlocalversion @@ -2,7 +2,7 @@ # SPDX-License-Identifier: GPL-2.0 # # This scripts adds local version information from the version -# control systems git, mercurial (hg) and subversion (svn). +# control system git. # # If something goes wrong, send a mail the kernel build mailinglist # (see MAINTAINERS) and CC Nico Schottelius @@ -57,21 +57,37 @@ scm_version() return fi - # If a localversion*' file and the corresponding annotated tag exist, - # use it. This is the case in linux-next. + # mainline kernel: 6.2.0-rc5 -> v6.2-rc5 + # stable kernel: 6.1.7 -> v6.1.7 + version_tag=v$(echo "${KERNELVERSION}" | sed -E 's/^([0-9]+\.[0-9]+)\.0(.*)$/\1\2/') + + # If a localversion* file exists, and the corresponding + # annotated tag exists and is an ancestor of HEAD, use + # it. This is the case in linux-next. tag=${file_localversion#-} - tag=$(git describe --exact-match --match=$tag $tag 2>/dev/null) + desc= + if [ -n "${tag}" ]; then + desc=$(git describe --match=$tag 2>/dev/null) + fi + + # Otherwise, if a localversion* file exists, and the tag + # obtained by appending it to the tag derived from + # KERNELVERSION exists and is an ancestor of HEAD, use + # it. This is e.g. the case in linux-rt. + if [ -z "${desc}" ] && [ -n "${file_localversion}" ]; then + tag="${version_tag}${file_localversion}" + desc=$(git describe --match=$tag 2>/dev/null) + fi # Otherwise, default to the annotated tag derived from KERNELVERSION. - # mainline kernel: 6.2.0-rc5 -> v6.2-rc5 - # stable kernel: 6.1.7 -> v6.1.7 - if [ -z "${tag}" ]; then - tag=v$(echo "${KERNELVERSION}" | sed -E 's/^([0-9]+\.[0-9]+)\.0(.*)$/\1\2/') + if [ -z "${desc}" ]; then + tag="${version_tag}" + desc=$(git describe --match=$tag 2>/dev/null) fi # If we are at the tagged commit, we ignore it because the version is # well-defined. - if [ -z "$(git describe --exact-match --match=$tag 2>/dev/null)" ]; then + if [ "${tag}" != "${desc}" ]; then # If only the short version is requested, don't bother # running further git commands @@ -81,8 +97,8 @@ scm_version() fi # If we are past the tagged commit, we pretty print it. # (like 6.1.0-14595-g292a089d78d3) - if atag="$(git describe --match=$tag 2>/dev/null)"; then - echo "$atag" | awk -F- '{printf("-%05d", $(NF-1))}' + if [ -n "${desc}" ]; then + echo "${desc}" | awk -F- '{printf("-%05d", $(NF-1))}' fi # Add -g and exactly 12 hex chars. diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 969d4aa6fd55..57ee70ae50f2 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -184,6 +184,7 @@ static bool tomoyo_manage_by_non_root; * * Returns nothing. */ +__printf(3, 4) static void tomoyo_addprintf(char *buffer, int len, const char *fmt, ...) { va_list args; diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index a539b2cbb5c4..0e8e2e959aef 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -954,7 +954,7 @@ bool tomoyo_str_starts(char **src, const char *find); char *tomoyo_encode(const char *str); char *tomoyo_encode2(const char *str, int str_len); char *tomoyo_init_log(struct tomoyo_request_info *r, int len, const char *fmt, - va_list args); + va_list args) __printf(3, 0); char *tomoyo_read_token(struct tomoyo_acl_param *param); char *tomoyo_realpath_from_path(const struct path *path); char *tomoyo_realpath_nofollow(const char *pathname); @@ -1037,8 +1037,6 @@ struct tomoyo_policy_namespace *tomoyo_assign_namespace (const char *domainname); struct tomoyo_profile *tomoyo_profile(const struct tomoyo_policy_namespace *ns, const u8 profile); -unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, - const u8 index); u8 tomoyo_parse_ulong(unsigned long *result, char **str); void *tomoyo_commit_ok(void *data, const unsigned int size); void __init tomoyo_load_builtin_policy(void); @@ -1067,7 +1065,7 @@ void tomoyo_warn_oom(const char *function); void tomoyo_write_log(struct tomoyo_request_info *r, const char *fmt, ...) __printf(2, 3); void tomoyo_write_log2(struct tomoyo_request_info *r, int len, const char *fmt, - va_list args); + va_list args) __printf(3, 0); /********** External variable definitions. **********/ diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index ac20c0bdff9d..90b53500a236 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -784,13 +784,12 @@ retry: if (!strcmp(domainname, "parent")) { char *cp; - strncpy(ee->tmp, old_domain->domainname->name, - TOMOYO_EXEC_TMPSIZE - 1); + strscpy(ee->tmp, old_domain->domainname->name, TOMOYO_EXEC_TMPSIZE); cp = strrchr(ee->tmp, ' '); if (cp) *cp = '\0'; } else if (*domainname == '<') - strncpy(ee->tmp, domainname, TOMOYO_EXEC_TMPSIZE - 1); + strscpy(ee->tmp, domainname, TOMOYO_EXEC_TMPSIZE); else snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s", old_domain->domainname->name, domainname); diff --git a/sound/Kconfig b/sound/Kconfig index f0e15822e858..4c036a9a420a 100644 --- a/sound/Kconfig +++ b/sound/Kconfig @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only menuconfig SOUND tristate "Sound card support" - depends on HAS_IOMEM + depends on HAS_IOMEM || UML help If you have a sound card in your computer, i.e. if it can say more than an occasional beep, say Y. diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile index dc531805a570..b53753dee02f 100644 --- a/tools/power/cpupower/Makefile +++ b/tools/power/cpupower/Makefile @@ -57,7 +57,7 @@ LIB_MIN= 1 PACKAGE = cpupower PACKAGE_BUGREPORT = linux-pm@vger.kernel.org -LANGUAGES = de fr it cs pt +LANGUAGES = de fr it cs pt ka # Directory definitions. These are default and most probably |