diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-12-09 12:26:06 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-12-09 12:26:06 -0500 |
commit | 978d6a90411ca92e591f3434c98d200e4e3dc5dd (patch) | |
tree | c48b73a2eb33b0c387107a3c1beace8102df7afa | |
parent | aa53685549a2cfb5f175b0c4a20bc9aa1e5a1b85 (diff) | |
parent | 99496bd2971fc378226ad4413e5b72c4545714bd (diff) |
Merge tag 'pci-v4.4-fixes-2' of git://git.kernel.org/pub/scm/linux/kernel/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
-rw-r--r-- | drivers/pci/host/pcie-altera.c | 23 | ||||
-rw-r--r-- | drivers/pci/msi.c | 4 |
2 files changed, 18 insertions, 9 deletions
diff --git a/drivers/pci/host/pcie-altera.c b/drivers/pci/host/pcie-altera.c index e5dda38bdde5..99da549d5d06 100644 --- a/drivers/pci/host/pcie-altera.c +++ b/drivers/pci/host/pcie-altera.c | |||
@@ -55,8 +55,10 @@ | |||
55 | #define TLP_CFG_DW2(bus, devfn, offset) \ | 55 | #define TLP_CFG_DW2(bus, devfn, offset) \ |
56 | (((bus) << 24) | ((devfn) << 16) | (offset)) | 56 | (((bus) << 24) | ((devfn) << 16) | (offset)) |
57 | #define TLP_REQ_ID(bus, devfn) (((bus) << 8) | (devfn)) | 57 | #define TLP_REQ_ID(bus, devfn) (((bus) << 8) | (devfn)) |
58 | #define TLP_COMP_STATUS(s) (((s) >> 12) & 7) | ||
58 | #define TLP_HDR_SIZE 3 | 59 | #define TLP_HDR_SIZE 3 |
59 | #define TLP_LOOP 500 | 60 | #define TLP_LOOP 500 |
61 | #define RP_DEVFN 0 | ||
60 | 62 | ||
61 | #define INTX_NUM 4 | 63 | #define INTX_NUM 4 |
62 | 64 | ||
@@ -166,34 +168,41 @@ static bool altera_pcie_valid_config(struct altera_pcie *pcie, | |||
166 | 168 | ||
167 | static int tlp_read_packet(struct altera_pcie *pcie, u32 *value) | 169 | static int tlp_read_packet(struct altera_pcie *pcie, u32 *value) |
168 | { | 170 | { |
169 | u8 loop; | 171 | int i; |
170 | bool sop = 0; | 172 | bool sop = 0; |
171 | u32 ctrl; | 173 | u32 ctrl; |
172 | u32 reg0, reg1; | 174 | u32 reg0, reg1; |
175 | u32 comp_status = 1; | ||
173 | 176 | ||
174 | /* | 177 | /* |
175 | * Minimum 2 loops to read TLP headers and 1 loop to read data | 178 | * Minimum 2 loops to read TLP headers and 1 loop to read data |
176 | * payload. | 179 | * payload. |
177 | */ | 180 | */ |
178 | for (loop = 0; loop < TLP_LOOP; loop++) { | 181 | for (i = 0; i < TLP_LOOP; i++) { |
179 | ctrl = cra_readl(pcie, RP_RXCPL_STATUS); | 182 | ctrl = cra_readl(pcie, RP_RXCPL_STATUS); |
180 | if ((ctrl & RP_RXCPL_SOP) || (ctrl & RP_RXCPL_EOP) || sop) { | 183 | if ((ctrl & RP_RXCPL_SOP) || (ctrl & RP_RXCPL_EOP) || sop) { |
181 | reg0 = cra_readl(pcie, RP_RXCPL_REG0); | 184 | reg0 = cra_readl(pcie, RP_RXCPL_REG0); |
182 | reg1 = cra_readl(pcie, RP_RXCPL_REG1); | 185 | reg1 = cra_readl(pcie, RP_RXCPL_REG1); |
183 | 186 | ||
184 | if (ctrl & RP_RXCPL_SOP) | 187 | if (ctrl & RP_RXCPL_SOP) { |
185 | sop = true; | 188 | sop = true; |
189 | comp_status = TLP_COMP_STATUS(reg1); | ||
190 | } | ||
186 | 191 | ||
187 | if (ctrl & RP_RXCPL_EOP) { | 192 | if (ctrl & RP_RXCPL_EOP) { |
193 | if (comp_status) | ||
194 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
195 | |||
188 | if (value) | 196 | if (value) |
189 | *value = reg0; | 197 | *value = reg0; |
198 | |||
190 | return PCIBIOS_SUCCESSFUL; | 199 | return PCIBIOS_SUCCESSFUL; |
191 | } | 200 | } |
192 | } | 201 | } |
193 | udelay(5); | 202 | udelay(5); |
194 | } | 203 | } |
195 | 204 | ||
196 | return -ENOENT; | 205 | return PCIBIOS_DEVICE_NOT_FOUND; |
197 | } | 206 | } |
198 | 207 | ||
199 | static void tlp_write_packet(struct altera_pcie *pcie, u32 *headers, | 208 | static void tlp_write_packet(struct altera_pcie *pcie, u32 *headers, |
@@ -233,7 +242,7 @@ static int tlp_cfg_dword_read(struct altera_pcie *pcie, u8 bus, u32 devfn, | |||
233 | else | 242 | else |
234 | headers[0] = TLP_CFG_DW0(TLP_FMTTYPE_CFGRD1); | 243 | headers[0] = TLP_CFG_DW0(TLP_FMTTYPE_CFGRD1); |
235 | 244 | ||
236 | headers[1] = TLP_CFG_DW1(TLP_REQ_ID(pcie->root_bus_nr, devfn), | 245 | headers[1] = TLP_CFG_DW1(TLP_REQ_ID(pcie->root_bus_nr, RP_DEVFN), |
237 | TLP_READ_TAG, byte_en); | 246 | TLP_READ_TAG, byte_en); |
238 | headers[2] = TLP_CFG_DW2(bus, devfn, where); | 247 | headers[2] = TLP_CFG_DW2(bus, devfn, where); |
239 | 248 | ||
@@ -253,7 +262,7 @@ static int tlp_cfg_dword_write(struct altera_pcie *pcie, u8 bus, u32 devfn, | |||
253 | else | 262 | else |
254 | headers[0] = TLP_CFG_DW0(TLP_FMTTYPE_CFGWR1); | 263 | headers[0] = TLP_CFG_DW0(TLP_FMTTYPE_CFGWR1); |
255 | 264 | ||
256 | headers[1] = TLP_CFG_DW1(TLP_REQ_ID(pcie->root_bus_nr, devfn), | 265 | headers[1] = TLP_CFG_DW1(TLP_REQ_ID(pcie->root_bus_nr, RP_DEVFN), |
257 | TLP_WRITE_TAG, byte_en); | 266 | TLP_WRITE_TAG, byte_en); |
258 | headers[2] = TLP_CFG_DW2(bus, devfn, where); | 267 | headers[2] = TLP_CFG_DW2(bus, devfn, where); |
259 | 268 | ||
@@ -458,7 +467,7 @@ static int altera_pcie_init_irq_domain(struct altera_pcie *pcie) | |||
458 | struct device_node *node = dev->of_node; | 467 | struct device_node *node = dev->of_node; |
459 | 468 | ||
460 | /* Setup INTx */ | 469 | /* Setup INTx */ |
461 | pcie->irq_domain = irq_domain_add_linear(node, INTX_NUM, | 470 | pcie->irq_domain = irq_domain_add_linear(node, INTX_NUM + 1, |
462 | &intx_domain_ops, pcie); | 471 | &intx_domain_ops, pcie); |
463 | if (!pcie->irq_domain) { | 472 | if (!pcie->irq_domain) { |
464 | dev_err(dev, "Failed to get a INTx IRQ domain\n"); | 473 | dev_err(dev, "Failed to get a INTx IRQ domain\n"); |
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 53e463244bb7..7eaa4c87fec7 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
@@ -54,7 +54,7 @@ static int pci_msi_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
54 | struct irq_domain *domain; | 54 | struct irq_domain *domain; |
55 | 55 | ||
56 | domain = pci_msi_get_domain(dev); | 56 | domain = pci_msi_get_domain(dev); |
57 | if (domain) | 57 | if (domain && irq_domain_is_hierarchy(domain)) |
58 | return pci_msi_domain_alloc_irqs(domain, dev, nvec, type); | 58 | return pci_msi_domain_alloc_irqs(domain, dev, nvec, type); |
59 | 59 | ||
60 | return arch_setup_msi_irqs(dev, nvec, type); | 60 | return arch_setup_msi_irqs(dev, nvec, type); |
@@ -65,7 +65,7 @@ static void pci_msi_teardown_msi_irqs(struct pci_dev *dev) | |||
65 | struct irq_domain *domain; | 65 | struct irq_domain *domain; |
66 | 66 | ||
67 | domain = pci_msi_get_domain(dev); | 67 | domain = pci_msi_get_domain(dev); |
68 | if (domain) | 68 | if (domain && irq_domain_is_hierarchy(domain)) |
69 | pci_msi_domain_free_irqs(domain, dev); | 69 | pci_msi_domain_free_irqs(domain, dev); |
70 | else | 70 | else |
71 | arch_teardown_msi_irqs(dev); | 71 | arch_teardown_msi_irqs(dev); |