| 1 | From 2e535c334018d58b0bf6df583486abda5bfb2003 Mon Sep 17 00:00:00 2001 |
| 2 | From: Gabor Juhos <juhosg@openwrt.org> |
| 3 | Date: Fri, 18 Nov 2011 22:25:30 +0100 |
| 4 | Subject: [PATCH 10/35] MIPS: ath79: fix broken ar724x_pci_{read,write} functions |
| 5 | |
| 6 | The current ar724x_pci_{read,write} functions are |
| 7 | broken. Due to that, pci_read_config_byte returns |
| 8 | with bogus values, and pci_write_config_{byte,word} |
| 9 | unconditionally clears the accessed PCI configuration |
| 10 | registers instead of changing the value of them. |
| 11 | |
| 12 | The patch fixes the broken functions, thus the PCI |
| 13 | configuration space can be accessed correctly. |
| 14 | |
| 15 | Signed-off-by: Gabor Juhos <juhosg@openwrt.org> |
| 16 | |
| 17 | v2: - no changes |
| 18 | |
| 19 | Output of 'lspci -vv' without the patch: |
| 20 | |
| 21 | 00:00.0 Network controller: Atheros Communications Inc. AR9285 Wireless |
| 22 | Network Adapter (PCI-Express) (rev 01) |
| 23 | Subsystem: Atheros Communications Inc. Device a091 |
| 24 | Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx- |
| 25 | Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx- |
| 26 | Latency: 0 |
| 27 | Interrupt: pin A routed to IRQ 0 |
| 28 | Region 0: Memory at 10000000 (64-bit, non-prefetchable) [size=64K] |
| 29 | Capabilities: [40] Power Management version 3 |
| 30 | Flags: PMEClk- DSI- D1+ D2- AuxCurrent=375mA PME(D0+,D1+,D2-,D3hot+,D3cold-) |
| 31 | Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME- |
| 32 | Capabilities: [50] MSI: Enable- Count=1/1 Maskable- 64bit- |
| 33 | Address: 00000000 Data: 0000 |
| 34 | Capabilities: [60] Express (v2) Legacy Endpoint, MSI 00 |
| 35 | DevCap: MaxPayload 128 bytes, PhantFunc 0, Latency L0s <512ns, L1 <64us |
| 36 | ExtTag- AttnBtn- AttnInd- PwrInd- RBE+ FLReset- |
| 37 | DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported- |
| 38 | RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop- |
| 39 | MaxPayload 128 bytes, MaxReadReq 512 bytes |
| 40 | DevSta: CorrErr- UncorrErr- FatalErr- UnsuppReq- AuxPwr- TransPend- |
| 41 | LnkCap: Port #0, Speed 2.5GT/s, Width x1, ASPM unknown, Latency L0 <512ns, L1 <64us |
| 42 | ClockPM- Surprise- LLActRep- BwNot- |
| 43 | LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- Retrain- CommClk- |
| 44 | ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt- |
| 45 | LnkSta: Speed 2.5GT/s, Width x1, TrErr- Train- SlotClk+ DLActive- BWMgmt- ABWMgmt- |
| 46 | DevCap2: Completion Timeout: Not Supported, TimeoutDis+ |
| 47 | DevCtl2: Completion Timeout: 50us to 50ms, TimeoutDis- |
| 48 | LnkCtl2: Target Link Speed: 2.5GT/s, EnterCompliance- SpeedDis-, Selectable De-emphasis: -6dB |
| 49 | Transmit Margin: Normal Operating Range, EnterModifiedCompliance- ComplianceSOS- |
| 50 | Compliance De-emphasis: -6dB |
| 51 | LnkSta2: Current De-emphasis Level: -6dB |
| 52 | |
| 53 | Output of 'lspci -vv' with the patch: |
| 54 | |
| 55 | 00:00.0 Network controller: Atheros Communications Inc. AR9285 Wireless |
| 56 | Network Adapter (PCI-Express) (rev 01) |
| 57 | Subsystem: Atheros Communications Inc. Device a091 |
| 58 | Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx- |
| 59 | Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx- |
| 60 | Latency: 0 |
| 61 | Interrupt: pin A routed to IRQ 48 |
| 62 | Region 0: Memory at 10000000 (64-bit, non-prefetchable) [size=64K] |
| 63 | Capabilities: [40] Power Management version 3 |
| 64 | Flags: PMEClk- DSI- D1+ D2- AuxCurrent=375mA PME(D0+,D1+,D2-,D3hot+,D3cold-) |
| 65 | Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME- |
| 66 | Capabilities: [50] MSI: Enable- Count=1/1 Maskable- 64bit- |
| 67 | Address: 00000000 Data: 0000 |
| 68 | Capabilities: [60] Express (v2) Legacy Endpoint, MSI 00 |
| 69 | DevCap: MaxPayload 128 bytes, PhantFunc 0, Latency L0s <512ns, L1 <64us |
| 70 | ExtTag- AttnBtn- AttnInd- PwrInd- RBE+ FLReset- |
| 71 | DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported- |
| 72 | RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop- |
| 73 | MaxPayload 128 bytes, MaxReadReq 512 bytes |
| 74 | DevSta: CorrErr- UncorrErr- FatalErr- UnsuppReq- AuxPwr- TransPend- |
| 75 | LnkCap: Port #0, Speed 2.5GT/s, Width x1, ASPM unknown, Latency L0 <512ns, L1 <64us |
| 76 | ClockPM- Surprise- LLActRep- BwNot- |
| 77 | LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- Retrain- CommClk- |
| 78 | ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt- |
| 79 | LnkSta: Speed 2.5GT/s, Width x1, TrErr- Train- SlotClk+ DLActive- BWMgmt- ABWMgmt- |
| 80 | DevCap2: Completion Timeout: Not Supported, TimeoutDis+ |
| 81 | DevCtl2: Completion Timeout: 50us to 50ms, TimeoutDis- |
| 82 | LnkCtl2: Target Link Speed: 2.5GT/s, EnterCompliance- SpeedDis-, Selectable De-emphasis: -6dB |
| 83 | Transmit Margin: Normal Operating Range, EnterModifiedCompliance- ComplianceSOS- |
| 84 | Compliance De-emphasis: -6dB |
| 85 | LnkSta2: Current De-emphasis Level: -6dB |
| 86 | Capabilities: [100 v1] Advanced Error Reporting |
| 87 | UESta: DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol- |
| 88 | UEMsk: DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol- |
| 89 | UESvrt: DLP+ SDES+ TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt- RxOF+ MalfTLP+ ECRC- UnsupReq- ACSViol- |
| 90 | CESta: RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr- |
| 91 | CEMsk: RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr+ |
| 92 | AERCap: First Error Pointer: 00, GenCap+ CGenEn- ChkCap+ ChkEn- |
| 93 | Capabilities: [140 v1] Virtual Channel |
| 94 | Caps: LPEVC=0 RefClk=100ns PATEntryBits=1 |
| 95 | Arb: Fixed- WRR32- WRR64- WRR128- |
| 96 | Ctrl: ArbSelect=Fixed |
| 97 | Status: InProgress- |
| 98 | VC0: Caps: PATOffset=00 MaxTimeSlots=1 RejSnoopTrans- |
| 99 | Arb: Fixed- WRR32- WRR64- WRR128- TWRR128- WRR256- |
| 100 | Ctrl: Enable+ ID=0 ArbSelect=Fixed TC/VC=ff |
| 101 | Status: NegoPending- InProgress- |
| 102 | Capabilities: [160 v1] Device Serial Number 00-15-17-ff-ff-24-14-12 |
| 103 | Capabilities: [170 v1] Power Budgeting <?> |
| 104 | --- |
| 105 | arch/mips/pci/pci-ar724x.c | 52 ++++++++++++++++++++++---------------------- |
| 106 | 1 files changed, 26 insertions(+), 26 deletions(-) |
| 107 | |
| 108 | --- a/arch/mips/pci/pci-ar724x.c |
| 109 | +++ b/arch/mips/pci/pci-ar724x.c |
| 110 | @@ -22,8 +22,9 @@ static void __iomem *ar724x_pci_devcfg_b |
| 111 | static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, |
| 112 | int size, uint32_t *value) |
| 113 | { |
| 114 | - unsigned long flags, addr, tval, mask; |
| 115 | + unsigned long flags; |
| 116 | void __iomem *base; |
| 117 | + u32 data; |
| 118 | |
| 119 | if (devfn) |
| 120 | return PCIBIOS_DEVICE_NOT_FOUND; |
| 121 | @@ -31,24 +32,22 @@ static int ar724x_pci_read(struct pci_bu |
| 122 | base = ar724x_pci_devcfg_base; |
| 123 | |
| 124 | spin_lock_irqsave(&ar724x_pci_lock, flags); |
| 125 | + data = __raw_readl(base + (where & ~3)); |
| 126 | |
| 127 | switch (size) { |
| 128 | case 1: |
| 129 | - addr = where & ~3; |
| 130 | - mask = 0xff000000 >> ((where % 4) * 8); |
| 131 | - tval = __raw_readl(base + addr); |
| 132 | - tval = tval & ~mask; |
| 133 | - *value = (tval >> ((4 - (where % 4))*8)); |
| 134 | + if (where & 1) |
| 135 | + data >>= 8; |
| 136 | + if (where & 2) |
| 137 | + data >>= 16; |
| 138 | + data &= 0xff; |
| 139 | break; |
| 140 | case 2: |
| 141 | - addr = where & ~3; |
| 142 | - mask = 0xffff0000 >> ((where % 4)*8); |
| 143 | - tval = __raw_readl(base + addr); |
| 144 | - tval = tval & ~mask; |
| 145 | - *value = (tval >> ((4 - (where % 4))*8)); |
| 146 | + if (where & 2) |
| 147 | + data >>= 16; |
| 148 | + data &= 0xffff; |
| 149 | break; |
| 150 | case 4: |
| 151 | - *value = __raw_readl(base + where); |
| 152 | break; |
| 153 | default: |
| 154 | spin_unlock_irqrestore(&ar724x_pci_lock, flags); |
| 155 | @@ -57,6 +56,7 @@ static int ar724x_pci_read(struct pci_bu |
| 156 | } |
| 157 | |
| 158 | spin_unlock_irqrestore(&ar724x_pci_lock, flags); |
| 159 | + *value = data; |
| 160 | |
| 161 | return PCIBIOS_SUCCESSFUL; |
| 162 | } |
| 163 | @@ -64,8 +64,10 @@ static int ar724x_pci_read(struct pci_bu |
| 164 | static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where, |
| 165 | int size, uint32_t value) |
| 166 | { |
| 167 | - unsigned long flags, tval, addr, mask; |
| 168 | + unsigned long flags; |
| 169 | void __iomem *base; |
| 170 | + u32 data; |
| 171 | + int s; |
| 172 | |
| 173 | if (devfn) |
| 174 | return PCIBIOS_DEVICE_NOT_FOUND; |
| 175 | @@ -73,26 +75,21 @@ static int ar724x_pci_write(struct pci_b |
| 176 | base = ar724x_pci_devcfg_base; |
| 177 | |
| 178 | spin_lock_irqsave(&ar724x_pci_lock, flags); |
| 179 | + data = __raw_readl(base + (where & ~3)); |
| 180 | |
| 181 | switch (size) { |
| 182 | case 1: |
| 183 | - addr = where & ~3; |
| 184 | - mask = 0xff000000 >> ((where % 4)*8); |
| 185 | - tval = __raw_readl(base + addr); |
| 186 | - tval = tval & ~mask; |
| 187 | - tval |= (value << ((4 - (where % 4))*8)) & mask; |
| 188 | - __raw_writel(tval, base + addr); |
| 189 | + s = ((where & 3) * 8); |
| 190 | + data &= ~(0xff << s); |
| 191 | + data |= ((value & 0xff) << s); |
| 192 | break; |
| 193 | case 2: |
| 194 | - addr = where & ~3; |
| 195 | - mask = 0xffff0000 >> ((where % 4)*8); |
| 196 | - tval = __raw_readl(base + addr); |
| 197 | - tval = tval & ~mask; |
| 198 | - tval |= (value << ((4 - (where % 4))*8)) & mask; |
| 199 | - __raw_writel(tval, base + addr); |
| 200 | + s = ((where & 2) * 8); |
| 201 | + data &= ~(0xffff << s); |
| 202 | + data |= ((value & 0xffff) << s); |
| 203 | break; |
| 204 | case 4: |
| 205 | - __raw_writel(value, (base + where)); |
| 206 | + data = value; |
| 207 | break; |
| 208 | default: |
| 209 | spin_unlock_irqrestore(&ar724x_pci_lock, flags); |
| 210 | @@ -100,6 +97,9 @@ static int ar724x_pci_write(struct pci_b |
| 211 | return PCIBIOS_BAD_REGISTER_NUMBER; |
| 212 | } |
| 213 | |
| 214 | + __raw_writel(data, base + (where & ~3)); |
| 215 | + /* flush write */ |
| 216 | + __raw_readl(base + (where & ~3)); |
| 217 | spin_unlock_irqrestore(&ar724x_pci_lock, flags); |
| 218 | |
| 219 | return PCIBIOS_SUCCESSFUL; |
| 220 | |