diff options
author | Ley Foon Tan <lftan@altera.com> | 2015-12-04 17:21:16 -0500 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2015-12-04 17:21:16 -0500 |
commit | ea1d3795f65e14619642b5f67382800f58e43f3d (patch) | |
tree | 49c6c45b9c7cb4c8360034d1cd4611a9305304a4 | |
parent | 23ec56708af7155414a979675dc8132a5d6e16ef (diff) |
PCI: altera: Check TLP completion status
Check TLP packet successful completion status. This fix the issue when
accessing multi-function devices in enumeration process, TLP will return
error when accessing non-exist function number. Returns PCI error code
instead of generic errno.
Tested on Ethernet adapter card with multi-functions.
[bhelgaas: simplify completion status checking code]
Signed-off-by: Ley Foon Tan <lftan@altera.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
-rw-r--r-- | drivers/pci/host/pcie-altera.c | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/drivers/pci/host/pcie-altera.c b/drivers/pci/host/pcie-altera.c index ed736a94eade..072255d5b31c 100644 --- a/drivers/pci/host/pcie-altera.c +++ b/drivers/pci/host/pcie-altera.c | |||
@@ -55,6 +55,7 @@ | |||
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 |
60 | #define RP_DEVFN 0 | 61 | #define RP_DEVFN 0 |
@@ -171,6 +172,7 @@ static int tlp_read_packet(struct altera_pcie *pcie, u32 *value) | |||
171 | bool sop = 0; | 172 | bool sop = 0; |
172 | u32 ctrl; | 173 | u32 ctrl; |
173 | u32 reg0, reg1; | 174 | u32 reg0, reg1; |
175 | u32 comp_status = 1; | ||
174 | 176 | ||
175 | /* | 177 | /* |
176 | * 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 |
@@ -182,19 +184,25 @@ static int tlp_read_packet(struct altera_pcie *pcie, u32 *value) | |||
182 | reg0 = cra_readl(pcie, RP_RXCPL_REG0); | 184 | reg0 = cra_readl(pcie, RP_RXCPL_REG0); |
183 | reg1 = cra_readl(pcie, RP_RXCPL_REG1); | 185 | reg1 = cra_readl(pcie, RP_RXCPL_REG1); |
184 | 186 | ||
185 | if (ctrl & RP_RXCPL_SOP) | 187 | if (ctrl & RP_RXCPL_SOP) { |
186 | sop = true; | 188 | sop = true; |
189 | comp_status = TLP_COMP_STATUS(reg1); | ||
190 | } | ||
187 | 191 | ||
188 | if (ctrl & RP_RXCPL_EOP) { | 192 | if (ctrl & RP_RXCPL_EOP) { |
193 | if (comp_status) | ||
194 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
195 | |||
189 | if (value) | 196 | if (value) |
190 | *value = reg0; | 197 | *value = reg0; |
198 | |||
191 | return PCIBIOS_SUCCESSFUL; | 199 | return PCIBIOS_SUCCESSFUL; |
192 | } | 200 | } |
193 | } | 201 | } |
194 | udelay(5); | 202 | udelay(5); |
195 | } | 203 | } |
196 | 204 | ||
197 | return -ENOENT; | 205 | return PCIBIOS_DEVICE_NOT_FOUND; |
198 | } | 206 | } |
199 | 207 | ||
200 | static void tlp_write_packet(struct altera_pcie *pcie, u32 *headers, | 208 | static void tlp_write_packet(struct altera_pcie *pcie, u32 *headers, |