Skip to content

Commit

Permalink
Merge tag 'pci-v4.4-fixes-2' of git://git.kernel.org/pub/scm/linux/ke…
Browse files Browse the repository at this point in the history
…rnel/git/helgaas/pci

Pull PCI fixes from Bjorn Helgaas:
 "These are more fixes I'd like to have in v4.4.  Several for the Altera
  driver added for v4.4, and one for an MSI domain problem that affects
  several arm64 platforms:

  MSI:
   - Only use the generic MSI layer when domain is hierarchical (Marc
     Zyngier)

  Altera host bridge driver:
   - Fix loop in tlp_read_packet() (Dan Carpenter)
   - Fix Requester ID for config accesses (Ley Foon Tan)
   - Check TLP completion status (Ley Foon Tan)
   - Fix error when INTx is 4 (Ley Foon Tan)"

* tag 'pci-v4.4-fixes-2' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci:
  PCI: altera: Fix error when INTx is 4
  PCI: altera: Check TLP completion status
  PCI: altera: Fix Requester ID for config accesses
  PCI: altera: Fix loop in tlp_read_packet()
  PCI/MSI: Only use the generic MSI layer when domain is hierarchical
  • Loading branch information
Linus Torvalds committed Dec 9, 2015
2 parents aa53685 + 99496bd commit 978d6a9
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 9 deletions.
23 changes: 16 additions & 7 deletions drivers/pci/host/pcie-altera.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,10 @@
#define TLP_CFG_DW2(bus, devfn, offset) \
(((bus) << 24) | ((devfn) << 16) | (offset))
#define TLP_REQ_ID(bus, devfn) (((bus) << 8) | (devfn))
#define TLP_COMP_STATUS(s) (((s) >> 12) & 7)
#define TLP_HDR_SIZE 3
#define TLP_LOOP 500
#define RP_DEVFN 0

#define INTX_NUM 4

Expand Down Expand Up @@ -166,34 +168,41 @@ static bool altera_pcie_valid_config(struct altera_pcie *pcie,

static int tlp_read_packet(struct altera_pcie *pcie, u32 *value)
{
u8 loop;
int i;
bool sop = 0;
u32 ctrl;
u32 reg0, reg1;
u32 comp_status = 1;

/*
* Minimum 2 loops to read TLP headers and 1 loop to read data
* payload.
*/
for (loop = 0; loop < TLP_LOOP; loop++) {
for (i = 0; i < TLP_LOOP; i++) {
ctrl = cra_readl(pcie, RP_RXCPL_STATUS);
if ((ctrl & RP_RXCPL_SOP) || (ctrl & RP_RXCPL_EOP) || sop) {
reg0 = cra_readl(pcie, RP_RXCPL_REG0);
reg1 = cra_readl(pcie, RP_RXCPL_REG1);

if (ctrl & RP_RXCPL_SOP)
if (ctrl & RP_RXCPL_SOP) {
sop = true;
comp_status = TLP_COMP_STATUS(reg1);
}

if (ctrl & RP_RXCPL_EOP) {
if (comp_status)
return PCIBIOS_DEVICE_NOT_FOUND;

if (value)
*value = reg0;

return PCIBIOS_SUCCESSFUL;
}
}
udelay(5);
}

return -ENOENT;
return PCIBIOS_DEVICE_NOT_FOUND;
}

static void tlp_write_packet(struct altera_pcie *pcie, u32 *headers,
Expand Down Expand Up @@ -233,7 +242,7 @@ static int tlp_cfg_dword_read(struct altera_pcie *pcie, u8 bus, u32 devfn,
else
headers[0] = TLP_CFG_DW0(TLP_FMTTYPE_CFGRD1);

headers[1] = TLP_CFG_DW1(TLP_REQ_ID(pcie->root_bus_nr, devfn),
headers[1] = TLP_CFG_DW1(TLP_REQ_ID(pcie->root_bus_nr, RP_DEVFN),
TLP_READ_TAG, byte_en);
headers[2] = TLP_CFG_DW2(bus, devfn, where);

Expand All @@ -253,7 +262,7 @@ static int tlp_cfg_dword_write(struct altera_pcie *pcie, u8 bus, u32 devfn,
else
headers[0] = TLP_CFG_DW0(TLP_FMTTYPE_CFGWR1);

headers[1] = TLP_CFG_DW1(TLP_REQ_ID(pcie->root_bus_nr, devfn),
headers[1] = TLP_CFG_DW1(TLP_REQ_ID(pcie->root_bus_nr, RP_DEVFN),
TLP_WRITE_TAG, byte_en);
headers[2] = TLP_CFG_DW2(bus, devfn, where);

Expand Down Expand Up @@ -458,7 +467,7 @@ static int altera_pcie_init_irq_domain(struct altera_pcie *pcie)
struct device_node *node = dev->of_node;

/* Setup INTx */
pcie->irq_domain = irq_domain_add_linear(node, INTX_NUM,
pcie->irq_domain = irq_domain_add_linear(node, INTX_NUM + 1,
&intx_domain_ops, pcie);
if (!pcie->irq_domain) {
dev_err(dev, "Failed to get a INTx IRQ domain\n");
Expand Down
4 changes: 2 additions & 2 deletions drivers/pci/msi.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ static int pci_msi_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
struct irq_domain *domain;

domain = pci_msi_get_domain(dev);
if (domain)
if (domain && irq_domain_is_hierarchy(domain))
return pci_msi_domain_alloc_irqs(domain, dev, nvec, type);

return arch_setup_msi_irqs(dev, nvec, type);
Expand All @@ -65,7 +65,7 @@ static void pci_msi_teardown_msi_irqs(struct pci_dev *dev)
struct irq_domain *domain;

domain = pci_msi_get_domain(dev);
if (domain)
if (domain && irq_domain_is_hierarchy(domain))
pci_msi_domain_free_irqs(domain, dev);
else
arch_teardown_msi_irqs(dev);
Expand Down

0 comments on commit 978d6a9

Please sign in to comment.