// SPDX-License-Identifier: GPL-2.0+ /* * ACPI PCI HotPlug glue functions to ACPI CA subsystem * * Copyright (C) 2002,2003 Takayoshi Kochi ([email protected]) * Copyright (C) 2002 Hiroshi Aono ([email protected]) * Copyright (C) 2002,2003 NEC Corporation * Copyright (C) 2003-2005 Matthew Wilcox ([email protected]) * Copyright (C) 2003-2005 Hewlett Packard * Copyright (C) 2005 Rajesh Shah ([email protected]) * Copyright (C) 2005 Intel Corporation * * All rights reserved. * * Send feedback to <[email protected]> * */ /* * Lifetime rules for pci_dev: * - The one in acpiphp_bridge has its refcount elevated by pci_get_slot() * when the bridge is scanned and it loses a refcount when the bridge * is removed. * - When a P2P bridge is present, we elevate the refcount on the subordinate * bus. It loses the refcount when the driver unloads. */ #define pr_fmt(fmt) … #include <linux/module.h> #include <linux/kernel.h> #include <linux/pci.h> #include <linux/pci_hotplug.h> #include <linux/pci-acpi.h> #include <linux/pm_runtime.h> #include <linux/mutex.h> #include <linux/slab.h> #include <linux/acpi.h> #include "../pci.h" #include "acpiphp.h" static LIST_HEAD(bridge_list); static DEFINE_MUTEX(bridge_mutex); static int acpiphp_hotplug_notify(struct acpi_device *adev, u32 type); static void acpiphp_post_dock_fixup(struct acpi_device *adev); static void acpiphp_sanitize_bus(struct pci_bus *bus); static void hotplug_event(u32 type, struct acpiphp_context *context); static void free_bridge(struct kref *kref); /** * acpiphp_init_context - Create hotplug context and grab a reference to it. * @adev: ACPI device object to create the context for. * * Call under acpi_hp_context_lock. */ static struct acpiphp_context *acpiphp_init_context(struct acpi_device *adev) { … } /** * acpiphp_get_context - Get hotplug context and grab a reference to it. * @adev: ACPI device object to get the context for. * * Call under acpi_hp_context_lock. */ static struct acpiphp_context *acpiphp_get_context(struct acpi_device *adev) { … } /** * acpiphp_put_context - Drop a reference to ACPI hotplug context. * @context: ACPI hotplug context to drop a reference to. * * The context object is removed if there are no more references to it. * * Call under acpi_hp_context_lock. */ static void acpiphp_put_context(struct acpiphp_context *context) { … } static inline void get_bridge(struct acpiphp_bridge *bridge) { … } static inline void put_bridge(struct acpiphp_bridge *bridge) { … } static struct acpiphp_context *acpiphp_grab_context(struct acpi_device *adev) { … } static void acpiphp_let_context_go(struct acpiphp_context *context) { … } static void free_bridge(struct kref *kref) { … } /** * acpiphp_post_dock_fixup - Post-dock fixups for PCI devices. * @adev: ACPI device object corresponding to a PCI device. * * TBD - figure out a way to only call fixups for systems that require them. */ static void acpiphp_post_dock_fixup(struct acpi_device *adev) { … } /** * acpiphp_add_context - Add ACPIPHP context to an ACPI device object. * @handle: ACPI handle of the object to add a context to. * @lvl: Not used. * @data: The object's parent ACPIPHP bridge. * @rv: Not used. */ static acpi_status acpiphp_add_context(acpi_handle handle, u32 lvl, void *data, void **rv) { … } static void cleanup_bridge(struct acpiphp_bridge *bridge) { … } /** * acpiphp_max_busnr - return the highest reserved bus number under the given bus. * @bus: bus to start search with */ static unsigned char acpiphp_max_busnr(struct pci_bus *bus) { … } static void acpiphp_set_acpi_region(struct acpiphp_slot *slot) { … } static void check_hotplug_bridge(struct acpiphp_slot *slot, struct pci_dev *dev) { … } static int acpiphp_rescan_slot(struct acpiphp_slot *slot) { … } static void acpiphp_native_scan_bridge(struct pci_dev *bridge) { … } /** * enable_slot - enable, configure a slot * @slot: slot to be enabled * @bridge: true if enable is for the whole bridge (not a single slot) * * This function should be called per *physical slot*, * not per each slot object in ACPI namespace. */ static void enable_slot(struct acpiphp_slot *slot, bool bridge) { … } /** * disable_slot - disable a slot * @slot: ACPI PHP slot */ static void disable_slot(struct acpiphp_slot *slot) { … } static bool slot_no_hotplug(struct acpiphp_slot *slot) { … } /** * get_slot_status - get ACPI slot status * @slot: ACPI PHP slot * * If a slot has _STA for each function and if any one of them * returned non-zero status, return it. * * If a slot doesn't have _STA and if any one of its functions' * configuration space is configured, return 0x0f as a _STA. * * Otherwise return 0. */ static unsigned int get_slot_status(struct acpiphp_slot *slot) { … } static inline bool device_status_valid(unsigned int sta) { … } /** * trim_stale_devices - remove PCI devices that are not responding. * @dev: PCI device to start walking the hierarchy from. */ static void trim_stale_devices(struct pci_dev *dev) { … } /** * acpiphp_check_bridge - re-enumerate devices * @bridge: where to begin re-enumeration * * Iterate over all slots under this bridge and make sure that if a * card is present they are enabled, and if not they are disabled. */ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge) { … } /* * Remove devices for which we could not assign resources, call * arch specific code to fix-up the bus */ static void acpiphp_sanitize_bus(struct pci_bus *bus) { … } /* * ACPI event handlers */ void acpiphp_check_host_bridge(struct acpi_device *adev) { … } static int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot); static void hotplug_event(u32 type, struct acpiphp_context *context) { … } static int acpiphp_hotplug_notify(struct acpi_device *adev, u32 type) { … } /** * acpiphp_enumerate_slots - Enumerate PCI slots for a given bus. * @bus: PCI bus to enumerate the slots for. * * A "slot" is an object associated with a PCI device number. All functions * (PCI devices) with the same bus and device number belong to the same slot. */ void acpiphp_enumerate_slots(struct pci_bus *bus) { … } static void acpiphp_drop_bridge(struct acpiphp_bridge *bridge) { … } /** * acpiphp_remove_slots - Remove slot objects associated with a given bus. * @bus: PCI bus to remove the slot objects for. */ void acpiphp_remove_slots(struct pci_bus *bus) { … } /** * acpiphp_enable_slot - power on slot * @slot: ACPI PHP slot */ int acpiphp_enable_slot(struct acpiphp_slot *slot) { … } /** * acpiphp_disable_and_eject_slot - power off and eject slot * @slot: ACPI PHP slot */ static int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot) { … } int acpiphp_disable_slot(struct acpiphp_slot *slot) { … } /* * slot enabled: 1 * slot disabled: 0 */ u8 acpiphp_get_power_status(struct acpiphp_slot *slot) { … } /* * latch open: 1 * latch closed: 0 */ u8 acpiphp_get_latch_status(struct acpiphp_slot *slot) { … } /* * adapter presence : 1 * absence : 0 */ u8 acpiphp_get_adapter_status(struct acpiphp_slot *slot) { … }