LCOV - code coverage report
Current view: top level - drivers/acpi - acpi_lpit.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 6 70 8.6 %
Date: 2022-04-01 13:59:58 Functions: 1 7 14.3 %
Branches: 1 42 2.4 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-only
       2                 :            : 
       3                 :            : /*
       4                 :            :  * acpi_lpit.c - LPIT table processing functions
       5                 :            :  *
       6                 :            :  * Copyright (C) 2017 Intel Corporation. All rights reserved.
       7                 :            :  */
       8                 :            : 
       9                 :            : #include <linux/cpu.h>
      10                 :            : #include <linux/acpi.h>
      11                 :            : #include <asm/msr.h>
      12                 :            : #include <asm/tsc.h>
      13                 :            : 
      14                 :            : struct lpit_residency_info {
      15                 :            :         struct acpi_generic_address gaddr;
      16                 :            :         u64 frequency;
      17                 :            :         void __iomem *iomem_addr;
      18                 :            : };
      19                 :            : 
      20                 :            : /* Storage for an memory mapped and FFH based entries */
      21                 :            : static struct lpit_residency_info residency_info_mem;
      22                 :            : static struct lpit_residency_info residency_info_ffh;
      23                 :            : 
      24                 :          0 : static int lpit_read_residency_counter_us(u64 *counter, bool io_mem)
      25                 :            : {
      26                 :          0 :         int err;
      27                 :            : 
      28         [ #  # ]:          0 :         if (io_mem) {
      29                 :          0 :                 u64 count = 0;
      30                 :          0 :                 int error;
      31                 :            : 
      32                 :          0 :                 error = acpi_os_read_iomem(residency_info_mem.iomem_addr, &count,
      33                 :          0 :                                            residency_info_mem.gaddr.bit_width);
      34         [ #  # ]:          0 :                 if (error)
      35                 :            :                         return error;
      36                 :            : 
      37                 :          0 :                 *counter = div64_u64(count * 1000000ULL, residency_info_mem.frequency);
      38                 :          0 :                 return 0;
      39                 :            :         }
      40                 :            : 
      41                 :          0 :         err = rdmsrl_safe(residency_info_ffh.gaddr.address, counter);
      42         [ #  # ]:          0 :         if (!err) {
      43                 :          0 :                 u64 mask = GENMASK_ULL(residency_info_ffh.gaddr.bit_offset +
      44                 :            :                                        residency_info_ffh.gaddr. bit_width - 1,
      45                 :            :                                        residency_info_ffh.gaddr.bit_offset);
      46                 :            : 
      47                 :          0 :                 *counter &= mask;
      48                 :          0 :                 *counter >>= residency_info_ffh.gaddr.bit_offset;
      49                 :          0 :                 *counter = div64_u64(*counter * 1000000ULL, residency_info_ffh.frequency);
      50                 :          0 :                 return 0;
      51                 :            :         }
      52                 :            : 
      53                 :            :         return -ENODATA;
      54                 :            : }
      55                 :            : 
      56                 :          0 : static ssize_t low_power_idle_system_residency_us_show(struct device *dev,
      57                 :            :                                                        struct device_attribute *attr,
      58                 :            :                                                        char *buf)
      59                 :            : {
      60                 :          0 :         u64 counter;
      61                 :          0 :         int ret;
      62                 :            : 
      63                 :          0 :         ret = lpit_read_residency_counter_us(&counter, true);
      64         [ #  # ]:          0 :         if (ret)
      65                 :          0 :                 return ret;
      66                 :            : 
      67                 :          0 :         return sprintf(buf, "%llu\n", counter);
      68                 :            : }
      69                 :            : static DEVICE_ATTR_RO(low_power_idle_system_residency_us);
      70                 :            : 
      71                 :          0 : static ssize_t low_power_idle_cpu_residency_us_show(struct device *dev,
      72                 :            :                                                     struct device_attribute *attr,
      73                 :            :                                                     char *buf)
      74                 :            : {
      75                 :          0 :         u64 counter;
      76                 :          0 :         int ret;
      77                 :            : 
      78                 :          0 :         ret = lpit_read_residency_counter_us(&counter, false);
      79         [ #  # ]:          0 :         if (ret)
      80                 :          0 :                 return ret;
      81                 :            : 
      82                 :          0 :         return sprintf(buf, "%llu\n", counter);
      83                 :            : }
      84                 :            : static DEVICE_ATTR_RO(low_power_idle_cpu_residency_us);
      85                 :            : 
      86                 :          0 : int lpit_read_residency_count_address(u64 *address)
      87                 :            : {
      88         [ #  # ]:          0 :         if (!residency_info_mem.gaddr.address)
      89                 :            :                 return -EINVAL;
      90                 :            : 
      91                 :          0 :         *address = residency_info_mem.gaddr.address;
      92                 :            : 
      93                 :          0 :         return 0;
      94                 :            : }
      95                 :            : EXPORT_SYMBOL_GPL(lpit_read_residency_count_address);
      96                 :            : 
      97                 :          0 : static void lpit_update_residency(struct lpit_residency_info *info,
      98                 :            :                                  struct acpi_lpit_native *lpit_native)
      99                 :            : {
     100                 :          0 :         info->frequency = lpit_native->counter_frequency ?
     101         [ #  # ]:          0 :                                 lpit_native->counter_frequency : tsc_khz * 1000;
     102         [ #  # ]:          0 :         if (!info->frequency)
     103                 :          0 :                 info->frequency = 1;
     104                 :            : 
     105                 :          0 :         info->gaddr = lpit_native->residency_counter;
     106         [ #  # ]:          0 :         if (info->gaddr.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
     107                 :          0 :                 info->iomem_addr = ioremap(info->gaddr.address,
     108                 :          0 :                                                    info->gaddr.bit_width / 8);
     109         [ #  # ]:          0 :                 if (!info->iomem_addr)
     110                 :            :                         return;
     111                 :            : 
     112         [ #  # ]:          0 :                 if (!(acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0))
     113                 :            :                         return;
     114                 :            : 
     115                 :            :                 /* Silently fail, if cpuidle attribute group is not present */
     116                 :          0 :                 sysfs_add_file_to_group(&cpu_subsys.dev_root->kobj,
     117                 :            :                                         &dev_attr_low_power_idle_system_residency_us.attr,
     118                 :            :                                         "cpuidle");
     119         [ #  # ]:          0 :         } else if (info->gaddr.space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) {
     120         [ #  # ]:          0 :                 if (!(acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0))
     121                 :            :                         return;
     122                 :            : 
     123                 :            :                 /* Silently fail, if cpuidle attribute group is not present */
     124                 :          0 :                 sysfs_add_file_to_group(&cpu_subsys.dev_root->kobj,
     125                 :            :                                         &dev_attr_low_power_idle_cpu_residency_us.attr,
     126                 :            :                                         "cpuidle");
     127                 :            :         }
     128                 :            : }
     129                 :            : 
     130                 :          0 : static void lpit_process(u64 begin, u64 end)
     131                 :            : {
     132         [ #  # ]:          0 :         while (begin + sizeof(struct acpi_lpit_native) <= end) {
     133                 :          0 :                 struct acpi_lpit_native *lpit_native = (struct acpi_lpit_native *)begin;
     134                 :            : 
     135   [ #  #  #  # ]:          0 :                 if (!lpit_native->header.type && !lpit_native->header.flags) {
     136         [ #  # ]:          0 :                         if (lpit_native->residency_counter.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY &&
     137         [ #  # ]:          0 :                             !residency_info_mem.gaddr.address) {
     138                 :          0 :                                 lpit_update_residency(&residency_info_mem, lpit_native);
     139         [ #  # ]:          0 :                         } else if (lpit_native->residency_counter.space_id == ACPI_ADR_SPACE_FIXED_HARDWARE &&
     140         [ #  # ]:          0 :                                    !residency_info_ffh.gaddr.address) {
     141                 :          0 :                                 lpit_update_residency(&residency_info_ffh, lpit_native);
     142                 :            :                         }
     143                 :            :                 }
     144                 :          0 :                 begin += lpit_native->header.length;
     145                 :            :         }
     146                 :          0 : }
     147                 :            : 
     148                 :         78 : void acpi_init_lpit(void)
     149                 :            : {
     150                 :         78 :         acpi_status status;
     151                 :         78 :         struct acpi_table_lpit *lpit;
     152                 :            : 
     153                 :         78 :         status = acpi_get_table(ACPI_SIG_LPIT, 0, (struct acpi_table_header **)&lpit);
     154                 :            : 
     155         [ +  - ]:         78 :         if (ACPI_FAILURE(status))
     156                 :         78 :                 return;
     157                 :            : 
     158                 :          0 :         lpit_process((u64)lpit + sizeof(*lpit),
     159                 :          0 :                      (u64)lpit + lpit->header.length);
     160                 :            : }

Generated by: LCOV version 1.14