diff options
author | Bryan O'Sullivan <bos@pathscale.com> | 2006-03-29 18:23:26 -0500 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2006-03-31 16:14:18 -0500 |
commit | cc533a5721b79d231c127fd56d55e6df23c19770 (patch) | |
tree | 3b4f172b5c056b7b88005214f81f465391e4b8c5 /drivers/infiniband | |
parent | d41d3aeb76135a70bfda9cd6666290fee0700b70 (diff) |
IB/ipath: support for HyperTransport devices
The ipath_ht400.c file contains routines and definitions specific to
HyperTransport-based InfiniPath devices.
Signed-off-by: Bryan O'Sullivan <bos@pathscale.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_ht400.c | 1586 |
1 files changed, 1586 insertions, 0 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_ht400.c b/drivers/infiniband/hw/ipath/ipath_ht400.c new file mode 100644 index 000000000000..4652435998f3 --- /dev/null +++ b/drivers/infiniband/hw/ipath/ipath_ht400.c | |||
@@ -0,0 +1,1586 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. | ||
3 | * | ||
4 | * This software is available to you under a choice of one of two | ||
5 | * licenses. You may choose to be licensed under the terms of the GNU | ||
6 | * General Public License (GPL) Version 2, available from the file | ||
7 | * COPYING in the main directory of this source tree, or the | ||
8 | * OpenIB.org BSD license below: | ||
9 | * | ||
10 | * Redistribution and use in source and binary forms, with or | ||
11 | * without modification, are permitted provided that the following | ||
12 | * conditions are met: | ||
13 | * | ||
14 | * - Redistributions of source code must retain the above | ||
15 | * copyright notice, this list of conditions and the following | ||
16 | * disclaimer. | ||
17 | * | ||
18 | * - Redistributions in binary form must reproduce the above | ||
19 | * copyright notice, this list of conditions and the following | ||
20 | * disclaimer in the documentation and/or other materials | ||
21 | * provided with the distribution. | ||
22 | * | ||
23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
24 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
25 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
26 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
27 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
28 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
29 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
30 | * SOFTWARE. | ||
31 | */ | ||
32 | |||
33 | /* | ||
34 | * This file contains all of the code that is specific to the InfiniPath | ||
35 | * HT-400 chip. | ||
36 | */ | ||
37 | |||
38 | #include <linux/pci.h> | ||
39 | #include <linux/delay.h> | ||
40 | |||
41 | #include "ipath_kernel.h" | ||
42 | #include "ipath_registers.h" | ||
43 | |||
44 | /* | ||
45 | * This lists the InfiniPath HT400 registers, in the actual chip layout. | ||
46 | * This structure should never be directly accessed. | ||
47 | * | ||
48 | * The names are in InterCap form because they're taken straight from | ||
49 | * the chip specification. Since they're only used in this file, they | ||
50 | * don't pollute the rest of the source. | ||
51 | */ | ||
52 | |||
53 | struct _infinipath_do_not_use_kernel_regs { | ||
54 | unsigned long long Revision; | ||
55 | unsigned long long Control; | ||
56 | unsigned long long PageAlign; | ||
57 | unsigned long long PortCnt; | ||
58 | unsigned long long DebugPortSelect; | ||
59 | unsigned long long DebugPort; | ||
60 | unsigned long long SendRegBase; | ||
61 | unsigned long long UserRegBase; | ||
62 | unsigned long long CounterRegBase; | ||
63 | unsigned long long Scratch; | ||
64 | unsigned long long ReservedMisc1; | ||
65 | unsigned long long InterruptConfig; | ||
66 | unsigned long long IntBlocked; | ||
67 | unsigned long long IntMask; | ||
68 | unsigned long long IntStatus; | ||
69 | unsigned long long IntClear; | ||
70 | unsigned long long ErrorMask; | ||
71 | unsigned long long ErrorStatus; | ||
72 | unsigned long long ErrorClear; | ||
73 | unsigned long long HwErrMask; | ||
74 | unsigned long long HwErrStatus; | ||
75 | unsigned long long HwErrClear; | ||
76 | unsigned long long HwDiagCtrl; | ||
77 | unsigned long long MDIO; | ||
78 | unsigned long long IBCStatus; | ||
79 | unsigned long long IBCCtrl; | ||
80 | unsigned long long ExtStatus; | ||
81 | unsigned long long ExtCtrl; | ||
82 | unsigned long long GPIOOut; | ||
83 | unsigned long long GPIOMask; | ||
84 | unsigned long long GPIOStatus; | ||
85 | unsigned long long GPIOClear; | ||
86 | unsigned long long RcvCtrl; | ||
87 | unsigned long long RcvBTHQP; | ||
88 | unsigned long long RcvHdrSize; | ||
89 | unsigned long long RcvHdrCnt; | ||
90 | unsigned long long RcvHdrEntSize; | ||
91 | unsigned long long RcvTIDBase; | ||
92 | unsigned long long RcvTIDCnt; | ||
93 | unsigned long long RcvEgrBase; | ||
94 | unsigned long long RcvEgrCnt; | ||
95 | unsigned long long RcvBufBase; | ||
96 | unsigned long long RcvBufSize; | ||
97 | unsigned long long RxIntMemBase; | ||
98 | unsigned long long RxIntMemSize; | ||
99 | unsigned long long RcvPartitionKey; | ||
100 | unsigned long long ReservedRcv[10]; | ||
101 | unsigned long long SendCtrl; | ||
102 | unsigned long long SendPIOBufBase; | ||
103 | unsigned long long SendPIOSize; | ||
104 | unsigned long long SendPIOBufCnt; | ||
105 | unsigned long long SendPIOAvailAddr; | ||
106 | unsigned long long TxIntMemBase; | ||
107 | unsigned long long TxIntMemSize; | ||
108 | unsigned long long ReservedSend[9]; | ||
109 | unsigned long long SendBufferError; | ||
110 | unsigned long long SendBufferErrorCONT1; | ||
111 | unsigned long long SendBufferErrorCONT2; | ||
112 | unsigned long long SendBufferErrorCONT3; | ||
113 | unsigned long long ReservedSBE[4]; | ||
114 | unsigned long long RcvHdrAddr0; | ||
115 | unsigned long long RcvHdrAddr1; | ||
116 | unsigned long long RcvHdrAddr2; | ||
117 | unsigned long long RcvHdrAddr3; | ||
118 | unsigned long long RcvHdrAddr4; | ||
119 | unsigned long long RcvHdrAddr5; | ||
120 | unsigned long long RcvHdrAddr6; | ||
121 | unsigned long long RcvHdrAddr7; | ||
122 | unsigned long long RcvHdrAddr8; | ||
123 | unsigned long long ReservedRHA[7]; | ||
124 | unsigned long long RcvHdrTailAddr0; | ||
125 | unsigned long long RcvHdrTailAddr1; | ||
126 | unsigned long long RcvHdrTailAddr2; | ||
127 | unsigned long long RcvHdrTailAddr3; | ||
128 | unsigned long long RcvHdrTailAddr4; | ||
129 | unsigned long long RcvHdrTailAddr5; | ||
130 | unsigned long long RcvHdrTailAddr6; | ||
131 | unsigned long long RcvHdrTailAddr7; | ||
132 | unsigned long long RcvHdrTailAddr8; | ||
133 | unsigned long long ReservedRHTA[7]; | ||
134 | unsigned long long Sync; /* Software only */ | ||
135 | unsigned long long Dump; /* Software only */ | ||
136 | unsigned long long SimVer; /* Software only */ | ||
137 | unsigned long long ReservedSW[5]; | ||
138 | unsigned long long SerdesConfig0; | ||
139 | unsigned long long SerdesConfig1; | ||
140 | unsigned long long SerdesStatus; | ||
141 | unsigned long long XGXSConfig; | ||
142 | unsigned long long ReservedSW2[4]; | ||
143 | }; | ||
144 | |||
145 | #define IPATH_KREG_OFFSET(field) (offsetof(struct \ | ||
146 | _infinipath_do_not_use_kernel_regs, field) / sizeof(u64)) | ||
147 | #define IPATH_CREG_OFFSET(field) (offsetof( \ | ||
148 | struct infinipath_counters, field) / sizeof(u64)) | ||
149 | |||
150 | static const struct ipath_kregs ipath_ht_kregs = { | ||
151 | .kr_control = IPATH_KREG_OFFSET(Control), | ||
152 | .kr_counterregbase = IPATH_KREG_OFFSET(CounterRegBase), | ||
153 | .kr_debugport = IPATH_KREG_OFFSET(DebugPort), | ||
154 | .kr_debugportselect = IPATH_KREG_OFFSET(DebugPortSelect), | ||
155 | .kr_errorclear = IPATH_KREG_OFFSET(ErrorClear), | ||
156 | .kr_errormask = IPATH_KREG_OFFSET(ErrorMask), | ||
157 | .kr_errorstatus = IPATH_KREG_OFFSET(ErrorStatus), | ||
158 | .kr_extctrl = IPATH_KREG_OFFSET(ExtCtrl), | ||
159 | .kr_extstatus = IPATH_KREG_OFFSET(ExtStatus), | ||
160 | .kr_gpio_clear = IPATH_KREG_OFFSET(GPIOClear), | ||
161 | .kr_gpio_mask = IPATH_KREG_OFFSET(GPIOMask), | ||
162 | .kr_gpio_out = IPATH_KREG_OFFSET(GPIOOut), | ||
163 | .kr_gpio_status = IPATH_KREG_OFFSET(GPIOStatus), | ||
164 | .kr_hwdiagctrl = IPATH_KREG_OFFSET(HwDiagCtrl), | ||
165 | .kr_hwerrclear = IPATH_KREG_OFFSET(HwErrClear), | ||
166 | .kr_hwerrmask = IPATH_KREG_OFFSET(HwErrMask), | ||
167 | .kr_hwerrstatus = IPATH_KREG_OFFSET(HwErrStatus), | ||
168 | .kr_ibcctrl = IPATH_KREG_OFFSET(IBCCtrl), | ||
169 | .kr_ibcstatus = IPATH_KREG_OFFSET(IBCStatus), | ||
170 | .kr_intblocked = IPATH_KREG_OFFSET(IntBlocked), | ||
171 | .kr_intclear = IPATH_KREG_OFFSET(IntClear), | ||
172 | .kr_interruptconfig = IPATH_KREG_OFFSET(InterruptConfig), | ||
173 | .kr_intmask = IPATH_KREG_OFFSET(IntMask), | ||
174 | .kr_intstatus = IPATH_KREG_OFFSET(IntStatus), | ||
175 | .kr_mdio = IPATH_KREG_OFFSET(MDIO), | ||
176 | .kr_pagealign = IPATH_KREG_OFFSET(PageAlign), | ||
177 | .kr_partitionkey = IPATH_KREG_OFFSET(RcvPartitionKey), | ||
178 | .kr_portcnt = IPATH_KREG_OFFSET(PortCnt), | ||
179 | .kr_rcvbthqp = IPATH_KREG_OFFSET(RcvBTHQP), | ||
180 | .kr_rcvbufbase = IPATH_KREG_OFFSET(RcvBufBase), | ||
181 | .kr_rcvbufsize = IPATH_KREG_OFFSET(RcvBufSize), | ||
182 | .kr_rcvctrl = IPATH_KREG_OFFSET(RcvCtrl), | ||
183 | .kr_rcvegrbase = IPATH_KREG_OFFSET(RcvEgrBase), | ||
184 | .kr_rcvegrcnt = IPATH_KREG_OFFSET(RcvEgrCnt), | ||
185 | .kr_rcvhdrcnt = IPATH_KREG_OFFSET(RcvHdrCnt), | ||
186 | .kr_rcvhdrentsize = IPATH_KREG_OFFSET(RcvHdrEntSize), | ||
187 | .kr_rcvhdrsize = IPATH_KREG_OFFSET(RcvHdrSize), | ||
188 | .kr_rcvintmembase = IPATH_KREG_OFFSET(RxIntMemBase), | ||
189 | .kr_rcvintmemsize = IPATH_KREG_OFFSET(RxIntMemSize), | ||
190 | .kr_rcvtidbase = IPATH_KREG_OFFSET(RcvTIDBase), | ||
191 | .kr_rcvtidcnt = IPATH_KREG_OFFSET(RcvTIDCnt), | ||
192 | .kr_revision = IPATH_KREG_OFFSET(Revision), | ||
193 | .kr_scratch = IPATH_KREG_OFFSET(Scratch), | ||
194 | .kr_sendbuffererror = IPATH_KREG_OFFSET(SendBufferError), | ||
195 | .kr_sendctrl = IPATH_KREG_OFFSET(SendCtrl), | ||
196 | .kr_sendpioavailaddr = IPATH_KREG_OFFSET(SendPIOAvailAddr), | ||
197 | .kr_sendpiobufbase = IPATH_KREG_OFFSET(SendPIOBufBase), | ||
198 | .kr_sendpiobufcnt = IPATH_KREG_OFFSET(SendPIOBufCnt), | ||
199 | .kr_sendpiosize = IPATH_KREG_OFFSET(SendPIOSize), | ||
200 | .kr_sendregbase = IPATH_KREG_OFFSET(SendRegBase), | ||
201 | .kr_txintmembase = IPATH_KREG_OFFSET(TxIntMemBase), | ||
202 | .kr_txintmemsize = IPATH_KREG_OFFSET(TxIntMemSize), | ||
203 | .kr_userregbase = IPATH_KREG_OFFSET(UserRegBase), | ||
204 | .kr_serdesconfig0 = IPATH_KREG_OFFSET(SerdesConfig0), | ||
205 | .kr_serdesconfig1 = IPATH_KREG_OFFSET(SerdesConfig1), | ||
206 | .kr_serdesstatus = IPATH_KREG_OFFSET(SerdesStatus), | ||
207 | .kr_xgxsconfig = IPATH_KREG_OFFSET(XGXSConfig), | ||
208 | /* | ||
209 | * These should not be used directly via ipath_read_kreg64(), | ||
210 | * use them with ipath_read_kreg64_port(), | ||
211 | */ | ||
212 | .kr_rcvhdraddr = IPATH_KREG_OFFSET(RcvHdrAddr0), | ||
213 | .kr_rcvhdrtailaddr = IPATH_KREG_OFFSET(RcvHdrTailAddr0) | ||
214 | }; | ||
215 | |||
216 | static const struct ipath_cregs ipath_ht_cregs = { | ||
217 | .cr_badformatcnt = IPATH_CREG_OFFSET(RxBadFormatCnt), | ||
218 | .cr_erricrccnt = IPATH_CREG_OFFSET(RxICRCErrCnt), | ||
219 | .cr_errlinkcnt = IPATH_CREG_OFFSET(RxLinkProblemCnt), | ||
220 | .cr_errlpcrccnt = IPATH_CREG_OFFSET(RxLPCRCErrCnt), | ||
221 | .cr_errpkey = IPATH_CREG_OFFSET(RxPKeyMismatchCnt), | ||
222 | .cr_errrcvflowctrlcnt = IPATH_CREG_OFFSET(RxFlowCtrlErrCnt), | ||
223 | .cr_err_rlencnt = IPATH_CREG_OFFSET(RxLenErrCnt), | ||
224 | .cr_errslencnt = IPATH_CREG_OFFSET(TxLenErrCnt), | ||
225 | .cr_errtidfull = IPATH_CREG_OFFSET(RxTIDFullErrCnt), | ||
226 | .cr_errtidvalid = IPATH_CREG_OFFSET(RxTIDValidErrCnt), | ||
227 | .cr_errvcrccnt = IPATH_CREG_OFFSET(RxVCRCErrCnt), | ||
228 | .cr_ibstatuschange = IPATH_CREG_OFFSET(IBStatusChangeCnt), | ||
229 | /* calc from Reg_CounterRegBase + offset */ | ||
230 | .cr_intcnt = IPATH_CREG_OFFSET(LBIntCnt), | ||
231 | .cr_invalidrlencnt = IPATH_CREG_OFFSET(RxMaxMinLenErrCnt), | ||
232 | .cr_invalidslencnt = IPATH_CREG_OFFSET(TxMaxMinLenErrCnt), | ||
233 | .cr_lbflowstallcnt = IPATH_CREG_OFFSET(LBFlowStallCnt), | ||
234 | .cr_pktrcvcnt = IPATH_CREG_OFFSET(RxDataPktCnt), | ||
235 | .cr_pktrcvflowctrlcnt = IPATH_CREG_OFFSET(RxFlowPktCnt), | ||
236 | .cr_pktsendcnt = IPATH_CREG_OFFSET(TxDataPktCnt), | ||
237 | .cr_pktsendflowcnt = IPATH_CREG_OFFSET(TxFlowPktCnt), | ||
238 | .cr_portovflcnt = IPATH_CREG_OFFSET(RxP0HdrEgrOvflCnt), | ||
239 | .cr_rcvebpcnt = IPATH_CREG_OFFSET(RxEBPCnt), | ||
240 | .cr_rcvovflcnt = IPATH_CREG_OFFSET(RxBufOvflCnt), | ||
241 | .cr_senddropped = IPATH_CREG_OFFSET(TxDroppedPktCnt), | ||
242 | .cr_sendstallcnt = IPATH_CREG_OFFSET(TxFlowStallCnt), | ||
243 | .cr_sendunderruncnt = IPATH_CREG_OFFSET(TxUnderrunCnt), | ||
244 | .cr_wordrcvcnt = IPATH_CREG_OFFSET(RxDwordCnt), | ||
245 | .cr_wordsendcnt = IPATH_CREG_OFFSET(TxDwordCnt), | ||
246 | .cr_unsupvlcnt = IPATH_CREG_OFFSET(TxUnsupVLErrCnt), | ||
247 | .cr_rxdroppktcnt = IPATH_CREG_OFFSET(RxDroppedPktCnt), | ||
248 | .cr_iblinkerrrecovcnt = IPATH_CREG_OFFSET(IBLinkErrRecoveryCnt), | ||
249 | .cr_iblinkdowncnt = IPATH_CREG_OFFSET(IBLinkDownedCnt), | ||
250 | .cr_ibsymbolerrcnt = IPATH_CREG_OFFSET(IBSymbolErrCnt) | ||
251 | }; | ||
252 | |||
253 | /* kr_intstatus, kr_intclear, kr_intmask bits */ | ||
254 | #define INFINIPATH_I_RCVURG_MASK 0x1FF | ||
255 | #define INFINIPATH_I_RCVAVAIL_MASK 0x1FF | ||
256 | |||
257 | /* kr_hwerrclear, kr_hwerrmask, kr_hwerrstatus, bits */ | ||
258 | #define INFINIPATH_HWE_HTCMEMPARITYERR_SHIFT 0 | ||
259 | #define INFINIPATH_HWE_HTCMEMPARITYERR_MASK 0x3FFFFFULL | ||
260 | #define INFINIPATH_HWE_HTCLNKABYTE0CRCERR 0x0000000000800000ULL | ||
261 | #define INFINIPATH_HWE_HTCLNKABYTE1CRCERR 0x0000000001000000ULL | ||
262 | #define INFINIPATH_HWE_HTCLNKBBYTE0CRCERR 0x0000000002000000ULL | ||
263 | #define INFINIPATH_HWE_HTCLNKBBYTE1CRCERR 0x0000000004000000ULL | ||
264 | #define INFINIPATH_HWE_HTCMISCERR4 0x0000000008000000ULL | ||
265 | #define INFINIPATH_HWE_HTCMISCERR5 0x0000000010000000ULL | ||
266 | #define INFINIPATH_HWE_HTCMISCERR6 0x0000000020000000ULL | ||
267 | #define INFINIPATH_HWE_HTCMISCERR7 0x0000000040000000ULL | ||
268 | #define INFINIPATH_HWE_HTCBUSTREQPARITYERR 0x0000000080000000ULL | ||
269 | #define INFINIPATH_HWE_HTCBUSTRESPPARITYERR 0x0000000100000000ULL | ||
270 | #define INFINIPATH_HWE_HTCBUSIREQPARITYERR 0x0000000200000000ULL | ||
271 | #define INFINIPATH_HWE_COREPLL_FBSLIP 0x0080000000000000ULL | ||
272 | #define INFINIPATH_HWE_COREPLL_RFSLIP 0x0100000000000000ULL | ||
273 | #define INFINIPATH_HWE_HTBPLL_FBSLIP 0x0200000000000000ULL | ||
274 | #define INFINIPATH_HWE_HTBPLL_RFSLIP 0x0400000000000000ULL | ||
275 | #define INFINIPATH_HWE_HTAPLL_FBSLIP 0x0800000000000000ULL | ||
276 | #define INFINIPATH_HWE_HTAPLL_RFSLIP 0x1000000000000000ULL | ||
277 | #define INFINIPATH_HWE_SERDESPLLFAILED 0x2000000000000000ULL | ||
278 | |||
279 | /* kr_extstatus bits */ | ||
280 | #define INFINIPATH_EXTS_FREQSEL 0x2 | ||
281 | #define INFINIPATH_EXTS_SERDESSEL 0x4 | ||
282 | #define INFINIPATH_EXTS_MEMBIST_ENDTEST 0x0000000000004000 | ||
283 | #define INFINIPATH_EXTS_MEMBIST_CORRECT 0x0000000000008000 | ||
284 | |||
285 | /* | ||
286 | * masks and bits that are different in different chips, or present only | ||
287 | * in one | ||
288 | */ | ||
289 | static const ipath_err_t infinipath_hwe_htcmemparityerr_mask = | ||
290 | INFINIPATH_HWE_HTCMEMPARITYERR_MASK; | ||
291 | static const ipath_err_t infinipath_hwe_htcmemparityerr_shift = | ||
292 | INFINIPATH_HWE_HTCMEMPARITYERR_SHIFT; | ||
293 | |||
294 | static const ipath_err_t infinipath_hwe_htclnkabyte0crcerr = | ||
295 | INFINIPATH_HWE_HTCLNKABYTE0CRCERR; | ||
296 | static const ipath_err_t infinipath_hwe_htclnkabyte1crcerr = | ||
297 | INFINIPATH_HWE_HTCLNKABYTE1CRCERR; | ||
298 | static const ipath_err_t infinipath_hwe_htclnkbbyte0crcerr = | ||
299 | INFINIPATH_HWE_HTCLNKBBYTE0CRCERR; | ||
300 | static const ipath_err_t infinipath_hwe_htclnkbbyte1crcerr = | ||
301 | INFINIPATH_HWE_HTCLNKBBYTE1CRCERR; | ||
302 | |||
303 | #define _IPATH_GPIO_SDA_NUM 1 | ||
304 | #define _IPATH_GPIO_SCL_NUM 0 | ||
305 | |||
306 | #define IPATH_GPIO_SDA \ | ||
307 | (1ULL << (_IPATH_GPIO_SDA_NUM+INFINIPATH_EXTC_GPIOOE_SHIFT)) | ||
308 | #define IPATH_GPIO_SCL \ | ||
309 | (1ULL << (_IPATH_GPIO_SCL_NUM+INFINIPATH_EXTC_GPIOOE_SHIFT)) | ||
310 | |||
311 | /* keep the code below somewhat more readonable; not used elsewhere */ | ||
312 | #define _IPATH_HTLINK0_CRCBITS (infinipath_hwe_htclnkabyte0crcerr | \ | ||
313 | infinipath_hwe_htclnkabyte1crcerr) | ||
314 | #define _IPATH_HTLINK1_CRCBITS (infinipath_hwe_htclnkbbyte0crcerr | \ | ||
315 | infinipath_hwe_htclnkbbyte1crcerr) | ||
316 | #define _IPATH_HTLANE0_CRCBITS (infinipath_hwe_htclnkabyte0crcerr | \ | ||
317 | infinipath_hwe_htclnkbbyte0crcerr) | ||
318 | #define _IPATH_HTLANE1_CRCBITS (infinipath_hwe_htclnkabyte1crcerr | \ | ||
319 | infinipath_hwe_htclnkbbyte1crcerr) | ||
320 | |||
321 | static void hwerr_crcbits(struct ipath_devdata *dd, ipath_err_t hwerrs, | ||
322 | char *msg, size_t msgl) | ||
323 | { | ||
324 | char bitsmsg[64]; | ||
325 | ipath_err_t crcbits = hwerrs & | ||
326 | (_IPATH_HTLINK0_CRCBITS | _IPATH_HTLINK1_CRCBITS); | ||
327 | /* don't check if 8bit HT */ | ||
328 | if (dd->ipath_flags & IPATH_8BIT_IN_HT0) | ||
329 | crcbits &= ~infinipath_hwe_htclnkabyte1crcerr; | ||
330 | /* don't check if 8bit HT */ | ||
331 | if (dd->ipath_flags & IPATH_8BIT_IN_HT1) | ||
332 | crcbits &= ~infinipath_hwe_htclnkbbyte1crcerr; | ||
333 | /* | ||
334 | * we'll want to ignore link errors on link that is | ||
335 | * not in use, if any. For now, complain about both | ||
336 | */ | ||
337 | if (crcbits) { | ||
338 | u16 ctrl0, ctrl1; | ||
339 | snprintf(bitsmsg, sizeof bitsmsg, | ||
340 | "[HT%s lane %s CRC (%llx); ignore till reload]", | ||
341 | !(crcbits & _IPATH_HTLINK1_CRCBITS) ? | ||
342 | "0 (A)" : (!(crcbits & _IPATH_HTLINK0_CRCBITS) | ||
343 | ? "1 (B)" : "0+1 (A+B)"), | ||
344 | !(crcbits & _IPATH_HTLANE1_CRCBITS) ? "0" | ||
345 | : (!(crcbits & _IPATH_HTLANE0_CRCBITS) ? "1" : | ||
346 | "0+1"), (unsigned long long) crcbits); | ||
347 | strlcat(msg, bitsmsg, msgl); | ||
348 | |||
349 | /* | ||
350 | * print extra info for debugging. slave/primary | ||
351 | * config word 4, 8 (link control 0, 1) | ||
352 | */ | ||
353 | |||
354 | if (pci_read_config_word(dd->pcidev, | ||
355 | dd->ipath_ht_slave_off + 0x4, | ||
356 | &ctrl0)) | ||
357 | dev_info(&dd->pcidev->dev, "Couldn't read " | ||
358 | "linkctrl0 of slave/primary " | ||
359 | "config block\n"); | ||
360 | else if (!(ctrl0 & 1 << 6)) | ||
361 | /* not if EOC bit set */ | ||
362 | ipath_dbg("HT linkctrl0 0x%x%s%s\n", ctrl0, | ||
363 | ((ctrl0 >> 8) & 7) ? " CRC" : "", | ||
364 | ((ctrl0 >> 4) & 1) ? "linkfail" : | ||
365 | ""); | ||
366 | if (pci_read_config_word(dd->pcidev, | ||
367 | dd->ipath_ht_slave_off + 0x8, | ||
368 | &ctrl1)) | ||
369 | dev_info(&dd->pcidev->dev, "Couldn't read " | ||
370 | "linkctrl1 of slave/primary " | ||
371 | "config block\n"); | ||
372 | else if (!(ctrl1 & 1 << 6)) | ||
373 | /* not if EOC bit set */ | ||
374 | ipath_dbg("HT linkctrl1 0x%x%s%s\n", ctrl1, | ||
375 | ((ctrl1 >> 8) & 7) ? " CRC" : "", | ||
376 | ((ctrl1 >> 4) & 1) ? "linkfail" : | ||
377 | ""); | ||
378 | |||
379 | /* disable until driver reloaded */ | ||
380 | dd->ipath_hwerrmask &= ~crcbits; | ||
381 | ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask, | ||
382 | dd->ipath_hwerrmask); | ||
383 | ipath_dbg("HT crc errs: %s\n", msg); | ||
384 | } else | ||
385 | ipath_dbg("ignoring HT crc errors 0x%llx, " | ||
386 | "not in use\n", (unsigned long long) | ||
387 | (hwerrs & (_IPATH_HTLINK0_CRCBITS | | ||
388 | _IPATH_HTLINK1_CRCBITS))); | ||
389 | } | ||
390 | |||
391 | /** | ||
392 | * ipath_ht_handle_hwerrors - display hardware errors | ||
393 | * @dd: the infinipath device | ||
394 | * @msg: the output buffer | ||
395 | * @msgl: the size of the output buffer | ||
396 | * | ||
397 | * Use same msg buffer as regular errors to avoid | ||
398 | * excessive stack use. Most hardware errors are catastrophic, but for | ||
399 | * right now, we'll print them and continue. | ||
400 | * We reuse the same message buffer as ipath_handle_errors() to avoid | ||
401 | * excessive stack usage. | ||
402 | */ | ||
403 | static void ipath_ht_handle_hwerrors(struct ipath_devdata *dd, char *msg, | ||
404 | size_t msgl) | ||
405 | { | ||
406 | ipath_err_t hwerrs; | ||
407 | u32 bits, ctrl; | ||
408 | int isfatal = 0; | ||
409 | char bitsmsg[64]; | ||
410 | |||
411 | hwerrs = ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwerrstatus); | ||
412 | |||
413 | if (!hwerrs) { | ||
414 | ipath_cdbg(VERBOSE, "Called but no hardware errors set\n"); | ||
415 | /* | ||
416 | * better than printing cofusing messages | ||
417 | * This seems to be related to clearing the crc error, or | ||
418 | * the pll error during init. | ||
419 | */ | ||
420 | goto bail; | ||
421 | } else if (hwerrs == -1LL) { | ||
422 | ipath_dev_err(dd, "Read of hardware error status failed " | ||
423 | "(all bits set); ignoring\n"); | ||
424 | goto bail; | ||
425 | } | ||
426 | ipath_stats.sps_hwerrs++; | ||
427 | |||
428 | /* Always clear the error status register, except MEMBISTFAIL, | ||
429 | * regardless of whether we continue or stop using the chip. | ||
430 | * We want that set so we know it failed, even across driver reload. | ||
431 | * We'll still ignore it in the hwerrmask. We do this partly for | ||
432 | * diagnostics, but also for support */ | ||
433 | ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear, | ||
434 | hwerrs&~INFINIPATH_HWE_MEMBISTFAILED); | ||
435 | |||
436 | hwerrs &= dd->ipath_hwerrmask; | ||
437 | |||
438 | /* | ||
439 | * make sure we get this much out, unless told to be quiet, | ||
440 | * or it's occurred within the last 5 seconds | ||
441 | */ | ||
442 | if ((hwerrs & ~dd->ipath_lasthwerror) || | ||
443 | (ipath_debug & __IPATH_VERBDBG)) | ||
444 | dev_info(&dd->pcidev->dev, "Hardware error: hwerr=0x%llx " | ||
445 | "(cleared)\n", (unsigned long long) hwerrs); | ||
446 | dd->ipath_lasthwerror |= hwerrs; | ||
447 | |||
448 | if (hwerrs & ~infinipath_hwe_bitsextant) | ||
449 | ipath_dev_err(dd, "hwerror interrupt with unknown errors " | ||
450 | "%llx set\n", (unsigned long long) | ||
451 | (hwerrs & ~infinipath_hwe_bitsextant)); | ||
452 | |||
453 | ctrl = ipath_read_kreg32(dd, dd->ipath_kregs->kr_control); | ||
454 | if (ctrl & INFINIPATH_C_FREEZEMODE) { | ||
455 | if (hwerrs) { | ||
456 | /* | ||
457 | * if any set that we aren't ignoring; only | ||
458 | * make the complaint once, in case it's stuck | ||
459 | * or recurring, and we get here multiple | ||
460 | * times. | ||
461 | */ | ||
462 | if (dd->ipath_flags & IPATH_INITTED) { | ||
463 | ipath_dev_err(dd, "Fatal Error (freeze " | ||
464 | "mode), no longer usable\n"); | ||
465 | isfatal = 1; | ||
466 | } | ||
467 | *dd->ipath_statusp &= ~IPATH_STATUS_IB_READY; | ||
468 | /* mark as having had error */ | ||
469 | *dd->ipath_statusp |= IPATH_STATUS_HWERROR; | ||
470 | /* | ||
471 | * mark as not usable, at a minimum until driver | ||
472 | * is reloaded, probably until reboot, since no | ||
473 | * other reset is possible. | ||
474 | */ | ||
475 | dd->ipath_flags &= ~IPATH_INITTED; | ||
476 | } else { | ||
477 | ipath_dbg("Clearing freezemode on ignored hardware " | ||
478 | "error\n"); | ||
479 | ctrl &= ~INFINIPATH_C_FREEZEMODE; | ||
480 | ipath_write_kreg(dd, dd->ipath_kregs->kr_control, | ||
481 | ctrl); | ||
482 | } | ||
483 | } | ||
484 | |||
485 | *msg = '\0'; | ||
486 | |||
487 | /* | ||
488 | * may someday want to decode into which bits are which | ||
489 | * functional area for parity errors, etc. | ||
490 | */ | ||
491 | if (hwerrs & (infinipath_hwe_htcmemparityerr_mask | ||
492 | << INFINIPATH_HWE_HTCMEMPARITYERR_SHIFT)) { | ||
493 | bits = (u32) ((hwerrs >> | ||
494 | INFINIPATH_HWE_HTCMEMPARITYERR_SHIFT) & | ||
495 | INFINIPATH_HWE_HTCMEMPARITYERR_MASK); | ||
496 | snprintf(bitsmsg, sizeof bitsmsg, "[HTC Parity Errs %x] ", | ||
497 | bits); | ||
498 | strlcat(msg, bitsmsg, msgl); | ||
499 | } | ||
500 | if (hwerrs & (INFINIPATH_HWE_RXEMEMPARITYERR_MASK | ||
501 | << INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT)) { | ||
502 | bits = (u32) ((hwerrs >> | ||
503 | INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT) & | ||
504 | INFINIPATH_HWE_RXEMEMPARITYERR_MASK); | ||
505 | snprintf(bitsmsg, sizeof bitsmsg, "[RXE Parity Errs %x] ", | ||
506 | bits); | ||
507 | strlcat(msg, bitsmsg, msgl); | ||
508 | } | ||
509 | if (hwerrs & (INFINIPATH_HWE_TXEMEMPARITYERR_MASK | ||
510 | << INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT)) { | ||
511 | bits = (u32) ((hwerrs >> | ||
512 | INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT) & | ||
513 | INFINIPATH_HWE_TXEMEMPARITYERR_MASK); | ||
514 | snprintf(bitsmsg, sizeof bitsmsg, "[TXE Parity Errs %x] ", | ||
515 | bits); | ||
516 | strlcat(msg, bitsmsg, msgl); | ||
517 | } | ||
518 | if (hwerrs & INFINIPATH_HWE_IBCBUSTOSPCPARITYERR) | ||
519 | strlcat(msg, "[IB2IPATH Parity]", msgl); | ||
520 | if (hwerrs & INFINIPATH_HWE_IBCBUSFRSPCPARITYERR) | ||
521 | strlcat(msg, "[IPATH2IB Parity]", msgl); | ||
522 | if (hwerrs & INFINIPATH_HWE_HTCBUSIREQPARITYERR) | ||
523 | strlcat(msg, "[HTC Ireq Parity]", msgl); | ||
524 | if (hwerrs & INFINIPATH_HWE_HTCBUSTREQPARITYERR) | ||
525 | strlcat(msg, "[HTC Treq Parity]", msgl); | ||
526 | if (hwerrs & INFINIPATH_HWE_HTCBUSTRESPPARITYERR) | ||
527 | strlcat(msg, "[HTC Tresp Parity]", msgl); | ||
528 | |||
529 | if (hwerrs & (_IPATH_HTLINK0_CRCBITS | _IPATH_HTLINK1_CRCBITS)) | ||
530 | hwerr_crcbits(dd, hwerrs, msg, msgl); | ||
531 | |||
532 | if (hwerrs & INFINIPATH_HWE_HTCMISCERR5) | ||
533 | strlcat(msg, "[HT core Misc5]", msgl); | ||
534 | if (hwerrs & INFINIPATH_HWE_HTCMISCERR6) | ||
535 | strlcat(msg, "[HT core Misc6]", msgl); | ||
536 | if (hwerrs & INFINIPATH_HWE_HTCMISCERR7) | ||
537 | strlcat(msg, "[HT core Misc7]", msgl); | ||
538 | if (hwerrs & INFINIPATH_HWE_MEMBISTFAILED) { | ||
539 | strlcat(msg, "[Memory BIST test failed, HT-400 unusable]", | ||
540 | msgl); | ||
541 | /* ignore from now on, so disable until driver reloaded */ | ||
542 | dd->ipath_hwerrmask &= ~INFINIPATH_HWE_MEMBISTFAILED; | ||
543 | ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask, | ||
544 | dd->ipath_hwerrmask); | ||
545 | } | ||
546 | #define _IPATH_PLL_FAIL (INFINIPATH_HWE_COREPLL_FBSLIP | \ | ||
547 | INFINIPATH_HWE_COREPLL_RFSLIP | \ | ||
548 | INFINIPATH_HWE_HTBPLL_FBSLIP | \ | ||
549 | INFINIPATH_HWE_HTBPLL_RFSLIP | \ | ||
550 | INFINIPATH_HWE_HTAPLL_FBSLIP | \ | ||
551 | INFINIPATH_HWE_HTAPLL_RFSLIP) | ||
552 | |||
553 | if (hwerrs & _IPATH_PLL_FAIL) { | ||
554 | snprintf(bitsmsg, sizeof bitsmsg, | ||
555 | "[PLL failed (%llx), HT-400 unusable]", | ||
556 | (unsigned long long) (hwerrs & _IPATH_PLL_FAIL)); | ||
557 | strlcat(msg, bitsmsg, msgl); | ||
558 | /* ignore from now on, so disable until driver reloaded */ | ||
559 | dd->ipath_hwerrmask &= ~(hwerrs & _IPATH_PLL_FAIL); | ||
560 | ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask, | ||
561 | dd->ipath_hwerrmask); | ||
562 | } | ||
563 | |||
564 | if (hwerrs & INFINIPATH_HWE_SERDESPLLFAILED) { | ||
565 | /* | ||
566 | * If it occurs, it is left masked since the eternal | ||
567 | * interface is unused | ||
568 | */ | ||
569 | dd->ipath_hwerrmask &= ~INFINIPATH_HWE_SERDESPLLFAILED; | ||
570 | ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask, | ||
571 | dd->ipath_hwerrmask); | ||
572 | } | ||
573 | |||
574 | if (hwerrs & INFINIPATH_HWE_RXDSYNCMEMPARITYERR) | ||
575 | strlcat(msg, "[Rx Dsync]", msgl); | ||
576 | if (hwerrs & INFINIPATH_HWE_SERDESPLLFAILED) | ||
577 | strlcat(msg, "[SerDes PLL]", msgl); | ||
578 | |||
579 | ipath_dev_err(dd, "%s hardware error\n", msg); | ||
580 | if (isfatal && !ipath_diag_inuse && dd->ipath_freezemsg) | ||
581 | /* | ||
582 | * for status file; if no trailing brace is copied, | ||
583 | * we'll know it was truncated. | ||
584 | */ | ||
585 | snprintf(dd->ipath_freezemsg, | ||
586 | dd->ipath_freezelen, "{%s}", msg); | ||
587 | |||
588 | bail:; | ||
589 | } | ||
590 | |||
591 | /** | ||
592 | * ipath_ht_boardname - fill in the board name | ||
593 | * @dd: the infinipath device | ||
594 | * @name: the output buffer | ||
595 | * @namelen: the size of the output buffer | ||
596 | * | ||
597 | * fill in the board name, based on the board revision register | ||
598 | */ | ||
599 | static int ipath_ht_boardname(struct ipath_devdata *dd, char *name, | ||
600 | size_t namelen) | ||
601 | { | ||
602 | char *n = NULL; | ||
603 | u8 boardrev = dd->ipath_boardrev; | ||
604 | int ret; | ||
605 | |||
606 | switch (boardrev) { | ||
607 | case 4: /* Ponderosa is one of the bringup boards */ | ||
608 | n = "Ponderosa"; | ||
609 | break; | ||
610 | case 5: /* HT-460 original production board */ | ||
611 | n = "InfiniPath_HT-460"; | ||
612 | break; | ||
613 | case 6: | ||
614 | n = "OEM_Board_3"; | ||
615 | break; | ||
616 | case 7: | ||
617 | /* HT-460 small form factor production board */ | ||
618 | n = "InfiniPath_HT-465"; | ||
619 | break; | ||
620 | case 8: | ||
621 | n = "LS/X-1"; | ||
622 | break; | ||
623 | case 9: /* Comstock bringup test board */ | ||
624 | n = "Comstock"; | ||
625 | break; | ||
626 | case 10: | ||
627 | n = "OEM_Board_2"; | ||
628 | break; | ||
629 | case 11: | ||
630 | n = "InfiniPath_HT-470"; | ||
631 | break; | ||
632 | case 12: | ||
633 | n = "OEM_Board_4"; | ||
634 | break; | ||
635 | default: /* don't know, just print the number */ | ||
636 | ipath_dev_err(dd, "Don't yet know about board " | ||
637 | "with ID %u\n", boardrev); | ||
638 | snprintf(name, namelen, "Unknown_InfiniPath_HT-4xx_%u", | ||
639 | boardrev); | ||
640 | break; | ||
641 | } | ||
642 | if (n) | ||
643 | snprintf(name, namelen, "%s", n); | ||
644 | |||
645 | if (dd->ipath_majrev != 3 || dd->ipath_minrev != 2) { | ||
646 | /* | ||
647 | * This version of the driver only supports the HT-400 | ||
648 | * Rev 3.2 | ||
649 | */ | ||
650 | ipath_dev_err(dd, | ||
651 | "Unsupported HT-400 revision %u.%u!\n", | ||
652 | dd->ipath_majrev, dd->ipath_minrev); | ||
653 | ret = 1; | ||
654 | goto bail; | ||
655 | } | ||
656 | /* | ||
657 | * pkt/word counters are 32 bit, and therefore wrap fast enough | ||
658 | * that we snapshot them from a timer, and maintain 64 bit shadow | ||
659 | * copies | ||
660 | */ | ||
661 | dd->ipath_flags |= IPATH_32BITCOUNTERS; | ||
662 | if (dd->ipath_htspeed != 800) | ||
663 | ipath_dev_err(dd, | ||
664 | "Incorrectly configured for HT @ %uMHz\n", | ||
665 | dd->ipath_htspeed); | ||
666 | if (dd->ipath_boardrev == 7 || dd->ipath_boardrev == 11 || | ||
667 | dd->ipath_boardrev == 6) | ||
668 | dd->ipath_flags |= IPATH_GPIO_INTR; | ||
669 | else | ||
670 | dd->ipath_flags |= IPATH_POLL_RX_INTR; | ||
671 | if (dd->ipath_boardrev == 8) { /* LS/X-1 */ | ||
672 | u64 val; | ||
673 | val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extstatus); | ||
674 | if (val & INFINIPATH_EXTS_SERDESSEL) { | ||
675 | /* | ||
676 | * hardware disabled | ||
677 | * | ||
678 | * This means that the chip is hardware disabled, | ||
679 | * and will not be able to bring up the link, | ||
680 | * in any case. We special case this and abort | ||
681 | * early, to avoid later messages. We also set | ||
682 | * the DISABLED status bit | ||
683 | */ | ||
684 | ipath_dbg("Unit %u is hardware-disabled\n", | ||
685 | dd->ipath_unit); | ||
686 | *dd->ipath_statusp |= IPATH_STATUS_DISABLED; | ||
687 | /* this value is handled differently */ | ||
688 | ret = 2; | ||
689 | goto bail; | ||
690 | } | ||
691 | } | ||
692 | ret = 0; | ||
693 | |||
694 | bail: | ||
695 | return ret; | ||
696 | } | ||
697 | |||
698 | static void ipath_check_htlink(struct ipath_devdata *dd) | ||
699 | { | ||
700 | u8 linkerr, link_off, i; | ||
701 | |||
702 | for (i = 0; i < 2; i++) { | ||
703 | link_off = dd->ipath_ht_slave_off + i * 4 + 0xd; | ||
704 | if (pci_read_config_byte(dd->pcidev, link_off, &linkerr)) | ||
705 | dev_info(&dd->pcidev->dev, "Couldn't read " | ||
706 | "linkerror%d of HT slave/primary block\n", | ||
707 | i); | ||
708 | else if (linkerr & 0xf0) { | ||
709 | ipath_cdbg(VERBOSE, "HT linkerr%d bits 0x%x set, " | ||
710 | "clearing\n", linkerr >> 4, i); | ||
711 | /* | ||
712 | * writing the linkerr bits that are set should | ||
713 | * clear them | ||
714 | */ | ||
715 | if (pci_write_config_byte(dd->pcidev, link_off, | ||
716 | linkerr)) | ||
717 | ipath_dbg("Failed write to clear HT " | ||
718 | "linkerror%d\n", i); | ||
719 | if (pci_read_config_byte(dd->pcidev, link_off, | ||
720 | &linkerr)) | ||
721 | dev_info(&dd->pcidev->dev, | ||
722 | "Couldn't reread linkerror%d of " | ||
723 | "HT slave/primary block\n", i); | ||
724 | else if (linkerr & 0xf0) | ||
725 | dev_info(&dd->pcidev->dev, | ||
726 | "HT linkerror%d bits 0x%x " | ||
727 | "couldn't be cleared\n", | ||
728 | i, linkerr >> 4); | ||
729 | } | ||
730 | } | ||
731 | } | ||
732 | |||
733 | static int ipath_setup_ht_reset(struct ipath_devdata *dd) | ||
734 | { | ||
735 | ipath_dbg("No reset possible for HT-400\n"); | ||
736 | return 0; | ||
737 | } | ||
738 | |||
739 | #define HT_CAPABILITY_ID 0x08 /* HT capabilities not defined in kernel */ | ||
740 | #define HT_INTR_DISC_CONFIG 0x80 /* HT interrupt and discovery cap */ | ||
741 | #define HT_INTR_REG_INDEX 2 /* intconfig requires indirect accesses */ | ||
742 | |||
743 | /* | ||
744 | * Bits 13-15 of command==0 is slave/primary block. Clear any HT CRC | ||
745 | * errors. We only bother to do this at load time, because it's OK if | ||
746 | * it happened before we were loaded (first time after boot/reset), | ||
747 | * but any time after that, it's fatal anyway. Also need to not check | ||
748 | * for for upper byte errors if we are in 8 bit mode, so figure out | ||
749 | * our width. For now, at least, also complain if it's 8 bit. | ||
750 | */ | ||
751 | static void slave_or_pri_blk(struct ipath_devdata *dd, struct pci_dev *pdev, | ||
752 | int pos, u8 cap_type) | ||
753 | { | ||
754 | u8 linkwidth = 0, linkerr, link_a_b_off, link_off; | ||
755 | u16 linkctrl = 0; | ||
756 | int i; | ||
757 | |||
758 | dd->ipath_ht_slave_off = pos; | ||
759 | /* command word, master_host bit */ | ||
760 | /* master host || slave */ | ||
761 | if ((cap_type >> 2) & 1) | ||
762 | link_a_b_off = 4; | ||
763 | else | ||
764 | link_a_b_off = 0; | ||
765 | ipath_cdbg(VERBOSE, "HT%u (Link %c) connected to processor\n", | ||
766 | link_a_b_off ? 1 : 0, | ||
767 | link_a_b_off ? 'B' : 'A'); | ||
768 | |||
769 | link_a_b_off += pos; | ||
770 | |||
771 | /* | ||
772 | * check both link control registers; clear both HT CRC sets if | ||
773 | * necessary. | ||
774 | */ | ||
775 | for (i = 0; i < 2; i++) { | ||
776 | link_off = pos + i * 4 + 0x4; | ||
777 | if (pci_read_config_word(pdev, link_off, &linkctrl)) | ||
778 | ipath_dev_err(dd, "Couldn't read HT link control%d " | ||
779 | "register\n", i); | ||
780 | else if (linkctrl & (0xf << 8)) { | ||
781 | ipath_cdbg(VERBOSE, "Clear linkctrl%d CRC Error " | ||
782 | "bits %x\n", i, linkctrl & (0xf << 8)); | ||
783 | /* | ||
784 | * now write them back to clear the error. | ||
785 | */ | ||
786 | pci_write_config_byte(pdev, link_off, | ||
787 | linkctrl & (0xf << 8)); | ||
788 | } | ||
789 | } | ||
790 | |||
791 | /* | ||
792 | * As with HT CRC bits, same for protocol errors that might occur | ||
793 | * during boot. | ||
794 | */ | ||
795 | for (i = 0; i < 2; i++) { | ||
796 | link_off = pos + i * 4 + 0xd; | ||
797 | if (pci_read_config_byte(pdev, link_off, &linkerr)) | ||
798 | dev_info(&pdev->dev, "Couldn't read linkerror%d " | ||
799 | "of HT slave/primary block\n", i); | ||
800 | else if (linkerr & 0xf0) { | ||
801 | ipath_cdbg(VERBOSE, "HT linkerr%d bits 0x%x set, " | ||
802 | "clearing\n", linkerr >> 4, i); | ||
803 | /* | ||
804 | * writing the linkerr bits that are set will clear | ||
805 | * them | ||
806 | */ | ||
807 | if (pci_write_config_byte | ||
808 | (pdev, link_off, linkerr)) | ||
809 | ipath_dbg("Failed write to clear HT " | ||
810 | "linkerror%d\n", i); | ||
811 | if (pci_read_config_byte(pdev, link_off, &linkerr)) | ||
812 | dev_info(&pdev->dev, "Couldn't reread " | ||
813 | "linkerror%d of HT slave/primary " | ||
814 | "block\n", i); | ||
815 | else if (linkerr & 0xf0) | ||
816 | dev_info(&pdev->dev, "HT linkerror%d bits " | ||
817 | "0x%x couldn't be cleared\n", | ||
818 | i, linkerr >> 4); | ||
819 | } | ||
820 | } | ||
821 | |||
822 | /* | ||
823 | * this is just for our link to the host, not devices connected | ||
824 | * through tunnel. | ||
825 | */ | ||
826 | |||
827 | if (pci_read_config_byte(pdev, link_a_b_off + 7, &linkwidth)) | ||
828 | ipath_dev_err(dd, "Couldn't read HT link width " | ||
829 | "config register\n"); | ||
830 | else { | ||
831 | u32 width; | ||
832 | switch (linkwidth & 7) { | ||
833 | case 5: | ||
834 | width = 4; | ||
835 | break; | ||
836 | case 4: | ||
837 | width = 2; | ||
838 | break; | ||
839 | case 3: | ||
840 | width = 32; | ||
841 | break; | ||
842 | case 1: | ||
843 | width = 16; | ||
844 | break; | ||
845 | case 0: | ||
846 | default: /* if wrong, assume 8 bit */ | ||
847 | width = 8; | ||
848 | break; | ||
849 | } | ||
850 | |||
851 | dd->ipath_htwidth = width; | ||
852 | |||
853 | if (linkwidth != 0x11) { | ||
854 | ipath_dev_err(dd, "Not configured for 16 bit HT " | ||
855 | "(%x)\n", linkwidth); | ||
856 | if (!(linkwidth & 0xf)) { | ||
857 | ipath_dbg("Will ignore HT lane1 errors\n"); | ||
858 | dd->ipath_flags |= IPATH_8BIT_IN_HT0; | ||
859 | } | ||
860 | } | ||
861 | } | ||
862 | |||
863 | /* | ||
864 | * this is just for our link to the host, not devices connected | ||
865 | * through tunnel. | ||
866 | */ | ||
867 | if (pci_read_config_byte(pdev, link_a_b_off + 0xd, &linkwidth)) | ||
868 | ipath_dev_err(dd, "Couldn't read HT link frequency " | ||
869 | "config register\n"); | ||
870 | else { | ||
871 | u32 speed; | ||
872 | switch (linkwidth & 0xf) { | ||
873 | case 6: | ||
874 | speed = 1000; | ||
875 | break; | ||
876 | case 5: | ||
877 | speed = 800; | ||
878 | break; | ||
879 | case 4: | ||
880 | speed = 600; | ||
881 | break; | ||
882 | case 3: | ||
883 | speed = 500; | ||
884 | break; | ||
885 | case 2: | ||
886 | speed = 400; | ||
887 | break; | ||
888 | case 1: | ||
889 | speed = 300; | ||
890 | break; | ||
891 | default: | ||
892 | /* | ||
893 | * assume reserved and vendor-specific are 200... | ||
894 | */ | ||
895 | case 0: | ||
896 | speed = 200; | ||
897 | break; | ||
898 | } | ||
899 | dd->ipath_htspeed = speed; | ||
900 | } | ||
901 | } | ||
902 | |||
903 | static int set_int_handler(struct ipath_devdata *dd, struct pci_dev *pdev, | ||
904 | int pos) | ||
905 | { | ||
906 | u32 int_handler_addr_lower; | ||
907 | u32 int_handler_addr_upper; | ||
908 | u64 ihandler; | ||
909 | u32 intvec; | ||
910 | |||
911 | /* use indirection register to get the intr handler */ | ||
912 | pci_write_config_byte(pdev, pos + HT_INTR_REG_INDEX, 0x10); | ||
913 | pci_read_config_dword(pdev, pos + 4, &int_handler_addr_lower); | ||
914 | pci_write_config_byte(pdev, pos + HT_INTR_REG_INDEX, 0x11); | ||
915 | pci_read_config_dword(pdev, pos + 4, &int_handler_addr_upper); | ||
916 | |||
917 | ihandler = (u64) int_handler_addr_lower | | ||
918 | ((u64) int_handler_addr_upper << 32); | ||
919 | |||
920 | /* | ||
921 | * kernels with CONFIG_PCI_MSI set the vector in the irq field of | ||
922 | * struct pci_device, so we use that to program the HT-400 internal | ||
923 | * interrupt register (not config space) with that value. The BIOS | ||
924 | * must still have done the basic MSI setup. | ||
925 | */ | ||
926 | intvec = pdev->irq; | ||
927 | /* | ||
928 | * clear any vector bits there; normally not set but we'll overload | ||
929 | * this for some debug purposes (setting the HTC debug register | ||
930 | * value from software, rather than GPIOs), so it might be set on a | ||
931 | * driver reload. | ||
932 | */ | ||
933 | ihandler &= ~0xff0000; | ||
934 | /* x86 vector goes in intrinfo[23:16] */ | ||
935 | ihandler |= intvec << 16; | ||
936 | ipath_cdbg(VERBOSE, "ihandler lower %x, upper %x, intvec %x, " | ||
937 | "interruptconfig %llx\n", int_handler_addr_lower, | ||
938 | int_handler_addr_upper, intvec, | ||
939 | (unsigned long long) ihandler); | ||
940 | |||
941 | /* can't program yet, so save for interrupt setup */ | ||
942 | dd->ipath_intconfig = ihandler; | ||
943 | /* keep going, so we find link control stuff also */ | ||
944 | |||
945 | return ihandler != 0; | ||
946 | } | ||
947 | |||
948 | /** | ||
949 | * ipath_setup_ht_config - setup the interruptconfig register | ||
950 | * @dd: the infinipath device | ||
951 | * @pdev: the PCI device | ||
952 | * | ||
953 | * setup the interruptconfig register from the HT config info. | ||
954 | * Also clear CRC errors in HT linkcontrol, if necessary. | ||
955 | * This is done only for the real hardware. It is done before | ||
956 | * chip address space is initted, so can't touch infinipath registers | ||
957 | */ | ||
958 | static int ipath_setup_ht_config(struct ipath_devdata *dd, | ||
959 | struct pci_dev *pdev) | ||
960 | { | ||
961 | int pos, ret = 0; | ||
962 | int ihandler = 0; | ||
963 | |||
964 | /* | ||
965 | * Read the capability info to find the interrupt info, and also | ||
966 | * handle clearing CRC errors in linkctrl register if necessary. We | ||
967 | * do this early, before we ever enable errors or hardware errors, | ||
968 | * mostly to avoid causing the chip to enter freeze mode. | ||
969 | */ | ||
970 | pos = pci_find_capability(pdev, HT_CAPABILITY_ID); | ||
971 | if (!pos) { | ||
972 | ipath_dev_err(dd, "Couldn't find HyperTransport " | ||
973 | "capability; no interrupts\n"); | ||
974 | ret = -ENODEV; | ||
975 | goto bail; | ||
976 | } | ||
977 | do { | ||
978 | u8 cap_type; | ||
979 | |||
980 | /* the HT capability type byte is 3 bytes after the | ||
981 | * capability byte. | ||
982 | */ | ||
983 | if (pci_read_config_byte(pdev, pos + 3, &cap_type)) { | ||
984 | dev_info(&pdev->dev, "Couldn't read config " | ||
985 | "command @ %d\n", pos); | ||
986 | continue; | ||
987 | } | ||
988 | if (!(cap_type & 0xE0)) | ||
989 | slave_or_pri_blk(dd, pdev, pos, cap_type); | ||
990 | else if (cap_type == HT_INTR_DISC_CONFIG) | ||
991 | ihandler = set_int_handler(dd, pdev, pos); | ||
992 | } while ((pos = pci_find_next_capability(pdev, pos, | ||
993 | HT_CAPABILITY_ID))); | ||
994 | |||
995 | if (!ihandler) { | ||
996 | ipath_dev_err(dd, "Couldn't find interrupt handler in " | ||
997 | "config space\n"); | ||
998 | ret = -ENODEV; | ||
999 | } | ||
1000 | |||
1001 | bail: | ||
1002 | return ret; | ||
1003 | } | ||
1004 | |||
1005 | /** | ||
1006 | * ipath_setup_ht_cleanup - clean up any per-chip chip-specific stuff | ||
1007 | * @dd: the infinipath device | ||
1008 | * | ||
1009 | * Called during driver unload. | ||
1010 | * This is currently a nop for the HT-400, not for all chips | ||
1011 | */ | ||
1012 | static void ipath_setup_ht_cleanup(struct ipath_devdata *dd) | ||
1013 | { | ||
1014 | } | ||
1015 | |||
1016 | /** | ||
1017 | * ipath_setup_ht_setextled - set the state of the two external LEDs | ||
1018 | * @dd: the infinipath device | ||
1019 | * @lst: the L state | ||
1020 | * @ltst: the LT state | ||
1021 | * | ||
1022 | * Set the state of the two external LEDs, to indicate physical and | ||
1023 | * logical state of IB link. For this chip (at least with recommended | ||
1024 | * board pinouts), LED1 is Green (physical state), and LED2 is Yellow | ||
1025 | * (logical state) | ||
1026 | * | ||
1027 | * Note: We try to match the Mellanox HCA LED behavior as best | ||
1028 | * we can. Green indicates physical link state is OK (something is | ||
1029 | * plugged in, and we can train). | ||
1030 | * Amber indicates the link is logically up (ACTIVE). | ||
1031 | * Mellanox further blinks the amber LED to indicate data packet | ||
1032 | * activity, but we have no hardware support for that, so it would | ||
1033 | * require waking up every 10-20 msecs and checking the counters | ||
1034 | * on the chip, and then turning the LED off if appropriate. That's | ||
1035 | * visible overhead, so not something we will do. | ||
1036 | * | ||
1037 | */ | ||
1038 | static void ipath_setup_ht_setextled(struct ipath_devdata *dd, | ||
1039 | u64 lst, u64 ltst) | ||
1040 | { | ||
1041 | u64 extctl; | ||
1042 | |||
1043 | /* the diags use the LED to indicate diag info, so we leave | ||
1044 | * the external LED alone when the diags are running */ | ||
1045 | if (ipath_diag_inuse) | ||
1046 | return; | ||
1047 | |||
1048 | /* | ||
1049 | * start by setting both LED control bits to off, then turn | ||
1050 | * on the appropriate bit(s). | ||
1051 | */ | ||
1052 | if (dd->ipath_boardrev == 8) { /* LS/X-1 uses different pins */ | ||
1053 | /* | ||
1054 | * major difference is that INFINIPATH_EXTC_LEDGBLERR_OFF | ||
1055 | * is inverted, because it is normally used to indicate | ||
1056 | * a hardware fault at reset, if there were errors | ||
1057 | */ | ||
1058 | extctl = (dd->ipath_extctrl & ~INFINIPATH_EXTC_LEDGBLOK_ON) | ||
1059 | | INFINIPATH_EXTC_LEDGBLERR_OFF; | ||
1060 | if (ltst == INFINIPATH_IBCS_LT_STATE_LINKUP) | ||
1061 | extctl &= ~INFINIPATH_EXTC_LEDGBLERR_OFF; | ||
1062 | if (lst == INFINIPATH_IBCS_L_STATE_ACTIVE) | ||
1063 | extctl |= INFINIPATH_EXTC_LEDGBLOK_ON; | ||
1064 | } | ||
1065 | else { | ||
1066 | extctl = dd->ipath_extctrl & | ||
1067 | ~(INFINIPATH_EXTC_LED1PRIPORT_ON | | ||
1068 | INFINIPATH_EXTC_LED2PRIPORT_ON); | ||
1069 | if (ltst == INFINIPATH_IBCS_LT_STATE_LINKUP) | ||
1070 | extctl |= INFINIPATH_EXTC_LED1PRIPORT_ON; | ||
1071 | if (lst == INFINIPATH_IBCS_L_STATE_ACTIVE) | ||
1072 | extctl |= INFINIPATH_EXTC_LED2PRIPORT_ON; | ||
1073 | } | ||
1074 | dd->ipath_extctrl = extctl; | ||
1075 | ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, extctl); | ||
1076 | } | ||
1077 | |||
1078 | static void ipath_init_ht_variables(void) | ||
1079 | { | ||
1080 | ipath_gpio_sda_num = _IPATH_GPIO_SDA_NUM; | ||
1081 | ipath_gpio_scl_num = _IPATH_GPIO_SCL_NUM; | ||
1082 | ipath_gpio_sda = IPATH_GPIO_SDA; | ||
1083 | ipath_gpio_scl = IPATH_GPIO_SCL; | ||
1084 | |||
1085 | infinipath_i_bitsextant = | ||
1086 | (INFINIPATH_I_RCVURG_MASK << INFINIPATH_I_RCVURG_SHIFT) | | ||
1087 | (INFINIPATH_I_RCVAVAIL_MASK << | ||
1088 | INFINIPATH_I_RCVAVAIL_SHIFT) | | ||
1089 | INFINIPATH_I_ERROR | INFINIPATH_I_SPIOSENT | | ||
1090 | INFINIPATH_I_SPIOBUFAVAIL | INFINIPATH_I_GPIO; | ||
1091 | |||
1092 | infinipath_e_bitsextant = | ||
1093 | INFINIPATH_E_RFORMATERR | INFINIPATH_E_RVCRC | | ||
1094 | INFINIPATH_E_RICRC | INFINIPATH_E_RMINPKTLEN | | ||
1095 | INFINIPATH_E_RMAXPKTLEN | INFINIPATH_E_RLONGPKTLEN | | ||
1096 | INFINIPATH_E_RSHORTPKTLEN | INFINIPATH_E_RUNEXPCHAR | | ||
1097 | INFINIPATH_E_RUNSUPVL | INFINIPATH_E_REBP | | ||
1098 | INFINIPATH_E_RIBFLOW | INFINIPATH_E_RBADVERSION | | ||
1099 | INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL | | ||
1100 | INFINIPATH_E_RBADTID | INFINIPATH_E_RHDRLEN | | ||
1101 | INFINIPATH_E_RHDR | INFINIPATH_E_RIBLOSTLINK | | ||
1102 | INFINIPATH_E_SMINPKTLEN | INFINIPATH_E_SMAXPKTLEN | | ||
1103 | INFINIPATH_E_SUNDERRUN | INFINIPATH_E_SPKTLEN | | ||
1104 | INFINIPATH_E_SDROPPEDSMPPKT | INFINIPATH_E_SDROPPEDDATAPKT | | ||
1105 | INFINIPATH_E_SPIOARMLAUNCH | INFINIPATH_E_SUNEXPERRPKTNUM | | ||
1106 | INFINIPATH_E_SUNSUPVL | INFINIPATH_E_IBSTATUSCHANGED | | ||
1107 | INFINIPATH_E_INVALIDADDR | INFINIPATH_E_RESET | | ||
1108 | INFINIPATH_E_HARDWARE; | ||
1109 | |||
1110 | infinipath_hwe_bitsextant = | ||
1111 | (INFINIPATH_HWE_HTCMEMPARITYERR_MASK << | ||
1112 | INFINIPATH_HWE_HTCMEMPARITYERR_SHIFT) | | ||
1113 | (INFINIPATH_HWE_TXEMEMPARITYERR_MASK << | ||
1114 | INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT) | | ||
1115 | (INFINIPATH_HWE_RXEMEMPARITYERR_MASK << | ||
1116 | INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT) | | ||
1117 | INFINIPATH_HWE_HTCLNKABYTE0CRCERR | | ||
1118 | INFINIPATH_HWE_HTCLNKABYTE1CRCERR | | ||
1119 | INFINIPATH_HWE_HTCLNKBBYTE0CRCERR | | ||
1120 | INFINIPATH_HWE_HTCLNKBBYTE1CRCERR | | ||
1121 | INFINIPATH_HWE_HTCMISCERR4 | | ||
1122 | INFINIPATH_HWE_HTCMISCERR5 | INFINIPATH_HWE_HTCMISCERR6 | | ||
1123 | INFINIPATH_HWE_HTCMISCERR7 | | ||
1124 | INFINIPATH_HWE_HTCBUSTREQPARITYERR | | ||
1125 | INFINIPATH_HWE_HTCBUSTRESPPARITYERR | | ||
1126 | INFINIPATH_HWE_HTCBUSIREQPARITYERR | | ||
1127 | INFINIPATH_HWE_RXDSYNCMEMPARITYERR | | ||
1128 | INFINIPATH_HWE_MEMBISTFAILED | | ||
1129 | INFINIPATH_HWE_COREPLL_FBSLIP | | ||
1130 | INFINIPATH_HWE_COREPLL_RFSLIP | | ||
1131 | INFINIPATH_HWE_HTBPLL_FBSLIP | | ||
1132 | INFINIPATH_HWE_HTBPLL_RFSLIP | | ||
1133 | INFINIPATH_HWE_HTAPLL_FBSLIP | | ||
1134 | INFINIPATH_HWE_HTAPLL_RFSLIP | | ||
1135 | INFINIPATH_HWE_SERDESPLLFAILED | | ||
1136 | INFINIPATH_HWE_IBCBUSTOSPCPARITYERR | | ||
1137 | INFINIPATH_HWE_IBCBUSFRSPCPARITYERR; | ||
1138 | |||
1139 | infinipath_i_rcvavail_mask = INFINIPATH_I_RCVAVAIL_MASK; | ||
1140 | infinipath_i_rcvurg_mask = INFINIPATH_I_RCVURG_MASK; | ||
1141 | } | ||
1142 | |||
1143 | /** | ||
1144 | * ipath_ht_init_hwerrors - enable hardware errors | ||
1145 | * @dd: the infinipath device | ||
1146 | * | ||
1147 | * now that we have finished initializing everything that might reasonably | ||
1148 | * cause a hardware error, and cleared those errors bits as they occur, | ||
1149 | * we can enable hardware errors in the mask (potentially enabling | ||
1150 | * freeze mode), and enable hardware errors as errors (along with | ||
1151 | * everything else) in errormask | ||
1152 | */ | ||
1153 | static void ipath_ht_init_hwerrors(struct ipath_devdata *dd) | ||
1154 | { | ||
1155 | ipath_err_t val; | ||
1156 | u64 extsval; | ||
1157 | |||
1158 | extsval = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extstatus); | ||
1159 | |||
1160 | if (!(extsval & INFINIPATH_EXTS_MEMBIST_ENDTEST)) | ||
1161 | ipath_dev_err(dd, "MemBIST did not complete!\n"); | ||
1162 | |||
1163 | ipath_check_htlink(dd); | ||
1164 | |||
1165 | /* barring bugs, all hwerrors become interrupts, which can */ | ||
1166 | val = -1LL; | ||
1167 | /* don't look at crc lane1 if 8 bit */ | ||
1168 | if (dd->ipath_flags & IPATH_8BIT_IN_HT0) | ||
1169 | val &= ~infinipath_hwe_htclnkabyte1crcerr; | ||
1170 | /* don't look at crc lane1 if 8 bit */ | ||
1171 | if (dd->ipath_flags & IPATH_8BIT_IN_HT1) | ||
1172 | val &= ~infinipath_hwe_htclnkbbyte1crcerr; | ||
1173 | |||
1174 | /* | ||
1175 | * disable RXDSYNCMEMPARITY because external serdes is unused, | ||
1176 | * and therefore the logic will never be used or initialized, | ||
1177 | * and uninitialized state will normally result in this error | ||
1178 | * being asserted. Similarly for the external serdess pll | ||
1179 | * lock signal. | ||
1180 | */ | ||
1181 | val &= ~(INFINIPATH_HWE_SERDESPLLFAILED | | ||
1182 | INFINIPATH_HWE_RXDSYNCMEMPARITYERR); | ||
1183 | |||
1184 | /* | ||
1185 | * Disable MISCERR4 because of an inversion in the HT core | ||
1186 | * logic checking for errors that cause this bit to be set. | ||
1187 | * The errata can also cause the protocol error bit to be set | ||
1188 | * in the HT config space linkerror register(s). | ||
1189 | */ | ||
1190 | val &= ~INFINIPATH_HWE_HTCMISCERR4; | ||
1191 | |||
1192 | /* | ||
1193 | * PLL ignored because MDIO interface has a logic problem | ||
1194 | * for reads, on Comstock and Ponderosa. BRINGUP | ||
1195 | */ | ||
1196 | if (dd->ipath_boardrev == 4 || dd->ipath_boardrev == 9) | ||
1197 | val &= ~INFINIPATH_HWE_SERDESPLLFAILED; | ||
1198 | dd->ipath_hwerrmask = val; | ||
1199 | } | ||
1200 | |||
1201 | /** | ||
1202 | * ipath_ht_bringup_serdes - bring up the serdes | ||
1203 | * @dd: the infinipath device | ||
1204 | */ | ||
1205 | static int ipath_ht_bringup_serdes(struct ipath_devdata *dd) | ||
1206 | { | ||
1207 | u64 val, config1; | ||
1208 | int ret = 0, change = 0; | ||
1209 | |||
1210 | ipath_dbg("Trying to bringup serdes\n"); | ||
1211 | |||
1212 | if (ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwerrstatus) & | ||
1213 | INFINIPATH_HWE_SERDESPLLFAILED) | ||
1214 | { | ||
1215 | ipath_dbg("At start, serdes PLL failed bit set in " | ||
1216 | "hwerrstatus, clearing and continuing\n"); | ||
1217 | ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear, | ||
1218 | INFINIPATH_HWE_SERDESPLLFAILED); | ||
1219 | } | ||
1220 | |||
1221 | val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0); | ||
1222 | config1 = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig1); | ||
1223 | |||
1224 | ipath_cdbg(VERBOSE, "Initial serdes status is config0=%llx " | ||
1225 | "config1=%llx, sstatus=%llx xgxs %llx\n", | ||
1226 | (unsigned long long) val, (unsigned long long) config1, | ||
1227 | (unsigned long long) | ||
1228 | ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesstatus), | ||
1229 | (unsigned long long) | ||
1230 | ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig)); | ||
1231 | |||
1232 | /* force reset on */ | ||
1233 | val |= INFINIPATH_SERDC0_RESET_PLL | ||
1234 | /* | INFINIPATH_SERDC0_RESET_MASK */ | ||
1235 | ; | ||
1236 | ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0, val); | ||
1237 | udelay(15); /* need pll reset set at least for a bit */ | ||
1238 | |||
1239 | if (val & INFINIPATH_SERDC0_RESET_PLL) { | ||
1240 | u64 val2 = val &= ~INFINIPATH_SERDC0_RESET_PLL; | ||
1241 | /* set lane resets, and tx idle, during pll reset */ | ||
1242 | val2 |= INFINIPATH_SERDC0_RESET_MASK | | ||
1243 | INFINIPATH_SERDC0_TXIDLE; | ||
1244 | ipath_cdbg(VERBOSE, "Clearing serdes PLL reset (writing " | ||
1245 | "%llx)\n", (unsigned long long) val2); | ||
1246 | ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0, | ||
1247 | val2); | ||
1248 | /* | ||
1249 | * be sure chip saw it | ||
1250 | */ | ||
1251 | val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); | ||
1252 | /* | ||
1253 | * need pll reset clear at least 11 usec before lane | ||
1254 | * resets cleared; give it a few more | ||
1255 | */ | ||
1256 | udelay(15); | ||
1257 | val = val2; /* for check below */ | ||
1258 | } | ||
1259 | |||
1260 | if (val & (INFINIPATH_SERDC0_RESET_PLL | | ||
1261 | INFINIPATH_SERDC0_RESET_MASK | | ||
1262 | INFINIPATH_SERDC0_TXIDLE)) { | ||
1263 | val &= ~(INFINIPATH_SERDC0_RESET_PLL | | ||
1264 | INFINIPATH_SERDC0_RESET_MASK | | ||
1265 | INFINIPATH_SERDC0_TXIDLE); | ||
1266 | /* clear them */ | ||
1267 | ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0, | ||
1268 | val); | ||
1269 | } | ||
1270 | |||
1271 | val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig); | ||
1272 | if (((val >> INFINIPATH_XGXS_MDIOADDR_SHIFT) & | ||
1273 | INFINIPATH_XGXS_MDIOADDR_MASK) != 3) { | ||
1274 | val &= ~(INFINIPATH_XGXS_MDIOADDR_MASK << | ||
1275 | INFINIPATH_XGXS_MDIOADDR_SHIFT); | ||
1276 | /* | ||
1277 | * we use address 3 | ||
1278 | */ | ||
1279 | val |= 3ULL << INFINIPATH_XGXS_MDIOADDR_SHIFT; | ||
1280 | change = 1; | ||
1281 | } | ||
1282 | if (val & INFINIPATH_XGXS_RESET) { | ||
1283 | /* normally true after boot */ | ||
1284 | val &= ~INFINIPATH_XGXS_RESET; | ||
1285 | change = 1; | ||
1286 | } | ||
1287 | if (change) | ||
1288 | ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, val); | ||
1289 | |||
1290 | val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0); | ||
1291 | |||
1292 | /* clear current and de-emphasis bits */ | ||
1293 | config1 &= ~0x0ffffffff00ULL; | ||
1294 | /* set current to 20ma */ | ||
1295 | config1 |= 0x00000000000ULL; | ||
1296 | /* set de-emphasis to -5.68dB */ | ||
1297 | config1 |= 0x0cccc000000ULL; | ||
1298 | ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig1, config1); | ||
1299 | |||
1300 | ipath_cdbg(VERBOSE, "After setup: serdes status is config0=%llx " | ||
1301 | "config1=%llx, sstatus=%llx xgxs %llx\n", | ||
1302 | (unsigned long long) val, (unsigned long long) config1, | ||
1303 | (unsigned long long) | ||
1304 | ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesstatus), | ||
1305 | (unsigned long long) | ||
1306 | ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig)); | ||
1307 | |||
1308 | if (!ipath_waitfor_mdio_cmdready(dd)) { | ||
1309 | ipath_write_kreg(dd, dd->ipath_kregs->kr_mdio, | ||
1310 | ipath_mdio_req(IPATH_MDIO_CMD_READ, 31, | ||
1311 | IPATH_MDIO_CTRL_XGXS_REG_8, | ||
1312 | 0)); | ||
1313 | if (ipath_waitfor_complete(dd, dd->ipath_kregs->kr_mdio, | ||
1314 | IPATH_MDIO_DATAVALID, &val)) | ||
1315 | ipath_dbg("Never got MDIO data for XGXS status " | ||
1316 | "read\n"); | ||
1317 | else | ||
1318 | ipath_cdbg(VERBOSE, "MDIO Read reg8, " | ||
1319 | "'bank' 31 %x\n", (u32) val); | ||
1320 | } else | ||
1321 | ipath_dbg("Never got MDIO cmdready for XGXS status read\n"); | ||
1322 | |||
1323 | return ret; /* for now, say we always succeeded */ | ||
1324 | } | ||
1325 | |||
1326 | /** | ||
1327 | * ipath_ht_quiet_serdes - set serdes to txidle | ||
1328 | * @dd: the infinipath device | ||
1329 | * driver is being unloaded | ||
1330 | */ | ||
1331 | static void ipath_ht_quiet_serdes(struct ipath_devdata *dd) | ||
1332 | { | ||
1333 | u64 val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0); | ||
1334 | |||
1335 | val |= INFINIPATH_SERDC0_TXIDLE; | ||
1336 | ipath_dbg("Setting TxIdleEn on serdes (config0 = %llx)\n", | ||
1337 | (unsigned long long) val); | ||
1338 | ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0, val); | ||
1339 | } | ||
1340 | |||
1341 | static int ipath_ht_intconfig(struct ipath_devdata *dd) | ||
1342 | { | ||
1343 | int ret; | ||
1344 | |||
1345 | if (!dd->ipath_intconfig) { | ||
1346 | ipath_dev_err(dd, "No interrupts enabled, couldn't setup " | ||
1347 | "interrupt address\n"); | ||
1348 | ret = 1; | ||
1349 | goto bail; | ||
1350 | } | ||
1351 | |||
1352 | ipath_write_kreg(dd, dd->ipath_kregs->kr_interruptconfig, | ||
1353 | dd->ipath_intconfig); /* interrupt address */ | ||
1354 | ret = 0; | ||
1355 | |||
1356 | bail: | ||
1357 | return ret; | ||
1358 | } | ||
1359 | |||
1360 | /** | ||
1361 | * ipath_pe_put_tid - write a TID in chip | ||
1362 | * @dd: the infinipath device | ||
1363 | * @tidptr: pointer to the expected TID (in chip) to udpate | ||
1364 | * @tidtype: 0 for eager, 1 for expected | ||
1365 | * @pa: physical address of in memory buffer; ipath_tidinvalid if freeing | ||
1366 | * | ||
1367 | * This exists as a separate routine to allow for special locking etc. | ||
1368 | * It's used for both the full cleanup on exit, as well as the normal | ||
1369 | * setup and teardown. | ||
1370 | */ | ||
1371 | static void ipath_ht_put_tid(struct ipath_devdata *dd, | ||
1372 | u64 __iomem *tidptr, u32 type, | ||
1373 | unsigned long pa) | ||
1374 | { | ||
1375 | if (pa != dd->ipath_tidinvalid) { | ||
1376 | if (unlikely((pa & ~INFINIPATH_RT_ADDR_MASK))) { | ||
1377 | dev_info(&dd->pcidev->dev, | ||
1378 | "physaddr %lx has more than " | ||
1379 | "40 bits, using only 40!!!\n", pa); | ||
1380 | pa &= INFINIPATH_RT_ADDR_MASK; | ||
1381 | } | ||
1382 | if (type == 0) | ||
1383 | pa |= dd->ipath_tidtemplate; | ||
1384 | else { | ||
1385 | /* in words (fixed, full page). */ | ||
1386 | u64 lenvalid = PAGE_SIZE >> 2; | ||
1387 | lenvalid <<= INFINIPATH_RT_BUFSIZE_SHIFT; | ||
1388 | pa |= lenvalid | INFINIPATH_RT_VALID; | ||
1389 | } | ||
1390 | } | ||
1391 | if (dd->ipath_kregbase) | ||
1392 | writeq(pa, tidptr); | ||
1393 | } | ||
1394 | |||
1395 | /** | ||
1396 | * ipath_ht_clear_tid - clear all TID entries for a port, expected and eager | ||
1397 | * @dd: the infinipath device | ||
1398 | * @port: the port | ||
1399 | * | ||
1400 | * Used from ipath_close(), and at chip initialization. | ||
1401 | */ | ||
1402 | static void ipath_ht_clear_tids(struct ipath_devdata *dd, unsigned port) | ||
1403 | { | ||
1404 | u64 __iomem *tidbase; | ||
1405 | int i; | ||
1406 | |||
1407 | if (!dd->ipath_kregbase) | ||
1408 | return; | ||
1409 | |||
1410 | ipath_cdbg(VERBOSE, "Invalidate TIDs for port %u\n", port); | ||
1411 | |||
1412 | /* | ||
1413 | * need to invalidate all of the expected TID entries for this | ||
1414 | * port, so we don't have valid entries that might somehow get | ||
1415 | * used (early in next use of this port, or through some bug) | ||
1416 | */ | ||
1417 | tidbase = (u64 __iomem *) ((char __iomem *)(dd->ipath_kregbase) + | ||
1418 | dd->ipath_rcvtidbase + | ||
1419 | port * dd->ipath_rcvtidcnt * | ||
1420 | sizeof(*tidbase)); | ||
1421 | for (i = 0; i < dd->ipath_rcvtidcnt; i++) | ||
1422 | ipath_ht_put_tid(dd, &tidbase[i], 1, dd->ipath_tidinvalid); | ||
1423 | |||
1424 | tidbase = (u64 __iomem *) ((char __iomem *)(dd->ipath_kregbase) + | ||
1425 | dd->ipath_rcvegrbase + | ||
1426 | port * dd->ipath_rcvegrcnt * | ||
1427 | sizeof(*tidbase)); | ||
1428 | |||
1429 | for (i = 0; i < dd->ipath_rcvegrcnt; i++) | ||
1430 | ipath_ht_put_tid(dd, &tidbase[i], 0, dd->ipath_tidinvalid); | ||
1431 | } | ||
1432 | |||
1433 | /** | ||
1434 | * ipath_ht_tidtemplate - setup constants for TID updates | ||
1435 | * @dd: the infinipath device | ||
1436 | * | ||
1437 | * We setup stuff that we use a lot, to avoid calculating each time | ||
1438 | */ | ||
1439 | static void ipath_ht_tidtemplate(struct ipath_devdata *dd) | ||
1440 | { | ||
1441 | dd->ipath_tidtemplate = dd->ipath_ibmaxlen >> 2; | ||
1442 | dd->ipath_tidtemplate <<= INFINIPATH_RT_BUFSIZE_SHIFT; | ||
1443 | dd->ipath_tidtemplate |= INFINIPATH_RT_VALID; | ||
1444 | |||
1445 | /* | ||
1446 | * work around chip errata bug 7358, by marking invalid tids | ||
1447 | * as having max length | ||
1448 | */ | ||
1449 | dd->ipath_tidinvalid = (-1LL & INFINIPATH_RT_BUFSIZE_MASK) << | ||
1450 | INFINIPATH_RT_BUFSIZE_SHIFT; | ||
1451 | } | ||
1452 | |||
1453 | static int ipath_ht_early_init(struct ipath_devdata *dd) | ||
1454 | { | ||
1455 | u32 __iomem *piobuf; | ||
1456 | u32 pioincr, val32, egrsize; | ||
1457 | int i; | ||
1458 | |||
1459 | /* | ||
1460 | * one cache line; long IB headers will spill over into received | ||
1461 | * buffer | ||
1462 | */ | ||
1463 | dd->ipath_rcvhdrentsize = 16; | ||
1464 | dd->ipath_rcvhdrsize = IPATH_DFLT_RCVHDRSIZE; | ||
1465 | |||
1466 | /* | ||
1467 | * For HT-400, we allocate a somewhat overly large eager buffer, | ||
1468 | * such that we can guarantee that we can receive the largest | ||
1469 | * packet that we can send out. To truly support a 4KB MTU, | ||
1470 | * we need to bump this to a large value. To date, other than | ||
1471 | * testing, we have never encountered an HCA that can really | ||
1472 | * send 4KB MTU packets, so we do not handle that (we'll get | ||
1473 | * errors interrupts if we ever see one). | ||
1474 | */ | ||
1475 | dd->ipath_rcvegrbufsize = dd->ipath_piosize2k; | ||
1476 | egrsize = dd->ipath_rcvegrbufsize; | ||
1477 | |||
1478 | /* | ||
1479 | * the min() check here is currently a nop, but it may not | ||
1480 | * always be, depending on just how we do ipath_rcvegrbufsize | ||
1481 | */ | ||
1482 | dd->ipath_ibmaxlen = min(dd->ipath_piosize2k, | ||
1483 | dd->ipath_rcvegrbufsize); | ||
1484 | dd->ipath_init_ibmaxlen = dd->ipath_ibmaxlen; | ||
1485 | ipath_ht_tidtemplate(dd); | ||
1486 | |||
1487 | /* | ||
1488 | * zero all the TID entries at startup. We do this for sanity, | ||
1489 | * in case of a previous driver crash of some kind, and also | ||
1490 | * because the chip powers up with these memories in an unknown | ||
1491 | * state. Use portcnt, not cfgports, since this is for the | ||
1492 | * full chip, not for current (possibly different) configuration | ||
1493 | * value. | ||
1494 | * Chip Errata bug 6447 | ||
1495 | */ | ||
1496 | for (val32 = 0; val32 < dd->ipath_portcnt; val32++) | ||
1497 | ipath_ht_clear_tids(dd, val32); | ||
1498 | |||
1499 | /* | ||
1500 | * write the pbc of each buffer, to be sure it's initialized, then | ||
1501 | * cancel all the buffers, and also abort any packets that might | ||
1502 | * have been in flight for some reason (the latter is for driver | ||
1503 | * unload/reload, but isn't a bad idea at first init). PIO send | ||
1504 | * isn't enabled at this point, so there is no danger of sending | ||
1505 | * these out on the wire. | ||
1506 | * Chip Errata bug 6610 | ||
1507 | */ | ||
1508 | piobuf = (u32 __iomem *) (((char __iomem *)(dd->ipath_kregbase)) + | ||
1509 | dd->ipath_piobufbase); | ||
1510 | pioincr = dd->ipath_palign / sizeof(*piobuf); | ||
1511 | for (i = 0; i < dd->ipath_piobcnt2k; i++) { | ||
1512 | /* | ||
1513 | * reasonable word count, just to init pbc | ||
1514 | */ | ||
1515 | writel(16, piobuf); | ||
1516 | piobuf += pioincr; | ||
1517 | } | ||
1518 | /* | ||
1519 | * self-clearing | ||
1520 | */ | ||
1521 | ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, | ||
1522 | INFINIPATH_S_ABORT); | ||
1523 | return 0; | ||
1524 | } | ||
1525 | |||
1526 | /** | ||
1527 | * ipath_init_ht_get_base_info - set chip-specific flags for user code | ||
1528 | * @dd: the infinipath device | ||
1529 | * @kbase: ipath_base_info pointer | ||
1530 | * | ||
1531 | * We set the PCIE flag because the lower bandwidth on PCIe vs | ||
1532 | * HyperTransport can affect some user packet algorithims. | ||
1533 | */ | ||
1534 | static int ipath_ht_get_base_info(struct ipath_portdata *pd, void *kbase) | ||
1535 | { | ||
1536 | struct ipath_base_info *kinfo = kbase; | ||
1537 | |||
1538 | kinfo->spi_runtime_flags |= IPATH_RUNTIME_HT | | ||
1539 | IPATH_RUNTIME_RCVHDR_COPY; | ||
1540 | |||
1541 | return 0; | ||
1542 | } | ||
1543 | |||
1544 | /** | ||
1545 | * ipath_init_ht400_funcs - set up the chip-specific function pointers | ||
1546 | * @dd: the infinipath device | ||
1547 | * | ||
1548 | * This is global, and is called directly at init to set up the | ||
1549 | * chip-specific function pointers for later use. | ||
1550 | */ | ||
1551 | void ipath_init_ht400_funcs(struct ipath_devdata *dd) | ||
1552 | { | ||
1553 | dd->ipath_f_intrsetup = ipath_ht_intconfig; | ||
1554 | dd->ipath_f_bus = ipath_setup_ht_config; | ||
1555 | dd->ipath_f_reset = ipath_setup_ht_reset; | ||
1556 | dd->ipath_f_get_boardname = ipath_ht_boardname; | ||
1557 | dd->ipath_f_init_hwerrors = ipath_ht_init_hwerrors; | ||
1558 | dd->ipath_f_init_hwerrors = ipath_ht_init_hwerrors; | ||
1559 | dd->ipath_f_early_init = ipath_ht_early_init; | ||
1560 | dd->ipath_f_handle_hwerrors = ipath_ht_handle_hwerrors; | ||
1561 | dd->ipath_f_quiet_serdes = ipath_ht_quiet_serdes; | ||
1562 | dd->ipath_f_bringup_serdes = ipath_ht_bringup_serdes; | ||
1563 | dd->ipath_f_clear_tids = ipath_ht_clear_tids; | ||
1564 | dd->ipath_f_put_tid = ipath_ht_put_tid; | ||
1565 | dd->ipath_f_cleanup = ipath_setup_ht_cleanup; | ||
1566 | dd->ipath_f_setextled = ipath_setup_ht_setextled; | ||
1567 | dd->ipath_f_get_base_info = ipath_ht_get_base_info; | ||
1568 | |||
1569 | /* | ||
1570 | * initialize chip-specific variables | ||
1571 | */ | ||
1572 | dd->ipath_f_tidtemplate = ipath_ht_tidtemplate; | ||
1573 | |||
1574 | /* | ||
1575 | * setup the register offsets, since they are different for each | ||
1576 | * chip | ||
1577 | */ | ||
1578 | dd->ipath_kregs = &ipath_ht_kregs; | ||
1579 | dd->ipath_cregs = &ipath_ht_cregs; | ||
1580 | |||
1581 | /* | ||
1582 | * do very early init that is needed before ipath_f_bus is | ||
1583 | * called | ||
1584 | */ | ||
1585 | ipath_init_ht_variables(); | ||
1586 | } | ||