linux/drivers/pci/pcie/aspm.c

// SPDX-License-Identifier: GPL-2.0
/*
 * Enable PCIe link L0s/L1 state and Clock Power Management
 *
 * Copyright (C) 2007 Intel
 * Copyright (C) Zhang Yanmin ([email protected])
 * Copyright (C) Shaohua Li ([email protected])
 */

#include <linux/bitfield.h>
#include <linux/bits.h>
#include <linux/build_bug.h>
#include <linux/kernel.h>
#include <linux/limits.h>
#include <linux/math.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/pci.h>
#include <linux/pci_regs.h>
#include <linux/errno.h>
#include <linux/pm.h>
#include <linux/init.h>
#include <linux/printk.h>
#include <linux/slab.h>
#include <linux/time.h>

#include "../pci.h"

void pci_save_ltr_state(struct pci_dev *dev)
{}

void pci_restore_ltr_state(struct pci_dev *dev)
{}

void pci_configure_aspm_l1ss(struct pci_dev *pdev)
{}

void pci_save_aspm_l1ss_state(struct pci_dev *pdev)
{}

void pci_restore_aspm_l1ss_state(struct pci_dev *pdev)
{}

#ifdef CONFIG_PCIEASPM

#ifdef MODULE_PARAM_PREFIX
#undef MODULE_PARAM_PREFIX
#endif
#define MODULE_PARAM_PREFIX

/* Note: these are not register definitions */
#define PCIE_LINK_STATE_L0S_UP
#define PCIE_LINK_STATE_L0S_DW
static_assert();

#define PCIE_LINK_STATE_L1_SS_PCIPM
#define PCIE_LINK_STATE_L1_2_MASK
#define PCIE_LINK_STATE_L1SS

struct pcie_link_state {};

static int aspm_disabled, aspm_force;
static bool aspm_support_enabled =;
static DEFINE_MUTEX(aspm_lock);
static LIST_HEAD(link_list);

#define POLICY_DEFAULT
#define POLICY_PERFORMANCE
#define POLICY_POWERSAVE
#define POLICY_POWER_SUPERSAVE

#ifdef CONFIG_PCIEASPM_PERFORMANCE
static int aspm_policy = POLICY_PERFORMANCE;
#elif defined CONFIG_PCIEASPM_POWERSAVE
static int aspm_policy = POLICY_POWERSAVE;
#elif defined CONFIG_PCIEASPM_POWER_SUPERSAVE
static int aspm_policy = POLICY_POWER_SUPERSAVE;
#else
static int aspm_policy;
#endif

static const char *policy_str[] =;

/*
 * The L1 PM substate capability is only implemented in function 0 in a
 * multi function device.
 */
static struct pci_dev *pci_function_0(struct pci_bus *linkbus)
{}

static int policy_to_aspm_state(struct pcie_link_state *link)
{}

static int policy_to_clkpm_state(struct pcie_link_state *link)
{}

static void pci_update_aspm_saved_state(struct pci_dev *dev)
{}

static void pcie_set_clkpm_nocheck(struct pcie_link_state *link, int enable)
{}

static void pcie_set_clkpm(struct pcie_link_state *link, int enable)
{}

static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist)
{}

/*
 * pcie_aspm_configure_common_clock: check if the 2 ends of a link
 *   could use common clock. If they are, configure them to use the
 *   common clock. That will reduce the ASPM state exit latency.
 */
static void pcie_aspm_configure_common_clock(struct pcie_link_state *link)
{}

/* Convert L0s latency encoding to ns */
static u32 calc_l0s_latency(u32 lnkcap)
{}

/* Convert L0s acceptable latency encoding to ns */
static u32 calc_l0s_acceptable(u32 encoding)
{}

/* Convert L1 latency encoding to ns */
static u32 calc_l1_latency(u32 lnkcap)
{}

/* Convert L1 acceptable latency encoding to ns */
static u32 calc_l1_acceptable(u32 encoding)
{}

/* Convert L1SS T_pwr encoding to usec */
static u32 calc_l12_pwron(struct pci_dev *pdev, u32 scale, u32 val)
{}

/*
 * Encode an LTR_L1.2_THRESHOLD value for the L1 PM Substates Control 1
 * register.  Ports enter L1.2 when the most recent LTR value is greater
 * than or equal to LTR_L1.2_THRESHOLD, so we round up to make sure we
 * don't enter L1.2 too aggressively.
 *
 * See PCIe r6.0, sec 5.5.1, 6.18, 7.8.3.3.
 */
static void encode_l12_threshold(u32 threshold_us, u32 *scale, u32 *value)
{}

static void pcie_aspm_check_latency(struct pci_dev *endpoint)
{}

/* Calculate L1.2 PM substate timing parameters */
static void aspm_calc_l12_info(struct pcie_link_state *link,
				u32 parent_l1ss_cap, u32 child_l1ss_cap)
{}

static void aspm_l1ss_init(struct pcie_link_state *link)
{}

static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
{}

/* Configure the ASPM L1 substates */
static void pcie_config_aspm_l1ss(struct pcie_link_state *link, u32 state)
{}

static void pcie_config_aspm_dev(struct pci_dev *pdev, u32 val)
{}

static void pcie_config_aspm_link(struct pcie_link_state *link, u32 state)
{}

static void pcie_config_aspm_path(struct pcie_link_state *link)
{}

static void free_link_state(struct pcie_link_state *link)
{}

static int pcie_aspm_sanity_check(struct pci_dev *pdev)
{}

static struct pcie_link_state *alloc_pcie_link_state(struct pci_dev *pdev)
{}

static void pcie_aspm_update_sysfs_visibility(struct pci_dev *pdev)
{}

/*
 * pcie_aspm_init_link_state: Initiate PCI express link state.
 * It is called after the pcie and its children devices are scanned.
 * @pdev: the root port or switch downstream port
 */
void pcie_aspm_init_link_state(struct pci_dev *pdev)
{}

void pci_bridge_reconfigure_ltr(struct pci_dev *pdev)
{}

void pci_configure_ltr(struct pci_dev *pdev)
{}

/* Recheck latencies and update aspm_capable for links under the root */
static void pcie_update_aspm_capable(struct pcie_link_state *root)
{}

/* @pdev: the endpoint device */
void pcie_aspm_exit_link_state(struct pci_dev *pdev)
{}

/*
 * @pdev: the root port or switch downstream port
 * @locked: whether pci_bus_sem is held
 */
void pcie_aspm_pm_state_change(struct pci_dev *pdev, bool locked)
{}

void pcie_aspm_powersave_config_link(struct pci_dev *pdev)
{}

static struct pcie_link_state *pcie_aspm_get_link(struct pci_dev *pdev)
{}

static u8 pci_calc_aspm_disable_mask(int state)
{}

static u8 pci_calc_aspm_enable_mask(int state)
{}

static int __pci_disable_link_state(struct pci_dev *pdev, int state, bool locked)
{}

int pci_disable_link_state_locked(struct pci_dev *pdev, int state)
{}
EXPORT_SYMBOL();

/**
 * pci_disable_link_state - Disable device's link state, so the link will
 * never enter specific states.  Note that if the BIOS didn't grant ASPM
 * control to the OS, this does nothing because we can't touch the LNKCTL
 * register. Returns 0 or a negative errno.
 *
 * @pdev: PCI device
 * @state: ASPM link state to disable
 */
int pci_disable_link_state(struct pci_dev *pdev, int state)
{}
EXPORT_SYMBOL();

static int __pci_enable_link_state(struct pci_dev *pdev, int state, bool locked)
{}

/**
 * pci_enable_link_state - Clear and set the default device link state so that
 * the link may be allowed to enter the specified states. Note that if the
 * BIOS didn't grant ASPM control to the OS, this does nothing because we can't
 * touch the LNKCTL register. Also note that this does not enable states
 * disabled by pci_disable_link_state(). Return 0 or a negative errno.
 *
 * @pdev: PCI device
 * @state: Mask of ASPM link states to enable
 */
int pci_enable_link_state(struct pci_dev *pdev, int state)
{}
EXPORT_SYMBOL();

/**
 * pci_enable_link_state_locked - Clear and set the default device link state
 * so that the link may be allowed to enter the specified states. Note that if
 * the BIOS didn't grant ASPM control to the OS, this does nothing because we
 * can't touch the LNKCTL register. Also note that this does not enable states
 * disabled by pci_disable_link_state(). Return 0 or a negative errno.
 *
 * @pdev: PCI device
 * @state: Mask of ASPM link states to enable
 *
 * Context: Caller holds pci_bus_sem read lock.
 */
int pci_enable_link_state_locked(struct pci_dev *pdev, int state)
{}
EXPORT_SYMBOL();

static int pcie_aspm_set_policy(const char *val,
				const struct kernel_param *kp)
{}

static int pcie_aspm_get_policy(char *buffer, const struct kernel_param *kp)
{}

module_param_call();

/**
 * pcie_aspm_enabled - Check if PCIe ASPM has been enabled for a device.
 * @pdev: Target device.
 *
 * Relies on the upstream bridge's link_state being valid.  The link_state
 * is deallocated only when the last child of the bridge (i.e., @pdev or a
 * sibling) is removed, and the caller should be holding a reference to
 * @pdev, so this should be safe.
 */
bool pcie_aspm_enabled(struct pci_dev *pdev)
{}
EXPORT_SYMBOL_GPL();

static ssize_t aspm_attr_show_common(struct device *dev,
				     struct device_attribute *attr,
				     char *buf, u8 state)
{}

static ssize_t aspm_attr_store_common(struct device *dev,
				      struct device_attribute *attr,
				      const char *buf, size_t len, u8 state)
{}

#define ASPM_ATTR(_f, _s)

ASPM_ATTR()
ASPM_ATTR()
ASPM_ATTR()
ASPM_ATTR()
ASPM_ATTR()
ASPM_ATTR()

static ssize_t clkpm_show(struct device *dev,
			  struct device_attribute *attr, char *buf)
{}

static ssize_t clkpm_store(struct device *dev,
			   struct device_attribute *attr,
			   const char *buf, size_t len)
{}

static DEVICE_ATTR_RW(clkpm);
static DEVICE_ATTR_RW(l0s_aspm);
static DEVICE_ATTR_RW(l1_aspm);
static DEVICE_ATTR_RW(l1_1_aspm);
static DEVICE_ATTR_RW(l1_2_aspm);
static DEVICE_ATTR_RW(l1_1_pcipm);
static DEVICE_ATTR_RW(l1_2_pcipm);

static struct attribute *aspm_ctrl_attrs[] =;

static umode_t aspm_ctrl_attrs_are_visible(struct kobject *kobj,
					   struct attribute *a, int n)
{}

const struct attribute_group aspm_ctrl_attr_group =;

static int __init pcie_aspm_disable(char *str)
{}

__setup();

void pcie_no_aspm(void)
{}

bool pcie_aspm_support_enabled(void)
{}

#endif /* CONFIG_PCIEASPM */