Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 424600f9 authored by Rajesh Shah's avatar Rajesh Shah Committed by Greg Kroah-Hartman
Browse files

[PATCH] shpchp: reduce dependence on ACPI



Reduce the SHPC hotplug driver's dependence on ACPI. We don't
walk the acpi namespace anymore to build a list of bridges and
devices. The remaining interaction with ACPI is to run the
_OSHP method to transition control of hotplug hardware from
system BIOS to the shpc hotplug driver, and to run the _HPP
method to get hotplug device parameters like cache line size,
latency timer and SERR/PERR enable from BIOS.

Note that one of the side effects of this patch is that shpchp
does not enable the hot-added device or its DMA bus mastering
automatically now. It expects the device driver to do that.
This may break some drivers and we will have to fix them as
they are reported.

Signed-off-by: default avatarRajesh Shah <rajesh.shah@intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 7e88ed19
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -122,6 +122,13 @@ struct controller {
	u16 vendor_id;
};

struct hotplug_params {
	u8	cache_line_size;
	u8	latency_timer;
	u8	enable_serr;
	u8	enable_perr;
};

/* Define AMD SHPC ID  */
#define PCI_DEVICE_ID_AMD_GOLAM_7450	0x7450 

@@ -192,6 +199,11 @@ extern int shpchp_save_config(struct controller *ctrl, int busnumber, int num_ct
extern int	shpchp_save_slot_config(struct controller *ctrl, struct pci_func * new_slot);
extern int	shpchp_configure_device(struct slot *p_slot);
extern int	shpchp_unconfigure_device(struct pci_func* func);
extern void	get_hp_hw_control_from_firmware(struct pci_dev *dev);
extern void	get_hp_params_from_firmware(struct pci_dev *dev,
		struct hotplug_params *hpp);
extern int	shpchprm_get_physical_slot_number(struct controller *ctrl,
		u32 *sun, u8 busnum, u8 devnum);


/* Global variables */
+3 −10
Original line number Diff line number Diff line
@@ -39,7 +39,6 @@
#include <linux/init.h>
#include <asm/uaccess.h>
#include "shpchp.h"
#include "shpchprm.h"

/* Global variables */
int shpchp_debug;
@@ -566,16 +565,12 @@ static int __init shpcd_init(void)
	if (retval)
		goto error_hpc_init;

	retval = shpchprm_init(PCI);
	if (!retval) {
	retval = pci_register_driver(&shpc_driver);
	dbg("%s: pci_register_driver = %d\n", __FUNCTION__, retval);
	info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
	}

error_hpc_init:
	if (retval) {
		shpchprm_cleanup();
		shpchp_event_stop_thread();
	}
	return retval;
@@ -586,8 +581,6 @@ static void __exit shpcd_cleanup(void)
	dbg("unload_shpchpd()\n");
	unload_shpchpd();

	shpchprm_cleanup();

	dbg("pci_unregister_driver\n");
	pci_unregister_driver(&shpc_driver);

+0 −1
Original line number Diff line number Diff line
@@ -40,7 +40,6 @@
#include <linux/pci.h>
#include "../pci.h"
#include "shpchp.h"
#include "shpchprm.h"

static void interrupt_event_handler(struct controller *ctrl);

+1 −1
Original line number Diff line number Diff line
@@ -1566,8 +1566,8 @@ int shpc_init(struct controller * ctrl,
			err("Can't get irq %d for the hotplug controller\n", php_ctlr->irq);
			goto abort_free_ctlr;
		}
		/* Execute OSHP method here */
	}
	get_hp_hw_control_from_firmware(pdev);
	dbg("%s: Before adding HPC to HPC list\n", __FUNCTION__);

	/*  Add this HPC instance into the HPC list */
+50 −2
Original line number Diff line number Diff line
@@ -38,6 +38,55 @@
#include "../pci.h"
#include "shpchp.h"

void program_fw_provided_values(struct pci_dev *dev)
{
	u16 pci_cmd, pci_bctl;
	struct pci_dev *cdev;
	struct hotplug_params hpp = {0x8, 0x40, 0, 0}; /* defaults */

	/* Program hpp values for this device */
	if (!(dev->hdr_type == PCI_HEADER_TYPE_NORMAL ||
			(dev->hdr_type == PCI_HEADER_TYPE_BRIDGE &&
			(dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)))
		return;

	get_hp_params_from_firmware(dev, &hpp);

	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, hpp.cache_line_size);
	pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp.latency_timer);
	pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
	if (hpp.enable_serr)
		pci_cmd |= PCI_COMMAND_SERR;
	else
		pci_cmd &= ~PCI_COMMAND_SERR;
	if (hpp.enable_perr)
		pci_cmd |= PCI_COMMAND_PARITY;
	else
		pci_cmd &= ~PCI_COMMAND_PARITY;
	pci_write_config_word(dev, PCI_COMMAND, pci_cmd);

	/* Program bridge control value and child devices */
	if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
		pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER,
				hpp.latency_timer);
		pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl);
		if (hpp.enable_serr)
			pci_bctl |= PCI_BRIDGE_CTL_SERR;
		else
			pci_bctl &= ~PCI_BRIDGE_CTL_SERR;
		if (hpp.enable_perr)
			pci_bctl |= PCI_BRIDGE_CTL_PARITY;
		else
			pci_bctl &= ~PCI_BRIDGE_CTL_PARITY;
		pci_write_config_word(dev, PCI_BRIDGE_CONTROL, pci_bctl);
		if (dev->subordinate) {
			list_for_each_entry(cdev, &dev->subordinate->devices,
					bus_list)
				program_fw_provided_values(cdev);
		}
	}
}

int shpchp_configure_device(struct slot *p_slot)
{
	struct pci_dev *dev;
@@ -90,8 +139,7 @@ int shpchp_configure_device(struct slot *p_slot)
			child->subordinate = pci_do_scan_bus(child);
			pci_bus_size_bridges(child);
		}
		/* TBD: program firmware provided _HPP values */
		/* program_fw_provided_values(dev); */
		program_fw_provided_values(dev);
	}

	pci_bus_assign_resources(parent);
Loading