mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 06:31:49 +00:00
ASoC: Further updates for v4.2
There's a bunch of additional updates and fixes that came in since my orignal pull request here, including DT support for rt5645 and fairly large serieses of cleanups and improvements to tas2552 and rcar. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJVh9RgAAoJECTWi3JdVIfQZjYH/3t48LgdB5dxKxIhn70kiaUx DqXCIkFOvkum1KUU3VTgcCZAT/dOEvbAY2S8PtxKbPRyRpmY1CqyXDEL7fXICl+y kyDBhZYKdzVlf+LBb4TIOibaRONQqJNATRWFN8bJu0L9wzqo2jUjZSYqpJxuvnYD U9T4P0dNbIN35ioVrK/0QPt6V2bCPs/qw3UwXmojl2T/4JDATdE+2yJO/SXzdEdR qq5aRtS+Ak6yx5DpWw/QBkt85NrbuwyoeYRNQuRXCOAWC8SPmHB/H+aNsvMNAcP1 UZuRVtxPXjkFp6OVDJ4rIOg8hVb0cfXqUfnj+syEpZxtmRcS7Wwi1Y2M3BJMV1A= =H6q+ -----END PGP SIGNATURE----- Merge tag 'asoc-v4.2-2' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-next ASoC: Further updates for v4.2 There's a bunch of additional updates and fixes that came in since my orignal pull request here, including DT support for rt5645 and fairly large serieses of cleanups and improvements to tas2552 and rcar.
This commit is contained in:
commit
57fa8a1e22
@ -32,8 +32,8 @@ Example:
|
||||
touchscreen-fuzz-x = <4>;
|
||||
touchscreen-fuzz-y = <7>;
|
||||
touchscreen-fuzz-pressure = <2>;
|
||||
touchscreen-max-x = <4096>;
|
||||
touchscreen-max-y = <4096>;
|
||||
touchscreen-size-x = <4096>;
|
||||
touchscreen-size-y = <4096>;
|
||||
touchscreen-max-pressure = <2048>;
|
||||
|
||||
ti,x-plate-ohms = <280>;
|
||||
|
13
Documentation/devicetree/bindings/sound/mt8173-max98090.txt
Normal file
13
Documentation/devicetree/bindings/sound/mt8173-max98090.txt
Normal file
@ -0,0 +1,13 @@
|
||||
MT8173 with MAX98090 CODEC
|
||||
|
||||
Required properties:
|
||||
- compatible : "mediatek,mt8173-max98090"
|
||||
- mediatek,audio-codec: the phandle of the MAX98090 audio codec
|
||||
|
||||
Example:
|
||||
|
||||
sound {
|
||||
compatible = "mediatek,mt8173-max98090";
|
||||
mediatek,audio-codec = <&max98090>;
|
||||
};
|
||||
|
@ -0,0 +1,13 @@
|
||||
MT8173 with RT5650 RT5676 CODECS
|
||||
|
||||
Required properties:
|
||||
- compatible : "mediatek,mt8173-rt5650-rt5676"
|
||||
- mediatek,audio-codec: the phandles of rt5650 and rt5676 codecs
|
||||
|
||||
Example:
|
||||
|
||||
sound {
|
||||
compatible = "mediatek,mt8173-rt5650-rt5676";
|
||||
mediatek,audio-codec = <&rt5650 &rt5676>;
|
||||
};
|
||||
|
45
Documentation/devicetree/bindings/sound/mtk-afe-pcm.txt
Normal file
45
Documentation/devicetree/bindings/sound/mtk-afe-pcm.txt
Normal file
@ -0,0 +1,45 @@
|
||||
Mediatek AFE PCM controller
|
||||
|
||||
Required properties:
|
||||
- compatible = "mediatek,mt8173-afe-pcm";
|
||||
- reg: register location and size
|
||||
- interrupts: Should contain AFE interrupt
|
||||
- clock-names: should have these clock names:
|
||||
"infra_sys_audio_clk",
|
||||
"top_pdn_audio",
|
||||
"top_pdn_aud_intbus",
|
||||
"bck0",
|
||||
"bck1",
|
||||
"i2s0_m",
|
||||
"i2s1_m",
|
||||
"i2s2_m",
|
||||
"i2s3_m",
|
||||
"i2s3_b";
|
||||
|
||||
Example:
|
||||
|
||||
afe: mt8173-afe-pcm@11220000 {
|
||||
compatible = "mediatek,mt8173-afe-pcm";
|
||||
reg = <0 0x11220000 0 0x1000>;
|
||||
interrupts = <GIC_SPI 134 IRQ_TYPE_EDGE_FALLING>;
|
||||
clocks = <&infracfg INFRA_AUDIO>,
|
||||
<&topckgen TOP_AUDIO_SEL>,
|
||||
<&topckgen TOP_AUD_INTBUS_SEL>,
|
||||
<&topckgen TOP_APLL1_DIV0>,
|
||||
<&topckgen TOP_APLL2_DIV0>,
|
||||
<&topckgen TOP_I2S0_M_CK_SEL>,
|
||||
<&topckgen TOP_I2S1_M_CK_SEL>,
|
||||
<&topckgen TOP_I2S2_M_CK_SEL>,
|
||||
<&topckgen TOP_I2S3_M_CK_SEL>,
|
||||
<&topckgen TOP_I2S3_B_CK_SEL>;
|
||||
clock-names = "infra_sys_audio_clk",
|
||||
"top_pdn_audio",
|
||||
"top_pdn_aud_intbus",
|
||||
"bck0",
|
||||
"bck1",
|
||||
"i2s0_m",
|
||||
"i2s1_m",
|
||||
"i2s2_m",
|
||||
"i2s3_m",
|
||||
"i2s3_b";
|
||||
};
|
60
Documentation/devicetree/bindings/sound/qcom,apq8016-sbc.txt
Normal file
60
Documentation/devicetree/bindings/sound/qcom,apq8016-sbc.txt
Normal file
@ -0,0 +1,60 @@
|
||||
* Qualcomm Technologies APQ8016 SBC ASoC machine driver
|
||||
|
||||
This node models the Qualcomm Technologies APQ8016 SBC ASoC machine driver
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : "qcom,apq8016-sbc-sndcard"
|
||||
|
||||
- pinctrl-N : One property must exist for each entry in
|
||||
pinctrl-names. See ../pinctrl/pinctrl-bindings.txt
|
||||
for details of the property values.
|
||||
- pinctrl-names : Must contain a "default" entry.
|
||||
- reg : Must contain an address for each entry in reg-names.
|
||||
- reg-names : A list which must include the following entries:
|
||||
* "mic-iomux"
|
||||
* "spkr-iomux"
|
||||
- qcom,model : Name of the sound card.
|
||||
|
||||
Dai-link subnode properties and subnodes:
|
||||
|
||||
Required dai-link subnodes:
|
||||
|
||||
- cpu : CPU sub-node
|
||||
- codec : CODEC sub-node
|
||||
|
||||
Required CPU/CODEC subnodes properties:
|
||||
|
||||
-link-name : Name of the dai link.
|
||||
-sound-dai : phandle and port of CPU/CODEC
|
||||
-capture-dai : phandle and port of CPU/CODEC
|
||||
|
||||
Example:
|
||||
|
||||
sound: sound {
|
||||
compatible = "qcom,apq8016-sbc-sndcard";
|
||||
reg = <0x07702000 0x4>, <0x07702004 0x4>;
|
||||
reg-names = "mic-iomux", "spkr-iomux";
|
||||
qcom,model = "DB410c";
|
||||
|
||||
/* I2S - Internal codec */
|
||||
internal-dai-link@0 {
|
||||
cpu { /* PRIMARY */
|
||||
sound-dai = <&lpass MI2S_PRIMARY>;
|
||||
};
|
||||
codec {
|
||||
sound-dai = <&wcd_codec 0>;
|
||||
};
|
||||
};
|
||||
|
||||
/* External Primary or External Secondary -ADV7533 HDMI */
|
||||
external-dai-link@0 {
|
||||
link-name = "ADV7533";
|
||||
cpu { /* QUAT */
|
||||
sound-dai = <&lpass MI2S_QUATERNARY>;
|
||||
};
|
||||
codec {
|
||||
sound-dai = <&adv_bridge 0>;
|
||||
};
|
||||
};
|
||||
};
|
72
Documentation/devicetree/bindings/sound/rt5645.txt
Normal file
72
Documentation/devicetree/bindings/sound/rt5645.txt
Normal file
@ -0,0 +1,72 @@
|
||||
RT5650/RT5645 audio CODEC
|
||||
|
||||
This device supports I2C only.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : One of "realtek,rt5645" or "realtek,rt5650".
|
||||
|
||||
- reg : The I2C address of the device.
|
||||
|
||||
- interrupts : The CODEC's interrupt output.
|
||||
|
||||
Optional properties:
|
||||
|
||||
- hp-detect-gpios:
|
||||
a GPIO spec for the external headphone detect pin. If jd-mode = 0,
|
||||
we will get the JD status by getting the value of hp-detect-gpios.
|
||||
|
||||
- realtek,in2-differential
|
||||
Boolean. Indicate MIC2 input are differential, rather than single-ended.
|
||||
|
||||
- realtek,dmic1-data-pin
|
||||
0: dmic1 is not used
|
||||
1: using IN2P pin as dmic1 data pin
|
||||
2: using GPIO6 pin as dmic1 data pin
|
||||
3: using GPIO10 pin as dmic1 data pin
|
||||
4: using GPIO12 pin as dmic1 data pin
|
||||
|
||||
- realtek,dmic2-data-pin
|
||||
0: dmic2 is not used
|
||||
1: using IN2N pin as dmic2 data pin
|
||||
2: using GPIO5 pin as dmic2 data pin
|
||||
3: using GPIO11 pin as dmic2 data pin
|
||||
|
||||
-- realtek,jd-mode : The JD mode of rt5645/rt5650
|
||||
0 : rt5645/rt5650 JD function is not used
|
||||
1 : Mode-0 (VDD=3.3V), two port jack detection
|
||||
2 : Mode-1 (VDD=3.3V), one port jack detection
|
||||
3 : Mode-2 (VDD=1.8V), one port jack detection
|
||||
|
||||
Pins on the device (for linking into audio routes) for RT5645/RT5650:
|
||||
|
||||
* DMIC L1
|
||||
* DMIC R1
|
||||
* DMIC L2
|
||||
* DMIC R2
|
||||
* IN1P
|
||||
* IN1N
|
||||
* IN2P
|
||||
* IN2N
|
||||
* Haptic Generator
|
||||
* HPOL
|
||||
* HPOR
|
||||
* LOUTL
|
||||
* LOUTR
|
||||
* PDM1L
|
||||
* PDM1R
|
||||
* SPOL
|
||||
* SPOR
|
||||
|
||||
Example:
|
||||
|
||||
codec: rt5650@1a {
|
||||
compatible = "realtek,rt5650";
|
||||
reg = <0x1a>;
|
||||
hp-detect-gpios = <&gpio 19 0>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
|
||||
realtek,dmic-en = "true";
|
||||
realtek,en-jd-func = "true";
|
||||
realtek,jd-mode = <3>;
|
||||
};
|
@ -16,7 +16,8 @@ Optional properties:
|
||||
connection's sink, the second being the connection's
|
||||
source.
|
||||
- simple-audio-card,mclk-fs : Multiplication factor between stream rate and codec
|
||||
mclk.
|
||||
mclk. When defined, mclk-fs property defined in
|
||||
dai-link sub nodes are ignored.
|
||||
- simple-audio-card,hp-det-gpio : Reference to GPIO that signals when
|
||||
headphones are attached.
|
||||
- simple-audio-card,mic-det-gpio : Reference to GPIO that signals when
|
||||
@ -55,6 +56,9 @@ Optional dai-link subnode properties:
|
||||
dai-link uses bit clock inversion.
|
||||
- frame-inversion : bool property. Add this if the
|
||||
dai-link uses frame clock inversion.
|
||||
- mclk-fs : Multiplication factor between stream
|
||||
rate and codec mclk, applied only for
|
||||
the dai-link.
|
||||
|
||||
For backward compatibility the frame-master and bitclock-master
|
||||
properties can be used as booleans in codec subnode to indicate if the
|
||||
|
@ -14,6 +14,12 @@ Required properties:
|
||||
Optional properties:
|
||||
- enable-gpio - gpio pin to enable/disable the device
|
||||
|
||||
tas2552 can receive it's reference clock via MCLK, BCLK, IVCLKIN pin or use the
|
||||
internal 1.8MHz. This CLKIN is used by the PLL. In addition to PLL, the PDM
|
||||
reference clock is also selectable: PLL, IVCLKIN, BCLK or MCLK.
|
||||
For system integration the dt-bindings/sound/tas2552.h header file provides
|
||||
defined values to selct and configure the PLL and PDM reference clocks.
|
||||
|
||||
Example:
|
||||
|
||||
tas2552: tas2552@41 {
|
||||
|
@ -15,10 +15,8 @@ Optional properties:
|
||||
- phys: phandle + phy specifier pair
|
||||
- phy-names: must be "usb"
|
||||
- dmas: Must contain a list of references to DMA specifiers.
|
||||
- dma-names : Must contain a list of DMA names:
|
||||
- tx0 ... tx<n>
|
||||
- rx0 ... rx<n>
|
||||
- This <n> means DnFIFO in USBHS module.
|
||||
- dma-names : named "ch%d", where %d is the channel number ranging from zero
|
||||
to the number of channels (DnFIFOs) minus one.
|
||||
|
||||
Example:
|
||||
usbhs: usb@e6590000 {
|
||||
|
@ -1481,6 +1481,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
||||
By default, super page will be supported if Intel IOMMU
|
||||
has the capability. With this option, super page will
|
||||
not be supported.
|
||||
ecs_off [Default Off]
|
||||
By default, extended context tables will be supported if
|
||||
the hardware advertises that it has support both for the
|
||||
extended tables themselves, and also PASID support. With
|
||||
this option set, extended tables will not be used even
|
||||
on hardware which claims to support them.
|
||||
|
||||
intel_idle.max_cstate= [KNL,HW,ACPI,X86]
|
||||
0 disables intel_idle and fall back on acpi_idle.
|
||||
|
@ -20,7 +20,7 @@
|
||||
files/UDP-Lite-HOWTO.txt
|
||||
|
||||
o The Wireshark UDP-Lite WiKi (with capture files):
|
||||
http://wiki.wireshark.org/Lightweight_User_Datagram_Protocol
|
||||
https://wiki.wireshark.org/Lightweight_User_Datagram_Protocol
|
||||
|
||||
o The Protocol Spec, RFC 3828, http://www.ietf.org/rfc/rfc3828.txt
|
||||
|
||||
|
13
MAINTAINERS
13
MAINTAINERS
@ -51,9 +51,9 @@ trivial patch so apply some common sense.
|
||||
or does something very odd once a month document it.
|
||||
|
||||
PLEASE remember that submissions must be made under the terms
|
||||
of the OSDL certificate of contribution and should include a
|
||||
Signed-off-by: line. The current version of this "Developer's
|
||||
Certificate of Origin" (DCO) is listed in the file
|
||||
of the Linux Foundation certificate of contribution and should
|
||||
include a Signed-off-by: line. The current version of this
|
||||
"Developer's Certificate of Origin" (DCO) is listed in the file
|
||||
Documentation/SubmittingPatches.
|
||||
|
||||
6. Make sure you have the right to send any changes you make. If you
|
||||
@ -7575,6 +7575,7 @@ F: drivers/pci/host/pci-exynos.c
|
||||
|
||||
PCI DRIVER FOR SYNOPSIS DESIGNWARE
|
||||
M: Jingoo Han <jingoohan1@gmail.com>
|
||||
M: Pratyush Anand <pratyush.anand@gmail.com>
|
||||
L: linux-pci@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/pci/host/*designware*
|
||||
@ -7588,8 +7589,9 @@ F: Documentation/devicetree/bindings/pci/host-generic-pci.txt
|
||||
F: drivers/pci/host/pci-host-generic.c
|
||||
|
||||
PCIE DRIVER FOR ST SPEAR13XX
|
||||
M: Pratyush Anand <pratyush.anand@gmail.com>
|
||||
L: linux-pci@vger.kernel.org
|
||||
S: Orphan
|
||||
S: Maintained
|
||||
F: drivers/pci/host/*spear*
|
||||
|
||||
PCMCIA SUBSYSTEM
|
||||
@ -10593,8 +10595,7 @@ F: drivers/virtio/virtio_input.c
|
||||
F: include/uapi/linux/virtio_input.h
|
||||
|
||||
VIA RHINE NETWORK DRIVER
|
||||
M: Roger Luethi <rl@hellgate.ch>
|
||||
S: Maintained
|
||||
S: Orphan
|
||||
F: drivers/net/ethernet/via/via-rhine.c
|
||||
|
||||
VIA SD/MMC CARD CONTROLLER DRIVER
|
||||
|
2
Makefile
2
Makefile
@ -1,7 +1,7 @@
|
||||
VERSION = 4
|
||||
PATCHLEVEL = 1
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc6
|
||||
EXTRAVERSION = -rc8
|
||||
NAME = Hurr durr I'ma sheep
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
@ -223,6 +223,25 @@
|
||||
/include/ "tps65217.dtsi"
|
||||
|
||||
&tps {
|
||||
/*
|
||||
* Configure pmic to enter OFF-state instead of SLEEP-state ("RTC-only
|
||||
* mode") at poweroff. Most BeagleBone versions do not support RTC-only
|
||||
* mode and risk hardware damage if this mode is entered.
|
||||
*
|
||||
* For details, see linux-omap mailing list May 2015 thread
|
||||
* [PATCH] ARM: dts: am335x-bone* enable pmic-shutdown-controller
|
||||
* In particular, messages:
|
||||
* http://www.spinics.net/lists/linux-omap/msg118585.html
|
||||
* http://www.spinics.net/lists/linux-omap/msg118615.html
|
||||
*
|
||||
* You can override this later with
|
||||
* &tps { /delete-property/ ti,pmic-shutdown-controller; }
|
||||
* if you want to use RTC-only mode and made sure you are not affected
|
||||
* by the hardware problems. (Tip: double-check by performing a current
|
||||
* measurement after shutdown: it should be less than 1 mA.)
|
||||
*/
|
||||
ti,pmic-shutdown-controller;
|
||||
|
||||
regulators {
|
||||
dcdc1_reg: regulator@0 {
|
||||
regulator-name = "vdds_dpr";
|
||||
|
@ -12,7 +12,7 @@
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,am35xx-gate-clock";
|
||||
clocks = <&ipss_ick>;
|
||||
reg = <0x059c>;
|
||||
reg = <0x032c>;
|
||||
ti,bit-shift = <1>;
|
||||
};
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,gate-clock";
|
||||
clocks = <&rmii_ck>;
|
||||
reg = <0x059c>;
|
||||
reg = <0x032c>;
|
||||
ti,bit-shift = <9>;
|
||||
};
|
||||
|
||||
@ -28,7 +28,7 @@
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,am35xx-gate-clock";
|
||||
clocks = <&ipss_ick>;
|
||||
reg = <0x059c>;
|
||||
reg = <0x032c>;
|
||||
ti,bit-shift = <2>;
|
||||
};
|
||||
|
||||
@ -36,7 +36,7 @@
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,gate-clock";
|
||||
clocks = <&pclk_ck>;
|
||||
reg = <0x059c>;
|
||||
reg = <0x032c>;
|
||||
ti,bit-shift = <10>;
|
||||
};
|
||||
|
||||
@ -44,7 +44,7 @@
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,am35xx-gate-clock";
|
||||
clocks = <&ipss_ick>;
|
||||
reg = <0x059c>;
|
||||
reg = <0x032c>;
|
||||
ti,bit-shift = <0>;
|
||||
};
|
||||
|
||||
@ -52,7 +52,7 @@
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,gate-clock";
|
||||
clocks = <&sys_ck>;
|
||||
reg = <0x059c>;
|
||||
reg = <0x032c>;
|
||||
ti,bit-shift = <8>;
|
||||
};
|
||||
|
||||
@ -60,7 +60,7 @@
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,am35xx-gate-clock";
|
||||
clocks = <&sys_ck>;
|
||||
reg = <0x059c>;
|
||||
reg = <0x032c>;
|
||||
ti,bit-shift = <3>;
|
||||
};
|
||||
};
|
||||
|
@ -95,6 +95,11 @@
|
||||
|
||||
internal-regs {
|
||||
|
||||
rtc@10300 {
|
||||
/* No crystal connected to the internal RTC */
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
/* J10: VCC, NC, RX, NC, TX, GND */
|
||||
serial@12000 {
|
||||
status = "okay";
|
||||
|
@ -382,7 +382,7 @@
|
||||
ti,hwmods = "usb_otg_hs";
|
||||
|
||||
usb0: usb@47401000 {
|
||||
compatible = "ti,musb-am33xx";
|
||||
compatible = "ti,musb-dm816";
|
||||
reg = <0x47401400 0x400
|
||||
0x47401000 0x200>;
|
||||
reg-names = "mc", "control";
|
||||
@ -422,7 +422,7 @@
|
||||
};
|
||||
|
||||
usb1: usb@47401800 {
|
||||
compatible = "ti,musb-am33xx";
|
||||
compatible = "ti,musb-dm816";
|
||||
reg = <0x47401c00 0x400
|
||||
0x47401800 0x200>;
|
||||
reg-names = "mc", "control";
|
||||
|
@ -832,8 +832,8 @@
|
||||
touchscreen-fuzz-x = <4>;
|
||||
touchscreen-fuzz-y = <7>;
|
||||
touchscreen-fuzz-pressure = <2>;
|
||||
touchscreen-max-x = <4096>;
|
||||
touchscreen-max-y = <4096>;
|
||||
touchscreen-size-x = <4096>;
|
||||
touchscreen-size-y = <4096>;
|
||||
touchscreen-max-pressure = <2048>;
|
||||
|
||||
ti,x-plate-ohms = <280>;
|
||||
|
@ -87,8 +87,8 @@ static unsigned int exynos_pmu_spare3;
|
||||
static u32 exynos_irqwake_intmask = 0xffffffff;
|
||||
|
||||
static const struct exynos_wkup_irq exynos3250_wkup_irq[] = {
|
||||
{ 105, BIT(1) }, /* RTC alarm */
|
||||
{ 106, BIT(2) }, /* RTC tick */
|
||||
{ 73, BIT(1) }, /* RTC alarm */
|
||||
{ 74, BIT(2) }, /* RTC tick */
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
|
@ -203,23 +203,8 @@ save_context_wfi:
|
||||
*/
|
||||
ldr r1, kernel_flush
|
||||
blx r1
|
||||
/*
|
||||
* The kernel doesn't interwork: v7_flush_dcache_all in particluar will
|
||||
* always return in Thumb state when CONFIG_THUMB2_KERNEL is enabled.
|
||||
* This sequence switches back to ARM. Note that .align may insert a
|
||||
* nop: bx pc needs to be word-aligned in order to work.
|
||||
*/
|
||||
THUMB( .thumb )
|
||||
THUMB( .align )
|
||||
THUMB( bx pc )
|
||||
THUMB( nop )
|
||||
.arm
|
||||
|
||||
b omap3_do_wfi
|
||||
|
||||
/*
|
||||
* Local variables
|
||||
*/
|
||||
ENDPROC(omap34xx_cpu_suspend)
|
||||
omap3_do_wfi_sram_addr:
|
||||
.word omap3_do_wfi_sram
|
||||
kernel_flush:
|
||||
@ -364,10 +349,7 @@ exit_nonoff_modes:
|
||||
* ===================================
|
||||
*/
|
||||
ldmfd sp!, {r4 - r11, pc} @ restore regs and return
|
||||
|
||||
/*
|
||||
* Local variables
|
||||
*/
|
||||
ENDPROC(omap3_do_wfi)
|
||||
sdrc_power:
|
||||
.word SDRC_POWER_V
|
||||
cm_idlest1_core:
|
||||
|
@ -16,7 +16,8 @@
|
||||
#include "mt8173.dtsi"
|
||||
|
||||
/ {
|
||||
model = "mediatek,mt8173-evb";
|
||||
model = "MediaTek MT8173 evaluation board";
|
||||
compatible = "mediatek,mt8173-evb", "mediatek,mt8173";
|
||||
|
||||
aliases {
|
||||
serial0 = &uart0;
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/types.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/def_LPBlackfin.h>
|
||||
|
||||
#define __raw_readb bfin_read8
|
||||
#define __raw_readw bfin_read16
|
||||
|
@ -127,7 +127,7 @@ int smp_num_siblings = 1;
|
||||
volatile int ia64_cpu_to_sapicid[NR_CPUS];
|
||||
EXPORT_SYMBOL(ia64_cpu_to_sapicid);
|
||||
|
||||
static volatile cpumask_t cpu_callin_map;
|
||||
static cpumask_t cpu_callin_map;
|
||||
|
||||
struct smp_boot_data smp_boot_data __initdata;
|
||||
|
||||
@ -477,6 +477,7 @@ do_boot_cpu (int sapicid, int cpu, struct task_struct *idle)
|
||||
for (timeout = 0; timeout < 100000; timeout++) {
|
||||
if (cpumask_test_cpu(cpu, &cpu_callin_map))
|
||||
break; /* It has booted */
|
||||
barrier(); /* Make sure we re-read cpu_callin_map */
|
||||
udelay(100);
|
||||
}
|
||||
Dprintk("\n");
|
||||
|
@ -225,7 +225,7 @@ void __init plat_time_init(void)
|
||||
ddr_clk_rate = ath79_get_sys_clk_rate("ddr");
|
||||
ref_clk_rate = ath79_get_sys_clk_rate("ref");
|
||||
|
||||
pr_info("Clocks: CPU:%lu.%03luMHz, DDR:%lu.%03luMHz, AHB:%lu.%03luMHz, Ref:%lu.%03luMHz",
|
||||
pr_info("Clocks: CPU:%lu.%03luMHz, DDR:%lu.%03luMHz, AHB:%lu.%03luMHz, Ref:%lu.%03luMHz\n",
|
||||
cpu_clk_rate / 1000000, (cpu_clk_rate / 1000) % 1000,
|
||||
ddr_clk_rate / 1000000, (ddr_clk_rate / 1000) % 1000,
|
||||
ahb_clk_rate / 1000000, (ahb_clk_rate / 1000) % 1000,
|
||||
|
@ -2,7 +2,6 @@
|
||||
# Makefile for the Cobalt micro systems family specific parts of the kernel
|
||||
#
|
||||
|
||||
obj-y := buttons.o irq.o lcd.o led.o reset.o rtc.o serial.o setup.o time.o
|
||||
obj-y := buttons.o irq.o lcd.o led.o mtd.o reset.o rtc.o serial.o setup.o time.o
|
||||
|
||||
obj-$(CONFIG_PCI) += pci.o
|
||||
obj-$(CONFIG_MTD_PHYSMAP) += mtd.o
|
||||
|
@ -113,7 +113,7 @@
|
||||
#define _PAGE_PRESENT_SHIFT 0
|
||||
#define _PAGE_PRESENT (1 << _PAGE_PRESENT_SHIFT)
|
||||
/* R2 or later cores check for RI/XI support to determine _PAGE_READ */
|
||||
#ifdef CONFIG_CPU_MIPSR2
|
||||
#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
|
||||
#define _PAGE_WRITE_SHIFT (_PAGE_PRESENT_SHIFT + 1)
|
||||
#define _PAGE_WRITE (1 << _PAGE_WRITE_SHIFT)
|
||||
#else
|
||||
@ -135,16 +135,16 @@
|
||||
#define _PAGE_SPLITTING (1 << _PAGE_SPLITTING_SHIFT)
|
||||
|
||||
/* Only R2 or newer cores have the XI bit */
|
||||
#ifdef CONFIG_CPU_MIPSR2
|
||||
#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
|
||||
#define _PAGE_NO_EXEC_SHIFT (_PAGE_SPLITTING_SHIFT + 1)
|
||||
#else
|
||||
#define _PAGE_GLOBAL_SHIFT (_PAGE_SPLITTING_SHIFT + 1)
|
||||
#define _PAGE_GLOBAL (1 << _PAGE_GLOBAL_SHIFT)
|
||||
#endif /* CONFIG_CPU_MIPSR2 */
|
||||
#endif /* CONFIG_CPU_MIPSR2 || CONFIG_CPU_MIPSR6 */
|
||||
|
||||
#endif /* CONFIG_64BIT && CONFIG_MIPS_HUGE_TLB_SUPPORT */
|
||||
|
||||
#ifdef CONFIG_CPU_MIPSR2
|
||||
#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
|
||||
/* XI - page cannot be executed */
|
||||
#ifndef _PAGE_NO_EXEC_SHIFT
|
||||
#define _PAGE_NO_EXEC_SHIFT (_PAGE_MODIFIED_SHIFT + 1)
|
||||
@ -160,10 +160,10 @@
|
||||
#define _PAGE_GLOBAL_SHIFT (_PAGE_NO_READ_SHIFT + 1)
|
||||
#define _PAGE_GLOBAL (1 << _PAGE_GLOBAL_SHIFT)
|
||||
|
||||
#else /* !CONFIG_CPU_MIPSR2 */
|
||||
#else /* !CONFIG_CPU_MIPSR2 && !CONFIG_CPU_MIPSR6 */
|
||||
#define _PAGE_GLOBAL_SHIFT (_PAGE_MODIFIED_SHIFT + 1)
|
||||
#define _PAGE_GLOBAL (1 << _PAGE_GLOBAL_SHIFT)
|
||||
#endif /* CONFIG_CPU_MIPSR2 */
|
||||
#endif /* CONFIG_CPU_MIPSR2 || CONFIG_CPU_MIPSR6 */
|
||||
|
||||
#define _PAGE_VALID_SHIFT (_PAGE_GLOBAL_SHIFT + 1)
|
||||
#define _PAGE_VALID (1 << _PAGE_VALID_SHIFT)
|
||||
@ -205,7 +205,7 @@
|
||||
*/
|
||||
static inline uint64_t pte_to_entrylo(unsigned long pte_val)
|
||||
{
|
||||
#ifdef CONFIG_CPU_MIPSR2
|
||||
#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
|
||||
if (cpu_has_rixi) {
|
||||
int sa;
|
||||
#ifdef CONFIG_32BIT
|
||||
|
@ -104,7 +104,6 @@ do { \
|
||||
if (test_and_clear_tsk_thread_flag(prev, TIF_USEDMSA)) \
|
||||
__fpsave = FP_SAVE_VECTOR; \
|
||||
(last) = resume(prev, next, task_thread_info(next), __fpsave); \
|
||||
disable_msa(); \
|
||||
} while (0)
|
||||
|
||||
#define finish_arch_switch(prev) \
|
||||
@ -122,6 +121,7 @@ do { \
|
||||
if (cpu_has_userlocal) \
|
||||
write_c0_userlocal(current_thread_info()->tp_value); \
|
||||
__restore_watch(); \
|
||||
disable_msa(); \
|
||||
} while (0)
|
||||
|
||||
#endif /* _ASM_SWITCH_TO_H */
|
||||
|
@ -74,13 +74,12 @@ static inline void cpu_set_fpu_fcsr_mask(struct cpuinfo_mips *c)
|
||||
{
|
||||
unsigned long sr, mask, fcsr, fcsr0, fcsr1;
|
||||
|
||||
fcsr = c->fpu_csr31;
|
||||
mask = FPU_CSR_ALL_X | FPU_CSR_ALL_E | FPU_CSR_ALL_S | FPU_CSR_RM;
|
||||
|
||||
sr = read_c0_status();
|
||||
__enable_fpu(FPU_AS_IS);
|
||||
|
||||
fcsr = read_32bit_cp1_register(CP1_STATUS);
|
||||
|
||||
fcsr0 = fcsr & mask;
|
||||
write_32bit_cp1_register(CP1_STATUS, fcsr0);
|
||||
fcsr0 = read_32bit_cp1_register(CP1_STATUS);
|
||||
|
@ -109,7 +109,7 @@ void __init init_IRQ(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef DEBUG_STACKOVERFLOW
|
||||
#ifdef CONFIG_DEBUG_STACKOVERFLOW
|
||||
static inline void check_stack_overflow(void)
|
||||
{
|
||||
unsigned long sp;
|
||||
|
@ -2409,7 +2409,7 @@ enum emulation_result kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu,
|
||||
if (vcpu->mmio_needed == 2)
|
||||
*gpr = *(int16_t *) run->mmio.data;
|
||||
else
|
||||
*gpr = *(int16_t *) run->mmio.data;
|
||||
*gpr = *(uint16_t *)run->mmio.data;
|
||||
|
||||
break;
|
||||
case 1:
|
||||
|
@ -3,15 +3,13 @@
|
||||
#
|
||||
|
||||
obj-y += setup.o init.o cmdline.o env.o time.o reset.o irq.o \
|
||||
bonito-irq.o mem.o machtype.o platform.o
|
||||
bonito-irq.o mem.o machtype.o platform.o serial.o
|
||||
obj-$(CONFIG_PCI) += pci.o
|
||||
|
||||
#
|
||||
# Serial port support
|
||||
#
|
||||
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
|
||||
loongson-serial-$(CONFIG_SERIAL_8250) := serial.o
|
||||
obj-y += $(loongson-serial-m) $(loongson-serial-y)
|
||||
obj-$(CONFIG_LOONGSON_UART_BASE) += uart_base.o
|
||||
obj-$(CONFIG_LOONGSON_MC146818) += rtc.o
|
||||
|
||||
|
@ -272,7 +272,7 @@ void loongson3_ipi_interrupt(struct pt_regs *regs)
|
||||
if (action & SMP_ASK_C0COUNT) {
|
||||
BUG_ON(cpu != 0);
|
||||
c0count = read_c0_count();
|
||||
for (i = 1; i < loongson_sysconf.nr_cpus; i++)
|
||||
for (i = 1; i < num_possible_cpus(); i++)
|
||||
per_cpu(core0_c0count, i) = c0count;
|
||||
}
|
||||
}
|
||||
|
@ -1372,7 +1372,7 @@ static int probe_scache(void)
|
||||
scache_size = addr;
|
||||
c->scache.linesz = 16 << ((config & R4K_CONF_SB) >> 22);
|
||||
c->scache.ways = 1;
|
||||
c->dcache.waybit = 0; /* does not matter */
|
||||
c->scache.waybit = 0; /* does not matter */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -681,11 +681,7 @@ static unsigned int get_stack_depth(struct jit_ctx *ctx)
|
||||
sp_off += config_enabled(CONFIG_64BIT) ?
|
||||
(ARGS_USED_BY_JIT + 1) * RSIZE : RSIZE;
|
||||
|
||||
/*
|
||||
* Subtract the bytes for the last registers since we only care about
|
||||
* the location on the stack pointer.
|
||||
*/
|
||||
return sp_off - RSIZE;
|
||||
return sp_off;
|
||||
}
|
||||
|
||||
static void build_prologue(struct jit_ctx *ctx)
|
||||
|
@ -41,7 +41,7 @@ static irqreturn_t ill_acc_irq_handler(int irq, void *_priv)
|
||||
addr, (type >> ILL_ACC_OFF_S) & ILL_ACC_OFF_M,
|
||||
type & ILL_ACC_LEN_M);
|
||||
|
||||
rt_memc_w32(REG_ILL_ACC_TYPE, REG_ILL_ACC_TYPE);
|
||||
rt_memc_w32(ILL_INT_STATUS, REG_ILL_ACC_TYPE);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
@ -48,7 +48,9 @@ extern u8 sk_load_word[], sk_load_half[], sk_load_byte[];
|
||||
* We get 160 bytes stack space from calling function, but only use
|
||||
* 11 * 8 byte (old backchain + r15 - r6) for storing registers.
|
||||
*/
|
||||
#define STK_OFF (MAX_BPF_STACK + 8 + 4 + 4 + (160 - 11 * 8))
|
||||
#define STK_SPACE (MAX_BPF_STACK + 8 + 4 + 4 + 160)
|
||||
#define STK_160_UNUSED (160 - 11 * 8)
|
||||
#define STK_OFF (STK_SPACE - STK_160_UNUSED)
|
||||
#define STK_OFF_TMP 160 /* Offset of tmp buffer on stack */
|
||||
#define STK_OFF_HLEN 168 /* Offset of SKB header length on stack */
|
||||
|
||||
|
@ -384,13 +384,16 @@ static void bpf_jit_prologue(struct bpf_jit *jit)
|
||||
}
|
||||
/* Setup stack and backchain */
|
||||
if (jit->seen & SEEN_STACK) {
|
||||
/* lgr %bfp,%r15 (BPF frame pointer) */
|
||||
EMIT4(0xb9040000, BPF_REG_FP, REG_15);
|
||||
if (jit->seen & SEEN_FUNC)
|
||||
/* lgr %w1,%r15 (backchain) */
|
||||
EMIT4(0xb9040000, REG_W1, REG_15);
|
||||
/* la %bfp,STK_160_UNUSED(%r15) (BPF frame pointer) */
|
||||
EMIT4_DISP(0x41000000, BPF_REG_FP, REG_15, STK_160_UNUSED);
|
||||
/* aghi %r15,-STK_OFF */
|
||||
EMIT4_IMM(0xa70b0000, REG_15, -STK_OFF);
|
||||
if (jit->seen & SEEN_FUNC)
|
||||
/* stg %bfp,152(%r15) (backchain) */
|
||||
EMIT6_DISP_LH(0xe3000000, 0x0024, BPF_REG_FP, REG_0,
|
||||
/* stg %w1,152(%r15) (backchain) */
|
||||
EMIT6_DISP_LH(0xe3000000, 0x0024, REG_W1, REG_0,
|
||||
REG_15, 152);
|
||||
}
|
||||
/*
|
||||
|
@ -175,10 +175,10 @@ ENTRY(__clear_user)
|
||||
br r3
|
||||
|
||||
.section .fixup, "ax"
|
||||
99:
|
||||
br r3
|
||||
.previous
|
||||
.section __ex_table, "a"
|
||||
.align 2
|
||||
99:
|
||||
.word 0b, 99b
|
||||
.previous
|
||||
|
@ -24,7 +24,8 @@ typedef struct {
|
||||
unsigned int icache_line_size;
|
||||
unsigned int ecache_size;
|
||||
unsigned int ecache_line_size;
|
||||
int core_id;
|
||||
unsigned short sock_id;
|
||||
unsigned short core_id;
|
||||
int proc_id;
|
||||
} cpuinfo_sparc;
|
||||
|
||||
|
@ -308,12 +308,26 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t prot)
|
||||
" sllx %1, 32, %1\n"
|
||||
" or %0, %1, %0\n"
|
||||
" .previous\n"
|
||||
" .section .sun_m7_2insn_patch, \"ax\"\n"
|
||||
" .word 661b\n"
|
||||
" sethi %%uhi(%4), %1\n"
|
||||
" sethi %%hi(%4), %0\n"
|
||||
" .word 662b\n"
|
||||
" or %1, %%ulo(%4), %1\n"
|
||||
" or %0, %%lo(%4), %0\n"
|
||||
" .word 663b\n"
|
||||
" sllx %1, 32, %1\n"
|
||||
" or %0, %1, %0\n"
|
||||
" .previous\n"
|
||||
: "=r" (mask), "=r" (tmp)
|
||||
: "i" (_PAGE_PADDR_4U | _PAGE_MODIFIED_4U | _PAGE_ACCESSED_4U |
|
||||
_PAGE_CP_4U | _PAGE_CV_4U | _PAGE_E_4U |
|
||||
_PAGE_SPECIAL | _PAGE_PMD_HUGE | _PAGE_SZALL_4U),
|
||||
"i" (_PAGE_PADDR_4V | _PAGE_MODIFIED_4V | _PAGE_ACCESSED_4V |
|
||||
_PAGE_CP_4V | _PAGE_CV_4V | _PAGE_E_4V |
|
||||
_PAGE_SPECIAL | _PAGE_PMD_HUGE | _PAGE_SZALL_4V),
|
||||
"i" (_PAGE_PADDR_4V | _PAGE_MODIFIED_4V | _PAGE_ACCESSED_4V |
|
||||
_PAGE_CP_4V | _PAGE_E_4V |
|
||||
_PAGE_SPECIAL | _PAGE_PMD_HUGE | _PAGE_SZALL_4V));
|
||||
|
||||
return __pte((pte_val(pte) & mask) | (pgprot_val(prot) & ~mask));
|
||||
@ -342,9 +356,15 @@ static inline pgprot_t pgprot_noncached(pgprot_t prot)
|
||||
" andn %0, %4, %0\n"
|
||||
" or %0, %5, %0\n"
|
||||
" .previous\n"
|
||||
" .section .sun_m7_2insn_patch, \"ax\"\n"
|
||||
" .word 661b\n"
|
||||
" andn %0, %6, %0\n"
|
||||
" or %0, %5, %0\n"
|
||||
" .previous\n"
|
||||
: "=r" (val)
|
||||
: "0" (val), "i" (_PAGE_CP_4U | _PAGE_CV_4U), "i" (_PAGE_E_4U),
|
||||
"i" (_PAGE_CP_4V | _PAGE_CV_4V), "i" (_PAGE_E_4V));
|
||||
"i" (_PAGE_CP_4V | _PAGE_CV_4V), "i" (_PAGE_E_4V),
|
||||
"i" (_PAGE_CP_4V));
|
||||
|
||||
return __pgprot(val);
|
||||
}
|
||||
|
@ -40,11 +40,12 @@ static inline int pcibus_to_node(struct pci_bus *pbus)
|
||||
#ifdef CONFIG_SMP
|
||||
#define topology_physical_package_id(cpu) (cpu_data(cpu).proc_id)
|
||||
#define topology_core_id(cpu) (cpu_data(cpu).core_id)
|
||||
#define topology_core_cpumask(cpu) (&cpu_core_map[cpu])
|
||||
#define topology_core_cpumask(cpu) (&cpu_core_sib_map[cpu])
|
||||
#define topology_thread_cpumask(cpu) (&per_cpu(cpu_sibling_map, cpu))
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
extern cpumask_t cpu_core_map[NR_CPUS];
|
||||
extern cpumask_t cpu_core_sib_map[NR_CPUS];
|
||||
static inline const struct cpumask *cpu_coregroup_mask(int cpu)
|
||||
{
|
||||
return &cpu_core_map[cpu];
|
||||
|
@ -79,6 +79,8 @@ struct sun4v_2insn_patch_entry {
|
||||
};
|
||||
extern struct sun4v_2insn_patch_entry __sun4v_2insn_patch,
|
||||
__sun4v_2insn_patch_end;
|
||||
extern struct sun4v_2insn_patch_entry __sun_m7_2insn_patch,
|
||||
__sun_m7_2insn_patch_end;
|
||||
|
||||
|
||||
#endif /* !(__ASSEMBLY__) */
|
||||
|
@ -69,6 +69,8 @@ void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *,
|
||||
struct sun4v_1insn_patch_entry *);
|
||||
void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *,
|
||||
struct sun4v_2insn_patch_entry *);
|
||||
void sun_m7_patch_2insn_range(struct sun4v_2insn_patch_entry *,
|
||||
struct sun4v_2insn_patch_entry *);
|
||||
extern unsigned int dcache_parity_tl1_occurred;
|
||||
extern unsigned int icache_parity_tl1_occurred;
|
||||
|
||||
|
@ -723,7 +723,6 @@ static int grpci2_of_probe(struct platform_device *ofdev)
|
||||
err = -ENOMEM;
|
||||
goto err1;
|
||||
}
|
||||
memset(grpci2priv, 0, sizeof(*grpci2priv));
|
||||
priv->regs = regs;
|
||||
priv->irq = ofdev->archdata.irqs[0]; /* BASE IRQ */
|
||||
priv->irq_mode = (capability & STS_IRQMODE) >> STS_IRQMODE_BIT;
|
||||
|
@ -614,45 +614,68 @@ static void fill_in_one_cache(cpuinfo_sparc *c, struct mdesc_handle *hp, u64 mp)
|
||||
}
|
||||
}
|
||||
|
||||
static void mark_core_ids(struct mdesc_handle *hp, u64 mp, int core_id)
|
||||
static void find_back_node_value(struct mdesc_handle *hp, u64 node,
|
||||
char *srch_val,
|
||||
void (*func)(struct mdesc_handle *, u64, int),
|
||||
u64 val, int depth)
|
||||
{
|
||||
u64 a;
|
||||
u64 arc;
|
||||
|
||||
mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_BACK) {
|
||||
u64 t = mdesc_arc_target(hp, a);
|
||||
const char *name;
|
||||
const u64 *id;
|
||||
/* Since we have an estimate of recursion depth, do a sanity check. */
|
||||
if (depth == 0)
|
||||
return;
|
||||
|
||||
name = mdesc_node_name(hp, t);
|
||||
if (!strcmp(name, "cpu")) {
|
||||
id = mdesc_get_property(hp, t, "id", NULL);
|
||||
if (*id < NR_CPUS)
|
||||
cpu_data(*id).core_id = core_id;
|
||||
} else {
|
||||
u64 j;
|
||||
mdesc_for_each_arc(arc, hp, node, MDESC_ARC_TYPE_BACK) {
|
||||
u64 n = mdesc_arc_target(hp, arc);
|
||||
const char *name = mdesc_node_name(hp, n);
|
||||
|
||||
mdesc_for_each_arc(j, hp, t, MDESC_ARC_TYPE_BACK) {
|
||||
u64 n = mdesc_arc_target(hp, j);
|
||||
const char *n_name;
|
||||
if (!strcmp(srch_val, name))
|
||||
(*func)(hp, n, val);
|
||||
|
||||
n_name = mdesc_node_name(hp, n);
|
||||
if (strcmp(n_name, "cpu"))
|
||||
continue;
|
||||
|
||||
id = mdesc_get_property(hp, n, "id", NULL);
|
||||
if (*id < NR_CPUS)
|
||||
cpu_data(*id).core_id = core_id;
|
||||
}
|
||||
}
|
||||
find_back_node_value(hp, n, srch_val, func, val, depth-1);
|
||||
}
|
||||
}
|
||||
|
||||
static void __mark_core_id(struct mdesc_handle *hp, u64 node,
|
||||
int core_id)
|
||||
{
|
||||
const u64 *id = mdesc_get_property(hp, node, "id", NULL);
|
||||
|
||||
if (*id < num_possible_cpus())
|
||||
cpu_data(*id).core_id = core_id;
|
||||
}
|
||||
|
||||
static void __mark_sock_id(struct mdesc_handle *hp, u64 node,
|
||||
int sock_id)
|
||||
{
|
||||
const u64 *id = mdesc_get_property(hp, node, "id", NULL);
|
||||
|
||||
if (*id < num_possible_cpus())
|
||||
cpu_data(*id).sock_id = sock_id;
|
||||
}
|
||||
|
||||
static void mark_core_ids(struct mdesc_handle *hp, u64 mp,
|
||||
int core_id)
|
||||
{
|
||||
find_back_node_value(hp, mp, "cpu", __mark_core_id, core_id, 10);
|
||||
}
|
||||
|
||||
static void mark_sock_ids(struct mdesc_handle *hp, u64 mp,
|
||||
int sock_id)
|
||||
{
|
||||
find_back_node_value(hp, mp, "cpu", __mark_sock_id, sock_id, 10);
|
||||
}
|
||||
|
||||
static void set_core_ids(struct mdesc_handle *hp)
|
||||
{
|
||||
int idx;
|
||||
u64 mp;
|
||||
|
||||
idx = 1;
|
||||
|
||||
/* Identify unique cores by looking for cpus backpointed to by
|
||||
* level 1 instruction caches.
|
||||
*/
|
||||
mdesc_for_each_node_by_name(hp, mp, "cache") {
|
||||
const u64 *level;
|
||||
const char *type;
|
||||
@ -667,11 +690,72 @@ static void set_core_ids(struct mdesc_handle *hp)
|
||||
continue;
|
||||
|
||||
mark_core_ids(hp, mp, idx);
|
||||
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
static int set_sock_ids_by_cache(struct mdesc_handle *hp, int level)
|
||||
{
|
||||
u64 mp;
|
||||
int idx = 1;
|
||||
int fnd = 0;
|
||||
|
||||
/* Identify unique sockets by looking for cpus backpointed to by
|
||||
* shared level n caches.
|
||||
*/
|
||||
mdesc_for_each_node_by_name(hp, mp, "cache") {
|
||||
const u64 *cur_lvl;
|
||||
|
||||
cur_lvl = mdesc_get_property(hp, mp, "level", NULL);
|
||||
if (*cur_lvl != level)
|
||||
continue;
|
||||
|
||||
mark_sock_ids(hp, mp, idx);
|
||||
idx++;
|
||||
fnd = 1;
|
||||
}
|
||||
return fnd;
|
||||
}
|
||||
|
||||
static void set_sock_ids_by_socket(struct mdesc_handle *hp, u64 mp)
|
||||
{
|
||||
int idx = 1;
|
||||
|
||||
mdesc_for_each_node_by_name(hp, mp, "socket") {
|
||||
u64 a;
|
||||
|
||||
mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {
|
||||
u64 t = mdesc_arc_target(hp, a);
|
||||
const char *name;
|
||||
const u64 *id;
|
||||
|
||||
name = mdesc_node_name(hp, t);
|
||||
if (strcmp(name, "cpu"))
|
||||
continue;
|
||||
|
||||
id = mdesc_get_property(hp, t, "id", NULL);
|
||||
if (*id < num_possible_cpus())
|
||||
cpu_data(*id).sock_id = idx;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
static void set_sock_ids(struct mdesc_handle *hp)
|
||||
{
|
||||
u64 mp;
|
||||
|
||||
/* If machine description exposes sockets data use it.
|
||||
* Otherwise fallback to use shared L3 or L2 caches.
|
||||
*/
|
||||
mp = mdesc_node_by_name(hp, MDESC_NODE_NULL, "sockets");
|
||||
if (mp != MDESC_NODE_NULL)
|
||||
return set_sock_ids_by_socket(hp, mp);
|
||||
|
||||
if (!set_sock_ids_by_cache(hp, 3))
|
||||
set_sock_ids_by_cache(hp, 2);
|
||||
}
|
||||
|
||||
static void mark_proc_ids(struct mdesc_handle *hp, u64 mp, int proc_id)
|
||||
{
|
||||
u64 a;
|
||||
@ -707,7 +791,6 @@ static void __set_proc_ids(struct mdesc_handle *hp, const char *exec_unit_name)
|
||||
continue;
|
||||
|
||||
mark_proc_ids(hp, mp, idx);
|
||||
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
@ -900,6 +983,7 @@ void mdesc_fill_in_cpu_data(cpumask_t *mask)
|
||||
|
||||
set_core_ids(hp);
|
||||
set_proc_ids(hp);
|
||||
set_sock_ids(hp);
|
||||
|
||||
mdesc_release(hp);
|
||||
|
||||
|
@ -1002,6 +1002,38 @@ static int __init pcibios_init(void)
|
||||
subsys_initcall(pcibios_init);
|
||||
|
||||
#ifdef CONFIG_SYSFS
|
||||
|
||||
#define SLOT_NAME_SIZE 11 /* Max decimal digits + null in u32 */
|
||||
|
||||
static void pcie_bus_slot_names(struct pci_bus *pbus)
|
||||
{
|
||||
struct pci_dev *pdev;
|
||||
struct pci_bus *bus;
|
||||
|
||||
list_for_each_entry(pdev, &pbus->devices, bus_list) {
|
||||
char name[SLOT_NAME_SIZE];
|
||||
struct pci_slot *pci_slot;
|
||||
const u32 *slot_num;
|
||||
int len;
|
||||
|
||||
slot_num = of_get_property(pdev->dev.of_node,
|
||||
"physical-slot#", &len);
|
||||
|
||||
if (slot_num == NULL || len != 4)
|
||||
continue;
|
||||
|
||||
snprintf(name, sizeof(name), "%u", slot_num[0]);
|
||||
pci_slot = pci_create_slot(pbus, slot_num[0], name, NULL);
|
||||
|
||||
if (IS_ERR(pci_slot))
|
||||
pr_err("PCI: pci_create_slot returned %ld.\n",
|
||||
PTR_ERR(pci_slot));
|
||||
}
|
||||
|
||||
list_for_each_entry(bus, &pbus->children, node)
|
||||
pcie_bus_slot_names(bus);
|
||||
}
|
||||
|
||||
static void pci_bus_slot_names(struct device_node *node, struct pci_bus *bus)
|
||||
{
|
||||
const struct pci_slot_names {
|
||||
@ -1053,18 +1085,29 @@ static int __init of_pci_slot_init(void)
|
||||
|
||||
while ((pbus = pci_find_next_bus(pbus)) != NULL) {
|
||||
struct device_node *node;
|
||||
struct pci_dev *pdev;
|
||||
|
||||
if (pbus->self) {
|
||||
/* PCI->PCI bridge */
|
||||
node = pbus->self->dev.of_node;
|
||||
pdev = list_first_entry(&pbus->devices, struct pci_dev,
|
||||
bus_list);
|
||||
|
||||
if (pdev && pci_is_pcie(pdev)) {
|
||||
pcie_bus_slot_names(pbus);
|
||||
} else {
|
||||
struct pci_pbm_info *pbm = pbus->sysdata;
|
||||
|
||||
/* Host PCI controller */
|
||||
node = pbm->op->dev.of_node;
|
||||
if (pbus->self) {
|
||||
|
||||
/* PCI->PCI bridge */
|
||||
node = pbus->self->dev.of_node;
|
||||
|
||||
} else {
|
||||
struct pci_pbm_info *pbm = pbus->sysdata;
|
||||
|
||||
/* Host PCI controller */
|
||||
node = pbm->op->dev.of_node;
|
||||
}
|
||||
|
||||
pci_bus_slot_names(node, pbus);
|
||||
}
|
||||
|
||||
pci_bus_slot_names(node, pbus);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -255,6 +255,24 @@ void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *start,
|
||||
}
|
||||
}
|
||||
|
||||
void sun_m7_patch_2insn_range(struct sun4v_2insn_patch_entry *start,
|
||||
struct sun4v_2insn_patch_entry *end)
|
||||
{
|
||||
while (start < end) {
|
||||
unsigned long addr = start->addr;
|
||||
|
||||
*(unsigned int *) (addr + 0) = start->insns[0];
|
||||
wmb();
|
||||
__asm__ __volatile__("flush %0" : : "r" (addr + 0));
|
||||
|
||||
*(unsigned int *) (addr + 4) = start->insns[1];
|
||||
wmb();
|
||||
__asm__ __volatile__("flush %0" : : "r" (addr + 4));
|
||||
|
||||
start++;
|
||||
}
|
||||
}
|
||||
|
||||
static void __init sun4v_patch(void)
|
||||
{
|
||||
extern void sun4v_hvapi_init(void);
|
||||
@ -267,6 +285,9 @@ static void __init sun4v_patch(void)
|
||||
|
||||
sun4v_patch_2insn_range(&__sun4v_2insn_patch,
|
||||
&__sun4v_2insn_patch_end);
|
||||
if (sun4v_chip_type == SUN4V_CHIP_SPARC_M7)
|
||||
sun_m7_patch_2insn_range(&__sun_m7_2insn_patch,
|
||||
&__sun_m7_2insn_patch_end);
|
||||
|
||||
sun4v_hvapi_init();
|
||||
}
|
||||
|
@ -60,8 +60,12 @@ DEFINE_PER_CPU(cpumask_t, cpu_sibling_map) = CPU_MASK_NONE;
|
||||
cpumask_t cpu_core_map[NR_CPUS] __read_mostly =
|
||||
{ [0 ... NR_CPUS-1] = CPU_MASK_NONE };
|
||||
|
||||
cpumask_t cpu_core_sib_map[NR_CPUS] __read_mostly = {
|
||||
[0 ... NR_CPUS-1] = CPU_MASK_NONE };
|
||||
|
||||
EXPORT_PER_CPU_SYMBOL(cpu_sibling_map);
|
||||
EXPORT_SYMBOL(cpu_core_map);
|
||||
EXPORT_SYMBOL(cpu_core_sib_map);
|
||||
|
||||
static cpumask_t smp_commenced_mask;
|
||||
|
||||
@ -1243,6 +1247,15 @@ void smp_fill_in_sib_core_maps(void)
|
||||
}
|
||||
}
|
||||
|
||||
for_each_present_cpu(i) {
|
||||
unsigned int j;
|
||||
|
||||
for_each_present_cpu(j) {
|
||||
if (cpu_data(i).sock_id == cpu_data(j).sock_id)
|
||||
cpumask_set_cpu(j, &cpu_core_sib_map[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for_each_present_cpu(i) {
|
||||
unsigned int j;
|
||||
|
||||
|
@ -138,6 +138,11 @@ SECTIONS
|
||||
*(.pause_3insn_patch)
|
||||
__pause_3insn_patch_end = .;
|
||||
}
|
||||
.sun_m7_2insn_patch : {
|
||||
__sun_m7_2insn_patch = .;
|
||||
*(.sun_m7_2insn_patch)
|
||||
__sun_m7_2insn_patch_end = .;
|
||||
}
|
||||
PERCPU_SECTION(SMP_CACHE_BYTES)
|
||||
|
||||
. = ALIGN(PAGE_SIZE);
|
||||
|
@ -54,6 +54,7 @@
|
||||
#include "init_64.h"
|
||||
|
||||
unsigned long kern_linear_pte_xor[4] __read_mostly;
|
||||
static unsigned long page_cache4v_flag;
|
||||
|
||||
/* A bitmap, two bits for every 256MB of physical memory. These two
|
||||
* bits determine what page size we use for kernel linear
|
||||
@ -1909,11 +1910,24 @@ static void __init sun4u_linear_pte_xor_finalize(void)
|
||||
|
||||
static void __init sun4v_linear_pte_xor_finalize(void)
|
||||
{
|
||||
unsigned long pagecv_flag;
|
||||
|
||||
/* Bit 9 of TTE is no longer CV bit on M7 processor and it instead
|
||||
* enables MCD error. Do not set bit 9 on M7 processor.
|
||||
*/
|
||||
switch (sun4v_chip_type) {
|
||||
case SUN4V_CHIP_SPARC_M7:
|
||||
pagecv_flag = 0x00;
|
||||
break;
|
||||
default:
|
||||
pagecv_flag = _PAGE_CV_4V;
|
||||
break;
|
||||
}
|
||||
#ifndef CONFIG_DEBUG_PAGEALLOC
|
||||
if (cpu_pgsz_mask & HV_PGSZ_MASK_256MB) {
|
||||
kern_linear_pte_xor[1] = (_PAGE_VALID | _PAGE_SZ256MB_4V) ^
|
||||
PAGE_OFFSET;
|
||||
kern_linear_pte_xor[1] |= (_PAGE_CP_4V | _PAGE_CV_4V |
|
||||
kern_linear_pte_xor[1] |= (_PAGE_CP_4V | pagecv_flag |
|
||||
_PAGE_P_4V | _PAGE_W_4V);
|
||||
} else {
|
||||
kern_linear_pte_xor[1] = kern_linear_pte_xor[0];
|
||||
@ -1922,7 +1936,7 @@ static void __init sun4v_linear_pte_xor_finalize(void)
|
||||
if (cpu_pgsz_mask & HV_PGSZ_MASK_2GB) {
|
||||
kern_linear_pte_xor[2] = (_PAGE_VALID | _PAGE_SZ2GB_4V) ^
|
||||
PAGE_OFFSET;
|
||||
kern_linear_pte_xor[2] |= (_PAGE_CP_4V | _PAGE_CV_4V |
|
||||
kern_linear_pte_xor[2] |= (_PAGE_CP_4V | pagecv_flag |
|
||||
_PAGE_P_4V | _PAGE_W_4V);
|
||||
} else {
|
||||
kern_linear_pte_xor[2] = kern_linear_pte_xor[1];
|
||||
@ -1931,7 +1945,7 @@ static void __init sun4v_linear_pte_xor_finalize(void)
|
||||
if (cpu_pgsz_mask & HV_PGSZ_MASK_16GB) {
|
||||
kern_linear_pte_xor[3] = (_PAGE_VALID | _PAGE_SZ16GB_4V) ^
|
||||
PAGE_OFFSET;
|
||||
kern_linear_pte_xor[3] |= (_PAGE_CP_4V | _PAGE_CV_4V |
|
||||
kern_linear_pte_xor[3] |= (_PAGE_CP_4V | pagecv_flag |
|
||||
_PAGE_P_4V | _PAGE_W_4V);
|
||||
} else {
|
||||
kern_linear_pte_xor[3] = kern_linear_pte_xor[2];
|
||||
@ -1958,6 +1972,13 @@ static phys_addr_t __init available_memory(void)
|
||||
return available;
|
||||
}
|
||||
|
||||
#define _PAGE_CACHE_4U (_PAGE_CP_4U | _PAGE_CV_4U)
|
||||
#define _PAGE_CACHE_4V (_PAGE_CP_4V | _PAGE_CV_4V)
|
||||
#define __DIRTY_BITS_4U (_PAGE_MODIFIED_4U | _PAGE_WRITE_4U | _PAGE_W_4U)
|
||||
#define __DIRTY_BITS_4V (_PAGE_MODIFIED_4V | _PAGE_WRITE_4V | _PAGE_W_4V)
|
||||
#define __ACCESS_BITS_4U (_PAGE_ACCESSED_4U | _PAGE_READ_4U | _PAGE_R)
|
||||
#define __ACCESS_BITS_4V (_PAGE_ACCESSED_4V | _PAGE_READ_4V | _PAGE_R)
|
||||
|
||||
/* We need to exclude reserved regions. This exclusion will include
|
||||
* vmlinux and initrd. To be more precise the initrd size could be used to
|
||||
* compute a new lower limit because it is freed later during initialization.
|
||||
@ -2034,6 +2055,25 @@ void __init paging_init(void)
|
||||
memset(swapper_4m_tsb, 0x40, sizeof(swapper_4m_tsb));
|
||||
#endif
|
||||
|
||||
/* TTE.cv bit on sparc v9 occupies the same position as TTE.mcde
|
||||
* bit on M7 processor. This is a conflicting usage of the same
|
||||
* bit. Enabling TTE.cv on M7 would turn on Memory Corruption
|
||||
* Detection error on all pages and this will lead to problems
|
||||
* later. Kernel does not run with MCD enabled and hence rest
|
||||
* of the required steps to fully configure memory corruption
|
||||
* detection are not taken. We need to ensure TTE.mcde is not
|
||||
* set on M7 processor. Compute the value of cacheability
|
||||
* flag for use later taking this into consideration.
|
||||
*/
|
||||
switch (sun4v_chip_type) {
|
||||
case SUN4V_CHIP_SPARC_M7:
|
||||
page_cache4v_flag = _PAGE_CP_4V;
|
||||
break;
|
||||
default:
|
||||
page_cache4v_flag = _PAGE_CACHE_4V;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tlb_type == hypervisor)
|
||||
sun4v_pgprot_init();
|
||||
else
|
||||
@ -2274,13 +2314,6 @@ void free_initrd_mem(unsigned long start, unsigned long end)
|
||||
}
|
||||
#endif
|
||||
|
||||
#define _PAGE_CACHE_4U (_PAGE_CP_4U | _PAGE_CV_4U)
|
||||
#define _PAGE_CACHE_4V (_PAGE_CP_4V | _PAGE_CV_4V)
|
||||
#define __DIRTY_BITS_4U (_PAGE_MODIFIED_4U | _PAGE_WRITE_4U | _PAGE_W_4U)
|
||||
#define __DIRTY_BITS_4V (_PAGE_MODIFIED_4V | _PAGE_WRITE_4V | _PAGE_W_4V)
|
||||
#define __ACCESS_BITS_4U (_PAGE_ACCESSED_4U | _PAGE_READ_4U | _PAGE_R)
|
||||
#define __ACCESS_BITS_4V (_PAGE_ACCESSED_4V | _PAGE_READ_4V | _PAGE_R)
|
||||
|
||||
pgprot_t PAGE_KERNEL __read_mostly;
|
||||
EXPORT_SYMBOL(PAGE_KERNEL);
|
||||
|
||||
@ -2312,8 +2345,7 @@ int __meminit vmemmap_populate(unsigned long vstart, unsigned long vend,
|
||||
_PAGE_P_4U | _PAGE_W_4U);
|
||||
if (tlb_type == hypervisor)
|
||||
pte_base = (_PAGE_VALID | _PAGE_SZ4MB_4V |
|
||||
_PAGE_CP_4V | _PAGE_CV_4V |
|
||||
_PAGE_P_4V | _PAGE_W_4V);
|
||||
page_cache4v_flag | _PAGE_P_4V | _PAGE_W_4V);
|
||||
|
||||
pte_base |= _PAGE_PMD_HUGE;
|
||||
|
||||
@ -2450,14 +2482,14 @@ static void __init sun4v_pgprot_init(void)
|
||||
int i;
|
||||
|
||||
PAGE_KERNEL = __pgprot (_PAGE_PRESENT_4V | _PAGE_VALID |
|
||||
_PAGE_CACHE_4V | _PAGE_P_4V |
|
||||
page_cache4v_flag | _PAGE_P_4V |
|
||||
__ACCESS_BITS_4V | __DIRTY_BITS_4V |
|
||||
_PAGE_EXEC_4V);
|
||||
PAGE_KERNEL_LOCKED = PAGE_KERNEL;
|
||||
|
||||
_PAGE_IE = _PAGE_IE_4V;
|
||||
_PAGE_E = _PAGE_E_4V;
|
||||
_PAGE_CACHE = _PAGE_CACHE_4V;
|
||||
_PAGE_CACHE = page_cache4v_flag;
|
||||
|
||||
#ifdef CONFIG_DEBUG_PAGEALLOC
|
||||
kern_linear_pte_xor[0] = _PAGE_VALID ^ PAGE_OFFSET;
|
||||
@ -2465,8 +2497,8 @@ static void __init sun4v_pgprot_init(void)
|
||||
kern_linear_pte_xor[0] = (_PAGE_VALID | _PAGE_SZ4MB_4V) ^
|
||||
PAGE_OFFSET;
|
||||
#endif
|
||||
kern_linear_pte_xor[0] |= (_PAGE_CP_4V | _PAGE_CV_4V |
|
||||
_PAGE_P_4V | _PAGE_W_4V);
|
||||
kern_linear_pte_xor[0] |= (page_cache4v_flag | _PAGE_P_4V |
|
||||
_PAGE_W_4V);
|
||||
|
||||
for (i = 1; i < 4; i++)
|
||||
kern_linear_pte_xor[i] = kern_linear_pte_xor[0];
|
||||
@ -2479,12 +2511,12 @@ static void __init sun4v_pgprot_init(void)
|
||||
_PAGE_SZ4MB_4V | _PAGE_SZ512K_4V |
|
||||
_PAGE_SZ64K_4V | _PAGE_SZ8K_4V);
|
||||
|
||||
page_none = _PAGE_PRESENT_4V | _PAGE_ACCESSED_4V | _PAGE_CACHE_4V;
|
||||
page_shared = (_PAGE_VALID | _PAGE_PRESENT_4V | _PAGE_CACHE_4V |
|
||||
page_none = _PAGE_PRESENT_4V | _PAGE_ACCESSED_4V | page_cache4v_flag;
|
||||
page_shared = (_PAGE_VALID | _PAGE_PRESENT_4V | page_cache4v_flag |
|
||||
__ACCESS_BITS_4V | _PAGE_WRITE_4V | _PAGE_EXEC_4V);
|
||||
page_copy = (_PAGE_VALID | _PAGE_PRESENT_4V | _PAGE_CACHE_4V |
|
||||
page_copy = (_PAGE_VALID | _PAGE_PRESENT_4V | page_cache4v_flag |
|
||||
__ACCESS_BITS_4V | _PAGE_EXEC_4V);
|
||||
page_readonly = (_PAGE_VALID | _PAGE_PRESENT_4V | _PAGE_CACHE_4V |
|
||||
page_readonly = (_PAGE_VALID | _PAGE_PRESENT_4V | page_cache4v_flag |
|
||||
__ACCESS_BITS_4V | _PAGE_EXEC_4V);
|
||||
|
||||
page_exec_bit = _PAGE_EXEC_4V;
|
||||
@ -2542,7 +2574,7 @@ static unsigned long kern_large_tte(unsigned long paddr)
|
||||
_PAGE_EXEC_4U | _PAGE_L_4U | _PAGE_W_4U);
|
||||
if (tlb_type == hypervisor)
|
||||
val = (_PAGE_VALID | _PAGE_SZ4MB_4V |
|
||||
_PAGE_CP_4V | _PAGE_CV_4V | _PAGE_P_4V |
|
||||
page_cache4v_flag | _PAGE_P_4V |
|
||||
_PAGE_EXEC_4V | _PAGE_W_4V);
|
||||
|
||||
return val | paddr;
|
||||
|
@ -2,15 +2,14 @@
|
||||
#define BOOT_COMPRESSED_MISC_H
|
||||
|
||||
/*
|
||||
* we have to be careful, because no indirections are allowed here, and
|
||||
* paravirt_ops is a kind of one. As it will only run in baremetal anyway,
|
||||
* we just keep it from happening
|
||||
* Special hack: we have to be careful, because no indirections are allowed here,
|
||||
* and paravirt_ops is a kind of one. As it will only run in baremetal anyway,
|
||||
* we just keep it from happening. (This list needs to be extended when new
|
||||
* paravirt and debugging variants are added.)
|
||||
*/
|
||||
#undef CONFIG_PARAVIRT
|
||||
#undef CONFIG_PARAVIRT_SPINLOCKS
|
||||
#undef CONFIG_KASAN
|
||||
#ifdef CONFIG_X86_32
|
||||
#define _ASM_X86_DESC_H 1
|
||||
#endif
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <linux/screen_info.h>
|
||||
|
@ -107,7 +107,7 @@ static inline unsigned long regs_return_value(struct pt_regs *regs)
|
||||
static inline int user_mode(struct pt_regs *regs)
|
||||
{
|
||||
#ifdef CONFIG_X86_32
|
||||
return (regs->cs & SEGMENT_RPL_MASK) == USER_RPL;
|
||||
return ((regs->cs & SEGMENT_RPL_MASK) | (regs->flags & X86_VM_MASK)) >= USER_RPL;
|
||||
#else
|
||||
return !!(regs->cs & 3);
|
||||
#endif
|
||||
|
@ -231,11 +231,21 @@
|
||||
#define TLS_SIZE (GDT_ENTRY_TLS_ENTRIES* 8)
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
/*
|
||||
* early_idt_handler_array is an array of entry points referenced in the
|
||||
* early IDT. For simplicity, it's a real array with one entry point
|
||||
* every nine bytes. That leaves room for an optional 'push $0' if the
|
||||
* vector has no error code (two bytes), a 'push $vector_number' (two
|
||||
* bytes), and a jump to the common entry code (up to five bytes).
|
||||
*/
|
||||
#define EARLY_IDT_HANDLER_SIZE 9
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
extern const char early_idt_handlers[NUM_EXCEPTION_VECTORS][2+2+5];
|
||||
extern const char early_idt_handler_array[NUM_EXCEPTION_VECTORS][EARLY_IDT_HANDLER_SIZE];
|
||||
#ifdef CONFIG_TRACING
|
||||
# define trace_early_idt_handlers early_idt_handlers
|
||||
# define trace_early_idt_handler_array early_idt_handler_array
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -190,6 +190,7 @@ static bool check_hw_exists(void)
|
||||
u64 val, val_fail, val_new= ~0;
|
||||
int i, reg, reg_fail, ret = 0;
|
||||
int bios_fail = 0;
|
||||
int reg_safe = -1;
|
||||
|
||||
/*
|
||||
* Check to see if the BIOS enabled any of the counters, if so
|
||||
@ -204,6 +205,8 @@ static bool check_hw_exists(void)
|
||||
bios_fail = 1;
|
||||
val_fail = val;
|
||||
reg_fail = reg;
|
||||
} else {
|
||||
reg_safe = i;
|
||||
}
|
||||
}
|
||||
|
||||
@ -221,12 +224,23 @@ static bool check_hw_exists(void)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If all the counters are enabled, the below test will always
|
||||
* fail. The tools will also become useless in this scenario.
|
||||
* Just fail and disable the hardware counters.
|
||||
*/
|
||||
|
||||
if (reg_safe == -1) {
|
||||
reg = reg_safe;
|
||||
goto msr_fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the current value, change it and read it back to see if it
|
||||
* matches, this is needed to detect certain hardware emulators
|
||||
* (qemu/kvm) that don't trap on the MSR access and always return 0s.
|
||||
*/
|
||||
reg = x86_pmu_event_addr(0);
|
||||
reg = x86_pmu_event_addr(reg_safe);
|
||||
if (rdmsrl_safe(reg, &val))
|
||||
goto msr_fail;
|
||||
val ^= 0xffffUL;
|
||||
@ -611,6 +625,7 @@ struct sched_state {
|
||||
int event; /* event index */
|
||||
int counter; /* counter index */
|
||||
int unassigned; /* number of events to be assigned left */
|
||||
int nr_gp; /* number of GP counters used */
|
||||
unsigned long used[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
|
||||
};
|
||||
|
||||
@ -620,27 +635,29 @@ struct sched_state {
|
||||
struct perf_sched {
|
||||
int max_weight;
|
||||
int max_events;
|
||||
struct perf_event **events;
|
||||
struct sched_state state;
|
||||
int max_gp;
|
||||
int saved_states;
|
||||
struct event_constraint **constraints;
|
||||
struct sched_state state;
|
||||
struct sched_state saved[SCHED_STATES_MAX];
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialize interator that runs through all events and counters.
|
||||
*/
|
||||
static void perf_sched_init(struct perf_sched *sched, struct perf_event **events,
|
||||
int num, int wmin, int wmax)
|
||||
static void perf_sched_init(struct perf_sched *sched, struct event_constraint **constraints,
|
||||
int num, int wmin, int wmax, int gpmax)
|
||||
{
|
||||
int idx;
|
||||
|
||||
memset(sched, 0, sizeof(*sched));
|
||||
sched->max_events = num;
|
||||
sched->max_weight = wmax;
|
||||
sched->events = events;
|
||||
sched->max_gp = gpmax;
|
||||
sched->constraints = constraints;
|
||||
|
||||
for (idx = 0; idx < num; idx++) {
|
||||
if (events[idx]->hw.constraint->weight == wmin)
|
||||
if (constraints[idx]->weight == wmin)
|
||||
break;
|
||||
}
|
||||
|
||||
@ -687,7 +704,7 @@ static bool __perf_sched_find_counter(struct perf_sched *sched)
|
||||
if (sched->state.event >= sched->max_events)
|
||||
return false;
|
||||
|
||||
c = sched->events[sched->state.event]->hw.constraint;
|
||||
c = sched->constraints[sched->state.event];
|
||||
/* Prefer fixed purpose counters */
|
||||
if (c->idxmsk64 & (~0ULL << INTEL_PMC_IDX_FIXED)) {
|
||||
idx = INTEL_PMC_IDX_FIXED;
|
||||
@ -696,11 +713,16 @@ static bool __perf_sched_find_counter(struct perf_sched *sched)
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/* Grab the first unused counter starting with idx */
|
||||
idx = sched->state.counter;
|
||||
for_each_set_bit_from(idx, c->idxmsk, INTEL_PMC_IDX_FIXED) {
|
||||
if (!__test_and_set_bit(idx, sched->state.used))
|
||||
if (!__test_and_set_bit(idx, sched->state.used)) {
|
||||
if (sched->state.nr_gp++ >= sched->max_gp)
|
||||
return false;
|
||||
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -745,7 +767,7 @@ static bool perf_sched_next_event(struct perf_sched *sched)
|
||||
if (sched->state.weight > sched->max_weight)
|
||||
return false;
|
||||
}
|
||||
c = sched->events[sched->state.event]->hw.constraint;
|
||||
c = sched->constraints[sched->state.event];
|
||||
} while (c->weight != sched->state.weight);
|
||||
|
||||
sched->state.counter = 0; /* start with first counter */
|
||||
@ -756,12 +778,12 @@ static bool perf_sched_next_event(struct perf_sched *sched)
|
||||
/*
|
||||
* Assign a counter for each event.
|
||||
*/
|
||||
int perf_assign_events(struct perf_event **events, int n,
|
||||
int wmin, int wmax, int *assign)
|
||||
int perf_assign_events(struct event_constraint **constraints, int n,
|
||||
int wmin, int wmax, int gpmax, int *assign)
|
||||
{
|
||||
struct perf_sched sched;
|
||||
|
||||
perf_sched_init(&sched, events, n, wmin, wmax);
|
||||
perf_sched_init(&sched, constraints, n, wmin, wmax, gpmax);
|
||||
|
||||
do {
|
||||
if (!perf_sched_find_counter(&sched))
|
||||
@ -788,9 +810,9 @@ int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
|
||||
x86_pmu.start_scheduling(cpuc);
|
||||
|
||||
for (i = 0, wmin = X86_PMC_IDX_MAX, wmax = 0; i < n; i++) {
|
||||
hwc = &cpuc->event_list[i]->hw;
|
||||
cpuc->event_constraint[i] = NULL;
|
||||
c = x86_pmu.get_event_constraints(cpuc, i, cpuc->event_list[i]);
|
||||
hwc->constraint = c;
|
||||
cpuc->event_constraint[i] = c;
|
||||
|
||||
wmin = min(wmin, c->weight);
|
||||
wmax = max(wmax, c->weight);
|
||||
@ -801,7 +823,7 @@ int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
|
||||
*/
|
||||
for (i = 0; i < n; i++) {
|
||||
hwc = &cpuc->event_list[i]->hw;
|
||||
c = hwc->constraint;
|
||||
c = cpuc->event_constraint[i];
|
||||
|
||||
/* never assigned */
|
||||
if (hwc->idx == -1)
|
||||
@ -821,9 +843,26 @@ int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
|
||||
}
|
||||
|
||||
/* slow path */
|
||||
if (i != n)
|
||||
unsched = perf_assign_events(cpuc->event_list, n, wmin,
|
||||
wmax, assign);
|
||||
if (i != n) {
|
||||
int gpmax = x86_pmu.num_counters;
|
||||
|
||||
/*
|
||||
* Do not allow scheduling of more than half the available
|
||||
* generic counters.
|
||||
*
|
||||
* This helps avoid counter starvation of sibling thread by
|
||||
* ensuring at most half the counters cannot be in exclusive
|
||||
* mode. There is no designated counters for the limits. Any
|
||||
* N/2 counters can be used. This helps with events with
|
||||
* specific counter constraints.
|
||||
*/
|
||||
if (is_ht_workaround_enabled() && !cpuc->is_fake &&
|
||||
READ_ONCE(cpuc->excl_cntrs->exclusive_present))
|
||||
gpmax /= 2;
|
||||
|
||||
unsched = perf_assign_events(cpuc->event_constraint, n, wmin,
|
||||
wmax, gpmax, assign);
|
||||
}
|
||||
|
||||
/*
|
||||
* In case of success (unsched = 0), mark events as committed,
|
||||
@ -840,7 +879,7 @@ int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
|
||||
e = cpuc->event_list[i];
|
||||
e->hw.flags |= PERF_X86_EVENT_COMMITTED;
|
||||
if (x86_pmu.commit_scheduling)
|
||||
x86_pmu.commit_scheduling(cpuc, e, assign[i]);
|
||||
x86_pmu.commit_scheduling(cpuc, i, assign[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1292,8 +1331,10 @@ static void x86_pmu_del(struct perf_event *event, int flags)
|
||||
x86_pmu.put_event_constraints(cpuc, event);
|
||||
|
||||
/* Delete the array entry. */
|
||||
while (++i < cpuc->n_events)
|
||||
while (++i < cpuc->n_events) {
|
||||
cpuc->event_list[i-1] = cpuc->event_list[i];
|
||||
cpuc->event_constraint[i-1] = cpuc->event_constraint[i];
|
||||
}
|
||||
--cpuc->n_events;
|
||||
|
||||
perf_event_update_userpage(event);
|
||||
|
@ -74,6 +74,7 @@ struct event_constraint {
|
||||
#define PERF_X86_EVENT_EXCL 0x0040 /* HT exclusivity on counter */
|
||||
#define PERF_X86_EVENT_DYNAMIC 0x0080 /* dynamic alloc'd constraint */
|
||||
#define PERF_X86_EVENT_RDPMC_ALLOWED 0x0100 /* grant rdpmc permission */
|
||||
#define PERF_X86_EVENT_EXCL_ACCT 0x0200 /* accounted EXCL event */
|
||||
|
||||
|
||||
struct amd_nb {
|
||||
@ -134,8 +135,6 @@ enum intel_excl_state_type {
|
||||
struct intel_excl_states {
|
||||
enum intel_excl_state_type init_state[X86_PMC_IDX_MAX];
|
||||
enum intel_excl_state_type state[X86_PMC_IDX_MAX];
|
||||
int num_alloc_cntrs;/* #counters allocated */
|
||||
int max_alloc_cntrs;/* max #counters allowed */
|
||||
bool sched_started; /* true if scheduling has started */
|
||||
};
|
||||
|
||||
@ -144,6 +143,11 @@ struct intel_excl_cntrs {
|
||||
|
||||
struct intel_excl_states states[2];
|
||||
|
||||
union {
|
||||
u16 has_exclusive[2];
|
||||
u32 exclusive_present;
|
||||
};
|
||||
|
||||
int refcnt; /* per-core: #HT threads */
|
||||
unsigned core_id; /* per-core: core id */
|
||||
};
|
||||
@ -172,7 +176,11 @@ struct cpu_hw_events {
|
||||
added in the current transaction */
|
||||
int assign[X86_PMC_IDX_MAX]; /* event to counter assignment */
|
||||
u64 tags[X86_PMC_IDX_MAX];
|
||||
|
||||
struct perf_event *event_list[X86_PMC_IDX_MAX]; /* in enabled order */
|
||||
struct event_constraint *event_constraint[X86_PMC_IDX_MAX];
|
||||
|
||||
int n_excl; /* the number of exclusive events */
|
||||
|
||||
unsigned int group_flag;
|
||||
int is_fake;
|
||||
@ -519,9 +527,7 @@ struct x86_pmu {
|
||||
void (*put_event_constraints)(struct cpu_hw_events *cpuc,
|
||||
struct perf_event *event);
|
||||
|
||||
void (*commit_scheduling)(struct cpu_hw_events *cpuc,
|
||||
struct perf_event *event,
|
||||
int cntr);
|
||||
void (*commit_scheduling)(struct cpu_hw_events *cpuc, int idx, int cntr);
|
||||
|
||||
void (*start_scheduling)(struct cpu_hw_events *cpuc);
|
||||
|
||||
@ -717,8 +723,8 @@ static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc,
|
||||
|
||||
void x86_pmu_enable_all(int added);
|
||||
|
||||
int perf_assign_events(struct perf_event **events, int n,
|
||||
int wmin, int wmax, int *assign);
|
||||
int perf_assign_events(struct event_constraint **constraints, int n,
|
||||
int wmin, int wmax, int gpmax, int *assign);
|
||||
int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign);
|
||||
|
||||
void x86_pmu_stop(struct perf_event *event, int flags);
|
||||
@ -929,4 +935,8 @@ static inline struct intel_shared_regs *allocate_shared_regs(int cpu)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int is_ht_workaround_enabled(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_CPU_SUP_INTEL */
|
||||
|
@ -1923,7 +1923,6 @@ intel_start_scheduling(struct cpu_hw_events *cpuc)
|
||||
xl = &excl_cntrs->states[tid];
|
||||
|
||||
xl->sched_started = true;
|
||||
xl->num_alloc_cntrs = 0;
|
||||
/*
|
||||
* lock shared state until we are done scheduling
|
||||
* in stop_event_scheduling()
|
||||
@ -2000,6 +1999,11 @@ intel_get_excl_constraints(struct cpu_hw_events *cpuc, struct perf_event *event,
|
||||
* across HT threads
|
||||
*/
|
||||
is_excl = c->flags & PERF_X86_EVENT_EXCL;
|
||||
if (is_excl && !(event->hw.flags & PERF_X86_EVENT_EXCL_ACCT)) {
|
||||
event->hw.flags |= PERF_X86_EVENT_EXCL_ACCT;
|
||||
if (!cpuc->n_excl++)
|
||||
WRITE_ONCE(excl_cntrs->has_exclusive[tid], 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* xl = state of current HT
|
||||
@ -2008,18 +2012,6 @@ intel_get_excl_constraints(struct cpu_hw_events *cpuc, struct perf_event *event,
|
||||
xl = &excl_cntrs->states[tid];
|
||||
xlo = &excl_cntrs->states[o_tid];
|
||||
|
||||
/*
|
||||
* do not allow scheduling of more than max_alloc_cntrs
|
||||
* which is set to half the available generic counters.
|
||||
* this helps avoid counter starvation of sibling thread
|
||||
* by ensuring at most half the counters cannot be in
|
||||
* exclusive mode. There is not designated counters for the
|
||||
* limits. Any N/2 counters can be used. This helps with
|
||||
* events with specifix counter constraints
|
||||
*/
|
||||
if (xl->num_alloc_cntrs++ == xl->max_alloc_cntrs)
|
||||
return &emptyconstraint;
|
||||
|
||||
cx = c;
|
||||
|
||||
/*
|
||||
@ -2106,7 +2098,7 @@ static struct event_constraint *
|
||||
intel_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
|
||||
struct perf_event *event)
|
||||
{
|
||||
struct event_constraint *c1 = event->hw.constraint;
|
||||
struct event_constraint *c1 = cpuc->event_constraint[idx];
|
||||
struct event_constraint *c2;
|
||||
|
||||
/*
|
||||
@ -2150,6 +2142,11 @@ static void intel_put_excl_constraints(struct cpu_hw_events *cpuc,
|
||||
|
||||
xl = &excl_cntrs->states[tid];
|
||||
xlo = &excl_cntrs->states[o_tid];
|
||||
if (hwc->flags & PERF_X86_EVENT_EXCL_ACCT) {
|
||||
hwc->flags &= ~PERF_X86_EVENT_EXCL_ACCT;
|
||||
if (!--cpuc->n_excl)
|
||||
WRITE_ONCE(excl_cntrs->has_exclusive[tid], 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* put_constraint may be called from x86_schedule_events()
|
||||
@ -2188,8 +2185,6 @@ intel_put_shared_regs_event_constraints(struct cpu_hw_events *cpuc,
|
||||
static void intel_put_event_constraints(struct cpu_hw_events *cpuc,
|
||||
struct perf_event *event)
|
||||
{
|
||||
struct event_constraint *c = event->hw.constraint;
|
||||
|
||||
intel_put_shared_regs_event_constraints(cpuc, event);
|
||||
|
||||
/*
|
||||
@ -2197,19 +2192,14 @@ static void intel_put_event_constraints(struct cpu_hw_events *cpuc,
|
||||
* all events are subject to and must call the
|
||||
* put_excl_constraints() routine
|
||||
*/
|
||||
if (c && cpuc->excl_cntrs)
|
||||
if (cpuc->excl_cntrs)
|
||||
intel_put_excl_constraints(cpuc, event);
|
||||
|
||||
/* cleanup dynamic constraint */
|
||||
if (c && (c->flags & PERF_X86_EVENT_DYNAMIC))
|
||||
event->hw.constraint = NULL;
|
||||
}
|
||||
|
||||
static void intel_commit_scheduling(struct cpu_hw_events *cpuc,
|
||||
struct perf_event *event, int cntr)
|
||||
static void intel_commit_scheduling(struct cpu_hw_events *cpuc, int idx, int cntr)
|
||||
{
|
||||
struct intel_excl_cntrs *excl_cntrs = cpuc->excl_cntrs;
|
||||
struct event_constraint *c = event->hw.constraint;
|
||||
struct event_constraint *c = cpuc->event_constraint[idx];
|
||||
struct intel_excl_states *xlo, *xl;
|
||||
int tid = cpuc->excl_thread_id;
|
||||
int o_tid = 1 - tid;
|
||||
@ -2639,8 +2629,6 @@ static void intel_pmu_cpu_starting(int cpu)
|
||||
cpuc->lbr_sel = &cpuc->shared_regs->regs[EXTRA_REG_LBR];
|
||||
|
||||
if (x86_pmu.flags & PMU_FL_EXCL_CNTRS) {
|
||||
int h = x86_pmu.num_counters >> 1;
|
||||
|
||||
for_each_cpu(i, topology_thread_cpumask(cpu)) {
|
||||
struct intel_excl_cntrs *c;
|
||||
|
||||
@ -2654,11 +2642,6 @@ static void intel_pmu_cpu_starting(int cpu)
|
||||
}
|
||||
cpuc->excl_cntrs->core_id = core_id;
|
||||
cpuc->excl_cntrs->refcnt++;
|
||||
/*
|
||||
* set hard limit to half the number of generic counters
|
||||
*/
|
||||
cpuc->excl_cntrs->states[0].max_alloc_cntrs = h;
|
||||
cpuc->excl_cntrs->states[1].max_alloc_cntrs = h;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -706,9 +706,9 @@ void intel_pmu_pebs_disable(struct perf_event *event)
|
||||
|
||||
cpuc->pebs_enabled &= ~(1ULL << hwc->idx);
|
||||
|
||||
if (event->hw.constraint->flags & PERF_X86_EVENT_PEBS_LDLAT)
|
||||
if (event->hw.flags & PERF_X86_EVENT_PEBS_LDLAT)
|
||||
cpuc->pebs_enabled &= ~(1ULL << (hwc->idx + 32));
|
||||
else if (event->hw.constraint->flags & PERF_X86_EVENT_PEBS_ST)
|
||||
else if (event->hw.flags & PERF_X86_EVENT_PEBS_ST)
|
||||
cpuc->pebs_enabled &= ~(1ULL << 63);
|
||||
|
||||
if (cpuc->enabled)
|
||||
|
@ -151,7 +151,7 @@ static int __init pt_pmu_hw_init(void)
|
||||
|
||||
de_attr->attr.attr.name = pt_caps[i].name;
|
||||
|
||||
sysfs_attr_init(&de_attrs->attr.attr);
|
||||
sysfs_attr_init(&de_attr->attr.attr);
|
||||
|
||||
de_attr->attr.attr.mode = S_IRUGO;
|
||||
de_attr->attr.show = pt_cap_show;
|
||||
@ -615,7 +615,8 @@ static int pt_buffer_reset_markers(struct pt_buffer *buf,
|
||||
struct perf_output_handle *handle)
|
||||
|
||||
{
|
||||
unsigned long idx, npages, end;
|
||||
unsigned long head = local64_read(&buf->head);
|
||||
unsigned long idx, npages, wakeup;
|
||||
|
||||
if (buf->snapshot)
|
||||
return 0;
|
||||
@ -634,17 +635,26 @@ static int pt_buffer_reset_markers(struct pt_buffer *buf,
|
||||
buf->topa_index[buf->stop_pos]->stop = 0;
|
||||
buf->topa_index[buf->intr_pos]->intr = 0;
|
||||
|
||||
if (pt_cap_get(PT_CAP_topa_multiple_entries)) {
|
||||
npages = (handle->size + 1) >> PAGE_SHIFT;
|
||||
end = (local64_read(&buf->head) >> PAGE_SHIFT) + npages;
|
||||
/*if (end > handle->wakeup >> PAGE_SHIFT)
|
||||
end = handle->wakeup >> PAGE_SHIFT;*/
|
||||
idx = end & (buf->nr_pages - 1);
|
||||
buf->stop_pos = idx;
|
||||
idx = (local64_read(&buf->head) >> PAGE_SHIFT) + npages - 1;
|
||||
idx &= buf->nr_pages - 1;
|
||||
buf->intr_pos = idx;
|
||||
}
|
||||
/* how many pages till the STOP marker */
|
||||
npages = handle->size >> PAGE_SHIFT;
|
||||
|
||||
/* if it's on a page boundary, fill up one more page */
|
||||
if (!offset_in_page(head + handle->size + 1))
|
||||
npages++;
|
||||
|
||||
idx = (head >> PAGE_SHIFT) + npages;
|
||||
idx &= buf->nr_pages - 1;
|
||||
buf->stop_pos = idx;
|
||||
|
||||
wakeup = handle->wakeup >> PAGE_SHIFT;
|
||||
|
||||
/* in the worst case, wake up the consumer one page before hard stop */
|
||||
idx = (head >> PAGE_SHIFT) + npages - 1;
|
||||
if (idx > wakeup)
|
||||
idx = wakeup;
|
||||
|
||||
idx &= buf->nr_pages - 1;
|
||||
buf->intr_pos = idx;
|
||||
|
||||
buf->topa_index[buf->stop_pos]->stop = 1;
|
||||
buf->topa_index[buf->intr_pos]->intr = 1;
|
||||
|
@ -365,9 +365,8 @@ static int uncore_assign_events(struct intel_uncore_box *box, int assign[], int
|
||||
bitmap_zero(used_mask, UNCORE_PMC_IDX_MAX);
|
||||
|
||||
for (i = 0, wmin = UNCORE_PMC_IDX_MAX, wmax = 0; i < n; i++) {
|
||||
hwc = &box->event_list[i]->hw;
|
||||
c = uncore_get_event_constraint(box, box->event_list[i]);
|
||||
hwc->constraint = c;
|
||||
box->event_constraint[i] = c;
|
||||
wmin = min(wmin, c->weight);
|
||||
wmax = max(wmax, c->weight);
|
||||
}
|
||||
@ -375,7 +374,7 @@ static int uncore_assign_events(struct intel_uncore_box *box, int assign[], int
|
||||
/* fastpath, try to reuse previous register */
|
||||
for (i = 0; i < n; i++) {
|
||||
hwc = &box->event_list[i]->hw;
|
||||
c = hwc->constraint;
|
||||
c = box->event_constraint[i];
|
||||
|
||||
/* never assigned */
|
||||
if (hwc->idx == -1)
|
||||
@ -395,8 +394,8 @@ static int uncore_assign_events(struct intel_uncore_box *box, int assign[], int
|
||||
}
|
||||
/* slow path */
|
||||
if (i != n)
|
||||
ret = perf_assign_events(box->event_list, n,
|
||||
wmin, wmax, assign);
|
||||
ret = perf_assign_events(box->event_constraint, n,
|
||||
wmin, wmax, n, assign);
|
||||
|
||||
if (!assign || ret) {
|
||||
for (i = 0; i < n; i++)
|
||||
@ -840,6 +839,7 @@ static int uncore_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id
|
||||
box->phys_id = phys_id;
|
||||
box->pci_dev = pdev;
|
||||
box->pmu = pmu;
|
||||
uncore_box_init(box);
|
||||
pci_set_drvdata(pdev, box);
|
||||
|
||||
raw_spin_lock(&uncore_box_lock);
|
||||
@ -1003,8 +1003,10 @@ static int uncore_cpu_starting(int cpu)
|
||||
pmu = &type->pmus[j];
|
||||
box = *per_cpu_ptr(pmu->box, cpu);
|
||||
/* called by uncore_cpu_init? */
|
||||
if (box && box->phys_id >= 0)
|
||||
if (box && box->phys_id >= 0) {
|
||||
uncore_box_init(box);
|
||||
continue;
|
||||
}
|
||||
|
||||
for_each_online_cpu(k) {
|
||||
exist = *per_cpu_ptr(pmu->box, k);
|
||||
@ -1020,8 +1022,10 @@ static int uncore_cpu_starting(int cpu)
|
||||
}
|
||||
}
|
||||
|
||||
if (box)
|
||||
if (box) {
|
||||
box->phys_id = phys_id;
|
||||
uncore_box_init(box);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
@ -97,6 +97,7 @@ struct intel_uncore_box {
|
||||
atomic_t refcnt;
|
||||
struct perf_event *events[UNCORE_PMC_IDX_MAX];
|
||||
struct perf_event *event_list[UNCORE_PMC_IDX_MAX];
|
||||
struct event_constraint *event_constraint[UNCORE_PMC_IDX_MAX];
|
||||
unsigned long active_mask[BITS_TO_LONGS(UNCORE_PMC_IDX_MAX)];
|
||||
u64 tags[UNCORE_PMC_IDX_MAX];
|
||||
struct pci_dev *pci_dev;
|
||||
@ -257,14 +258,6 @@ static inline int uncore_num_counters(struct intel_uncore_box *box)
|
||||
return box->pmu->type->num_counters;
|
||||
}
|
||||
|
||||
static inline void uncore_box_init(struct intel_uncore_box *box)
|
||||
{
|
||||
if (!test_and_set_bit(UNCORE_BOX_FLAG_INITIATED, &box->flags)) {
|
||||
if (box->pmu->type->ops->init_box)
|
||||
box->pmu->type->ops->init_box(box);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void uncore_disable_box(struct intel_uncore_box *box)
|
||||
{
|
||||
if (box->pmu->type->ops->disable_box)
|
||||
@ -273,8 +266,6 @@ static inline void uncore_disable_box(struct intel_uncore_box *box)
|
||||
|
||||
static inline void uncore_enable_box(struct intel_uncore_box *box)
|
||||
{
|
||||
uncore_box_init(box);
|
||||
|
||||
if (box->pmu->type->ops->enable_box)
|
||||
box->pmu->type->ops->enable_box(box);
|
||||
}
|
||||
@ -297,6 +288,14 @@ static inline u64 uncore_read_counter(struct intel_uncore_box *box,
|
||||
return box->pmu->type->ops->read_counter(box, event);
|
||||
}
|
||||
|
||||
static inline void uncore_box_init(struct intel_uncore_box *box)
|
||||
{
|
||||
if (!test_and_set_bit(UNCORE_BOX_FLAG_INITIATED, &box->flags)) {
|
||||
if (box->pmu->type->ops->init_box)
|
||||
box->pmu->type->ops->init_box(box);
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool uncore_box_is_fake(struct intel_uncore_box *box)
|
||||
{
|
||||
return (box->phys_id < 0);
|
||||
|
@ -164,8 +164,8 @@
|
||||
((1ULL << (n)) - 1)))
|
||||
|
||||
/* Haswell-EP Ubox */
|
||||
#define HSWEP_U_MSR_PMON_CTR0 0x705
|
||||
#define HSWEP_U_MSR_PMON_CTL0 0x709
|
||||
#define HSWEP_U_MSR_PMON_CTR0 0x709
|
||||
#define HSWEP_U_MSR_PMON_CTL0 0x705
|
||||
#define HSWEP_U_MSR_PMON_FILTER 0x707
|
||||
|
||||
#define HSWEP_U_MSR_PMON_UCLK_FIXED_CTL 0x703
|
||||
@ -1914,7 +1914,7 @@ static struct intel_uncore_type hswep_uncore_cbox = {
|
||||
.name = "cbox",
|
||||
.num_counters = 4,
|
||||
.num_boxes = 18,
|
||||
.perf_ctr_bits = 44,
|
||||
.perf_ctr_bits = 48,
|
||||
.event_ctl = HSWEP_C0_MSR_PMON_CTL0,
|
||||
.perf_ctr = HSWEP_C0_MSR_PMON_CTR0,
|
||||
.event_mask = SNBEP_CBO_MSR_PMON_RAW_EVENT_MASK,
|
||||
|
@ -167,7 +167,7 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data)
|
||||
clear_bss();
|
||||
|
||||
for (i = 0; i < NUM_EXCEPTION_VECTORS; i++)
|
||||
set_intr_gate(i, early_idt_handlers[i]);
|
||||
set_intr_gate(i, early_idt_handler_array[i]);
|
||||
load_idt((const struct desc_ptr *)&idt_descr);
|
||||
|
||||
copy_bootdata(__va(real_mode_data));
|
||||
|
@ -478,21 +478,22 @@ is486:
|
||||
__INIT
|
||||
setup_once:
|
||||
/*
|
||||
* Set up a idt with 256 entries pointing to ignore_int,
|
||||
* interrupt gates. It doesn't actually load idt - that needs
|
||||
* to be done on each CPU. Interrupts are enabled elsewhere,
|
||||
* when we can be relatively sure everything is ok.
|
||||
* Set up a idt with 256 interrupt gates that push zero if there
|
||||
* is no error code and then jump to early_idt_handler_common.
|
||||
* It doesn't actually load the idt - that needs to be done on
|
||||
* each CPU. Interrupts are enabled elsewhere, when we can be
|
||||
* relatively sure everything is ok.
|
||||
*/
|
||||
|
||||
movl $idt_table,%edi
|
||||
movl $early_idt_handlers,%eax
|
||||
movl $early_idt_handler_array,%eax
|
||||
movl $NUM_EXCEPTION_VECTORS,%ecx
|
||||
1:
|
||||
movl %eax,(%edi)
|
||||
movl %eax,4(%edi)
|
||||
/* interrupt gate, dpl=0, present */
|
||||
movl $(0x8E000000 + __KERNEL_CS),2(%edi)
|
||||
addl $9,%eax
|
||||
addl $EARLY_IDT_HANDLER_SIZE,%eax
|
||||
addl $8,%edi
|
||||
loop 1b
|
||||
|
||||
@ -524,26 +525,28 @@ setup_once:
|
||||
andl $0,setup_once_ref /* Once is enough, thanks */
|
||||
ret
|
||||
|
||||
ENTRY(early_idt_handlers)
|
||||
ENTRY(early_idt_handler_array)
|
||||
# 36(%esp) %eflags
|
||||
# 32(%esp) %cs
|
||||
# 28(%esp) %eip
|
||||
# 24(%rsp) error code
|
||||
i = 0
|
||||
.rept NUM_EXCEPTION_VECTORS
|
||||
.if (EXCEPTION_ERRCODE_MASK >> i) & 1
|
||||
ASM_NOP2
|
||||
.else
|
||||
.ifeq (EXCEPTION_ERRCODE_MASK >> i) & 1
|
||||
pushl $0 # Dummy error code, to make stack frame uniform
|
||||
.endif
|
||||
pushl $i # 20(%esp) Vector number
|
||||
jmp early_idt_handler
|
||||
jmp early_idt_handler_common
|
||||
i = i + 1
|
||||
.fill early_idt_handler_array + i*EARLY_IDT_HANDLER_SIZE - ., 1, 0xcc
|
||||
.endr
|
||||
ENDPROC(early_idt_handlers)
|
||||
ENDPROC(early_idt_handler_array)
|
||||
|
||||
/* This is global to keep gas from relaxing the jumps */
|
||||
ENTRY(early_idt_handler)
|
||||
early_idt_handler_common:
|
||||
/*
|
||||
* The stack is the hardware frame, an error code or zero, and the
|
||||
* vector number.
|
||||
*/
|
||||
cld
|
||||
|
||||
cmpl $2,(%esp) # X86_TRAP_NMI
|
||||
@ -603,7 +606,7 @@ ex_entry:
|
||||
is_nmi:
|
||||
addl $8,%esp /* drop vector number and error code */
|
||||
iret
|
||||
ENDPROC(early_idt_handler)
|
||||
ENDPROC(early_idt_handler_common)
|
||||
|
||||
/* This is the default interrupt "handler" :-) */
|
||||
ALIGN
|
||||
|
@ -321,26 +321,28 @@ bad_address:
|
||||
jmp bad_address
|
||||
|
||||
__INIT
|
||||
.globl early_idt_handlers
|
||||
early_idt_handlers:
|
||||
ENTRY(early_idt_handler_array)
|
||||
# 104(%rsp) %rflags
|
||||
# 96(%rsp) %cs
|
||||
# 88(%rsp) %rip
|
||||
# 80(%rsp) error code
|
||||
i = 0
|
||||
.rept NUM_EXCEPTION_VECTORS
|
||||
.if (EXCEPTION_ERRCODE_MASK >> i) & 1
|
||||
ASM_NOP2
|
||||
.else
|
||||
.ifeq (EXCEPTION_ERRCODE_MASK >> i) & 1
|
||||
pushq $0 # Dummy error code, to make stack frame uniform
|
||||
.endif
|
||||
pushq $i # 72(%rsp) Vector number
|
||||
jmp early_idt_handler
|
||||
jmp early_idt_handler_common
|
||||
i = i + 1
|
||||
.fill early_idt_handler_array + i*EARLY_IDT_HANDLER_SIZE - ., 1, 0xcc
|
||||
.endr
|
||||
ENDPROC(early_idt_handler_array)
|
||||
|
||||
/* This is global to keep gas from relaxing the jumps */
|
||||
ENTRY(early_idt_handler)
|
||||
early_idt_handler_common:
|
||||
/*
|
||||
* The stack is the hardware frame, an error code or zero, and the
|
||||
* vector number.
|
||||
*/
|
||||
cld
|
||||
|
||||
cmpl $2,(%rsp) # X86_TRAP_NMI
|
||||
@ -412,7 +414,7 @@ ENTRY(early_idt_handler)
|
||||
is_nmi:
|
||||
addq $16,%rsp # drop vector number and error code
|
||||
INTERRUPT_RETURN
|
||||
ENDPROC(early_idt_handler)
|
||||
ENDPROC(early_idt_handler_common)
|
||||
|
||||
__INITDATA
|
||||
|
||||
|
@ -4215,13 +4215,13 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
|
||||
u64 entry, gentry, *spte;
|
||||
int npte;
|
||||
bool remote_flush, local_flush, zap_page;
|
||||
union kvm_mmu_page_role mask = (union kvm_mmu_page_role) {
|
||||
.cr0_wp = 1,
|
||||
.cr4_pae = 1,
|
||||
.nxe = 1,
|
||||
.smep_andnot_wp = 1,
|
||||
.smap_andnot_wp = 1,
|
||||
};
|
||||
union kvm_mmu_page_role mask = { };
|
||||
|
||||
mask.cr0_wp = 1;
|
||||
mask.cr4_pae = 1;
|
||||
mask.nxe = 1;
|
||||
mask.smep_andnot_wp = 1;
|
||||
mask.smap_andnot_wp = 1;
|
||||
|
||||
/*
|
||||
* If we don't have indirect shadow pages, it means no page is
|
||||
|
@ -1600,6 +1600,7 @@ static int blk_mq_hctx_notify(void *data, unsigned long action,
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
/* hctx->ctxs will be freed in queue's release handler */
|
||||
static void blk_mq_exit_hctx(struct request_queue *q,
|
||||
struct blk_mq_tag_set *set,
|
||||
struct blk_mq_hw_ctx *hctx, unsigned int hctx_idx)
|
||||
@ -1618,7 +1619,6 @@ static void blk_mq_exit_hctx(struct request_queue *q,
|
||||
|
||||
blk_mq_unregister_cpu_notifier(&hctx->cpu_notifier);
|
||||
blk_free_flush_queue(hctx->fq);
|
||||
kfree(hctx->ctxs);
|
||||
blk_mq_free_bitmap(&hctx->ctx_map);
|
||||
}
|
||||
|
||||
@ -1891,8 +1891,12 @@ void blk_mq_release(struct request_queue *q)
|
||||
unsigned int i;
|
||||
|
||||
/* hctx kobj stays in hctx */
|
||||
queue_for_each_hw_ctx(q, hctx, i)
|
||||
queue_for_each_hw_ctx(q, hctx, i) {
|
||||
if (!hctx)
|
||||
continue;
|
||||
kfree(hctx->ctxs);
|
||||
kfree(hctx);
|
||||
}
|
||||
|
||||
kfree(q->queue_hw_ctx);
|
||||
|
||||
|
@ -422,9 +422,9 @@ int blk_alloc_devt(struct hd_struct *part, dev_t *devt)
|
||||
/* allocate ext devt */
|
||||
idr_preload(GFP_KERNEL);
|
||||
|
||||
spin_lock(&ext_devt_lock);
|
||||
spin_lock_bh(&ext_devt_lock);
|
||||
idx = idr_alloc(&ext_devt_idr, part, 0, NR_EXT_DEVT, GFP_NOWAIT);
|
||||
spin_unlock(&ext_devt_lock);
|
||||
spin_unlock_bh(&ext_devt_lock);
|
||||
|
||||
idr_preload_end();
|
||||
if (idx < 0)
|
||||
@ -449,9 +449,9 @@ void blk_free_devt(dev_t devt)
|
||||
return;
|
||||
|
||||
if (MAJOR(devt) == BLOCK_EXT_MAJOR) {
|
||||
spin_lock(&ext_devt_lock);
|
||||
spin_lock_bh(&ext_devt_lock);
|
||||
idr_remove(&ext_devt_idr, blk_mangle_minor(MINOR(devt)));
|
||||
spin_unlock(&ext_devt_lock);
|
||||
spin_unlock_bh(&ext_devt_lock);
|
||||
}
|
||||
}
|
||||
|
||||
@ -653,7 +653,6 @@ void del_gendisk(struct gendisk *disk)
|
||||
disk->flags &= ~GENHD_FL_UP;
|
||||
|
||||
sysfs_remove_link(&disk_to_dev(disk)->kobj, "bdi");
|
||||
bdi_unregister(&disk->queue->backing_dev_info);
|
||||
blk_unregister_queue(disk);
|
||||
blk_unregister_region(disk_devt(disk), disk->minors);
|
||||
|
||||
@ -691,13 +690,13 @@ struct gendisk *get_gendisk(dev_t devt, int *partno)
|
||||
} else {
|
||||
struct hd_struct *part;
|
||||
|
||||
spin_lock(&ext_devt_lock);
|
||||
spin_lock_bh(&ext_devt_lock);
|
||||
part = idr_find(&ext_devt_idr, blk_mangle_minor(MINOR(devt)));
|
||||
if (part && get_disk(part_to_disk(part))) {
|
||||
*partno = part->partno;
|
||||
disk = part_to_disk(part);
|
||||
}
|
||||
spin_unlock(&ext_devt_lock);
|
||||
spin_unlock_bh(&ext_devt_lock);
|
||||
}
|
||||
|
||||
return disk;
|
||||
|
@ -45,7 +45,7 @@ static void ahci_mvebu_mbus_config(struct ahci_host_priv *hpriv,
|
||||
writel((cs->mbus_attr << 8) |
|
||||
(dram->mbus_dram_target_id << 4) | 1,
|
||||
hpriv->mmio + AHCI_WINDOW_CTRL(i));
|
||||
writel(cs->base, hpriv->mmio + AHCI_WINDOW_BASE(i));
|
||||
writel(cs->base >> 16, hpriv->mmio + AHCI_WINDOW_BASE(i));
|
||||
writel(((cs->size - 1) & 0xffff0000),
|
||||
hpriv->mmio + AHCI_WINDOW_SIZE(i));
|
||||
}
|
||||
|
@ -1053,7 +1053,7 @@ static struct of_device_id octeon_cf_match[] = {
|
||||
},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, octeon_i2c_match);
|
||||
MODULE_DEVICE_TABLE(of, octeon_cf_match);
|
||||
|
||||
static struct platform_driver octeon_cf_driver = {
|
||||
.probe = octeon_cf_probe,
|
||||
|
@ -179,7 +179,7 @@ static int detect_cache_attributes(unsigned int cpu)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (init_cache_level(cpu))
|
||||
if (init_cache_level(cpu) || !cache_leaves(cpu))
|
||||
return -ENOENT;
|
||||
|
||||
per_cpu_cacheinfo(cpu) = kcalloc(cache_leaves(cpu),
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <linux/device.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/memory.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include "base.h"
|
||||
|
||||
@ -34,4 +35,5 @@ void __init driver_init(void)
|
||||
cpu_dev_init();
|
||||
memory_dev_init();
|
||||
container_dev_init();
|
||||
of_core_init();
|
||||
}
|
||||
|
@ -406,6 +406,7 @@ config BLK_DEV_RAM_DAX
|
||||
|
||||
config BLK_DEV_PMEM
|
||||
tristate "Persistent memory block device support"
|
||||
depends on HAS_IOMEM
|
||||
help
|
||||
Saying Y here will allow you to use a contiguous range of reserved
|
||||
memory as one or more persistent block devices.
|
||||
|
@ -1750,6 +1750,7 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio)
|
||||
struct nvme_iod *iod;
|
||||
dma_addr_t meta_dma = 0;
|
||||
void *meta = NULL;
|
||||
void __user *metadata;
|
||||
|
||||
if (copy_from_user(&io, uio, sizeof(io)))
|
||||
return -EFAULT;
|
||||
@ -1763,6 +1764,8 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio)
|
||||
meta_len = 0;
|
||||
}
|
||||
|
||||
metadata = (void __user *)(unsigned long)io.metadata;
|
||||
|
||||
write = io.opcode & 1;
|
||||
|
||||
switch (io.opcode) {
|
||||
@ -1786,13 +1789,13 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio)
|
||||
if (meta_len) {
|
||||
meta = dma_alloc_coherent(&dev->pci_dev->dev, meta_len,
|
||||
&meta_dma, GFP_KERNEL);
|
||||
|
||||
if (!meta) {
|
||||
status = -ENOMEM;
|
||||
goto unmap;
|
||||
}
|
||||
if (write) {
|
||||
if (copy_from_user(meta, (void __user *)io.metadata,
|
||||
meta_len)) {
|
||||
if (copy_from_user(meta, metadata, meta_len)) {
|
||||
status = -EFAULT;
|
||||
goto unmap;
|
||||
}
|
||||
@ -1819,8 +1822,7 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio)
|
||||
nvme_free_iod(dev, iod);
|
||||
if (meta) {
|
||||
if (status == NVME_SC_SUCCESS && !write) {
|
||||
if (copy_to_user((void __user *)io.metadata, meta,
|
||||
meta_len))
|
||||
if (copy_to_user(metadata, meta, meta_len))
|
||||
status = -EFAULT;
|
||||
}
|
||||
dma_free_coherent(&dev->pci_dev->dev, meta_len, meta, meta_dma);
|
||||
|
@ -805,7 +805,9 @@ static void zram_reset_device(struct zram *zram)
|
||||
memset(&zram->stats, 0, sizeof(zram->stats));
|
||||
zram->disksize = 0;
|
||||
zram->max_comp_streams = 1;
|
||||
|
||||
set_capacity(zram->disk, 0);
|
||||
part_stat_set_all(&zram->disk->part0, 0);
|
||||
|
||||
up_write(&zram->init_lock);
|
||||
/* I/O operation under all of CPU are done so let's free */
|
||||
|
@ -58,7 +58,6 @@
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/syscore_ops.h>
|
||||
#include <linux/memblock.h>
|
||||
|
||||
/*
|
||||
* DDR target is the same on all platforms.
|
||||
@ -70,6 +69,7 @@
|
||||
*/
|
||||
#define WIN_CTRL_OFF 0x0000
|
||||
#define WIN_CTRL_ENABLE BIT(0)
|
||||
/* Only on HW I/O coherency capable platforms */
|
||||
#define WIN_CTRL_SYNCBARRIER BIT(1)
|
||||
#define WIN_CTRL_TGT_MASK 0xf0
|
||||
#define WIN_CTRL_TGT_SHIFT 4
|
||||
@ -102,9 +102,7 @@
|
||||
|
||||
/* Relative to mbusbridge_base */
|
||||
#define MBUS_BRIDGE_CTRL_OFF 0x0
|
||||
#define MBUS_BRIDGE_SIZE_MASK 0xffff0000
|
||||
#define MBUS_BRIDGE_BASE_OFF 0x4
|
||||
#define MBUS_BRIDGE_BASE_MASK 0xffff0000
|
||||
|
||||
/* Maximum number of windows, for all known platforms */
|
||||
#define MBUS_WINS_MAX 20
|
||||
@ -323,8 +321,9 @@ static int mvebu_mbus_setup_window(struct mvebu_mbus_state *mbus,
|
||||
ctrl = ((size - 1) & WIN_CTRL_SIZE_MASK) |
|
||||
(attr << WIN_CTRL_ATTR_SHIFT) |
|
||||
(target << WIN_CTRL_TGT_SHIFT) |
|
||||
WIN_CTRL_SYNCBARRIER |
|
||||
WIN_CTRL_ENABLE;
|
||||
if (mbus->hw_io_coherency)
|
||||
ctrl |= WIN_CTRL_SYNCBARRIER;
|
||||
|
||||
writel(base & WIN_BASE_LOW, addr + WIN_BASE_OFF);
|
||||
writel(ctrl, addr + WIN_CTRL_OFF);
|
||||
@ -577,106 +576,36 @@ static unsigned int armada_xp_mbus_win_remap_offset(int win)
|
||||
return MVEBU_MBUS_NO_REMAP;
|
||||
}
|
||||
|
||||
/*
|
||||
* Use the memblock information to find the MBus bridge hole in the
|
||||
* physical address space.
|
||||
*/
|
||||
static void __init
|
||||
mvebu_mbus_find_bridge_hole(uint64_t *start, uint64_t *end)
|
||||
{
|
||||
struct memblock_region *r;
|
||||
uint64_t s = 0;
|
||||
|
||||
for_each_memblock(memory, r) {
|
||||
/*
|
||||
* This part of the memory is above 4 GB, so we don't
|
||||
* care for the MBus bridge hole.
|
||||
*/
|
||||
if (r->base >= 0x100000000)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* The MBus bridge hole is at the end of the RAM under
|
||||
* the 4 GB limit.
|
||||
*/
|
||||
if (r->base + r->size > s)
|
||||
s = r->base + r->size;
|
||||
}
|
||||
|
||||
*start = s;
|
||||
*end = 0x100000000;
|
||||
}
|
||||
|
||||
static void __init
|
||||
mvebu_mbus_default_setup_cpu_target(struct mvebu_mbus_state *mbus)
|
||||
{
|
||||
int i;
|
||||
int cs;
|
||||
uint64_t mbus_bridge_base, mbus_bridge_end;
|
||||
|
||||
mvebu_mbus_dram_info.mbus_dram_target_id = TARGET_DDR;
|
||||
|
||||
mvebu_mbus_find_bridge_hole(&mbus_bridge_base, &mbus_bridge_end);
|
||||
|
||||
for (i = 0, cs = 0; i < 4; i++) {
|
||||
u64 base = readl(mbus->sdramwins_base + DDR_BASE_CS_OFF(i));
|
||||
u64 size = readl(mbus->sdramwins_base + DDR_SIZE_CS_OFF(i));
|
||||
u64 end;
|
||||
struct mbus_dram_window *w;
|
||||
|
||||
/* Ignore entries that are not enabled */
|
||||
if (!(size & DDR_SIZE_ENABLED))
|
||||
continue;
|
||||
u32 base = readl(mbus->sdramwins_base + DDR_BASE_CS_OFF(i));
|
||||
u32 size = readl(mbus->sdramwins_base + DDR_SIZE_CS_OFF(i));
|
||||
|
||||
/*
|
||||
* Ignore entries whose base address is above 2^32,
|
||||
* since devices cannot DMA to such high addresses
|
||||
* We only take care of entries for which the chip
|
||||
* select is enabled, and that don't have high base
|
||||
* address bits set (devices can only access the first
|
||||
* 32 bits of the memory).
|
||||
*/
|
||||
if (base & DDR_BASE_CS_HIGH_MASK)
|
||||
continue;
|
||||
if ((size & DDR_SIZE_ENABLED) &&
|
||||
!(base & DDR_BASE_CS_HIGH_MASK)) {
|
||||
struct mbus_dram_window *w;
|
||||
|
||||
base = base & DDR_BASE_CS_LOW_MASK;
|
||||
size = (size | ~DDR_SIZE_MASK) + 1;
|
||||
end = base + size;
|
||||
|
||||
/*
|
||||
* Adjust base/size of the current CS to make sure it
|
||||
* doesn't overlap with the MBus bridge hole. This is
|
||||
* particularly important for devices that do DMA from
|
||||
* DRAM to a SRAM mapped in a MBus window, such as the
|
||||
* CESA cryptographic engine.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The CS is fully enclosed inside the MBus bridge
|
||||
* area, so ignore it.
|
||||
*/
|
||||
if (base >= mbus_bridge_base && end <= mbus_bridge_end)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Beginning of CS overlaps with end of MBus, raise CS
|
||||
* base address, and shrink its size.
|
||||
*/
|
||||
if (base >= mbus_bridge_base && end > mbus_bridge_end) {
|
||||
size -= mbus_bridge_end - base;
|
||||
base = mbus_bridge_end;
|
||||
w = &mvebu_mbus_dram_info.cs[cs++];
|
||||
w->cs_index = i;
|
||||
w->mbus_attr = 0xf & ~(1 << i);
|
||||
if (mbus->hw_io_coherency)
|
||||
w->mbus_attr |= ATTR_HW_COHERENCY;
|
||||
w->base = base & DDR_BASE_CS_LOW_MASK;
|
||||
w->size = (size | ~DDR_SIZE_MASK) + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* End of CS overlaps with beginning of MBus, shrink
|
||||
* CS size.
|
||||
*/
|
||||
if (base < mbus_bridge_base && end > mbus_bridge_base)
|
||||
size -= end - mbus_bridge_base;
|
||||
|
||||
w = &mvebu_mbus_dram_info.cs[cs++];
|
||||
w->cs_index = i;
|
||||
w->mbus_attr = 0xf & ~(1 << i);
|
||||
if (mbus->hw_io_coherency)
|
||||
w->mbus_attr |= ATTR_HW_COHERENCY;
|
||||
w->base = base;
|
||||
w->size = size;
|
||||
}
|
||||
mvebu_mbus_dram_info.num_cs = cs;
|
||||
}
|
||||
|
@ -174,6 +174,8 @@
|
||||
#define AT_XDMAC_MBR_UBC_NDV3 (0x3 << 27) /* Next Descriptor View 3 */
|
||||
|
||||
#define AT_XDMAC_MAX_CHAN 0x20
|
||||
#define AT_XDMAC_MAX_CSIZE 16 /* 16 data */
|
||||
#define AT_XDMAC_MAX_DWIDTH 8 /* 64 bits */
|
||||
|
||||
#define AT_XDMAC_DMA_BUSWIDTHS\
|
||||
(BIT(DMA_SLAVE_BUSWIDTH_UNDEFINED) |\
|
||||
@ -192,20 +194,17 @@ struct at_xdmac_chan {
|
||||
struct dma_chan chan;
|
||||
void __iomem *ch_regs;
|
||||
u32 mask; /* Channel Mask */
|
||||
u32 cfg[2]; /* Channel Configuration Register */
|
||||
#define AT_XDMAC_DEV_TO_MEM_CFG 0 /* Predifined dev to mem channel conf */
|
||||
#define AT_XDMAC_MEM_TO_DEV_CFG 1 /* Predifined mem to dev channel conf */
|
||||
u32 cfg; /* Channel Configuration Register */
|
||||
u8 perid; /* Peripheral ID */
|
||||
u8 perif; /* Peripheral Interface */
|
||||
u8 memif; /* Memory Interface */
|
||||
u32 per_src_addr;
|
||||
u32 per_dst_addr;
|
||||
u32 save_cc;
|
||||
u32 save_cim;
|
||||
u32 save_cnda;
|
||||
u32 save_cndc;
|
||||
unsigned long status;
|
||||
struct tasklet_struct tasklet;
|
||||
struct dma_slave_config sconfig;
|
||||
|
||||
spinlock_t lock;
|
||||
|
||||
@ -415,8 +414,9 @@ static dma_cookie_t at_xdmac_tx_submit(struct dma_async_tx_descriptor *tx)
|
||||
struct at_xdmac_desc *desc = txd_to_at_desc(tx);
|
||||
struct at_xdmac_chan *atchan = to_at_xdmac_chan(tx->chan);
|
||||
dma_cookie_t cookie;
|
||||
unsigned long irqflags;
|
||||
|
||||
spin_lock_bh(&atchan->lock);
|
||||
spin_lock_irqsave(&atchan->lock, irqflags);
|
||||
cookie = dma_cookie_assign(tx);
|
||||
|
||||
dev_vdbg(chan2dev(tx->chan), "%s: atchan 0x%p, add desc 0x%p to xfers_list\n",
|
||||
@ -425,7 +425,7 @@ static dma_cookie_t at_xdmac_tx_submit(struct dma_async_tx_descriptor *tx)
|
||||
if (list_is_singular(&atchan->xfers_list))
|
||||
at_xdmac_start_xfer(atchan, desc);
|
||||
|
||||
spin_unlock_bh(&atchan->lock);
|
||||
spin_unlock_irqrestore(&atchan->lock, irqflags);
|
||||
return cookie;
|
||||
}
|
||||
|
||||
@ -494,61 +494,94 @@ static struct dma_chan *at_xdmac_xlate(struct of_phandle_args *dma_spec,
|
||||
return chan;
|
||||
}
|
||||
|
||||
static int at_xdmac_compute_chan_conf(struct dma_chan *chan,
|
||||
enum dma_transfer_direction direction)
|
||||
{
|
||||
struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan);
|
||||
int csize, dwidth;
|
||||
|
||||
if (direction == DMA_DEV_TO_MEM) {
|
||||
atchan->cfg =
|
||||
AT91_XDMAC_DT_PERID(atchan->perid)
|
||||
| AT_XDMAC_CC_DAM_INCREMENTED_AM
|
||||
| AT_XDMAC_CC_SAM_FIXED_AM
|
||||
| AT_XDMAC_CC_DIF(atchan->memif)
|
||||
| AT_XDMAC_CC_SIF(atchan->perif)
|
||||
| AT_XDMAC_CC_SWREQ_HWR_CONNECTED
|
||||
| AT_XDMAC_CC_DSYNC_PER2MEM
|
||||
| AT_XDMAC_CC_MBSIZE_SIXTEEN
|
||||
| AT_XDMAC_CC_TYPE_PER_TRAN;
|
||||
csize = ffs(atchan->sconfig.src_maxburst) - 1;
|
||||
if (csize < 0) {
|
||||
dev_err(chan2dev(chan), "invalid src maxburst value\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
atchan->cfg |= AT_XDMAC_CC_CSIZE(csize);
|
||||
dwidth = ffs(atchan->sconfig.src_addr_width) - 1;
|
||||
if (dwidth < 0) {
|
||||
dev_err(chan2dev(chan), "invalid src addr width value\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
atchan->cfg |= AT_XDMAC_CC_DWIDTH(dwidth);
|
||||
} else if (direction == DMA_MEM_TO_DEV) {
|
||||
atchan->cfg =
|
||||
AT91_XDMAC_DT_PERID(atchan->perid)
|
||||
| AT_XDMAC_CC_DAM_FIXED_AM
|
||||
| AT_XDMAC_CC_SAM_INCREMENTED_AM
|
||||
| AT_XDMAC_CC_DIF(atchan->perif)
|
||||
| AT_XDMAC_CC_SIF(atchan->memif)
|
||||
| AT_XDMAC_CC_SWREQ_HWR_CONNECTED
|
||||
| AT_XDMAC_CC_DSYNC_MEM2PER
|
||||
| AT_XDMAC_CC_MBSIZE_SIXTEEN
|
||||
| AT_XDMAC_CC_TYPE_PER_TRAN;
|
||||
csize = ffs(atchan->sconfig.dst_maxburst) - 1;
|
||||
if (csize < 0) {
|
||||
dev_err(chan2dev(chan), "invalid src maxburst value\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
atchan->cfg |= AT_XDMAC_CC_CSIZE(csize);
|
||||
dwidth = ffs(atchan->sconfig.dst_addr_width) - 1;
|
||||
if (dwidth < 0) {
|
||||
dev_err(chan2dev(chan), "invalid dst addr width value\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
atchan->cfg |= AT_XDMAC_CC_DWIDTH(dwidth);
|
||||
}
|
||||
|
||||
dev_dbg(chan2dev(chan), "%s: cfg=0x%08x\n", __func__, atchan->cfg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Only check that maxburst and addr width values are supported by the
|
||||
* the controller but not that the configuration is good to perform the
|
||||
* transfer since we don't know the direction at this stage.
|
||||
*/
|
||||
static int at_xdmac_check_slave_config(struct dma_slave_config *sconfig)
|
||||
{
|
||||
if ((sconfig->src_maxburst > AT_XDMAC_MAX_CSIZE)
|
||||
|| (sconfig->dst_maxburst > AT_XDMAC_MAX_CSIZE))
|
||||
return -EINVAL;
|
||||
|
||||
if ((sconfig->src_addr_width > AT_XDMAC_MAX_DWIDTH)
|
||||
|| (sconfig->dst_addr_width > AT_XDMAC_MAX_DWIDTH))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int at_xdmac_set_slave_config(struct dma_chan *chan,
|
||||
struct dma_slave_config *sconfig)
|
||||
{
|
||||
struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan);
|
||||
u8 dwidth;
|
||||
int csize;
|
||||
|
||||
atchan->cfg[AT_XDMAC_DEV_TO_MEM_CFG] =
|
||||
AT91_XDMAC_DT_PERID(atchan->perid)
|
||||
| AT_XDMAC_CC_DAM_INCREMENTED_AM
|
||||
| AT_XDMAC_CC_SAM_FIXED_AM
|
||||
| AT_XDMAC_CC_DIF(atchan->memif)
|
||||
| AT_XDMAC_CC_SIF(atchan->perif)
|
||||
| AT_XDMAC_CC_SWREQ_HWR_CONNECTED
|
||||
| AT_XDMAC_CC_DSYNC_PER2MEM
|
||||
| AT_XDMAC_CC_MBSIZE_SIXTEEN
|
||||
| AT_XDMAC_CC_TYPE_PER_TRAN;
|
||||
csize = at_xdmac_csize(sconfig->src_maxburst);
|
||||
if (csize < 0) {
|
||||
dev_err(chan2dev(chan), "invalid src maxburst value\n");
|
||||
if (at_xdmac_check_slave_config(sconfig)) {
|
||||
dev_err(chan2dev(chan), "invalid slave configuration\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
atchan->cfg[AT_XDMAC_DEV_TO_MEM_CFG] |= AT_XDMAC_CC_CSIZE(csize);
|
||||
dwidth = ffs(sconfig->src_addr_width) - 1;
|
||||
atchan->cfg[AT_XDMAC_DEV_TO_MEM_CFG] |= AT_XDMAC_CC_DWIDTH(dwidth);
|
||||
|
||||
|
||||
atchan->cfg[AT_XDMAC_MEM_TO_DEV_CFG] =
|
||||
AT91_XDMAC_DT_PERID(atchan->perid)
|
||||
| AT_XDMAC_CC_DAM_FIXED_AM
|
||||
| AT_XDMAC_CC_SAM_INCREMENTED_AM
|
||||
| AT_XDMAC_CC_DIF(atchan->perif)
|
||||
| AT_XDMAC_CC_SIF(atchan->memif)
|
||||
| AT_XDMAC_CC_SWREQ_HWR_CONNECTED
|
||||
| AT_XDMAC_CC_DSYNC_MEM2PER
|
||||
| AT_XDMAC_CC_MBSIZE_SIXTEEN
|
||||
| AT_XDMAC_CC_TYPE_PER_TRAN;
|
||||
csize = at_xdmac_csize(sconfig->dst_maxburst);
|
||||
if (csize < 0) {
|
||||
dev_err(chan2dev(chan), "invalid src maxburst value\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
atchan->cfg[AT_XDMAC_MEM_TO_DEV_CFG] |= AT_XDMAC_CC_CSIZE(csize);
|
||||
dwidth = ffs(sconfig->dst_addr_width) - 1;
|
||||
atchan->cfg[AT_XDMAC_MEM_TO_DEV_CFG] |= AT_XDMAC_CC_DWIDTH(dwidth);
|
||||
|
||||
/* Src and dst addr are needed to configure the link list descriptor. */
|
||||
atchan->per_src_addr = sconfig->src_addr;
|
||||
atchan->per_dst_addr = sconfig->dst_addr;
|
||||
|
||||
dev_dbg(chan2dev(chan),
|
||||
"%s: cfg[dev2mem]=0x%08x, cfg[mem2dev]=0x%08x, per_src_addr=0x%08x, per_dst_addr=0x%08x\n",
|
||||
__func__, atchan->cfg[AT_XDMAC_DEV_TO_MEM_CFG],
|
||||
atchan->cfg[AT_XDMAC_MEM_TO_DEV_CFG],
|
||||
atchan->per_src_addr, atchan->per_dst_addr);
|
||||
memcpy(&atchan->sconfig, sconfig, sizeof(atchan->sconfig));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -563,6 +596,8 @@ at_xdmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
|
||||
struct scatterlist *sg;
|
||||
int i;
|
||||
unsigned int xfer_size = 0;
|
||||
unsigned long irqflags;
|
||||
struct dma_async_tx_descriptor *ret = NULL;
|
||||
|
||||
if (!sgl)
|
||||
return NULL;
|
||||
@ -578,7 +613,10 @@ at_xdmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
|
||||
flags);
|
||||
|
||||
/* Protect dma_sconfig field that can be modified by set_slave_conf. */
|
||||
spin_lock_bh(&atchan->lock);
|
||||
spin_lock_irqsave(&atchan->lock, irqflags);
|
||||
|
||||
if (at_xdmac_compute_chan_conf(chan, direction))
|
||||
goto spin_unlock;
|
||||
|
||||
/* Prepare descriptors. */
|
||||
for_each_sg(sgl, sg, sg_len, i) {
|
||||
@ -589,8 +627,7 @@ at_xdmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
|
||||
mem = sg_dma_address(sg);
|
||||
if (unlikely(!len)) {
|
||||
dev_err(chan2dev(chan), "sg data length is zero\n");
|
||||
spin_unlock_bh(&atchan->lock);
|
||||
return NULL;
|
||||
goto spin_unlock;
|
||||
}
|
||||
dev_dbg(chan2dev(chan), "%s: * sg%d len=%u, mem=0x%08x\n",
|
||||
__func__, i, len, mem);
|
||||
@ -600,20 +637,18 @@ at_xdmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
|
||||
dev_err(chan2dev(chan), "can't get descriptor\n");
|
||||
if (first)
|
||||
list_splice_init(&first->descs_list, &atchan->free_descs_list);
|
||||
spin_unlock_bh(&atchan->lock);
|
||||
return NULL;
|
||||
goto spin_unlock;
|
||||
}
|
||||
|
||||
/* Linked list descriptor setup. */
|
||||
if (direction == DMA_DEV_TO_MEM) {
|
||||
desc->lld.mbr_sa = atchan->per_src_addr;
|
||||
desc->lld.mbr_sa = atchan->sconfig.src_addr;
|
||||
desc->lld.mbr_da = mem;
|
||||
desc->lld.mbr_cfg = atchan->cfg[AT_XDMAC_DEV_TO_MEM_CFG];
|
||||
} else {
|
||||
desc->lld.mbr_sa = mem;
|
||||
desc->lld.mbr_da = atchan->per_dst_addr;
|
||||
desc->lld.mbr_cfg = atchan->cfg[AT_XDMAC_MEM_TO_DEV_CFG];
|
||||
desc->lld.mbr_da = atchan->sconfig.dst_addr;
|
||||
}
|
||||
desc->lld.mbr_cfg = atchan->cfg;
|
||||
dwidth = at_xdmac_get_dwidth(desc->lld.mbr_cfg);
|
||||
fixed_dwidth = IS_ALIGNED(len, 1 << dwidth)
|
||||
? at_xdmac_get_dwidth(desc->lld.mbr_cfg)
|
||||
@ -645,13 +680,15 @@ at_xdmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
|
||||
xfer_size += len;
|
||||
}
|
||||
|
||||
spin_unlock_bh(&atchan->lock);
|
||||
|
||||
first->tx_dma_desc.flags = flags;
|
||||
first->xfer_size = xfer_size;
|
||||
first->direction = direction;
|
||||
ret = &first->tx_dma_desc;
|
||||
|
||||
return &first->tx_dma_desc;
|
||||
spin_unlock:
|
||||
spin_unlock_irqrestore(&atchan->lock, irqflags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct dma_async_tx_descriptor *
|
||||
@ -664,6 +701,7 @@ at_xdmac_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr,
|
||||
struct at_xdmac_desc *first = NULL, *prev = NULL;
|
||||
unsigned int periods = buf_len / period_len;
|
||||
int i;
|
||||
unsigned long irqflags;
|
||||
|
||||
dev_dbg(chan2dev(chan), "%s: buf_addr=%pad, buf_len=%zd, period_len=%zd, dir=%s, flags=0x%lx\n",
|
||||
__func__, &buf_addr, buf_len, period_len,
|
||||
@ -679,32 +717,34 @@ at_xdmac_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (at_xdmac_compute_chan_conf(chan, direction))
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < periods; i++) {
|
||||
struct at_xdmac_desc *desc = NULL;
|
||||
|
||||
spin_lock_bh(&atchan->lock);
|
||||
spin_lock_irqsave(&atchan->lock, irqflags);
|
||||
desc = at_xdmac_get_desc(atchan);
|
||||
if (!desc) {
|
||||
dev_err(chan2dev(chan), "can't get descriptor\n");
|
||||
if (first)
|
||||
list_splice_init(&first->descs_list, &atchan->free_descs_list);
|
||||
spin_unlock_bh(&atchan->lock);
|
||||
spin_unlock_irqrestore(&atchan->lock, irqflags);
|
||||
return NULL;
|
||||
}
|
||||
spin_unlock_bh(&atchan->lock);
|
||||
spin_unlock_irqrestore(&atchan->lock, irqflags);
|
||||
dev_dbg(chan2dev(chan),
|
||||
"%s: desc=0x%p, tx_dma_desc.phys=%pad\n",
|
||||
__func__, desc, &desc->tx_dma_desc.phys);
|
||||
|
||||
if (direction == DMA_DEV_TO_MEM) {
|
||||
desc->lld.mbr_sa = atchan->per_src_addr;
|
||||
desc->lld.mbr_sa = atchan->sconfig.src_addr;
|
||||
desc->lld.mbr_da = buf_addr + i * period_len;
|
||||
desc->lld.mbr_cfg = atchan->cfg[AT_XDMAC_DEV_TO_MEM_CFG];
|
||||
} else {
|
||||
desc->lld.mbr_sa = buf_addr + i * period_len;
|
||||
desc->lld.mbr_da = atchan->per_dst_addr;
|
||||
desc->lld.mbr_cfg = atchan->cfg[AT_XDMAC_MEM_TO_DEV_CFG];
|
||||
desc->lld.mbr_da = atchan->sconfig.dst_addr;
|
||||
}
|
||||
desc->lld.mbr_cfg = atchan->cfg;
|
||||
desc->lld.mbr_ubc = AT_XDMAC_MBR_UBC_NDV1
|
||||
| AT_XDMAC_MBR_UBC_NDEN
|
||||
| AT_XDMAC_MBR_UBC_NSEN
|
||||
@ -766,6 +806,7 @@ at_xdmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
|
||||
| AT_XDMAC_CC_SIF(0)
|
||||
| AT_XDMAC_CC_MBSIZE_SIXTEEN
|
||||
| AT_XDMAC_CC_TYPE_MEM_TRAN;
|
||||
unsigned long irqflags;
|
||||
|
||||
dev_dbg(chan2dev(chan), "%s: src=%pad, dest=%pad, len=%zd, flags=0x%lx\n",
|
||||
__func__, &src, &dest, len, flags);
|
||||
@ -798,9 +839,9 @@ at_xdmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
|
||||
|
||||
dev_dbg(chan2dev(chan), "%s: remaining_size=%zu\n", __func__, remaining_size);
|
||||
|
||||
spin_lock_bh(&atchan->lock);
|
||||
spin_lock_irqsave(&atchan->lock, irqflags);
|
||||
desc = at_xdmac_get_desc(atchan);
|
||||
spin_unlock_bh(&atchan->lock);
|
||||
spin_unlock_irqrestore(&atchan->lock, irqflags);
|
||||
if (!desc) {
|
||||
dev_err(chan2dev(chan), "can't get descriptor\n");
|
||||
if (first)
|
||||
@ -886,6 +927,7 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
|
||||
int residue;
|
||||
u32 cur_nda, mask, value;
|
||||
u8 dwidth = 0;
|
||||
unsigned long flags;
|
||||
|
||||
ret = dma_cookie_status(chan, cookie, txstate);
|
||||
if (ret == DMA_COMPLETE)
|
||||
@ -894,7 +936,7 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
|
||||
if (!txstate)
|
||||
return ret;
|
||||
|
||||
spin_lock_bh(&atchan->lock);
|
||||
spin_lock_irqsave(&atchan->lock, flags);
|
||||
|
||||
desc = list_first_entry(&atchan->xfers_list, struct at_xdmac_desc, xfer_node);
|
||||
|
||||
@ -904,8 +946,7 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
|
||||
*/
|
||||
if (!desc->active_xfer) {
|
||||
dma_set_residue(txstate, desc->xfer_size);
|
||||
spin_unlock_bh(&atchan->lock);
|
||||
return ret;
|
||||
goto spin_unlock;
|
||||
}
|
||||
|
||||
residue = desc->xfer_size;
|
||||
@ -936,14 +977,14 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
|
||||
}
|
||||
residue += at_xdmac_chan_read(atchan, AT_XDMAC_CUBC) << dwidth;
|
||||
|
||||
spin_unlock_bh(&atchan->lock);
|
||||
|
||||
dma_set_residue(txstate, residue);
|
||||
|
||||
dev_dbg(chan2dev(chan),
|
||||
"%s: desc=0x%p, tx_dma_desc.phys=%pad, tx_status=%d, cookie=%d, residue=%d\n",
|
||||
__func__, desc, &desc->tx_dma_desc.phys, ret, cookie, residue);
|
||||
|
||||
spin_unlock:
|
||||
spin_unlock_irqrestore(&atchan->lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -964,8 +1005,9 @@ static void at_xdmac_remove_xfer(struct at_xdmac_chan *atchan,
|
||||
static void at_xdmac_advance_work(struct at_xdmac_chan *atchan)
|
||||
{
|
||||
struct at_xdmac_desc *desc;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_bh(&atchan->lock);
|
||||
spin_lock_irqsave(&atchan->lock, flags);
|
||||
|
||||
/*
|
||||
* If channel is enabled, do nothing, advance_work will be triggered
|
||||
@ -980,7 +1022,7 @@ static void at_xdmac_advance_work(struct at_xdmac_chan *atchan)
|
||||
at_xdmac_start_xfer(atchan, desc);
|
||||
}
|
||||
|
||||
spin_unlock_bh(&atchan->lock);
|
||||
spin_unlock_irqrestore(&atchan->lock, flags);
|
||||
}
|
||||
|
||||
static void at_xdmac_handle_cyclic(struct at_xdmac_chan *atchan)
|
||||
@ -1116,12 +1158,13 @@ static int at_xdmac_device_config(struct dma_chan *chan,
|
||||
{
|
||||
struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan);
|
||||
int ret;
|
||||
unsigned long flags;
|
||||
|
||||
dev_dbg(chan2dev(chan), "%s\n", __func__);
|
||||
|
||||
spin_lock_bh(&atchan->lock);
|
||||
spin_lock_irqsave(&atchan->lock, flags);
|
||||
ret = at_xdmac_set_slave_config(chan, config);
|
||||
spin_unlock_bh(&atchan->lock);
|
||||
spin_unlock_irqrestore(&atchan->lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -1130,18 +1173,19 @@ static int at_xdmac_device_pause(struct dma_chan *chan)
|
||||
{
|
||||
struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan);
|
||||
struct at_xdmac *atxdmac = to_at_xdmac(atchan->chan.device);
|
||||
unsigned long flags;
|
||||
|
||||
dev_dbg(chan2dev(chan), "%s\n", __func__);
|
||||
|
||||
if (test_and_set_bit(AT_XDMAC_CHAN_IS_PAUSED, &atchan->status))
|
||||
return 0;
|
||||
|
||||
spin_lock_bh(&atchan->lock);
|
||||
spin_lock_irqsave(&atchan->lock, flags);
|
||||
at_xdmac_write(atxdmac, AT_XDMAC_GRWS, atchan->mask);
|
||||
while (at_xdmac_chan_read(atchan, AT_XDMAC_CC)
|
||||
& (AT_XDMAC_CC_WRIP | AT_XDMAC_CC_RDIP))
|
||||
cpu_relax();
|
||||
spin_unlock_bh(&atchan->lock);
|
||||
spin_unlock_irqrestore(&atchan->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1150,18 +1194,19 @@ static int at_xdmac_device_resume(struct dma_chan *chan)
|
||||
{
|
||||
struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan);
|
||||
struct at_xdmac *atxdmac = to_at_xdmac(atchan->chan.device);
|
||||
unsigned long flags;
|
||||
|
||||
dev_dbg(chan2dev(chan), "%s\n", __func__);
|
||||
|
||||
spin_lock_bh(&atchan->lock);
|
||||
spin_lock_irqsave(&atchan->lock, flags);
|
||||
if (!at_xdmac_chan_is_paused(atchan)) {
|
||||
spin_unlock_bh(&atchan->lock);
|
||||
spin_unlock_irqrestore(&atchan->lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
at_xdmac_write(atxdmac, AT_XDMAC_GRWR, atchan->mask);
|
||||
clear_bit(AT_XDMAC_CHAN_IS_PAUSED, &atchan->status);
|
||||
spin_unlock_bh(&atchan->lock);
|
||||
spin_unlock_irqrestore(&atchan->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1171,10 +1216,11 @@ static int at_xdmac_device_terminate_all(struct dma_chan *chan)
|
||||
struct at_xdmac_desc *desc, *_desc;
|
||||
struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan);
|
||||
struct at_xdmac *atxdmac = to_at_xdmac(atchan->chan.device);
|
||||
unsigned long flags;
|
||||
|
||||
dev_dbg(chan2dev(chan), "%s\n", __func__);
|
||||
|
||||
spin_lock_bh(&atchan->lock);
|
||||
spin_lock_irqsave(&atchan->lock, flags);
|
||||
at_xdmac_write(atxdmac, AT_XDMAC_GD, atchan->mask);
|
||||
while (at_xdmac_read(atxdmac, AT_XDMAC_GS) & atchan->mask)
|
||||
cpu_relax();
|
||||
@ -1184,7 +1230,7 @@ static int at_xdmac_device_terminate_all(struct dma_chan *chan)
|
||||
at_xdmac_remove_xfer(atchan, desc);
|
||||
|
||||
clear_bit(AT_XDMAC_CHAN_IS_CYCLIC, &atchan->status);
|
||||
spin_unlock_bh(&atchan->lock);
|
||||
spin_unlock_irqrestore(&atchan->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1194,8 +1240,9 @@ static int at_xdmac_alloc_chan_resources(struct dma_chan *chan)
|
||||
struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan);
|
||||
struct at_xdmac_desc *desc;
|
||||
int i;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_bh(&atchan->lock);
|
||||
spin_lock_irqsave(&atchan->lock, flags);
|
||||
|
||||
if (at_xdmac_chan_is_enabled(atchan)) {
|
||||
dev_err(chan2dev(chan),
|
||||
@ -1226,7 +1273,7 @@ static int at_xdmac_alloc_chan_resources(struct dma_chan *chan)
|
||||
dev_dbg(chan2dev(chan), "%s: allocated %d descriptors\n", __func__, i);
|
||||
|
||||
spin_unlock:
|
||||
spin_unlock_bh(&atchan->lock);
|
||||
spin_unlock_irqrestore(&atchan->lock, flags);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
@ -487,7 +487,11 @@ int dma_get_slave_caps(struct dma_chan *chan, struct dma_slave_caps *caps)
|
||||
caps->directions = device->directions;
|
||||
caps->residue_granularity = device->residue_granularity;
|
||||
|
||||
caps->cmd_pause = !!device->device_pause;
|
||||
/*
|
||||
* Some devices implement only pause (e.g. to get residuum) but no
|
||||
* resume. However cmd_pause is advertised as pause AND resume.
|
||||
*/
|
||||
caps->cmd_pause = !!(device->device_pause && device->device_resume);
|
||||
caps->cmd_terminate = !!device->device_terminate_all;
|
||||
|
||||
return 0;
|
||||
|
@ -384,7 +384,10 @@ static int hsu_dma_terminate_all(struct dma_chan *chan)
|
||||
spin_lock_irqsave(&hsuc->vchan.lock, flags);
|
||||
|
||||
hsu_dma_stop_channel(hsuc);
|
||||
hsuc->desc = NULL;
|
||||
if (hsuc->desc) {
|
||||
hsu_dma_desc_free(&hsuc->desc->vdesc);
|
||||
hsuc->desc = NULL;
|
||||
}
|
||||
|
||||
vchan_get_all_descriptors(&hsuc->vchan, &head);
|
||||
spin_unlock_irqrestore(&hsuc->vchan.lock, flags);
|
||||
|
@ -2127,6 +2127,7 @@ static int pl330_terminate_all(struct dma_chan *chan)
|
||||
struct pl330_dmac *pl330 = pch->dmac;
|
||||
LIST_HEAD(list);
|
||||
|
||||
pm_runtime_get_sync(pl330->ddma.dev);
|
||||
spin_lock_irqsave(&pch->lock, flags);
|
||||
spin_lock(&pl330->lock);
|
||||
_stop(pch->thread);
|
||||
@ -2151,6 +2152,8 @@ static int pl330_terminate_all(struct dma_chan *chan)
|
||||
list_splice_tail_init(&pch->work_list, &pl330->desc_pool);
|
||||
list_splice_tail_init(&pch->completed_list, &pl330->desc_pool);
|
||||
spin_unlock_irqrestore(&pch->lock, flags);
|
||||
pm_runtime_mark_last_busy(pl330->ddma.dev);
|
||||
pm_runtime_put_autosuspend(pl330->ddma.dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -186,8 +186,20 @@ struct ibft_kobject {
|
||||
|
||||
static struct iscsi_boot_kset *boot_kset;
|
||||
|
||||
/* fully null address */
|
||||
static const char nulls[16];
|
||||
|
||||
/* IPv4-mapped IPv6 ::ffff:0.0.0.0 */
|
||||
static const char mapped_nulls[16] = { 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
static int address_not_null(u8 *ip)
|
||||
{
|
||||
return (memcmp(ip, nulls, 16) && memcmp(ip, mapped_nulls, 16));
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper functions to parse data properly.
|
||||
*/
|
||||
@ -445,7 +457,7 @@ static umode_t ibft_check_nic_for(void *data, int type)
|
||||
rc = S_IRUGO;
|
||||
break;
|
||||
case ISCSI_BOOT_ETH_IP_ADDR:
|
||||
if (memcmp(nic->ip_addr, nulls, sizeof(nic->ip_addr)))
|
||||
if (address_not_null(nic->ip_addr))
|
||||
rc = S_IRUGO;
|
||||
break;
|
||||
case ISCSI_BOOT_ETH_SUBNET_MASK:
|
||||
@ -456,21 +468,19 @@ static umode_t ibft_check_nic_for(void *data, int type)
|
||||
rc = S_IRUGO;
|
||||
break;
|
||||
case ISCSI_BOOT_ETH_GATEWAY:
|
||||
if (memcmp(nic->gateway, nulls, sizeof(nic->gateway)))
|
||||
if (address_not_null(nic->gateway))
|
||||
rc = S_IRUGO;
|
||||
break;
|
||||
case ISCSI_BOOT_ETH_PRIMARY_DNS:
|
||||
if (memcmp(nic->primary_dns, nulls,
|
||||
sizeof(nic->primary_dns)))
|
||||
if (address_not_null(nic->primary_dns))
|
||||
rc = S_IRUGO;
|
||||
break;
|
||||
case ISCSI_BOOT_ETH_SECONDARY_DNS:
|
||||
if (memcmp(nic->secondary_dns, nulls,
|
||||
sizeof(nic->secondary_dns)))
|
||||
if (address_not_null(nic->secondary_dns))
|
||||
rc = S_IRUGO;
|
||||
break;
|
||||
case ISCSI_BOOT_ETH_DHCP:
|
||||
if (memcmp(nic->dhcp, nulls, sizeof(nic->dhcp)))
|
||||
if (address_not_null(nic->dhcp))
|
||||
rc = S_IRUGO;
|
||||
break;
|
||||
case ISCSI_BOOT_ETH_VLAN:
|
||||
@ -536,23 +546,19 @@ static umode_t __init ibft_check_initiator_for(void *data, int type)
|
||||
rc = S_IRUGO;
|
||||
break;
|
||||
case ISCSI_BOOT_INI_ISNS_SERVER:
|
||||
if (memcmp(init->isns_server, nulls,
|
||||
sizeof(init->isns_server)))
|
||||
if (address_not_null(init->isns_server))
|
||||
rc = S_IRUGO;
|
||||
break;
|
||||
case ISCSI_BOOT_INI_SLP_SERVER:
|
||||
if (memcmp(init->slp_server, nulls,
|
||||
sizeof(init->slp_server)))
|
||||
if (address_not_null(init->slp_server))
|
||||
rc = S_IRUGO;
|
||||
break;
|
||||
case ISCSI_BOOT_INI_PRI_RADIUS_SERVER:
|
||||
if (memcmp(init->pri_radius_server, nulls,
|
||||
sizeof(init->pri_radius_server)))
|
||||
if (address_not_null(init->pri_radius_server))
|
||||
rc = S_IRUGO;
|
||||
break;
|
||||
case ISCSI_BOOT_INI_SEC_RADIUS_SERVER:
|
||||
if (memcmp(init->sec_radius_server, nulls,
|
||||
sizeof(init->sec_radius_server)))
|
||||
if (address_not_null(init->sec_radius_server))
|
||||
rc = S_IRUGO;
|
||||
break;
|
||||
case ISCSI_BOOT_INI_INITIATOR_NAME:
|
||||
|
@ -684,8 +684,6 @@ static ssize_t node_show(struct kobject *kobj, struct attribute *attr,
|
||||
dev->node_props.cpu_core_id_base);
|
||||
sysfs_show_32bit_prop(buffer, "simd_id_base",
|
||||
dev->node_props.simd_id_base);
|
||||
sysfs_show_32bit_prop(buffer, "capability",
|
||||
dev->node_props.capability);
|
||||
sysfs_show_32bit_prop(buffer, "max_waves_per_simd",
|
||||
dev->node_props.max_waves_per_simd);
|
||||
sysfs_show_32bit_prop(buffer, "lds_size_in_kb",
|
||||
@ -736,6 +734,8 @@ static ssize_t node_show(struct kobject *kobj, struct attribute *attr,
|
||||
dev->gpu->kfd2kgd->get_fw_version(
|
||||
dev->gpu->kgd,
|
||||
KGD_ENGINE_MEC1));
|
||||
sysfs_show_32bit_prop(buffer, "capability",
|
||||
dev->node_props.capability);
|
||||
}
|
||||
|
||||
return sysfs_show_32bit_prop(buffer, "max_engine_clk_ccompute",
|
||||
|
@ -217,7 +217,7 @@ static ssize_t status_store(struct device *device,
|
||||
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
|
||||
return ret;
|
||||
return ret ? ret : count;
|
||||
}
|
||||
|
||||
static ssize_t status_show(struct device *device,
|
||||
|
@ -1667,12 +1667,15 @@ static int i915_sr_status(struct seq_file *m, void *unused)
|
||||
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
sr_enabled = I915_READ(WM1_LP_ILK) & WM1_LP_SR_EN;
|
||||
else if (IS_CRESTLINE(dev) || IS_I945G(dev) || IS_I945GM(dev))
|
||||
else if (IS_CRESTLINE(dev) || IS_G4X(dev) ||
|
||||
IS_I945G(dev) || IS_I945GM(dev))
|
||||
sr_enabled = I915_READ(FW_BLC_SELF) & FW_BLC_SELF_EN;
|
||||
else if (IS_I915GM(dev))
|
||||
sr_enabled = I915_READ(INSTPM) & INSTPM_SELF_EN;
|
||||
else if (IS_PINEVIEW(dev))
|
||||
sr_enabled = I915_READ(DSPFW3) & PINEVIEW_SELF_REFRESH_EN;
|
||||
else if (IS_VALLEYVIEW(dev))
|
||||
sr_enabled = I915_READ(FW_BLC_SELF_VLV) & FW_CSPWRDWNEN;
|
||||
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
|
||||
|
@ -2656,9 +2656,6 @@ void i915_gem_reset(struct drm_device *dev)
|
||||
void
|
||||
i915_gem_retire_requests_ring(struct intel_engine_cs *ring)
|
||||
{
|
||||
if (list_empty(&ring->request_list))
|
||||
return;
|
||||
|
||||
WARN_ON(i915_verify_lists(ring->dev));
|
||||
|
||||
/* Retire requests first as we use it above for the early return.
|
||||
|
@ -880,10 +880,8 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
|
||||
DP_AUX_CH_CTL_RECEIVE_ERROR))
|
||||
continue;
|
||||
if (status & DP_AUX_CH_CTL_DONE)
|
||||
break;
|
||||
goto done;
|
||||
}
|
||||
if (status & DP_AUX_CH_CTL_DONE)
|
||||
break;
|
||||
}
|
||||
|
||||
if ((status & DP_AUX_CH_CTL_DONE) == 0) {
|
||||
@ -892,6 +890,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
|
||||
goto out;
|
||||
}
|
||||
|
||||
done:
|
||||
/* Check for timeout or receive error.
|
||||
* Timeouts occur when the sink is not connected
|
||||
*/
|
||||
|
@ -435,7 +435,7 @@ gmbus_xfer(struct i2c_adapter *adapter,
|
||||
struct intel_gmbus,
|
||||
adapter);
|
||||
struct drm_i915_private *dev_priv = bus->dev_priv;
|
||||
int i, reg_offset;
|
||||
int i = 0, inc, try = 0, reg_offset;
|
||||
int ret = 0;
|
||||
|
||||
intel_aux_display_runtime_get(dev_priv);
|
||||
@ -448,12 +448,14 @@ gmbus_xfer(struct i2c_adapter *adapter,
|
||||
|
||||
reg_offset = dev_priv->gpio_mmio_base;
|
||||
|
||||
retry:
|
||||
I915_WRITE(GMBUS0 + reg_offset, bus->reg0);
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
for (; i < num; i += inc) {
|
||||
inc = 1;
|
||||
if (gmbus_is_index_read(msgs, i, num)) {
|
||||
ret = gmbus_xfer_index_read(dev_priv, &msgs[i]);
|
||||
i += 1; /* set i to the index of the read xfer */
|
||||
inc = 2; /* an index read is two msgs */
|
||||
} else if (msgs[i].flags & I2C_M_RD) {
|
||||
ret = gmbus_xfer_read(dev_priv, &msgs[i], 0);
|
||||
} else {
|
||||
@ -525,6 +527,18 @@ clear_err:
|
||||
adapter->name, msgs[i].addr,
|
||||
(msgs[i].flags & I2C_M_RD) ? 'r' : 'w', msgs[i].len);
|
||||
|
||||
/*
|
||||
* Passive adapters sometimes NAK the first probe. Retry the first
|
||||
* message once on -ENXIO for GMBUS transfers; the bit banging algorithm
|
||||
* has retries internally. See also the retry loop in
|
||||
* drm_do_probe_ddc_edid, which bails out on the first -ENXIO.
|
||||
*/
|
||||
if (ret == -ENXIO && i == 0 && try++ == 0) {
|
||||
DRM_DEBUG_KMS("GMBUS [%s] NAK on first message, retry\n",
|
||||
adapter->name);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
goto out;
|
||||
|
||||
timeout:
|
||||
|
@ -1134,6 +1134,12 @@ static int gen8_init_common_ring(struct intel_engine_cs *ring)
|
||||
I915_WRITE_IMR(ring, ~(ring->irq_enable_mask | ring->irq_keep_mask));
|
||||
I915_WRITE(RING_HWSTAM(ring->mmio_base), 0xffffffff);
|
||||
|
||||
if (ring->status_page.obj) {
|
||||
I915_WRITE(RING_HWS_PGA(ring->mmio_base),
|
||||
(u32)ring->status_page.gfx_addr);
|
||||
POSTING_READ(RING_HWS_PGA(ring->mmio_base));
|
||||
}
|
||||
|
||||
I915_WRITE(RING_MODE_GEN7(ring),
|
||||
_MASKED_BIT_DISABLE(GFX_REPLAY_MODE) |
|
||||
_MASKED_BIT_ENABLE(GFX_RUN_LIST_ENABLE));
|
||||
|
@ -901,13 +901,6 @@ static int chv_init_workarounds(struct intel_engine_cs *ring)
|
||||
GEN6_WIZ_HASHING_MASK,
|
||||
GEN6_WIZ_HASHING_16x4);
|
||||
|
||||
if (INTEL_REVID(dev) == SKL_REVID_C0 ||
|
||||
INTEL_REVID(dev) == SKL_REVID_D0)
|
||||
/* WaBarrierPerformanceFixDisable:skl */
|
||||
WA_SET_BIT_MASKED(HDC_CHICKEN0,
|
||||
HDC_FENCE_DEST_SLM_DISABLE |
|
||||
HDC_BARRIER_PERFORMANCE_DISABLE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1024,6 +1017,13 @@ static int skl_init_workarounds(struct intel_engine_cs *ring)
|
||||
WA_SET_BIT_MASKED(HIZ_CHICKEN,
|
||||
BDW_HIZ_POWER_COMPILER_CLOCK_GATING_DISABLE);
|
||||
|
||||
if (INTEL_REVID(dev) == SKL_REVID_C0 ||
|
||||
INTEL_REVID(dev) == SKL_REVID_D0)
|
||||
/* WaBarrierPerformanceFixDisable:skl */
|
||||
WA_SET_BIT_MASKED(HDC_CHICKEN0,
|
||||
HDC_FENCE_DEST_SLM_DISABLE |
|
||||
HDC_BARRIER_PERFORMANCE_DISABLE);
|
||||
|
||||
return skl_tune_iz_hashing(ring);
|
||||
}
|
||||
|
||||
|
@ -2550,7 +2550,7 @@ intel_sdvo_analog_init(struct intel_sdvo *intel_sdvo, int device)
|
||||
|
||||
DRM_DEBUG_KMS("initialising analog device %d\n", device);
|
||||
|
||||
intel_sdvo_connector = kzalloc(sizeof(*intel_sdvo_connector), GFP_KERNEL);
|
||||
intel_sdvo_connector = intel_sdvo_connector_alloc();
|
||||
if (!intel_sdvo_connector)
|
||||
return false;
|
||||
|
||||
|
@ -580,9 +580,6 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
|
||||
else
|
||||
radeon_crtc->pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
|
||||
|
||||
/* if there is no audio, set MINM_OVER_MAXP */
|
||||
if (!drm_detect_monitor_audio(radeon_connector_edid(connector)))
|
||||
radeon_crtc->pll_flags |= RADEON_PLL_PREFER_MINM_OVER_MAXP;
|
||||
if (rdev->family < CHIP_RV770)
|
||||
radeon_crtc->pll_flags |= RADEON_PLL_PREFER_MINM_OVER_MAXP;
|
||||
/* use frac fb div on APUs */
|
||||
@ -1798,9 +1795,7 @@ static int radeon_get_shared_nondp_ppll(struct drm_crtc *crtc)
|
||||
if ((crtc->mode.clock == test_crtc->mode.clock) &&
|
||||
(adjusted_clock == test_adjusted_clock) &&
|
||||
(radeon_crtc->ss_enabled == test_radeon_crtc->ss_enabled) &&
|
||||
(test_radeon_crtc->pll_id != ATOM_PPLL_INVALID) &&
|
||||
(drm_detect_monitor_audio(radeon_connector_edid(test_radeon_crtc->connector)) ==
|
||||
drm_detect_monitor_audio(radeon_connector_edid(radeon_crtc->connector))))
|
||||
(test_radeon_crtc->pll_id != ATOM_PPLL_INVALID))
|
||||
return test_radeon_crtc->pll_id;
|
||||
}
|
||||
}
|
||||
|
@ -173,7 +173,7 @@ void dce3_2_hdmi_update_acr(struct drm_encoder *encoder, long offset,
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
|
||||
WREG32(HDMI0_ACR_PACKET_CONTROL + offset,
|
||||
WREG32(DCE3_HDMI0_ACR_PACKET_CONTROL + offset,
|
||||
HDMI0_ACR_SOURCE | /* select SW CTS value */
|
||||
HDMI0_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */
|
||||
|
||||
|
@ -1463,6 +1463,21 @@ int radeon_device_init(struct radeon_device *rdev,
|
||||
if (r)
|
||||
DRM_ERROR("ib ring test failed (%d).\n", r);
|
||||
|
||||
/*
|
||||
* Turks/Thames GPU will freeze whole laptop if DPM is not restarted
|
||||
* after the CP ring have chew one packet at least. Hence here we stop
|
||||
* and restart DPM after the radeon_ib_ring_tests().
|
||||
*/
|
||||
if (rdev->pm.dpm_enabled &&
|
||||
(rdev->pm.pm_method == PM_METHOD_DPM) &&
|
||||
(rdev->family == CHIP_TURKS) &&
|
||||
(rdev->flags & RADEON_IS_MOBILITY)) {
|
||||
mutex_lock(&rdev->pm.mutex);
|
||||
radeon_dpm_disable(rdev);
|
||||
radeon_dpm_enable(rdev);
|
||||
mutex_unlock(&rdev->pm.mutex);
|
||||
}
|
||||
|
||||
if ((radeon_testing & 1)) {
|
||||
if (rdev->accel_working)
|
||||
radeon_test_moves(rdev);
|
||||
|
@ -458,14 +458,16 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev,
|
||||
/* make sure object fit at this offset */
|
||||
eoffset = soffset + size;
|
||||
if (soffset >= eoffset) {
|
||||
return -EINVAL;
|
||||
r = -EINVAL;
|
||||
goto error_unreserve;
|
||||
}
|
||||
|
||||
last_pfn = eoffset / RADEON_GPU_PAGE_SIZE;
|
||||
if (last_pfn > rdev->vm_manager.max_pfn) {
|
||||
dev_err(rdev->dev, "va above limit (0x%08X > 0x%08X)\n",
|
||||
last_pfn, rdev->vm_manager.max_pfn);
|
||||
return -EINVAL;
|
||||
r = -EINVAL;
|
||||
goto error_unreserve;
|
||||
}
|
||||
|
||||
} else {
|
||||
@ -486,7 +488,8 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev,
|
||||
"(bo %p 0x%010lx 0x%010lx)\n", bo_va->bo,
|
||||
soffset, tmp->bo, tmp->it.start, tmp->it.last);
|
||||
mutex_unlock(&vm->mutex);
|
||||
return -EINVAL;
|
||||
r = -EINVAL;
|
||||
goto error_unreserve;
|
||||
}
|
||||
}
|
||||
|
||||
@ -497,7 +500,8 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev,
|
||||
tmp = kzalloc(sizeof(struct radeon_bo_va), GFP_KERNEL);
|
||||
if (!tmp) {
|
||||
mutex_unlock(&vm->mutex);
|
||||
return -ENOMEM;
|
||||
r = -ENOMEM;
|
||||
goto error_unreserve;
|
||||
}
|
||||
tmp->it.start = bo_va->it.start;
|
||||
tmp->it.last = bo_va->it.last;
|
||||
@ -555,7 +559,6 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev,
|
||||
r = radeon_vm_clear_bo(rdev, pt);
|
||||
if (r) {
|
||||
radeon_bo_unref(&pt);
|
||||
radeon_bo_reserve(bo_va->bo, false);
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -575,6 +578,10 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev,
|
||||
|
||||
mutex_unlock(&vm->mutex);
|
||||
return 0;
|
||||
|
||||
error_unreserve:
|
||||
radeon_bo_unreserve(bo_va->bo);
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -554,4 +554,4 @@ module_platform_driver(hix5hd2_i2c_driver);
|
||||
MODULE_DESCRIPTION("Hix5hd2 I2C Bus driver");
|
||||
MODULE_AUTHOR("Wei Yan <sledge.yanwei@huawei.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:i2c-hix5hd2");
|
||||
MODULE_ALIAS("platform:hix5hd2-i2c");
|
||||
|
@ -1143,6 +1143,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
|
||||
return -ENOMEM;
|
||||
|
||||
i2c->quirks = s3c24xx_get_device_quirks(pdev);
|
||||
i2c->sysreg = ERR_PTR(-ENOENT);
|
||||
if (pdata)
|
||||
memcpy(i2c->pdata, pdata, sizeof(*pdata));
|
||||
else
|
||||
|
@ -1001,7 +1001,7 @@ static struct platform_driver twl6030_gpadc_driver = {
|
||||
|
||||
module_platform_driver(twl6030_gpadc_driver);
|
||||
|
||||
MODULE_ALIAS("platform: " DRIVER_NAME);
|
||||
MODULE_ALIAS("platform:" DRIVER_NAME);
|
||||
MODULE_AUTHOR("Balaji T K <balajitk@ti.com>");
|
||||
MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>");
|
||||
MODULE_AUTHOR("Oleksandr Kozaruk <oleksandr.kozaruk@ti.com");
|
||||
|
@ -139,6 +139,7 @@
|
||||
#define ADIS16400_NO_BURST BIT(1)
|
||||
#define ADIS16400_HAS_SLOW_MODE BIT(2)
|
||||
#define ADIS16400_HAS_SERIAL_NUMBER BIT(3)
|
||||
#define ADIS16400_BURST_DIAG_STAT BIT(4)
|
||||
|
||||
struct adis16400_state;
|
||||
|
||||
@ -165,6 +166,7 @@ struct adis16400_state {
|
||||
int filt_int;
|
||||
|
||||
struct adis adis;
|
||||
unsigned long avail_scan_mask[2];
|
||||
};
|
||||
|
||||
/* At the moment triggers are only used for ring buffer
|
||||
|
@ -18,7 +18,8 @@ int adis16400_update_scan_mode(struct iio_dev *indio_dev,
|
||||
{
|
||||
struct adis16400_state *st = iio_priv(indio_dev);
|
||||
struct adis *adis = &st->adis;
|
||||
uint16_t *tx;
|
||||
unsigned int burst_length;
|
||||
u8 *tx;
|
||||
|
||||
if (st->variant->flags & ADIS16400_NO_BURST)
|
||||
return adis_update_scan_mode(indio_dev, scan_mask);
|
||||
@ -26,26 +27,29 @@ int adis16400_update_scan_mode(struct iio_dev *indio_dev,
|
||||
kfree(adis->xfer);
|
||||
kfree(adis->buffer);
|
||||
|
||||
/* All but the timestamp channel */
|
||||
burst_length = (indio_dev->num_channels - 1) * sizeof(u16);
|
||||
if (st->variant->flags & ADIS16400_BURST_DIAG_STAT)
|
||||
burst_length += sizeof(u16);
|
||||
|
||||
adis->xfer = kcalloc(2, sizeof(*adis->xfer), GFP_KERNEL);
|
||||
if (!adis->xfer)
|
||||
return -ENOMEM;
|
||||
|
||||
adis->buffer = kzalloc(indio_dev->scan_bytes + sizeof(u16),
|
||||
GFP_KERNEL);
|
||||
adis->buffer = kzalloc(burst_length + sizeof(u16), GFP_KERNEL);
|
||||
if (!adis->buffer)
|
||||
return -ENOMEM;
|
||||
|
||||
tx = adis->buffer + indio_dev->scan_bytes;
|
||||
|
||||
tx = adis->buffer + burst_length;
|
||||
tx[0] = ADIS_READ_REG(ADIS16400_GLOB_CMD);
|
||||
tx[1] = 0;
|
||||
|
||||
adis->xfer[0].tx_buf = tx;
|
||||
adis->xfer[0].bits_per_word = 8;
|
||||
adis->xfer[0].len = 2;
|
||||
adis->xfer[1].tx_buf = tx;
|
||||
adis->xfer[1].rx_buf = adis->buffer;
|
||||
adis->xfer[1].bits_per_word = 8;
|
||||
adis->xfer[1].len = indio_dev->scan_bytes;
|
||||
adis->xfer[1].len = burst_length;
|
||||
|
||||
spi_message_init(&adis->msg);
|
||||
spi_message_add_tail(&adis->xfer[0], &adis->msg);
|
||||
@ -61,6 +65,7 @@ irqreturn_t adis16400_trigger_handler(int irq, void *p)
|
||||
struct adis16400_state *st = iio_priv(indio_dev);
|
||||
struct adis *adis = &st->adis;
|
||||
u32 old_speed_hz = st->adis.spi->max_speed_hz;
|
||||
void *buffer;
|
||||
int ret;
|
||||
|
||||
if (!adis->buffer)
|
||||
@ -81,7 +86,12 @@ irqreturn_t adis16400_trigger_handler(int irq, void *p)
|
||||
spi_setup(st->adis.spi);
|
||||
}
|
||||
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, adis->buffer,
|
||||
if (st->variant->flags & ADIS16400_BURST_DIAG_STAT)
|
||||
buffer = adis->buffer + sizeof(u16);
|
||||
else
|
||||
buffer = adis->buffer;
|
||||
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, buffer,
|
||||
pf->timestamp);
|
||||
|
||||
iio_trigger_notify_done(indio_dev->trig);
|
||||
|
@ -405,6 +405,11 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
|
||||
*val = st->variant->temp_scale_nano / 1000000;
|
||||
*val2 = (st->variant->temp_scale_nano % 1000000);
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
case IIO_PRESSURE:
|
||||
/* 20 uBar = 0.002kPascal */
|
||||
*val = 0;
|
||||
*val2 = 2000;
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -454,10 +459,10 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
|
||||
}
|
||||
}
|
||||
|
||||
#define ADIS16400_VOLTAGE_CHAN(addr, bits, name, si) { \
|
||||
#define ADIS16400_VOLTAGE_CHAN(addr, bits, name, si, chn) { \
|
||||
.type = IIO_VOLTAGE, \
|
||||
.indexed = 1, \
|
||||
.channel = 0, \
|
||||
.channel = chn, \
|
||||
.extend_name = name, \
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
|
||||
BIT(IIO_CHAN_INFO_SCALE), \
|
||||
@ -474,10 +479,10 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
|
||||
}
|
||||
|
||||
#define ADIS16400_SUPPLY_CHAN(addr, bits) \
|
||||
ADIS16400_VOLTAGE_CHAN(addr, bits, "supply", ADIS16400_SCAN_SUPPLY)
|
||||
ADIS16400_VOLTAGE_CHAN(addr, bits, "supply", ADIS16400_SCAN_SUPPLY, 0)
|
||||
|
||||
#define ADIS16400_AUX_ADC_CHAN(addr, bits) \
|
||||
ADIS16400_VOLTAGE_CHAN(addr, bits, NULL, ADIS16400_SCAN_ADC)
|
||||
ADIS16400_VOLTAGE_CHAN(addr, bits, NULL, ADIS16400_SCAN_ADC, 1)
|
||||
|
||||
#define ADIS16400_GYRO_CHAN(mod, addr, bits) { \
|
||||
.type = IIO_ANGL_VEL, \
|
||||
@ -773,7 +778,8 @@ static struct adis16400_chip_info adis16400_chips[] = {
|
||||
.channels = adis16448_channels,
|
||||
.num_channels = ARRAY_SIZE(adis16448_channels),
|
||||
.flags = ADIS16400_HAS_PROD_ID |
|
||||
ADIS16400_HAS_SERIAL_NUMBER,
|
||||
ADIS16400_HAS_SERIAL_NUMBER |
|
||||
ADIS16400_BURST_DIAG_STAT,
|
||||
.gyro_scale_micro = IIO_DEGREE_TO_RAD(10000), /* 0.01 deg/s */
|
||||
.accel_scale_micro = IIO_G_TO_M_S_2(833), /* 1/1200 g */
|
||||
.temp_scale_nano = 73860000, /* 0.07386 C */
|
||||
@ -791,11 +797,6 @@ static const struct iio_info adis16400_info = {
|
||||
.debugfs_reg_access = adis_debugfs_reg_access,
|
||||
};
|
||||
|
||||
static const unsigned long adis16400_burst_scan_mask[] = {
|
||||
~0UL,
|
||||
0,
|
||||
};
|
||||
|
||||
static const char * const adis16400_status_error_msgs[] = {
|
||||
[ADIS16400_DIAG_STAT_ZACCL_FAIL] = "Z-axis accelerometer self-test failure",
|
||||
[ADIS16400_DIAG_STAT_YACCL_FAIL] = "Y-axis accelerometer self-test failure",
|
||||
@ -843,6 +844,20 @@ static const struct adis_data adis16400_data = {
|
||||
BIT(ADIS16400_DIAG_STAT_POWER_LOW),
|
||||
};
|
||||
|
||||
static void adis16400_setup_chan_mask(struct adis16400_state *st)
|
||||
{
|
||||
const struct adis16400_chip_info *chip_info = st->variant;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < chip_info->num_channels; i++) {
|
||||
const struct iio_chan_spec *ch = &chip_info->channels[i];
|
||||
|
||||
if (ch->scan_index >= 0 &&
|
||||
ch->scan_index != ADIS16400_SCAN_TIMESTAMP)
|
||||
st->avail_scan_mask[0] |= BIT(ch->scan_index);
|
||||
}
|
||||
}
|
||||
|
||||
static int adis16400_probe(struct spi_device *spi)
|
||||
{
|
||||
struct adis16400_state *st;
|
||||
@ -866,8 +881,10 @@ static int adis16400_probe(struct spi_device *spi)
|
||||
indio_dev->info = &adis16400_info;
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
|
||||
if (!(st->variant->flags & ADIS16400_NO_BURST))
|
||||
indio_dev->available_scan_masks = adis16400_burst_scan_mask;
|
||||
if (!(st->variant->flags & ADIS16400_NO_BURST)) {
|
||||
adis16400_setup_chan_mask(st);
|
||||
indio_dev->available_scan_masks = st->avail_scan_mask;
|
||||
}
|
||||
|
||||
ret = adis_init(&st->adis, indio_dev, spi, &adis16400_data);
|
||||
if (ret)
|
||||
|
@ -1063,9 +1063,8 @@ static void alps_process_trackstick_packet_v7(struct psmouse *psmouse)
|
||||
right = (packet[1] & 0x02) >> 1;
|
||||
middle = (packet[1] & 0x04) >> 2;
|
||||
|
||||
/* Divide 2 since trackpoint's speed is too fast */
|
||||
input_report_rel(dev2, REL_X, (char)x / 2);
|
||||
input_report_rel(dev2, REL_Y, -((char)y / 2));
|
||||
input_report_rel(dev2, REL_X, (char)x);
|
||||
input_report_rel(dev2, REL_Y, -((char)y));
|
||||
|
||||
input_report_key(dev2, BTN_LEFT, left);
|
||||
input_report_key(dev2, BTN_RIGHT, right);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user