Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branches 'pm-devfreq', 'pm-qos', 'pm-tools' and 'pm-docs'

Merge devfreq changes, PM QoS change, and power management tools and
documentation changes for v5.20-rc1:

- Add new devfreq driver for Mediatek CCI (Cache Coherent
Interconnect) (Johnson Wang).

- Convert the Samsung Exynos SoC Bus bindings to DT schema of
exynos-bus.c (Krzysztof Kozlowski).

- Address kernel-doc warnings by adding the description for unused
fucntion parameters in devfreq core (Mauro Carvalho Chehab).

- Use NULL to pass a null pointer rather than zero according to the
function propotype in imx-bus.c (Colin Ian King).

- Print error message instead of error interger value in
tegra30-devfreq.c (Dmitry Osipenko).

- Add checks to prevent setting negative frequency QoS limits for
CPUs (Shivnandan Kumar).

- Update the pm-graph suite of utilities to the latest revision 5.9
including multiple improvements (Todd Brandt).

- Drop pme_interrupt reference from the PCI power management
documentation (Mario Limonciello).

* pm-devfreq:
PM / devfreq: tegra30: Add error message for devm_devfreq_add_device()
PM / devfreq: imx-bus: use NULL to pass a null pointer rather than zero
PM / devfreq: shut up kernel-doc warnings
dt-bindings: interconnect: samsung,exynos-bus: convert to dtschema
PM / devfreq: mediatek: Introduce MediaTek CCI devfreq driver
dt-bindings: interconnect: Add MediaTek CCI dt-bindings

* pm-qos:
PM: QoS: Add check to make sure CPU freq is non-negative

* pm-tools:
pm-graph v5.9

* pm-docs:
Documentation: PM: Drop pme_interrupt reference

+1255 -680
-488
Documentation/devicetree/bindings/devfreq/exynos-bus.txt
··· 1 - * Generic Exynos Bus frequency device 2 - 3 - The Samsung Exynos SoC has many buses for data transfer between DRAM 4 - and sub-blocks in SoC. Most Exynos SoCs share the common architecture 5 - for buses. Generally, each bus of Exynos SoC includes a source clock 6 - and a power line, which are able to change the clock frequency 7 - of the bus in runtime. To monitor the usage of each bus in runtime, 8 - the driver uses the PPMU (Platform Performance Monitoring Unit), which 9 - is able to measure the current load of sub-blocks. 10 - 11 - The Exynos SoC includes the various sub-blocks which have the each AXI bus. 12 - The each AXI bus has the owned source clock but, has not the only owned 13 - power line. The power line might be shared among one more sub-blocks. 14 - So, we can divide into two type of device as the role of each sub-block. 15 - There are two type of bus devices as following: 16 - - parent bus device 17 - - passive bus device 18 - 19 - Basically, parent and passive bus device share the same power line. 20 - The parent bus device can only change the voltage of shared power line 21 - and the rest bus devices (passive bus device) depend on the decision of 22 - the parent bus device. If there are three blocks which share the VDD_xxx 23 - power line, Only one block should be parent device and then the rest blocks 24 - should depend on the parent device as passive device. 25 - 26 - VDD_xxx |--- A block (parent) 27 - |--- B block (passive) 28 - |--- C block (passive) 29 - 30 - There are a little different composition among Exynos SoC because each Exynos 31 - SoC has different sub-blocks. Therefore, such difference should be specified 32 - in devicetree file instead of each device driver. In result, this driver 33 - is able to support the bus frequency for all Exynos SoCs. 34 - 35 - Required properties for all bus devices: 36 - - compatible: Should be "samsung,exynos-bus". 37 - - clock-names : the name of clock used by the bus, "bus". 38 - - clocks : phandles for clock specified in "clock-names" property. 39 - - operating-points-v2: the OPP table including frequency/voltage information 40 - to support DVFS (Dynamic Voltage/Frequency Scaling) feature. 41 - 42 - Required properties only for parent bus device: 43 - - vdd-supply: the regulator to provide the buses with the voltage. 44 - - devfreq-events: the devfreq-event device to monitor the current utilization 45 - of buses. 46 - 47 - Required properties only for passive bus device: 48 - - devfreq: the parent bus device. 49 - 50 - Optional properties only for parent bus device: 51 - - exynos,saturation-ratio: the percentage value which is used to calibrate 52 - the performance count against total cycle count. 53 - 54 - Optional properties for the interconnect functionality (QoS frequency 55 - constraints): 56 - - #interconnect-cells: should be 0. 57 - - interconnects: as documented in ../interconnect.txt, describes a path at the 58 - higher level interconnects used by this interconnect provider. 59 - If this interconnect provider is directly linked to a top level interconnect 60 - provider the property contains only one phandle. The provider extends 61 - the interconnect graph by linking its node to a node registered by provider 62 - pointed to by first phandle in the 'interconnects' property. 63 - 64 - - samsung,data-clock-ratio: ratio of the data throughput in B/s to minimum data 65 - clock frequency in Hz, default value is 8 when this property is missing. 66 - 67 - Detailed correlation between sub-blocks and power line according to Exynos SoC: 68 - - In case of Exynos3250, there are two power line as following: 69 - VDD_MIF |--- DMC 70 - 71 - VDD_INT |--- LEFTBUS (parent device) 72 - |--- PERIL 73 - |--- MFC 74 - |--- G3D 75 - |--- RIGHTBUS 76 - |--- PERIR 77 - |--- FSYS 78 - |--- LCD0 79 - |--- PERIR 80 - |--- ISP 81 - |--- CAM 82 - 83 - - In case of Exynos4210, there is one power line as following: 84 - VDD_INT |--- DMC (parent device) 85 - |--- LEFTBUS 86 - |--- PERIL 87 - |--- MFC(L) 88 - |--- G3D 89 - |--- TV 90 - |--- LCD0 91 - |--- RIGHTBUS 92 - |--- PERIR 93 - |--- MFC(R) 94 - |--- CAM 95 - |--- FSYS 96 - |--- GPS 97 - |--- LCD0 98 - |--- LCD1 99 - 100 - - In case of Exynos4x12, there are two power line as following: 101 - VDD_MIF |--- DMC 102 - 103 - VDD_INT |--- LEFTBUS (parent device) 104 - |--- PERIL 105 - |--- MFC(L) 106 - |--- G3D 107 - |--- TV 108 - |--- IMAGE 109 - |--- RIGHTBUS 110 - |--- PERIR 111 - |--- MFC(R) 112 - |--- CAM 113 - |--- FSYS 114 - |--- GPS 115 - |--- LCD0 116 - |--- ISP 117 - 118 - - In case of Exynos5422, there are two power line as following: 119 - VDD_MIF |--- DREX 0 (parent device, DRAM EXpress controller) 120 - |--- DREX 1 121 - 122 - VDD_INT |--- NoC_Core (parent device) 123 - |--- G2D 124 - |--- G3D 125 - |--- DISP1 126 - |--- NoC_WCORE 127 - |--- GSCL 128 - |--- MSCL 129 - |--- ISP 130 - |--- MFC 131 - |--- GEN 132 - |--- PERIS 133 - |--- PERIC 134 - |--- FSYS 135 - |--- FSYS2 136 - 137 - - In case of Exynos5433, there is VDD_INT power line as following: 138 - VDD_INT |--- G2D (parent device) 139 - |--- MSCL 140 - |--- GSCL 141 - |--- JPEG 142 - |--- MFC 143 - |--- HEVC 144 - |--- BUS0 145 - |--- BUS1 146 - |--- BUS2 147 - |--- PERIS (Fixed clock rate) 148 - |--- PERIC (Fixed clock rate) 149 - |--- FSYS (Fixed clock rate) 150 - 151 - Example 1: 152 - Show the AXI buses of Exynos3250 SoC. Exynos3250 divides the buses to 153 - power line (regulator). The MIF (Memory Interface) AXI bus is used to 154 - transfer data between DRAM and CPU and uses the VDD_MIF regulator. 155 - 156 - - MIF (Memory Interface) block 157 - : VDD_MIF |--- DMC (Dynamic Memory Controller) 158 - 159 - - INT (Internal) block 160 - : VDD_INT |--- LEFTBUS (parent device) 161 - |--- PERIL 162 - |--- MFC 163 - |--- G3D 164 - |--- RIGHTBUS 165 - |--- FSYS 166 - |--- LCD0 167 - |--- PERIR 168 - |--- ISP 169 - |--- CAM 170 - 171 - - MIF bus's frequency/voltage table 172 - ----------------------- 173 - |Lv| Freq | Voltage | 174 - ----------------------- 175 - |L1| 50000 |800000 | 176 - |L2| 100000 |800000 | 177 - |L3| 134000 |800000 | 178 - |L4| 200000 |825000 | 179 - |L5| 400000 |875000 | 180 - ----------------------- 181 - 182 - - INT bus's frequency/voltage table 183 - ---------------------------------------------------------- 184 - |Block|LEFTBUS|RIGHTBUS|MCUISP |ISP |PERIL ||VDD_INT | 185 - | name| |LCD0 | | | || | 186 - | | |FSYS | | | || | 187 - | | |MFC | | | || | 188 - ---------------------------------------------------------- 189 - |Mode |*parent|passive |passive|passive|passive|| | 190 - ---------------------------------------------------------- 191 - |Lv |Frequency ||Voltage | 192 - ---------------------------------------------------------- 193 - |L1 |50000 |50000 |50000 |50000 |50000 ||900000 | 194 - |L2 |80000 |80000 |80000 |80000 |80000 ||900000 | 195 - |L3 |100000 |100000 |100000 |100000 |100000 ||1000000 | 196 - |L4 |134000 |134000 |200000 |200000 | ||1000000 | 197 - |L5 |200000 |200000 |400000 |300000 | ||1000000 | 198 - ---------------------------------------------------------- 199 - 200 - Example 2: 201 - The bus of DMC (Dynamic Memory Controller) block in exynos3250.dtsi 202 - is listed below: 203 - 204 - bus_dmc: bus_dmc { 205 - compatible = "samsung,exynos-bus"; 206 - clocks = <&cmu_dmc CLK_DIV_DMC>; 207 - clock-names = "bus"; 208 - operating-points-v2 = <&bus_dmc_opp_table>; 209 - status = "disabled"; 210 - }; 211 - 212 - bus_dmc_opp_table: opp_table1 { 213 - compatible = "operating-points-v2"; 214 - opp-shared; 215 - 216 - opp-50000000 { 217 - opp-hz = /bits/ 64 <50000000>; 218 - opp-microvolt = <800000>; 219 - }; 220 - opp-100000000 { 221 - opp-hz = /bits/ 64 <100000000>; 222 - opp-microvolt = <800000>; 223 - }; 224 - opp-134000000 { 225 - opp-hz = /bits/ 64 <134000000>; 226 - opp-microvolt = <800000>; 227 - }; 228 - opp-200000000 { 229 - opp-hz = /bits/ 64 <200000000>; 230 - opp-microvolt = <825000>; 231 - }; 232 - opp-400000000 { 233 - opp-hz = /bits/ 64 <400000000>; 234 - opp-microvolt = <875000>; 235 - }; 236 - }; 237 - 238 - bus_leftbus: bus_leftbus { 239 - compatible = "samsung,exynos-bus"; 240 - clocks = <&cmu CLK_DIV_GDL>; 241 - clock-names = "bus"; 242 - operating-points-v2 = <&bus_leftbus_opp_table>; 243 - status = "disabled"; 244 - }; 245 - 246 - bus_rightbus: bus_rightbus { 247 - compatible = "samsung,exynos-bus"; 248 - clocks = <&cmu CLK_DIV_GDR>; 249 - clock-names = "bus"; 250 - operating-points-v2 = <&bus_leftbus_opp_table>; 251 - status = "disabled"; 252 - }; 253 - 254 - bus_lcd0: bus_lcd0 { 255 - compatible = "samsung,exynos-bus"; 256 - clocks = <&cmu CLK_DIV_ACLK_160>; 257 - clock-names = "bus"; 258 - operating-points-v2 = <&bus_leftbus_opp_table>; 259 - status = "disabled"; 260 - }; 261 - 262 - bus_fsys: bus_fsys { 263 - compatible = "samsung,exynos-bus"; 264 - clocks = <&cmu CLK_DIV_ACLK_200>; 265 - clock-names = "bus"; 266 - operating-points-v2 = <&bus_leftbus_opp_table>; 267 - status = "disabled"; 268 - }; 269 - 270 - bus_mcuisp: bus_mcuisp { 271 - compatible = "samsung,exynos-bus"; 272 - clocks = <&cmu CLK_DIV_ACLK_400_MCUISP>; 273 - clock-names = "bus"; 274 - operating-points-v2 = <&bus_mcuisp_opp_table>; 275 - status = "disabled"; 276 - }; 277 - 278 - bus_isp: bus_isp { 279 - compatible = "samsung,exynos-bus"; 280 - clocks = <&cmu CLK_DIV_ACLK_266>; 281 - clock-names = "bus"; 282 - operating-points-v2 = <&bus_isp_opp_table>; 283 - status = "disabled"; 284 - }; 285 - 286 - bus_peril: bus_peril { 287 - compatible = "samsung,exynos-bus"; 288 - clocks = <&cmu CLK_DIV_ACLK_100>; 289 - clock-names = "bus"; 290 - operating-points-v2 = <&bus_peril_opp_table>; 291 - status = "disabled"; 292 - }; 293 - 294 - bus_mfc: bus_mfc { 295 - compatible = "samsung,exynos-bus"; 296 - clocks = <&cmu CLK_SCLK_MFC>; 297 - clock-names = "bus"; 298 - operating-points-v2 = <&bus_leftbus_opp_table>; 299 - status = "disabled"; 300 - }; 301 - 302 - bus_leftbus_opp_table: opp_table1 { 303 - compatible = "operating-points-v2"; 304 - opp-shared; 305 - 306 - opp-50000000 { 307 - opp-hz = /bits/ 64 <50000000>; 308 - opp-microvolt = <900000>; 309 - }; 310 - opp-80000000 { 311 - opp-hz = /bits/ 64 <80000000>; 312 - opp-microvolt = <900000>; 313 - }; 314 - opp-100000000 { 315 - opp-hz = /bits/ 64 <100000000>; 316 - opp-microvolt = <1000000>; 317 - }; 318 - opp-134000000 { 319 - opp-hz = /bits/ 64 <134000000>; 320 - opp-microvolt = <1000000>; 321 - }; 322 - opp-200000000 { 323 - opp-hz = /bits/ 64 <200000000>; 324 - opp-microvolt = <1000000>; 325 - }; 326 - }; 327 - 328 - bus_mcuisp_opp_table: opp_table2 { 329 - compatible = "operating-points-v2"; 330 - opp-shared; 331 - 332 - opp-50000000 { 333 - opp-hz = /bits/ 64 <50000000>; 334 - }; 335 - opp-80000000 { 336 - opp-hz = /bits/ 64 <80000000>; 337 - }; 338 - opp-100000000 { 339 - opp-hz = /bits/ 64 <100000000>; 340 - }; 341 - opp-200000000 { 342 - opp-hz = /bits/ 64 <200000000>; 343 - }; 344 - opp-400000000 { 345 - opp-hz = /bits/ 64 <400000000>; 346 - }; 347 - }; 348 - 349 - bus_isp_opp_table: opp_table3 { 350 - compatible = "operating-points-v2"; 351 - opp-shared; 352 - 353 - opp-50000000 { 354 - opp-hz = /bits/ 64 <50000000>; 355 - }; 356 - opp-80000000 { 357 - opp-hz = /bits/ 64 <80000000>; 358 - }; 359 - opp-100000000 { 360 - opp-hz = /bits/ 64 <100000000>; 361 - }; 362 - opp-200000000 { 363 - opp-hz = /bits/ 64 <200000000>; 364 - }; 365 - opp-300000000 { 366 - opp-hz = /bits/ 64 <300000000>; 367 - }; 368 - }; 369 - 370 - bus_peril_opp_table: opp_table4 { 371 - compatible = "operating-points-v2"; 372 - opp-shared; 373 - 374 - opp-50000000 { 375 - opp-hz = /bits/ 64 <50000000>; 376 - }; 377 - opp-80000000 { 378 - opp-hz = /bits/ 64 <80000000>; 379 - }; 380 - opp-100000000 { 381 - opp-hz = /bits/ 64 <100000000>; 382 - }; 383 - }; 384 - 385 - 386 - Usage case to handle the frequency and voltage of bus on runtime 387 - in exynos3250-rinato.dts is listed below: 388 - 389 - &bus_dmc { 390 - devfreq-events = <&ppmu_dmc0_3>, <&ppmu_dmc1_3>; 391 - vdd-supply = <&buck1_reg>; /* VDD_MIF */ 392 - status = "okay"; 393 - }; 394 - 395 - &bus_leftbus { 396 - devfreq-events = <&ppmu_leftbus_3>, <&ppmu_rightbus_3>; 397 - vdd-supply = <&buck3_reg>; 398 - status = "okay"; 399 - }; 400 - 401 - &bus_rightbus { 402 - devfreq = <&bus_leftbus>; 403 - status = "okay"; 404 - }; 405 - 406 - &bus_lcd0 { 407 - devfreq = <&bus_leftbus>; 408 - status = "okay"; 409 - }; 410 - 411 - &bus_fsys { 412 - devfreq = <&bus_leftbus>; 413 - status = "okay"; 414 - }; 415 - 416 - &bus_mcuisp { 417 - devfreq = <&bus_leftbus>; 418 - status = "okay"; 419 - }; 420 - 421 - &bus_isp { 422 - devfreq = <&bus_leftbus>; 423 - status = "okay"; 424 - }; 425 - 426 - &bus_peril { 427 - devfreq = <&bus_leftbus>; 428 - status = "okay"; 429 - }; 430 - 431 - &bus_mfc { 432 - devfreq = <&bus_leftbus>; 433 - status = "okay"; 434 - }; 435 - 436 - Example 3: 437 - An interconnect path "bus_display -- bus_leftbus -- bus_dmc" on 438 - Exynos4412 SoC with video mixer as an interconnect consumer device. 439 - 440 - soc { 441 - bus_dmc: bus_dmc { 442 - compatible = "samsung,exynos-bus"; 443 - clocks = <&clock CLK_DIV_DMC>; 444 - clock-names = "bus"; 445 - operating-points-v2 = <&bus_dmc_opp_table>; 446 - samsung,data-clock-ratio = <4>; 447 - #interconnect-cells = <0>; 448 - }; 449 - 450 - bus_leftbus: bus_leftbus { 451 - compatible = "samsung,exynos-bus"; 452 - clocks = <&clock CLK_DIV_GDL>; 453 - clock-names = "bus"; 454 - operating-points-v2 = <&bus_leftbus_opp_table>; 455 - #interconnect-cells = <0>; 456 - interconnects = <&bus_dmc>; 457 - }; 458 - 459 - bus_display: bus_display { 460 - compatible = "samsung,exynos-bus"; 461 - clocks = <&clock CLK_ACLK160>; 462 - clock-names = "bus"; 463 - operating-points-v2 = <&bus_display_opp_table>; 464 - #interconnect-cells = <0>; 465 - interconnects = <&bus_leftbus &bus_dmc>; 466 - }; 467 - 468 - bus_dmc_opp_table: opp_table1 { 469 - compatible = "operating-points-v2"; 470 - /* ... */ 471 - } 472 - 473 - bus_leftbus_opp_table: opp_table3 { 474 - compatible = "operating-points-v2"; 475 - /* ... */ 476 - }; 477 - 478 - bus_display_opp_table: opp_table4 { 479 - compatible = "operating-points-v2"; 480 - /* .. */ 481 - }; 482 - 483 - &mixer { 484 - compatible = "samsung,exynos4212-mixer"; 485 - interconnects = <&bus_display &bus_dmc>; 486 - /* ... */ 487 - }; 488 - };
+141
Documentation/devicetree/bindings/interconnect/mediatek,cci.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/interconnect/mediatek,cci.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: MediaTek Cache Coherent Interconnect (CCI) frequency and voltage scaling 8 + 9 + maintainers: 10 + - Jia-Wei Chang <jia-wei.chang@mediatek.com> 11 + - Johnson Wang <johnson.wang@mediatek.com> 12 + 13 + description: | 14 + MediaTek Cache Coherent Interconnect (CCI) is a hardware engine used by 15 + MT8183 and MT8186 SoCs to scale the frequency and adjust the voltage in 16 + hardware. It can also optimize the voltage to reduce the power consumption. 17 + 18 + properties: 19 + compatible: 20 + enum: 21 + - mediatek,mt8183-cci 22 + - mediatek,mt8186-cci 23 + 24 + clocks: 25 + items: 26 + - description: 27 + The multiplexer for clock input of the bus. 28 + - description: 29 + A parent of "bus" clock which is used as an intermediate clock source 30 + when the original clock source (PLL) is under transition and not 31 + stable yet. 32 + 33 + clock-names: 34 + items: 35 + - const: cci 36 + - const: intermediate 37 + 38 + operating-points-v2: true 39 + opp-table: true 40 + 41 + proc-supply: 42 + description: 43 + Phandle of the regulator for CCI that provides the supply voltage. 44 + 45 + sram-supply: 46 + description: 47 + Phandle of the regulator for sram of CCI that provides the supply 48 + voltage. When it is present, the implementation needs to do 49 + "voltage tracking" to step by step scale up/down Vproc and Vsram to fit 50 + SoC specific needs. When absent, the voltage scaling flow is handled by 51 + hardware, hence no software "voltage tracking" is needed. 52 + 53 + required: 54 + - compatible 55 + - clocks 56 + - clock-names 57 + - operating-points-v2 58 + - proc-supply 59 + 60 + additionalProperties: false 61 + 62 + examples: 63 + - | 64 + #include <dt-bindings/clock/mt8183-clk.h> 65 + cci: cci { 66 + compatible = "mediatek,mt8183-cci"; 67 + clocks = <&mcucfg CLK_MCU_BUS_SEL>, 68 + <&topckgen CLK_TOP_ARMPLL_DIV_PLL1>; 69 + clock-names = "cci", "intermediate"; 70 + operating-points-v2 = <&cci_opp>; 71 + proc-supply = <&mt6358_vproc12_reg>; 72 + }; 73 + 74 + cci_opp: opp-table-cci { 75 + compatible = "operating-points-v2"; 76 + opp-shared; 77 + opp2_00: opp-273000000 { 78 + opp-hz = /bits/ 64 <273000000>; 79 + opp-microvolt = <650000>; 80 + }; 81 + opp2_01: opp-338000000 { 82 + opp-hz = /bits/ 64 <338000000>; 83 + opp-microvolt = <687500>; 84 + }; 85 + opp2_02: opp-403000000 { 86 + opp-hz = /bits/ 64 <403000000>; 87 + opp-microvolt = <718750>; 88 + }; 89 + opp2_03: opp-463000000 { 90 + opp-hz = /bits/ 64 <463000000>; 91 + opp-microvolt = <756250>; 92 + }; 93 + opp2_04: opp-546000000 { 94 + opp-hz = /bits/ 64 <546000000>; 95 + opp-microvolt = <800000>; 96 + }; 97 + opp2_05: opp-624000000 { 98 + opp-hz = /bits/ 64 <624000000>; 99 + opp-microvolt = <818750>; 100 + }; 101 + opp2_06: opp-689000000 { 102 + opp-hz = /bits/ 64 <689000000>; 103 + opp-microvolt = <850000>; 104 + }; 105 + opp2_07: opp-767000000 { 106 + opp-hz = /bits/ 64 <767000000>; 107 + opp-microvolt = <868750>; 108 + }; 109 + opp2_08: opp-845000000 { 110 + opp-hz = /bits/ 64 <845000000>; 111 + opp-microvolt = <893750>; 112 + }; 113 + opp2_09: opp-871000000 { 114 + opp-hz = /bits/ 64 <871000000>; 115 + opp-microvolt = <906250>; 116 + }; 117 + opp2_10: opp-923000000 { 118 + opp-hz = /bits/ 64 <923000000>; 119 + opp-microvolt = <931250>; 120 + }; 121 + opp2_11: opp-962000000 { 122 + opp-hz = /bits/ 64 <962000000>; 123 + opp-microvolt = <943750>; 124 + }; 125 + opp2_12: opp-1027000000 { 126 + opp-hz = /bits/ 64 <1027000000>; 127 + opp-microvolt = <975000>; 128 + }; 129 + opp2_13: opp-1092000000 { 130 + opp-hz = /bits/ 64 <1092000000>; 131 + opp-microvolt = <1000000>; 132 + }; 133 + opp2_14: opp-1144000000 { 134 + opp-hz = /bits/ 64 <1144000000>; 135 + opp-microvolt = <1025000>; 136 + }; 137 + opp2_15: opp-1196000000 { 138 + opp-hz = /bits/ 64 <1196000000>; 139 + opp-microvolt = <1050000>; 140 + }; 141 + };
+290
Documentation/devicetree/bindings/interconnect/samsung,exynos-bus.yaml
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/interconnect/samsung,exynos-bus.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Samsung Exynos SoC Bus and Interconnect 8 + 9 + maintainers: 10 + - Chanwoo Choi <cw00.choi@samsung.com> 11 + - Krzysztof Kozlowski <krzk@kernel.org> 12 + 13 + description: | 14 + The Samsung Exynos SoC has many buses for data transfer between DRAM and 15 + sub-blocks in SoC. Most Exynos SoCs share the common architecture for buses. 16 + Generally, each bus of Exynos SoC includes a source clock and a power line, 17 + which are able to change the clock frequency of the bus in runtime. To 18 + monitor the usage of each bus in runtime, the driver uses the PPMU (Platform 19 + Performance Monitoring Unit), which is able to measure the current load of 20 + sub-blocks. 21 + 22 + The Exynos SoC includes the various sub-blocks which have the each AXI bus. 23 + The each AXI bus has the owned source clock but, has not the only owned power 24 + line. The power line might be shared among one more sub-blocks. So, we can 25 + divide into two type of device as the role of each sub-block. There are two 26 + type of bus devices as following:: 27 + - parent bus device 28 + - passive bus device 29 + 30 + Basically, parent and passive bus device share the same power line. The 31 + parent bus device can only change the voltage of shared power line and the 32 + rest bus devices (passive bus device) depend on the decision of the parent 33 + bus device. If there are three blocks which share the VDD_xxx power line, 34 + Only one block should be parent device and then the rest blocks should depend 35 + on the parent device as passive device. 36 + 37 + VDD_xxx |--- A block (parent) 38 + |--- B block (passive) 39 + |--- C block (passive) 40 + 41 + There are a little different composition among Exynos SoC because each Exynos 42 + SoC has different sub-blocks. Therefore, such difference should be specified 43 + in devicetree file instead of each device driver. In result, this driver is 44 + able to support the bus frequency for all Exynos SoCs. 45 + 46 + Detailed correlation between sub-blocks and power line according 47 + to Exynos SoC:: 48 + - In case of Exynos3250, there are two power line as following:: 49 + VDD_MIF |--- DMC (Dynamic Memory Controller) 50 + 51 + VDD_INT |--- LEFTBUS (parent device) 52 + |--- PERIL 53 + |--- MFC 54 + |--- G3D 55 + |--- RIGHTBUS 56 + |--- PERIR 57 + |--- FSYS 58 + |--- LCD0 59 + |--- PERIR 60 + |--- ISP 61 + |--- CAM 62 + 63 + - MIF bus's frequency/voltage table 64 + ----------------------- 65 + |Lv| Freq | Voltage | 66 + ----------------------- 67 + |L1| 50000 |800000 | 68 + |L2| 100000 |800000 | 69 + |L3| 134000 |800000 | 70 + |L4| 200000 |825000 | 71 + |L5| 400000 |875000 | 72 + ----------------------- 73 + 74 + - INT bus's frequency/voltage table 75 + ---------------------------------------------------------- 76 + |Block|LEFTBUS|RIGHTBUS|MCUISP |ISP |PERIL ||VDD_INT | 77 + | name| |LCD0 | | | || | 78 + | | |FSYS | | | || | 79 + | | |MFC | | | || | 80 + ---------------------------------------------------------- 81 + |Mode |*parent|passive |passive|passive|passive|| | 82 + ---------------------------------------------------------- 83 + |Lv |Frequency ||Voltage | 84 + ---------------------------------------------------------- 85 + |L1 |50000 |50000 |50000 |50000 |50000 ||900000 | 86 + |L2 |80000 |80000 |80000 |80000 |80000 ||900000 | 87 + |L3 |100000 |100000 |100000 |100000 |100000 ||1000000 | 88 + |L4 |134000 |134000 |200000 |200000 | ||1000000 | 89 + |L5 |200000 |200000 |400000 |300000 | ||1000000 | 90 + ---------------------------------------------------------- 91 + 92 + - In case of Exynos4210, there is one power line as following:: 93 + VDD_INT |--- DMC (parent device, Dynamic Memory Controller) 94 + |--- LEFTBUS 95 + |--- PERIL 96 + |--- MFC(L) 97 + |--- G3D 98 + |--- TV 99 + |--- LCD0 100 + |--- RIGHTBUS 101 + |--- PERIR 102 + |--- MFC(R) 103 + |--- CAM 104 + |--- FSYS 105 + |--- GPS 106 + |--- LCD0 107 + |--- LCD1 108 + 109 + - In case of Exynos4x12, there are two power line as following:: 110 + VDD_MIF |--- DMC (Dynamic Memory Controller) 111 + 112 + VDD_INT |--- LEFTBUS (parent device) 113 + |--- PERIL 114 + |--- MFC(L) 115 + |--- G3D 116 + |--- TV 117 + |--- IMAGE 118 + |--- RIGHTBUS 119 + |--- PERIR 120 + |--- MFC(R) 121 + |--- CAM 122 + |--- FSYS 123 + |--- GPS 124 + |--- LCD0 125 + |--- ISP 126 + 127 + - In case of Exynos5422, there are two power line as following:: 128 + VDD_MIF |--- DREX 0 (parent device, DRAM EXpress controller) 129 + |--- DREX 1 130 + 131 + VDD_INT |--- NoC_Core (parent device) 132 + |--- G2D 133 + |--- G3D 134 + |--- DISP1 135 + |--- NoC_WCORE 136 + |--- GSCL 137 + |--- MSCL 138 + |--- ISP 139 + |--- MFC 140 + |--- GEN 141 + |--- PERIS 142 + |--- PERIC 143 + |--- FSYS 144 + |--- FSYS2 145 + 146 + - In case of Exynos5433, there is VDD_INT power line as following:: 147 + VDD_INT |--- G2D (parent device) 148 + |--- MSCL 149 + |--- GSCL 150 + |--- JPEG 151 + |--- MFC 152 + |--- HEVC 153 + |--- BUS0 154 + |--- BUS1 155 + |--- BUS2 156 + |--- PERIS (Fixed clock rate) 157 + |--- PERIC (Fixed clock rate) 158 + |--- FSYS (Fixed clock rate) 159 + 160 + properties: 161 + compatible: 162 + enum: 163 + - samsung,exynos-bus 164 + 165 + clocks: 166 + maxItems: 1 167 + 168 + clock-names: 169 + items: 170 + - const: bus 171 + 172 + devfreq: 173 + $ref: /schemas/types.yaml#/definitions/phandle 174 + description: 175 + Parent bus device. Valid and required only for the passive bus devices. 176 + 177 + devfreq-events: 178 + $ref: /schemas/types.yaml#/definitions/phandle-array 179 + minItems: 1 180 + maxItems: 4 181 + description: 182 + Devfreq-event device to monitor the current utilization of buses. Valid 183 + and required only for the parent bus devices. 184 + 185 + exynos,saturation-ratio: 186 + $ref: /schemas/types.yaml#/definitions/uint32 187 + description: 188 + Percentage value which is used to calibrate the performance count against 189 + total cycle count. Valid only for the parent bus devices. 190 + 191 + '#interconnect-cells': 192 + const: 0 193 + 194 + interconnects: 195 + minItems: 1 196 + maxItems: 2 197 + 198 + operating-points-v2: true 199 + 200 + samsung,data-clock-ratio: 201 + $ref: /schemas/types.yaml#/definitions/uint32 202 + default: 8 203 + description: 204 + Ratio of the data throughput in B/s to minimum data clock frequency in 205 + Hz. 206 + 207 + vdd-supply: 208 + description: 209 + Main bus power rail. Valid and required only for the parent bus devices. 210 + 211 + required: 212 + - compatible 213 + - clocks 214 + - clock-names 215 + - operating-points-v2 216 + 217 + additionalProperties: false 218 + 219 + examples: 220 + - | 221 + #include <dt-bindings/clock/exynos3250.h> 222 + 223 + bus-dmc { 224 + compatible = "samsung,exynos-bus"; 225 + clocks = <&cmu_dmc CLK_DIV_DMC>; 226 + clock-names = "bus"; 227 + operating-points-v2 = <&bus_dmc_opp_table>; 228 + devfreq-events = <&ppmu_dmc0_3>, <&ppmu_dmc1_3>; 229 + vdd-supply = <&buck1_reg>; 230 + }; 231 + 232 + ppmu_dmc0: ppmu@106a0000 { 233 + compatible = "samsung,exynos-ppmu"; 234 + reg = <0x106a0000 0x2000>; 235 + events { 236 + ppmu_dmc0_3: ppmu-event3-dmc0 { 237 + event-name = "ppmu-event3-dmc0"; 238 + }; 239 + }; 240 + }; 241 + 242 + bus_leftbus: bus-leftbus { 243 + compatible = "samsung,exynos-bus"; 244 + clocks = <&cmu CLK_DIV_GDL>; 245 + clock-names = "bus"; 246 + operating-points-v2 = <&bus_leftbus_opp_table>; 247 + devfreq-events = <&ppmu_leftbus_3>, <&ppmu_rightbus_3>; 248 + vdd-supply = <&buck3_reg>; 249 + }; 250 + 251 + bus-rightbus { 252 + compatible = "samsung,exynos-bus"; 253 + clocks = <&cmu CLK_DIV_GDR>; 254 + clock-names = "bus"; 255 + operating-points-v2 = <&bus_leftbus_opp_table>; 256 + devfreq = <&bus_leftbus>; 257 + }; 258 + 259 + - | 260 + dmc: bus-dmc { 261 + compatible = "samsung,exynos-bus"; 262 + clocks = <&clock CLK_DIV_DMC>; 263 + clock-names = "bus"; 264 + operating-points-v2 = <&bus_dmc_opp_table>; 265 + samsung,data-clock-ratio = <4>; 266 + #interconnect-cells = <0>; 267 + devfreq-events = <&ppmu_dmc0_3>, <&ppmu_dmc1_3>; 268 + vdd-supply = <&buck1_reg>; 269 + }; 270 + 271 + leftbus: bus-leftbus { 272 + compatible = "samsung,exynos-bus"; 273 + clocks = <&clock CLK_DIV_GDL>; 274 + clock-names = "bus"; 275 + operating-points-v2 = <&bus_leftbus_opp_table>; 276 + interconnects = <&dmc>; 277 + #interconnect-cells = <0>; 278 + devfreq-events = <&ppmu_leftbus_3>, <&ppmu_rightbus_3>; 279 + vdd-supply = <&buck3_reg>; 280 + }; 281 + 282 + display: bus-display { 283 + compatible = "samsung,exynos-bus"; 284 + clocks = <&clock CLK_DIV_ACLK_266>; 285 + clock-names = "bus"; 286 + operating-points-v2 = <&bus_display_opp_table>; 287 + interconnects = <&leftbus &dmc>; 288 + #interconnect-cells = <0>; 289 + devfreq = <&leftbus>; 290 + };
+1 -1
Documentation/power/pci.rst
··· 315 315 configuration space */ 316 316 unsigned int pme_support:5; /* Bitmask of states from which PME# 317 317 can be generated */ 318 - unsigned int pme_interrupt:1;/* Is native PCIe PME signaling used? */ 318 + unsigned int pme_poll:1; /* Poll device's PME status bit */ 319 319 unsigned int d1_support:1; /* Low power state D1 is supported */ 320 320 unsigned int d2_support:1; /* Low power state D2 is supported */ 321 321 unsigned int no_d1d2:1; /* D1 and D2 are forbidden */
+2 -1
MAINTAINERS
··· 4373 4373 L: linux-samsung-soc@vger.kernel.org 4374 4374 S: Maintained 4375 4375 T: git git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/linux.git 4376 - F: Documentation/devicetree/bindings/devfreq/exynos-bus.txt 4376 + F: Documentation/devicetree/bindings/interconnect/samsung,exynos-bus.yaml 4377 4377 F: drivers/devfreq/exynos-bus.c 4378 4378 4379 4379 BUSLOGIC SCSI DRIVER ··· 5855 5855 S: Maintained 5856 5856 T: git git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/linux.git 5857 5857 F: Documentation/devicetree/bindings/devfreq/ 5858 + F: Documentation/devicetree/bindings/interconnect/mediatek,cci.yaml 5858 5859 F: drivers/devfreq/ 5859 5860 F: include/linux/devfreq.h 5860 5861 F: include/trace/events/devfreq.h
+10
drivers/devfreq/Kconfig
··· 120 120 It reads ACTMON counters of memory controllers and adjusts the 121 121 operating frequencies and voltages with OPP support. 122 122 123 + config ARM_MEDIATEK_CCI_DEVFREQ 124 + tristate "MEDIATEK CCI DEVFREQ Driver" 125 + depends on ARM_MEDIATEK_CPUFREQ || COMPILE_TEST 126 + select DEVFREQ_GOV_PASSIVE 127 + help 128 + This adds a devfreq driver for MediaTek Cache Coherent Interconnect 129 + which is shared the same regulators with the cpu cluster. It can track 130 + buck voltages and update a proper CCI frequency. Use the notification 131 + to get the regulator status. 132 + 123 133 config ARM_RK3399_DMC_DEVFREQ 124 134 tristate "ARM RK3399 DMC DEVFREQ Driver" 125 135 depends on (ARCH_ROCKCHIP && HAVE_ARM_SMCCC) || \
+1
drivers/devfreq/Makefile
··· 11 11 obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += exynos-bus.o 12 12 obj-$(CONFIG_ARM_IMX_BUS_DEVFREQ) += imx-bus.o 13 13 obj-$(CONFIG_ARM_IMX8M_DDRC_DEVFREQ) += imx8m-ddrc.o 14 + obj-$(CONFIG_ARM_MEDIATEK_CCI_DEVFREQ) += mtk-cci-devfreq.o 14 15 obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ) += rk3399_dmc.o 15 16 obj-$(CONFIG_ARM_SUN8I_A33_MBUS_DEVFREQ) += sun8i-a33-mbus.o 16 17 obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra30-devfreq.o
+4
drivers/devfreq/devfreq.c
··· 696 696 /** 697 697 * qos_min_notifier_call() - Callback for QoS min_freq changes. 698 698 * @nb: Should be devfreq->nb_min 699 + * @val: not used 700 + * @ptr: not used 699 701 */ 700 702 static int qos_min_notifier_call(struct notifier_block *nb, 701 703 unsigned long val, void *ptr) ··· 708 706 /** 709 707 * qos_max_notifier_call() - Callback for QoS max_freq changes. 710 708 * @nb: Should be devfreq->nb_max 709 + * @val: not used 710 + * @ptr: not used 711 711 */ 712 712 static int qos_max_notifier_call(struct notifier_block *nb, 713 713 unsigned long val, void *ptr)
+1 -1
drivers/devfreq/imx-bus.c
··· 59 59 struct imx_bus *priv = dev_get_drvdata(dev); 60 60 const char *icc_driver_name; 61 61 62 - if (!of_get_property(dev->of_node, "#interconnect-cells", 0)) 62 + if (!of_get_property(dev->of_node, "#interconnect-cells", NULL)) 63 63 return 0; 64 64 if (!IS_ENABLED(CONFIG_INTERCONNECT_IMX)) { 65 65 dev_warn(dev, "imx interconnect drivers disabled\n");
+440
drivers/devfreq/mtk-cci-devfreq.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (C) 2022 MediaTek Inc. 4 + */ 5 + 6 + #include <linux/clk.h> 7 + #include <linux/devfreq.h> 8 + #include <linux/minmax.h> 9 + #include <linux/module.h> 10 + #include <linux/of.h> 11 + #include <linux/of_device.h> 12 + #include <linux/platform_device.h> 13 + #include <linux/pm_opp.h> 14 + #include <linux/regulator/consumer.h> 15 + 16 + struct mtk_ccifreq_platform_data { 17 + int min_volt_shift; 18 + int max_volt_shift; 19 + int proc_max_volt; 20 + int sram_min_volt; 21 + int sram_max_volt; 22 + }; 23 + 24 + struct mtk_ccifreq_drv { 25 + struct device *dev; 26 + struct devfreq *devfreq; 27 + struct regulator *proc_reg; 28 + struct regulator *sram_reg; 29 + struct clk *cci_clk; 30 + struct clk *inter_clk; 31 + int inter_voltage; 32 + unsigned long pre_freq; 33 + /* Avoid race condition for regulators between notify and policy */ 34 + struct mutex reg_lock; 35 + struct notifier_block opp_nb; 36 + const struct mtk_ccifreq_platform_data *soc_data; 37 + int vtrack_max; 38 + }; 39 + 40 + static int mtk_ccifreq_set_voltage(struct mtk_ccifreq_drv *drv, int new_voltage) 41 + { 42 + const struct mtk_ccifreq_platform_data *soc_data = drv->soc_data; 43 + struct device *dev = drv->dev; 44 + int pre_voltage, pre_vsram, new_vsram, vsram, voltage, ret; 45 + int retry_max = drv->vtrack_max; 46 + 47 + if (!drv->sram_reg) { 48 + ret = regulator_set_voltage(drv->proc_reg, new_voltage, 49 + drv->soc_data->proc_max_volt); 50 + return ret; 51 + } 52 + 53 + pre_voltage = regulator_get_voltage(drv->proc_reg); 54 + if (pre_voltage < 0) { 55 + dev_err(dev, "invalid vproc value: %d\n", pre_voltage); 56 + return pre_voltage; 57 + } 58 + 59 + pre_vsram = regulator_get_voltage(drv->sram_reg); 60 + if (pre_vsram < 0) { 61 + dev_err(dev, "invalid vsram value: %d\n", pre_vsram); 62 + return pre_vsram; 63 + } 64 + 65 + new_vsram = clamp(new_voltage + soc_data->min_volt_shift, 66 + soc_data->sram_min_volt, soc_data->sram_max_volt); 67 + 68 + do { 69 + if (pre_voltage <= new_voltage) { 70 + vsram = clamp(pre_voltage + soc_data->max_volt_shift, 71 + soc_data->sram_min_volt, new_vsram); 72 + ret = regulator_set_voltage(drv->sram_reg, vsram, 73 + soc_data->sram_max_volt); 74 + if (ret) 75 + return ret; 76 + 77 + if (vsram == soc_data->sram_max_volt || 78 + new_vsram == soc_data->sram_min_volt) 79 + voltage = new_voltage; 80 + else 81 + voltage = vsram - soc_data->min_volt_shift; 82 + 83 + ret = regulator_set_voltage(drv->proc_reg, voltage, 84 + soc_data->proc_max_volt); 85 + if (ret) { 86 + regulator_set_voltage(drv->sram_reg, pre_vsram, 87 + soc_data->sram_max_volt); 88 + return ret; 89 + } 90 + } else if (pre_voltage > new_voltage) { 91 + voltage = max(new_voltage, 92 + pre_vsram - soc_data->max_volt_shift); 93 + ret = regulator_set_voltage(drv->proc_reg, voltage, 94 + soc_data->proc_max_volt); 95 + if (ret) 96 + return ret; 97 + 98 + if (voltage == new_voltage) 99 + vsram = new_vsram; 100 + else 101 + vsram = max(new_vsram, 102 + voltage + soc_data->min_volt_shift); 103 + 104 + ret = regulator_set_voltage(drv->sram_reg, vsram, 105 + soc_data->sram_max_volt); 106 + if (ret) { 107 + regulator_set_voltage(drv->proc_reg, pre_voltage, 108 + soc_data->proc_max_volt); 109 + return ret; 110 + } 111 + } 112 + 113 + pre_voltage = voltage; 114 + pre_vsram = vsram; 115 + 116 + if (--retry_max < 0) { 117 + dev_err(dev, 118 + "over loop count, failed to set voltage\n"); 119 + return -EINVAL; 120 + } 121 + } while (voltage != new_voltage || vsram != new_vsram); 122 + 123 + return 0; 124 + } 125 + 126 + static int mtk_ccifreq_target(struct device *dev, unsigned long *freq, 127 + u32 flags) 128 + { 129 + struct mtk_ccifreq_drv *drv = dev_get_drvdata(dev); 130 + struct clk *cci_pll = clk_get_parent(drv->cci_clk); 131 + struct dev_pm_opp *opp; 132 + unsigned long opp_rate; 133 + int voltage, pre_voltage, inter_voltage, target_voltage, ret; 134 + 135 + if (!drv) 136 + return -EINVAL; 137 + 138 + if (drv->pre_freq == *freq) 139 + return 0; 140 + 141 + inter_voltage = drv->inter_voltage; 142 + 143 + opp_rate = *freq; 144 + opp = devfreq_recommended_opp(dev, &opp_rate, 1); 145 + if (IS_ERR(opp)) { 146 + dev_err(dev, "failed to find opp for freq: %ld\n", opp_rate); 147 + return PTR_ERR(opp); 148 + } 149 + 150 + mutex_lock(&drv->reg_lock); 151 + 152 + voltage = dev_pm_opp_get_voltage(opp); 153 + dev_pm_opp_put(opp); 154 + 155 + pre_voltage = regulator_get_voltage(drv->proc_reg); 156 + if (pre_voltage < 0) { 157 + dev_err(dev, "invalid vproc value: %d\n", pre_voltage); 158 + ret = pre_voltage; 159 + goto out_unlock; 160 + } 161 + 162 + /* scale up: set voltage first then freq. */ 163 + target_voltage = max(inter_voltage, voltage); 164 + if (pre_voltage <= target_voltage) { 165 + ret = mtk_ccifreq_set_voltage(drv, target_voltage); 166 + if (ret) { 167 + dev_err(dev, "failed to scale up voltage\n"); 168 + goto out_restore_voltage; 169 + } 170 + } 171 + 172 + /* switch the cci clock to intermediate clock source. */ 173 + ret = clk_set_parent(drv->cci_clk, drv->inter_clk); 174 + if (ret) { 175 + dev_err(dev, "failed to re-parent cci clock\n"); 176 + goto out_restore_voltage; 177 + } 178 + 179 + /* set the original clock to target rate. */ 180 + ret = clk_set_rate(cci_pll, *freq); 181 + if (ret) { 182 + dev_err(dev, "failed to set cci pll rate: %d\n", ret); 183 + clk_set_parent(drv->cci_clk, cci_pll); 184 + goto out_restore_voltage; 185 + } 186 + 187 + /* switch the cci clock back to the original clock source. */ 188 + ret = clk_set_parent(drv->cci_clk, cci_pll); 189 + if (ret) { 190 + dev_err(dev, "failed to re-parent cci clock\n"); 191 + mtk_ccifreq_set_voltage(drv, inter_voltage); 192 + goto out_unlock; 193 + } 194 + 195 + /* 196 + * If the new voltage is lower than the intermediate voltage or the 197 + * original voltage, scale down to the new voltage. 198 + */ 199 + if (voltage < inter_voltage || voltage < pre_voltage) { 200 + ret = mtk_ccifreq_set_voltage(drv, voltage); 201 + if (ret) { 202 + dev_err(dev, "failed to scale down voltage\n"); 203 + goto out_unlock; 204 + } 205 + } 206 + 207 + drv->pre_freq = *freq; 208 + mutex_unlock(&drv->reg_lock); 209 + 210 + return 0; 211 + 212 + out_restore_voltage: 213 + mtk_ccifreq_set_voltage(drv, pre_voltage); 214 + 215 + out_unlock: 216 + mutex_unlock(&drv->reg_lock); 217 + return ret; 218 + } 219 + 220 + static int mtk_ccifreq_opp_notifier(struct notifier_block *nb, 221 + unsigned long event, void *data) 222 + { 223 + struct dev_pm_opp *opp = data; 224 + struct mtk_ccifreq_drv *drv; 225 + unsigned long freq, volt; 226 + 227 + drv = container_of(nb, struct mtk_ccifreq_drv, opp_nb); 228 + 229 + if (event == OPP_EVENT_ADJUST_VOLTAGE) { 230 + freq = dev_pm_opp_get_freq(opp); 231 + 232 + mutex_lock(&drv->reg_lock); 233 + /* current opp item is changed */ 234 + if (freq == drv->pre_freq) { 235 + volt = dev_pm_opp_get_voltage(opp); 236 + mtk_ccifreq_set_voltage(drv, volt); 237 + } 238 + mutex_unlock(&drv->reg_lock); 239 + } 240 + 241 + return 0; 242 + } 243 + 244 + static struct devfreq_dev_profile mtk_ccifreq_profile = { 245 + .target = mtk_ccifreq_target, 246 + }; 247 + 248 + static int mtk_ccifreq_probe(struct platform_device *pdev) 249 + { 250 + struct device *dev = &pdev->dev; 251 + struct mtk_ccifreq_drv *drv; 252 + struct devfreq_passive_data *passive_data; 253 + struct dev_pm_opp *opp; 254 + unsigned long rate, opp_volt; 255 + int ret; 256 + 257 + drv = devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL); 258 + if (!drv) 259 + return -ENOMEM; 260 + 261 + drv->dev = dev; 262 + drv->soc_data = (const struct mtk_ccifreq_platform_data *) 263 + of_device_get_match_data(&pdev->dev); 264 + mutex_init(&drv->reg_lock); 265 + platform_set_drvdata(pdev, drv); 266 + 267 + drv->cci_clk = devm_clk_get(dev, "cci"); 268 + if (IS_ERR(drv->cci_clk)) { 269 + ret = PTR_ERR(drv->cci_clk); 270 + return dev_err_probe(dev, ret, "failed to get cci clk\n"); 271 + } 272 + 273 + drv->inter_clk = devm_clk_get(dev, "intermediate"); 274 + if (IS_ERR(drv->inter_clk)) { 275 + ret = PTR_ERR(drv->inter_clk); 276 + return dev_err_probe(dev, ret, 277 + "failed to get intermediate clk\n"); 278 + } 279 + 280 + drv->proc_reg = devm_regulator_get_optional(dev, "proc"); 281 + if (IS_ERR(drv->proc_reg)) { 282 + ret = PTR_ERR(drv->proc_reg); 283 + return dev_err_probe(dev, ret, 284 + "failed to get proc regulator\n"); 285 + } 286 + 287 + ret = regulator_enable(drv->proc_reg); 288 + if (ret) { 289 + dev_err(dev, "failed to enable proc regulator\n"); 290 + return ret; 291 + } 292 + 293 + drv->sram_reg = devm_regulator_get_optional(dev, "sram"); 294 + if (IS_ERR(drv->sram_reg)) 295 + drv->sram_reg = NULL; 296 + else { 297 + ret = regulator_enable(drv->sram_reg); 298 + if (ret) { 299 + dev_err(dev, "failed to enable sram regulator\n"); 300 + goto out_free_resources; 301 + } 302 + } 303 + 304 + /* 305 + * We assume min voltage is 0 and tracking target voltage using 306 + * min_volt_shift for each iteration. 307 + * The retry_max is 3 times of expected iteration count. 308 + */ 309 + drv->vtrack_max = 3 * DIV_ROUND_UP(max(drv->soc_data->sram_max_volt, 310 + drv->soc_data->proc_max_volt), 311 + drv->soc_data->min_volt_shift); 312 + 313 + ret = clk_prepare_enable(drv->cci_clk); 314 + if (ret) 315 + goto out_free_resources; 316 + 317 + ret = dev_pm_opp_of_add_table(dev); 318 + if (ret) { 319 + dev_err(dev, "failed to add opp table: %d\n", ret); 320 + goto out_disable_cci_clk; 321 + } 322 + 323 + rate = clk_get_rate(drv->inter_clk); 324 + opp = dev_pm_opp_find_freq_ceil(dev, &rate); 325 + if (IS_ERR(opp)) { 326 + ret = PTR_ERR(opp); 327 + dev_err(dev, "failed to get intermediate opp: %d\n", ret); 328 + goto out_remove_opp_table; 329 + } 330 + drv->inter_voltage = dev_pm_opp_get_voltage(opp); 331 + dev_pm_opp_put(opp); 332 + 333 + rate = U32_MAX; 334 + opp = dev_pm_opp_find_freq_floor(drv->dev, &rate); 335 + if (IS_ERR(opp)) { 336 + dev_err(dev, "failed to get opp\n"); 337 + ret = PTR_ERR(opp); 338 + goto out_remove_opp_table; 339 + } 340 + 341 + opp_volt = dev_pm_opp_get_voltage(opp); 342 + dev_pm_opp_put(opp); 343 + ret = mtk_ccifreq_set_voltage(drv, opp_volt); 344 + if (ret) { 345 + dev_err(dev, "failed to scale to highest voltage %lu in proc_reg\n", 346 + opp_volt); 347 + goto out_remove_opp_table; 348 + } 349 + 350 + passive_data = devm_kzalloc(dev, sizeof(*passive_data), GFP_KERNEL); 351 + if (!passive_data) { 352 + ret = -ENOMEM; 353 + goto out_remove_opp_table; 354 + } 355 + 356 + passive_data->parent_type = CPUFREQ_PARENT_DEV; 357 + drv->devfreq = devm_devfreq_add_device(dev, &mtk_ccifreq_profile, 358 + DEVFREQ_GOV_PASSIVE, 359 + passive_data); 360 + if (IS_ERR(drv->devfreq)) { 361 + ret = -EPROBE_DEFER; 362 + dev_err(dev, "failed to add devfreq device: %ld\n", 363 + PTR_ERR(drv->devfreq)); 364 + goto out_remove_opp_table; 365 + } 366 + 367 + drv->opp_nb.notifier_call = mtk_ccifreq_opp_notifier; 368 + ret = dev_pm_opp_register_notifier(dev, &drv->opp_nb); 369 + if (ret) { 370 + dev_err(dev, "failed to register opp notifier: %d\n", ret); 371 + goto out_remove_opp_table; 372 + } 373 + return 0; 374 + 375 + out_remove_opp_table: 376 + dev_pm_opp_of_remove_table(dev); 377 + 378 + out_disable_cci_clk: 379 + clk_disable_unprepare(drv->cci_clk); 380 + 381 + out_free_resources: 382 + if (regulator_is_enabled(drv->proc_reg)) 383 + regulator_disable(drv->proc_reg); 384 + if (drv->sram_reg && regulator_is_enabled(drv->sram_reg)) 385 + regulator_disable(drv->sram_reg); 386 + 387 + return ret; 388 + } 389 + 390 + static int mtk_ccifreq_remove(struct platform_device *pdev) 391 + { 392 + struct device *dev = &pdev->dev; 393 + struct mtk_ccifreq_drv *drv; 394 + 395 + drv = platform_get_drvdata(pdev); 396 + 397 + dev_pm_opp_unregister_notifier(dev, &drv->opp_nb); 398 + dev_pm_opp_of_remove_table(dev); 399 + clk_disable_unprepare(drv->cci_clk); 400 + regulator_disable(drv->proc_reg); 401 + if (drv->sram_reg) 402 + regulator_disable(drv->sram_reg); 403 + 404 + return 0; 405 + } 406 + 407 + static const struct mtk_ccifreq_platform_data mt8183_platform_data = { 408 + .min_volt_shift = 100000, 409 + .max_volt_shift = 200000, 410 + .proc_max_volt = 1150000, 411 + }; 412 + 413 + static const struct mtk_ccifreq_platform_data mt8186_platform_data = { 414 + .min_volt_shift = 100000, 415 + .max_volt_shift = 250000, 416 + .proc_max_volt = 1118750, 417 + .sram_min_volt = 850000, 418 + .sram_max_volt = 1118750, 419 + }; 420 + 421 + static const struct of_device_id mtk_ccifreq_machines[] = { 422 + { .compatible = "mediatek,mt8183-cci", .data = &mt8183_platform_data }, 423 + { .compatible = "mediatek,mt8186-cci", .data = &mt8186_platform_data }, 424 + { }, 425 + }; 426 + MODULE_DEVICE_TABLE(of, mtk_ccifreq_machines); 427 + 428 + static struct platform_driver mtk_ccifreq_platdrv = { 429 + .probe = mtk_ccifreq_probe, 430 + .remove = mtk_ccifreq_remove, 431 + .driver = { 432 + .name = "mtk-ccifreq", 433 + .of_match_table = mtk_ccifreq_machines, 434 + }, 435 + }; 436 + module_platform_driver(mtk_ccifreq_platdrv); 437 + 438 + MODULE_DESCRIPTION("MediaTek CCI devfreq driver"); 439 + MODULE_AUTHOR("Jia-Wei Chang <jia-wei.chang@mediatek.com>"); 440 + MODULE_LICENSE("GPL v2");
+3 -1
drivers/devfreq/tegra30-devfreq.c
··· 922 922 923 923 devfreq = devm_devfreq_add_device(&pdev->dev, &tegra_devfreq_profile, 924 924 "tegra_actmon", NULL); 925 - if (IS_ERR(devfreq)) 925 + if (IS_ERR(devfreq)) { 926 + dev_err(&pdev->dev, "Failed to add device: %pe\n", devfreq); 926 927 return PTR_ERR(devfreq); 928 + } 927 929 928 930 return 0; 929 931 }
+2 -2
kernel/power/qos.c
··· 531 531 { 532 532 int ret; 533 533 534 - if (IS_ERR_OR_NULL(qos) || !req) 534 + if (IS_ERR_OR_NULL(qos) || !req || value < 0) 535 535 return -EINVAL; 536 536 537 537 if (WARN(freq_qos_request_active(req), ··· 563 563 */ 564 564 int freq_qos_update_request(struct freq_qos_request *req, s32 new_value) 565 565 { 566 - if (!req) 566 + if (!req || new_value < 0) 567 567 return -EINVAL; 568 568 569 569 if (WARN(!freq_qos_request_active(req),
+3 -3
tools/power/pm-graph/README
··· 6 6 |_| |___/ |_| 7 7 8 8 pm-graph: suspend/resume/boot timing analysis tools 9 - Version: 5.8 9 + Version: 5.9 10 10 Author: Todd Brandt <todd.e.brandt@intel.com> 11 11 Home Page: https://01.org/pm-graph 12 12 ··· 97 97 (kernel/pre-3.15/enable_trace_events_suspend_resume.patch) 98 98 (kernel/pre-3.15/enable_trace_events_device_pm_callback.patch) 99 99 100 - If you're using a kernel older than 3.15.0, the following 101 - additional kernel parameters are required: 100 + If you're using bootgraph, or sleepgraph with a kernel older than 3.15.0, 101 + the following additional kernel parameters are required: 102 102 (e.g. in file /etc/default/grub) 103 103 GRUB_CMDLINE_LINUX_DEFAULT="... initcall_debug log_buf_len=32M ..." 104 104
+11 -9
tools/power/pm-graph/bootgraph.py
··· 69 69 bootloader = 'grub' 70 70 blexec = [] 71 71 def __init__(self): 72 - self.hostname = platform.node() 72 + self.kernel, self.hostname = 'unknown', platform.node() 73 73 self.testtime = datetime.now().strftime('%Y-%m-%d_%H:%M:%S') 74 74 if os.path.exists('/proc/version'): 75 75 fp = open('/proc/version', 'r') 76 - val = fp.read().strip() 76 + self.kernel = self.kernelVersion(fp.read().strip()) 77 77 fp.close() 78 - self.kernel = self.kernelVersion(val) 79 - else: 80 - self.kernel = 'unknown' 81 78 self.testdir = datetime.now().strftime('boot-%y%m%d-%H%M%S') 82 79 def kernelVersion(self, msg): 83 - return msg.split()[2] 80 + m = re.match('^[Ll]inux *[Vv]ersion *(?P<v>\S*) .*', msg) 81 + if m: 82 + return m.group('v') 83 + return 'unknown' 84 84 def checkFtraceKernelVersion(self): 85 - val = tuple(map(int, self.kernel.split('-')[0].split('.'))) 86 - if val >= (4, 10, 0): 87 - return True 85 + m = re.match('^(?P<x>[0-9]*)\.(?P<y>[0-9]*)\.(?P<z>[0-9]*).*', self.kernel) 86 + if m: 87 + val = tuple(map(int, m.groups())) 88 + if val >= (4, 10, 0): 89 + return True 88 90 return False 89 91 def kernelParams(self): 90 92 cmdline = 'initcall_debug log_buf_len=32M'
+1 -1
tools/power/pm-graph/config/custom-timeline-functions.cfg
··· 125 125 suspend_console: 126 126 acpi_pm_prepare: 127 127 syscore_suspend: 128 - arch_thaw_secondary_cpus_end: 128 + arch_enable_nonboot_cpus_end: 129 129 syscore_resume: 130 130 acpi_pm_finish: 131 131 resume_console:
+345 -173
tools/power/pm-graph/sleepgraph.py
··· 66 66 from subprocess import call, Popen, PIPE 67 67 import base64 68 68 69 + debugtiming = False 70 + mystarttime = time.time() 69 71 def pprint(msg): 70 - print(msg) 72 + if debugtiming: 73 + print('[%09.3f] %s' % (time.time()-mystarttime, msg)) 74 + else: 75 + print(msg) 71 76 sys.stdout.flush() 72 77 73 78 def ascii(text): ··· 86 81 # store system values and test parameters 87 82 class SystemValues: 88 83 title = 'SleepGraph' 89 - version = '5.8' 84 + version = '5.9' 90 85 ansi = False 91 86 rs = 0 92 87 display = '' 93 88 gzip = False 94 89 sync = False 95 90 wifi = False 91 + netfix = False 96 92 verbose = False 97 93 testlog = True 98 94 dmesglog = True ··· 114 108 cpucount = 0 115 109 memtotal = 204800 116 110 memfree = 204800 111 + osversion = '' 117 112 srgap = 0 118 113 cgexp = False 119 114 testdir = '' ··· 123 116 fpdtpath = '/sys/firmware/acpi/tables/FPDT' 124 117 epath = '/sys/kernel/debug/tracing/events/power/' 125 118 pmdpath = '/sys/power/pm_debug_messages' 119 + s0ixpath = '/sys/module/intel_pmc_core/parameters/warn_on_s0ix_failures' 126 120 acpipath='/sys/module/acpi/parameters/debug_level' 127 121 traceevents = [ 128 122 'suspend_resume', ··· 164 156 ftop = False 165 157 usetraceevents = False 166 158 usetracemarkers = True 159 + useftrace = True 167 160 usekprobes = True 168 161 usedevsrc = False 169 162 useprocmon = False ··· 288 279 'intel_fbdev_set_suspend': {}, 289 280 } 290 281 infocmds = [ 282 + [0, 'sysinfo', 'uname', '-a'], 283 + [0, 'cpuinfo', 'head', '-7', '/proc/cpuinfo'], 291 284 [0, 'kparams', 'cat', '/proc/cmdline'], 292 285 [0, 'mcelog', 'mcelog'], 293 286 [0, 'pcidevices', 'lspci', '-tv'], 294 - [0, 'usbdevices', 'lsusb', '-t'], 287 + [0, 'usbdevices', 'lsusb', '-tv'], 288 + [0, 'acpidevices', 'sh', '-c', 'ls -l /sys/bus/acpi/devices/*/physical_node'], 289 + [0, 's0ix_require', 'cat', '/sys/kernel/debug/pmc_core/substate_requirements'], 290 + [0, 's0ix_debug', 'cat', '/sys/kernel/debug/pmc_core/slp_s0_debug_status'], 291 + [1, 's0ix_residency', 'cat', '/sys/kernel/debug/pmc_core/slp_s0_residency_usec'], 295 292 [1, 'interrupts', 'cat', '/proc/interrupts'], 296 293 [1, 'wakeups', 'cat', '/sys/kernel/debug/wakeup_sources'], 297 294 [2, 'gpecounts', 'sh', '-c', 'grep -v invalid /sys/firmware/acpi/interrupts/*'], ··· 373 358 self.outputResult({'error':msg}) 374 359 sys.exit(1) 375 360 return False 376 - def usable(self, file): 377 - return (os.path.exists(file) and os.path.getsize(file) > 0) 361 + def usable(self, file, ishtml=False): 362 + if not os.path.exists(file) or os.path.getsize(file) < 1: 363 + return False 364 + if ishtml: 365 + try: 366 + fp = open(file, 'r') 367 + res = fp.read(1000) 368 + fp.close() 369 + except: 370 + return False 371 + if '<html>' not in res: 372 + return False 373 + return True 378 374 def getExec(self, cmd): 379 375 try: 380 376 fp = Popen(['which', cmd], stdout=PIPE, stderr=PIPE).stdout ··· 439 413 r = info['bios-release-date'] if 'bios-release-date' in info else '' 440 414 self.sysstamp = '# sysinfo | man:%s | plat:%s | cpu:%s | bios:%s | biosdate:%s | numcpu:%d | memsz:%d | memfr:%d' % \ 441 415 (m, p, c, b, r, self.cpucount, self.memtotal, self.memfree) 416 + if self.osversion: 417 + self.sysstamp += ' | os:%s' % self.osversion 442 418 def printSystemInfo(self, fatal=False): 443 419 self.rootCheck(True) 444 420 out = dmidecode(self.mempath, fatal) 445 421 if len(out) < 1: 446 422 return 447 423 fmt = '%-24s: %s' 424 + if self.osversion: 425 + print(fmt % ('os-version', self.osversion)) 448 426 for name in sorted(out): 449 427 print(fmt % (name, out[name])) 450 428 print(fmt % ('cpucount', ('%d' % self.cpucount))) ··· 456 426 print(fmt % ('memfree', ('%d kB' % self.memfree))) 457 427 def cpuInfo(self): 458 428 self.cpucount = 0 459 - fp = open('/proc/cpuinfo', 'r') 460 - for line in fp: 461 - if re.match('^processor[ \t]*:[ \t]*[0-9]*', line): 462 - self.cpucount += 1 463 - fp.close() 464 - fp = open('/proc/meminfo', 'r') 465 - for line in fp: 466 - m = re.match('^MemTotal:[ \t]*(?P<sz>[0-9]*) *kB', line) 467 - if m: 468 - self.memtotal = int(m.group('sz')) 469 - m = re.match('^MemFree:[ \t]*(?P<sz>[0-9]*) *kB', line) 470 - if m: 471 - self.memfree = int(m.group('sz')) 472 - fp.close() 429 + if os.path.exists('/proc/cpuinfo'): 430 + with open('/proc/cpuinfo', 'r') as fp: 431 + for line in fp: 432 + if re.match('^processor[ \t]*:[ \t]*[0-9]*', line): 433 + self.cpucount += 1 434 + if os.path.exists('/proc/meminfo'): 435 + with open('/proc/meminfo', 'r') as fp: 436 + for line in fp: 437 + m = re.match('^MemTotal:[ \t]*(?P<sz>[0-9]*) *kB', line) 438 + if m: 439 + self.memtotal = int(m.group('sz')) 440 + m = re.match('^MemFree:[ \t]*(?P<sz>[0-9]*) *kB', line) 441 + if m: 442 + self.memfree = int(m.group('sz')) 443 + if os.path.exists('/etc/os-release'): 444 + with open('/etc/os-release', 'r') as fp: 445 + for line in fp: 446 + if line.startswith('PRETTY_NAME='): 447 + self.osversion = line[12:].strip().replace('"', '') 473 448 def initTestOutput(self, name): 474 449 self.prefix = self.hostname 475 450 v = open('/proc/version', 'r').read().strip() ··· 733 698 return False 734 699 return True 735 700 def fsetVal(self, val, path): 701 + if not self.useftrace: 702 + return False 736 703 return self.setVal(val, self.tpath+path) 737 704 def getVal(self, file): 738 705 res = '' ··· 748 711 pass 749 712 return res 750 713 def fgetVal(self, path): 714 + if not self.useftrace: 715 + return '' 751 716 return self.getVal(self.tpath+path) 752 717 def cleanupFtrace(self): 753 - if(self.usecallgraph or self.usetraceevents or self.usedevsrc): 718 + if self.useftrace: 754 719 self.fsetVal('0', 'events/kprobes/enable') 755 720 self.fsetVal('', 'kprobe_events') 756 721 self.fsetVal('1024', 'buffer_size_kb') ··· 773 734 return True 774 735 return False 775 736 def initFtrace(self, quiet=False): 737 + if not self.useftrace: 738 + return 776 739 if not quiet: 777 740 sysvals.printSystemInfo(False) 778 741 pprint('INITIALIZING FTRACE...') 779 742 # turn trace off 780 743 self.fsetVal('0', 'tracing_on') 781 744 self.cleanupFtrace() 782 - self.testVal(self.pmdpath, 'basic', '1') 783 745 # set the trace clock to global 784 746 self.fsetVal('global', 'trace_clock') 785 747 self.fsetVal('nop', 'current_tracer') ··· 806 766 # set trace type 807 767 self.fsetVal('function_graph', 'current_tracer') 808 768 self.fsetVal('', 'set_ftrace_filter') 769 + # temporary hack to fix https://bugzilla.kernel.org/show_bug.cgi?id=212761 770 + fp = open(self.tpath+'set_ftrace_notrace', 'w') 771 + fp.write('native_queued_spin_lock_slowpath\ndev_driver_string') 772 + fp.close() 809 773 # set trace format options 810 774 self.fsetVal('print-parent', 'trace_options') 811 775 self.fsetVal('funcgraph-abstime', 'trace_options') ··· 890 846 fp.write('# turbostat %s\n' % test['turbo']) 891 847 if 'wifi' in test: 892 848 fp.write('# wifi %s\n' % test['wifi']) 849 + if 'netfix' in test: 850 + fp.write('# netfix %s\n' % test['netfix']) 893 851 if test['error'] or len(testdata) > 1: 894 852 fp.write('# enter_sleep_error %s\n' % test['error']) 895 853 return fp ··· 911 865 fp.write('error%s: %s\n' % (n, testdata['error'])) 912 866 else: 913 867 fp.write('result%s: pass\n' % n) 868 + if 'mode' in testdata: 869 + fp.write('mode%s: %s\n' % (n, testdata['mode'])) 914 870 for v in ['suspend', 'resume', 'boot', 'lastinit']: 915 871 if v in testdata: 916 872 fp.write('%s%s: %.3f\n' % (v, n, testdata[v])) ··· 949 901 fp.write(text) 950 902 fp.close() 951 903 def dlog(self, text): 904 + if not self.dmesgfile: 905 + return 952 906 self.putlog(self.dmesgfile, '# %s\n' % text) 953 907 def flog(self, text): 954 908 self.putlog(self.ftracefile, text) ··· 1004 954 dirname = props[dev].syspath 1005 955 if not dirname or not os.path.exists(dirname): 1006 956 continue 1007 - with open(dirname+'/power/async') as fp: 1008 - text = fp.read() 1009 - props[dev].isasync = False 1010 - if 'enabled' in text: 957 + props[dev].isasync = False 958 + if os.path.exists(dirname+'/power/async'): 959 + fp = open(dirname+'/power/async') 960 + if 'enabled' in fp.read(): 1011 961 props[dev].isasync = True 962 + fp.close() 1012 963 fields = os.listdir(dirname) 1013 - if 'product' in fields: 1014 - with open(dirname+'/product', 'rb') as fp: 1015 - props[dev].altname = ascii(fp.read()) 1016 - elif 'name' in fields: 1017 - with open(dirname+'/name', 'rb') as fp: 1018 - props[dev].altname = ascii(fp.read()) 1019 - elif 'model' in fields: 1020 - with open(dirname+'/model', 'rb') as fp: 1021 - props[dev].altname = ascii(fp.read()) 1022 - elif 'description' in fields: 1023 - with open(dirname+'/description', 'rb') as fp: 1024 - props[dev].altname = ascii(fp.read()) 1025 - elif 'id' in fields: 1026 - with open(dirname+'/id', 'rb') as fp: 1027 - props[dev].altname = ascii(fp.read()) 1028 - elif 'idVendor' in fields and 'idProduct' in fields: 1029 - idv, idp = '', '' 1030 - with open(dirname+'/idVendor', 'rb') as fp: 1031 - idv = ascii(fp.read()).strip() 1032 - with open(dirname+'/idProduct', 'rb') as fp: 1033 - idp = ascii(fp.read()).strip() 1034 - props[dev].altname = '%s:%s' % (idv, idp) 964 + for file in ['product', 'name', 'model', 'description', 'id', 'idVendor']: 965 + if file not in fields: 966 + continue 967 + try: 968 + with open(os.path.join(dirname, file), 'rb') as fp: 969 + props[dev].altname = ascii(fp.read()) 970 + except: 971 + continue 972 + if file == 'idVendor': 973 + idv, idp = props[dev].altname.strip(), '' 974 + try: 975 + with open(os.path.join(dirname, 'idProduct'), 'rb') as fp: 976 + idp = ascii(fp.read()).strip() 977 + except: 978 + props[dev].altname = '' 979 + break 980 + props[dev].altname = '%s:%s' % (idv, idp) 981 + break 1035 982 if props[dev].altname: 1036 983 out = props[dev].altname.strip().replace('\n', ' ')\ 1037 984 .replace(',', ' ').replace(';', ' ') ··· 1094 1047 self.cmd1[name] = self.dictify(info, delta) 1095 1048 elif not debug and delta and name in self.cmd1: 1096 1049 before, after = self.cmd1[name], self.dictify(info, delta) 1097 - dinfo = ('\t%s\n' % before['@']) if '@' in before else '' 1050 + dinfo = ('\t%s\n' % before['@']) if '@' in before and len(before) > 1 else '' 1098 1051 prefix = self.commonPrefix(list(before.keys())) 1099 1052 for key in sorted(before): 1100 1053 if key in after and before[key] != after[key]: ··· 1175 1128 val = valline[idx] 1176 1129 out.append('%s=%s' % (key, val)) 1177 1130 return '|'.join(out) 1131 + def netfixon(self, net='both'): 1132 + cmd = self.getExec('netfix') 1133 + if not cmd: 1134 + return '' 1135 + fp = Popen([cmd, '-s', net, 'on'], stdout=PIPE, stderr=PIPE).stdout 1136 + out = ascii(fp.read()).strip() 1137 + fp.close() 1138 + return out 1139 + def wifiRepair(self): 1140 + out = self.netfixon('wifi') 1141 + if not out or 'error' in out.lower(): 1142 + return '' 1143 + m = re.match('WIFI \S* ONLINE (?P<action>\S*)', out) 1144 + if not m: 1145 + return 'dead' 1146 + return m.group('action') 1178 1147 def wifiDetails(self, dev): 1179 1148 try: 1180 1149 info = open('/sys/class/net/%s/device/uevent' % dev, 'r').read().strip() ··· 1207 1144 except: 1208 1145 return '' 1209 1146 for line in reversed(w.split('\n')): 1210 - m = re.match(' *(?P<dev>.*): (?P<stat>[0-9a-f]*) .*', w.split('\n')[-1]) 1147 + m = re.match(' *(?P<dev>.*): (?P<stat>[0-9a-f]*) .*', line) 1211 1148 if not m or (dev and dev != m.group('dev')): 1212 1149 continue 1213 1150 return m.group('dev') 1214 1151 return '' 1215 - def pollWifi(self, dev, timeout=60): 1152 + def pollWifi(self, dev, timeout=10): 1216 1153 start = time.time() 1217 1154 while (time.time() - start) < timeout: 1218 1155 w = self.checkWifi(dev) ··· 1220 1157 return '%s reconnected %.2f' % \ 1221 1158 (self.wifiDetails(dev), max(0, time.time() - start)) 1222 1159 time.sleep(0.01) 1160 + if self.netfix: 1161 + res = self.wifiRepair() 1162 + if res: 1163 + timeout = max(0, time.time() - start) 1164 + return '%s %s %d' % (self.wifiDetails(dev), res, timeout) 1223 1165 return '%s timeout %d' % (self.wifiDetails(dev), timeout) 1224 1166 def errorSummary(self, errinfo, msg): 1225 1167 found = False ··· 1351 1283 switchvalues = ['enable', 'disable', 'on', 'off', 'true', 'false', '1', '0'] 1352 1284 switchoff = ['disable', 'off', 'false', '0'] 1353 1285 suspendmodename = { 1354 - 'freeze': 'Freeze (S0)', 1355 - 'standby': 'Standby (S1)', 1356 - 'mem': 'Suspend (S3)', 1357 - 'disk': 'Hibernate (S4)' 1286 + 'standby': 'standby (S1)', 1287 + 'freeze': 'freeze (S2idle)', 1288 + 'mem': 'suspend (S3)', 1289 + 'disk': 'hibernate (S4)' 1358 1290 } 1359 1291 1360 1292 # Class: DevProps ··· 1444 1376 'INVALID' : r'(?i).*\bINVALID\b.*', 1445 1377 'CRASH' : r'(?i).*\bCRASHED\b.*', 1446 1378 'TIMEOUT' : r'(?i).*\bTIMEOUT\b.*', 1379 + 'ABORT' : r'(?i).*\bABORT\b.*', 1447 1380 'IRQ' : r'.*\bgenirq: .*', 1448 1381 'TASKFAIL': r'.*Freezing of tasks *.*', 1449 1382 'ACPI' : r'.*\bACPI *(?P<b>[A-Za-z]*) *Error[: ].*', ··· 1793 1724 if 'waking' in self.dmesg[lp]: 1794 1725 tCnt = self.dmesg[lp]['waking'][0] 1795 1726 if self.dmesg[lp]['waking'][1] >= 0.001: 1796 - tTry = '-%.0f' % (round(self.dmesg[lp]['waking'][1] * 1000)) 1727 + tTry = '%.0f' % (round(self.dmesg[lp]['waking'][1] * 1000)) 1797 1728 else: 1798 - tTry = '-%.3f' % (self.dmesg[lp]['waking'][1] * 1000) 1729 + tTry = '%.3f' % (self.dmesg[lp]['waking'][1] * 1000) 1799 1730 text = '%.0f (%s ms waking %d times)' % (tL * 1000, tTry, tCnt) 1800 1731 else: 1801 1732 text = '%.0f' % (tL * 1000) ··· 2176 2107 # set resume complete to end at end marker 2177 2108 if 'resume_complete' in dm: 2178 2109 dm['resume_complete']['end'] = time 2110 + def initcall_debug_call(self, line, quick=False): 2111 + m = re.match('.*(\[ *)(?P<t>[0-9\.]*)(\]) .* (?P<f>.*)\: '+\ 2112 + 'PM: *calling .* @ (?P<n>.*), parent: (?P<p>.*)', line) 2113 + if not m: 2114 + m = re.match('.*(\[ *)(?P<t>[0-9\.]*)(\]) .* (?P<f>.*)\: '+\ 2115 + 'calling .* @ (?P<n>.*), parent: (?P<p>.*)', line) 2116 + if not m: 2117 + m = re.match('.*(\[ *)(?P<t>[0-9\.]*)(\]) calling '+\ 2118 + '(?P<f>.*)\+ @ (?P<n>.*), parent: (?P<p>.*)', line) 2119 + if m: 2120 + return True if quick else m.group('t', 'f', 'n', 'p') 2121 + return False if quick else ('', '', '', '') 2122 + def initcall_debug_return(self, line, quick=False): 2123 + m = re.match('.*(\[ *)(?P<t>[0-9\.]*)(\]) .* (?P<f>.*)\: PM: '+\ 2124 + '.* returned (?P<r>[0-9]*) after (?P<dt>[0-9]*) usecs', line) 2125 + if not m: 2126 + m = re.match('.*(\[ *)(?P<t>[0-9\.]*)(\]) .* (?P<f>.*)\: '+\ 2127 + '.* returned (?P<r>[0-9]*) after (?P<dt>[0-9]*) usecs', line) 2128 + if not m: 2129 + m = re.match('.*(\[ *)(?P<t>[0-9\.]*)(\]) call '+\ 2130 + '(?P<f>.*)\+ returned .* after (?P<dt>.*) usecs', line) 2131 + if m: 2132 + return True if quick else m.group('t', 'f', 'dt') 2133 + return False if quick else ('', '', '') 2179 2134 def debugPrint(self): 2180 2135 for p in self.sortedPhases(): 2181 2136 list = self.dmesg[p]['list'] ··· 2973 2880 cmdlinefmt = '^# command \| (?P<cmd>.*)' 2974 2881 kparamsfmt = '^# kparams \| (?P<kp>.*)' 2975 2882 devpropfmt = '# Device Properties: .*' 2976 - pinfofmt = '# platform-(?P<val>[a-z,A-Z,0-9]*): (?P<info>.*)' 2883 + pinfofmt = '# platform-(?P<val>[a-z,A-Z,0-9,_]*): (?P<info>.*)' 2977 2884 tracertypefmt = '# tracer: (?P<t>.*)' 2978 2885 firmwarefmt = '# fwsuspend (?P<s>[0-9]*) fwresume (?P<r>[0-9]*)$' 2979 2886 procexecfmt = 'ps - (?P<ps>.*)$' 2887 + procmultifmt = '@(?P<n>[0-9]*)\|(?P<ps>.*)$' 2980 2888 ftrace_line_fmt_fg = \ 2981 2889 '^ *(?P<time>[0-9\.]*) *\| *(?P<cpu>[0-9]*)\)'+\ 2982 2890 ' *(?P<proc>.*)-(?P<pid>[0-9]*) *\|'+\ ··· 2987 2893 '(?P<flags>\S*) *(?P<time>[0-9\.]*): *'+\ 2988 2894 '(?P<msg>.*)' 2989 2895 machinesuspend = 'machine_suspend\[.*' 2896 + multiproclist = dict() 2897 + multiproctime = 0.0 2898 + multiproccnt = 0 2990 2899 def __init__(self): 2991 2900 self.stamp = '' 2992 2901 self.sysinfo = '' ··· 3160 3063 self.ttemp = dict() 3161 3064 3162 3065 class ProcessMonitor: 3066 + maxchars = 512 3163 3067 def __init__(self): 3164 3068 self.proclist = dict() 3165 3069 self.running = False ··· 3186 3088 if ujiff > 0 or kjiff > 0: 3187 3089 running[pid] = ujiff + kjiff 3188 3090 process.wait() 3189 - out = '' 3091 + out = [''] 3190 3092 for pid in running: 3191 3093 jiffies = running[pid] 3192 3094 val = self.proclist[pid] 3193 - if out: 3194 - out += ',' 3195 - out += '%s-%s %d' % (val['name'], pid, jiffies) 3196 - return 'ps - '+out 3095 + if len(out[-1]) > self.maxchars: 3096 + out.append('') 3097 + elif len(out[-1]) > 0: 3098 + out[-1] += ',' 3099 + out[-1] += '%s-%s %d' % (val['name'], pid, jiffies) 3100 + if len(out) > 1: 3101 + for line in out: 3102 + sysvals.fsetVal('ps - @%d|%s' % (len(out), line), 'trace_marker') 3103 + else: 3104 + sysvals.fsetVal('ps - %s' % out[0], 'trace_marker') 3197 3105 def processMonitor(self, tid): 3198 3106 while self.running: 3199 - out = self.procstat() 3200 - if out: 3201 - sysvals.fsetVal(out, 'trace_marker') 3107 + self.procstat() 3202 3108 def start(self): 3203 3109 self.thread = Thread(target=self.processMonitor, args=(0,)) 3204 3110 self.running = True ··· 3246 3144 3247 3145 # Function: appendIncompleteTraceLog 3248 3146 # Description: 3249 - # [deprecated for kernel 3.15 or newer] 3250 3147 # Adds callgraph data which lacks trace event data. This is only 3251 3148 # for timelines generated from 3.15 or older 3252 3149 # Arguments: ··· 3347 3246 dev['ftrace'] = cg 3348 3247 break 3349 3248 3249 + # Function: loadTraceLog 3250 + # Description: 3251 + # load the ftrace file into memory and fix up any ordering issues 3252 + # Output: 3253 + # TestProps instance and an array of lines in proper order 3254 + def loadTraceLog(): 3255 + tp, data, lines, trace = TestProps(), dict(), [], [] 3256 + tf = sysvals.openlog(sysvals.ftracefile, 'r') 3257 + for line in tf: 3258 + # remove any latent carriage returns 3259 + line = line.replace('\r\n', '') 3260 + if tp.stampInfo(line, sysvals): 3261 + continue 3262 + # ignore all other commented lines 3263 + if line[0] == '#': 3264 + continue 3265 + # ftrace line: parse only valid lines 3266 + m = re.match(tp.ftrace_line_fmt, line) 3267 + if(not m): 3268 + continue 3269 + dur = m.group('dur') if tp.cgformat else 'traceevent' 3270 + info = (m.group('time'), m.group('proc'), m.group('pid'), 3271 + m.group('msg'), dur) 3272 + # group the data by timestamp 3273 + t = float(info[0]) 3274 + if t in data: 3275 + data[t].append(info) 3276 + else: 3277 + data[t] = [info] 3278 + # we only care about trace event ordering 3279 + if (info[3].startswith('suspend_resume:') or \ 3280 + info[3].startswith('tracing_mark_write:')) and t not in trace: 3281 + trace.append(t) 3282 + tf.close() 3283 + for t in sorted(data): 3284 + first, last, blk = [], [], data[t] 3285 + if len(blk) > 1 and t in trace: 3286 + # move certain lines to the start or end of a timestamp block 3287 + for i in range(len(blk)): 3288 + if 'SUSPEND START' in blk[i][3]: 3289 + first.append(i) 3290 + elif re.match('.* timekeeping_freeze.*begin', blk[i][3]): 3291 + last.append(i) 3292 + elif re.match('.* timekeeping_freeze.*end', blk[i][3]): 3293 + first.append(i) 3294 + elif 'RESUME COMPLETE' in blk[i][3]: 3295 + last.append(i) 3296 + if len(first) == 1 and len(last) == 0: 3297 + blk.insert(0, blk.pop(first[0])) 3298 + elif len(last) == 1 and len(first) == 0: 3299 + blk.append(blk.pop(last[0])) 3300 + for info in blk: 3301 + lines.append(info) 3302 + return (tp, lines) 3303 + 3350 3304 # Function: parseTraceLog 3351 3305 # Description: 3352 3306 # Analyze an ftrace log output file generated from this app during ··· 3427 3271 3428 3272 # extract the callgraph and traceevent data 3429 3273 s2idle_enter = hwsus = False 3430 - tp = TestProps() 3431 3274 testruns, testdata = [], [] 3432 3275 testrun, data, limbo = 0, 0, True 3433 - tf = sysvals.openlog(sysvals.ftracefile, 'r') 3434 3276 phase = 'suspend_prepare' 3435 - for line in tf: 3436 - # remove any latent carriage returns 3437 - line = line.replace('\r\n', '') 3438 - if tp.stampInfo(line, sysvals): 3439 - continue 3440 - # ignore all other commented lines 3441 - if line[0] == '#': 3442 - continue 3443 - # ftrace line: parse only valid lines 3444 - m = re.match(tp.ftrace_line_fmt, line) 3445 - if(not m): 3446 - continue 3277 + tp, tf = loadTraceLog() 3278 + for m_time, m_proc, m_pid, m_msg, m_param3 in tf: 3447 3279 # gather the basic message data from the line 3448 - m_time = m.group('time') 3449 - m_proc = m.group('proc') 3450 - m_pid = m.group('pid') 3451 - m_msg = m.group('msg') 3452 - if(tp.cgformat): 3453 - m_param3 = m.group('dur') 3454 - else: 3455 - m_param3 = 'traceevent' 3456 3280 if(m_time and m_pid and m_msg): 3457 3281 t = FTraceLine(m_time, m_msg, m_param3) 3458 3282 pid = int(m_pid) ··· 3458 3322 if t.type == 'tracing_mark_write': 3459 3323 m = re.match(tp.procexecfmt, t.name) 3460 3324 if(m): 3461 - proclist = dict() 3462 - for ps in m.group('ps').split(','): 3325 + parts, msg = 1, m.group('ps') 3326 + m = re.match(tp.procmultifmt, msg) 3327 + if(m): 3328 + parts, msg = int(m.group('n')), m.group('ps') 3329 + if tp.multiproccnt == 0: 3330 + tp.multiproctime = t.time 3331 + tp.multiproclist = dict() 3332 + proclist = tp.multiproclist 3333 + tp.multiproccnt += 1 3334 + else: 3335 + proclist = dict() 3336 + tp.multiproccnt = 0 3337 + for ps in msg.split(','): 3463 3338 val = ps.split() 3464 - if not val: 3339 + if not val or len(val) != 2: 3465 3340 continue 3466 3341 name = val[0].replace('--', '-') 3467 3342 proclist[name] = int(val[1]) 3468 - data.pstl[t.time] = proclist 3343 + if parts == 1: 3344 + data.pstl[t.time] = proclist 3345 + elif parts == tp.multiproccnt: 3346 + data.pstl[tp.multiproctime] = proclist 3347 + tp.multiproccnt = 0 3469 3348 continue 3470 3349 # find the end of resume 3471 3350 if(t.endMarker()): ··· 3696 3545 testrun.ftemp[key].append(FTraceCallGraph(pid, sysvals)) 3697 3546 if(res == -1): 3698 3547 testrun.ftemp[key][-1].addLine(t) 3699 - tf.close() 3700 3548 if len(testdata) < 1: 3701 3549 sysvals.vprint('WARNING: ftrace start marker is missing') 3702 3550 if data and not data.devicegroups: ··· 3817 3667 if p not in data.dmesg: 3818 3668 if not terr: 3819 3669 ph = p if 'machine' in p else lp 3820 - terr = '%s%s failed in %s phase' % (sysvals.suspendmode, tn, ph) 3670 + if p == 'suspend_machine': 3671 + sm = sysvals.suspendmode 3672 + if sm in suspendmodename: 3673 + sm = suspendmodename[sm] 3674 + terr = 'test%s did not enter %s power mode' % (tn, sm) 3675 + else: 3676 + terr = '%s%s failed in %s phase' % (sysvals.suspendmode, tn, ph) 3821 3677 pprint('TEST%s FAILED: %s' % (tn, terr)) 3822 3678 error.append(terr) 3823 3679 if data.tSuspended == 0: ··· 3864 3708 3865 3709 # Function: loadKernelLog 3866 3710 # Description: 3867 - # [deprecated for kernel 3.15.0 or newer] 3868 3711 # load the dmesg file into memory and fix up any ordering issues 3869 - # The dmesg filename is taken from sysvals 3870 3712 # Output: 3871 3713 # An array of empty Data objects with only their dmesgtext attributes set 3872 3714 def loadKernelLog(): ··· 3890 3736 if(not m): 3891 3737 continue 3892 3738 msg = m.group("msg") 3893 - if(re.match('PM: Syncing filesystems.*', msg)): 3739 + if re.match('PM: Syncing filesystems.*', msg) or \ 3740 + re.match('PM: suspend entry.*', msg): 3894 3741 if(data): 3895 3742 testruns.append(data) 3896 3743 data = Data(len(testruns)) ··· 3902 3747 if(m): 3903 3748 sysvals.stamp['kernel'] = m.group('k') 3904 3749 m = re.match('PM: Preparing system for (?P<m>.*) sleep', msg) 3905 - if(m): 3750 + if not m: 3751 + m = re.match('PM: Preparing system for sleep \((?P<m>.*)\)', msg) 3752 + if m: 3906 3753 sysvals.stamp['mode'] = sysvals.suspendmode = m.group('m') 3907 3754 data.dmesgtext.append(line) 3908 3755 lf.close() 3909 3756 3757 + if sysvals.suspendmode == 's2idle': 3758 + sysvals.suspendmode = 'freeze' 3759 + elif sysvals.suspendmode == 'deep': 3760 + sysvals.suspendmode = 'mem' 3910 3761 if data: 3911 3762 testruns.append(data) 3912 3763 if len(testruns) < 1: ··· 3923 3762 for data in testruns: 3924 3763 last = '' 3925 3764 for line in data.dmesgtext: 3926 - mc = re.match('.*(\[ *)(?P<t>[0-9\.]*)(\]) calling '+\ 3927 - '(?P<f>.*)\+ @ .*, parent: .*', line) 3928 - mr = re.match('.*(\[ *)(?P<t>[0-9\.]*)(\]) call '+\ 3929 - '(?P<f>.*)\+ returned .* after (?P<dt>.*) usecs', last) 3930 - if(mc and mr and (mc.group('t') == mr.group('t')) and 3931 - (mc.group('f') == mr.group('f'))): 3765 + ct, cf, n, p = data.initcall_debug_call(line) 3766 + rt, rf, l = data.initcall_debug_return(last) 3767 + if ct and rt and ct == rt and cf == rf: 3932 3768 i = data.dmesgtext.index(last) 3933 3769 j = data.dmesgtext.index(line) 3934 3770 data.dmesgtext[i] = line ··· 3935 3777 3936 3778 # Function: parseKernelLog 3937 3779 # Description: 3938 - # [deprecated for kernel 3.15.0 or newer] 3939 3780 # Analyse a dmesg log output file generated from this app during 3940 3781 # the execution phase. Create a set of device structures in memory 3941 3782 # for subsequent formatting in the html output file ··· 3953 3796 3954 3797 # dmesg phase match table 3955 3798 dm = { 3956 - 'suspend_prepare': ['PM: Syncing filesystems.*'], 3957 - 'suspend': ['PM: Entering [a-z]* sleep.*', 'Suspending console.*'], 3958 - 'suspend_late': ['PM: suspend of devices complete after.*'], 3959 - 'suspend_noirq': ['PM: late suspend of devices complete after.*'], 3960 - 'suspend_machine': ['PM: noirq suspend of devices complete after.*'], 3961 - 'resume_machine': ['ACPI: Low-level resume complete.*'], 3962 - 'resume_noirq': ['ACPI: Waking up from system sleep state.*'], 3963 - 'resume_early': ['PM: noirq resume of devices complete after.*'], 3964 - 'resume': ['PM: early resume of devices complete after.*'], 3965 - 'resume_complete': ['PM: resume of devices complete after.*'], 3799 + 'suspend_prepare': ['PM: Syncing filesystems.*', 'PM: suspend entry.*'], 3800 + 'suspend': ['PM: Entering [a-z]* sleep.*', 'Suspending console.*', 3801 + 'PM: Suspending system .*'], 3802 + 'suspend_late': ['PM: suspend of devices complete after.*', 3803 + 'PM: freeze of devices complete after.*'], 3804 + 'suspend_noirq': ['PM: late suspend of devices complete after.*', 3805 + 'PM: late freeze of devices complete after.*'], 3806 + 'suspend_machine': ['PM: suspend-to-idle', 3807 + 'PM: noirq suspend of devices complete after.*', 3808 + 'PM: noirq freeze of devices complete after.*'], 3809 + 'resume_machine': ['PM: Timekeeping suspended for.*', 3810 + 'ACPI: Low-level resume complete.*', 3811 + 'ACPI: resume from mwait', 3812 + 'Suspended for [0-9\.]* seconds'], 3813 + 'resume_noirq': ['PM: resume from suspend-to-idle', 3814 + 'ACPI: Waking up from system sleep state.*'], 3815 + 'resume_early': ['PM: noirq resume of devices complete after.*', 3816 + 'PM: noirq restore of devices complete after.*'], 3817 + 'resume': ['PM: early resume of devices complete after.*', 3818 + 'PM: early restore of devices complete after.*'], 3819 + 'resume_complete': ['PM: resume of devices complete after.*', 3820 + 'PM: restore of devices complete after.*'], 3966 3821 'post_resume': ['.*Restarting tasks \.\.\..*'], 3967 3822 } 3968 - if(sysvals.suspendmode == 'standby'): 3969 - dm['resume_machine'] = ['PM: Restoring platform NVS memory'] 3970 - elif(sysvals.suspendmode == 'disk'): 3971 - dm['suspend_late'] = ['PM: freeze of devices complete after.*'] 3972 - dm['suspend_noirq'] = ['PM: late freeze of devices complete after.*'] 3973 - dm['suspend_machine'] = ['PM: noirq freeze of devices complete after.*'] 3974 - dm['resume_machine'] = ['PM: Restoring platform NVS memory'] 3975 - dm['resume_early'] = ['PM: noirq restore of devices complete after.*'] 3976 - dm['resume'] = ['PM: early restore of devices complete after.*'] 3977 - dm['resume_complete'] = ['PM: restore of devices complete after.*'] 3978 - elif(sysvals.suspendmode == 'freeze'): 3979 - dm['resume_machine'] = ['ACPI: resume from mwait'] 3980 3823 3981 3824 # action table (expected events that occur and show up in dmesg) 3982 3825 at = { ··· 4024 3867 for s in dm[p]: 4025 3868 if(re.match(s, msg)): 4026 3869 phasechange, phase = True, p 3870 + dm[p] = [s] 4027 3871 break 4028 3872 4029 3873 # hack for determining resume_machine end for freeze 4030 3874 if(not sysvals.usetraceevents and sysvals.suspendmode == 'freeze' \ 4031 3875 and phase == 'resume_machine' and \ 4032 - re.match('calling (?P<f>.*)\+ @ .*, parent: .*', msg)): 3876 + data.initcall_debug_call(line, True)): 4033 3877 data.setPhase(phase, ktime, False) 4034 3878 phase = 'resume_noirq' 4035 3879 data.setPhase(phase, ktime, True) ··· 4103 3945 # -- device callbacks -- 4104 3946 if(phase in data.sortedPhases()): 4105 3947 # device init call 4106 - if(re.match('calling (?P<f>.*)\+ @ .*, parent: .*', msg)): 4107 - sm = re.match('calling (?P<f>.*)\+ @ '+\ 4108 - '(?P<n>.*), parent: (?P<p>.*)', msg); 4109 - f = sm.group('f') 4110 - n = sm.group('n') 4111 - p = sm.group('p') 4112 - if(f and n and p): 4113 - data.newAction(phase, f, int(n), p, ktime, -1, '') 4114 - # device init return 4115 - elif(re.match('call (?P<f>.*)\+ returned .* after '+\ 4116 - '(?P<t>.*) usecs', msg)): 4117 - sm = re.match('call (?P<f>.*)\+ returned .* after '+\ 4118 - '(?P<t>.*) usecs(?P<a>.*)', msg); 4119 - f = sm.group('f') 4120 - t = sm.group('t') 4121 - list = data.dmesg[phase]['list'] 4122 - if(f in list): 4123 - dev = list[f] 4124 - dev['length'] = int(t) 4125 - dev['end'] = ktime 3948 + t, f, n, p = data.initcall_debug_call(line) 3949 + if t and f and n and p: 3950 + data.newAction(phase, f, int(n), p, ktime, -1, '') 3951 + else: 3952 + # device init return 3953 + t, f, l = data.initcall_debug_return(line) 3954 + if t and f and l: 3955 + list = data.dmesg[phase]['list'] 3956 + if(f in list): 3957 + dev = list[f] 3958 + dev['length'] = int(l) 3959 + dev['end'] = ktime 4126 3960 4127 3961 # if trace events are not available, these are better than nothing 4128 3962 if(not sysvals.usetraceevents): ··· 4156 4006 # fill in any missing phases 4157 4007 phasedef = data.phasedef 4158 4008 terr, lp = '', 'suspend_prepare' 4009 + if lp not in data.dmesg: 4010 + doError('dmesg log format has changed, could not find start of suspend') 4159 4011 for p in sorted(phasedef, key=lambda k:phasedef[k]['order']): 4160 4012 if p not in data.dmesg: 4161 4013 if not terr: ··· 5454 5302 sv.dlog('read dmesg') 5455 5303 sv.initdmesg() 5456 5304 # start ftrace 5457 - if(sv.usecallgraph or sv.usetraceevents): 5305 + if sv.useftrace: 5458 5306 if not quiet: 5459 5307 pprint('START TRACING') 5460 5308 sv.dlog('start ftrace tracing') ··· 5486 5334 sv.dlog('enable RTC wake alarm') 5487 5335 sv.rtcWakeAlarmOn() 5488 5336 # start of suspend trace marker 5489 - if(sv.usecallgraph or sv.usetraceevents): 5490 - sv.fsetVal(datetime.now().strftime(sv.tmstart), 'trace_marker') 5337 + sv.fsetVal(datetime.now().strftime(sv.tmstart), 'trace_marker') 5491 5338 # predelay delay 5492 5339 if(count == 1 and sv.predelay > 0): 5493 5340 sv.fsetVal('WAIT %d' % sv.predelay, 'trace_marker') ··· 5535 5384 sv.fsetVal('WAIT END', 'trace_marker') 5536 5385 # return from suspend 5537 5386 pprint('RESUME COMPLETE') 5538 - if(sv.usecallgraph or sv.usetraceevents): 5539 - sv.fsetVal(datetime.now().strftime(sv.tmend), 'trace_marker') 5387 + sv.fsetVal(datetime.now().strftime(sv.tmend), 'trace_marker') 5540 5388 if sv.wifi and wifi: 5541 5389 tdata['wifi'] = sv.pollWifi(wifi) 5542 5390 sv.dlog('wifi check, %s' % tdata['wifi']) 5391 + if sv.netfix: 5392 + netfixout = sv.netfixon('wired') 5393 + elif sv.netfix: 5394 + netfixout = sv.netfixon() 5395 + if sv.netfix and netfixout: 5396 + tdata['netfix'] = netfixout 5397 + sv.dlog('netfix, %s' % tdata['netfix']) 5543 5398 if(sv.suspendmode == 'mem' or sv.suspendmode == 'command'): 5544 5399 sv.dlog('read the ACPI FPDT') 5545 5400 tdata['fw'] = getFPDT(False) ··· 5553 5396 sv.dlog('run the cmdinfo list after') 5554 5397 cmdafter = sv.cmdinfo(False) 5555 5398 # stop ftrace 5556 - if(sv.usecallgraph or sv.usetraceevents): 5399 + if sv.useftrace: 5557 5400 if sv.useprocmon: 5558 5401 sv.dlog('stop the process monitor') 5559 5402 pm.stop() ··· 5564 5407 sysvals.dlog('EXECUTION TRACE END') 5565 5408 sv.getdmesg(testdata) 5566 5409 # grab a copy of the ftrace output 5567 - if(sv.usecallgraph or sv.usetraceevents): 5410 + if sv.useftrace: 5568 5411 if not quiet: 5569 5412 pprint('CAPTURING TRACE') 5570 5413 op = sv.writeDatafileHeader(sv.ftracefile, testdata) ··· 5995 5838 pprint(' please choose one with -m') 5996 5839 5997 5840 # check if ftrace is available 5998 - res = sysvals.colorText('NO') 5999 - ftgood = sysvals.verifyFtrace() 6000 - if(ftgood): 6001 - res = 'YES' 6002 - elif(sysvals.usecallgraph): 6003 - status = 'ftrace is not properly supported' 6004 - pprint(' is ftrace supported: %s' % res) 5841 + if sysvals.useftrace: 5842 + res = sysvals.colorText('NO') 5843 + sysvals.useftrace = sysvals.verifyFtrace() 5844 + efmt = '"{0}" uses ftrace, and it is not properly supported' 5845 + if sysvals.useftrace: 5846 + res = 'YES' 5847 + elif sysvals.usecallgraph: 5848 + status = efmt.format('-f') 5849 + elif sysvals.usedevsrc: 5850 + status = efmt.format('-dev') 5851 + elif sysvals.useprocmon: 5852 + status = efmt.format('-proc') 5853 + pprint(' is ftrace supported: %s' % res) 6005 5854 6006 5855 # check if kprobes are available 6007 5856 if sysvals.usekprobes: ··· 6020 5857 pprint(' are kprobes supported: %s' % res) 6021 5858 6022 5859 # what data source are we using 6023 - res = 'DMESG' 6024 - if(ftgood): 5860 + res = 'DMESG (very limited, ftrace is preferred)' 5861 + if sysvals.useftrace: 6025 5862 sysvals.usetraceevents = True 6026 5863 for e in sysvals.traceevents: 6027 5864 if not os.path.exists(sysvals.epath+e): ··· 6042 5879 pprint(' optional commands this tool may use for info:') 6043 5880 no = sysvals.colorText('MISSING') 6044 5881 yes = sysvals.colorText('FOUND', 32) 6045 - for c in ['turbostat', 'mcelog', 'lspci', 'lsusb']: 5882 + for c in ['turbostat', 'mcelog', 'lspci', 'lsusb', 'netfix']: 6046 5883 if c == 'turbostat': 6047 5884 res = yes if sysvals.haveTurbostat() else no 6048 5885 else: ··· 6134 5971 if not sysvals.stamp: 6135 5972 pprint('ERROR: data does not include the expected stamp') 6136 5973 return (testruns, {'error': 'timeline generation failed'}) 6137 - shown = ['bios', 'biosdate', 'cpu', 'host', 'kernel', 'man', 'memfr', 5974 + shown = ['os', 'bios', 'biosdate', 'cpu', 'host', 'kernel', 'man', 'memfr', 6138 5975 'memsz', 'mode', 'numcpu', 'plat', 'time', 'wifi'] 6139 5976 sysvals.vprint('System Info:') 6140 5977 for key in sorted(sysvals.stamp): ··· 6215 6052 if sysvals.display: 6216 6053 ret = sysvals.displayControl('init') 6217 6054 sysvals.dlog('xset display init, ret = %d' % ret) 6055 + sysvals.testVal(sysvals.pmdpath, 'basic', '1') 6056 + sysvals.testVal(sysvals.s0ixpath, 'basic', 'Y') 6218 6057 sysvals.dlog('initialize ftrace') 6219 6058 sysvals.initFtrace(quiet) 6220 6059 ··· 6310 6145 elist[err[0]] += 1 6311 6146 for i in elist: 6312 6147 ilist.append('%sx%d' % (i, elist[i]) if elist[i] > 1 else i) 6313 - wifi = find_in_html(html, 'Wifi Resume: ', '</td>') 6314 - if wifi: 6315 - extra['wifi'] = wifi 6148 + line = find_in_html(log, '# wifi ', '\n') 6149 + if line: 6150 + extra['wifi'] = line 6151 + line = find_in_html(log, '# netfix ', '\n') 6152 + if line: 6153 + extra['netfix'] = line 6316 6154 low = find_in_html(html, 'freeze time: <b>', ' ms</b>') 6317 6155 for lowstr in ['waking', '+']: 6318 6156 if not low: ··· 6411 6243 sysvals.ftracefile = file 6412 6244 sysvals.setOutputFile() 6413 6245 if (sysvals.dmesgfile or sysvals.ftracefile) and sysvals.htmlfile and \ 6414 - (force or not sysvals.usable(sysvals.htmlfile)): 6246 + (force or not sysvals.usable(sysvals.htmlfile, True)): 6415 6247 pprint('FTRACE: %s' % sysvals.ftracefile) 6416 6248 if sysvals.dmesgfile: 6417 6249 pprint('DMESG : %s' % sysvals.dmesgfile) ··· 6701 6533 ' -skiphtml Run the test and capture the trace logs, but skip the timeline (default: disabled)\n'\ 6702 6534 ' -result fn Export a results table to a text file for parsing.\n'\ 6703 6535 ' -wifi If a wifi connection is available, check that it reconnects after resume.\n'\ 6536 + ' -netfix Use netfix to reset the network in the event it fails to resume.\n'\ 6704 6537 ' [testprep]\n'\ 6705 6538 ' -sync Sync the filesystems before starting the test\n'\ 6706 6539 ' -rs on/off Enable/disable runtime suspend for all devices, restore all after test\n'\ ··· 6784 6615 elif(arg == '-v'): 6785 6616 pprint("Version %s" % sysvals.version) 6786 6617 sys.exit(0) 6618 + elif(arg == '-debugtiming'): 6619 + debugtiming = True 6787 6620 elif(arg == '-x2'): 6788 6621 sysvals.execcount = 2 6789 6622 elif(arg == '-x2delay'): ··· 6828 6657 sysvals.sync = True 6829 6658 elif(arg == '-wifi'): 6830 6659 sysvals.wifi = True 6660 + elif(arg == '-netfix'): 6661 + sysvals.netfix = True 6831 6662 elif(arg == '-gzip'): 6832 6663 sysvals.gzip = True 6833 6664 elif(arg == '-info'): ··· 6992 6819 sysvals.outdir = val 6993 6820 sysvals.notestrun = True 6994 6821 if(os.path.isdir(val) == False): 6995 - doError('%s is not accessible' % val) 6822 + doError('%s is not accesible' % val) 6996 6823 elif(arg == '-filter'): 6997 6824 try: 6998 6825 val = next(args) ··· 7115 6942 time.sleep(sysvals.multitest['delay']) 7116 6943 fmt = 'suspend-%y%m%d-%H%M%S' 7117 6944 sysvals.testdir = os.path.join(sysvals.outdir, datetime.now().strftime(fmt)) 7118 - ret = runTest(i+1, True) 6945 + ret = runTest(i+1, not sysvals.verbose) 7119 6946 failcnt = 0 if not ret else failcnt + 1 7120 6947 if sysvals.maxfail > 0 and failcnt >= sysvals.maxfail: 7121 6948 pprint('Maximum fail count of %d reached, aborting multitest' % (sysvals.maxfail)) 7122 6949 break 7123 - time.sleep(5) 7124 6950 sysvals.resetlog() 7125 6951 sysvals.multistat(False, i, finish) 7126 6952 if 'time' in sysvals.multitest and datetime.now() >= finish: