Skip to contentSkip to conversation

PCI/ACPI: Rename _HPP to _HPX and move of ACPI-specific code from probe.c

PATCH Applied Krzysztof Wilczynski 2 participants 5 messages Aug 27, 2019 – Aug 28, 2019

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover PCI/ACPI: Rename _HPP to _HPX and move of ACPI-specific code from probe.c

This series of patches moves the ACPI-specific code currently included as part of the drivers/pci/probe.c. First, the ACPI Hot Plug structs for Type 0, 1 and 2, and any relevant variable names, structs, function names, etc., will have their names changed to reflect that these are related to _HPX rather than _HPP. Second, all of the ACPI-specific code will be moved to drivers/pci/pci-acpi.c for better organisation and to keep ACPI-related code base together. Third, remove the now obsolete struct hotplug_program_ops from drivers/pci/pci-acpi.c.

Patches should be preferably merged in order as they build upon one-another.

Related:
https://lore.kernel.org/lkml/[email protected]
https://lore.kernel.org/lkml/[email protected]
https://lore.kernel.org/lkml/[email protected]

Krzysztof Wilczynski (3):
PCI/ACPI: Rename ACPI Hot Plug structs for Type 0, 1 and 2 from _HPP
to _HPX
PCI/ACPI: Move ACPI-specific Hot Plug programming functions to
pci-acpi.c
PCI/ACPI: Remove unnecessary struct hotplug_program_ops from
pci-acpi.c

 drivers/pci/pci-acpi.c      | 410 +++++++++++++++++++++++++++++++++---
 drivers/pci/pci.h           |   9 +
 drivers/pci/probe.c         | 278 +-----------------------
 include/linux/pci_hotplug.h | 100 ---------
 4 files changed, 389 insertions(+), 408 deletions(-)
Signature · 1 line
2.22.1
#1 lore raw

PATCH 1/3 PCI/ACPI: Rename ACPI Hot Plug structs for Type 0, 1 and 2 from _HPP to _HPX

The name of the following structs suggests that these are related to the _HPP record type, whereas these are related to _HPX, not _HPP, that is the structs hpp_type0, hpp_type1 and hpp_type2.

The struct hpp_type0 denotes an _HPX Type 0 setting record that supersedes the _HPP setting record type, and has been used interchangeably for _HPP as per the ACPI specification (see version 6.3, section 6.2.9.1) which states that it should be applied to PCI, PCI-X and PCI Express devices, with settings being ignored if they are not applicable. There aren't any Type 1 and Type 2 setting record types in _HPP, therefore structs hpp_type1 and hpp_type2 are renamed to reflect their relation to _HPX rather than _HPP.

Any relevant variable names, structs and function names, etc., have been updated to reflect the name change of the A CPI Hot Plug structs.

---
 drivers/pci/pci-acpi.c      | 28 +++++++--------
 drivers/pci/probe.c         | 72 ++++++++++++++++++-------------------
 include/linux/pci_hotplug.h | 30 ++++++++--------
 3 files changed, 64 insertions(+), 66 deletions(-)
drivers/pci/pci-acpi.c +14 -14
index 45049f558860..02addc47edae 100644
@@ -119,7 +119,7 @@ phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle)
 }
 
 static acpi_status decode_type0_hpx_record(union acpi_object *record,
-					   struct hpp_type0 *hpx0)
+					   struct hpx_type0 *hpx0)
 {
 	int i;
 	union acpi_object *fields = record->package.elements;
@@ -147,7 +147,7 @@ static acpi_status decode_type0_hpx_record(union acpi_object *record,
 }
 
 static acpi_status decode_type1_hpx_record(union acpi_object *record,
-					   struct hpp_type1 *hpx1)
+					   struct hpx_type1 *hpx1)
 {
 	int i;
 	union acpi_object *fields = record->package.elements;
@@ -174,7 +174,7 @@ static acpi_status decode_type1_hpx_record(union acpi_object *record,
 }
 
 static acpi_status decode_type2_hpx_record(union acpi_object *record,
-					   struct hpp_type2 *hpx2)
+					   struct hpx_type2 *hpx2)
 {
 	int i;
 	union acpi_object *fields = record->package.elements;
@@ -277,9 +277,9 @@ static acpi_status acpi_run_hpx(struct pci_dev *dev, acpi_handle handle,
 	acpi_status status;
 	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
 	union acpi_object *package, *record, *fields;
-	struct hpp_type0 hpx0;
-	struct hpp_type1 hpx1;
-	struct hpp_type2 hpx2;
+	struct hpx_type0 hpx0;
+	struct hpx_type1 hpx1;
+	struct hpx_type2 hpx2;
 	u32 type;
 	int i;
 
@@ -353,10 +353,10 @@ static acpi_status acpi_run_hpp(struct pci_dev *dev, acpi_handle handle,
 	acpi_status status;
 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
 	union acpi_object *package, *fields;
-	struct hpp_type0 hpp0;
+	struct hpx_type0 hpx0;
 	int i;
 
-	memset(&hpp0, 0, sizeof(hpp0));
+	memset(&hpx0, 0, sizeof(hpx0));
 
 	status = acpi_evaluate_object(handle, "_HPP", NULL, &buffer);
 	if (ACPI_FAILURE(status))
@@ -377,13 +377,13 @@ static acpi_status acpi_run_hpp(struct pci_dev *dev, acpi_handle handle,
 		}
 	}
 
-	hpp0.revision        = 1;
-	hpp0.cache_line_size = fields[0].integer.value;
-	hpp0.latency_timer   = fields[1].integer.value;
-	hpp0.enable_serr     = fields[2].integer.value;
-	hpp0.enable_perr     = fields[3].integer.value;
+	hpx0.revision        = 1;
+	hpx0.cache_line_size = fields[0].integer.value;
+	hpx0.latency_timer   = fields[1].integer.value;
+	hpx0.enable_serr     = fields[2].integer.value;
+	hpx0.enable_perr     = fields[3].integer.value;
 
-	hp_ops->program_type0(dev, &hpp0);
+	hp_ops->program_type0(dev, &hpx0);
 
 exit:
 	kfree(buffer.pointer);
drivers/pci/probe.c +36 -36

180 lines not on this page · raw message

include/linux/pci_hotplug.h +14 -16
index f694eb2ca978..18fc6c7c3249 100644
@@ -86,25 +86,25 @@ void pci_hp_deregister(struct hotplug_slot *slot);
 #define pci_hp_initialize(slot, bus, nr, name) \
 	__pci_hp_initialize(slot, bus, nr, name, THIS_MODULE, KBUILD_MODNAME)
 
-/* PCI Setting Record (Type 0) */
-struct hpp_type0 {
-	u32 revision;
-	u8  cache_line_size;
-	u8  latency_timer;
+/* _HPX PCI Setting Record (Type 0) */
+struct hpx_type0 {
+	u32 revision; /* Not present in _HPP */
+	u8  cache_line_size; /* Not applicable to PCI Express */
+	u8  latency_timer;   /* Not applicable to PCI Express */
 	u8  enable_serr;
 	u8  enable_perr;
 };
 
-/* PCI-X Setting Record (Type 1) */
-struct hpp_type1 {
+/* _HPX PCI-X Setting Record (Type 1) */
+struct hpx_type1 {
 	u32 revision;
 	u8  max_mem_read;
 	u8  avg_max_split;
 	u16 tot_max_split;
 };
 
-/* PCI Express Setting Record (Type 2) */
-struct hpp_type2 {
+/* _HPX PCI Express Setting Record (Type 2) */
+struct hpx_type2 {
 	u32 revision;
 	u32 unc_err_mask_and;
 	u32 unc_err_mask_or;
@@ -124,9 +124,7 @@ struct hpp_type2 {
 	u32 sec_unc_err_mask_or;
 };
 
-/*
- * _HPX PCI Express Setting Record (Type 3)
- */
+/* _HPX PCI Express Setting Record (Type 3) */
 struct hpx_type3 {
 	u16 device_type;
 	u16 function_type;
@@ -145,10 +143,10 @@ struct hpx_type3 {
 };
 
 struct hotplug_program_ops {
-	void (*program_type0)(struct pci_dev *dev, struct hpp_type0 *hpp);
-	void (*program_type1)(struct pci_dev *dev, struct hpp_type1 *hpp);
-	void (*program_type2)(struct pci_dev *dev, struct hpp_type2 *hpp);
-	void (*program_type3)(struct pci_dev *dev, struct hpx_type3 *hpp);
+	void (*program_type0)(struct pci_dev *dev, struct hpx_type0 *hpx);
+	void (*program_type1)(struct pci_dev *dev, struct hpx_type1 *hpx);
+	void (*program_type2)(struct pci_dev *dev, struct hpx_type2 *hpx);
+	void (*program_type3)(struct pci_dev *dev, struct hpx_type3 *hpx);
 };
 
 enum hpx_type3_dev_type {
Signature · 1 line
2.22.1
#2 lore raw

PATCH 2/3 PCI/ACPI: Move ACPI-specific Hot Plug programming functions to pci-acpi.c

In reply to Krzysztof Wilczynski

Move functions program_hpx_type0(), program_hpx_type1(), etc., from drivers/pci/probe.c to drivers/pci/pci-acpi.c, and enums hpx_type3_dev_type, hpx_type3_fn_type and hpx_type3_cfg_loc to drivers/pci/pci-acpi.c as these functions and enums are ACPI-specific.

Then move structs hpx_type0, hpx_type1, hpx_type2 and hpx_type3 to drivers/pci/pci.h as these are shared between drivers/pci/pci-acpi.c and drivers/pci/probe.c.

---
 drivers/pci/pci-acpi.c      | 296 ++++++++++++++++++++++++++++++++++++
 drivers/pci/pci.h           |  79 ++++++++++
 drivers/pci/probe.c         | 269 --------------------------------
 include/linux/pci_hotplug.h | 100 ------------
 4 files changed, 375 insertions(+), 369 deletions(-)
drivers/pci/pci-acpi.c +296 -0
index 02addc47edae..0bfabb3f9931 100644
@@ -118,6 +118,47 @@ phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle)
 	return (phys_addr_t)mcfg_addr;
 }
 
+static struct hpx_type0 pci_default_type0 = {
+	.revision = 1,
+	.cache_line_size = 8,
+	.latency_timer = 0x40,
+	.enable_serr = 0,
+	.enable_perr = 0,
+};
+
+void program_hpx_type0(struct pci_dev *dev, struct hpx_type0 *hpx)
+{
+	u16 pci_cmd, pci_bctl;
+
+	if (!hpx)
+		hpx = &pci_default_type0;
+
+	if (hpx->revision > 1) {
+		pci_warn(dev, "PCI settings rev %d not supported; using defaults\n",
+			 hpx->revision);
+		hpx = &pci_default_type0;
+	}
+
+	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, hpx->cache_line_size);
+	pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpx->latency_timer);
+	pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
+	if (hpx->enable_serr)
+		pci_cmd |= PCI_COMMAND_SERR;
+	if (hpx->enable_perr)
+		pci_cmd |= PCI_COMMAND_PARITY;
+	pci_write_config_word(dev, PCI_COMMAND, pci_cmd);
+
+	/* Program bridge control value */
+	if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
+		pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER,
+				      hpx->latency_timer);
+		pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl);
+		if (hpx->enable_perr)
+			pci_bctl |= PCI_BRIDGE_CTL_PARITY;
+		pci_write_config_word(dev, PCI_BRIDGE_CONTROL, pci_bctl);
+	}
+}
+
 static acpi_status decode_type0_hpx_record(union acpi_object *record,
 					   struct hpx_type0 *hpx0)
 {
@@ -146,6 +187,20 @@ static acpi_status decode_type0_hpx_record(union acpi_object *record,
 	return AE_OK;
 }
 
+void program_hpx_type1(struct pci_dev *dev, struct hpx_type1 *hpx)
+{
+	int pos;
+
+	if (!hpx)
+		return;
+
+	pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
+	if (!pos)
+		return;
+
+	pci_warn(dev, "PCI-X settings not supported\n");
+}
+
 static acpi_status decode_type1_hpx_record(union acpi_object *record,
 					   struct hpx_type1 *hpx1)
 {
@@ -173,6 +228,107 @@ static acpi_status decode_type1_hpx_record(union acpi_object *record,
 	return AE_OK;
 }
 
+static bool pcie_root_rcb_set(struct pci_dev *dev)
+{
+	struct pci_dev *rp = pcie_find_root_port(dev);
+	u16 lnkctl;
+
+	if (!rp)
+		return false;
+
+	pcie_capability_read_word(rp, PCI_EXP_LNKCTL, &lnkctl);
+	if (lnkctl & PCI_EXP_LNKCTL_RCB)
+		return true;
+
+	return false;
+}
+
+void program_hpx_type2(struct pci_dev *dev, struct hpx_type2 *hpx)
+{
+	int pos;
+	u32 reg32;
+
+	if (!hpx)
+		return;
+
+	if (!pci_is_pcie(dev))
+		return;
+
+	if (hpx->revision > 1) {
+		pci_warn(dev, "PCIe settings rev %d not supported\n",
+			 hpx->revision);
+		return;
+	}
+
+	/*
+	 * Don't allow _HPX to change MPS or MRRS settings.  We manage
+	 * those to make sure they're consistent with the rest of the
+	 * platform.
+	 */
+	hpx->pci_exp_devctl_and |= PCI_EXP_DEVCTL_PAYLOAD |
+				    PCI_EXP_DEVCTL_READRQ;
+	hpx->pci_exp_devctl_or &= ~(PCI_EXP_DEVCTL_PAYLOAD |
+				    PCI_EXP_DEVCTL_READRQ);
+
+	/* Initialize Device Control Register */
+	pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL,
+			~hpx->pci_exp_devctl_and, hpx->pci_exp_devctl_or);
+
+	/* Initialize Link Control Register */
+	if (pcie_cap_has_lnkctl(dev)) {
+
+		/*
+		 * If the Root Port supports Read Completion Boundary of
+		 * 128, set RCB to 128.  Otherwise, clear it.
+		 */
+		hpx->pci_exp_lnkctl_and |= PCI_EXP_LNKCTL_RCB;
+		hpx->pci_exp_lnkctl_or &= ~PCI_EXP_LNKCTL_RCB;
+		if (pcie_root_rcb_set(dev))
+			hpx->pci_exp_lnkctl_or |= PCI_EXP_LNKCTL_RCB;
+
+		pcie_capability_clear_and_set_word(dev, PCI_EXP_LNKCTL,
+			~hpx->pci_exp_lnkctl_and, hpx->pci_exp_lnkctl_or);
+	}
+
+	/* Find Advanced Error Reporting Enhanced Capability */
+	pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
+	if (!pos)
+		return;
+
+	/* Initialize Uncorrectable Error Mask Register */
+	pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, &reg32);
+	reg32 = (reg32 & hpx->unc_err_mask_and) | hpx->unc_err_mask_or;
+	pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, reg32);
+
+	/* Initialize Uncorrectable Error Severity Register */
+	pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &reg32);
+	reg32 = (reg32 & hpx->unc_err_sever_and) | hpx->unc_err_sever_or;
+	pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, reg32);
+
+	/* Initialize Correctable Error Mask Register */
+	pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, &reg32);
+	reg32 = (reg32 & hpx->cor_err_mask_and) | hpx->cor_err_mask_or;
+	pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg32);
+
+	/* Initialize Advanced Error Capabilities and Control Register */
+	pci_read_config_dword(dev, pos + PCI_ERR_CAP, &reg32);
+	reg32 = (reg32 & hpx->adv_err_cap_and) | hpx->adv_err_cap_or;
+
+	/* Don't enable ECRC generation or checking if unsupported */
+	if (!(reg32 & PCI_ERR_CAP_ECRC_GENC))
+		reg32 &= ~PCI_ERR_CAP_ECRC_GENE;
+	if (!(reg32 & PCI_ERR_CAP_ECRC_CHKC))
+		reg32 &= ~PCI_ERR_CAP_ECRC_CHKE;
+	pci_write_config_dword(dev, pos + PCI_ERR_CAP, reg32);
+
+	/*
+	 * FIXME: The following two registers are not supported yet.
+	 *
+	 *   o Secondary Uncorrectable Error Severity Register
+	 *   o Secondary Uncorrectable Error Mask Register
+	 */
+}
+
 static acpi_status decode_type2_hpx_record(union acpi_object *record,
 					   struct hpx_type2 *hpx2)
 {
@@ -213,6 +369,146 @@ static acpi_status decode_type2_hpx_record(union acpi_object *record,
 	return AE_OK;
 }
 
+enum hpx_type3_dev_type {
+	HPX_TYPE_ENDPOINT	= BIT(0),
+	HPX_TYPE_LEG_END	= BIT(1),
+	HPX_TYPE_RC_END		= BIT(2),
+	HPX_TYPE_RC_EC		= BIT(3),
+	HPX_TYPE_ROOT_PORT	= BIT(4),
+	HPX_TYPE_UPSTREAM	= BIT(5),
+	HPX_TYPE_DOWNSTREAM	= BIT(6),
+	HPX_TYPE_PCI_BRIDGE	= BIT(7),
+	HPX_TYPE_PCIE_BRIDGE	= BIT(8),
+};
+
+static u16 hpx3_device_type(struct pci_dev *dev)
+{
+	u16 pcie_type = pci_pcie_type(dev);
+	const int pcie_to_hpx3_type[] = {
+		[PCI_EXP_TYPE_ENDPOINT]    = HPX_TYPE_ENDPOINT,
+		[PCI_EXP_TYPE_LEG_END]     = HPX_TYPE_LEG_END,
+		[PCI_EXP_TYPE_RC_END]      = HPX_TYPE_RC_END,
+		[PCI_EXP_TYPE_RC_EC]       = HPX_TYPE_RC_EC,
+		[PCI_EXP_TYPE_ROOT_PORT]   = HPX_TYPE_ROOT_PORT,
+		[PCI_EXP_TYPE_UPSTREAM]    = HPX_TYPE_UPSTREAM,
+		[PCI_EXP_TYPE_DOWNSTREAM]  = HPX_TYPE_DOWNSTREAM,
+		[PCI_EXP_TYPE_PCI_BRIDGE]  = HPX_TYPE_PCI_BRIDGE,
+		[PCI_EXP_TYPE_PCIE_BRIDGE] = HPX_TYPE_PCIE_BRIDGE,
+	};
+
+	if (pcie_type >= ARRAY_SIZE(pcie_to_hpx3_type))
+		return 0;
+
+	return pcie_to_hpx3_type[pcie_type];
+}
+
+enum hpx_type3_fn_type {
+	HPX_FN_NORMAL		= BIT(0),
+	HPX_FN_SRIOV_PHYS	= BIT(1),
+	HPX_FN_SRIOV_VIRT	= BIT(2),
+};
+
+static u8 hpx3_function_type(struct pci_dev *dev)
+{
+	if (dev->is_virtfn)
+		return HPX_FN_SRIOV_VIRT;
+	else if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV) > 0)
+		return HPX_FN_SRIOV_PHYS;
+	else
+		return HPX_FN_NORMAL;
+}
+
+static bool hpx3_cap_ver_matches(u8 pcie_cap_id, u8 hpx3_cap_id)
+{
+	u8 cap_ver = hpx3_cap_id & 0xf;
+
+	if ((hpx3_cap_id & BIT(4)) && cap_ver >= pcie_cap_id)
+		return true;
+	else if (cap_ver == pcie_cap_id)
+		return true;
+
+	return false;
+}
+
+enum hpx_type3_cfg_loc {
+	HPX_CFG_PCICFG		= 0,
+	HPX_CFG_PCIE_CAP	= 1,
+	HPX_CFG_PCIE_CAP_EXT	= 2,
+	HPX_CFG_VEND_CAP	= 3,
+	HPX_CFG_DVSEC		= 4,
+	HPX_CFG_MAX,
+};
+
+static void program_hpx_type3_register(struct pci_dev *dev,
+				       const struct hpx_type3 *reg)
+{
+	u32 match_reg, write_reg, header, orig_value;
+	u16 pos;
+
+	if (!(hpx3_device_type(dev) & reg->device_type))
+		return;
+
+	if (!(hpx3_function_type(dev) & reg->function_type))
+		return;
+
+	switch (reg->config_space_location) {
+	case HPX_CFG_PCICFG:
+		pos = 0;
+		break;
+	case HPX_CFG_PCIE_CAP:
+		pos = pci_find_capability(dev, reg->pci_exp_cap_id);
+		if (pos == 0)
+			return;
+
+		break;
+	case HPX_CFG_PCIE_CAP_EXT:
+		pos = pci_find_ext_capability(dev, reg->pci_exp_cap_id);
+		if (pos == 0)
+			return;
+
+		pci_read_config_dword(dev, pos, &header);
+		if (!hpx3_cap_ver_matches(PCI_EXT_CAP_VER(header),
+					  reg->pci_exp_cap_ver))
+			return;
+
+		break;
+	case HPX_CFG_VEND_CAP:	/* Fall through */
+	case HPX_CFG_DVSEC:	/* Fall through */
+	default:
+		pci_warn(dev, "Encountered _HPX type 3 with unsupported config space location");
+		return;
+	}
+
+	pci_read_config_dword(dev, pos + reg->match_offset, &match_reg);
+
+	if ((match_reg & reg->match_mask_and) != reg->match_value)
+		return;
+
+	pci_read_config_dword(dev, pos + reg->reg_offset, &write_reg);
+	orig_value = write_reg;
+	write_reg &= reg->reg_mask_and;
+	write_reg |= reg->reg_mask_or;
+
+	if (orig_value == write_reg)
+		return;
+
+	pci_write_config_dword(dev, pos + reg->reg_offset, write_reg);
+
+	pci_dbg(dev, "Applied _HPX3 at [0x%x]: 0x%08x -> 0x%08x",
+		pos, orig_value, write_reg);
+}
+
+void program_hpx_type3(struct pci_dev *dev, struct hpx_type3 *hpx)
+{
+	if (!hpx)
+		return;
+
+	if (!pci_is_pcie(dev))
+		return;
+
+	program_hpx_type3_register(dev, hpx);
+}
+
 static void parse_hpx3_register(struct hpx_type3 *hpx3_reg,
 				union acpi_object *reg_fields)
 {
drivers/pci/pci.h +79 -0

83 lines not on this page · raw message

drivers/pci/probe.c +0 -269

275 lines not on this page · raw message

include/linux/pci_hotplug.h +0 -98

112 lines not on this page · raw message

Signature · 1 line
2.22.1
#3 lore raw

PATCH 3/3 PCI/ACPI: Remove unnecessary struct hotplug_program_ops from pci-acpi.c

In reply to Krzysztof Wilczynski

Move the ACPI-specific structs hpx_type0, hpx_type1, hpx_type2 and hpx_type3 to drivers/pci/pci-acpi.c as they are not used anywhere else. Then remove the struct hotplug_program_ops that has been shared between drivers/pci/probe.c and drivers/pci/pci-acpi.c from drivers/pci/pci.h as it is no longer needed.

The struct hotplug_program_ops was introduced in the commit 87fcf12e846a ("PCI/ACPI: Remove the need for 'struct hotplug_params'") and replaced previously used struct hotplug_params enabling the support for the _HPX Type 3 Setting Record that has been added in the commit f873c51a155a ("PCI/ACPI: Implement _HPX Type 3 Setting Record").

The new struct allowed for the static functions such program_hpx_type0(), program_hpx_type1(), etc., from the drivers/pci/probe.c to be called from the function pci_acpi_program_hp_params() in the drivers/pci/pci-acpi.c.

Currently, a programming of _HPX Type 0 would be as follows:

drivers/pci/probe.c:

  program_hpx_type0()
  ...
  pci_configure_device()
    hp_ops = {
      .program_type0 = program_hpx_type0,
      ...
    }
    pci_acpi_program_hp_params(&hp_ops)

drivers/pci/pci-acpi.c:

pci_acpi_program_hp_params(&hp_ops)

    acpi_run_hpx(hp_ops)
      decode_type0_hpx_record()
        hp_ops->program_type0 # program_hpx_type0() called via hp_ops

After the ACPI-specific functions, structs, enums, etc., have been moved to drivers/pci/pci-acpi.c there will be no need to keep using the struct hotplug_program_ops as all of the _HPX Type 0, 1, 2 and 3 would be directly accessible.

---
 drivers/pci/pci-acpi.c | 96 ++++++++++++++++++++++++++++++++----------
 drivers/pci/pci.h      | 74 +-------------------------------
 drivers/pci/probe.c    |  9 +---
 3 files changed, 77 insertions(+), 102 deletions(-)
drivers/pci/pci-acpi.c +73 -22
index 0bfabb3f9931..c476b9ed009e 100644
@@ -118,6 +118,15 @@ phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle)
 	return (phys_addr_t)mcfg_addr;
 }
 
+/* _HPX PCI Setting Record (Type 0) */
+struct hpx_type0 {
+	u32 revision; /* Not present in _HPP */
+	u8  cache_line_size; /* Not applicable to PCI Express */
+	u8  latency_timer;   /* Not applicable to PCI Express */
+	u8  enable_serr;
+	u8  enable_perr;
+};
+
 static struct hpx_type0 pci_default_type0 = {
 	.revision = 1,
 	.cache_line_size = 8,
@@ -126,7 +135,7 @@ static struct hpx_type0 pci_default_type0 = {
 	.enable_perr = 0,
 };
 
-void program_hpx_type0(struct pci_dev *dev, struct hpx_type0 *hpx)
+static void program_hpx_type0(struct pci_dev *dev, struct hpx_type0 *hpx)
 {
 	u16 pci_cmd, pci_bctl;
 
@@ -187,7 +196,15 @@ static acpi_status decode_type0_hpx_record(union acpi_object *record,
 	return AE_OK;
 }
 
-void program_hpx_type1(struct pci_dev *dev, struct hpx_type1 *hpx)
+/* _HPX PCI-X Setting Record (Type 1) */
+struct hpx_type1 {
+	u32 revision;
+	u8  max_mem_read;
+	u8  avg_max_split;
+	u16 tot_max_split;
+};
+
+static void program_hpx_type1(struct pci_dev *dev, struct hpx_type1 *hpx)
 {
 	int pos;
 
@@ -243,7 +260,28 @@ static bool pcie_root_rcb_set(struct pci_dev *dev)
 	return false;
 }
 
-void program_hpx_type2(struct pci_dev *dev, struct hpx_type2 *hpx)
+/* _HPX PCI Express Setting Record (Type 2) */
+struct hpx_type2 {
+	u32 revision;
+	u32 unc_err_mask_and;
+	u32 unc_err_mask_or;
+	u32 unc_err_sever_and;
+	u32 unc_err_sever_or;
+	u32 cor_err_mask_and;
+	u32 cor_err_mask_or;
+	u32 adv_err_cap_and;
+	u32 adv_err_cap_or;
+	u16 pci_exp_devctl_and;
+	u16 pci_exp_devctl_or;
+	u16 pci_exp_lnkctl_and;
+	u16 pci_exp_lnkctl_or;
+	u32 sec_unc_err_sever_and;
+	u32 sec_unc_err_sever_or;
+	u32 sec_unc_err_mask_and;
+	u32 sec_unc_err_mask_or;
+};
+
+static void program_hpx_type2(struct pci_dev *dev, struct hpx_type2 *hpx)
 {
 	int pos;
 	u32 reg32;
@@ -369,6 +407,24 @@ static acpi_status decode_type2_hpx_record(union acpi_object *record,
 	return AE_OK;
 }
 
+/* _HPX PCI Express Setting Record (Type 3) */
+struct hpx_type3 {
+	u16 device_type;
+	u16 function_type;
+	u16 config_space_location;
+	u16 pci_exp_cap_id;
+	u16 pci_exp_cap_ver;
+	u16 pci_exp_vendor_id;
+	u16 dvsec_id;
+	u16 dvsec_rev;
+	u16 match_offset;
+	u32 match_mask_and;
+	u32 match_value;
+	u16 reg_offset;
+	u32 reg_mask_and;
+	u32 reg_mask_or;
+};
+
 enum hpx_type3_dev_type {
 	HPX_TYPE_ENDPOINT	= BIT(0),
 	HPX_TYPE_LEG_END	= BIT(1),
@@ -498,7 +554,7 @@ static void program_hpx_type3_register(struct pci_dev *dev,
 		pos, orig_value, write_reg);
 }
 
-void program_hpx_type3(struct pci_dev *dev, struct hpx_type3 *hpx)
+static void program_hpx_type3(struct pci_dev *dev, struct hpx_type3 *hpx)
 {
 	if (!hpx)
 		return;
@@ -529,8 +585,7 @@ static void parse_hpx3_register(struct hpx_type3 *hpx3_reg,
 }
 
 static acpi_status program_type3_hpx_record(struct pci_dev *dev,
-					   union acpi_object *record,
-					   const struct hotplug_program_ops *hp_ops)
+					   union acpi_object *record)
 {
 	union acpi_object *fields = record->package.elements;
 	u32 desc_count, expected_length, revision;
@@ -554,7 +609,7 @@ static acpi_status program_type3_hpx_record(struct pci_dev *dev,
 		for (i = 0; i < desc_count; i++) {
 			reg_fields = fields + 3 + i * 14;
 			parse_hpx3_register(&hpx3, reg_fields);
-			hp_ops->program_type3(dev, &hpx3);
+			program_hpx_type3(dev, &hpx3);
 		}
 
 		break;
@@ -567,8 +622,7 @@ static acpi_status program_type3_hpx_record(struct pci_dev *dev,
 	return AE_OK;
 }
 
-static acpi_status acpi_run_hpx(struct pci_dev *dev, acpi_handle handle,
-				const struct hotplug_program_ops *hp_ops)
+static acpi_status acpi_run_hpx(struct pci_dev *dev, acpi_handle handle)
 {
 	acpi_status status;
 	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
@@ -610,24 +664,24 @@ static acpi_status acpi_run_hpx(struct pci_dev *dev, acpi_handle handle,
 			status = decode_type0_hpx_record(record, &hpx0);
 			if (ACPI_FAILURE(status))
 				goto exit;
-			hp_ops->program_type0(dev, &hpx0);
+			program_hpx_type0(dev, &hpx0);
 			break;
 		case 1:
 			memset(&hpx1, 0, sizeof(hpx1));
 			status = decode_type1_hpx_record(record, &hpx1);
 			if (ACPI_FAILURE(status))
 				goto exit;
-			hp_ops->program_type1(dev, &hpx1);
+			program_hpx_type1(dev, &hpx1);
 			break;
 		case 2:
 			memset(&hpx2, 0, sizeof(hpx2));
 			status = decode_type2_hpx_record(record, &hpx2);
 			if (ACPI_FAILURE(status))
 				goto exit;
-			hp_ops->program_type2(dev, &hpx2);
+			program_hpx_type2(dev, &hpx2);
 			break;
 		case 3:
-			status = program_type3_hpx_record(dev, record, hp_ops);
+			status = program_type3_hpx_record(dev, record);
 			if (ACPI_FAILURE(status))
 				goto exit;
 			break;
@@ -643,8 +697,7 @@ static acpi_status acpi_run_hpx(struct pci_dev *dev, acpi_handle handle,
 	return status;
 }
 
-static acpi_status acpi_run_hpp(struct pci_dev *dev, acpi_handle handle,
-				const struct hotplug_program_ops *hp_ops)
+static acpi_status acpi_run_hpp(struct pci_dev *dev, acpi_handle handle)
 {
 	acpi_status status;
 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -679,20 +732,18 @@ static acpi_status acpi_run_hpp(struct pci_dev *dev, acpi_handle handle,
 	hpx0.enable_serr     = fields[2].integer.value;
 	hpx0.enable_perr     = fields[3].integer.value;
 
-	hp_ops->program_type0(dev, &hpx0);
+	program_hpx_type0(dev, &hpx0);
 
 exit:
 	kfree(buffer.pointer);
 	return status;
 }
 
-/* pci_get_hp_params
+/* pci_acpi_program_hp_params
  *
  * @dev - the pci_dev for which we want parameters
- * @hpp - allocated by the caller
  */
-int pci_acpi_program_hp_params(struct pci_dev *dev,
-			       const struct hotplug_program_ops *hp_ops)
+int pci_acpi_program_hp_params(struct pci_dev *dev)
 {
 	acpi_status status;
 	acpi_handle handle, phandle;
@@ -715,10 +766,10 @@ int pci_acpi_program_hp_params(struct pci_dev *dev,
 	 * this pci dev.
 	 */
 	while (handle) {
-		status = acpi_run_hpx(dev, handle, hp_ops);
+		status = acpi_run_hpx(dev, handle);
 		if (ACPI_SUCCESS(status))
 			return 0;
-		status = acpi_run_hpp(dev, handle, hp_ops);
+		status = acpi_run_hpp(dev, handle);
 		if (ACPI_SUCCESS(status))
 			return 0;
 		if (acpi_is_root_bridge(handle))
drivers/pci/pci.h +2 -72

82 lines not on this page · raw message

drivers/pci/probe.c +1 -8
@@ -2095,13 +2095,6 @@ static void pci_configure_serr(struct pci_dev *dev)
 
 static void pci_configure_device(struct pci_dev *dev)
 {
-	static const struct hotplug_program_ops hp_ops = {
-		.program_type0 = program_hpx_type0,
-		.program_type1 = program_hpx_type1,
-		.program_type2 = program_hpx_type2,
-		.program_type3 = program_hpx_type3,
-	};
-
 	pci_configure_mps(dev);
 	pci_configure_extended_tags(dev, NULL);
 	pci_configure_relaxed_ordering(dev);
@@ -2109,7 +2102,7 @@ static void pci_configure_device(struct pci_dev *dev)
 	pci_configure_eetlp_prefix(dev);
 	pci_configure_serr(dev);
 
-	pci_acpi_program_hp_params(dev, &hp_ops);
+	pci_acpi_program_hp_params(dev);
 }
 
 static void pci_release_capabilities(struct pci_dev *dev)
Signature · 1 line
2.22.1
#4 lore raw
In reply to Krzysztof Wilczynski
Quoted 11 lines · Krzysztof Wilczynski

This series of patches moves the ACPI-specific code currently included as part of the drivers/pci/probe.c. First, the ACPI Hot Plug structs for Type 0, 1 and 2, and any relevant variable names, structs, function names, etc., will have their names changed to reflect that these are related to _HPX rather than _HPP. Second, all of the ACPI-specific code will be moved to drivers/pci/pci-acpi.c for better organisation and to keep ACPI-related code base together. Third, remove the now obsolete struct hotplug_program_ops from drivers/pci/pci-acpi.c.

Patches should be preferably merged in order as they build upon one-another.

This is always the case; it's one of the main reasons for grouping patches into a series.

Quoted 13 lines

Related:
https://lore.kernel.org/lkml/[email protected]
https://lore.kernel.org/lkml/[email protected]
https://lore.kernel.org/lkml/[email protected]

Krzysztof Wilczynski (3):
PCI/ACPI: Rename ACPI Hot Plug structs for Type 0, 1 and 2 from _HPP
to _HPX
PCI/ACPI: Move ACPI-specific Hot Plug programming functions to
pci-acpi.c
PCI/ACPI: Remove unnecessary struct hotplug_program_ops from
pci-acpi.c

Quoted 5 lines
 drivers/pci/pci-acpi.c      | 410 +++++++++++++++++++++++++++++++++---
 drivers/pci/pci.h           |   9 +
 drivers/pci/probe.c         | 278 +-----------------------
 include/linux/pci_hotplug.h | 100 ---------
 4 files changed, 389 insertions(+), 408 deletions(-)

I applied these to pci/enumeration for v5.4, thanks!