powerpc/powernv: Set PELTV for compound PEs
Commit 262af55
("powerpc/powernv: Enable M64 aperatus for PHB3")
introduced compound PEs in order to support M64 aperatus on PHB3.
However, we never configured PELTV for compound PEs. The patch
fixes that by: parent PE can freeze all child compound PEs. Any
compound PE affects the group.
Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
This commit is contained in:
parent
4b82ab1803
commit
b131a8425c
1 changed files with 102 additions and 16 deletions
|
@ -522,6 +522,106 @@ static struct pnv_ioda_pe *pnv_ioda_get_pe(struct pci_dev *dev)
|
|||
}
|
||||
#endif /* CONFIG_PCI_MSI */
|
||||
|
||||
static int pnv_ioda_set_one_peltv(struct pnv_phb *phb,
|
||||
struct pnv_ioda_pe *parent,
|
||||
struct pnv_ioda_pe *child,
|
||||
bool is_add)
|
||||
{
|
||||
const char *desc = is_add ? "adding" : "removing";
|
||||
uint8_t op = is_add ? OPAL_ADD_PE_TO_DOMAIN :
|
||||
OPAL_REMOVE_PE_FROM_DOMAIN;
|
||||
struct pnv_ioda_pe *slave;
|
||||
long rc;
|
||||
|
||||
/* Parent PE affects child PE */
|
||||
rc = opal_pci_set_peltv(phb->opal_id, parent->pe_number,
|
||||
child->pe_number, op);
|
||||
if (rc != OPAL_SUCCESS) {
|
||||
pe_warn(child, "OPAL error %ld %s to parent PELTV\n",
|
||||
rc, desc);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
if (!(child->flags & PNV_IODA_PE_MASTER))
|
||||
return 0;
|
||||
|
||||
/* Compound case: parent PE affects slave PEs */
|
||||
list_for_each_entry(slave, &child->slaves, list) {
|
||||
rc = opal_pci_set_peltv(phb->opal_id, parent->pe_number,
|
||||
slave->pe_number, op);
|
||||
if (rc != OPAL_SUCCESS) {
|
||||
pe_warn(slave, "OPAL error %ld %s to parent PELTV\n",
|
||||
rc, desc);
|
||||
return -ENXIO;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pnv_ioda_set_peltv(struct pnv_phb *phb,
|
||||
struct pnv_ioda_pe *pe,
|
||||
bool is_add)
|
||||
{
|
||||
struct pnv_ioda_pe *slave;
|
||||
struct pci_dev *pdev;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Clear PE frozen state. If it's master PE, we need
|
||||
* clear slave PE frozen state as well.
|
||||
*/
|
||||
if (is_add) {
|
||||
opal_pci_eeh_freeze_clear(phb->opal_id, pe->pe_number,
|
||||
OPAL_EEH_ACTION_CLEAR_FREEZE_ALL);
|
||||
if (pe->flags & PNV_IODA_PE_MASTER) {
|
||||
list_for_each_entry(slave, &pe->slaves, list)
|
||||
opal_pci_eeh_freeze_clear(phb->opal_id,
|
||||
slave->pe_number,
|
||||
OPAL_EEH_ACTION_CLEAR_FREEZE_ALL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Associate PE in PELT. We need add the PE into the
|
||||
* corresponding PELT-V as well. Otherwise, the error
|
||||
* originated from the PE might contribute to other
|
||||
* PEs.
|
||||
*/
|
||||
ret = pnv_ioda_set_one_peltv(phb, pe, pe, is_add);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* For compound PEs, any one affects all of them */
|
||||
if (pe->flags & PNV_IODA_PE_MASTER) {
|
||||
list_for_each_entry(slave, &pe->slaves, list) {
|
||||
ret = pnv_ioda_set_one_peltv(phb, slave, pe, is_add);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (pe->flags & (PNV_IODA_PE_BUS_ALL | PNV_IODA_PE_BUS))
|
||||
pdev = pe->pbus->self;
|
||||
else
|
||||
pdev = pe->pdev->bus->self;
|
||||
while (pdev) {
|
||||
struct pci_dn *pdn = pci_get_pdn(pdev);
|
||||
struct pnv_ioda_pe *parent;
|
||||
|
||||
if (pdn && pdn->pe_number != IODA_INVALID_PE) {
|
||||
parent = &phb->ioda.pe_array[pdn->pe_number];
|
||||
ret = pnv_ioda_set_one_peltv(phb, parent, pe, is_add);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
pdev = pdev->bus->self;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pnv_ioda_configure_pe(struct pnv_phb *phb, struct pnv_ioda_pe *pe)
|
||||
{
|
||||
struct pci_dev *parent;
|
||||
|
@ -576,23 +676,9 @@ static int pnv_ioda_configure_pe(struct pnv_phb *phb, struct pnv_ioda_pe *pe)
|
|||
return -ENXIO;
|
||||
}
|
||||
|
||||
rc = opal_pci_set_peltv(phb->opal_id, pe->pe_number,
|
||||
pe->pe_number, OPAL_ADD_PE_TO_DOMAIN);
|
||||
if (rc)
|
||||
pe_warn(pe, "OPAL error %d adding self to PELTV\n", rc);
|
||||
opal_pci_eeh_freeze_clear(phb->opal_id, pe->pe_number,
|
||||
OPAL_EEH_ACTION_CLEAR_FREEZE_ALL);
|
||||
/* Configure PELTV */
|
||||
pnv_ioda_set_peltv(phb, pe, true);
|
||||
|
||||
/* Add to all parents PELT-V */
|
||||
while (parent) {
|
||||
struct pci_dn *pdn = pci_get_pdn(parent);
|
||||
if (pdn && pdn->pe_number != IODA_INVALID_PE) {
|
||||
rc = opal_pci_set_peltv(phb->opal_id, pdn->pe_number,
|
||||
pe->pe_number, OPAL_ADD_PE_TO_DOMAIN);
|
||||
/* XXX What to do in case of error ? */
|
||||
}
|
||||
parent = parent->bus->self;
|
||||
}
|
||||
/* Setup reverse map */
|
||||
for (rid = pe->rid; rid < rid_end; rid++)
|
||||
phb->ioda.pe_rmap[rid] = pe->pe_number;
|
||||
|
|
Loading…
Reference in a new issue