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 /drivers | |
| 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>
Diffstat (limited to 'drivers')
| -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, |
