2019-08-27 09:51:01

by Krzysztof Wilczyński

[permalink] [raw]
Subject: [PATCH 0/3] 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(-)

--
2.22.1


2019-08-27 09:51:06

by Krzysztof Wilczyński

[permalink] [raw]
Subject: [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.

Signed-off-by: Krzysztof Wilczynski <[email protected]>
---
drivers/pci/pci-acpi.c | 28 +++++++--------
drivers/pci/probe.c | 72 ++++++++++++++++++-------------------
include/linux/pci_hotplug.h | 30 ++++++++--------
3 files changed, 64 insertions(+), 66 deletions(-)

diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 45049f558860..02addc47edae 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -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);
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index dbeeb385fb9f..33dae8f5e73e 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1915,7 +1915,7 @@ static void pci_configure_mps(struct pci_dev *dev)
p_mps, mps, mpss);
}

-static struct hpp_type0 pci_default_type0 = {
+static struct hpx_type0 pci_default_type0 = {
.revision = 1,
.cache_line_size = 8,
.latency_timer = 0x40,
@@ -1923,44 +1923,44 @@ static struct hpp_type0 pci_default_type0 = {
.enable_perr = 0,
};

-static void program_hpp_type0(struct pci_dev *dev, struct hpp_type0 *hpp)
+static void program_hpx_type0(struct pci_dev *dev, struct hpx_type0 *hpx)
{
u16 pci_cmd, pci_bctl;

- if (!hpp)
- hpp = &pci_default_type0;
+ if (!hpx)
+ hpx = &pci_default_type0;

- if (hpp->revision > 1) {
+ if (hpx->revision > 1) {
pci_warn(dev, "PCI settings rev %d not supported; using defaults\n",
- hpp->revision);
- hpp = &pci_default_type0;
+ hpx->revision);
+ hpx = &pci_default_type0;
}

- 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_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 (hpp->enable_serr)
+ if (hpx->enable_serr)
pci_cmd |= PCI_COMMAND_SERR;
- if (hpp->enable_perr)
+ 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,
- hpp->latency_timer);
+ hpx->latency_timer);
pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl);
- if (hpp->enable_perr)
+ if (hpx->enable_perr)
pci_bctl |= PCI_BRIDGE_CTL_PARITY;
pci_write_config_word(dev, PCI_BRIDGE_CONTROL, pci_bctl);
}
}

-static void program_hpp_type1(struct pci_dev *dev, struct hpp_type1 *hpp)
+static void program_hpx_type1(struct pci_dev *dev, struct hpx_type1 *hpx)
{
int pos;

- if (!hpp)
+ if (!hpx)
return;

pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
@@ -1985,20 +1985,20 @@ static bool pcie_root_rcb_set(struct pci_dev *dev)
return false;
}

-static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp)
+static void program_hpx_type2(struct pci_dev *dev, struct hpx_type2 *hpx)
{
int pos;
u32 reg32;

- if (!hpp)
+ if (!hpx)
return;

if (!pci_is_pcie(dev))
return;

- if (hpp->revision > 1) {
+ if (hpx->revision > 1) {
pci_warn(dev, "PCIe settings rev %d not supported\n",
- hpp->revision);
+ hpx->revision);
return;
}

@@ -2007,14 +2007,14 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp)
* those to make sure they're consistent with the rest of the
* platform.
*/
- hpp->pci_exp_devctl_and |= PCI_EXP_DEVCTL_PAYLOAD |
+ hpx->pci_exp_devctl_and |= PCI_EXP_DEVCTL_PAYLOAD |
PCI_EXP_DEVCTL_READRQ;
- hpp->pci_exp_devctl_or &= ~(PCI_EXP_DEVCTL_PAYLOAD |
+ 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,
- ~hpp->pci_exp_devctl_and, hpp->pci_exp_devctl_or);
+ ~hpx->pci_exp_devctl_and, hpx->pci_exp_devctl_or);

/* Initialize Link Control Register */
if (pcie_cap_has_lnkctl(dev)) {
@@ -2023,13 +2023,13 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp)
* If the Root Port supports Read Completion Boundary of
* 128, set RCB to 128. Otherwise, clear it.
*/
- hpp->pci_exp_lnkctl_and |= PCI_EXP_LNKCTL_RCB;
- hpp->pci_exp_lnkctl_or &= ~PCI_EXP_LNKCTL_RCB;
+ hpx->pci_exp_lnkctl_and |= PCI_EXP_LNKCTL_RCB;
+ hpx->pci_exp_lnkctl_or &= ~PCI_EXP_LNKCTL_RCB;
if (pcie_root_rcb_set(dev))
- hpp->pci_exp_lnkctl_or |= PCI_EXP_LNKCTL_RCB;
+ hpx->pci_exp_lnkctl_or |= PCI_EXP_LNKCTL_RCB;

pcie_capability_clear_and_set_word(dev, PCI_EXP_LNKCTL,
- ~hpp->pci_exp_lnkctl_and, hpp->pci_exp_lnkctl_or);
+ ~hpx->pci_exp_lnkctl_and, hpx->pci_exp_lnkctl_or);
}

/* Find Advanced Error Reporting Enhanced Capability */
@@ -2039,22 +2039,22 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp)

/* Initialize Uncorrectable Error Mask Register */
pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, &reg32);
- reg32 = (reg32 & hpp->unc_err_mask_and) | hpp->unc_err_mask_or;
+ 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 & hpp->unc_err_sever_and) | hpp->unc_err_sever_or;
+ 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 & hpp->cor_err_mask_and) | hpp->cor_err_mask_or;
+ 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 & hpp->adv_err_cap_and) | hpp->adv_err_cap_or;
+ 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))
@@ -2173,15 +2173,15 @@ static void program_hpx_type3_register(struct pci_dev *dev,
pos, orig_value, write_reg);
}

-static void program_hpx_type3(struct pci_dev *dev, struct hpx_type3 *hpx3)
+static void program_hpx_type3(struct pci_dev *dev, struct hpx_type3 *hpx)
{
- if (!hpx3)
+ if (!hpx)
return;

if (!pci_is_pcie(dev))
return;

- program_hpx_type3_register(dev, hpx3);
+ program_hpx_type3_register(dev, hpx);
}

int pci_configure_extended_tags(struct pci_dev *dev, void *ign)
@@ -2365,9 +2365,9 @@ 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_hpp_type0,
- .program_type1 = program_hpp_type1,
- .program_type2 = program_hpp_type2,
+ .program_type0 = program_hpx_type0,
+ .program_type1 = program_hpx_type1,
+ .program_type2 = program_hpx_type2,
.program_type3 = program_hpx_type3,
};

diff --git a/include/linux/pci_hotplug.h b/include/linux/pci_hotplug.h
index f694eb2ca978..18fc6c7c3249 100644
--- a/include/linux/pci_hotplug.h
+++ b/include/linux/pci_hotplug.h
@@ -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 {
--
2.22.1

2019-08-27 09:51:10

by Krzysztof Wilczyński

[permalink] [raw]
Subject: [PATCH 3/3] PCI/ACPI: Remove unnecessary struct hotplug_program_ops from pci-acpi.c

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.

Signed-off-by: Krzysztof Wilczynski <[email protected]>
---
drivers/pci/pci-acpi.c | 96 ++++++++++++++++++++++++++++++++----------
drivers/pci/pci.h | 74 +-------------------------------
drivers/pci/probe.c | 9 +---
3 files changed, 77 insertions(+), 102 deletions(-)

diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 0bfabb3f9931..c476b9ed009e 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -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))
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -649,80 +649,10 @@ static inline void pci_aer_clear_fatal_status(struct pci_dev *dev) { }
static inline void pci_aer_clear_device_status(struct pci_dev *dev) { }
#endif

-/* _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;
-};
-
-/* _HPX PCI-X Setting Record (Type 1) */
-struct hpx_type1 {
- u32 revision;
- u8 max_mem_read;
- u8 avg_max_split;
- u16 tot_max_split;
-};
-
-/* _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;
-};
-
-/* _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;
-};
-
-void program_hpx_type0(struct pci_dev *dev, struct hpx_type0 *hpx);
-void program_hpx_type1(struct pci_dev *dev, struct hpx_type1 *hpx);
-void program_hpx_type2(struct pci_dev *dev, struct hpx_type2 *hpx);
-void program_hpx_type3(struct pci_dev *dev, struct hpx_type3 *hpx);
-
-struct hotplug_program_ops {
- 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);
-};
-
#ifdef CONFIG_ACPI
-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);
#else
-static inline int pci_acpi_program_hp_params(struct pci_dev *dev,
- const struct hotplug_program_ops *hp_ops)
+static inline int pci_acpi_program_hp_params(struct pci_dev *dev)
{
return -ENODEV;
}
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -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)
--
2.22.1

2019-08-27 09:51:28

by Krzysztof Wilczyński

[permalink] [raw]
Subject: [PATCH 2/3] PCI/ACPI: Move ACPI-specific Hot Plug programming functions to pci-acpi.c

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.

Signed-off-by: Krzysztof Wilczynski <[email protected]>
---
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(-)

diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 02addc47edae..0bfabb3f9931 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -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)
{
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -649,4 +649,83 @@ static inline void pci_aer_clear_fatal_status(struct pci_dev *dev) { }
static inline void pci_aer_clear_device_status(struct pci_dev *dev) { }
#endif

+/* _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;
+};
+
+/* _HPX PCI-X Setting Record (Type 1) */
+struct hpx_type1 {
+ u32 revision;
+ u8 max_mem_read;
+ u8 avg_max_split;
+ u16 tot_max_split;
+};
+
+/* _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;
+};
+
+/* _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;
+};
+
+void program_hpx_type0(struct pci_dev *dev, struct hpx_type0 *hpx);
+void program_hpx_type1(struct pci_dev *dev, struct hpx_type1 *hpx);
+void program_hpx_type2(struct pci_dev *dev, struct hpx_type2 *hpx);
+void program_hpx_type3(struct pci_dev *dev, struct hpx_type3 *hpx);
+
+struct hotplug_program_ops {
+ 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);
+};
+
+#ifdef CONFIG_ACPI
+int pci_acpi_program_hp_params(struct pci_dev *dev,
+ const struct hotplug_program_ops *hp_ops);
+#else
+static inline int pci_acpi_program_hp_params(struct pci_dev *dev,
+ const struct hotplug_program_ops *hp_ops)
+{
+ return -ENODEV;
+}
+#endif
+
#endif /* DRIVERS_PCI_H */
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1915,275 +1915,6 @@ static void pci_configure_mps(struct pci_dev *dev)
p_mps, mps, mpss);
}

-static struct hpx_type0 pci_default_type0 = {
- .revision = 1,
- .cache_line_size = 8,
- .latency_timer = 0x40,
- .enable_serr = 0,
- .enable_perr = 0,
-};
-
-static 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 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 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;
-}
-
-static 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 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];
-}
-
-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;
-}
-
-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);
-}
-
-static 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);
-}
-
int pci_configure_extended_tags(struct pci_dev *dev, void *ign)
{
struct pci_host_bridge *host;
diff --git a/include/linux/pci_hotplug.h b/include/linux/pci_hotplug.h
--- a/include/linux/pci_hotplug.h
+++ b/include/linux/pci_hotplug.h
@@ -86,112 +86,14 @@ 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)

-/* _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;
-};
-
-/* _HPX PCI-X Setting Record (Type 1) */
-struct hpx_type1 {
- u32 revision;
- u8 max_mem_read;
- u8 avg_max_split;
- u16 tot_max_split;
-};
-
-/* _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;
-};
-
-/* _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;
-};
-
-struct hotplug_program_ops {
- 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 {
- 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),
-};
-
-enum hpx_type3_fn_type {
- HPX_FN_NORMAL = BIT(0),
- HPX_FN_SRIOV_PHYS = BIT(1),
- HPX_FN_SRIOV_VIRT = BIT(2),
-};
-
-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,
-};
-
#ifdef CONFIG_ACPI
#include <linux/acpi.h>
-int pci_acpi_program_hp_params(struct pci_dev *dev,
- const struct hotplug_program_ops *hp_ops);
bool pciehp_is_native(struct pci_dev *bridge);
int acpi_get_hp_hw_control_from_firmware(struct pci_dev *bridge);
bool shpchp_is_native(struct pci_dev *bridge);
int acpi_pci_check_ejectable(struct pci_bus *pbus, acpi_handle handle);
int acpi_pci_detect_ejectable(acpi_handle handle);
#else
-static inline int pci_acpi_program_hp_params(struct pci_dev *dev,
- const struct hotplug_program_ops *hp_ops)
-{
- return -ENODEV;
-}
-
static inline int acpi_get_hp_hw_control_from_firmware(struct pci_dev *bridge)
{
return 0;
--
2.22.1

2019-08-28 20:36:02

by Bjorn Helgaas

[permalink] [raw]
Subject: Re: [PATCH 0/3] PCI/ACPI: Rename _HPP to _HPX and move of ACPI-specific code from probe.c

On Tue, Aug 27, 2019 at 11:49:48AM +0200, Krzysztof Wilczynski wrote:
> 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.

> 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(-)

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